summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/app/app.cpp602
-rw-r--r--src/app/app.h174
-rw-r--r--src/app/main.cpp18
-rw-r--r--src/app/system.cpp340
-rw-r--r--src/app/system.h28
-rw-r--r--src/common/event.cpp192
-rw-r--r--src/common/event.h1266
-rw-r--r--src/common/global.h132
-rw-r--r--src/common/iman.cpp324
-rw-r--r--src/common/iman.h110
-rw-r--r--src/common/language.h108
-rw-r--r--src/common/metafile.cpp832
-rw-r--r--src/common/metafile.h148
-rw-r--r--src/common/misc.cpp882
-rw-r--r--src/common/misc.h476
-rw-r--r--src/common/modfile.cpp1390
-rw-r--r--src/common/modfile.h230
-rw-r--r--src/common/profile.cpp228
-rw-r--r--src/common/profile.h60
-rw-r--r--src/common/restext.cpp7319
-rw-r--r--src/common/restext.h316
-rw-r--r--src/common/struct.h106
-rw-r--r--src/graphics/common/camera.h378
-rw-r--r--src/graphics/common/cloud.h74
-rw-r--r--src/graphics/common/color.h12
-rw-r--r--src/graphics/common/device.cpp16
-rw-r--r--src/graphics/common/device.h36
-rw-r--r--src/graphics/common/engine.cpp52
-rw-r--r--src/graphics/common/engine.h1122
-rw-r--r--src/graphics/common/light.h104
-rw-r--r--src/graphics/common/lightning.h60
-rw-r--r--src/graphics/common/material.h12
-rw-r--r--src/graphics/common/model.h198
-rw-r--r--src/graphics/common/modfile.h114
-rw-r--r--src/graphics/common/particle.h506
-rw-r--r--src/graphics/common/planet.h54
-rw-r--r--src/graphics/common/pyro.h202
-rw-r--r--src/graphics/common/terrain.h270
-rw-r--r--src/graphics/common/text.h82
-rw-r--r--src/graphics/common/vertex.h26
-rw-r--r--src/graphics/common/water.h130
-rw-r--r--src/math/const.h32
-rw-r--r--src/math/conv.h26
-rw-r--r--src/math/func.h156
-rw-r--r--src/math/geometry.h496
-rw-r--r--src/math/intpoint.h10
-rw-r--r--src/math/matrix.h630
-rw-r--r--src/math/point.h216
-rw-r--r--src/math/test/geometry_test.cpp472
-rw-r--r--src/math/test/matrix_test.cpp612
-rw-r--r--src/math/test/vector_test.cpp132
-rw-r--r--src/math/vector.h332
-rw-r--r--src/object/auto/auto.cpp874
-rw-r--r--src/object/auto/auto.h222
-rw-r--r--src/object/auto/autobase.cpp2882
-rw-r--r--src/object/auto/autobase.h224
-rw-r--r--src/object/auto/autoconvert.cpp1054
-rw-r--r--src/object/auto/autoconvert.h140
-rw-r--r--src/object/auto/autoderrick.cpp1178
-rw-r--r--src/object/auto/autoderrick.h142
-rw-r--r--src/object/auto/autodestroyer.cpp748
-rw-r--r--src/object/auto/autodestroyer.h130
-rw-r--r--src/object/auto/autoegg.cpp718
-rw-r--r--src/object/auto/autoegg.h138
-rw-r--r--src/object/auto/autoenergy.cpp1294
-rw-r--r--src/object/auto/autoenergy.h142
-rw-r--r--src/object/auto/autofactory.cpp1882
-rw-r--r--src/object/auto/autofactory.h148
-rw-r--r--src/object/auto/autoflag.cpp324
-rw-r--r--src/object/auto/autoflag.h92
-rw-r--r--src/object/auto/autohuston.cpp592
-rw-r--r--src/object/auto/autohuston.h130
-rw-r--r--src/object/auto/autoinfo.cpp1034
-rw-r--r--src/object/auto/autoinfo.h136
-rw-r--r--src/object/auto/autojostle.cpp284
-rw-r--r--src/object/auto/autojostle.h96
-rw-r--r--src/object/auto/autokid.cpp402
-rw-r--r--src/object/auto/autokid.h94
-rw-r--r--src/object/auto/autolabo.cpp1220
-rw-r--r--src/object/auto/autolabo.h150
-rw-r--r--src/object/auto/automush.cpp688
-rw-r--r--src/object/auto/automush.h122
-rw-r--r--src/object/auto/autonest.cpp550
-rw-r--r--src/object/auto/autonest.h122
-rw-r--r--src/object/auto/autonuclear.cpp968
-rw-r--r--src/object/auto/autonuclear.h136
-rw-r--r--src/object/auto/autopara.cpp654
-rw-r--r--src/object/auto/autopara.h130
-rw-r--r--src/object/auto/autoportico.cpp850
-rw-r--r--src/object/auto/autoportico.h138
-rw-r--r--src/object/auto/autoradar.cpp612
-rw-r--r--src/object/auto/autoradar.h128
-rw-r--r--src/object/auto/autorepair.cpp678
-rw-r--r--src/object/auto/autorepair.h130
-rw-r--r--src/object/auto/autoresearch.cpp1216
-rw-r--r--src/object/auto/autoresearch.h140
-rw-r--r--src/object/auto/autoroot.cpp240
-rw-r--r--src/object/auto/autoroot.h88
-rw-r--r--src/object/auto/autosafe.cpp1224
-rw-r--r--src/object/auto/autosafe.h148
-rw-r--r--src/object/auto/autostation.cpp740
-rw-r--r--src/object/auto/autostation.h112
-rw-r--r--src/object/auto/autotower.cpp1082
-rw-r--r--src/object/auto/autotower.h148
-rw-r--r--src/object/brain.cpp5998
-rw-r--r--src/object/brain.h436
-rw-r--r--src/object/mainmovie.cpp476
-rw-r--r--src/object/mainmovie.h160
-rw-r--r--src/object/motion/motion.cpp478
-rw-r--r--src/object/motion/motion.h186
-rw-r--r--src/object/motion/motionant.cpp1742
-rw-r--r--src/object/motion/motionant.h146
-rw-r--r--src/object/motion/motionbee.cpp1288
-rw-r--r--src/object/motion/motionbee.h132
-rw-r--r--src/object/motion/motionhuman.cpp3540
-rw-r--r--src/object/motion/motionhuman.h188
-rw-r--r--src/object/motion/motionmother.cpp1048
-rw-r--r--src/object/motion/motionmother.h108
-rw-r--r--src/object/motion/motionspider.cpp1518
-rw-r--r--src/object/motion/motionspider.h142
-rw-r--r--src/object/motion/motiontoto.cpp1738
-rw-r--r--src/object/motion/motiontoto.h140
-rw-r--r--src/object/motion/motionvehicle.cpp4146
-rw-r--r--src/object/motion/motionvehicle.h138
-rw-r--r--src/object/motion/motionworm.cpp730
-rw-r--r--src/object/motion/motionworm.h124
-rw-r--r--src/object/object.cpp15212
-rw-r--r--src/object/object.h1550
-rw-r--r--src/object/robotmain.cpp14064
-rw-r--r--src/object/robotmain.h918
-rw-r--r--src/object/task/task.cpp178
-rw-r--r--src/object/task/task.h172
-rw-r--r--src/object/task/taskadvance.cpp292
-rw-r--r--src/object/task/taskadvance.h100
-rw-r--r--src/object/task/taskbuild.cpp1612
-rw-r--r--src/object/task/taskbuild.h170
-rw-r--r--src/object/task/taskfire.cpp768
-rw-r--r--src/object/task/taskfire.h104
-rw-r--r--src/object/task/taskfireant.cpp424
-rw-r--r--src/object/task/taskfireant.h126
-rw-r--r--src/object/task/taskflag.cpp610
-rw-r--r--src/object/task/taskflag.h116
-rw-r--r--src/object/task/taskgoto.cpp4682
-rw-r--r--src/object/task/taskgoto.h314
-rw-r--r--src/object/task/taskgungoal.cpp298
-rw-r--r--src/object/task/taskgungoal.h96
-rw-r--r--src/object/task/taskinfo.cpp438
-rw-r--r--src/object/task/taskinfo.h94
-rw-r--r--src/object/task/taskmanager.cpp556
-rw-r--r--src/object/task/taskmanager.h142
-rw-r--r--src/object/task/taskmanip.cpp2766
-rw-r--r--src/object/task/taskmanip.h198
-rw-r--r--src/object/task/taskpen.cpp574
-rw-r--r--src/object/task/taskpen.h136
-rw-r--r--src/object/task/taskrecover.cpp834
-rw-r--r--src/object/task/taskrecover.h132
-rw-r--r--src/object/task/taskreset.cpp660
-rw-r--r--src/object/task/taskreset.h126
-rw-r--r--src/object/task/tasksearch.cpp642
-rw-r--r--src/object/task/tasksearch.h140
-rw-r--r--src/object/task/taskshield.cpp1120
-rw-r--r--src/object/task/taskshield.h168
-rw-r--r--src/object/task/taskspiderexplo.cpp220
-rw-r--r--src/object/task/taskspiderexplo.h88
-rw-r--r--src/object/task/tasktake.cpp1192
-rw-r--r--src/object/task/tasktake.h150
-rw-r--r--src/object/task/taskterraform.cpp832
-rw-r--r--src/object/task/taskterraform.h124
-rw-r--r--src/object/task/taskturn.cpp268
-rw-r--r--src/object/task/taskturn.h92
-rw-r--r--src/object/task/taskwait.cpp148
-rw-r--r--src/object/task/taskwait.h88
-rw-r--r--src/old/blitz.cpp950
-rw-r--r--src/old/blitz.h166
-rw-r--r--src/old/camera.cpp4218
-rw-r--r--src/old/camera.h538
-rw-r--r--src/old/cloud.cpp676
-rw-r--r--src/old/cloud.h176
-rw-r--r--src/old/d3dapp.cpp4902
-rw-r--r--src/old/d3dapp.h332
-rw-r--r--src/old/d3dengine.cpp11650
-rw-r--r--src/old/d3dengine.h1354
-rw-r--r--src/old/d3denum.cpp1240
-rw-r--r--src/old/d3denum.h266
-rw-r--r--src/old/d3dframe.cpp1244
-rw-r--r--src/old/d3dframe.h282
-rw-r--r--src/old/d3dmath.cpp686
-rw-r--r--src/old/d3dmath.h214
-rw-r--r--src/old/d3dres.h110
-rw-r--r--src/old/d3dtextr.cpp2162
-rw-r--r--src/old/d3dtextr.h158
-rw-r--r--src/old/d3dutil.cpp650
-rw-r--r--src/old/d3dutil.h226
-rw-r--r--src/old/joystick.cpp488
-rw-r--r--src/old/joystick.h54
-rw-r--r--src/old/light.cpp1008
-rw-r--r--src/old/light.h218
-rw-r--r--src/old/math3d.cpp2394
-rw-r--r--src/old/math3d.h96
-rw-r--r--src/old/model.cpp6456
-rw-r--r--src/old/model.h272
-rw-r--r--src/old/modfile.cpp1058
-rw-r--r--src/old/modfile.h114
-rw-r--r--src/old/particule.cpp8802
-rw-r--r--src/old/particule.h674
-rw-r--r--src/old/planet.cpp494
-rw-r--r--src/old/planet.h152
-rw-r--r--src/old/pyro.cpp4972
-rw-r--r--src/old/pyro.h340
-rw-r--r--src/old/resource.h110
-rw-r--r--src/old/sound.cpp3318
-rw-r--r--src/old/sound.h484
-rw-r--r--src/old/terrain.cpp4540
-rw-r--r--src/old/terrain.h418
-rw-r--r--src/old/text.cpp3758
-rw-r--r--src/old/text.h222
-rw-r--r--src/old/water.cpp1688
-rw-r--r--src/old/water.h260
-rw-r--r--src/physics/physics.cpp7770
-rw-r--r--src/physics/physics.h492
-rw-r--r--src/script/ClassFILE.cpp850
-rw-r--r--src/script/cbottoken.cpp1038
-rw-r--r--src/script/cbottoken.h72
-rw-r--r--src/script/cmdtoken.cpp1952
-rw-r--r--src/script/cmdtoken.h128
-rw-r--r--src/script/dd.cpp350
-rw-r--r--src/script/script.cpp7552
-rw-r--r--src/script/script.h236
-rw-r--r--src/sound/sound.h222
-rw-r--r--src/ui/button.cpp492
-rw-r--r--src/ui/button.h112
-rw-r--r--src/ui/check.cpp332
-rw-r--r--src/ui/check.h92
-rw-r--r--src/ui/color.cpp448
-rw-r--r--src/ui/color.h112
-rw-r--r--src/ui/compass.cpp350
-rw-r--r--src/ui/compass.h100
-rw-r--r--src/ui/control.cpp1748
-rw-r--r--src/ui/control.h276
-rw-r--r--src/ui/displayinfo.cpp2438
-rw-r--r--src/ui/displayinfo.h180
-rw-r--r--src/ui/displaytext.cpp1226
-rw-r--r--src/ui/displaytext.h192
-rw-r--r--src/ui/edit.cpp6632
-rw-r--r--src/ui/edit.h496
-rw-r--r--src/ui/editvalue.cpp756
-rw-r--r--src/ui/editvalue.h166
-rw-r--r--src/ui/gauge.cpp314
-rw-r--r--src/ui/gauge.h100
-rw-r--r--src/ui/group.cpp1288
-rw-r--r--src/ui/group.h92
-rw-r--r--src/ui/image.cpp310
-rw-r--r--src/ui/image.h100
-rw-r--r--src/ui/interface.cpp1210
-rw-r--r--src/ui/interface.h190
-rw-r--r--src/ui/key.cpp576
-rw-r--r--src/ui/key.h104
-rw-r--r--src/ui/label.cpp186
-rw-r--r--src/ui/label.h92
-rw-r--r--src/ui/list.cpp1736
-rw-r--r--src/ui/list.h230
-rw-r--r--src/ui/maindialog.cpp13870
-rw-r--r--src/ui/maindialog.h506
-rw-r--r--src/ui/mainmap.cpp804
-rw-r--r--src/ui/mainmap.h140
-rw-r--r--src/ui/mainshort.cpp748
-rw-r--r--src/ui/mainshort.h124
-rw-r--r--src/ui/map.cpp2678
-rw-r--r--src/ui/map.h274
-rw-r--r--src/ui/scroll.cpp938
-rw-r--r--src/ui/scroll.h162
-rw-r--r--src/ui/shortcut.cpp482
-rw-r--r--src/ui/shortcut.h96
-rw-r--r--src/ui/slider.cpp1160
-rw-r--r--src/ui/slider.h162
-rw-r--r--src/ui/studio.cpp3330
-rw-r--r--src/ui/studio.h230
-rw-r--r--src/ui/target.cpp566
-rw-r--r--src/ui/target.h96
-rw-r--r--src/ui/window.cpp3240
-rw-r--r--src/ui/window.h292
-rw-r--r--tools/README.txt4
-rwxr-xr-xtools/convert-whitespace.sh10
283 files changed, 137774 insertions, 137759 deletions
diff --git a/src/app/app.cpp b/src/app/app.cpp
index 726d32d..466d757 100644
--- a/src/app/app.cpp
+++ b/src/app/app.cpp
@@ -34,492 +34,492 @@
*/
struct ApplicationPrivate
{
- //! Display surface
- SDL_Surface *surface;
- //! Currently handled event
- SDL_Event currentEvent;
- //! Joystick
- SDL_Joystick *joystick;
- //! Index of joystick device
- int joystickDevice;
-
- ApplicationPrivate()
- {
- memset(&currentEvent, 0, sizeof(SDL_Event));
- surface = NULL;
- joystick = NULL;
- joystickDevice = 0;
- }
+ //! Display surface
+ SDL_Surface *surface;
+ //! Currently handled event
+ SDL_Event currentEvent;
+ //! Joystick
+ SDL_Joystick *joystick;
+ //! Index of joystick device
+ int joystickDevice;
+
+ ApplicationPrivate()
+ {
+ memset(&currentEvent, 0, sizeof(SDL_Event));
+ surface = NULL;
+ joystick = NULL;
+ joystickDevice = 0;
+ }
};
CApplication::CApplication()
{
- m_private = new ApplicationPrivate();
- m_exitCode = 0;
+ m_private = new ApplicationPrivate();
+ m_exitCode = 0;
- m_iMan = new CInstanceManager();
- m_event = new CEvent(m_iMan);
+ m_iMan = new CInstanceManager();
+ m_event = new CEvent(m_iMan);
- m_engine = 0;
- m_robotMain = 0;
- m_sound = 0;
+ m_engine = 0;
+ m_robotMain = 0;
+ m_sound = 0;
- m_keyState = 0;
- m_axeKey = Math::Vector(0.0f, 0.0f, 0.0f);
- m_axeJoy = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_keyState = 0;
+ m_axeKey = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_axeJoy = Math::Vector(0.0f, 0.0f, 0.0f);
- m_vidMemTotal = 0;
- m_active = false;
- m_activateApp = false;
- m_ready = false;
- m_joystick = false;
- m_time = 0.0f;
+ m_vidMemTotal = 0;
+ m_active = false;
+ m_activateApp = false;
+ m_ready = false;
+ m_joystick = false;
+ m_time = 0.0f;
- for (int i = 0; i < 32; i++)
- {
- m_joyButton[i] = false;
- }
+ for (int i = 0; i < 32; i++)
+ {
+ m_joyButton[i] = false;
+ }
- m_windowTitle = "COLOBOT";
+ m_windowTitle = "COLOBOT";
- m_appUseZBuffer = true;
- m_appUseStereo = true;
- m_showStats = false;
- m_debugMode = false;
- m_audioState = true;
- m_audioTrack = true;
- m_niceMouse = false;
- m_setupMode = true;
+ m_appUseZBuffer = true;
+ m_appUseStereo = true;
+ m_showStats = false;
+ m_debugMode = false;
+ m_audioState = true;
+ m_audioTrack = true;
+ m_niceMouse = false;
+ m_setupMode = true;
- ResetKey();
+ ResetKey();
}
CApplication::~CApplication()
{
- delete m_private;
- m_private = NULL;
+ delete m_private;
+ m_private = NULL;
- delete m_iMan;
- m_iMan = NULL;
+ delete m_iMan;
+ m_iMan = NULL;
}
Error CApplication::ParseArguments(int argc, char *argv[])
{
- for (int i = 1; i < argc; ++i)
- {
- std::string arg = argv[i];
-
- if (arg == "-debug")
- {
- m_showStats = true;
- SetDebugMode(true);
- }
- else if (arg == "-audiostate")
- {
- m_audioState = false;
- }
- else if (arg == "-audiotrack")
- {
- m_audioTrack = false;
- }
- // TODO else {} report invalid argument
- }
-
- return ERR_OK;
+ for (int i = 1; i < argc; ++i)
+ {
+ std::string arg = argv[i];
+
+ if (arg == "-debug")
+ {
+ m_showStats = true;
+ SetDebugMode(true);
+ }
+ else if (arg == "-audiostate")
+ {
+ m_audioState = false;
+ }
+ else if (arg == "-audiotrack")
+ {
+ m_audioTrack = false;
+ }
+ // TODO else {} report invalid argument
+ }
+
+ return ERR_OK;
}
bool CApplication::Create()
{
/*
TODO
- Full screen by default unless in debug mode
- if (! m_debugMode)
- m_deviceConfig.fullScreen = true;
+ Full screen by default unless in debug mode
+ if (! m_debugMode)
+ m_deviceConfig.fullScreen = true;
- int full = 0;
- if (GetProfileInt("Device", "FullScreen", full))
- m_deviceConfig.fullScreen = full == 1;
+ int full = 0;
+ if (GetProfileInt("Device", "FullScreen", full))
+ m_deviceConfig.fullScreen = full == 1;
*/
- // Temporarily -- only in windowed mode
- m_deviceConfig.fullScreen = false;
+ // Temporarily -- only in windowed mode
+ m_deviceConfig.fullScreen = false;
/*
TODO
- // Create the 3D engine.
- m_engine = new CEngine(m_iMan, this);
+ // Create the 3D engine.
+ m_engine = new CEngine(m_iMan, this);
- // Initialize the app's custom scene stuff
- if (! m_engine->OneTimeSceneInit())
- {
- SystemDialog(SDT_ERROR, "COLOBOT - Error", m_engine->RetError());
- return false;
- }
+ // Initialize the app's custom scene stuff
+ if (! m_engine->OneTimeSceneInit())
+ {
+ SystemDialog(SDT_ERROR, "COLOBOT - Error", m_engine->RetError());
+ return false;
+ }
- // Create the sound instance.
- m_sound = new CSound(m_iMan);
+ // Create the sound instance.
+ m_sound = new CSound(m_iMan);
- // Create the robot application.
- m_robotMain = new CRobotMain(m_iMan);
+ // Create the robot application.
+ m_robotMain = new CRobotMain(m_iMan);
*/
- Uint32 initFlags = SDL_INIT_VIDEO;
- if (m_joystick)
- initFlags |= SDL_INIT_JOYSTICK;
+ Uint32 initFlags = SDL_INIT_VIDEO;
+ if (m_joystick)
+ initFlags |= SDL_INIT_JOYSTICK;
- if (SDL_Init(initFlags) < 0)
- {
- SystemDialog( SDT_ERROR, "COLOBOT - Error", "SDL initialization error:\n" + std::string(SDL_GetError()) );
- return false;
- }
+ if (SDL_Init(initFlags) < 0)
+ {
+ SystemDialog( SDT_ERROR, "COLOBOT - Error", "SDL initialization error:\n" + std::string(SDL_GetError()) );
+ return false;
+ }
- const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
- if (! videoInfo)
- {
- SystemDialog( SDT_ERROR, "COLOBOT - Error", "SDL error while getting video info:\n " + std::string(SDL_GetError()) );
- return false;
- }
+ const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
+ if (! videoInfo)
+ {
+ SystemDialog( SDT_ERROR, "COLOBOT - Error", "SDL error while getting video info:\n " + std::string(SDL_GetError()) );
+ return false;
+ }
- Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE;
+ Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE;
- if (m_deviceConfig.resizeable)
- videoFlags |= SDL_RESIZABLE;
+ if (m_deviceConfig.resizeable)
+ videoFlags |= SDL_RESIZABLE;
- // Use hardware surface if available
- if (videoInfo->hw_available)
- videoFlags |= SDL_HWSURFACE;
- else
- videoFlags |= SDL_SWSURFACE;
+ // Use hardware surface if available
+ if (videoInfo->hw_available)
+ videoFlags |= SDL_HWSURFACE;
+ else
+ videoFlags |= SDL_SWSURFACE;
- // Enable hardware blit if available
- if (videoInfo->blit_hw)
- videoFlags |= SDL_HWACCEL;
+ // Enable hardware blit if available
+ if (videoInfo->blit_hw)
+ videoFlags |= SDL_HWACCEL;
- if (m_deviceConfig.fullScreen)
- videoFlags |= SDL_FULLSCREEN;
+ if (m_deviceConfig.fullScreen)
+ videoFlags |= SDL_FULLSCREEN;
- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- if ((IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) == 0)
- {
- SystemDialog( SDT_ERROR, "COLOBOT - Error", std::string("SDL_Image initialization error:\n") +
- std::string(IMG_GetError()) );
- return false;
- }
+ if ((IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) == 0)
+ {
+ SystemDialog( SDT_ERROR, "COLOBOT - Error", std::string("SDL_Image initialization error:\n") +
+ std::string(IMG_GetError()) );
+ return false;
+ }
- m_private->surface = SDL_SetVideoMode(m_deviceConfig.width, m_deviceConfig.height,
- m_deviceConfig.bpp, videoFlags);
+ m_private->surface = SDL_SetVideoMode(m_deviceConfig.width, m_deviceConfig.height,
+ m_deviceConfig.bpp, videoFlags);
- if (! m_private->surface)
- {
- SystemDialog( SDT_ERROR, "COLOBT - Error", std::string("SDL error while setting video mode:\n") +
- std::string(SDL_GetError()) );
- return false;
- }
+ if (! m_private->surface)
+ {
+ SystemDialog( SDT_ERROR, "COLOBT - Error", std::string("SDL error while setting video mode:\n") +
+ std::string(SDL_GetError()) );
+ return false;
+ }
- SDL_WM_SetCaption(m_windowTitle.c_str(), m_windowTitle.c_str());
+ SDL_WM_SetCaption(m_windowTitle.c_str(), m_windowTitle.c_str());
- SDL_EnableUNICODE(1);
+ SDL_EnableUNICODE(1);
/*
TODO
- InitJoystick();
+ InitJoystick();
- if ( !GetProfileInt("Setup", "Sound3D", b3D) )
- {
- b3D = true;
- }
- m_pSound->SetDebugMode(m_bDebugMode);
- m_pSound->Create(m_hWnd, b3D);
- m_pSound->CacheAll();
- m_pSound->SetState(m_bAudioState);
- m_pSound->SetAudioTrack(m_bAudioTrack);
- m_pSound->SetCDpath(m_CDpath);
+ if ( !GetProfileInt("Setup", "Sound3D", b3D) )
+ {
+ b3D = true;
+ }
+ m_pSound->SetDebugMode(m_bDebugMode);
+ m_pSound->Create(m_hWnd, b3D);
+ m_pSound->CacheAll();
+ m_pSound->SetState(m_bAudioState);
+ m_pSound->SetAudioTrack(m_bAudioTrack);
+ m_pSound->SetCDpath(m_CDpath);
- // First execution?
- if ( !GetProfileInt("Setup", "ObjectDirty", iValue) )
- {
- m_pD3DEngine->FirstExecuteAdapt(true);
- }
+ // First execution?
+ if ( !GetProfileInt("Setup", "ObjectDirty", iValue) )
+ {
+ m_pD3DEngine->FirstExecuteAdapt(true);
+ }
- // Creates the file colobot.ini at the first execution.
- m_pRobotMain->CreateIni();
+ // Creates the file colobot.ini at the first execution.
+ m_pRobotMain->CreateIni();
- m_pRobotMain->ChangePhase(PHASE_WELCOME2);
+ m_pRobotMain->ChangePhase(PHASE_WELCOME2);
- m_engine->TimeInit();
+ m_engine->TimeInit();
*/
- // The app is ready to go
- m_ready = true;
+ // The app is ready to go
+ m_ready = true;
- return true;
+ return true;
}
void CApplication::Destroy()
{
- if (m_private->joystick != NULL)
- {
- SDL_JoystickClose(m_private->joystick);
- m_private->joystick = NULL;
- }
+ if (m_private->joystick != NULL)
+ {
+ SDL_JoystickClose(m_private->joystick);
+ m_private->joystick = NULL;
+ }
- SDL_FreeSurface(m_private->surface);
- m_private->surface = NULL;
+ SDL_FreeSurface(m_private->surface);
+ m_private->surface = NULL;
- IMG_Quit();
+ IMG_Quit();
- SDL_Quit();
+ SDL_Quit();
}
int CApplication::Run()
{
- m_active = true;
-
- while (m_private->currentEvent.type != SDL_QUIT)
- {
- // Use SDL_PeepEvents() if the app is active, so we can use idle time to
- // render the scene. Else, use SDL_PollEvent() to avoid eating CPU time.
- int count = 0;
- if (m_active)
- {
- SDL_PumpEvents();
- count = SDL_PeepEvents(&m_private->currentEvent, 1, SDL_GETEVENT, SDL_ALLEVENTS);
- }
- else
- {
- SDL_PollEvent(&m_private->currentEvent);
- }
-
- // If received an event
- if ((m_active && count > 0) || (!m_active))
- {
- ParseEvent();
- }
-
- // Render a frame during idle time (no messages are waiting)
- if (m_active && m_ready)
- {
- Event event;
- while (m_event->GetEvent(event))
- {
- if (event.event == EVENT_QUIT)
- {
- goto end; // exit both loops
- }
-
- //m_robotMain->EventProcess(event);
- }
-
- //if ( !RetNiceMouse())
- //{
- // SetMouseType(m_engine->RetMouseType());
- //}
-
- // If an error occurs, push quit event to the queue
- if (! Render())
- {
- SDL_Event quitEvent;
- memset(&quitEvent, 0, sizeof(SDL_Event));
- quitEvent.type = SDL_QUIT;
- SDL_PushEvent(&quitEvent);
- }
- }
- }
+ m_active = true;
+
+ while (m_private->currentEvent.type != SDL_QUIT)
+ {
+ // Use SDL_PeepEvents() if the app is active, so we can use idle time to
+ // render the scene. Else, use SDL_PollEvent() to avoid eating CPU time.
+ int count = 0;
+ if (m_active)
+ {
+ SDL_PumpEvents();
+ count = SDL_PeepEvents(&m_private->currentEvent, 1, SDL_GETEVENT, SDL_ALLEVENTS);
+ }
+ else
+ {
+ SDL_PollEvent(&m_private->currentEvent);
+ }
+
+ // If received an event
+ if ((m_active && count > 0) || (!m_active))
+ {
+ ParseEvent();
+ }
+
+ // Render a frame during idle time (no messages are waiting)
+ if (m_active && m_ready)
+ {
+ Event event;
+ while (m_event->GetEvent(event))
+ {
+ if (event.event == EVENT_QUIT)
+ {
+ goto end; // exit both loops
+ }
+
+ //m_robotMain->EventProcess(event);
+ }
+
+ //if ( !RetNiceMouse())
+ //{
+ // SetMouseType(m_engine->RetMouseType());
+ //}
+
+ // If an error occurs, push quit event to the queue
+ if (! Render())
+ {
+ SDL_Event quitEvent;
+ memset(&quitEvent, 0, sizeof(SDL_Event));
+ quitEvent.type = SDL_QUIT;
+ SDL_PushEvent(&quitEvent);
+ }
+ }
+ }
end:
- //m_sound->StopMusic();
- Destroy();
+ //m_sound->StopMusic();
+ Destroy();
- return m_exitCode;
+ return m_exitCode;
}
void CApplication::ParseEvent()
{
-/* Event event;
-
- if (m_private->currentEvent.type == SDL_MOUSEBUTTONDOWN)
- {
- if (m_private->currentEvent.button.button == SDL_BUTTON_LEFT)
- event.event = EVENT_LBUTTONDOWN;
- else if (m_private->currentEvent.button.button == SDL_BUTTON_RIGHT)
- event.event = EVENT_RBUTTONDOWN;
- }
- else if (m_private->currentEvent.type == SDL_MOUSEBUTTONUP)
- {
- if (m_private->currentEvent.button.button == SDL_BUTTON_LEFT)
- event.event = EVENT_LBUTTONUP;
- else if (m_private->currentEvent.button.button == SDL_BUTTON_RIGHT)
- event.event = EVENT_RBUTTONUP;
- }
- else if (m_private->currentEvent.type == SDL_MOUSEMOTION)
- {
- event.event = EVENT_MOUSEMOVE;
- }
- else if (m_private->currentEvent.type == SDL_KEYDOWN)
- {
- event.event = EVENT_KEYDOWN;
- }
- else if (m_private->currentEvent.type == SDL_KEYUP)
- {
- event.event = EVENT_KEYUP;
- }
-
- if (m_robotMain != NULL && event.event != EVENT_NULL)
- {
- m_robotMain->EventProcess(event);
- }
- if (m_engine != NULL)
- {
- m_engine->MsgProc( hWnd, uMsg, wParam, lParam );
- }
-
- ProcessEvent(event);*/
+/* Event event;
+
+ if (m_private->currentEvent.type == SDL_MOUSEBUTTONDOWN)
+ {
+ if (m_private->currentEvent.button.button == SDL_BUTTON_LEFT)
+ event.event = EVENT_LBUTTONDOWN;
+ else if (m_private->currentEvent.button.button == SDL_BUTTON_RIGHT)
+ event.event = EVENT_RBUTTONDOWN;
+ }
+ else if (m_private->currentEvent.type == SDL_MOUSEBUTTONUP)
+ {
+ if (m_private->currentEvent.button.button == SDL_BUTTON_LEFT)
+ event.event = EVENT_LBUTTONUP;
+ else if (m_private->currentEvent.button.button == SDL_BUTTON_RIGHT)
+ event.event = EVENT_RBUTTONUP;
+ }
+ else if (m_private->currentEvent.type == SDL_MOUSEMOTION)
+ {
+ event.event = EVENT_MOUSEMOVE;
+ }
+ else if (m_private->currentEvent.type == SDL_KEYDOWN)
+ {
+ event.event = EVENT_KEYDOWN;
+ }
+ else if (m_private->currentEvent.type == SDL_KEYUP)
+ {
+ event.event = EVENT_KEYUP;
+ }
+
+ if (m_robotMain != NULL && event.event != EVENT_NULL)
+ {
+ m_robotMain->EventProcess(event);
+ }
+ if (m_engine != NULL)
+ {
+ m_engine->MsgProc( hWnd, uMsg, wParam, lParam );
+ }
+
+ ProcessEvent(event);*/
}
void CApplication::ProcessEvent(Event event)
{
-
+
}
bool CApplication::Render()
{
- bool result = m_engine->Render();
- if (! result)
- return false;
+ bool result = m_engine->Render();
+ if (! result)
+ return false;
- if (m_deviceConfig.doubleBuf)
- SDL_GL_SwapBuffers();
+ if (m_deviceConfig.doubleBuf)
+ SDL_GL_SwapBuffers();
- return true;
+ return true;
}
void CApplication::Pause(bool pause)
{
- // TODO
+ // TODO
}
void CApplication::SetMousePos(Math::Point pos)
{
- // TODO
+ // TODO
}
void CApplication::StepSimulation(float rTime)
{
- // TODO
+ // TODO
}
void SetShowStat(bool show)
{
- // TODO
+ // TODO
}
bool CApplication::RetShowStat()
{
- // TODO
- return false;
+ // TODO
+ return false;
}
void CApplication::SetDebugMode(bool mode)
{
- // TODO
+ // TODO
}
bool CApplication::RetDebugMode()
{
- // TODO
- return false;
+ // TODO
+ return false;
}
bool CApplication::RetSetupMode()
{
- // TODO
- return false;
+ // TODO
+ return false;
}
void CApplication::FlushPressKey()
{
- // TODO
+ // TODO
}
void CApplication::ResetKey()
{
- // TODO
+ // TODO
}
void CApplication::SetKey(int keyRank, int option, int key)
{
- // TODO
+ // TODO
}
int CApplication::RetKey(int keyRank, int option)
{
- // TODO
- return 0;
+ // TODO
+ return 0;
}
void CApplication::SetJoystick(bool enable)
{
- // TODO
+ // TODO
}
bool CApplication::RetJoystick()
{
- // TODO
- return false;
+ // TODO
+ return false;
}
void SetMouseType(Gfx::MouseType type)
{
- // TODO
+ // TODO
}
void SetNiceMouse(bool nice)
{
- // TODO
+ // TODO
}
bool CApplication::RetNiceMouse()
{
- return false;
+ return false;
}
bool CApplication::RetNiceMouseCap()
{
- return false;
+ return false;
}
bool CApplication::WriteScreenShot(char *filename, int width, int height)
{
- // TODO
+ // TODO
}
void CApplication::InitText()
{
- // TODO
+ // TODO
}
void CApplication::DrawSuppl()
{
- // TODO
+ // TODO
}
void CApplication::ShowStats()
{
- // TODO
+ // TODO
}
void CApplication::OutputText(long x, long y, char* str)
{
- // TODO
+ // TODO
}
diff --git a/src/app/app.h b/src/app/app.h
index ee6184f..a58ea98 100644
--- a/src/app/app.h
+++ b/src/app/app.h
@@ -46,108 +46,108 @@ struct ApplicationPrivate;
class CApplication
{
public:
- //! Constructor (can only be called once!)
- CApplication();
- //! Destructor
- ~CApplication();
+ //! Constructor (can only be called once!)
+ CApplication();
+ //! Destructor
+ ~CApplication();
public:
- //! Parses commandline arguments
- Error ParseArguments(int argc, char *argv[]);
- //! Initializes the application
- bool Create();
- //! Main event loop
- int Run();
+ //! Parses commandline arguments
+ Error ParseArguments(int argc, char *argv[]);
+ //! Initializes the application
+ bool Create();
+ //! Main event loop
+ int Run();
protected:
- //! Cleans up before exit
- void Destroy();
- //! Processes an SDL event to Event struct
- void ParseEvent();
- //! Handles some incoming events
- void ProcessEvent(Event event);
- //! Renders the image in window
- bool Render();
+ //! Cleans up before exit
+ void Destroy();
+ //! Processes an SDL event to Event struct
+ void ParseEvent();
+ //! Handles some incoming events
+ void ProcessEvent(Event event);
+ //! Renders the image in window
+ bool Render();
public:
- void Pause(bool pause);
- void StepSimulation(float rTime);
+ void Pause(bool pause);
+ void StepSimulation(float rTime);
- void SetMousePos(Math::Point pos);
+ void SetMousePos(Math::Point pos);
- void SetShowStat(bool show);
- bool RetShowStat();
- void SetDebugMode(bool mode);
- bool RetDebugMode();
- bool RetSetupMode();
+ void SetShowStat(bool show);
+ bool RetShowStat();
+ void SetDebugMode(bool mode);
+ bool RetDebugMode();
+ bool RetSetupMode();
- void FlushPressKey();
- void ResetKey();
- void SetKey(int keyRank, int option, int key);
- int RetKey(int keyRank, int option);
+ void FlushPressKey();
+ void ResetKey();
+ void SetKey(int keyRank, int option, int key);
+ int RetKey(int keyRank, int option);
- void SetJoystick(bool enable);
- bool RetJoystick();
+ void SetJoystick(bool enable);
+ bool RetJoystick();
- void SetMouseType(Gfx::MouseType type);
- void SetNiceMouse(bool nice);
- bool RetNiceMouse();
- bool RetNiceMouseCap();
+ void SetMouseType(Gfx::MouseType type);
+ void SetNiceMouse(bool nice);
+ bool RetNiceMouse();
+ bool RetNiceMouseCap();
- bool WriteScreenShot(char *filename, int width, int height);
+ bool WriteScreenShot(char *filename, int width, int height);
protected:
- //HRESULT ConfirmDevice( DDCAPS* pddDriverCaps, D3DDEVICEDESC7* pd3dDeviceDesc );
- //HRESULT Initialize3DEnvironment();
- //HRESULT Change3DEnvironment();
- //HRESULT CreateZBuffer(GUID* pDeviceGUID);
- //HRESULT Render3DEnvironment();
- //VOID Cleanup3DEnvironment();
- //VOID DeleteDeviceObjects();
- //VOID DisplayFrameworkError( HRESULT, DWORD );
-
- void InitText();
- void DrawSuppl();
- void ShowStats();
- void OutputText(long x, long y, char* str);
+ //HRESULT ConfirmDevice( DDCAPS* pddDriverCaps, D3DDEVICEDESC7* pd3dDeviceDesc );
+ //HRESULT Initialize3DEnvironment();
+ //HRESULT Change3DEnvironment();
+ //HRESULT CreateZBuffer(GUID* pDeviceGUID);
+ //HRESULT Render3DEnvironment();
+ //VOID Cleanup3DEnvironment();
+ //VOID DeleteDeviceObjects();
+ //VOID DisplayFrameworkError( HRESULT, DWORD );
+
+ void InitText();
+ void DrawSuppl();
+ void ShowStats();
+ void OutputText(long x, long y, char* str);
protected:
- //! Private (SDL-dependent data)
- ApplicationPrivate* m_private;
- CInstanceManager* m_iMan;
- Gfx::DeviceConfig m_deviceConfig;
- Gfx::CEngine* m_engine;
- CEvent* m_event;
- CRobotMain* m_robotMain;
- CSound* m_sound;
-
- //! Code to return at exit
- int m_exitCode;
-
- bool m_active;
- bool m_activateApp;
- bool m_ready;
- bool m_joystick;
-
- std::string m_windowTitle;
- long m_vidMemTotal;
- bool m_appUseZBuffer;
- bool m_appUseStereo;
- bool m_showStats;
- bool m_debugMode;
- bool m_audioState;
- bool m_audioTrack;
- bool m_niceMouse;
- bool m_setupMode;
-
- int m_keyState;
- Math::Vector m_axeKey;
- Math::Vector m_axeJoy;
- bool m_joyButton[32];
- Math::Point m_mousePos;
- long m_mouseWheel;
-
- float m_time;
- long m_key[50][2];
+ //! Private (SDL-dependent data)
+ ApplicationPrivate* m_private;
+ CInstanceManager* m_iMan;
+ Gfx::DeviceConfig m_deviceConfig;
+ Gfx::CEngine* m_engine;
+ CEvent* m_event;
+ CRobotMain* m_robotMain;
+ CSound* m_sound;
+
+ //! Code to return at exit
+ int m_exitCode;
+
+ bool m_active;
+ bool m_activateApp;
+ bool m_ready;
+ bool m_joystick;
+
+ std::string m_windowTitle;
+ long m_vidMemTotal;
+ bool m_appUseZBuffer;
+ bool m_appUseStereo;
+ bool m_showStats;
+ bool m_debugMode;
+ bool m_audioState;
+ bool m_audioTrack;
+ bool m_niceMouse;
+ bool m_setupMode;
+
+ int m_keyState;
+ Math::Vector m_axeKey;
+ Math::Vector m_axeJoy;
+ bool m_joyButton[32];
+ Math::Point m_mousePos;
+ long m_mouseWheel;
+
+ float m_time;
+ long m_key[50][2];
};
diff --git a/src/app/main.cpp b/src/app/main.cpp
index 28d21ee..54d305e 100644
--- a/src/app/main.cpp
+++ b/src/app/main.cpp
@@ -26,16 +26,16 @@
//! Entry point to the program
int main(int argc, char *argv[])
{
- CApplication app; // single instance of the application
+ CApplication app; // single instance of the application
- Error err = app.ParseArguments(argc, argv);
- if (err != ERR_OK)
- {
- SystemDialog(SDT_ERROR, "COLOBOT", "Invalid commandline arguments!\n");
- }
+ Error err = app.ParseArguments(argc, argv);
+ if (err != ERR_OK)
+ {
+ SystemDialog(SDT_ERROR, "COLOBOT", "Invalid commandline arguments!\n");
+ }
- if (! app.Create())
- return 0;
+ if (! app.Create())
+ return 0;
- return app.Run();
+ return app.Run();
}
diff --git a/src/app/system.cpp b/src/app/system.cpp
index 4f7cd26..a765e11 100644
--- a/src/app/system.cpp
+++ b/src/app/system.cpp
@@ -45,13 +45,13 @@ SystemDialogResult SystemDialog_Other(SystemDialogType type, const std::string&
*/
SystemDialogResult SystemDialog(SystemDialogType type, const std::string& title, const std::string& message)
{
- #if defined(PLATFORM_WINDOWS)
- return SystemDialog_Windows(type, title, message);
- #elif defined(PLATFORM_LINUX)
- return SystemDialog_Linux(type, title, message);
- #else
- return SystemDialog_Other(type, title, message);
- #endif
+ #if defined(PLATFORM_WINDOWS)
+ return SystemDialog_Windows(type, title, message);
+ #elif defined(PLATFORM_LINUX)
+ return SystemDialog_Linux(type, title, message);
+ #else
+ return SystemDialog_Other(type, title, message);
+ #endif
}
@@ -61,193 +61,193 @@ SystemDialogResult SystemDialog(SystemDialogType type, const std::string& title,
// Convert a wide Unicode string to an UTF8 string
std::string UTF8_Encode_Windows(const std::wstring &wstr)
{
- int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
- std::string strTo(size_needed, 0);
- WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
- return strTo;
+ int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
+ std::string strTo(size_needed, 0);
+ WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
+ return strTo;
}
// Convert an UTF8 string to a wide Unicode String
std::wstring UTF8_Decode_Windows(const std::string &str)
{
- int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
- std::wstring wstrTo(size_needed, 0);
- MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
- return wstrTo;
+ int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
+ std::wstring wstrTo(size_needed, 0);
+ MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
+ return wstrTo;
}
SystemDialogResult SystemDialog_Windows(SystemDialogType type, const std::string& title, const std::string& message)
{
- unsigned int windowsType = 0;
- std::wstring windowsMessage = UTF8_Decode_Windows(message);
- std::wstring windowsTitle = UTF8_Decode_Windows(title);
-
- switch (type)
- {
- case SDT_INFO:
- default:
- windowsType = MB_ICONINFORMATION|MB_OK;
- break;
- case SDT_WARNING:
- windowsType = MB_ICONWARNING|MB_OK;
- break;
- case SDT_ERROR:
- windowsType = MB_ICONERROR|MB_OK;
- break;
- case SDT_YES_NO:
- windowsType = MB_ICONQUESTION|MB_YESNO;
- break;
- case SDT_OK_CANCEL:
- windowsType = MB_ICONWARNING|MB_OKCANCEL;
- break;
- }
-
- switch (MessageBoxW(NULL, windowsMessage.c_str(), windowsTitle.c_str(), windowsType))
- {
- case IDOK:
- return SDR_OK;
- case IDCANCEL:
- return SDR_CANCEL;
- case IDYES:
- return SDR_YES;
- case IDNO:
- return SDR_NO;
- default:
- break;
- }
-
- return SDR_OK;
+ unsigned int windowsType = 0;
+ std::wstring windowsMessage = UTF8_Decode_Windows(message);
+ std::wstring windowsTitle = UTF8_Decode_Windows(title);
+
+ switch (type)
+ {
+ case SDT_INFO:
+ default:
+ windowsType = MB_ICONINFORMATION|MB_OK;
+ break;
+ case SDT_WARNING:
+ windowsType = MB_ICONWARNING|MB_OK;
+ break;
+ case SDT_ERROR:
+ windowsType = MB_ICONERROR|MB_OK;
+ break;
+ case SDT_YES_NO:
+ windowsType = MB_ICONQUESTION|MB_YESNO;
+ break;
+ case SDT_OK_CANCEL:
+ windowsType = MB_ICONWARNING|MB_OKCANCEL;
+ break;
+ }
+
+ switch (MessageBoxW(NULL, windowsMessage.c_str(), windowsTitle.c_str(), windowsType))
+ {
+ case IDOK:
+ return SDR_OK;
+ case IDCANCEL:
+ return SDR_CANCEL;
+ case IDYES:
+ return SDR_YES;
+ case IDNO:
+ return SDR_NO;
+ default:
+ break;
+ }
+
+ return SDR_OK;
}
#elif defined(PLATFORM_LINUX)
SystemDialogResult SystemDialog_Linux(SystemDialogType type, const std::string& title, const std::string& message)
{
- std::string options = "";
- switch (type)
- {
- case SDT_INFO:
- default:
- options = "--info";
- break;
+ std::string options = "";
+ switch (type)
+ {
+ case SDT_INFO:
+ default:
+ options = "--info";
+ break;
case SDT_WARNING:
- options = "--warning";
- break;
+ options = "--warning";
+ break;
case SDT_ERROR:
- options = "--error";
- break;
+ options = "--error";
+ break;
case SDT_YES_NO:
- options = "--question --ok-label=\"Yes\" --cancel-label=\"No\"";
- break;
+ options = "--question --ok-label=\"Yes\" --cancel-label=\"No\"";
+ break;
case SDT_OK_CANCEL:
- options = "--question --ok-label=\"OK\" --cancel-label=\"Cancel\"";
- break;
- }
-
- std::string command = "zenity " + options + " --text=\"" + message + "\" --title=\"" + title + "\"";
- int code = system(command.c_str());
-
- SystemDialogResult result = SDR_OK;
- switch (type)
- {
- case SDT_YES_NO:
- result = code ? SDR_NO : SDR_YES;
- break;
- case SDT_OK_CANCEL:
- result = code ? SDR_CANCEL : SDR_OK;
- break;
- default:
- break;
- }
-
- return result;
+ options = "--question --ok-label=\"OK\" --cancel-label=\"Cancel\"";
+ break;
+ }
+
+ std::string command = "zenity " + options + " --text=\"" + message + "\" --title=\"" + title + "\"";
+ int code = system(command.c_str());
+
+ SystemDialogResult result = SDR_OK;
+ switch (type)
+ {
+ case SDT_YES_NO:
+ result = code ? SDR_NO : SDR_YES;
+ break;
+ case SDT_OK_CANCEL:
+ result = code ? SDR_CANCEL : SDR_OK;
+ break;
+ default:
+ break;
+ }
+
+ return result;
}
#else
SystemDialogResult SystemDialog_Other(SystemDialogType type, const std::string& title, const std::string& message)
{
- switch (type)
- {
- case SDT_INFO:
- std::cout << "INFO: ";
- break;
- case SDT_WARNING:
- std::cout << "WARNING:";
- break;
- case SDT_ERROR:
- std::cout << "ERROR: ";
- break;
- case SDT_YES_NO:
- case SDT_OK_CANCEL:
- std::cout << "QUESTION: ";
- break;
- }
-
- std::cout << message << std::endl;
-
- std::string line;
-
- SystemDialogResult result = SDR_OK;
-
- bool done = false;
- while (!done)
- {
- switch (type)
- {
- case SDT_INFO:
- case SDT_WARNING:
- case SDT_ERROR:
- std::cout << "Press ENTER to continue";
- break;
-
- case SDT_YES_NO:
- std::cout << "Type 'Y' for Yes or 'N' for No";
- break;
-
- case SDT_OK_CANCEL:
- std::cout << "Type 'O' for OK or 'C' for Cancel";
- break;
- }
-
- std::getline(std::cin, line);
-
- switch (type)
- {
- case SDT_INFO:
- case SDT_WARNING:
- case SDT_ERROR:
- done = true;
- break;
-
- case SDT_YES_NO:
- if (line == "Y" || line == "y")
- {
- result = SDR_YES;
- done = true;
- }
- else if (line == "N" || line == "n")
- {
- result = SDR_NO;
- done = true;
- }
- break;
-
- case SDT_OK_CANCEL:
- if (line == "O" || line == "o")
- {
- done = true;
- result = SDR_OK;
- }
- else if (line == "C" || line == "c")
- {
- done = true;
- result = SDR_CANCEL;
- }
- break;
- }
- }
-
- return result;
+ switch (type)
+ {
+ case SDT_INFO:
+ std::cout << "INFO: ";
+ break;
+ case SDT_WARNING:
+ std::cout << "WARNING:";
+ break;
+ case SDT_ERROR:
+ std::cout << "ERROR: ";
+ break;
+ case SDT_YES_NO:
+ case SDT_OK_CANCEL:
+ std::cout << "QUESTION: ";
+ break;
+ }
+
+ std::cout << message << std::endl;
+
+ std::string line;
+
+ SystemDialogResult result = SDR_OK;
+
+ bool done = false;
+ while (!done)
+ {
+ switch (type)
+ {
+ case SDT_INFO:
+ case SDT_WARNING:
+ case SDT_ERROR:
+ std::cout << "Press ENTER to continue";
+ break;
+
+ case SDT_YES_NO:
+ std::cout << "Type 'Y' for Yes or 'N' for No";
+ break;
+
+ case SDT_OK_CANCEL:
+ std::cout << "Type 'O' for OK or 'C' for Cancel";
+ break;
+ }
+
+ std::getline(std::cin, line);
+
+ switch (type)
+ {
+ case SDT_INFO:
+ case SDT_WARNING:
+ case SDT_ERROR:
+ done = true;
+ break;
+
+ case SDT_YES_NO:
+ if (line == "Y" || line == "y")
+ {
+ result = SDR_YES;
+ done = true;
+ }
+ else if (line == "N" || line == "n")
+ {
+ result = SDR_NO;
+ done = true;
+ }
+ break;
+
+ case SDT_OK_CANCEL:
+ if (line == "O" || line == "o")
+ {
+ done = true;
+ result = SDR_OK;
+ }
+ else if (line == "C" || line == "c")
+ {
+ done = true;
+ result = SDR_CANCEL;
+ }
+ break;
+ }
+ }
+
+ return result;
}
#endif // if defined(PLATFORM_WINDOWS)
diff --git a/src/app/system.h b/src/app/system.h
index fd1c051..95571a2 100644
--- a/src/app/system.h
+++ b/src/app/system.h
@@ -28,16 +28,16 @@
*/
enum SystemDialogType
{
- //! Information message
- SDT_INFO,
- //! Warning message
- SDT_WARNING,
- //! Error message
- SDT_ERROR,
- //! Yes/No question
- SDT_YES_NO,
- //! Ok/Cancel question
- SDT_OK_CANCEL
+ //! Information message
+ SDT_INFO,
+ //! Warning message
+ SDT_WARNING,
+ //! Error message
+ SDT_ERROR,
+ //! Yes/No question
+ SDT_YES_NO,
+ //! Ok/Cancel question
+ SDT_OK_CANCEL
};
/**
@@ -47,10 +47,10 @@ enum SystemDialogType
*/
enum SystemDialogResult
{
- SDR_OK,
- SDR_CANCEL,
- SDR_YES,
- SDR_NO
+ SDR_OK,
+ SDR_CANCEL,
+ SDR_YES,
+ SDR_NO
};
//! Displays a system dialog
diff --git a/src/common/event.cpp b/src/common/event.cpp
index 0a56fb9..9af4691 100644
--- a/src/common/event.cpp
+++ b/src/common/event.cpp
@@ -1,96 +1,96 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// event.cpp
-
-#include "common/iman.h"
-#include "common/event.h"
-
-#include <string.h>
-
-
-Event::Event()
-{
- event = EVENT_NULL;
- param = 0;
- axeX = 0.0f;
- axeY = 0.0f;
- axeZ = 0.0f;
- keyState = 0;
- rTime = 0.0f;
-}
-
-
-// Object's constructor.
-
-CEvent::CEvent(CInstanceManager* iMan)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_EVENT, this);
-
- Flush();
-}
-
-// Object's destructor.
-
-CEvent::~CEvent()
-{
-}
-
-
-// Empty the FIFO of events.
-
-void CEvent::Flush()
-{
- m_head = 0;
- m_tail = 0;
- m_total = 0;
-}
-
-// Produces an event.
-
-void CEvent::MakeEvent(Event &event, EventMsg msg)
-{
- memset(&event, 0, sizeof(Event));
- event.event = msg;
-}
-
-// Adds an event in the FIFO.
-
-bool CEvent::AddEvent(const Event &event)
-{
- if ( m_total >= MAXEVENT ) return false;
-
- m_fifo[m_head++] = event;
- if ( m_head >= MAXEVENT ) m_head = 0;
- m_total ++;
-
- return true;
-}
-
-// Removes an event from the FIFO.
-
-bool CEvent::GetEvent(Event &event)
-{
- if ( m_head == m_tail ) return false;
-
- event = m_fifo[m_tail++];
- if ( m_tail >= MAXEVENT ) m_tail = 0;
- m_total --;
-
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// event.cpp
+
+#include "common/iman.h"
+#include "common/event.h"
+
+#include <string.h>
+
+
+Event::Event()
+{
+ event = EVENT_NULL;
+ param = 0;
+ axeX = 0.0f;
+ axeY = 0.0f;
+ axeZ = 0.0f;
+ keyState = 0;
+ rTime = 0.0f;
+}
+
+
+// Object's constructor.
+
+CEvent::CEvent(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_EVENT, this);
+
+ Flush();
+}
+
+// Object's destructor.
+
+CEvent::~CEvent()
+{
+}
+
+
+// Empty the FIFO of events.
+
+void CEvent::Flush()
+{
+ m_head = 0;
+ m_tail = 0;
+ m_total = 0;
+}
+
+// Produces an event.
+
+void CEvent::MakeEvent(Event &event, EventMsg msg)
+{
+ memset(&event, 0, sizeof(Event));
+ event.event = msg;
+}
+
+// Adds an event in the FIFO.
+
+bool CEvent::AddEvent(const Event &event)
+{
+ if ( m_total >= MAXEVENT ) return false;
+
+ m_fifo[m_head++] = event;
+ if ( m_head >= MAXEVENT ) m_head = 0;
+ m_total ++;
+
+ return true;
+}
+
+// Removes an event from the FIFO.
+
+bool CEvent::GetEvent(Event &event)
+{
+ if ( m_head == m_tail ) return false;
+
+ event = m_fifo[m_tail++];
+ if ( m_tail >= MAXEVENT ) m_tail = 0;
+ m_total --;
+
+ return true;
+}
+
diff --git a/src/common/event.h b/src/common/event.h
index 95e303c..8174fab 100644
--- a/src/common/event.h
+++ b/src/common/event.h
@@ -1,633 +1,633 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// event.h
-
-#pragma once
-
-
-#include "math/point.h"
-
-
-#if !defined (WM_XBUTTONDOWN)
-#define WM_XBUTTONDOWN 0x020B
-#define WM_XBUTTONUP 0x020C
-#define XBUTTON1 0x0001
-#define XBUTTON2 0x0002
-#endif
-
-
-
-class CInstanceManager;
-
-
-const int MAXEVENT = 100;
-
-// Events.
-
-enum EventMsg
-{
- EVENT_NULL = 0,
-
- EVENT_QUIT = 1,
- EVENT_FRAME = 2,
- EVENT_LBUTTONDOWN = 3,
- EVENT_RBUTTONDOWN = 4,
- EVENT_LBUTTONUP = 5,
- EVENT_RBUTTONUP = 6,
- EVENT_MOUSEMOVE = 7,
- EVENT_KEYDOWN = 8,
- EVENT_KEYUP = 9,
- EVENT_CHAR = 10,
- EVENT_FOCUS = 11,
-
- EVENT_UPDINTERFACE = 20,
- EVENT_WIN = 30,
- EVENT_LOST = 31,
-
- EVENT_BUTTON_OK = 40,
- EVENT_BUTTON_CANCEL = 41,
- EVENT_BUTTON_NEXT = 42,
- EVENT_BUTTON_PREV = 43,
- EVENT_BUTTON_QUIT = 44,
-
- EVENT_BUTTON0 = 50,
- EVENT_BUTTON1 = 51,
- EVENT_BUTTON2 = 52,
- EVENT_BUTTON3 = 53,
- EVENT_BUTTON4 = 54,
- EVENT_BUTTON5 = 55,
- EVENT_BUTTON6 = 56,
- EVENT_BUTTON7 = 57,
- EVENT_BUTTON8 = 58,
- EVENT_BUTTON9 = 59,
- EVENT_BUTTON10 = 60,
- EVENT_BUTTON11 = 61,
- EVENT_BUTTON12 = 62,
- EVENT_BUTTON13 = 63,
- EVENT_BUTTON14 = 64,
- EVENT_BUTTON15 = 65,
- EVENT_BUTTON16 = 66,
- EVENT_BUTTON17 = 67,
- EVENT_BUTTON18 = 68,
- EVENT_BUTTON19 = 69,
-
- EVENT_EDIT0 = 70,
- EVENT_EDIT1 = 71,
- EVENT_EDIT2 = 72,
- EVENT_EDIT3 = 73,
- EVENT_EDIT4 = 74,
- EVENT_EDIT5 = 75,
- EVENT_EDIT6 = 76,
- EVENT_EDIT7 = 77,
- EVENT_EDIT8 = 78,
- EVENT_EDIT9 = 79,
-
- EVENT_WINDOW0 = 80, // the bottom panel
- EVENT_WINDOW1 = 81, // map
- EVENT_WINDOW2 = 82, // CDisplayText
- EVENT_WINDOW3 = 83, // CStudio
- EVENT_WINDOW4 = 84, // DisplayInfo
- EVENT_WINDOW5 = 85, // setup
- EVENT_WINDOW6 = 86,
- EVENT_WINDOW7 = 87,
- EVENT_WINDOW8 = 88,
- EVENT_WINDOW9 = 89, // dialogue
-
- EVENT_LABEL0 = 90,
- EVENT_LABEL1 = 91,
- EVENT_LABEL2 = 92,
- EVENT_LABEL3 = 93,
- EVENT_LABEL4 = 94,
- EVENT_LABEL5 = 95,
- EVENT_LABEL6 = 96,
- EVENT_LABEL7 = 97,
- EVENT_LABEL8 = 98,
- EVENT_LABEL9 = 99,
- EVENT_LABEL10 = 100,
- EVENT_LABEL11 = 101,
- EVENT_LABEL12 = 102,
- EVENT_LABEL13 = 103,
- EVENT_LABEL14 = 104,
- EVENT_LABEL15 = 105,
- EVENT_LABEL16 = 106,
- EVENT_LABEL17 = 107,
- EVENT_LABEL18 = 108,
- EVENT_LABEL19 = 109,
-
- EVENT_LIST0 = 110,
- EVENT_LIST1 = 111,
- EVENT_LIST2 = 112,
- EVENT_LIST3 = 113,
- EVENT_LIST4 = 114,
- EVENT_LIST5 = 115,
- EVENT_LIST6 = 116,
- EVENT_LIST7 = 117,
- EVENT_LIST8 = 118,
- EVENT_LIST9 = 119,
-
- EVENT_TOOLTIP = 200,
-
- EVENT_DIALOG_OK = 300,
- EVENT_DIALOG_CANCEL = 301,
- EVENT_DIALOG_LABEL = 302,
- EVENT_DIALOG_LABEL1 = 303,
- EVENT_DIALOG_LABEL2 = 304,
- EVENT_DIALOG_LABEL3 = 305,
- EVENT_DIALOG_LIST = 306,
- EVENT_DIALOG_EDIT = 307,
- EVENT_DIALOG_CHECK1 = 308,
- EVENT_DIALOG_CHECK2 = 309,
-
- EVENT_INTERFACE_TRAINER = 400,
- EVENT_INTERFACE_DEFI = 401,
- EVENT_INTERFACE_MISSION = 402,
- EVENT_INTERFACE_FREE = 403,
- EVENT_INTERFACE_PROTO = 404,
- EVENT_INTERFACE_NAME = 405,
- EVENT_INTERFACE_SETUP = 406,
- EVENT_INTERFACE_QUIT = 407,
- EVENT_INTERFACE_BACK = 408,
- EVENT_INTERFACE_AGAIN = 409,
- EVENT_INTERFACE_WRITE = 410,
- EVENT_INTERFACE_READ = 411,
- EVENT_INTERFACE_ABORT = 412,
- EVENT_INTERFACE_USER = 413,
- EVENT_INTERFACE_TEEN = 414,
-
- EVENT_INTERFACE_CHAP = 420,
- EVENT_INTERFACE_LIST = 421,
- EVENT_INTERFACE_RESUME = 422,
- EVENT_INTERFACE_PLAY = 423,
-
- EVENT_INTERFACE_SETUPd = 430,
- EVENT_INTERFACE_SETUPg = 431,
- EVENT_INTERFACE_SETUPp = 432,
- EVENT_INTERFACE_SETUPc = 433,
- EVENT_INTERFACE_SETUPs = 434,
-
- EVENT_INTERFACE_DEVICE = 440,
- EVENT_INTERFACE_RESOL = 441,
- EVENT_INTERFACE_FULL = 442,
- EVENT_INTERFACE_APPLY = 443,
-
- EVENT_INTERFACE_TOTO = 450,
- EVENT_INTERFACE_SHADOW = 451,
- EVENT_INTERFACE_DIRTY = 452,
- EVENT_INTERFACE_LENS = 453,
- EVENT_INTERFACE_SKY = 454,
- EVENT_INTERFACE_PLANET = 456,
- EVENT_INTERFACE_LIGHT = 457,
- EVENT_INTERFACE_PARTI = 458,
- EVENT_INTERFACE_CLIP = 459,
- EVENT_INTERFACE_DETAIL = 460,
- EVENT_INTERFACE_TEXTURE = 461,
- EVENT_INTERFACE_RAIN = 462,
- EVENT_INTERFACE_GLINT = 463,
- EVENT_INTERFACE_TOOLTIP = 464,
- EVENT_INTERFACE_MOVIES = 465,
- EVENT_INTERFACE_NICERST = 466,
- EVENT_INTERFACE_SCROLL = 467,
- EVENT_INTERFACE_INVERTX = 468,
- EVENT_INTERFACE_INVERTY = 469,
- EVENT_INTERFACE_EFFECT = 470,
- EVENT_INTERFACE_MOUSE = 471,
- EVENT_INTERFACE_GROUND = 472,
- EVENT_INTERFACE_GADGET = 473,
- EVENT_INTERFACE_FOG = 474,
- EVENT_INTERFACE_HIMSELF = 475,
- EVENT_INTERFACE_EDITMODE= 476,
- EVENT_INTERFACE_EDITVALUE= 477,
- EVENT_INTERFACE_SOLUCE4 = 478,
-
- EVENT_INTERFACE_KINFO1 = 500,
- EVENT_INTERFACE_KINFO2 = 501,
- EVENT_INTERFACE_KGROUP = 502,
- EVENT_INTERFACE_KSCROLL = 503,
- EVENT_INTERFACE_KDEF = 504,
- EVENT_INTERFACE_KLEFT = 505,
- EVENT_INTERFACE_KRIGHT = 506,
- EVENT_INTERFACE_KUP = 507,
- EVENT_INTERFACE_KDOWN = 508,
- EVENT_INTERFACE_KGUP = 509,
- EVENT_INTERFACE_KGDOWN = 510,
- EVENT_INTERFACE_KCAMERA = 511,
- EVENT_INTERFACE_KDESEL = 512,
- EVENT_INTERFACE_KACTION = 513,
- EVENT_INTERFACE_KNEAR = 514,
- EVENT_INTERFACE_KAWAY = 515,
- EVENT_INTERFACE_KNEXT = 516,
- EVENT_INTERFACE_KHUMAN = 517,
- EVENT_INTERFACE_KQUIT = 518,
- EVENT_INTERFACE_KHELP = 519,
- EVENT_INTERFACE_KPROG = 520,
- EVENT_INTERFACE_KCBOT = 521,
- EVENT_INTERFACE_KVISIT = 522,
- EVENT_INTERFACE_KSPEED10= 523,
- EVENT_INTERFACE_KSPEED15= 524,
- EVENT_INTERFACE_KSPEED20= 525,
- EVENT_INTERFACE_KSPEED30= 526,
-
- EVENT_INTERFACE_VOLSOUND= 530,
- EVENT_INTERFACE_VOLMUSIC= 531,
- EVENT_INTERFACE_SOUND3D = 532,
-
- EVENT_INTERFACE_MIN = 540,
- EVENT_INTERFACE_NORM = 541,
- EVENT_INTERFACE_MAX = 542,
-
- EVENT_INTERFACE_SILENT = 550,
- EVENT_INTERFACE_NOISY = 551,
-
- EVENT_INTERFACE_JOYSTICK= 560,
- EVENT_INTERFACE_SOLUCE = 561,
-
- EVENT_INTERFACE_GLINTl = 570,
- EVENT_INTERFACE_GLINTr = 571,
- EVENT_INTERFACE_GLINTu = 572,
- EVENT_INTERFACE_GLINTb = 573,
-
- EVENT_INTERFACE_NEDIT = 580,
- EVENT_INTERFACE_NLIST = 581,
- EVENT_INTERFACE_NOK = 582,
- EVENT_INTERFACE_NCANCEL = 583,
- EVENT_INTERFACE_NDELETE = 584,
- EVENT_INTERFACE_NLABEL = 585,
-
- EVENT_INTERFACE_IOWRITE = 600,
- EVENT_INTERFACE_IOREAD = 601,
- EVENT_INTERFACE_IOLIST = 602,
- EVENT_INTERFACE_IONAME = 603,
- EVENT_INTERFACE_IOLABEL = 604,
- EVENT_INTERFACE_IOIMAGE = 605,
- EVENT_INTERFACE_IODELETE= 606,
-
- EVENT_INTERFACE_PERSO = 620,
- EVENT_INTERFACE_POK = 621,
- EVENT_INTERFACE_PCANCEL = 622,
- EVENT_INTERFACE_PDEF = 623,
- EVENT_INTERFACE_PHEAD = 624,
- EVENT_INTERFACE_PBODY = 625,
- EVENT_INTERFACE_PLROT = 626,
- EVENT_INTERFACE_PRROT = 627,
- EVENT_INTERFACE_PC0a = 640,
- EVENT_INTERFACE_PC1a = 641,
- EVENT_INTERFACE_PC2a = 642,
- EVENT_INTERFACE_PC3a = 643,
- EVENT_INTERFACE_PC4a = 644,
- EVENT_INTERFACE_PC5a = 645,
- EVENT_INTERFACE_PC6a = 646,
- EVENT_INTERFACE_PC7a = 647,
- EVENT_INTERFACE_PC8a = 648,
- EVENT_INTERFACE_PC9a = 649,
- EVENT_INTERFACE_PCRa = 650,
- EVENT_INTERFACE_PCGa = 651,
- EVENT_INTERFACE_PCBa = 652,
- EVENT_INTERFACE_PC0b = 660,
- EVENT_INTERFACE_PC1b = 661,
- EVENT_INTERFACE_PC2b = 662,
- EVENT_INTERFACE_PC3b = 663,
- EVENT_INTERFACE_PC4b = 664,
- EVENT_INTERFACE_PC5b = 665,
- EVENT_INTERFACE_PC6b = 666,
- EVENT_INTERFACE_PC7b = 667,
- EVENT_INTERFACE_PC8b = 668,
- EVENT_INTERFACE_PC9b = 669,
- EVENT_INTERFACE_PCRb = 670,
- EVENT_INTERFACE_PCGb = 671,
- EVENT_INTERFACE_PCBb = 672,
- EVENT_INTERFACE_PFACE1 = 680,
- EVENT_INTERFACE_PFACE2 = 681,
- EVENT_INTERFACE_PFACE3 = 682,
- EVENT_INTERFACE_PFACE4 = 683,
- EVENT_INTERFACE_PGLASS0 = 690,
- EVENT_INTERFACE_PGLASS1 = 691,
- EVENT_INTERFACE_PGLASS2 = 692,
- EVENT_INTERFACE_PGLASS3 = 693,
- EVENT_INTERFACE_PGLASS4 = 694,
- EVENT_INTERFACE_PGLASS5 = 695,
- EVENT_INTERFACE_PGLASS6 = 696,
- EVENT_INTERFACE_PGLASS7 = 697,
- EVENT_INTERFACE_PGLASS8 = 698,
- EVENT_INTERFACE_PGLASS9 = 699,
-
- EVENT_DT_GROUP0 = 700,
- EVENT_DT_GROUP1 = 701,
- EVENT_DT_GROUP2 = 702,
- EVENT_DT_GROUP3 = 703,
- EVENT_DT_GROUP4 = 704,
- EVENT_DT_LABEL0 = 710,
- EVENT_DT_LABEL1 = 711,
- EVENT_DT_LABEL2 = 712,
- EVENT_DT_LABEL3 = 713,
- EVENT_DT_LABEL4 = 714,
- EVENT_DT_VISIT0 = 720,
- EVENT_DT_VISIT1 = 721,
- EVENT_DT_VISIT2 = 722,
- EVENT_DT_VISIT3 = 723,
- EVENT_DT_VISIT4 = 724,
- EVENT_DT_END = 725,
-
- EVENT_CMD = 800,
- EVENT_SPEED = 801,
-
- EVENT_HYPER_PREV = 900,
- EVENT_HYPER_NEXT = 901,
- EVENT_HYPER_HOME = 902,
- EVENT_HYPER_COPY = 903,
- EVENT_HYPER_SIZE1 = 904,
- EVENT_HYPER_SIZE2 = 905,
- EVENT_HYPER_SIZE3 = 906,
- EVENT_HYPER_SIZE4 = 907,
- EVENT_HYPER_SIZE5 = 908,
-
- EVENT_SATCOM_HUSTON = 920,
- EVENT_SATCOM_SAT = 921,
- EVENT_SATCOM_LOADING = 922,
- EVENT_SATCOM_OBJECT = 923,
- EVENT_SATCOM_PROG = 924,
- EVENT_SATCOM_SOLUCE = 925,
-
- EVENT_OBJECT_DESELECT = 1000,
- EVENT_OBJECT_LEFT = 1001,
- EVENT_OBJECT_RIGHT = 1002,
- EVENT_OBJECT_UP = 1003,
- EVENT_OBJECT_DOWN = 1004,
- EVENT_OBJECT_GASUP = 1005,
- EVENT_OBJECT_GASDOWN = 1006,
- EVENT_OBJECT_HTAKE = 1020,
- EVENT_OBJECT_MTAKE = 1021,
- EVENT_OBJECT_MFRONT = 1022,
- EVENT_OBJECT_MBACK = 1023,
- EVENT_OBJECT_MPOWER = 1024,
- EVENT_OBJECT_BHELP = 1040,
- EVENT_OBJECT_BTAKEOFF = 1041,
- EVENT_OBJECT_BDERRICK = 1050,
- EVENT_OBJECT_BSTATION = 1051,
- EVENT_OBJECT_BFACTORY = 1052,
- EVENT_OBJECT_BCONVERT = 1053,
- EVENT_OBJECT_BTOWER = 1054,
- EVENT_OBJECT_BREPAIR = 1055,
- EVENT_OBJECT_BRESEARCH = 1056,
- EVENT_OBJECT_BRADAR = 1057,
- EVENT_OBJECT_BENERGY = 1058,
- EVENT_OBJECT_BLABO = 1059,
- EVENT_OBJECT_BNUCLEAR = 1060,
- EVENT_OBJECT_BPARA = 1061,
- EVENT_OBJECT_BINFO = 1062,
- EVENT_OBJECT_BXXXX = 1063,
- EVENT_OBJECT_GFLAT = 1070,
- EVENT_OBJECT_FCREATE = 1071,
- EVENT_OBJECT_FDELETE = 1072,
- EVENT_OBJECT_FCOLORb = 1073,
- EVENT_OBJECT_FCOLORr = 1074,
- EVENT_OBJECT_FCOLORg = 1075,
- EVENT_OBJECT_FCOLORy = 1076,
- EVENT_OBJECT_FCOLORv = 1077,
- EVENT_OBJECT_FACTORYwa = 1080,
- EVENT_OBJECT_FACTORYta = 1081,
- EVENT_OBJECT_FACTORYfa = 1082,
- EVENT_OBJECT_FACTORYia = 1083,
- EVENT_OBJECT_FACTORYwc = 1084,
- EVENT_OBJECT_FACTORYtc = 1085,
- EVENT_OBJECT_FACTORYfc = 1086,
- EVENT_OBJECT_FACTORYic = 1087,
- EVENT_OBJECT_FACTORYwi = 1088,
- EVENT_OBJECT_FACTORYti = 1089,
- EVENT_OBJECT_FACTORYfi = 1090,
- EVENT_OBJECT_FACTORYii = 1091,
- EVENT_OBJECT_FACTORYws = 1092,
- EVENT_OBJECT_FACTORYts = 1093,
- EVENT_OBJECT_FACTORYfs = 1094,
- EVENT_OBJECT_FACTORYis = 1095,
- EVENT_OBJECT_FACTORYrt = 1096,
- EVENT_OBJECT_FACTORYrc = 1097,
- EVENT_OBJECT_FACTORYrr = 1098,
- EVENT_OBJECT_FACTORYrs = 1099,
- EVENT_OBJECT_FACTORYsa = 1100,
- EVENT_OBJECT_SEARCH = 1200,
- EVENT_OBJECT_TERRAFORM = 1201,
- EVENT_OBJECT_FIRE = 1202,
- EVENT_OBJECT_FIREANT = 1203,
- EVENT_OBJECT_RECOVER = 1220,
- EVENT_OBJECT_BEGSHIELD = 1221,
- EVENT_OBJECT_ENDSHIELD = 1222,
- EVENT_OBJECT_RTANK = 1223,
- EVENT_OBJECT_RFLY = 1224,
- EVENT_OBJECT_RTHUMP = 1225,
- EVENT_OBJECT_RCANON = 1226,
- EVENT_OBJECT_RTOWER = 1227,
- EVENT_OBJECT_RPHAZER = 1228,
- EVENT_OBJECT_RSHIELD = 1229,
- EVENT_OBJECT_RATOMIC = 1230,
- EVENT_OBJECT_RiPAW = 1231,
- EVENT_OBJECT_RiGUN = 1232,
- EVENT_OBJECT_RESET = 1233,
- EVENT_OBJECT_DIMSHIELD = 1234,
- EVENT_OBJECT_TARGET = 1235,
- EVENT_OBJECT_PROGLIST = 1310,
- EVENT_OBJECT_PROGRUN = 1311,
- EVENT_OBJECT_PROGEDIT = 1312,
- EVENT_OBJECT_PROGSTART = 1313,
- EVENT_OBJECT_PROGSTOP = 1314,
- EVENT_OBJECT_INFOOK = 1340,
- EVENT_OBJECT_DELETE = 1350,
- EVENT_OBJECT_GENERGY = 1360,
- EVENT_OBJECT_GSHIELD = 1361,
- EVENT_OBJECT_GRANGE = 1362,
- EVENT_OBJECT_COMPASS = 1363,
- EVENT_OBJECT_MAP = 1364,
- EVENT_OBJECT_MAPZOOM = 1365,
- EVENT_OBJECT_GPROGRESS = 1366,
- EVENT_OBJECT_GRADAR = 1367,
- EVENT_OBJECT_GINFO = 1368,
- EVENT_OBJECT_TYPE = 1369,
- EVENT_OBJECT_CROSSHAIR = 1370,
- EVENT_OBJECT_CORNERul = 1371,
- EVENT_OBJECT_CORNERur = 1372,
- EVENT_OBJECT_CORNERdl = 1373,
- EVENT_OBJECT_CORNERdr = 1374,
- EVENT_OBJECT_MAPi = 1375,
- EVENT_OBJECT_MAPg = 1376,
- EVENT_OBJECT_CAMERA = 1400,
- EVENT_OBJECT_HELP = 1401,
- EVENT_OBJECT_SOLUCE = 1402,
- EVENT_OBJECT_CAMERAleft = 1403,
- EVENT_OBJECT_CAMERAright= 1404,
- EVENT_OBJECT_CAMERAnear = 1405,
- EVENT_OBJECT_CAMERAaway = 1406,
- EVENT_OBJECT_SHORTCUT00 = 1500,
- EVENT_OBJECT_SHORTCUT01 = 1501,
- EVENT_OBJECT_SHORTCUT02 = 1502,
- EVENT_OBJECT_SHORTCUT03 = 1503,
- EVENT_OBJECT_SHORTCUT04 = 1504,
- EVENT_OBJECT_SHORTCUT05 = 1505,
- EVENT_OBJECT_SHORTCUT06 = 1506,
- EVENT_OBJECT_SHORTCUT07 = 1507,
- EVENT_OBJECT_SHORTCUT08 = 1508,
- EVENT_OBJECT_SHORTCUT09 = 1509,
- EVENT_OBJECT_SHORTCUT10 = 1510,
- EVENT_OBJECT_SHORTCUT11 = 1511,
- EVENT_OBJECT_SHORTCUT12 = 1512,
- EVENT_OBJECT_SHORTCUT13 = 1513,
- EVENT_OBJECT_SHORTCUT14 = 1514,
- EVENT_OBJECT_SHORTCUT15 = 1515,
- EVENT_OBJECT_SHORTCUT16 = 1516,
- EVENT_OBJECT_SHORTCUT17 = 1517,
- EVENT_OBJECT_SHORTCUT18 = 1518,
- EVENT_OBJECT_SHORTCUT19 = 1519,
- EVENT_OBJECT_MOVIELOCK = 1550,
- EVENT_OBJECT_EDITLOCK = 1551,
- EVENT_OBJECT_LIMIT = 1560,
-
- EVENT_OBJECT_PEN0 = 1570,
- EVENT_OBJECT_PEN1 = 1571,
- EVENT_OBJECT_PEN2 = 1572,
- EVENT_OBJECT_PEN3 = 1573,
- EVENT_OBJECT_PEN4 = 1574,
- EVENT_OBJECT_PEN5 = 1575,
- EVENT_OBJECT_PEN6 = 1576,
- EVENT_OBJECT_PEN7 = 1577,
- EVENT_OBJECT_PEN8 = 1578,
- EVENT_OBJECT_REC = 1580,
- EVENT_OBJECT_STOP = 1581,
-
- EVENT_STUDIO_OK = 2000,
- EVENT_STUDIO_CANCEL = 2001,
- EVENT_STUDIO_EDIT = 2002,
- EVENT_STUDIO_LIST = 2003,
- EVENT_STUDIO_NEW = 2010,
- EVENT_STUDIO_OPEN = 2011,
- EVENT_STUDIO_SAVE = 2012,
- EVENT_STUDIO_UNDO = 2013,
- EVENT_STUDIO_CUT = 2014,
- EVENT_STUDIO_COPY = 2015,
- EVENT_STUDIO_PASTE = 2016,
- EVENT_STUDIO_SIZE = 2017,
- EVENT_STUDIO_TOOL = 2018,
- EVENT_STUDIO_HELP = 2019,
- EVENT_STUDIO_COMPILE = 2050,
- EVENT_STUDIO_RUN = 2051,
- EVENT_STUDIO_REALTIME = 2052,
- EVENT_STUDIO_STEP = 2053,
-
- EVENT_USER = 10000,
- EVENT_FORCE_DWORD = 0x7fffffff
-};
-
-struct Event
-{
- EventMsg event; // event (EVENT *)
- long param; // parameter
- Math::Point pos; // mouse position (0 .. 1)
- float axeX; // control the X axis (-1 .. 1)
- float axeY; // control of the Y axis (-1 .. 1)
- float axeZ; // control the Z axis (-1 .. 1)
- short keyState; // state of the keyboard (KS_ *)
- float rTime; // relative time
-
- Event();
-};
-
-
-const int VK_BUTTON1 = (0x100+1); // joystick button 1
-const int VK_BUTTON2 = (0x100+2); // joystick button 2
-const int VK_BUTTON3 = (0x100+3); // joystick button 3
-const int VK_BUTTON4 = (0x100+4); // joystick button 4
-const int VK_BUTTON5 = (0x100+5); // joystick button 5
-const int VK_BUTTON6 = (0x100+6); // joystick button 6
-const int VK_BUTTON7 = (0x100+7); // joystick button 7
-const int VK_BUTTON8 = (0x100+8); // joystick button 8
-const int VK_BUTTON9 = (0x100+9); // joystick button 9
-const int VK_BUTTON10 = (0x100+10); // joystick button 10
-const int VK_BUTTON11 = (0x100+11); // joystick button 11
-const int VK_BUTTON12 = (0x100+12); // joystick button 12
-const int VK_BUTTON13 = (0x100+13); // joystick button 13
-const int VK_BUTTON14 = (0x100+14); // joystick button 14
-const int VK_BUTTON15 = (0x100+15); // joystick button 15
-const int VK_BUTTON16 = (0x100+16); // joystick button 16
-const int VK_BUTTON17 = (0x100+17); // joystick button 17
-const int VK_BUTTON18 = (0x100+18); // joystick button 18
-const int VK_BUTTON19 = (0x100+19); // joystick button 19
-const int VK_BUTTON20 = (0x100+20); // joystick button 20
-const int VK_BUTTON21 = (0x100+21); // joystick button 21
-const int VK_BUTTON22 = (0x100+22); // joystick button 22
-const int VK_BUTTON23 = (0x100+23); // joystick button 23
-const int VK_BUTTON24 = (0x100+24); // joystick button 24
-const int VK_BUTTON25 = (0x100+25); // joystick button 25
-const int VK_BUTTON26 = (0x100+26); // joystick button 26
-const int VK_BUTTON27 = (0x100+27); // joystick button 27
-const int VK_BUTTON28 = (0x100+28); // joystick button 28
-const int VK_BUTTON29 = (0x100+29); // joystick button 29
-const int VK_BUTTON30 = (0x100+30); // joystick button 30
-const int VK_BUTTON31 = (0x100+31); // joystick button 31
-const int VK_BUTTON32 = (0x100+32); // joystick button 32
-
-const int VK_WHEELUP = (0x200+1); // Mousewheel up
-const int VK_WHEELDOWN = (0x200+2); // Mousewheel down
-
-
-enum KeyRank
-{
- KEYRANK_LEFT = 0,
- KEYRANK_RIGHT = 1,
- KEYRANK_UP = 2,
- KEYRANK_DOWN = 3,
- KEYRANK_GUP = 4,
- KEYRANK_GDOWN = 5,
- KEYRANK_CAMERA = 6,
- KEYRANK_DESEL = 7,
- KEYRANK_ACTION = 8,
- KEYRANK_NEAR = 9,
- KEYRANK_AWAY = 10,
- KEYRANK_NEXT = 11,
- KEYRANK_HUMAN = 12,
- KEYRANK_QUIT = 13,
- KEYRANK_HELP = 14,
- KEYRANK_PROG = 15,
- KEYRANK_VISIT = 16,
- KEYRANK_SPEED10 = 17,
- KEYRANK_SPEED15 = 18,
- KEYRANK_SPEED20 = 19,
- KEYRANK_SPEED30 = 20,
- KEYRANK_AIMUP = 21,
- KEYRANK_AIMDOWN = 22,
- KEYRANK_CBOT = 23,
-};
-
-
-
-class CEvent
-{
-public:
- CEvent(CInstanceManager* iMan);
- ~CEvent();
-
- void Flush();
- void MakeEvent(Event &event, EventMsg msg);
- bool AddEvent(const Event &event);
- bool GetEvent(Event &event);
-
-protected:
- CInstanceManager* m_iMan;
-
- Event m_fifo[MAXEVENT];
- int m_head;
- int m_tail;
- int m_total;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// event.h
+
+#pragma once
+
+
+#include "math/point.h"
+
+
+#if !defined (WM_XBUTTONDOWN)
+#define WM_XBUTTONDOWN 0x020B
+#define WM_XBUTTONUP 0x020C
+#define XBUTTON1 0x0001
+#define XBUTTON2 0x0002
+#endif
+
+
+
+class CInstanceManager;
+
+
+const int MAXEVENT = 100;
+
+// Events.
+
+enum EventMsg
+{
+ EVENT_NULL = 0,
+
+ EVENT_QUIT = 1,
+ EVENT_FRAME = 2,
+ EVENT_LBUTTONDOWN = 3,
+ EVENT_RBUTTONDOWN = 4,
+ EVENT_LBUTTONUP = 5,
+ EVENT_RBUTTONUP = 6,
+ EVENT_MOUSEMOVE = 7,
+ EVENT_KEYDOWN = 8,
+ EVENT_KEYUP = 9,
+ EVENT_CHAR = 10,
+ EVENT_FOCUS = 11,
+
+ EVENT_UPDINTERFACE = 20,
+ EVENT_WIN = 30,
+ EVENT_LOST = 31,
+
+ EVENT_BUTTON_OK = 40,
+ EVENT_BUTTON_CANCEL = 41,
+ EVENT_BUTTON_NEXT = 42,
+ EVENT_BUTTON_PREV = 43,
+ EVENT_BUTTON_QUIT = 44,
+
+ EVENT_BUTTON0 = 50,
+ EVENT_BUTTON1 = 51,
+ EVENT_BUTTON2 = 52,
+ EVENT_BUTTON3 = 53,
+ EVENT_BUTTON4 = 54,
+ EVENT_BUTTON5 = 55,
+ EVENT_BUTTON6 = 56,
+ EVENT_BUTTON7 = 57,
+ EVENT_BUTTON8 = 58,
+ EVENT_BUTTON9 = 59,
+ EVENT_BUTTON10 = 60,
+ EVENT_BUTTON11 = 61,
+ EVENT_BUTTON12 = 62,
+ EVENT_BUTTON13 = 63,
+ EVENT_BUTTON14 = 64,
+ EVENT_BUTTON15 = 65,
+ EVENT_BUTTON16 = 66,
+ EVENT_BUTTON17 = 67,
+ EVENT_BUTTON18 = 68,
+ EVENT_BUTTON19 = 69,
+
+ EVENT_EDIT0 = 70,
+ EVENT_EDIT1 = 71,
+ EVENT_EDIT2 = 72,
+ EVENT_EDIT3 = 73,
+ EVENT_EDIT4 = 74,
+ EVENT_EDIT5 = 75,
+ EVENT_EDIT6 = 76,
+ EVENT_EDIT7 = 77,
+ EVENT_EDIT8 = 78,
+ EVENT_EDIT9 = 79,
+
+ EVENT_WINDOW0 = 80, // the bottom panel
+ EVENT_WINDOW1 = 81, // map
+ EVENT_WINDOW2 = 82, // CDisplayText
+ EVENT_WINDOW3 = 83, // CStudio
+ EVENT_WINDOW4 = 84, // DisplayInfo
+ EVENT_WINDOW5 = 85, // setup
+ EVENT_WINDOW6 = 86,
+ EVENT_WINDOW7 = 87,
+ EVENT_WINDOW8 = 88,
+ EVENT_WINDOW9 = 89, // dialogue
+
+ EVENT_LABEL0 = 90,
+ EVENT_LABEL1 = 91,
+ EVENT_LABEL2 = 92,
+ EVENT_LABEL3 = 93,
+ EVENT_LABEL4 = 94,
+ EVENT_LABEL5 = 95,
+ EVENT_LABEL6 = 96,
+ EVENT_LABEL7 = 97,
+ EVENT_LABEL8 = 98,
+ EVENT_LABEL9 = 99,
+ EVENT_LABEL10 = 100,
+ EVENT_LABEL11 = 101,
+ EVENT_LABEL12 = 102,
+ EVENT_LABEL13 = 103,
+ EVENT_LABEL14 = 104,
+ EVENT_LABEL15 = 105,
+ EVENT_LABEL16 = 106,
+ EVENT_LABEL17 = 107,
+ EVENT_LABEL18 = 108,
+ EVENT_LABEL19 = 109,
+
+ EVENT_LIST0 = 110,
+ EVENT_LIST1 = 111,
+ EVENT_LIST2 = 112,
+ EVENT_LIST3 = 113,
+ EVENT_LIST4 = 114,
+ EVENT_LIST5 = 115,
+ EVENT_LIST6 = 116,
+ EVENT_LIST7 = 117,
+ EVENT_LIST8 = 118,
+ EVENT_LIST9 = 119,
+
+ EVENT_TOOLTIP = 200,
+
+ EVENT_DIALOG_OK = 300,
+ EVENT_DIALOG_CANCEL = 301,
+ EVENT_DIALOG_LABEL = 302,
+ EVENT_DIALOG_LABEL1 = 303,
+ EVENT_DIALOG_LABEL2 = 304,
+ EVENT_DIALOG_LABEL3 = 305,
+ EVENT_DIALOG_LIST = 306,
+ EVENT_DIALOG_EDIT = 307,
+ EVENT_DIALOG_CHECK1 = 308,
+ EVENT_DIALOG_CHECK2 = 309,
+
+ EVENT_INTERFACE_TRAINER = 400,
+ EVENT_INTERFACE_DEFI = 401,
+ EVENT_INTERFACE_MISSION = 402,
+ EVENT_INTERFACE_FREE = 403,
+ EVENT_INTERFACE_PROTO = 404,
+ EVENT_INTERFACE_NAME = 405,
+ EVENT_INTERFACE_SETUP = 406,
+ EVENT_INTERFACE_QUIT = 407,
+ EVENT_INTERFACE_BACK = 408,
+ EVENT_INTERFACE_AGAIN = 409,
+ EVENT_INTERFACE_WRITE = 410,
+ EVENT_INTERFACE_READ = 411,
+ EVENT_INTERFACE_ABORT = 412,
+ EVENT_INTERFACE_USER = 413,
+ EVENT_INTERFACE_TEEN = 414,
+
+ EVENT_INTERFACE_CHAP = 420,
+ EVENT_INTERFACE_LIST = 421,
+ EVENT_INTERFACE_RESUME = 422,
+ EVENT_INTERFACE_PLAY = 423,
+
+ EVENT_INTERFACE_SETUPd = 430,
+ EVENT_INTERFACE_SETUPg = 431,
+ EVENT_INTERFACE_SETUPp = 432,
+ EVENT_INTERFACE_SETUPc = 433,
+ EVENT_INTERFACE_SETUPs = 434,
+
+ EVENT_INTERFACE_DEVICE = 440,
+ EVENT_INTERFACE_RESOL = 441,
+ EVENT_INTERFACE_FULL = 442,
+ EVENT_INTERFACE_APPLY = 443,
+
+ EVENT_INTERFACE_TOTO = 450,
+ EVENT_INTERFACE_SHADOW = 451,
+ EVENT_INTERFACE_DIRTY = 452,
+ EVENT_INTERFACE_LENS = 453,
+ EVENT_INTERFACE_SKY = 454,
+ EVENT_INTERFACE_PLANET = 456,
+ EVENT_INTERFACE_LIGHT = 457,
+ EVENT_INTERFACE_PARTI = 458,
+ EVENT_INTERFACE_CLIP = 459,
+ EVENT_INTERFACE_DETAIL = 460,
+ EVENT_INTERFACE_TEXTURE = 461,
+ EVENT_INTERFACE_RAIN = 462,
+ EVENT_INTERFACE_GLINT = 463,
+ EVENT_INTERFACE_TOOLTIP = 464,
+ EVENT_INTERFACE_MOVIES = 465,
+ EVENT_INTERFACE_NICERST = 466,
+ EVENT_INTERFACE_SCROLL = 467,
+ EVENT_INTERFACE_INVERTX = 468,
+ EVENT_INTERFACE_INVERTY = 469,
+ EVENT_INTERFACE_EFFECT = 470,
+ EVENT_INTERFACE_MOUSE = 471,
+ EVENT_INTERFACE_GROUND = 472,
+ EVENT_INTERFACE_GADGET = 473,
+ EVENT_INTERFACE_FOG = 474,
+ EVENT_INTERFACE_HIMSELF = 475,
+ EVENT_INTERFACE_EDITMODE= 476,
+ EVENT_INTERFACE_EDITVALUE= 477,
+ EVENT_INTERFACE_SOLUCE4 = 478,
+
+ EVENT_INTERFACE_KINFO1 = 500,
+ EVENT_INTERFACE_KINFO2 = 501,
+ EVENT_INTERFACE_KGROUP = 502,
+ EVENT_INTERFACE_KSCROLL = 503,
+ EVENT_INTERFACE_KDEF = 504,
+ EVENT_INTERFACE_KLEFT = 505,
+ EVENT_INTERFACE_KRIGHT = 506,
+ EVENT_INTERFACE_KUP = 507,
+ EVENT_INTERFACE_KDOWN = 508,
+ EVENT_INTERFACE_KGUP = 509,
+ EVENT_INTERFACE_KGDOWN = 510,
+ EVENT_INTERFACE_KCAMERA = 511,
+ EVENT_INTERFACE_KDESEL = 512,
+ EVENT_INTERFACE_KACTION = 513,
+ EVENT_INTERFACE_KNEAR = 514,
+ EVENT_INTERFACE_KAWAY = 515,
+ EVENT_INTERFACE_KNEXT = 516,
+ EVENT_INTERFACE_KHUMAN = 517,
+ EVENT_INTERFACE_KQUIT = 518,
+ EVENT_INTERFACE_KHELP = 519,
+ EVENT_INTERFACE_KPROG = 520,
+ EVENT_INTERFACE_KCBOT = 521,
+ EVENT_INTERFACE_KVISIT = 522,
+ EVENT_INTERFACE_KSPEED10= 523,
+ EVENT_INTERFACE_KSPEED15= 524,
+ EVENT_INTERFACE_KSPEED20= 525,
+ EVENT_INTERFACE_KSPEED30= 526,
+
+ EVENT_INTERFACE_VOLSOUND= 530,
+ EVENT_INTERFACE_VOLMUSIC= 531,
+ EVENT_INTERFACE_SOUND3D = 532,
+
+ EVENT_INTERFACE_MIN = 540,
+ EVENT_INTERFACE_NORM = 541,
+ EVENT_INTERFACE_MAX = 542,
+
+ EVENT_INTERFACE_SILENT = 550,
+ EVENT_INTERFACE_NOISY = 551,
+
+ EVENT_INTERFACE_JOYSTICK= 560,
+ EVENT_INTERFACE_SOLUCE = 561,
+
+ EVENT_INTERFACE_GLINTl = 570,
+ EVENT_INTERFACE_GLINTr = 571,
+ EVENT_INTERFACE_GLINTu = 572,
+ EVENT_INTERFACE_GLINTb = 573,
+
+ EVENT_INTERFACE_NEDIT = 580,
+ EVENT_INTERFACE_NLIST = 581,
+ EVENT_INTERFACE_NOK = 582,
+ EVENT_INTERFACE_NCANCEL = 583,
+ EVENT_INTERFACE_NDELETE = 584,
+ EVENT_INTERFACE_NLABEL = 585,
+
+ EVENT_INTERFACE_IOWRITE = 600,
+ EVENT_INTERFACE_IOREAD = 601,
+ EVENT_INTERFACE_IOLIST = 602,
+ EVENT_INTERFACE_IONAME = 603,
+ EVENT_INTERFACE_IOLABEL = 604,
+ EVENT_INTERFACE_IOIMAGE = 605,
+ EVENT_INTERFACE_IODELETE= 606,
+
+ EVENT_INTERFACE_PERSO = 620,
+ EVENT_INTERFACE_POK = 621,
+ EVENT_INTERFACE_PCANCEL = 622,
+ EVENT_INTERFACE_PDEF = 623,
+ EVENT_INTERFACE_PHEAD = 624,
+ EVENT_INTERFACE_PBODY = 625,
+ EVENT_INTERFACE_PLROT = 626,
+ EVENT_INTERFACE_PRROT = 627,
+ EVENT_INTERFACE_PC0a = 640,
+ EVENT_INTERFACE_PC1a = 641,
+ EVENT_INTERFACE_PC2a = 642,
+ EVENT_INTERFACE_PC3a = 643,
+ EVENT_INTERFACE_PC4a = 644,
+ EVENT_INTERFACE_PC5a = 645,
+ EVENT_INTERFACE_PC6a = 646,
+ EVENT_INTERFACE_PC7a = 647,
+ EVENT_INTERFACE_PC8a = 648,
+ EVENT_INTERFACE_PC9a = 649,
+ EVENT_INTERFACE_PCRa = 650,
+ EVENT_INTERFACE_PCGa = 651,
+ EVENT_INTERFACE_PCBa = 652,
+ EVENT_INTERFACE_PC0b = 660,
+ EVENT_INTERFACE_PC1b = 661,
+ EVENT_INTERFACE_PC2b = 662,
+ EVENT_INTERFACE_PC3b = 663,
+ EVENT_INTERFACE_PC4b = 664,
+ EVENT_INTERFACE_PC5b = 665,
+ EVENT_INTERFACE_PC6b = 666,
+ EVENT_INTERFACE_PC7b = 667,
+ EVENT_INTERFACE_PC8b = 668,
+ EVENT_INTERFACE_PC9b = 669,
+ EVENT_INTERFACE_PCRb = 670,
+ EVENT_INTERFACE_PCGb = 671,
+ EVENT_INTERFACE_PCBb = 672,
+ EVENT_INTERFACE_PFACE1 = 680,
+ EVENT_INTERFACE_PFACE2 = 681,
+ EVENT_INTERFACE_PFACE3 = 682,
+ EVENT_INTERFACE_PFACE4 = 683,
+ EVENT_INTERFACE_PGLASS0 = 690,
+ EVENT_INTERFACE_PGLASS1 = 691,
+ EVENT_INTERFACE_PGLASS2 = 692,
+ EVENT_INTERFACE_PGLASS3 = 693,
+ EVENT_INTERFACE_PGLASS4 = 694,
+ EVENT_INTERFACE_PGLASS5 = 695,
+ EVENT_INTERFACE_PGLASS6 = 696,
+ EVENT_INTERFACE_PGLASS7 = 697,
+ EVENT_INTERFACE_PGLASS8 = 698,
+ EVENT_INTERFACE_PGLASS9 = 699,
+
+ EVENT_DT_GROUP0 = 700,
+ EVENT_DT_GROUP1 = 701,
+ EVENT_DT_GROUP2 = 702,
+ EVENT_DT_GROUP3 = 703,
+ EVENT_DT_GROUP4 = 704,
+ EVENT_DT_LABEL0 = 710,
+ EVENT_DT_LABEL1 = 711,
+ EVENT_DT_LABEL2 = 712,
+ EVENT_DT_LABEL3 = 713,
+ EVENT_DT_LABEL4 = 714,
+ EVENT_DT_VISIT0 = 720,
+ EVENT_DT_VISIT1 = 721,
+ EVENT_DT_VISIT2 = 722,
+ EVENT_DT_VISIT3 = 723,
+ EVENT_DT_VISIT4 = 724,
+ EVENT_DT_END = 725,
+
+ EVENT_CMD = 800,
+ EVENT_SPEED = 801,
+
+ EVENT_HYPER_PREV = 900,
+ EVENT_HYPER_NEXT = 901,
+ EVENT_HYPER_HOME = 902,
+ EVENT_HYPER_COPY = 903,
+ EVENT_HYPER_SIZE1 = 904,
+ EVENT_HYPER_SIZE2 = 905,
+ EVENT_HYPER_SIZE3 = 906,
+ EVENT_HYPER_SIZE4 = 907,
+ EVENT_HYPER_SIZE5 = 908,
+
+ EVENT_SATCOM_HUSTON = 920,
+ EVENT_SATCOM_SAT = 921,
+ EVENT_SATCOM_LOADING = 922,
+ EVENT_SATCOM_OBJECT = 923,
+ EVENT_SATCOM_PROG = 924,
+ EVENT_SATCOM_SOLUCE = 925,
+
+ EVENT_OBJECT_DESELECT = 1000,
+ EVENT_OBJECT_LEFT = 1001,
+ EVENT_OBJECT_RIGHT = 1002,
+ EVENT_OBJECT_UP = 1003,
+ EVENT_OBJECT_DOWN = 1004,
+ EVENT_OBJECT_GASUP = 1005,
+ EVENT_OBJECT_GASDOWN = 1006,
+ EVENT_OBJECT_HTAKE = 1020,
+ EVENT_OBJECT_MTAKE = 1021,
+ EVENT_OBJECT_MFRONT = 1022,
+ EVENT_OBJECT_MBACK = 1023,
+ EVENT_OBJECT_MPOWER = 1024,
+ EVENT_OBJECT_BHELP = 1040,
+ EVENT_OBJECT_BTAKEOFF = 1041,
+ EVENT_OBJECT_BDERRICK = 1050,
+ EVENT_OBJECT_BSTATION = 1051,
+ EVENT_OBJECT_BFACTORY = 1052,
+ EVENT_OBJECT_BCONVERT = 1053,
+ EVENT_OBJECT_BTOWER = 1054,
+ EVENT_OBJECT_BREPAIR = 1055,
+ EVENT_OBJECT_BRESEARCH = 1056,
+ EVENT_OBJECT_BRADAR = 1057,
+ EVENT_OBJECT_BENERGY = 1058,
+ EVENT_OBJECT_BLABO = 1059,
+ EVENT_OBJECT_BNUCLEAR = 1060,
+ EVENT_OBJECT_BPARA = 1061,
+ EVENT_OBJECT_BINFO = 1062,
+ EVENT_OBJECT_BXXXX = 1063,
+ EVENT_OBJECT_GFLAT = 1070,
+ EVENT_OBJECT_FCREATE = 1071,
+ EVENT_OBJECT_FDELETE = 1072,
+ EVENT_OBJECT_FCOLORb = 1073,
+ EVENT_OBJECT_FCOLORr = 1074,
+ EVENT_OBJECT_FCOLORg = 1075,
+ EVENT_OBJECT_FCOLORy = 1076,
+ EVENT_OBJECT_FCOLORv = 1077,
+ EVENT_OBJECT_FACTORYwa = 1080,
+ EVENT_OBJECT_FACTORYta = 1081,
+ EVENT_OBJECT_FACTORYfa = 1082,
+ EVENT_OBJECT_FACTORYia = 1083,
+ EVENT_OBJECT_FACTORYwc = 1084,
+ EVENT_OBJECT_FACTORYtc = 1085,
+ EVENT_OBJECT_FACTORYfc = 1086,
+ EVENT_OBJECT_FACTORYic = 1087,
+ EVENT_OBJECT_FACTORYwi = 1088,
+ EVENT_OBJECT_FACTORYti = 1089,
+ EVENT_OBJECT_FACTORYfi = 1090,
+ EVENT_OBJECT_FACTORYii = 1091,
+ EVENT_OBJECT_FACTORYws = 1092,
+ EVENT_OBJECT_FACTORYts = 1093,
+ EVENT_OBJECT_FACTORYfs = 1094,
+ EVENT_OBJECT_FACTORYis = 1095,
+ EVENT_OBJECT_FACTORYrt = 1096,
+ EVENT_OBJECT_FACTORYrc = 1097,
+ EVENT_OBJECT_FACTORYrr = 1098,
+ EVENT_OBJECT_FACTORYrs = 1099,
+ EVENT_OBJECT_FACTORYsa = 1100,
+ EVENT_OBJECT_SEARCH = 1200,
+ EVENT_OBJECT_TERRAFORM = 1201,
+ EVENT_OBJECT_FIRE = 1202,
+ EVENT_OBJECT_FIREANT = 1203,
+ EVENT_OBJECT_RECOVER = 1220,
+ EVENT_OBJECT_BEGSHIELD = 1221,
+ EVENT_OBJECT_ENDSHIELD = 1222,
+ EVENT_OBJECT_RTANK = 1223,
+ EVENT_OBJECT_RFLY = 1224,
+ EVENT_OBJECT_RTHUMP = 1225,
+ EVENT_OBJECT_RCANON = 1226,
+ EVENT_OBJECT_RTOWER = 1227,
+ EVENT_OBJECT_RPHAZER = 1228,
+ EVENT_OBJECT_RSHIELD = 1229,
+ EVENT_OBJECT_RATOMIC = 1230,
+ EVENT_OBJECT_RiPAW = 1231,
+ EVENT_OBJECT_RiGUN = 1232,
+ EVENT_OBJECT_RESET = 1233,
+ EVENT_OBJECT_DIMSHIELD = 1234,
+ EVENT_OBJECT_TARGET = 1235,
+ EVENT_OBJECT_PROGLIST = 1310,
+ EVENT_OBJECT_PROGRUN = 1311,
+ EVENT_OBJECT_PROGEDIT = 1312,
+ EVENT_OBJECT_PROGSTART = 1313,
+ EVENT_OBJECT_PROGSTOP = 1314,
+ EVENT_OBJECT_INFOOK = 1340,
+ EVENT_OBJECT_DELETE = 1350,
+ EVENT_OBJECT_GENERGY = 1360,
+ EVENT_OBJECT_GSHIELD = 1361,
+ EVENT_OBJECT_GRANGE = 1362,
+ EVENT_OBJECT_COMPASS = 1363,
+ EVENT_OBJECT_MAP = 1364,
+ EVENT_OBJECT_MAPZOOM = 1365,
+ EVENT_OBJECT_GPROGRESS = 1366,
+ EVENT_OBJECT_GRADAR = 1367,
+ EVENT_OBJECT_GINFO = 1368,
+ EVENT_OBJECT_TYPE = 1369,
+ EVENT_OBJECT_CROSSHAIR = 1370,
+ EVENT_OBJECT_CORNERul = 1371,
+ EVENT_OBJECT_CORNERur = 1372,
+ EVENT_OBJECT_CORNERdl = 1373,
+ EVENT_OBJECT_CORNERdr = 1374,
+ EVENT_OBJECT_MAPi = 1375,
+ EVENT_OBJECT_MAPg = 1376,
+ EVENT_OBJECT_CAMERA = 1400,
+ EVENT_OBJECT_HELP = 1401,
+ EVENT_OBJECT_SOLUCE = 1402,
+ EVENT_OBJECT_CAMERAleft = 1403,
+ EVENT_OBJECT_CAMERAright= 1404,
+ EVENT_OBJECT_CAMERAnear = 1405,
+ EVENT_OBJECT_CAMERAaway = 1406,
+ EVENT_OBJECT_SHORTCUT00 = 1500,
+ EVENT_OBJECT_SHORTCUT01 = 1501,
+ EVENT_OBJECT_SHORTCUT02 = 1502,
+ EVENT_OBJECT_SHORTCUT03 = 1503,
+ EVENT_OBJECT_SHORTCUT04 = 1504,
+ EVENT_OBJECT_SHORTCUT05 = 1505,
+ EVENT_OBJECT_SHORTCUT06 = 1506,
+ EVENT_OBJECT_SHORTCUT07 = 1507,
+ EVENT_OBJECT_SHORTCUT08 = 1508,
+ EVENT_OBJECT_SHORTCUT09 = 1509,
+ EVENT_OBJECT_SHORTCUT10 = 1510,
+ EVENT_OBJECT_SHORTCUT11 = 1511,
+ EVENT_OBJECT_SHORTCUT12 = 1512,
+ EVENT_OBJECT_SHORTCUT13 = 1513,
+ EVENT_OBJECT_SHORTCUT14 = 1514,
+ EVENT_OBJECT_SHORTCUT15 = 1515,
+ EVENT_OBJECT_SHORTCUT16 = 1516,
+ EVENT_OBJECT_SHORTCUT17 = 1517,
+ EVENT_OBJECT_SHORTCUT18 = 1518,
+ EVENT_OBJECT_SHORTCUT19 = 1519,
+ EVENT_OBJECT_MOVIELOCK = 1550,
+ EVENT_OBJECT_EDITLOCK = 1551,
+ EVENT_OBJECT_LIMIT = 1560,
+
+ EVENT_OBJECT_PEN0 = 1570,
+ EVENT_OBJECT_PEN1 = 1571,
+ EVENT_OBJECT_PEN2 = 1572,
+ EVENT_OBJECT_PEN3 = 1573,
+ EVENT_OBJECT_PEN4 = 1574,
+ EVENT_OBJECT_PEN5 = 1575,
+ EVENT_OBJECT_PEN6 = 1576,
+ EVENT_OBJECT_PEN7 = 1577,
+ EVENT_OBJECT_PEN8 = 1578,
+ EVENT_OBJECT_REC = 1580,
+ EVENT_OBJECT_STOP = 1581,
+
+ EVENT_STUDIO_OK = 2000,
+ EVENT_STUDIO_CANCEL = 2001,
+ EVENT_STUDIO_EDIT = 2002,
+ EVENT_STUDIO_LIST = 2003,
+ EVENT_STUDIO_NEW = 2010,
+ EVENT_STUDIO_OPEN = 2011,
+ EVENT_STUDIO_SAVE = 2012,
+ EVENT_STUDIO_UNDO = 2013,
+ EVENT_STUDIO_CUT = 2014,
+ EVENT_STUDIO_COPY = 2015,
+ EVENT_STUDIO_PASTE = 2016,
+ EVENT_STUDIO_SIZE = 2017,
+ EVENT_STUDIO_TOOL = 2018,
+ EVENT_STUDIO_HELP = 2019,
+ EVENT_STUDIO_COMPILE = 2050,
+ EVENT_STUDIO_RUN = 2051,
+ EVENT_STUDIO_REALTIME = 2052,
+ EVENT_STUDIO_STEP = 2053,
+
+ EVENT_USER = 10000,
+ EVENT_FORCE_DWORD = 0x7fffffff
+};
+
+struct Event
+{
+ EventMsg event; // event (EVENT *)
+ long param; // parameter
+ Math::Point pos; // mouse position (0 .. 1)
+ float axeX; // control the X axis (-1 .. 1)
+ float axeY; // control of the Y axis (-1 .. 1)
+ float axeZ; // control the Z axis (-1 .. 1)
+ short keyState; // state of the keyboard (KS_ *)
+ float rTime; // relative time
+
+ Event();
+};
+
+
+const int VK_BUTTON1 = (0x100+1); // joystick button 1
+const int VK_BUTTON2 = (0x100+2); // joystick button 2
+const int VK_BUTTON3 = (0x100+3); // joystick button 3
+const int VK_BUTTON4 = (0x100+4); // joystick button 4
+const int VK_BUTTON5 = (0x100+5); // joystick button 5
+const int VK_BUTTON6 = (0x100+6); // joystick button 6
+const int VK_BUTTON7 = (0x100+7); // joystick button 7
+const int VK_BUTTON8 = (0x100+8); // joystick button 8
+const int VK_BUTTON9 = (0x100+9); // joystick button 9
+const int VK_BUTTON10 = (0x100+10); // joystick button 10
+const int VK_BUTTON11 = (0x100+11); // joystick button 11
+const int VK_BUTTON12 = (0x100+12); // joystick button 12
+const int VK_BUTTON13 = (0x100+13); // joystick button 13
+const int VK_BUTTON14 = (0x100+14); // joystick button 14
+const int VK_BUTTON15 = (0x100+15); // joystick button 15
+const int VK_BUTTON16 = (0x100+16); // joystick button 16
+const int VK_BUTTON17 = (0x100+17); // joystick button 17
+const int VK_BUTTON18 = (0x100+18); // joystick button 18
+const int VK_BUTTON19 = (0x100+19); // joystick button 19
+const int VK_BUTTON20 = (0x100+20); // joystick button 20
+const int VK_BUTTON21 = (0x100+21); // joystick button 21
+const int VK_BUTTON22 = (0x100+22); // joystick button 22
+const int VK_BUTTON23 = (0x100+23); // joystick button 23
+const int VK_BUTTON24 = (0x100+24); // joystick button 24
+const int VK_BUTTON25 = (0x100+25); // joystick button 25
+const int VK_BUTTON26 = (0x100+26); // joystick button 26
+const int VK_BUTTON27 = (0x100+27); // joystick button 27
+const int VK_BUTTON28 = (0x100+28); // joystick button 28
+const int VK_BUTTON29 = (0x100+29); // joystick button 29
+const int VK_BUTTON30 = (0x100+30); // joystick button 30
+const int VK_BUTTON31 = (0x100+31); // joystick button 31
+const int VK_BUTTON32 = (0x100+32); // joystick button 32
+
+const int VK_WHEELUP = (0x200+1); // Mousewheel up
+const int VK_WHEELDOWN = (0x200+2); // Mousewheel down
+
+
+enum KeyRank
+{
+ KEYRANK_LEFT = 0,
+ KEYRANK_RIGHT = 1,
+ KEYRANK_UP = 2,
+ KEYRANK_DOWN = 3,
+ KEYRANK_GUP = 4,
+ KEYRANK_GDOWN = 5,
+ KEYRANK_CAMERA = 6,
+ KEYRANK_DESEL = 7,
+ KEYRANK_ACTION = 8,
+ KEYRANK_NEAR = 9,
+ KEYRANK_AWAY = 10,
+ KEYRANK_NEXT = 11,
+ KEYRANK_HUMAN = 12,
+ KEYRANK_QUIT = 13,
+ KEYRANK_HELP = 14,
+ KEYRANK_PROG = 15,
+ KEYRANK_VISIT = 16,
+ KEYRANK_SPEED10 = 17,
+ KEYRANK_SPEED15 = 18,
+ KEYRANK_SPEED20 = 19,
+ KEYRANK_SPEED30 = 20,
+ KEYRANK_AIMUP = 21,
+ KEYRANK_AIMDOWN = 22,
+ KEYRANK_CBOT = 23,
+};
+
+
+
+class CEvent
+{
+public:
+ CEvent(CInstanceManager* iMan);
+ ~CEvent();
+
+ void Flush();
+ void MakeEvent(Event &event, EventMsg msg);
+ bool AddEvent(const Event &event);
+ bool GetEvent(Event &event);
+
+protected:
+ CInstanceManager* m_iMan;
+
+ Event m_fifo[MAXEVENT];
+ int m_head;
+ int m_tail;
+ int m_total;
+};
+
+
diff --git a/src/common/global.h b/src/common/global.h
index 0429cc1..670c578 100644
--- a/src/common/global.h
+++ b/src/common/global.h
@@ -1,66 +1,66 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// global.h
-
-#pragma once
-
-
-enum BuildType
-{
- BUILD_FACTORY = (1<<0), // factory
- BUILD_DERRICK = (1<<1), // derrick
- BUILD_CONVERT = (1<<2), // converter
- BUILD_RADAR = (1<<3), // radar
- BUILD_ENERGY = (1<<4), // factory of cells
- BUILD_NUCLEAR = (1<<5), // nuclear power plant
- BUILD_STATION = (1<<6), // base station
- BUILD_REPAIR = (1<<7), // repair center
- BUILD_TOWER = (1<<8), // defense tower
- BUILD_RESEARCH = (1<<9), // research center
- BUILD_LABO = (1<<10), // laboratory
- BUILD_PARA = (1<<11), // lightning protection
- BUILD_INFO = (1<<12), // information terminal
- BUILD_GFLAT = (1<<16), // flat floor
- BUILD_FLAG = (1<<17) // puts / removes colored flag
-};
-
-
-// Do not change values ​​was because of backups (bits = ...).
-enum ResearchType
-{
- RESEARCH_TANK = (1<<0), // caterpillars
- RESEARCH_FLY = (1<<1), // wings
- RESEARCH_CANON = (1<<2), // cannon
- RESEARCH_TOWER = (1<<3), // defense tower
- RESEARCH_ATOMIC = (1<<4), // nuclear
- RESEARCH_THUMP = (1<<5), // thumper
- RESEARCH_SHIELD = (1<<6), // shield
- RESEARCH_PHAZER = (1<<7), // phazer gun
- RESEARCH_iPAW = (1<<8), // legs of insects
- RESEARCH_iGUN = (1<<9), // cannon of insects
- RESEARCH_RECYCLER = (1<<10), // recycler
- RESEARCH_SUBM = (1<<11), // submarine
- RESEARCH_SNIFFER = (1<<12) // sniffer
-};
-
-extern long g_id; // unique identifier
-extern long g_build; // constructible buildings
-extern long g_researchDone; // research done
-extern long g_researchEnable; // research available
-extern float g_unit; // conversion factor
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// global.h
+
+#pragma once
+
+
+enum BuildType
+{
+ BUILD_FACTORY = (1<<0), // factory
+ BUILD_DERRICK = (1<<1), // derrick
+ BUILD_CONVERT = (1<<2), // converter
+ BUILD_RADAR = (1<<3), // radar
+ BUILD_ENERGY = (1<<4), // factory of cells
+ BUILD_NUCLEAR = (1<<5), // nuclear power plant
+ BUILD_STATION = (1<<6), // base station
+ BUILD_REPAIR = (1<<7), // repair center
+ BUILD_TOWER = (1<<8), // defense tower
+ BUILD_RESEARCH = (1<<9), // research center
+ BUILD_LABO = (1<<10), // laboratory
+ BUILD_PARA = (1<<11), // lightning protection
+ BUILD_INFO = (1<<12), // information terminal
+ BUILD_GFLAT = (1<<16), // flat floor
+ BUILD_FLAG = (1<<17) // puts / removes colored flag
+};
+
+
+// Do not change values ​​was because of backups (bits = ...).
+enum ResearchType
+{
+ RESEARCH_TANK = (1<<0), // caterpillars
+ RESEARCH_FLY = (1<<1), // wings
+ RESEARCH_CANON = (1<<2), // cannon
+ RESEARCH_TOWER = (1<<3), // defense tower
+ RESEARCH_ATOMIC = (1<<4), // nuclear
+ RESEARCH_THUMP = (1<<5), // thumper
+ RESEARCH_SHIELD = (1<<6), // shield
+ RESEARCH_PHAZER = (1<<7), // phazer gun
+ RESEARCH_iPAW = (1<<8), // legs of insects
+ RESEARCH_iGUN = (1<<9), // cannon of insects
+ RESEARCH_RECYCLER = (1<<10), // recycler
+ RESEARCH_SUBM = (1<<11), // submarine
+ RESEARCH_SNIFFER = (1<<12) // sniffer
+};
+
+extern long g_id; // unique identifier
+extern long g_build; // constructible buildings
+extern long g_researchDone; // research done
+extern long g_researchEnable; // research available
+extern float g_unit; // conversion factor
+
+
diff --git a/src/common/iman.cpp b/src/common/iman.cpp
index 53735a4..28ee3d3 100644
--- a/src/common/iman.cpp
+++ b/src/common/iman.cpp
@@ -1,162 +1,162 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// iman.cpp
-
-
-#include <stdio.h>
-
-#include "common/struct.h"
-#include "common/iman.h"
-
-
-
-
-// Object's constructor.
-
-CInstanceManager::CInstanceManager()
-{
- int i;
-
- for ( i=0 ; i<CLASS_MAX ; i++ )
- {
- m_table[i].totalPossible = 0;
- m_table[i].totalUsed = 0;
- m_table[i].classPointer = 0;
- }
-}
-
-// Object's destructor.
-
-CInstanceManager::~CInstanceManager()
-{
- int i;
-
- for ( i=0 ; i<CLASS_MAX ; i++ )
- {
- if ( m_table[i].classPointer != 0 )
- {
- free(m_table[i].classPointer);
- }
- }
-}
-
-
-// Empty the list of all classes.
-
-void CInstanceManager::Flush()
-{
- int i;
-
- for ( i=0 ; i<CLASS_MAX ; i++ )
- {
- if ( m_table[i].classPointer != 0 )
- {
- free(m_table[i].classPointer);
- }
- m_table[i].classPointer = 0;
- }
-}
-
-// Empty all instances of a given class.
-
-void CInstanceManager::Flush(ClassType classType)
-{
- if ( classType < 0 || classType >= CLASS_MAX ) return;
- if ( m_table[classType].classPointer == 0 ) return;
-
- free(m_table[classType].classPointer);
- m_table[classType].classPointer = 0;
-}
-
-
-// Adds a new instance of a class.
-
-bool CInstanceManager::AddInstance(ClassType classType, void* pointer, int max)
-{
- int i;
-
- if ( classType < 0 || classType >= CLASS_MAX ) return false;
-
- if ( m_table[classType].classPointer == 0 )
- {
- m_table[classType].classPointer = (void**)malloc(max*sizeof(void*));
- m_table[classType].totalPossible = max;
- m_table[classType].totalUsed = 0;
- }
-
- if ( m_table[classType].totalUsed >= m_table[classType].totalPossible ) return false;
-
- i = m_table[classType].totalUsed++;
- m_table[classType].classPointer[i] = pointer;
- return true;
-}
-
-// Deletes an instance of a class.
-
-bool CInstanceManager::DeleteInstance(ClassType classType, void* pointer)
-{
- int i;
-
- if ( classType < 0 || classType >= CLASS_MAX ) return false;
-
- for ( i=0 ; i<m_table[classType].totalUsed ; i++ )
- {
- if ( m_table[classType].classPointer[i] == pointer )
- {
- m_table[classType].classPointer[i] = 0;
- }
- }
-
- Compress(classType);
- return true;
-}
-
-// Seeking an existing instance. Returns 0 if it does not exist.
-// Must be super fast!
-
-void* CInstanceManager::SearchInstance(ClassType classType, int rank)
-{
-#if _DEBUG
- if ( classType < 0 || classType >= CLASS_MAX ) return 0;
- if ( m_table[classType].classPointer == 0 ) return 0;
-#endif
- if ( rank >= m_table[classType].totalUsed ) return 0;
-
- return m_table[classType].classPointer[rank];
-}
-
-
-// Fills holes in a table.
-
-void CInstanceManager::Compress(ClassType classType)
-{
- int i, j;
-
- if ( classType < 0 || classType >= CLASS_MAX ) return;
-
- j = 0;
- for ( i=0 ; i<m_table[classType].totalUsed ; i++ )
- {
- if ( m_table[classType].classPointer[i] != 0 )
- {
- m_table[classType].classPointer[j++] = m_table[classType].classPointer[i];
- }
- }
- m_table[classType].totalUsed = j;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// iman.cpp
+
+
+#include <stdio.h>
+
+#include "common/struct.h"
+#include "common/iman.h"
+
+
+
+
+// Object's constructor.
+
+CInstanceManager::CInstanceManager()
+{
+ int i;
+
+ for ( i=0 ; i<CLASS_MAX ; i++ )
+ {
+ m_table[i].totalPossible = 0;
+ m_table[i].totalUsed = 0;
+ m_table[i].classPointer = 0;
+ }
+}
+
+// Object's destructor.
+
+CInstanceManager::~CInstanceManager()
+{
+ int i;
+
+ for ( i=0 ; i<CLASS_MAX ; i++ )
+ {
+ if ( m_table[i].classPointer != 0 )
+ {
+ free(m_table[i].classPointer);
+ }
+ }
+}
+
+
+// Empty the list of all classes.
+
+void CInstanceManager::Flush()
+{
+ int i;
+
+ for ( i=0 ; i<CLASS_MAX ; i++ )
+ {
+ if ( m_table[i].classPointer != 0 )
+ {
+ free(m_table[i].classPointer);
+ }
+ m_table[i].classPointer = 0;
+ }
+}
+
+// Empty all instances of a given class.
+
+void CInstanceManager::Flush(ClassType classType)
+{
+ if ( classType < 0 || classType >= CLASS_MAX ) return;
+ if ( m_table[classType].classPointer == 0 ) return;
+
+ free(m_table[classType].classPointer);
+ m_table[classType].classPointer = 0;
+}
+
+
+// Adds a new instance of a class.
+
+bool CInstanceManager::AddInstance(ClassType classType, void* pointer, int max)
+{
+ int i;
+
+ if ( classType < 0 || classType >= CLASS_MAX ) return false;
+
+ if ( m_table[classType].classPointer == 0 )
+ {
+ m_table[classType].classPointer = (void**)malloc(max*sizeof(void*));
+ m_table[classType].totalPossible = max;
+ m_table[classType].totalUsed = 0;
+ }
+
+ if ( m_table[classType].totalUsed >= m_table[classType].totalPossible ) return false;
+
+ i = m_table[classType].totalUsed++;
+ m_table[classType].classPointer[i] = pointer;
+ return true;
+}
+
+// Deletes an instance of a class.
+
+bool CInstanceManager::DeleteInstance(ClassType classType, void* pointer)
+{
+ int i;
+
+ if ( classType < 0 || classType >= CLASS_MAX ) return false;
+
+ for ( i=0 ; i<m_table[classType].totalUsed ; i++ )
+ {
+ if ( m_table[classType].classPointer[i] == pointer )
+ {
+ m_table[classType].classPointer[i] = 0;
+ }
+ }
+
+ Compress(classType);
+ return true;
+}
+
+// Seeking an existing instance. Returns 0 if it does not exist.
+// Must be super fast!
+
+void* CInstanceManager::SearchInstance(ClassType classType, int rank)
+{
+#if _DEBUG
+ if ( classType < 0 || classType >= CLASS_MAX ) return 0;
+ if ( m_table[classType].classPointer == 0 ) return 0;
+#endif
+ if ( rank >= m_table[classType].totalUsed ) return 0;
+
+ return m_table[classType].classPointer[rank];
+}
+
+
+// Fills holes in a table.
+
+void CInstanceManager::Compress(ClassType classType)
+{
+ int i, j;
+
+ if ( classType < 0 || classType >= CLASS_MAX ) return;
+
+ j = 0;
+ for ( i=0 ; i<m_table[classType].totalUsed ; i++ )
+ {
+ if ( m_table[classType].classPointer[i] != 0 )
+ {
+ m_table[classType].classPointer[j++] = m_table[classType].classPointer[i];
+ }
+ }
+ m_table[classType].totalUsed = j;
+}
+
+
diff --git a/src/common/iman.h b/src/common/iman.h
index 738a8c2..7a7b499 100644
--- a/src/common/iman.h
+++ b/src/common/iman.h
@@ -1,55 +1,55 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// iman.h
-
-#pragma once
-
-
-#include "common/misc.h"
-
-
-
-struct BaseClass
-{
- int totalPossible;
- int totalUsed;
- void** classPointer;
-};
-
-
-
-class CInstanceManager
-{
-public:
- CInstanceManager();
- ~CInstanceManager();
-
- void Flush();
- void Flush(ClassType classType);
- bool AddInstance(ClassType classType, void* pointer, int max=1);
- bool DeleteInstance(ClassType classType, void* pointer);
- void* SearchInstance(ClassType classType, int rank=0);
-
-
-protected:
- void Compress(ClassType classType);
-
-protected:
- BaseClass m_table[CLASS_MAX];
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// iman.h
+
+#pragma once
+
+
+#include "common/misc.h"
+
+
+
+struct BaseClass
+{
+ int totalPossible;
+ int totalUsed;
+ void** classPointer;
+};
+
+
+
+class CInstanceManager
+{
+public:
+ CInstanceManager();
+ ~CInstanceManager();
+
+ void Flush();
+ void Flush(ClassType classType);
+ bool AddInstance(ClassType classType, void* pointer, int max=1);
+ bool DeleteInstance(ClassType classType, void* pointer);
+ void* SearchInstance(ClassType classType, int rank=0);
+
+
+protected:
+ void Compress(ClassType classType);
+
+protected:
+ BaseClass m_table[CLASS_MAX];
+};
+
+
diff --git a/src/common/language.h b/src/common/language.h
index 33c7465..51b80f4 100644
--- a/src/common/language.h
+++ b/src/common/language.h
@@ -1,54 +1,54 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// language.h
-
-#pragma once
-
-
-#define _FULL true // CoLoBoT
-#define _SCHOOL false // CeeBot-A or Teen
- #define _TEEN false // false for CeeBot-A, true for CeeBot-Teen
- #define _EDU false
- #define _PERSO false
- #define _CEEBOTDEMO false
-#define _NET false
-#define _DEMO false // DEMO only CoLoBoT (with _Full = false)!
-
-#define _FRENCH true
-#define _ENGLISH false
-#define _GERMAN false
-#define _WG false
-#define _POLISH false
-
-#define _NEWLOOK false // false for CoLoBoT, true for all CeeBot
-#define _SOUNDTRACKS false // always false since InitAudioTrackVolume crop in Vista
-
-
-// Verifications
-
-#if !_FULL & !_SCHOOL & !_NET & !_DEMO
--> no version chosen!
-#endif
-
-#if _SCHOOL
-#if !_EDU & !_PERSO & !_CEEBOTDEMO
--> EDU or PERSO or CEEBOTDEMO?
-#endif
-#if _EDU & _PERSO & _CEEBOTDEMO
--> EDU and PERSO and CEEBOTDEMO not at the same time!!!
-#endif
-#endif
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// language.h
+
+#pragma once
+
+
+#define _FULL true // CoLoBoT
+#define _SCHOOL false // CeeBot-A or Teen
+ #define _TEEN false // false for CeeBot-A, true for CeeBot-Teen
+ #define _EDU false
+ #define _PERSO false
+ #define _CEEBOTDEMO false
+#define _NET false
+#define _DEMO false // DEMO only CoLoBoT (with _Full = false)!
+
+#define _FRENCH true
+#define _ENGLISH false
+#define _GERMAN false
+#define _WG false
+#define _POLISH false
+
+#define _NEWLOOK false // false for CoLoBoT, true for all CeeBot
+#define _SOUNDTRACKS false // always false since InitAudioTrackVolume crop in Vista
+
+
+// Verifications
+
+#if !_FULL & !_SCHOOL & !_NET & !_DEMO
+-> no version chosen!
+#endif
+
+#if _SCHOOL
+#if !_EDU & !_PERSO & !_CEEBOTDEMO
+-> EDU or PERSO or CEEBOTDEMO?
+#endif
+#if _EDU & _PERSO & _CEEBOTDEMO
+-> EDU and PERSO and CEEBOTDEMO not at the same time!!!
+#endif
+#endif
diff --git a/src/common/metafile.cpp b/src/common/metafile.cpp
index 7a67931..9d54f78 100644
--- a/src/common/metafile.cpp
+++ b/src/common/metafile.cpp
@@ -1,416 +1,416 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// metafile.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-
-#include "common/language.h"
-#include "common/metafile.h"
-
-
-
-
-#if _FULL | _NET
-static unsigned char table_codec[23] =
-{
- 0x85, 0x91, 0x73, 0xcf, 0xa2, 0xbb, 0xf4, 0x77,
- 0x58, 0x39, 0x37, 0xfd, 0x2a, 0xcc, 0x5f, 0x55,
- 0x96, 0x90, 0x07, 0xcd, 0x11, 0x88, 0x21,
-};
-
-void Codec(void* buffer, int len, int start)
-{
- unsigned char *b = (unsigned char*)buffer;
- int i;
-
- for ( i=0 ; i<len ; i++ )
- {
- b[i] ^= table_codec[(start++)%23];
- }
-}
-#endif
-
-#if _SCHOOL
-#if _CEEBOTDEMO
-static unsigned char table_codec[136] =
-{
- 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
- 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
- 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
- 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
- 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
- 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
- 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
- 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
- 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
- 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
- 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
- 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
- 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
- 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
- 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
- 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
- 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
-};
-
-void Codec(void* buffer, int len, int start)
-{
- unsigned char *b = (unsigned char*)buffer;
- int i;
-
- for ( i=0 ; i<len ; i++ )
- {
- b[i] ^= table_codec[(start++)%136];
- }
-}
-#else
-static unsigned char table_codec[29] =
-{
- 0x72, 0x91, 0x37, 0xdf, 0xa1, 0xcc, 0xf5, 0x67,
- 0x53, 0x40, 0xd3, 0xed, 0x3a, 0xbb, 0x5e, 0x43,
- 0x67, 0x9a, 0x0c, 0xed, 0x33, 0x77, 0x2f, 0xf2,
- 0xe3, 0x42, 0x11, 0x5e, 0xc2,
-};
-
-void Codec(void* buffer, int len, int start)
-{
- unsigned char *b = (unsigned char*)buffer;
- int i;
-
- for ( i=0 ; i<len ; i++ )
- {
- b[i] ^= table_codec[(start++)%29];
- }
-}
-#endif
-#endif
-
-#if _DEMO
-static unsigned char table_codec[27] =
-{
- 0x85, 0x91, 0x77, 0xcf, 0xa3, 0xbb, 0xf4, 0x77,
- 0x58, 0x39, 0x37, 0xfd, 0x2a, 0xcc, 0x7f, 0x55,
- 0x96, 0x80, 0x07, 0xcd, 0x11, 0x88, 0x21, 0x44,
- 0x17, 0xee, 0xf0,
-};
-
-void Codec(void* buffer, int len, int start)
-{
- unsigned char *b = (unsigned char*)buffer;
- int i;
-
- for ( i=0 ; i<len ; i++ )
- {
- b[i] ^= table_codec[(start++)%27];
- }
-}
-#endif
-
-
-
-// Object's constructor.
-
-CMetaFile::CMetaFile()
-{
- int i;
-
- for ( i=0 ; i<METAMAX ; i++ )
- {
- m_list[i].stream = 0;
- m_list[i].headers = 0;
- }
-
- m_bMeta = false;
- m_bOpen = false;
- m_start = 0;
- m_pos = 0;
- m_len = 0;
- m_stream = 0;
-}
-
-// Object's destructor.
-
-CMetaFile::~CMetaFile()
-{
- MetaClose();
-}
-
-
-// Test if a file exists.
-
-bool CMetaFile::IsExist(char *metaname, char *filename)
-{
- FILE* file;
- int index, i;
-
- if ( metaname[0] == 0 )
- {
- file = fopen(filename, "rb");
- if ( file == NULL ) return false;
- fclose(file);
- return true;
- }
- else
- {
- index = MetaOpen(metaname);
- if ( index == -1 ) return 1;
-
- for ( i=0 ; i<m_list[index].total ; i++ )
- {
- if ( strcmp(m_list[index].headers[i].name, filename) == 0 )
- {
- return true;
- }
- }
- return false;
- }
-}
-
-// Opens a file. If metaname is empty, it normally opens a file.
-
-int CMetaFile::Open(char *metaname, char *filename)
-{
- int index, i;
-
- if ( m_bOpen ) // file already open?
- {
- Close();
- }
-
- if ( metaname[0] == 0 )
- {
- m_stream = fopen(filename, "rb");
- if ( m_stream == 0 ) return 1;
- m_bOpen = true;
- m_bMeta = false;
- return 0;
- }
- else
- {
- index = MetaOpen(metaname);
- if ( index == -1 ) return 1;
-
- for ( i=0 ; i<m_list[index].total ; i++ )
- {
- if ( strcmp(m_list[index].headers[i].name, filename) == 0 )
- {
- m_stream = m_list[index].stream;
- m_start = m_list[index].headers[i].start;
- m_len = m_list[index].headers[i].len;
- m_bOpen = true;
- m_bMeta = true;
- Seek(0);
- return 0;
- }
- }
- return 1;
- }
-}
-
-// Returns the length of a file.
-
-int CMetaFile::RetLength()
-{
- int len;
-
- if ( !m_bOpen ) return 0;
-
- if ( m_bMeta )
- {
- len = m_len;
- }
- else
- {
- fseek(m_stream, 0, SEEK_END);
- len = ftell(m_stream);
- fseek(m_stream, 0, SEEK_SET);
- }
- return len;
-}
-
-// Positioning in the file, relative to the beginning.
-
-int CMetaFile::Seek(int offset)
-{
- if ( !m_bOpen ) return 1;
-
- if ( m_bMeta )
- {
- m_pos = m_start+offset;
- return fseek(m_stream, m_start+offset, SEEK_SET);
- }
- else
- {
- return fseek(m_stream, offset, SEEK_SET);
- }
-}
-
-// Reads bytes number.
-
-int CMetaFile::Read(void *buffer, int size)
-{
- int err;
-
- if ( !m_bOpen ) return 1;
-
- if ( m_bMeta )
- {
- err = fread(buffer, size, 1, m_stream);
- Codec(buffer, size, m_pos);
- m_pos += size;
- return err;
- }
- else
- {
- return fread(buffer, size, 1, m_stream);
- }
-}
-
-// Reads a byte.
-
-int CMetaFile::GetByte()
-{
- BYTE b;
-
- if ( !m_bOpen ) return 1;
-
- b = getc(m_stream);
- if ( m_bMeta )
- {
- Codec(&b, 1, m_pos);
- m_pos += 1;
- }
- return b;
-}
-
-// Reads 2 bytes.
-
-int CMetaFile::GetWord()
-{
- WORD w;
-
- if ( !m_bOpen ) return 1;
-
- w = getc(m_stream);
- if ( m_bMeta )
- {
- Codec(&w, 2, m_pos);
- m_pos += 2;
- }
- return w;
-}
-
-// Closes the file.
-
-int CMetaFile::Close()
-{
- if ( !m_bOpen ) return 1;
-
- if ( !m_bMeta )
- {
- fclose(m_stream);
- }
- m_bOpen = false;
- m_stream = 0;
-
- return 0;
-}
-
-
-// Opens a metafile. Returns the index or -1.
-
-int CMetaFile::MetaOpen(char *metaname)
-{
- int i, j, offset;
-
- i = MetaSearch(metaname);
- if ( i != -1 ) return i;
-
- for ( i=0 ; i<METAMAX ; i++ )
- {
- if ( m_list[i].stream == 0 )
- {
- m_list[i].stream = fopen(metaname, "rb");
- if ( m_list[i].stream == 0 ) return -1;
-
- strcpy(m_list[i].name, metaname); // memorized the name
-
- fread(&m_list[i].total, sizeof(int), 1, m_list[i].stream);
- m_list[i].headers = (MetaHeader*)malloc(sizeof(MetaHeader)*m_list[i].total);
-
- offset = 4;
- for ( j=0 ; j<m_list[i].total ; j++ )
- {
- fread(&m_list[i].headers[j], sizeof(MetaHeader), 1, m_list[i].stream);
- Codec(&m_list[i].headers[j], sizeof(MetaHeader), offset);
- offset += sizeof(MetaHeader);
- }
- return i;
- }
- }
-
- return -1;
-}
-
-// Seeks if the metafile is already open. Returns the index or -1.
-
-int CMetaFile::MetaSearch(char *metaname)
-{
- int i;
-
- for ( i=0 ; i<METAMAX ; i++ )
- {
- if ( m_list[i].stream != 0 )
- {
- if ( strcmp(m_list[i].name, metaname) == 0 ) return i;
- }
- }
-
- return -1;
-}
-
-// Closes all metafiles.
-
-int CMetaFile::MetaClose()
-{
- int i;
-
- if ( m_stream != 0 )
- {
- fclose(m_stream);
- m_stream = 0;
- }
-
- for ( i=0 ; i<METAMAX ; i++ )
- {
- if ( m_list[i].stream != 0 )
- {
- free(m_list[i].headers);
- m_list[i].headers = 0;
-
- fclose(m_list[i].stream);
- m_list[i].stream = 0;
- }
- }
-
- return 0;
-}
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// metafile.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+
+#include "common/language.h"
+#include "common/metafile.h"
+
+
+
+
+#if _FULL | _NET
+static unsigned char table_codec[23] =
+{
+ 0x85, 0x91, 0x73, 0xcf, 0xa2, 0xbb, 0xf4, 0x77,
+ 0x58, 0x39, 0x37, 0xfd, 0x2a, 0xcc, 0x5f, 0x55,
+ 0x96, 0x90, 0x07, 0xcd, 0x11, 0x88, 0x21,
+};
+
+void Codec(void* buffer, int len, int start)
+{
+ unsigned char *b = (unsigned char*)buffer;
+ int i;
+
+ for ( i=0 ; i<len ; i++ )
+ {
+ b[i] ^= table_codec[(start++)%23];
+ }
+}
+#endif
+
+#if _SCHOOL
+#if _CEEBOTDEMO
+static unsigned char table_codec[136] =
+{
+ 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
+ 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
+ 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
+ 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
+ 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
+ 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
+ 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+ 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+ 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+ 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+ 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+ 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+ 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+ 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+ 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+ 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+ 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+};
+
+void Codec(void* buffer, int len, int start)
+{
+ unsigned char *b = (unsigned char*)buffer;
+ int i;
+
+ for ( i=0 ; i<len ; i++ )
+ {
+ b[i] ^= table_codec[(start++)%136];
+ }
+}
+#else
+static unsigned char table_codec[29] =
+{
+ 0x72, 0x91, 0x37, 0xdf, 0xa1, 0xcc, 0xf5, 0x67,
+ 0x53, 0x40, 0xd3, 0xed, 0x3a, 0xbb, 0x5e, 0x43,
+ 0x67, 0x9a, 0x0c, 0xed, 0x33, 0x77, 0x2f, 0xf2,
+ 0xe3, 0x42, 0x11, 0x5e, 0xc2,
+};
+
+void Codec(void* buffer, int len, int start)
+{
+ unsigned char *b = (unsigned char*)buffer;
+ int i;
+
+ for ( i=0 ; i<len ; i++ )
+ {
+ b[i] ^= table_codec[(start++)%29];
+ }
+}
+#endif
+#endif
+
+#if _DEMO
+static unsigned char table_codec[27] =
+{
+ 0x85, 0x91, 0x77, 0xcf, 0xa3, 0xbb, 0xf4, 0x77,
+ 0x58, 0x39, 0x37, 0xfd, 0x2a, 0xcc, 0x7f, 0x55,
+ 0x96, 0x80, 0x07, 0xcd, 0x11, 0x88, 0x21, 0x44,
+ 0x17, 0xee, 0xf0,
+};
+
+void Codec(void* buffer, int len, int start)
+{
+ unsigned char *b = (unsigned char*)buffer;
+ int i;
+
+ for ( i=0 ; i<len ; i++ )
+ {
+ b[i] ^= table_codec[(start++)%27];
+ }
+}
+#endif
+
+
+
+// Object's constructor.
+
+CMetaFile::CMetaFile()
+{
+ int i;
+
+ for ( i=0 ; i<METAMAX ; i++ )
+ {
+ m_list[i].stream = 0;
+ m_list[i].headers = 0;
+ }
+
+ m_bMeta = false;
+ m_bOpen = false;
+ m_start = 0;
+ m_pos = 0;
+ m_len = 0;
+ m_stream = 0;
+}
+
+// Object's destructor.
+
+CMetaFile::~CMetaFile()
+{
+ MetaClose();
+}
+
+
+// Test if a file exists.
+
+bool CMetaFile::IsExist(char *metaname, char *filename)
+{
+ FILE* file;
+ int index, i;
+
+ if ( metaname[0] == 0 )
+ {
+ file = fopen(filename, "rb");
+ if ( file == NULL ) return false;
+ fclose(file);
+ return true;
+ }
+ else
+ {
+ index = MetaOpen(metaname);
+ if ( index == -1 ) return 1;
+
+ for ( i=0 ; i<m_list[index].total ; i++ )
+ {
+ if ( strcmp(m_list[index].headers[i].name, filename) == 0 )
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+// Opens a file. If metaname is empty, it normally opens a file.
+
+int CMetaFile::Open(char *metaname, char *filename)
+{
+ int index, i;
+
+ if ( m_bOpen ) // file already open?
+ {
+ Close();
+ }
+
+ if ( metaname[0] == 0 )
+ {
+ m_stream = fopen(filename, "rb");
+ if ( m_stream == 0 ) return 1;
+ m_bOpen = true;
+ m_bMeta = false;
+ return 0;
+ }
+ else
+ {
+ index = MetaOpen(metaname);
+ if ( index == -1 ) return 1;
+
+ for ( i=0 ; i<m_list[index].total ; i++ )
+ {
+ if ( strcmp(m_list[index].headers[i].name, filename) == 0 )
+ {
+ m_stream = m_list[index].stream;
+ m_start = m_list[index].headers[i].start;
+ m_len = m_list[index].headers[i].len;
+ m_bOpen = true;
+ m_bMeta = true;
+ Seek(0);
+ return 0;
+ }
+ }
+ return 1;
+ }
+}
+
+// Returns the length of a file.
+
+int CMetaFile::RetLength()
+{
+ int len;
+
+ if ( !m_bOpen ) return 0;
+
+ if ( m_bMeta )
+ {
+ len = m_len;
+ }
+ else
+ {
+ fseek(m_stream, 0, SEEK_END);
+ len = ftell(m_stream);
+ fseek(m_stream, 0, SEEK_SET);
+ }
+ return len;
+}
+
+// Positioning in the file, relative to the beginning.
+
+int CMetaFile::Seek(int offset)
+{
+ if ( !m_bOpen ) return 1;
+
+ if ( m_bMeta )
+ {
+ m_pos = m_start+offset;
+ return fseek(m_stream, m_start+offset, SEEK_SET);
+ }
+ else
+ {
+ return fseek(m_stream, offset, SEEK_SET);
+ }
+}
+
+// Reads bytes number.
+
+int CMetaFile::Read(void *buffer, int size)
+{
+ int err;
+
+ if ( !m_bOpen ) return 1;
+
+ if ( m_bMeta )
+ {
+ err = fread(buffer, size, 1, m_stream);
+ Codec(buffer, size, m_pos);
+ m_pos += size;
+ return err;
+ }
+ else
+ {
+ return fread(buffer, size, 1, m_stream);
+ }
+}
+
+// Reads a byte.
+
+int CMetaFile::GetByte()
+{
+ BYTE b;
+
+ if ( !m_bOpen ) return 1;
+
+ b = getc(m_stream);
+ if ( m_bMeta )
+ {
+ Codec(&b, 1, m_pos);
+ m_pos += 1;
+ }
+ return b;
+}
+
+// Reads 2 bytes.
+
+int CMetaFile::GetWord()
+{
+ WORD w;
+
+ if ( !m_bOpen ) return 1;
+
+ w = getc(m_stream);
+ if ( m_bMeta )
+ {
+ Codec(&w, 2, m_pos);
+ m_pos += 2;
+ }
+ return w;
+}
+
+// Closes the file.
+
+int CMetaFile::Close()
+{
+ if ( !m_bOpen ) return 1;
+
+ if ( !m_bMeta )
+ {
+ fclose(m_stream);
+ }
+ m_bOpen = false;
+ m_stream = 0;
+
+ return 0;
+}
+
+
+// Opens a metafile. Returns the index or -1.
+
+int CMetaFile::MetaOpen(char *metaname)
+{
+ int i, j, offset;
+
+ i = MetaSearch(metaname);
+ if ( i != -1 ) return i;
+
+ for ( i=0 ; i<METAMAX ; i++ )
+ {
+ if ( m_list[i].stream == 0 )
+ {
+ m_list[i].stream = fopen(metaname, "rb");
+ if ( m_list[i].stream == 0 ) return -1;
+
+ strcpy(m_list[i].name, metaname); // memorized the name
+
+ fread(&m_list[i].total, sizeof(int), 1, m_list[i].stream);
+ m_list[i].headers = (MetaHeader*)malloc(sizeof(MetaHeader)*m_list[i].total);
+
+ offset = 4;
+ for ( j=0 ; j<m_list[i].total ; j++ )
+ {
+ fread(&m_list[i].headers[j], sizeof(MetaHeader), 1, m_list[i].stream);
+ Codec(&m_list[i].headers[j], sizeof(MetaHeader), offset);
+ offset += sizeof(MetaHeader);
+ }
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+// Seeks if the metafile is already open. Returns the index or -1.
+
+int CMetaFile::MetaSearch(char *metaname)
+{
+ int i;
+
+ for ( i=0 ; i<METAMAX ; i++ )
+ {
+ if ( m_list[i].stream != 0 )
+ {
+ if ( strcmp(m_list[i].name, metaname) == 0 ) return i;
+ }
+ }
+
+ return -1;
+}
+
+// Closes all metafiles.
+
+int CMetaFile::MetaClose()
+{
+ int i;
+
+ if ( m_stream != 0 )
+ {
+ fclose(m_stream);
+ m_stream = 0;
+ }
+
+ for ( i=0 ; i<METAMAX ; i++ )
+ {
+ if ( m_list[i].stream != 0 )
+ {
+ free(m_list[i].headers);
+ m_list[i].headers = 0;
+
+ fclose(m_list[i].stream);
+ m_list[i].stream = 0;
+ }
+ }
+
+ return 0;
+}
+
+
+
diff --git a/src/common/metafile.h b/src/common/metafile.h
index 0fa1b51..afa4d31 100644
--- a/src/common/metafile.h
+++ b/src/common/metafile.h
@@ -1,74 +1,74 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// metafile.h
-
-#pragma once
-
-
-#include <stdio.h>
-
-
-const int METAMAX = 5;
-
-struct MetaHeader
-{
- char name[14]; // file name (8.3 max)
- int start; // position from the beginning of the metafile
- int len; // length of the file
-};
-
-struct MetaFile
-{
- char name[50]; // name of the metafile
- FILE* stream; // channel
- int total; // number of files
- MetaHeader* headers; // headers of files
-};
-
-
-
-class CMetaFile
-{
-public:
- CMetaFile();
- ~CMetaFile();
-
- bool IsExist(char *metaname, char *filename);
- int Open(char *metaname, char *filename);
- int RetLength();
- int Seek(int offset);
- int Read(void *buffer, int size);
- int GetByte();
- int GetWord();
- int Close();
- int MetaClose();
-
-protected:
- int MetaOpen(char *metaname);
- int MetaSearch(char *metaname);
-
-protected:
- MetaFile m_list[METAMAX]; // metafile open
- bool m_bOpen; // open file
- bool m_bMeta; // metafile open
- FILE* m_stream; // channel
- int m_start; // position from the beginning
- int m_pos; // current position
- int m_len; // length of the file
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// metafile.h
+
+#pragma once
+
+
+#include <stdio.h>
+
+
+const int METAMAX = 5;
+
+struct MetaHeader
+{
+ char name[14]; // file name (8.3 max)
+ int start; // position from the beginning of the metafile
+ int len; // length of the file
+};
+
+struct MetaFile
+{
+ char name[50]; // name of the metafile
+ FILE* stream; // channel
+ int total; // number of files
+ MetaHeader* headers; // headers of files
+};
+
+
+
+class CMetaFile
+{
+public:
+ CMetaFile();
+ ~CMetaFile();
+
+ bool IsExist(char *metaname, char *filename);
+ int Open(char *metaname, char *filename);
+ int RetLength();
+ int Seek(int offset);
+ int Read(void *buffer, int size);
+ int GetByte();
+ int GetWord();
+ int Close();
+ int MetaClose();
+
+protected:
+ int MetaOpen(char *metaname);
+ int MetaSearch(char *metaname);
+
+protected:
+ MetaFile m_list[METAMAX]; // metafile open
+ bool m_bOpen; // open file
+ bool m_bMeta; // metafile open
+ FILE* m_stream; // channel
+ int m_start; // position from the beginning
+ int m_pos; // current position
+ int m_len; // length of the file
+};
+
+
diff --git a/src/common/misc.cpp b/src/common/misc.cpp
index 65efe2d..2427356 100644
--- a/src/common/misc.cpp
+++ b/src/common/misc.cpp
@@ -1,441 +1,441 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// misc.cpp
-
-
-#include <math.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <direct.h>
-#include <time.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "old/d3dutil.h"
-#include "common/language.h"
-#include "common/event.h"
-#include "common/misc.h"
-
-
-
-CMetaFile g_metafile;
-
-static EventMsg g_uniqueEventMsg = EVENT_USER;
-static bool g_bUserDir = false;
-static char g_userDir[100] = "";
-
-
-
-// Gives a single user event.
-
-EventMsg GetUniqueEventMsg()
-{
- int i;
-
- i = (int)g_uniqueEventMsg+1;
- g_uniqueEventMsg = (EventMsg)i;
- return g_uniqueEventMsg;
-}
-
-
-
-// Returns a non-accented letter.
-
-char RetNoAccent(char letter)
-{
- if ( letter < 0 )
- {
- if ( letter == 'á' ||
- letter == 'à' ||
- letter == 'â' ||
- letter == 'ä' ||
- letter == 'ã' ) return 'a';
-
- if ( letter == 'é' ||
- letter == 'è' ||
- letter == 'ê' ||
- letter == 'ë' ) return 'e';
-
- if ( letter == 'í' ||
- letter == 'ì' ||
- letter == 'î' ||
- letter == 'ï' ) return 'i';
-
- if ( letter == 'ó' ||
- letter == 'ò' ||
- letter == 'ô' ||
- letter == 'ö' ||
- letter == 'õ' ) return 'o';
-
- if ( letter == 'ú' ||
- letter == 'ù' ||
- letter == 'û' ||
- letter == 'ü' ) return 'u';
-
- if ( letter == 'ç' ) return 'c';
-
- if ( letter == 'ñ' ) return 'n';
-
- if ( letter == 'Á' ||
- letter == 'À' ||
- letter == 'Â' ||
- letter == 'Ä' ||
- letter == 'Ã' ) return 'A';
-
- if ( letter == 'É' ||
- letter == 'È' ||
- letter == 'Ê' ||
- letter == 'Ë' ) return 'E';
-
- if ( letter == 'Í' ||
- letter == 'Ì' ||
- letter == 'Î' ||
- letter == 'Ï' ) return 'I';
-
- if ( letter == 'Ó' ||
- letter == 'Ò' ||
- letter == 'Ô' ||
- letter == 'Ö' ||
- letter == 'Õ' ) return 'O';
-
- if ( letter == 'Ú' ||
- letter == 'Ù' ||
- letter == 'Û' ||
- letter == 'Ü' ) return 'U';
-
- if ( letter == 'Ç' ) return 'C';
-
- if ( letter == 'Ñ' ) return 'N';
- }
-
- return letter;
-}
-
-// Returns an uppercase letter.
-
-char RetToUpper(char letter)
-{
- if ( letter < 0 )
- {
- if ( letter == 'á' ) return 'Á';
- if ( letter == 'à' ) return 'À';
- if ( letter == 'â' ) return 'Â';
- if ( letter == 'ä' ) return 'Ä';
- if ( letter == 'ã' ) return 'Ã';
-
- if ( letter == 'é' ) return 'É';
- if ( letter == 'è' ) return 'È';
- if ( letter == 'ê' ) return 'Ê';
- if ( letter == 'ë' ) return 'Ë';
-
- if ( letter == 'í' ) return 'Í';
- if ( letter == 'ì' ) return 'Ì';
- if ( letter == 'î' ) return 'Î';
- if ( letter == 'ï' ) return 'Ï';
-
- if ( letter == 'ó' ) return 'Ó';
- if ( letter == 'ò' ) return 'Ò';
- if ( letter == 'ô' ) return 'Ô';
- if ( letter == 'ö' ) return 'Ö';
- if ( letter == 'õ' ) return 'Õ';
-
- if ( letter == 'ú' ) return 'Ú';
- if ( letter == 'ù' ) return 'Ù';
- if ( letter == 'û' ) return 'Û';
- if ( letter == 'ü' ) return 'Ü';
-
- if ( letter == 'ç' ) return 'Ç';
-
- if ( letter == 'ñ' ) return 'Ñ';
- }
-
- return toupper(letter);
-}
-
-// Returns a lowercase letter.
-
-char RetToLower(char letter)
-{
- if ( letter < 0 )
- {
- if ( letter == 'Á' ) return 'á';
- if ( letter == 'À' ) return 'à';
- if ( letter == 'Â' ) return 'â';
- if ( letter == 'Ä' ) return 'ä';
- if ( letter == 'Ã' ) return 'ã';
-
- if ( letter == 'É' ) return 'é';
- if ( letter == 'È' ) return 'è';
- if ( letter == 'Ê' ) return 'ê';
- if ( letter == 'Ë' ) return 'ë';
-
- if ( letter == 'Í' ) return 'í';
- if ( letter == 'Ì' ) return 'ì';
- if ( letter == 'Î' ) return 'î';
- if ( letter == 'Ï' ) return 'ï';
-
- if ( letter == 'Ó' ) return 'ó';
- if ( letter == 'Ò' ) return 'ò';
- if ( letter == 'Ô' ) return 'ô';
- if ( letter == 'Ö' ) return 'ö';
- if ( letter == 'Õ' ) return 'õ';
-
- if ( letter == 'Ú' ) return 'ú';
- if ( letter == 'Ù' ) return 'ù';
- if ( letter == 'Û' ) return 'û';
- if ( letter == 'Ü' ) return 'ü';
-
- if ( letter == 'Ç' ) return 'ç';
-
- if ( letter == 'Ñ' ) return 'ñ';
- }
-
- return tolower(letter);
-}
-
-
-// Converting time to string.
-
-void TimeToAscii(time_t time, char *buffer)
-{
- struct tm when;
- int year;
-
- when = *localtime(&time);
- year = when.tm_year+1900;
- if ( year < 2000 ) year -= 1900;
- else year -= 2000;
-#if _FRENCH
- sprintf(buffer, "%.2d.%.2d.%.2d %.2d:%.2d",
- when.tm_mday, when.tm_mon+1, year,
- when.tm_hour, when.tm_min);
-#endif
-#if _GERMAN | _WG
- sprintf(buffer, "%.2d.%.2d.%.2d %.2d:%.2d",
- when.tm_mday, when.tm_mon+1, year,
- when.tm_hour, when.tm_min);
-#endif
-#if _ENGLISH
- char format[10];
- int hour;
-
- hour = when.tm_hour; // 0..23
- if ( hour < 12 ) // morning?
- {
- strcpy(format, "am");
- }
- else // afternoon?
- {
- strcpy(format, "pm");
- hour -= 12; // 0..11
- }
- if ( hour == 0 ) hour = 12;
-
- sprintf(buffer, "%.2d.%.2d.%.2d %.2d:%.2d %s",
- when.tm_mon+1, when.tm_mday, year,
- hour, when.tm_min, format);
-#endif
-#if _POLISH
- sprintf(buffer, "%.2d.%.2d.%.2d %.2d:%.2d",
- when.tm_mday, when.tm_mon+1, year,
- when.tm_hour, when.tm_min);
-#endif
-}
-
-
-// Makes a copy of a file.
-
-bool Xfer(char* src, char* dst)
-{
- FILE *fs, *fd;
- char *buffer;
- int len;
-
- fs = fopen(src, "rb");
- if ( fs == 0 )
- {
- return false;
- }
-
- fd = fopen(dst, "wb");
- if ( fd == 0 )
- {
- fclose(fs);
- return false;
- }
-
- buffer = (char*)malloc(10000);
-
- while ( true )
- {
- len = fread(buffer, 1, 10000, fs);
- if ( len == 0 ) break;
- fwrite(buffer, 1, len, fd);
- }
-
- free(buffer);
- fclose(fs);
- fclose(fd);
- return true;
-}
-
-// Copy a file into the temporary folder.
-
-bool CopyFileToTemp(char* filename)
-{
- char src[100];
- char dst[100];
- char save[100];
-
- UserDir(src, filename, "textures");
-
- strcpy(save, g_userDir);
- strcpy(g_userDir, "temp");
- UserDir(dst, filename, "textures");
- strcpy(g_userDir, save);
-
- _mkdir("temp");
- if ( !Xfer(src, dst) ) return false;
-
- strcpy(filename, dst);
- return true;
-}
-
-// Copy a list of numbered files into the temporary folder.
-
-bool CopyFileListToTemp(char* filename, int* list, int total)
-{
- char name[100];
- char ext[10];
- char file[100];
- char save[100];
- char* p;
- int i;
-
- strcpy(name, filename);
- p = strchr(name, '.');
- if ( p == 0 )
- {
- strcpy(ext, ".tga");
- }
- else
- {
- strcpy(ext, p);
- *p = 0;
- }
-
- for ( i=0 ; i<total ; i++ )
- {
- sprintf(file, "%s%.3d%s", name, list[i], ext); // nameNNN.ext
- CopyFileToTemp(file);
- }
-
- strcpy(save, g_userDir);
- strcpy(g_userDir, "temp");
- UserDir(file, filename, "textures");
- strcpy(filename, file);
- strcpy(g_userDir, save);
-
- return true;
-}
-
-
-// Adds an extension to file, if doesn't already one.
-
-void AddExt(char* filename, char* ext)
-{
- if ( strchr(filename, '.') != 0 ) return; // already an extension?
- strcat(filename, ext);
-}
-
-
-// Specifies the user folder.
-
-void UserDir(bool bUser, char* dir)
-{
- g_bUserDir = bUser;
- strcpy(g_userDir, dir);
-}
-
-// Replaces the string %user% by the user folder.
-// in: dir = "%user%toto.txt"
-// def = "abc\"
-// out: buffer = "abc\toto.txt"
-
-void UserDir(char* buffer, char* dir, char* def)
-{
- char ddir[100];
- char* add;
-
- if ( strstr(dir, "\\") == 0 && def[0] != 0 )
- {
- sprintf(ddir, "%s\\%s", def, dir);
- }
- else
- {
- strcpy(ddir, dir);
- }
- dir = ddir;
-
- while ( *dir != 0 )
- {
- if ( dir[0] == '%' &&
- dir[1] == 'u' &&
- dir[2] == 's' &&
- dir[3] == 'e' &&
- dir[4] == 'r' &&
- dir[5] == '%' ) // %user% ?
- {
- if ( g_bUserDir ) add = g_userDir;
- else add = def;
-
- while ( *add != 0 )
- {
- *buffer++ = *add++;
- }
- dir += 6; // jumps to %user%
- continue;
- }
-
- *buffer++ = *dir++;
- }
- *buffer = 0;
-}
-
-
-// Returns the letter corresponding to the language.
-
-char RetLanguageLetter()
-{
-#if _FRENCH
- return 'F';
-#endif
-#if _ENGLISH
- return 'E';
-#endif
-#if _GERMAN | _WG
- return 'D';
-#endif
-#if _POLISH
- return 'P';
-#endif
- return 'X';
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// misc.cpp
+
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <direct.h>
+#include <time.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "old/d3dutil.h"
+#include "common/language.h"
+#include "common/event.h"
+#include "common/misc.h"
+
+
+
+CMetaFile g_metafile;
+
+static EventMsg g_uniqueEventMsg = EVENT_USER;
+static bool g_bUserDir = false;
+static char g_userDir[100] = "";
+
+
+
+// Gives a single user event.
+
+EventMsg GetUniqueEventMsg()
+{
+ int i;
+
+ i = (int)g_uniqueEventMsg+1;
+ g_uniqueEventMsg = (EventMsg)i;
+ return g_uniqueEventMsg;
+}
+
+
+
+// Returns a non-accented letter.
+
+char RetNoAccent(char letter)
+{
+ if ( letter < 0 )
+ {
+ if ( letter == 'á' ||
+ letter == 'à' ||
+ letter == 'â' ||
+ letter == 'ä' ||
+ letter == 'ã' ) return 'a';
+
+ if ( letter == 'é' ||
+ letter == 'è' ||
+ letter == 'ê' ||
+ letter == 'ë' ) return 'e';
+
+ if ( letter == 'í' ||
+ letter == 'ì' ||
+ letter == 'î' ||
+ letter == 'ï' ) return 'i';
+
+ if ( letter == 'ó' ||
+ letter == 'ò' ||
+ letter == 'ô' ||
+ letter == 'ö' ||
+ letter == 'õ' ) return 'o';
+
+ if ( letter == 'ú' ||
+ letter == 'ù' ||
+ letter == 'û' ||
+ letter == 'ü' ) return 'u';
+
+ if ( letter == 'ç' ) return 'c';
+
+ if ( letter == 'ñ' ) return 'n';
+
+ if ( letter == 'Á' ||
+ letter == 'À' ||
+ letter == 'Â' ||
+ letter == 'Ä' ||
+ letter == 'Ã' ) return 'A';
+
+ if ( letter == 'É' ||
+ letter == 'È' ||
+ letter == 'Ê' ||
+ letter == 'Ë' ) return 'E';
+
+ if ( letter == 'Í' ||
+ letter == 'Ì' ||
+ letter == 'Î' ||
+ letter == 'Ï' ) return 'I';
+
+ if ( letter == 'Ó' ||
+ letter == 'Ò' ||
+ letter == 'Ô' ||
+ letter == 'Ö' ||
+ letter == 'Õ' ) return 'O';
+
+ if ( letter == 'Ú' ||
+ letter == 'Ù' ||
+ letter == 'Û' ||
+ letter == 'Ü' ) return 'U';
+
+ if ( letter == 'Ç' ) return 'C';
+
+ if ( letter == 'Ñ' ) return 'N';
+ }
+
+ return letter;
+}
+
+// Returns an uppercase letter.
+
+char RetToUpper(char letter)
+{
+ if ( letter < 0 )
+ {
+ if ( letter == 'á' ) return 'Á';
+ if ( letter == 'à' ) return 'À';
+ if ( letter == 'â' ) return 'Â';
+ if ( letter == 'ä' ) return 'Ä';
+ if ( letter == 'ã' ) return 'Ã';
+
+ if ( letter == 'é' ) return 'É';
+ if ( letter == 'è' ) return 'È';
+ if ( letter == 'ê' ) return 'Ê';
+ if ( letter == 'ë' ) return 'Ë';
+
+ if ( letter == 'í' ) return 'Í';
+ if ( letter == 'ì' ) return 'Ì';
+ if ( letter == 'î' ) return 'Î';
+ if ( letter == 'ï' ) return 'Ï';
+
+ if ( letter == 'ó' ) return 'Ó';
+ if ( letter == 'ò' ) return 'Ò';
+ if ( letter == 'ô' ) return 'Ô';
+ if ( letter == 'ö' ) return 'Ö';
+ if ( letter == 'õ' ) return 'Õ';
+
+ if ( letter == 'ú' ) return 'Ú';
+ if ( letter == 'ù' ) return 'Ù';
+ if ( letter == 'û' ) return 'Û';
+ if ( letter == 'ü' ) return 'Ü';
+
+ if ( letter == 'ç' ) return 'Ç';
+
+ if ( letter == 'ñ' ) return 'Ñ';
+ }
+
+ return toupper(letter);
+}
+
+// Returns a lowercase letter.
+
+char RetToLower(char letter)
+{
+ if ( letter < 0 )
+ {
+ if ( letter == 'Á' ) return 'á';
+ if ( letter == 'À' ) return 'à';
+ if ( letter == 'Â' ) return 'â';
+ if ( letter == 'Ä' ) return 'ä';
+ if ( letter == 'Ã' ) return 'ã';
+
+ if ( letter == 'É' ) return 'é';
+ if ( letter == 'È' ) return 'è';
+ if ( letter == 'Ê' ) return 'ê';
+ if ( letter == 'Ë' ) return 'ë';
+
+ if ( letter == 'Í' ) return 'í';
+ if ( letter == 'Ì' ) return 'ì';
+ if ( letter == 'Î' ) return 'î';
+ if ( letter == 'Ï' ) return 'ï';
+
+ if ( letter == 'Ó' ) return 'ó';
+ if ( letter == 'Ò' ) return 'ò';
+ if ( letter == 'Ô' ) return 'ô';
+ if ( letter == 'Ö' ) return 'ö';
+ if ( letter == 'Õ' ) return 'õ';
+
+ if ( letter == 'Ú' ) return 'ú';
+ if ( letter == 'Ù' ) return 'ù';
+ if ( letter == 'Û' ) return 'û';
+ if ( letter == 'Ü' ) return 'ü';
+
+ if ( letter == 'Ç' ) return 'ç';
+
+ if ( letter == 'Ñ' ) return 'ñ';
+ }
+
+ return tolower(letter);
+}
+
+
+// Converting time to string.
+
+void TimeToAscii(time_t time, char *buffer)
+{
+ struct tm when;
+ int year;
+
+ when = *localtime(&time);
+ year = when.tm_year+1900;
+ if ( year < 2000 ) year -= 1900;
+ else year -= 2000;
+#if _FRENCH
+ sprintf(buffer, "%.2d.%.2d.%.2d %.2d:%.2d",
+ when.tm_mday, when.tm_mon+1, year,
+ when.tm_hour, when.tm_min);
+#endif
+#if _GERMAN | _WG
+ sprintf(buffer, "%.2d.%.2d.%.2d %.2d:%.2d",
+ when.tm_mday, when.tm_mon+1, year,
+ when.tm_hour, when.tm_min);
+#endif
+#if _ENGLISH
+ char format[10];
+ int hour;
+
+ hour = when.tm_hour; // 0..23
+ if ( hour < 12 ) // morning?
+ {
+ strcpy(format, "am");
+ }
+ else // afternoon?
+ {
+ strcpy(format, "pm");
+ hour -= 12; // 0..11
+ }
+ if ( hour == 0 ) hour = 12;
+
+ sprintf(buffer, "%.2d.%.2d.%.2d %.2d:%.2d %s",
+ when.tm_mon+1, when.tm_mday, year,
+ hour, when.tm_min, format);
+#endif
+#if _POLISH
+ sprintf(buffer, "%.2d.%.2d.%.2d %.2d:%.2d",
+ when.tm_mday, when.tm_mon+1, year,
+ when.tm_hour, when.tm_min);
+#endif
+}
+
+
+// Makes a copy of a file.
+
+bool Xfer(char* src, char* dst)
+{
+ FILE *fs, *fd;
+ char *buffer;
+ int len;
+
+ fs = fopen(src, "rb");
+ if ( fs == 0 )
+ {
+ return false;
+ }
+
+ fd = fopen(dst, "wb");
+ if ( fd == 0 )
+ {
+ fclose(fs);
+ return false;
+ }
+
+ buffer = (char*)malloc(10000);
+
+ while ( true )
+ {
+ len = fread(buffer, 1, 10000, fs);
+ if ( len == 0 ) break;
+ fwrite(buffer, 1, len, fd);
+ }
+
+ free(buffer);
+ fclose(fs);
+ fclose(fd);
+ return true;
+}
+
+// Copy a file into the temporary folder.
+
+bool CopyFileToTemp(char* filename)
+{
+ char src[100];
+ char dst[100];
+ char save[100];
+
+ UserDir(src, filename, "textures");
+
+ strcpy(save, g_userDir);
+ strcpy(g_userDir, "temp");
+ UserDir(dst, filename, "textures");
+ strcpy(g_userDir, save);
+
+ _mkdir("temp");
+ if ( !Xfer(src, dst) ) return false;
+
+ strcpy(filename, dst);
+ return true;
+}
+
+// Copy a list of numbered files into the temporary folder.
+
+bool CopyFileListToTemp(char* filename, int* list, int total)
+{
+ char name[100];
+ char ext[10];
+ char file[100];
+ char save[100];
+ char* p;
+ int i;
+
+ strcpy(name, filename);
+ p = strchr(name, '.');
+ if ( p == 0 )
+ {
+ strcpy(ext, ".tga");
+ }
+ else
+ {
+ strcpy(ext, p);
+ *p = 0;
+ }
+
+ for ( i=0 ; i<total ; i++ )
+ {
+ sprintf(file, "%s%.3d%s", name, list[i], ext); // nameNNN.ext
+ CopyFileToTemp(file);
+ }
+
+ strcpy(save, g_userDir);
+ strcpy(g_userDir, "temp");
+ UserDir(file, filename, "textures");
+ strcpy(filename, file);
+ strcpy(g_userDir, save);
+
+ return true;
+}
+
+
+// Adds an extension to file, if doesn't already one.
+
+void AddExt(char* filename, char* ext)
+{
+ if ( strchr(filename, '.') != 0 ) return; // already an extension?
+ strcat(filename, ext);
+}
+
+
+// Specifies the user folder.
+
+void UserDir(bool bUser, char* dir)
+{
+ g_bUserDir = bUser;
+ strcpy(g_userDir, dir);
+}
+
+// Replaces the string %user% by the user folder.
+// in: dir = "%user%toto.txt"
+// def = "abc\"
+// out: buffer = "abc\toto.txt"
+
+void UserDir(char* buffer, char* dir, char* def)
+{
+ char ddir[100];
+ char* add;
+
+ if ( strstr(dir, "\\") == 0 && def[0] != 0 )
+ {
+ sprintf(ddir, "%s\\%s", def, dir);
+ }
+ else
+ {
+ strcpy(ddir, dir);
+ }
+ dir = ddir;
+
+ while ( *dir != 0 )
+ {
+ if ( dir[0] == '%' &&
+ dir[1] == 'u' &&
+ dir[2] == 's' &&
+ dir[3] == 'e' &&
+ dir[4] == 'r' &&
+ dir[5] == '%' ) // %user% ?
+ {
+ if ( g_bUserDir ) add = g_userDir;
+ else add = def;
+
+ while ( *add != 0 )
+ {
+ *buffer++ = *add++;
+ }
+ dir += 6; // jumps to %user%
+ continue;
+ }
+
+ *buffer++ = *dir++;
+ }
+ *buffer = 0;
+}
+
+
+// Returns the letter corresponding to the language.
+
+char RetLanguageLetter()
+{
+#if _FRENCH
+ return 'F';
+#endif
+#if _ENGLISH
+ return 'E';
+#endif
+#if _GERMAN | _WG
+ return 'D';
+#endif
+#if _POLISH
+ return 'P';
+#endif
+ return 'X';
+}
+
diff --git a/src/common/misc.h b/src/common/misc.h
index 1108413..e863b69 100644
--- a/src/common/misc.h
+++ b/src/common/misc.h
@@ -1,238 +1,238 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// misc.h
-
-#pragma once
-
-
-#include <time.h>
-
-
-#include "common/metafile.h"
-#include "common/event.h"
-
-
-extern CMetaFile g_metafile;
-
-
-
-// Existing classes.
-
-enum ClassType
-{
- CLASS_EVENT = 1,
- CLASS_INTERFACE = 2,
- CLASS_MAIN = 3,
- CLASS_ENGINE = 4,
- CLASS_TERRAIN = 5,
- CLASS_OBJECT = 6,
- CLASS_PHYSICS = 7,
- CLASS_BRAIN = 8,
- CLASS_CAMERA = 9,
- CLASS_LIGHT = 10,
- CLASS_PARTICULE = 11,
- CLASS_AUTO = 12,
- CLASS_DISPLAYTEXT = 13,
- CLASS_PYRO = 14,
- CLASS_SCRIPT = 15,
- CLASS_TEXT = 16,
- CLASS_STUDIO = 17,
- CLASS_WATER = 18,
- CLASS_CLOUD = 19,
- CLASS_MOTION = 20,
- CLASS_SOUND = 21,
- CLASS_PLANET = 22,
- CLASS_TASKMANAGER = 23,
- CLASS_DIALOG = 24,
- CLASS_MAP = 25,
- CLASS_SHORT = 26,
- CLASS_BLITZ = 27,
-};
-
-const int CLASS_MAX = 30;
-
-
-
-enum Error
-{
- ERR_OK = 0, // ok
- ERR_GENERIC = 1, // any error
- ERR_CONTINUE = 2, // continues
- ERR_STOP = 3, // stops
- ERR_CMD = 4, // unknown command
- ERR_INSTALL = 20, // incorrectly installed program
- ERR_NOCD = 21, // CD not found
- ERR_MANIP_VEH = 100, // inappropriate vehicle
- ERR_MANIP_FLY = 101, // impossible in flight
- ERR_MANIP_BUSY = 102, // taking: hands already occupied
- ERR_MANIP_NIL = 103, // taking: nothing has to take
- ERR_MANIP_MOTOR = 105, // busy: impossible to move
- ERR_MANIP_OCC = 106, // busy: location already occupied
- ERR_MANIP_FRIEND = 107, // no other vehicle
- ERR_MANIP_RADIO = 108, // impossible because radioactive
- ERR_MANIP_WATER = 109, // not possible under water
- ERR_MANIP_EMPTY = 110, // nothing to deposit
- ERR_BUILD_FLY = 120, // not possible in flight
- ERR_BUILD_WATER = 121, // not possible under water
- ERR_BUILD_ENERGY = 122, // not enough energy
- ERR_BUILD_METALAWAY = 123, // lack of metal (too far)
- ERR_BUILD_METALNEAR = 124, // lack of metal (too close)
- ERR_BUILD_METALINEX = 125, // lack of metal
- ERR_BUILD_FLAT = 126, // not enough flat ground
- ERR_BUILD_FLATLIT = 127, // not enough flat ground space
- ERR_BUILD_BUSY = 128, // location occupied
- ERR_BUILD_BASE = 129, // too close to the rocket
- ERR_BUILD_NARROW = 130, // buildings too close
- ERR_BUILD_MOTOR = 131, // built: not possible in movement
- ERR_SEARCH_FLY = 140, // not possible in flight
- ERR_SEARCH_VEH = 141, // inappropriate vehicle
- ERR_SEARCH_MOTOR = 142, // impossible in movement
- ERR_TERRA_VEH = 150, // inappropriate vehicle
- ERR_TERRA_ENERGY = 151, // not enough energy
- ERR_TERRA_FLOOR = 152, // inappropriate ground
- ERR_TERRA_BUILDING = 153, // building too close
- ERR_TERRA_OBJECT = 154, // object too close
- ERR_FIRE_VEH = 160, // inappropriate vehicle
- ERR_FIRE_ENERGY = 161, // not enough energy
- ERR_FIRE_FLY = 162, // not possible in flight
- ERR_RECOVER_VEH = 170, // inappropriate vehicle
- ERR_RECOVER_ENERGY = 171, // not enough energy
- ERR_RECOVER_NULL = 172, // lack of ruin
- ERR_CONVERT_EMPTY = 180, // no stone was transformed
- ERR_SHIELD_VEH = 190, // inappropriate vehicle
- ERR_SHIELD_ENERGY = 191, // not enough energy
- ERR_MOVE_IMPOSSIBLE = 200, // move impossible
- ERR_FIND_IMPOSSIBLE = 201, // find impossible
- ERR_GOTO_IMPOSSIBLE = 210, // goto impossible
- ERR_GOTO_ITER = 211, // goto too complicated
- ERR_GOTO_BUSY = 212, // goto destination occupied
- ERR_DERRICK_NULL = 300, // no ore underground
- ERR_STATION_NULL = 301, // no energy underground
- ERR_TOWER_POWER = 310, // no battery
- ERR_TOWER_ENERGY = 311, // more energy
- ERR_RESEARCH_POWER = 320, // no battery
- ERR_RESEARCH_ENERGY = 321, // more energy
- ERR_RESEARCH_TYPE = 322, // the wrong type of battery
- ERR_RESEARCH_ALREADY = 323, // research already done
- ERR_ENERGY_NULL = 330, // no energy underground
- ERR_ENERGY_LOW = 331, // not enough energy
- ERR_ENERGY_EMPTY = 332, // lack of metal
- ERR_ENERGY_BAD = 333, // transforms only the metal
- ERR_BASE_DLOCK = 340, // doors locked
- ERR_BASE_DHUMAN = 341, // you must be on spaceship
- ERR_LABO_NULL = 350, // nothing to analyze
- ERR_LABO_BAD = 351, // analyzes only organic ball
- ERR_LABO_ALREADY = 352, // analysis already made
- ERR_NUCLEAR_NULL = 360, // no energy underground
- ERR_NUCLEAR_LOW = 361, // not enough energy
- ERR_NUCLEAR_EMPTY = 362, // lack of uranium
- ERR_NUCLEAR_BAD = 363, // transforms only uranium
- ERR_FACTORY_NULL = 370, // no metal
- ERR_FACTORY_NEAR = 371, // vehicle too close
- ERR_RESET_NEAR = 380, // vehicle too close
- ERR_INFO_NULL = 390, // no information terminal
- ERR_VEH_VIRUS = 400, // vehicle infected by a virus
- ERR_BAT_VIRUS = 401, // building infected by a virus
- ERR_VEH_POWER = 500, // no battery
- ERR_VEH_ENERGY = 501, // more energy
- ERR_FLAG_FLY = 510, // impossible in flight
- ERR_FLAG_WATER = 511, // impossible during swimming
- ERR_FLAG_MOTOR = 512, // impossible in movement
- ERR_FLAG_BUSY = 513, // taking: already creating flag
- ERR_FLAG_CREATE = 514, // too many flags
- ERR_FLAG_PROXY = 515, // too close
- ERR_FLAG_DELETE = 516, // nothing to remove
- ERR_MISSION_NOTERM = 600, // Mission not completed
- ERR_DELETEMOBILE = 700, // vehicle destroyed
- ERR_DELETEBUILDING = 701, // building destroyed
- ERR_TOOMANY = 702, // too many objects
- ERR_OBLIGATORYTOKEN = 800, // compulsory instruction missing
- ERR_PROHIBITEDTOKEN = 801, // instruction prohibited
-
- INFO_FIRST = 10000, // first information
- INFO_BUILD = 10001, // construction builded
- INFO_CONVERT = 10002, // metal available
- INFO_RESEARCH = 10003, // search ended
- INFO_FACTORY = 10004, // vehicle manufactured
- INFO_LABO = 10005, // analysis ended
- INFO_ENERGY = 10006, // battery available
- INFO_NUCLEAR = 10007, // nuclear battery available
- INFO_FINDING = 10008, // nuclear battery available
- INFO_MARKPOWER = 10020, // location for station found
- INFO_MARKURANIUM = 10021, // location for derrick found
- INFO_MARKSTONE = 10022, // location for derrick found
- INFO_MARKKEYa = 10023, // location for derrick found
- INFO_MARKKEYb = 10024, // location for derrick found
- INFO_MARKKEYc = 10025, // location for derrick found
- INFO_MARKKEYd = 10026, // location for derrick found
- INFO_RESEARCHTANK = 10030, // research ended
- INFO_RESEARCHFLY = 10031, // research ended
- INFO_RESEARCHTHUMP = 10032, // research ended
- INFO_RESEARCHCANON = 10033, // research ended
- INFO_RESEARCHTOWER = 10034, // research ended
- INFO_RESEARCHPHAZER = 10035, // research ended
- INFO_RESEARCHSHIELD = 10036, // research ended
- INFO_RESEARCHATOMIC = 10037, // research ended
- INFO_WIN = 10040, // win
- INFO_LOST = 10041, // lost
- INFO_LOSTq = 10042, // lost immediately
- INFO_WRITEOK = 10043, // record done
- INFO_DELETEPATH = 10050, // way mark deleted
- INFO_DELETEMOTHER = 10100, // insect killed
- INFO_DELETEANT = 10101, // insect killed
- INFO_DELETEBEE = 10102, // insect killed
- INFO_DELETEWORM = 10103, // insect killed
- INFO_DELETESPIDER = 10104, // insect killed
- INFO_BEGINSATCOM = 10105, // use your SatCom
-};
-
-
-// Keyboard state.
-
-const int KS_PAGEUP = (1<<4);
-const int KS_PAGEDOWN = (1<<5);
-const int KS_SHIFT = (1<<6);
-const int KS_CONTROL = (1<<7);
-const int KS_MLEFT = (1<<8);
-const int KS_MRIGHT = (1<<9);
-const int KS_NUMUP = (1<<10);
-const int KS_NUMDOWN = (1<<11);
-const int KS_NUMLEFT = (1<<12);
-const int KS_NUMRIGHT = (1<<13);
-const int KS_NUMPLUS = (1<<14);
-const int KS_NUMMINUS = (1<<15);
-
-
-// Procedures.
-
-extern EventMsg GetUniqueEventMsg();
-
-extern char RetNoAccent(char letter);
-extern char RetToUpper(char letter);
-extern char RetToLower(char letter);
-
-extern void TimeToAscii(time_t time, char *buffer);
-
-extern bool CopyFileToTemp(char* filename);
-extern bool CopyFileListToTemp(char* filename, int* list, int total);
-extern void AddExt(char* filename, char* ext);
-extern void UserDir(bool bUser, char* dir);
-extern void UserDir(char* buffer, char* dir, char* def);
-
-extern char RetLanguageLetter();
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// misc.h
+
+#pragma once
+
+
+#include <time.h>
+
+
+#include "common/metafile.h"
+#include "common/event.h"
+
+
+extern CMetaFile g_metafile;
+
+
+
+// Existing classes.
+
+enum ClassType
+{
+ CLASS_EVENT = 1,
+ CLASS_INTERFACE = 2,
+ CLASS_MAIN = 3,
+ CLASS_ENGINE = 4,
+ CLASS_TERRAIN = 5,
+ CLASS_OBJECT = 6,
+ CLASS_PHYSICS = 7,
+ CLASS_BRAIN = 8,
+ CLASS_CAMERA = 9,
+ CLASS_LIGHT = 10,
+ CLASS_PARTICULE = 11,
+ CLASS_AUTO = 12,
+ CLASS_DISPLAYTEXT = 13,
+ CLASS_PYRO = 14,
+ CLASS_SCRIPT = 15,
+ CLASS_TEXT = 16,
+ CLASS_STUDIO = 17,
+ CLASS_WATER = 18,
+ CLASS_CLOUD = 19,
+ CLASS_MOTION = 20,
+ CLASS_SOUND = 21,
+ CLASS_PLANET = 22,
+ CLASS_TASKMANAGER = 23,
+ CLASS_DIALOG = 24,
+ CLASS_MAP = 25,
+ CLASS_SHORT = 26,
+ CLASS_BLITZ = 27,
+};
+
+const int CLASS_MAX = 30;
+
+
+
+enum Error
+{
+ ERR_OK = 0, // ok
+ ERR_GENERIC = 1, // any error
+ ERR_CONTINUE = 2, // continues
+ ERR_STOP = 3, // stops
+ ERR_CMD = 4, // unknown command
+ ERR_INSTALL = 20, // incorrectly installed program
+ ERR_NOCD = 21, // CD not found
+ ERR_MANIP_VEH = 100, // inappropriate vehicle
+ ERR_MANIP_FLY = 101, // impossible in flight
+ ERR_MANIP_BUSY = 102, // taking: hands already occupied
+ ERR_MANIP_NIL = 103, // taking: nothing has to take
+ ERR_MANIP_MOTOR = 105, // busy: impossible to move
+ ERR_MANIP_OCC = 106, // busy: location already occupied
+ ERR_MANIP_FRIEND = 107, // no other vehicle
+ ERR_MANIP_RADIO = 108, // impossible because radioactive
+ ERR_MANIP_WATER = 109, // not possible under water
+ ERR_MANIP_EMPTY = 110, // nothing to deposit
+ ERR_BUILD_FLY = 120, // not possible in flight
+ ERR_BUILD_WATER = 121, // not possible under water
+ ERR_BUILD_ENERGY = 122, // not enough energy
+ ERR_BUILD_METALAWAY = 123, // lack of metal (too far)
+ ERR_BUILD_METALNEAR = 124, // lack of metal (too close)
+ ERR_BUILD_METALINEX = 125, // lack of metal
+ ERR_BUILD_FLAT = 126, // not enough flat ground
+ ERR_BUILD_FLATLIT = 127, // not enough flat ground space
+ ERR_BUILD_BUSY = 128, // location occupied
+ ERR_BUILD_BASE = 129, // too close to the rocket
+ ERR_BUILD_NARROW = 130, // buildings too close
+ ERR_BUILD_MOTOR = 131, // built: not possible in movement
+ ERR_SEARCH_FLY = 140, // not possible in flight
+ ERR_SEARCH_VEH = 141, // inappropriate vehicle
+ ERR_SEARCH_MOTOR = 142, // impossible in movement
+ ERR_TERRA_VEH = 150, // inappropriate vehicle
+ ERR_TERRA_ENERGY = 151, // not enough energy
+ ERR_TERRA_FLOOR = 152, // inappropriate ground
+ ERR_TERRA_BUILDING = 153, // building too close
+ ERR_TERRA_OBJECT = 154, // object too close
+ ERR_FIRE_VEH = 160, // inappropriate vehicle
+ ERR_FIRE_ENERGY = 161, // not enough energy
+ ERR_FIRE_FLY = 162, // not possible in flight
+ ERR_RECOVER_VEH = 170, // inappropriate vehicle
+ ERR_RECOVER_ENERGY = 171, // not enough energy
+ ERR_RECOVER_NULL = 172, // lack of ruin
+ ERR_CONVERT_EMPTY = 180, // no stone was transformed
+ ERR_SHIELD_VEH = 190, // inappropriate vehicle
+ ERR_SHIELD_ENERGY = 191, // not enough energy
+ ERR_MOVE_IMPOSSIBLE = 200, // move impossible
+ ERR_FIND_IMPOSSIBLE = 201, // find impossible
+ ERR_GOTO_IMPOSSIBLE = 210, // goto impossible
+ ERR_GOTO_ITER = 211, // goto too complicated
+ ERR_GOTO_BUSY = 212, // goto destination occupied
+ ERR_DERRICK_NULL = 300, // no ore underground
+ ERR_STATION_NULL = 301, // no energy underground
+ ERR_TOWER_POWER = 310, // no battery
+ ERR_TOWER_ENERGY = 311, // more energy
+ ERR_RESEARCH_POWER = 320, // no battery
+ ERR_RESEARCH_ENERGY = 321, // more energy
+ ERR_RESEARCH_TYPE = 322, // the wrong type of battery
+ ERR_RESEARCH_ALREADY = 323, // research already done
+ ERR_ENERGY_NULL = 330, // no energy underground
+ ERR_ENERGY_LOW = 331, // not enough energy
+ ERR_ENERGY_EMPTY = 332, // lack of metal
+ ERR_ENERGY_BAD = 333, // transforms only the metal
+ ERR_BASE_DLOCK = 340, // doors locked
+ ERR_BASE_DHUMAN = 341, // you must be on spaceship
+ ERR_LABO_NULL = 350, // nothing to analyze
+ ERR_LABO_BAD = 351, // analyzes only organic ball
+ ERR_LABO_ALREADY = 352, // analysis already made
+ ERR_NUCLEAR_NULL = 360, // no energy underground
+ ERR_NUCLEAR_LOW = 361, // not enough energy
+ ERR_NUCLEAR_EMPTY = 362, // lack of uranium
+ ERR_NUCLEAR_BAD = 363, // transforms only uranium
+ ERR_FACTORY_NULL = 370, // no metal
+ ERR_FACTORY_NEAR = 371, // vehicle too close
+ ERR_RESET_NEAR = 380, // vehicle too close
+ ERR_INFO_NULL = 390, // no information terminal
+ ERR_VEH_VIRUS = 400, // vehicle infected by a virus
+ ERR_BAT_VIRUS = 401, // building infected by a virus
+ ERR_VEH_POWER = 500, // no battery
+ ERR_VEH_ENERGY = 501, // more energy
+ ERR_FLAG_FLY = 510, // impossible in flight
+ ERR_FLAG_WATER = 511, // impossible during swimming
+ ERR_FLAG_MOTOR = 512, // impossible in movement
+ ERR_FLAG_BUSY = 513, // taking: already creating flag
+ ERR_FLAG_CREATE = 514, // too many flags
+ ERR_FLAG_PROXY = 515, // too close
+ ERR_FLAG_DELETE = 516, // nothing to remove
+ ERR_MISSION_NOTERM = 600, // Mission not completed
+ ERR_DELETEMOBILE = 700, // vehicle destroyed
+ ERR_DELETEBUILDING = 701, // building destroyed
+ ERR_TOOMANY = 702, // too many objects
+ ERR_OBLIGATORYTOKEN = 800, // compulsory instruction missing
+ ERR_PROHIBITEDTOKEN = 801, // instruction prohibited
+
+ INFO_FIRST = 10000, // first information
+ INFO_BUILD = 10001, // construction builded
+ INFO_CONVERT = 10002, // metal available
+ INFO_RESEARCH = 10003, // search ended
+ INFO_FACTORY = 10004, // vehicle manufactured
+ INFO_LABO = 10005, // analysis ended
+ INFO_ENERGY = 10006, // battery available
+ INFO_NUCLEAR = 10007, // nuclear battery available
+ INFO_FINDING = 10008, // nuclear battery available
+ INFO_MARKPOWER = 10020, // location for station found
+ INFO_MARKURANIUM = 10021, // location for derrick found
+ INFO_MARKSTONE = 10022, // location for derrick found
+ INFO_MARKKEYa = 10023, // location for derrick found
+ INFO_MARKKEYb = 10024, // location for derrick found
+ INFO_MARKKEYc = 10025, // location for derrick found
+ INFO_MARKKEYd = 10026, // location for derrick found
+ INFO_RESEARCHTANK = 10030, // research ended
+ INFO_RESEARCHFLY = 10031, // research ended
+ INFO_RESEARCHTHUMP = 10032, // research ended
+ INFO_RESEARCHCANON = 10033, // research ended
+ INFO_RESEARCHTOWER = 10034, // research ended
+ INFO_RESEARCHPHAZER = 10035, // research ended
+ INFO_RESEARCHSHIELD = 10036, // research ended
+ INFO_RESEARCHATOMIC = 10037, // research ended
+ INFO_WIN = 10040, // win
+ INFO_LOST = 10041, // lost
+ INFO_LOSTq = 10042, // lost immediately
+ INFO_WRITEOK = 10043, // record done
+ INFO_DELETEPATH = 10050, // way mark deleted
+ INFO_DELETEMOTHER = 10100, // insect killed
+ INFO_DELETEANT = 10101, // insect killed
+ INFO_DELETEBEE = 10102, // insect killed
+ INFO_DELETEWORM = 10103, // insect killed
+ INFO_DELETESPIDER = 10104, // insect killed
+ INFO_BEGINSATCOM = 10105, // use your SatCom
+};
+
+
+// Keyboard state.
+
+const int KS_PAGEUP = (1<<4);
+const int KS_PAGEDOWN = (1<<5);
+const int KS_SHIFT = (1<<6);
+const int KS_CONTROL = (1<<7);
+const int KS_MLEFT = (1<<8);
+const int KS_MRIGHT = (1<<9);
+const int KS_NUMUP = (1<<10);
+const int KS_NUMDOWN = (1<<11);
+const int KS_NUMLEFT = (1<<12);
+const int KS_NUMRIGHT = (1<<13);
+const int KS_NUMPLUS = (1<<14);
+const int KS_NUMMINUS = (1<<15);
+
+
+// Procedures.
+
+extern EventMsg GetUniqueEventMsg();
+
+extern char RetNoAccent(char letter);
+extern char RetToUpper(char letter);
+extern char RetToLower(char letter);
+
+extern void TimeToAscii(time_t time, char *buffer);
+
+extern bool CopyFileToTemp(char* filename);
+extern bool CopyFileListToTemp(char* filename, int* list, int total);
+extern void AddExt(char* filename, char* ext);
+extern void UserDir(bool bUser, char* dir);
+extern void UserDir(char* buffer, char* dir, char* def);
+
+extern char RetLanguageLetter();
+
+
diff --git a/src/common/modfile.cpp b/src/common/modfile.cpp
index f87df25..fc202b7 100644
--- a/src/common/modfile.cpp
+++ b/src/common/modfile.cpp
@@ -1,695 +1,695 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// modfile.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/geometry.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/language.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "common/modfile.h"
-
-
-
-const int MAX_VERTICES = 2000;
-
-
-
-// Object's constructor.
-
-CModFile::CModFile(CInstanceManager* iMan)
-{
- m_iMan = iMan;
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
-
- m_triangleUsed = 0;
- m_triangleTable = (ModelTriangle*)malloc(sizeof(ModelTriangle)*MAX_VERTICES);
- ZeroMemory(m_triangleTable, sizeof(ModelTriangle)*MAX_VERTICES);
-}
-
-// Object's destructor.
-
-CModFile::~CModFile()
-{
- free(m_triangleTable);
-}
-
-
-
-
-// Creates a triangle in the internal structure.
-
-bool CModFile::CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3,
- float min, float max)
-{
- Math::Vector n;
- int i;
-
- if ( m_triangleUsed >= MAX_VERTICES )
- {
- OutputDebugString("ERROR: CreateTriangle::Too many triangles\n");
- return false;
- }
-
- i = m_triangleUsed++;
-
- ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
-
- m_triangleTable[i].bUsed = true;
- m_triangleTable[i].bSelect = false;
-
- n = Math::NormalToPlane(p3, p2, p1);
- m_triangleTable[i].p1 = D3DVERTEX2( p1, n);
- m_triangleTable[i].p2 = D3DVERTEX2( p2, n);
- m_triangleTable[i].p3 = D3DVERTEX2( p3, n);
-
- m_triangleTable[i].material.diffuse.r = 1.0f;
- m_triangleTable[i].material.diffuse.g = 1.0f;
- m_triangleTable[i].material.diffuse.b = 1.0f; // white
- m_triangleTable[i].material.ambient.r = 0.5f;
- m_triangleTable[i].material.ambient.g = 0.5f;
- m_triangleTable[i].material.ambient.b = 0.5f;
-
- m_triangleTable[i].min = min;
- m_triangleTable[i].max = max;
-
- return true;
-}
-
-// Reads a DXF file.
-
-bool CModFile::ReadDXF(char *filename, float min, float max)
-{
- FILE* file = NULL;
- char line[100];
- int command, rankSommet, nbSommet, nbFace;
- Math::Vector table[MAX_VERTICES];
- bool bWaitNbSommet;
- bool bWaitNbFace;
- bool bWaitSommetX;
- bool bWaitSommetY;
- bool bWaitSommetZ;
- bool bWaitFaceX;
- bool bWaitFaceY;
- bool bWaitFaceZ;
- float x,y,z;
- int p1,p2,p3;
-
- file = fopen(filename, "r");
- if ( file == NULL ) return false;
-
- m_triangleUsed = 0;
-
- rankSommet = 0;
- bWaitNbSommet = false;
- bWaitNbFace = false;
- bWaitSommetX = false;
- bWaitSommetY = false;
- bWaitSommetZ = false;
- bWaitFaceX = false;
- bWaitFaceY = false;
- bWaitFaceZ = false;
-
- while ( fgets(line, 100, file) != NULL )
- {
- sscanf(line, "%d", &command);
- if ( fgets(line, 100, file) == NULL ) break;
-
- if ( command == 66 )
- {
- bWaitNbSommet = true;
- }
-
- if ( command == 71 && bWaitNbSommet )
- {
- bWaitNbSommet = false;
- sscanf(line, "%d", &nbSommet);
- if ( nbSommet > MAX_VERTICES ) nbSommet = MAX_VERTICES;
- rankSommet = 0;
- bWaitNbFace = true;
-
-//? sprintf(s, "Waiting for %d sommets\n", nbSommet);
-//? OutputDebugString(s);
- }
-
- if ( command == 72 && bWaitNbFace )
- {
- bWaitNbFace = false;
- sscanf(line, "%d", &nbFace);
- bWaitSommetX = true;
-
-//? sprintf(s, "Waiting for %d faces\n", nbFace);
-//? OutputDebugString(s);
- }
-
- if ( command == 10 && bWaitSommetX )
- {
- bWaitSommetX = false;
- sscanf(line, "%f", &x);
- bWaitSommetY = true;
- }
-
- if ( command == 20 && bWaitSommetY )
- {
- bWaitSommetY = false;
- sscanf(line, "%f", &y);
- bWaitSommetZ = true;
- }
-
- if ( command == 30 && bWaitSommetZ )
- {
- bWaitSommetZ = false;
- sscanf(line, "%f", &z);
-
- nbSommet --;
- if ( nbSommet >= 0 )
- {
- Math::Vector p(x,z,y); // permutation of Y and Z!
- table[rankSommet++] = p;
- bWaitSommetX = true;
-
-//? sprintf(s, "Sommet[%d]=%f;%f;%f\n", rankSommet, p.x,p.y,p.z);
-//? OutputDebugString(s);
- }
- else
- {
- bWaitFaceX = true;
- }
- }
-
- if ( command == 71 && bWaitFaceX )
- {
- bWaitFaceX = false;
- sscanf(line, "%d", &p1);
- if ( p1 < 0 ) p1 = -p1;
- bWaitFaceY = true;
- }
-
- if ( command == 72 && bWaitFaceY )
- {
- bWaitFaceY = false;
- sscanf(line, "%d", &p2);
- if ( p2 < 0 ) p2 = -p2;
- bWaitFaceZ = true;
- }
-
- if ( command == 73 && bWaitFaceZ )
- {
- bWaitFaceZ = false;
- sscanf(line, "%d", &p3);
- if ( p3 < 0 ) p3 = -p3;
-
- nbFace --;
- if ( nbFace >= 0 )
- {
- CreateTriangle( table[p3-1], table[p2-1], table[p1-1], min,max );
- bWaitFaceX = true;
-
-//? sprintf(s, "Face=%d;%d;%d\n", p1,p2,p3);
-//? OutputDebugString(s);
- }
- }
-
- }
-
- fclose(file);
- return true;
-}
-
-
-
-struct InfoMOD
-{
- int rev;
- int vers;
- int total;
- int reserve[10];
-};
-
-
-// Change nom.bmp to nom.tga
-
-void ChangeBMPtoTGA(char *filename)
-{
- char* p;
-
- p = strstr(filename, ".bmp");
- if ( p != 0 ) strcpy(p, ".tga");
-}
-
-
-// Reads a MOD file.
-
-bool CModFile::AddModel(char *filename, int first, bool bEdit, bool bMeta)
-{
- FILE* file;
- InfoMOD info;
- float limit[2];
- int i, nb, err;
- char* p;
-
- if ( m_engine->RetDebugMode() )
- {
- bMeta = false;
- }
-
- if ( bMeta )
- {
- p = strchr(filename, '\\');
- if ( p == 0 )
- {
-#if _SCHOOL
- err = g_metafile.Open("ceebot2.dat", filename);
-#else
- err = g_metafile.Open("colobot2.dat", filename);
-#endif
- }
- else
- {
-#if _SCHOOL
- err = g_metafile.Open("ceebot2.dat", p+1);
-#else
- err = g_metafile.Open("colobot2.dat", p+1);
-#endif
- }
- if ( err != 0 ) bMeta = false;
- }
- if ( !bMeta )
- {
- file = fopen(filename, "rb");
- if ( file == NULL ) return false;
- }
-
- if ( bMeta )
- {
- g_metafile.Read(&info, sizeof(InfoMOD));
- }
- else
- {
- fread(&info, sizeof(InfoMOD), 1, file);
- }
- nb = info.total;
- m_triangleUsed += nb;
-
- if ( info.rev == 1 && info.vers == 0 )
- {
- OldModelTriangle1 old;
-
- for ( i=first ; i<m_triangleUsed ; i++ )
- {
- if ( bMeta )
- {
- g_metafile.Read(&old, sizeof(OldModelTriangle1));
- }
- else
- {
- fread(&old, sizeof(OldModelTriangle1), 1, file);
- }
-
- ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
- m_triangleTable[i].bUsed = old.bUsed;
- m_triangleTable[i].bSelect = old.bSelect;
-
- m_triangleTable[i].p1.x = old.p1.x;
- m_triangleTable[i].p1.y = old.p1.y;
- m_triangleTable[i].p1.z = old.p1.z;
- m_triangleTable[i].p1.nx = old.p1.nx;
- m_triangleTable[i].p1.ny = old.p1.ny;
- m_triangleTable[i].p1.nz = old.p1.nz;
- m_triangleTable[i].p1.tu = old.p1.tu;
- m_triangleTable[i].p1.tv = old.p1.tv;
-
- m_triangleTable[i].p2.x = old.p2.x;
- m_triangleTable[i].p2.y = old.p2.y;
- m_triangleTable[i].p2.z = old.p2.z;
- m_triangleTable[i].p2.nx = old.p2.nx;
- m_triangleTable[i].p2.ny = old.p2.ny;
- m_triangleTable[i].p2.nz = old.p2.nz;
- m_triangleTable[i].p2.tu = old.p2.tu;
- m_triangleTable[i].p2.tv = old.p2.tv;
-
- m_triangleTable[i].p3.x = old.p3.x;
- m_triangleTable[i].p3.y = old.p3.y;
- m_triangleTable[i].p3.z = old.p3.z;
- m_triangleTable[i].p3.nx = old.p3.nx;
- m_triangleTable[i].p3.ny = old.p3.ny;
- m_triangleTable[i].p3.nz = old.p3.nz;
- m_triangleTable[i].p3.tu = old.p3.tu;
- m_triangleTable[i].p3.tv = old.p3.tv;
-
- m_triangleTable[i].material = old.material;
- strcpy(m_triangleTable[i].texName, old.texName);
- m_triangleTable[i].min = old.min;
- m_triangleTable[i].max = old.max;
- }
- }
- else if ( info.rev == 1 && info.vers == 1 )
- {
- OldModelTriangle2 old;
-
- for ( i=first ; i<m_triangleUsed ; i++ )
- {
- if ( bMeta )
- {
- g_metafile.Read(&old, sizeof(OldModelTriangle2));
- }
- else
- {
- fread(&old, sizeof(OldModelTriangle2), 1, file);
- }
-
- ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
- m_triangleTable[i].bUsed = old.bUsed;
- m_triangleTable[i].bSelect = old.bSelect;
-
- m_triangleTable[i].p1.x = old.p1.x;
- m_triangleTable[i].p1.y = old.p1.y;
- m_triangleTable[i].p1.z = old.p1.z;
- m_triangleTable[i].p1.nx = old.p1.nx;
- m_triangleTable[i].p1.ny = old.p1.ny;
- m_triangleTable[i].p1.nz = old.p1.nz;
- m_triangleTable[i].p1.tu = old.p1.tu;
- m_triangleTable[i].p1.tv = old.p1.tv;
-
- m_triangleTable[i].p2.x = old.p2.x;
- m_triangleTable[i].p2.y = old.p2.y;
- m_triangleTable[i].p2.z = old.p2.z;
- m_triangleTable[i].p2.nx = old.p2.nx;
- m_triangleTable[i].p2.ny = old.p2.ny;
- m_triangleTable[i].p2.nz = old.p2.nz;
- m_triangleTable[i].p2.tu = old.p2.tu;
- m_triangleTable[i].p2.tv = old.p2.tv;
-
- m_triangleTable[i].p3.x = old.p3.x;
- m_triangleTable[i].p3.y = old.p3.y;
- m_triangleTable[i].p3.z = old.p3.z;
- m_triangleTable[i].p3.nx = old.p3.nx;
- m_triangleTable[i].p3.ny = old.p3.ny;
- m_triangleTable[i].p3.nz = old.p3.nz;
- m_triangleTable[i].p3.tu = old.p3.tu;
- m_triangleTable[i].p3.tv = old.p3.tv;
-
- m_triangleTable[i].material = old.material;
- strcpy(m_triangleTable[i].texName, old.texName);
- m_triangleTable[i].min = old.min;
- m_triangleTable[i].max = old.max;
- m_triangleTable[i].state = old.state;
- m_triangleTable[i].reserve2 = old.reserve2;
- m_triangleTable[i].reserve3 = old.reserve3;
- m_triangleTable[i].reserve4 = old.reserve4;
- }
- }
- else
- {
- if ( bMeta )
- {
- g_metafile.Read(m_triangleTable+first, sizeof(ModelTriangle)*nb);
- }
- else
- {
- fread(m_triangleTable+first, sizeof(ModelTriangle), nb, file);
- }
- }
-
- for ( i=first ; i<m_triangleUsed ; i++ )
- {
- ChangeBMPtoTGA(m_triangleTable[i].texName);
- }
-
- if ( !bEdit )
- {
- limit[0] = m_engine->RetLimitLOD(0); // frontier AB as config
- limit[1] = m_engine->RetLimitLOD(1); // frontier BC as config
-
- // Standard frontiers -> config.
- for ( i=first ; i<m_triangleUsed ; i++ )
- {
- if ( m_triangleTable[i].min == 0.0f &&
- m_triangleTable[i].max == 100.0f ) // resolution A ?
- {
- m_triangleTable[i].max = limit[0];
- }
- else if ( m_triangleTable[i].min == 100.0f &&
- m_triangleTable[i].max == 200.0f ) // resolution B ?
- {
- m_triangleTable[i].min = limit[0];
- m_triangleTable[i].max = limit[1];
- }
- else if ( m_triangleTable[i].min == 200.0f &&
- m_triangleTable[i].max == 1000000.0f ) // resolution C ?
- {
- m_triangleTable[i].min = limit[1];
- }
- }
- }
-
- if ( bMeta )
- {
- g_metafile.Close();
- }
- else
- {
- fclose(file);
- }
- return true;
-}
-
-// Reads a MOD file.
-
-bool CModFile::ReadModel(char *filename, bool bEdit, bool bMeta)
-{
- m_triangleUsed = 0;
- return AddModel(filename, 0, bEdit, bMeta);
-}
-
-
-// Writes a MOD file.
-
-bool CModFile::WriteModel(char *filename)
-{
- FILE* file;
- InfoMOD info;
-
- if ( m_triangleUsed == 0 ) return false;
-
- file = fopen(filename, "wb");
- if ( file == NULL ) return false;
-
- ZeroMemory(&info, sizeof(InfoMOD));
- info.rev = 1;
- info.vers = 2;
- info.total = m_triangleUsed;
- fwrite(&info, sizeof(InfoMOD), 1, file);
-
- fwrite(m_triangleTable, sizeof(ModelTriangle), m_triangleUsed, file);
-
- fclose(file);
- return true;
-}
-
-
-// Creates the object in the 3D engine.
-
-bool CModFile::CreateEngineObject(int objRank, int addState)
-{
-#if 0
- char texName2[20];
- int texNum, i, state;
-
- for ( i=0 ; i<m_triangleUsed ; i++ )
- {
- if ( !m_triangleTable[i].bUsed ) continue;
-
- state = m_triangleTable[i].state;
- texName2[0] = 0;
-
- if ( m_triangleTable[i].texNum2 != 0 )
- {
- if ( m_triangleTable[i].texNum2 == 1 )
- {
- texNum = m_engine->RetSecondTexture();
- }
- else
- {
- texNum = m_triangleTable[i].texNum2;
- }
-
- if ( texNum >= 1 && texNum <= 10 )
- {
- state = m_triangleTable[i].state|D3DSTATEDUALb;
- }
- if ( texNum >= 11 && texNum <= 20 )
- {
- state = m_triangleTable[i].state|D3DSTATEDUALw;
- }
- sprintf(texName2, "dirty%.2d.bmp", texNum);
- }
-
- m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
- m_triangleTable[i].material,
- state+addState,
- m_triangleTable[i].texName, texName2,
- m_triangleTable[i].min,
- m_triangleTable[i].max, false);
- }
- return true;
-#else
- char texName1[20];
- char texName2[20];
- int texNum, i, state;
-
- for ( i=0 ; i<m_triangleUsed ; i++ )
- {
- if ( !m_triangleTable[i].bUsed ) continue;
-
- state = m_triangleTable[i].state;
- strcpy(texName1, m_triangleTable[i].texName);
- texName2[0] = 0;
-
- if ( strcmp(texName1, "plant.tga") == 0 )
- {
- state |= D3DSTATEALPHA;
- }
-
- if ( m_triangleTable[i].texNum2 != 0 )
- {
- if ( m_triangleTable[i].texNum2 == 1 )
- {
- texNum = m_engine->RetSecondTexture();
- }
- else
- {
- texNum = m_triangleTable[i].texNum2;
- }
-
- if ( texNum >= 1 && texNum <= 10 )
- {
- state |= D3DSTATEDUALb;
- }
- if ( texNum >= 11 && texNum <= 20 )
- {
- state |= D3DSTATEDUALw;
- }
- sprintf(texName2, "dirty%.2d.tga", texNum);
- }
-
- m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
- m_triangleTable[i].material,
- state+addState,
- texName1, texName2,
- m_triangleTable[i].min,
- m_triangleTable[i].max, false);
- }
- return true;
-#endif
-}
-
-
-// Performs a mirror according to Z.
-
-void CModFile::Mirror()
-{
- D3DVERTEX2 t;
- int i;
-
- for ( i=0 ; i<m_triangleUsed ; i++ )
- {
- t = m_triangleTable[i].p1;
- m_triangleTable[i].p1 = m_triangleTable[i].p2;
- m_triangleTable[i].p2 = t;
-
- m_triangleTable[i].p1.z = -m_triangleTable[i].p1.z;
- m_triangleTable[i].p2.z = -m_triangleTable[i].p2.z;
- m_triangleTable[i].p3.z = -m_triangleTable[i].p3.z;
-
- m_triangleTable[i].p1.nz = -m_triangleTable[i].p1.nz;
- m_triangleTable[i].p2.nz = -m_triangleTable[i].p2.nz;
- m_triangleTable[i].p3.nz = -m_triangleTable[i].p3.nz;
- }
-}
-
-
-// Returns the pointer to the list of triangles.
-
-void CModFile::SetTriangleUsed(int total)
-{
- m_triangleUsed = total;
-}
-
-int CModFile::RetTriangleUsed()
-{
- return m_triangleUsed;
-}
-
-int CModFile::RetTriangleMax()
-{
- return MAX_VERTICES;
-}
-
-ModelTriangle* CModFile::RetTriangleList()
-{
- return m_triangleTable;
-}
-
-
-// Returns the height according to a position (x - z);
-
-float CModFile::RetHeight(Math::Vector pos)
-{
- Math::Vector p1, p2, p3;
- float limit;
- int i;
-
- limit = 5.0f;
-
- for ( i=0 ; i<m_triangleUsed ; i++ )
- {
- if ( !m_triangleTable[i].bUsed ) continue;
-
- if ( fabs(pos.x-m_triangleTable[i].p1.x) < limit &&
- fabs(pos.z-m_triangleTable[i].p1.z) < limit )
- {
- return m_triangleTable[i].p1.y;
- }
-
- if ( fabs(pos.x-m_triangleTable[i].p2.x) < limit &&
- fabs(pos.z-m_triangleTable[i].p2.z) < limit )
- {
- return m_triangleTable[i].p2.y;
- }
-
- if ( fabs(pos.x-m_triangleTable[i].p3.x) < limit &&
- fabs(pos.z-m_triangleTable[i].p3.z) < limit )
- {
- return m_triangleTable[i].p3.y;
- }
- }
-
- return 0.0f;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// modfile.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/geometry.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/language.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "common/modfile.h"
+
+
+
+const int MAX_VERTICES = 2000;
+
+
+
+// Object's constructor.
+
+CModFile::CModFile(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+
+ m_triangleUsed = 0;
+ m_triangleTable = (ModelTriangle*)malloc(sizeof(ModelTriangle)*MAX_VERTICES);
+ ZeroMemory(m_triangleTable, sizeof(ModelTriangle)*MAX_VERTICES);
+}
+
+// Object's destructor.
+
+CModFile::~CModFile()
+{
+ free(m_triangleTable);
+}
+
+
+
+
+// Creates a triangle in the internal structure.
+
+bool CModFile::CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3,
+ float min, float max)
+{
+ Math::Vector n;
+ int i;
+
+ if ( m_triangleUsed >= MAX_VERTICES )
+ {
+ OutputDebugString("ERROR: CreateTriangle::Too many triangles\n");
+ return false;
+ }
+
+ i = m_triangleUsed++;
+
+ ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
+
+ m_triangleTable[i].bUsed = true;
+ m_triangleTable[i].bSelect = false;
+
+ n = Math::NormalToPlane(p3, p2, p1);
+ m_triangleTable[i].p1 = D3DVERTEX2( p1, n);
+ m_triangleTable[i].p2 = D3DVERTEX2( p2, n);
+ m_triangleTable[i].p3 = D3DVERTEX2( p3, n);
+
+ m_triangleTable[i].material.diffuse.r = 1.0f;
+ m_triangleTable[i].material.diffuse.g = 1.0f;
+ m_triangleTable[i].material.diffuse.b = 1.0f; // white
+ m_triangleTable[i].material.ambient.r = 0.5f;
+ m_triangleTable[i].material.ambient.g = 0.5f;
+ m_triangleTable[i].material.ambient.b = 0.5f;
+
+ m_triangleTable[i].min = min;
+ m_triangleTable[i].max = max;
+
+ return true;
+}
+
+// Reads a DXF file.
+
+bool CModFile::ReadDXF(char *filename, float min, float max)
+{
+ FILE* file = NULL;
+ char line[100];
+ int command, rankSommet, nbSommet, nbFace;
+ Math::Vector table[MAX_VERTICES];
+ bool bWaitNbSommet;
+ bool bWaitNbFace;
+ bool bWaitSommetX;
+ bool bWaitSommetY;
+ bool bWaitSommetZ;
+ bool bWaitFaceX;
+ bool bWaitFaceY;
+ bool bWaitFaceZ;
+ float x,y,z;
+ int p1,p2,p3;
+
+ file = fopen(filename, "r");
+ if ( file == NULL ) return false;
+
+ m_triangleUsed = 0;
+
+ rankSommet = 0;
+ bWaitNbSommet = false;
+ bWaitNbFace = false;
+ bWaitSommetX = false;
+ bWaitSommetY = false;
+ bWaitSommetZ = false;
+ bWaitFaceX = false;
+ bWaitFaceY = false;
+ bWaitFaceZ = false;
+
+ while ( fgets(line, 100, file) != NULL )
+ {
+ sscanf(line, "%d", &command);
+ if ( fgets(line, 100, file) == NULL ) break;
+
+ if ( command == 66 )
+ {
+ bWaitNbSommet = true;
+ }
+
+ if ( command == 71 && bWaitNbSommet )
+ {
+ bWaitNbSommet = false;
+ sscanf(line, "%d", &nbSommet);
+ if ( nbSommet > MAX_VERTICES ) nbSommet = MAX_VERTICES;
+ rankSommet = 0;
+ bWaitNbFace = true;
+
+//? sprintf(s, "Waiting for %d sommets\n", nbSommet);
+//? OutputDebugString(s);
+ }
+
+ if ( command == 72 && bWaitNbFace )
+ {
+ bWaitNbFace = false;
+ sscanf(line, "%d", &nbFace);
+ bWaitSommetX = true;
+
+//? sprintf(s, "Waiting for %d faces\n", nbFace);
+//? OutputDebugString(s);
+ }
+
+ if ( command == 10 && bWaitSommetX )
+ {
+ bWaitSommetX = false;
+ sscanf(line, "%f", &x);
+ bWaitSommetY = true;
+ }
+
+ if ( command == 20 && bWaitSommetY )
+ {
+ bWaitSommetY = false;
+ sscanf(line, "%f", &y);
+ bWaitSommetZ = true;
+ }
+
+ if ( command == 30 && bWaitSommetZ )
+ {
+ bWaitSommetZ = false;
+ sscanf(line, "%f", &z);
+
+ nbSommet --;
+ if ( nbSommet >= 0 )
+ {
+ Math::Vector p(x,z,y); // permutation of Y and Z!
+ table[rankSommet++] = p;
+ bWaitSommetX = true;
+
+//? sprintf(s, "Sommet[%d]=%f;%f;%f\n", rankSommet, p.x,p.y,p.z);
+//? OutputDebugString(s);
+ }
+ else
+ {
+ bWaitFaceX = true;
+ }
+ }
+
+ if ( command == 71 && bWaitFaceX )
+ {
+ bWaitFaceX = false;
+ sscanf(line, "%d", &p1);
+ if ( p1 < 0 ) p1 = -p1;
+ bWaitFaceY = true;
+ }
+
+ if ( command == 72 && bWaitFaceY )
+ {
+ bWaitFaceY = false;
+ sscanf(line, "%d", &p2);
+ if ( p2 < 0 ) p2 = -p2;
+ bWaitFaceZ = true;
+ }
+
+ if ( command == 73 && bWaitFaceZ )
+ {
+ bWaitFaceZ = false;
+ sscanf(line, "%d", &p3);
+ if ( p3 < 0 ) p3 = -p3;
+
+ nbFace --;
+ if ( nbFace >= 0 )
+ {
+ CreateTriangle( table[p3-1], table[p2-1], table[p1-1], min,max );
+ bWaitFaceX = true;
+
+//? sprintf(s, "Face=%d;%d;%d\n", p1,p2,p3);
+//? OutputDebugString(s);
+ }
+ }
+
+ }
+
+ fclose(file);
+ return true;
+}
+
+
+
+struct InfoMOD
+{
+ int rev;
+ int vers;
+ int total;
+ int reserve[10];
+};
+
+
+// Change nom.bmp to nom.tga
+
+void ChangeBMPtoTGA(char *filename)
+{
+ char* p;
+
+ p = strstr(filename, ".bmp");
+ if ( p != 0 ) strcpy(p, ".tga");
+}
+
+
+// Reads a MOD file.
+
+bool CModFile::AddModel(char *filename, int first, bool bEdit, bool bMeta)
+{
+ FILE* file;
+ InfoMOD info;
+ float limit[2];
+ int i, nb, err;
+ char* p;
+
+ if ( m_engine->RetDebugMode() )
+ {
+ bMeta = false;
+ }
+
+ if ( bMeta )
+ {
+ p = strchr(filename, '\\');
+ if ( p == 0 )
+ {
+#if _SCHOOL
+ err = g_metafile.Open("ceebot2.dat", filename);
+#else
+ err = g_metafile.Open("colobot2.dat", filename);
+#endif
+ }
+ else
+ {
+#if _SCHOOL
+ err = g_metafile.Open("ceebot2.dat", p+1);
+#else
+ err = g_metafile.Open("colobot2.dat", p+1);
+#endif
+ }
+ if ( err != 0 ) bMeta = false;
+ }
+ if ( !bMeta )
+ {
+ file = fopen(filename, "rb");
+ if ( file == NULL ) return false;
+ }
+
+ if ( bMeta )
+ {
+ g_metafile.Read(&info, sizeof(InfoMOD));
+ }
+ else
+ {
+ fread(&info, sizeof(InfoMOD), 1, file);
+ }
+ nb = info.total;
+ m_triangleUsed += nb;
+
+ if ( info.rev == 1 && info.vers == 0 )
+ {
+ OldModelTriangle1 old;
+
+ for ( i=first ; i<m_triangleUsed ; i++ )
+ {
+ if ( bMeta )
+ {
+ g_metafile.Read(&old, sizeof(OldModelTriangle1));
+ }
+ else
+ {
+ fread(&old, sizeof(OldModelTriangle1), 1, file);
+ }
+
+ ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
+ m_triangleTable[i].bUsed = old.bUsed;
+ m_triangleTable[i].bSelect = old.bSelect;
+
+ m_triangleTable[i].p1.x = old.p1.x;
+ m_triangleTable[i].p1.y = old.p1.y;
+ m_triangleTable[i].p1.z = old.p1.z;
+ m_triangleTable[i].p1.nx = old.p1.nx;
+ m_triangleTable[i].p1.ny = old.p1.ny;
+ m_triangleTable[i].p1.nz = old.p1.nz;
+ m_triangleTable[i].p1.tu = old.p1.tu;
+ m_triangleTable[i].p1.tv = old.p1.tv;
+
+ m_triangleTable[i].p2.x = old.p2.x;
+ m_triangleTable[i].p2.y = old.p2.y;
+ m_triangleTable[i].p2.z = old.p2.z;
+ m_triangleTable[i].p2.nx = old.p2.nx;
+ m_triangleTable[i].p2.ny = old.p2.ny;
+ m_triangleTable[i].p2.nz = old.p2.nz;
+ m_triangleTable[i].p2.tu = old.p2.tu;
+ m_triangleTable[i].p2.tv = old.p2.tv;
+
+ m_triangleTable[i].p3.x = old.p3.x;
+ m_triangleTable[i].p3.y = old.p3.y;
+ m_triangleTable[i].p3.z = old.p3.z;
+ m_triangleTable[i].p3.nx = old.p3.nx;
+ m_triangleTable[i].p3.ny = old.p3.ny;
+ m_triangleTable[i].p3.nz = old.p3.nz;
+ m_triangleTable[i].p3.tu = old.p3.tu;
+ m_triangleTable[i].p3.tv = old.p3.tv;
+
+ m_triangleTable[i].material = old.material;
+ strcpy(m_triangleTable[i].texName, old.texName);
+ m_triangleTable[i].min = old.min;
+ m_triangleTable[i].max = old.max;
+ }
+ }
+ else if ( info.rev == 1 && info.vers == 1 )
+ {
+ OldModelTriangle2 old;
+
+ for ( i=first ; i<m_triangleUsed ; i++ )
+ {
+ if ( bMeta )
+ {
+ g_metafile.Read(&old, sizeof(OldModelTriangle2));
+ }
+ else
+ {
+ fread(&old, sizeof(OldModelTriangle2), 1, file);
+ }
+
+ ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
+ m_triangleTable[i].bUsed = old.bUsed;
+ m_triangleTable[i].bSelect = old.bSelect;
+
+ m_triangleTable[i].p1.x = old.p1.x;
+ m_triangleTable[i].p1.y = old.p1.y;
+ m_triangleTable[i].p1.z = old.p1.z;
+ m_triangleTable[i].p1.nx = old.p1.nx;
+ m_triangleTable[i].p1.ny = old.p1.ny;
+ m_triangleTable[i].p1.nz = old.p1.nz;
+ m_triangleTable[i].p1.tu = old.p1.tu;
+ m_triangleTable[i].p1.tv = old.p1.tv;
+
+ m_triangleTable[i].p2.x = old.p2.x;
+ m_triangleTable[i].p2.y = old.p2.y;
+ m_triangleTable[i].p2.z = old.p2.z;
+ m_triangleTable[i].p2.nx = old.p2.nx;
+ m_triangleTable[i].p2.ny = old.p2.ny;
+ m_triangleTable[i].p2.nz = old.p2.nz;
+ m_triangleTable[i].p2.tu = old.p2.tu;
+ m_triangleTable[i].p2.tv = old.p2.tv;
+
+ m_triangleTable[i].p3.x = old.p3.x;
+ m_triangleTable[i].p3.y = old.p3.y;
+ m_triangleTable[i].p3.z = old.p3.z;
+ m_triangleTable[i].p3.nx = old.p3.nx;
+ m_triangleTable[i].p3.ny = old.p3.ny;
+ m_triangleTable[i].p3.nz = old.p3.nz;
+ m_triangleTable[i].p3.tu = old.p3.tu;
+ m_triangleTable[i].p3.tv = old.p3.tv;
+
+ m_triangleTable[i].material = old.material;
+ strcpy(m_triangleTable[i].texName, old.texName);
+ m_triangleTable[i].min = old.min;
+ m_triangleTable[i].max = old.max;
+ m_triangleTable[i].state = old.state;
+ m_triangleTable[i].reserve2 = old.reserve2;
+ m_triangleTable[i].reserve3 = old.reserve3;
+ m_triangleTable[i].reserve4 = old.reserve4;
+ }
+ }
+ else
+ {
+ if ( bMeta )
+ {
+ g_metafile.Read(m_triangleTable+first, sizeof(ModelTriangle)*nb);
+ }
+ else
+ {
+ fread(m_triangleTable+first, sizeof(ModelTriangle), nb, file);
+ }
+ }
+
+ for ( i=first ; i<m_triangleUsed ; i++ )
+ {
+ ChangeBMPtoTGA(m_triangleTable[i].texName);
+ }
+
+ if ( !bEdit )
+ {
+ limit[0] = m_engine->RetLimitLOD(0); // frontier AB as config
+ limit[1] = m_engine->RetLimitLOD(1); // frontier BC as config
+
+ // Standard frontiers -> config.
+ for ( i=first ; i<m_triangleUsed ; i++ )
+ {
+ if ( m_triangleTable[i].min == 0.0f &&
+ m_triangleTable[i].max == 100.0f ) // resolution A ?
+ {
+ m_triangleTable[i].max = limit[0];
+ }
+ else if ( m_triangleTable[i].min == 100.0f &&
+ m_triangleTable[i].max == 200.0f ) // resolution B ?
+ {
+ m_triangleTable[i].min = limit[0];
+ m_triangleTable[i].max = limit[1];
+ }
+ else if ( m_triangleTable[i].min == 200.0f &&
+ m_triangleTable[i].max == 1000000.0f ) // resolution C ?
+ {
+ m_triangleTable[i].min = limit[1];
+ }
+ }
+ }
+
+ if ( bMeta )
+ {
+ g_metafile.Close();
+ }
+ else
+ {
+ fclose(file);
+ }
+ return true;
+}
+
+// Reads a MOD file.
+
+bool CModFile::ReadModel(char *filename, bool bEdit, bool bMeta)
+{
+ m_triangleUsed = 0;
+ return AddModel(filename, 0, bEdit, bMeta);
+}
+
+
+// Writes a MOD file.
+
+bool CModFile::WriteModel(char *filename)
+{
+ FILE* file;
+ InfoMOD info;
+
+ if ( m_triangleUsed == 0 ) return false;
+
+ file = fopen(filename, "wb");
+ if ( file == NULL ) return false;
+
+ ZeroMemory(&info, sizeof(InfoMOD));
+ info.rev = 1;
+ info.vers = 2;
+ info.total = m_triangleUsed;
+ fwrite(&info, sizeof(InfoMOD), 1, file);
+
+ fwrite(m_triangleTable, sizeof(ModelTriangle), m_triangleUsed, file);
+
+ fclose(file);
+ return true;
+}
+
+
+// Creates the object in the 3D engine.
+
+bool CModFile::CreateEngineObject(int objRank, int addState)
+{
+#if 0
+ char texName2[20];
+ int texNum, i, state;
+
+ for ( i=0 ; i<m_triangleUsed ; i++ )
+ {
+ if ( !m_triangleTable[i].bUsed ) continue;
+
+ state = m_triangleTable[i].state;
+ texName2[0] = 0;
+
+ if ( m_triangleTable[i].texNum2 != 0 )
+ {
+ if ( m_triangleTable[i].texNum2 == 1 )
+ {
+ texNum = m_engine->RetSecondTexture();
+ }
+ else
+ {
+ texNum = m_triangleTable[i].texNum2;
+ }
+
+ if ( texNum >= 1 && texNum <= 10 )
+ {
+ state = m_triangleTable[i].state|D3DSTATEDUALb;
+ }
+ if ( texNum >= 11 && texNum <= 20 )
+ {
+ state = m_triangleTable[i].state|D3DSTATEDUALw;
+ }
+ sprintf(texName2, "dirty%.2d.bmp", texNum);
+ }
+
+ m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
+ m_triangleTable[i].material,
+ state+addState,
+ m_triangleTable[i].texName, texName2,
+ m_triangleTable[i].min,
+ m_triangleTable[i].max, false);
+ }
+ return true;
+#else
+ char texName1[20];
+ char texName2[20];
+ int texNum, i, state;
+
+ for ( i=0 ; i<m_triangleUsed ; i++ )
+ {
+ if ( !m_triangleTable[i].bUsed ) continue;
+
+ state = m_triangleTable[i].state;
+ strcpy(texName1, m_triangleTable[i].texName);
+ texName2[0] = 0;
+
+ if ( strcmp(texName1, "plant.tga") == 0 )
+ {
+ state |= D3DSTATEALPHA;
+ }
+
+ if ( m_triangleTable[i].texNum2 != 0 )
+ {
+ if ( m_triangleTable[i].texNum2 == 1 )
+ {
+ texNum = m_engine->RetSecondTexture();
+ }
+ else
+ {
+ texNum = m_triangleTable[i].texNum2;
+ }
+
+ if ( texNum >= 1 && texNum <= 10 )
+ {
+ state |= D3DSTATEDUALb;
+ }
+ if ( texNum >= 11 && texNum <= 20 )
+ {
+ state |= D3DSTATEDUALw;
+ }
+ sprintf(texName2, "dirty%.2d.tga", texNum);
+ }
+
+ m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
+ m_triangleTable[i].material,
+ state+addState,
+ texName1, texName2,
+ m_triangleTable[i].min,
+ m_triangleTable[i].max, false);
+ }
+ return true;
+#endif
+}
+
+
+// Performs a mirror according to Z.
+
+void CModFile::Mirror()
+{
+ D3DVERTEX2 t;
+ int i;
+
+ for ( i=0 ; i<m_triangleUsed ; i++ )
+ {
+ t = m_triangleTable[i].p1;
+ m_triangleTable[i].p1 = m_triangleTable[i].p2;
+ m_triangleTable[i].p2 = t;
+
+ m_triangleTable[i].p1.z = -m_triangleTable[i].p1.z;
+ m_triangleTable[i].p2.z = -m_triangleTable[i].p2.z;
+ m_triangleTable[i].p3.z = -m_triangleTable[i].p3.z;
+
+ m_triangleTable[i].p1.nz = -m_triangleTable[i].p1.nz;
+ m_triangleTable[i].p2.nz = -m_triangleTable[i].p2.nz;
+ m_triangleTable[i].p3.nz = -m_triangleTable[i].p3.nz;
+ }
+}
+
+
+// Returns the pointer to the list of triangles.
+
+void CModFile::SetTriangleUsed(int total)
+{
+ m_triangleUsed = total;
+}
+
+int CModFile::RetTriangleUsed()
+{
+ return m_triangleUsed;
+}
+
+int CModFile::RetTriangleMax()
+{
+ return MAX_VERTICES;
+}
+
+ModelTriangle* CModFile::RetTriangleList()
+{
+ return m_triangleTable;
+}
+
+
+// Returns the height according to a position (x - z);
+
+float CModFile::RetHeight(Math::Vector pos)
+{
+ Math::Vector p1, p2, p3;
+ float limit;
+ int i;
+
+ limit = 5.0f;
+
+ for ( i=0 ; i<m_triangleUsed ; i++ )
+ {
+ if ( !m_triangleTable[i].bUsed ) continue;
+
+ if ( fabs(pos.x-m_triangleTable[i].p1.x) < limit &&
+ fabs(pos.z-m_triangleTable[i].p1.z) < limit )
+ {
+ return m_triangleTable[i].p1.y;
+ }
+
+ if ( fabs(pos.x-m_triangleTable[i].p2.x) < limit &&
+ fabs(pos.z-m_triangleTable[i].p2.z) < limit )
+ {
+ return m_triangleTable[i].p2.y;
+ }
+
+ if ( fabs(pos.x-m_triangleTable[i].p3.x) < limit &&
+ fabs(pos.z-m_triangleTable[i].p3.z) < limit )
+ {
+ return m_triangleTable[i].p3.y;
+ }
+ }
+
+ return 0.0f;
+}
+
+
diff --git a/src/common/modfile.h b/src/common/modfile.h
index 5b2d496..c852c1e 100644
--- a/src/common/modfile.h
+++ b/src/common/modfile.h
@@ -1,115 +1,115 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// modfile.h
-
-#pragma once
-
-
-#include "math/vector.h"
-#include "old/d3dengine.h"
-
-
-class CInstanceManager;
-
-
-
-
-struct OldModelTriangle1
-{
- char bUsed; // true -> using
- char bSelect; // true -> selected
- D3DVERTEX p1;
- D3DVERTEX p2;
- D3DVERTEX p3;
- D3DMATERIAL7 material;
- char texName[20];
- float min;
- float max;
-}; // length = 196 bytes
-
-struct OldModelTriangle2
-{
- char bUsed; // true -> used
- char bSelect; // true -> selected
- D3DVERTEX p1;
- D3DVERTEX p2;
- D3DVERTEX p3;
- D3DMATERIAL7 material;
- char texName[20];
- float min;
- float max;
- long state;
- short reserve1;
- short reserve2;
- short reserve3;
- short reserve4;
-};
-
-struct ModelTriangle
-{
- char bUsed; // true -> used
- char bSelect; // true -> selected
- D3DVERTEX2 p1;
- D3DVERTEX2 p2;
- D3DVERTEX2 p3;
- D3DMATERIAL7 material;
- char texName[20];
- float min;
- float max;
- long state;
- short texNum2;
- short reserve2;
- short reserve3;
- short reserve4;
-}; // length = 208 bytes
-
-
-
-
-class CModFile
-{
-public:
- CModFile(CInstanceManager* iMan);
- ~CModFile();
-
- bool ReadDXF(char *filename, float min, float max);
- bool AddModel(char *filename, int first, bool bEdit=false, bool bMeta=true);
- bool ReadModel(char *filename, bool bEdit=false, bool bMeta=true);
- bool WriteModel(char *filename);
-
- bool CreateEngineObject(int objRank, int addState=0);
- void Mirror();
-
- void SetTriangleUsed(int total);
- int RetTriangleUsed();
- int RetTriangleMax();
- ModelTriangle* RetTriangleList();
-
- float RetHeight(Math::Vector pos);
-
-protected:
- bool CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, float min, float max);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
-
- ModelTriangle* m_triangleTable;
- int m_triangleUsed;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// modfile.h
+
+#pragma once
+
+
+#include "math/vector.h"
+#include "old/d3dengine.h"
+
+
+class CInstanceManager;
+
+
+
+
+struct OldModelTriangle1
+{
+ char bUsed; // true -> using
+ char bSelect; // true -> selected
+ D3DVERTEX p1;
+ D3DVERTEX p2;
+ D3DVERTEX p3;
+ D3DMATERIAL7 material;
+ char texName[20];
+ float min;
+ float max;
+}; // length = 196 bytes
+
+struct OldModelTriangle2
+{
+ char bUsed; // true -> used
+ char bSelect; // true -> selected
+ D3DVERTEX p1;
+ D3DVERTEX p2;
+ D3DVERTEX p3;
+ D3DMATERIAL7 material;
+ char texName[20];
+ float min;
+ float max;
+ long state;
+ short reserve1;
+ short reserve2;
+ short reserve3;
+ short reserve4;
+};
+
+struct ModelTriangle
+{
+ char bUsed; // true -> used
+ char bSelect; // true -> selected
+ D3DVERTEX2 p1;
+ D3DVERTEX2 p2;
+ D3DVERTEX2 p3;
+ D3DMATERIAL7 material;
+ char texName[20];
+ float min;
+ float max;
+ long state;
+ short texNum2;
+ short reserve2;
+ short reserve3;
+ short reserve4;
+}; // length = 208 bytes
+
+
+
+
+class CModFile
+{
+public:
+ CModFile(CInstanceManager* iMan);
+ ~CModFile();
+
+ bool ReadDXF(char *filename, float min, float max);
+ bool AddModel(char *filename, int first, bool bEdit=false, bool bMeta=true);
+ bool ReadModel(char *filename, bool bEdit=false, bool bMeta=true);
+ bool WriteModel(char *filename);
+
+ bool CreateEngineObject(int objRank, int addState=0);
+ void Mirror();
+
+ void SetTriangleUsed(int total);
+ int RetTriangleUsed();
+ int RetTriangleMax();
+ ModelTriangle* RetTriangleList();
+
+ float RetHeight(Math::Vector pos);
+
+protected:
+ bool CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, float min, float max);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+
+ ModelTriangle* m_triangleTable;
+ int m_triangleUsed;
+};
+
+
diff --git a/src/common/profile.cpp b/src/common/profile.cpp
index 9f3de54..07dafae 100644
--- a/src/common/profile.cpp
+++ b/src/common/profile.cpp
@@ -1,114 +1,114 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// profile.cpp
-
-
-#include <stdio.h>
-#include <d3d.h>
-#include <stdlib.h>
-
-#include "common/language.h"
-#include "common/struct.h"
-#include "common/profile.h"
-
-
-
-static char g_filename[100];
-
-
-
-bool InitCurrentDirectory()
-{
-#if _SCHOOL
- _fullpath(g_filename, "ceebot.ini", 100);
-#else
- _fullpath(g_filename, "colobot.ini", 100);
-#endif
- return true;
-}
-
-
-bool SetProfileString(char* section, char* key, char* string)
-{
- WritePrivateProfileString(section, key, string, g_filename);
- return true;
-}
-
-bool GetProfileString(char* section, char* key, char* buffer, int max)
-{
- int nb;
-
- nb = GetPrivateProfileString(section, key, "", buffer, max, g_filename);
- if ( nb == 0 )
- {
- buffer[0] = 0;
- return false;
- }
- return true;
-}
-
-
-bool SetProfileInt(char* section, char* key, int value)
-{
- char s[20];
-
- sprintf(s, "%d", value);
- WritePrivateProfileString(section, key, s, g_filename);
- return true;
-}
-
-bool GetProfileInt(char* section, char* key, int &value)
-{
- char s[20];
- int nb;
-
- nb = GetPrivateProfileString(section, key, "", s, 20, g_filename);
- if ( nb == 0 )
- {
- value = 0;
- return false;
- }
- sscanf(s, "%d", &value);
- return true;
-}
-
-
-bool SetProfileFloat(char* section, char* key, float value)
-{
- char s[20];
-
- sprintf(s, "%.2f", value);
- WritePrivateProfileString(section, key, s, g_filename);
- return true;
-}
-
-bool GetProfileFloat(char* section, char* key, float &value)
-{
- char s[20];
- int nb;
-
- nb = GetPrivateProfileString(section, key, "", s, 20, g_filename);
- if ( nb == 0 )
- {
- value = 0.0f;
- return false;
- }
- sscanf(s, "%f", &value);
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// profile.cpp
+
+
+#include <stdio.h>
+#include <d3d.h>
+#include <stdlib.h>
+
+#include "common/language.h"
+#include "common/struct.h"
+#include "common/profile.h"
+
+
+
+static char g_filename[100];
+
+
+
+bool InitCurrentDirectory()
+{
+#if _SCHOOL
+ _fullpath(g_filename, "ceebot.ini", 100);
+#else
+ _fullpath(g_filename, "colobot.ini", 100);
+#endif
+ return true;
+}
+
+
+bool SetProfileString(char* section, char* key, char* string)
+{
+ WritePrivateProfileString(section, key, string, g_filename);
+ return true;
+}
+
+bool GetProfileString(char* section, char* key, char* buffer, int max)
+{
+ int nb;
+
+ nb = GetPrivateProfileString(section, key, "", buffer, max, g_filename);
+ if ( nb == 0 )
+ {
+ buffer[0] = 0;
+ return false;
+ }
+ return true;
+}
+
+
+bool SetProfileInt(char* section, char* key, int value)
+{
+ char s[20];
+
+ sprintf(s, "%d", value);
+ WritePrivateProfileString(section, key, s, g_filename);
+ return true;
+}
+
+bool GetProfileInt(char* section, char* key, int &value)
+{
+ char s[20];
+ int nb;
+
+ nb = GetPrivateProfileString(section, key, "", s, 20, g_filename);
+ if ( nb == 0 )
+ {
+ value = 0;
+ return false;
+ }
+ sscanf(s, "%d", &value);
+ return true;
+}
+
+
+bool SetProfileFloat(char* section, char* key, float value)
+{
+ char s[20];
+
+ sprintf(s, "%.2f", value);
+ WritePrivateProfileString(section, key, s, g_filename);
+ return true;
+}
+
+bool GetProfileFloat(char* section, char* key, float &value)
+{
+ char s[20];
+ int nb;
+
+ nb = GetPrivateProfileString(section, key, "", s, 20, g_filename);
+ if ( nb == 0 )
+ {
+ value = 0.0f;
+ return false;
+ }
+ sscanf(s, "%f", &value);
+ return true;
+}
+
+
diff --git a/src/common/profile.h b/src/common/profile.h
index a7f04a6..1a36050 100644
--- a/src/common/profile.h
+++ b/src/common/profile.h
@@ -1,30 +1,30 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// profile.h
-
-#pragma once
-
-
-extern bool InitCurrentDirectory();
-extern bool SetProfileString(char* section, char* key, char* string);
-extern bool GetProfileString(char* section, char* key, char* buffer, int max);
-extern bool SetProfileInt(char* section, char* key, int value);
-extern bool GetProfileInt(char* section, char* key, int &value);
-extern bool SetProfileFloat(char* section, char* key, float value);
-extern bool GetProfileFloat(char* section, char* key, float &value);
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// profile.h
+
+#pragma once
+
+
+extern bool InitCurrentDirectory();
+extern bool SetProfileString(char* section, char* key, char* string);
+extern bool GetProfileString(char* section, char* key, char* buffer, int max);
+extern bool SetProfileInt(char* section, char* key, int value);
+extern bool GetProfileInt(char* section, char* key, int &value);
+extern bool SetProfileFloat(char* section, char* key, float value);
+extern bool GetProfileFloat(char* section, char* key, float &value);
+
+
diff --git a/src/common/restext.cpp b/src/common/restext.cpp
index 68b24e2..bbec090 100644
--- a/src/common/restext.cpp
+++ b/src/common/restext.cpp
@@ -1,3660 +1,3659 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.// restext.cpp
-
-
-#include <stdio.h>
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "common/language.h"
-#include "common/misc.h"
-#include "common/event.h"
-#include "object/object.h"
-#include "CBot/resource.h"
-#include "common/restext.h"
-
-
-
-//** -> text to translate!
-
-
-
-// Gives the pointer to the engine.
-
-void SetEngine(CD3DEngine *engine)
-{
- g_engine = engine;
-}
-
-// Give the player's name.
-
-void SetGlobalGamerName(char *name)
-{
- strcpy(g_gamerName, name);
-}
-
-
-
-struct KeyDesc
-{
- KeyRank key;
- char name[20];
-};
-
-static KeyDesc keyTable[22] =
-{
- { KEYRANK_LEFT, "left;" },
- { KEYRANK_RIGHT, "right;" },
- { KEYRANK_UP, "up;" },
- { KEYRANK_DOWN, "down;" },
- { KEYRANK_GUP, "gup;" },
- { KEYRANK_GDOWN, "gdown;" },
- { KEYRANK_CAMERA, "camera;" },
- { KEYRANK_DESEL, "desel;" },
- { KEYRANK_ACTION, "action;" },
- { KEYRANK_NEAR, "near;" },
- { KEYRANK_AWAY, "away;" },
- { KEYRANK_NEXT, "next;" },
- { KEYRANK_HUMAN, "human;" },
- { KEYRANK_QUIT, "quit;" },
- { KEYRANK_HELP, "help;" },
- { KEYRANK_PROG, "prog;" },
- { KEYRANK_CBOT, "cbot;" },
- { KEYRANK_VISIT, "visit;" },
- { KEYRANK_SPEED10, "speed10;" },
- { KEYRANK_SPEED15, "speed15;" },
- { KEYRANK_SPEED20, "speed20;" },
- { KEYRANK_SPEED30, "speed30;" },
-};
-
-// Seeks a key.
-
-bool SearchKey(char *cmd, KeyRank &key)
-{
- int i;
-
- for ( i=0 ; i<22 ; i++ )
- {
- if ( strstr(cmd, keyTable[i].name) == cmd )
- {
- key = keyTable[i].key;
- return true;
- }
- }
- return false;
-}
-
-// Replaces the commands "\key name;" in a text.
-
-void PutKeyName(char* dst, char* src)
-{
- KeyRank key;
- char name[50];
- int s, d, n, res;
-
- s = d = 0;
- while ( src[s] != 0 )
- {
- if ( src[s+0] == '\\' &&
- src[s+1] == 'k' &&
- src[s+2] == 'e' &&
- src[s+3] == 'y' &&
- src[s+4] == ' ' )
- {
- if ( SearchKey(src+s+5, key) )
- {
- res = g_engine->RetKey(key, 0);
- if ( res != 0 )
- {
- if ( GetResource(RES_KEY, res, name) )
- {
- n = 0;
- while ( name[n] != 0 )
- {
- dst[d++] = name[n++];
- }
- while ( src[s++] != ';' );
- continue;
- }
- }
- }
- }
-
- dst[d++] = src[s++];
- }
- dst[d++] = 0;
-}
-
-
-// Returns the text of a resource.
-
-bool GetResource(ResType type, int num, char* text)
-{
- char buffer[100];
-
- if ( !GetResourceBase(type, num, buffer) )
- {
- text[0] = 0;
- return false;
- }
-
- PutKeyName(text, buffer);
- return true;
-}
-
-
-// Returns the text of a resource.
-
-bool GetResourceBase(ResType type, int num, char* text)
-{
- text[0] = 0;
-
-#if _ENGLISH
- if ( type == RES_TEXT )
- {
- #if _FULL
- if ( num == RT_VERSION_ID ) strcpy(text, "1.18 /e");
- #endif
- #if _NET
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A 1.18");
- #endif
- #if _SCHOOL & _EDU
- #if _TEEN
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen EDU 1.18");
- #else
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A EDU 1.18");
- #endif
- #endif
- #if _SCHOOL & _PERSO
- #if _TEEN
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen PERSO 1.18");
- #else
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A PERSO 1.18");
- #endif
- #endif
- #if _SCHOOL & _CEEBOTDEMO
- #if _TEEN
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen DEMO 1.18");
- #else
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A DEMO 1.18");
- #endif
- #endif
- #if _DEMO
- if ( num == RT_VERSION_ID ) strcpy(text, "Demo 1.18 /e");
- #endif
- if ( num == RT_DISINFO_TITLE ) strcpy(text, "SatCom");
- if ( num == RT_WINDOW_MAXIMIZED ) strcpy(text, "Maximize");
- if ( num == RT_WINDOW_MINIMIZED ) strcpy(text, "Minimize");
- if ( num == RT_WINDOW_STANDARD ) strcpy(text, "Normal size");
- if ( num == RT_WINDOW_CLOSE ) strcpy(text, "Close");
-
- if ( num == RT_STUDIO_TITLE ) strcpy(text, "Program editor");
- if ( num == RT_SCRIPT_NEW ) strcpy(text, "New");
- if ( num == RT_NAME_DEFAULT ) strcpy(text, "Player");
- if ( num == RT_IO_NEW ) strcpy(text, "New ...");
- if ( num == RT_KEY_OR ) strcpy(text, " or ");
-
-#if _NEWLOOK
- if ( num == RT_TITLE_BASE ) strcpy(text, "CeeBot");
- if ( num == RT_TITLE_INIT ) strcpy(text, "CeeBot");
-#else
- if ( num == RT_TITLE_BASE ) strcpy(text, "COLOBOT");
- if ( num == RT_TITLE_INIT ) strcpy(text, "COLOBOT");
-#endif
- if ( num == RT_TITLE_TRAINER ) strcpy(text, "Programming exercises");
- if ( num == RT_TITLE_DEFI ) strcpy(text, "Challenges");
- if ( num == RT_TITLE_MISSION ) strcpy(text, "Missions");
- if ( num == RT_TITLE_FREE ) strcpy(text, "Free game");
- if ( num == RT_TITLE_TEEN ) strcpy(text, "Free game");
- if ( num == RT_TITLE_USER ) strcpy(text, "User levels");
- if ( num == RT_TITLE_PROTO ) strcpy(text, "Prototypes");
- if ( num == RT_TITLE_SETUP ) strcpy(text, "Options");
- if ( num == RT_TITLE_NAME ) strcpy(text, "Player's name");
- if ( num == RT_TITLE_PERSO ) strcpy(text, "Customize your appearance");
- if ( num == RT_TITLE_WRITE ) strcpy(text, "Save the current mission");
- if ( num == RT_TITLE_READ ) strcpy(text, "Load a saved mission");
-
- if ( num == RT_PLAY_CHAPt ) strcpy(text, " Chapters:");
- if ( num == RT_PLAY_CHAPd ) strcpy(text, " Chapters:");
- if ( num == RT_PLAY_CHAPm ) strcpy(text, " Planets:");
- if ( num == RT_PLAY_CHAPf ) strcpy(text, " Planets:");
- if ( num == RT_PLAY_CHAPu ) strcpy(text, " User levels:");
- if ( num == RT_PLAY_CHAPp ) strcpy(text, " Planets:");
- if ( num == RT_PLAY_CHAPte ) strcpy(text, " Chapters:");
- if ( num == RT_PLAY_LISTt ) strcpy(text, " Exercises in the chapter:");
- if ( num == RT_PLAY_LISTd ) strcpy(text, " Challenges in the chapter:");
- if ( num == RT_PLAY_LISTm ) strcpy(text, " Missions on this planet:");
- if ( num == RT_PLAY_LISTf ) strcpy(text, " Free game on this planet:");
- if ( num == RT_PLAY_LISTu ) strcpy(text, " Missions on this level:");
- if ( num == RT_PLAY_LISTp ) strcpy(text, " Prototypes on this planet:");
- if ( num == RT_PLAY_LISTk ) strcpy(text, " Free game on this chapter:");
- if ( num == RT_PLAY_RESUME ) strcpy(text, " Summary:");
-
- if ( num == RT_SETUP_DEVICE ) strcpy(text, " Drivers:");
- if ( num == RT_SETUP_MODE ) strcpy(text, " Resolution:");
- if ( num == RT_SETUP_KEY1 ) strcpy(text, "1) First click on the key you want to redefine.");
- if ( num == RT_SETUP_KEY2 ) strcpy(text, "2) Then press the key you want to use instead.");
-
- if ( num == RT_PERSO_FACE ) strcpy(text, "Face type:");
- if ( num == RT_PERSO_GLASSES ) strcpy(text, "Eyeglasses:");
- if ( num == RT_PERSO_HAIR ) strcpy(text, "Hair color:");
- if ( num == RT_PERSO_COMBI ) strcpy(text, "Suit color:");
- if ( num == RT_PERSO_BAND ) strcpy(text, "Strip color:");
-
-#if _NEWLOOK
- if ( num == RT_DIALOG_QUIT ) strcpy(text, "Do you want to quit CeeBot ?");
- if ( num == RT_DIALOG_TITLE ) strcpy(text, "CeeBot");
- if ( num == RT_DIALOG_YESQUIT ) strcpy(text, "Quit\\Quit CeeBot");
-#else
- if ( num == RT_DIALOG_QUIT ) strcpy(text, "Do you want to quit COLOBOT ?");
- if ( num == RT_DIALOG_TITLE ) strcpy(text, "COLOBOT");
- if ( num == RT_DIALOG_YESQUIT ) strcpy(text, "Quit\\Quit COLOBOT");
-#endif
- if ( num == RT_DIALOG_ABORT ) strcpy(text, "Quit the mission?");
- if ( num == RT_DIALOG_YES ) strcpy(text, "Abort\\Abort the current mission");
- if ( num == RT_DIALOG_NO ) strcpy(text, "Continue\\Continue the current mission");
- if ( num == RT_DIALOG_NOQUIT ) strcpy(text, "Continue\\Continue the game");
- if ( num == RT_DIALOG_DELOBJ ) strcpy(text, "Do you really want to destroy the selected building?");
- if ( num == RT_DIALOG_DELGAME ) strcpy(text, "Do you want to delete %s's saved games? ");
- if ( num == RT_DIALOG_YESDEL ) strcpy(text, "Delete");
- if ( num == RT_DIALOG_NODEL ) strcpy(text, "Cancel");
- if ( num == RT_DIALOG_LOADING ) strcpy(text, "LOADING");
-
- if ( num == RT_STUDIO_LISTTT ) strcpy(text, "Keyword help(\\key cbot;)");
- if ( num == RT_STUDIO_COMPOK ) strcpy(text, "Compilation ok (0 errors)");
- if ( num == RT_STUDIO_PROGSTOP ) strcpy(text, "Program finished");
-
- if ( num == RT_SATCOM_LIST ) strcpy(text, "\\b;List of objects\n");
- if ( num == RT_SATCOM_BOT ) strcpy(text, "\\b;Robots\n");
- if ( num == RT_SATCOM_BUILDING ) strcpy(text, "\\b;Buildings\n");
- if ( num == RT_SATCOM_FRET ) strcpy(text, "\\b;Moveable objects\n");
- if ( num == RT_SATCOM_ALIEN ) strcpy(text, "\\b;Aliens\n");
- if ( num == RT_SATCOM_NULL ) strcpy(text, "\\c; (none)\\n;\n");
- if ( num == RT_SATCOM_ERROR1 ) strcpy(text, "\\b;Error\n");
- if ( num == RT_SATCOM_ERROR2 ) strcpy(text, "The list is only available if a \\l;radar station\\u object\\radar; is working.\n");
-
- if ( num == RT_IO_OPEN ) strcpy(text, "Open");
- if ( num == RT_IO_SAVE ) strcpy(text, "Save");
- if ( num == RT_IO_LIST ) strcpy(text, "Folder: %s");
- if ( num == RT_IO_NAME ) strcpy(text, "Name:");
- if ( num == RT_IO_DIR ) strcpy(text, "Folder:");
- if ( num == RT_IO_PRIVATE ) strcpy(text, "Private\\Private folder");
- if ( num == RT_IO_PUBLIC ) strcpy(text, "Public\\Common folder");
-
- if ( num == RT_GENERIC_DEV1 ) strcpy(text, "Developed by :");
- if ( num == RT_GENERIC_DEV2 ) strcpy(text, "www.epsitec.com");
-//? if ( num == RT_GENERIC_EDIT1 ) strcpy(text, "English version published by:");
-//? if ( num == RT_GENERIC_EDIT2 ) strcpy(text, "www.?.com");
- if ( num == RT_GENERIC_EDIT1 ) strcpy(text, " ");
- if ( num == RT_GENERIC_EDIT2 ) strcpy(text, " ");
-
- if ( num == RT_INTERFACE_REC ) strcpy(text, "Recorder");
- }
-
- if ( type == RES_EVENT )
- {
- if ( num == EVENT_BUTTON_OK ) strcpy(text, "OK");
- if ( num == EVENT_BUTTON_CANCEL ) strcpy(text, "Cancel");
- if ( num == EVENT_BUTTON_NEXT ) strcpy(text, "Next");
- if ( num == EVENT_BUTTON_PREV ) strcpy(text, "Previous");
- if ( num == EVENT_BUTTON_QUIT ) strcpy(text, "Menu (\\key quit;)");
-
- if ( num == EVENT_DIALOG_OK ) strcpy(text, "OK");
- if ( num == EVENT_DIALOG_CANCEL ) strcpy(text, "Cancel");
-
- if ( num == EVENT_INTERFACE_TRAINER) strcpy(text, "Exercises\\Programming exercises");
- if ( num == EVENT_INTERFACE_DEFI ) strcpy(text, "Challenges\\Programming challenges");
- if ( num == EVENT_INTERFACE_MISSION) strcpy(text, "Missions\\Select mission");
- if ( num == EVENT_INTERFACE_FREE ) strcpy(text, "Free game\\Free game without a specific goal");
- if ( num == EVENT_INTERFACE_TEEN ) strcpy(text, "Free game\\Free game without a specific goal");
- if ( num == EVENT_INTERFACE_USER ) strcpy(text, "User\\User levels");
- if ( num == EVENT_INTERFACE_PROTO ) strcpy(text, "Proto\\Prototypes under development");
- if ( num == EVENT_INTERFACE_NAME ) strcpy(text, "New player\\Choose player's name");
- if ( num == EVENT_INTERFACE_SETUP ) strcpy(text, "Options\\Preferences");
- if ( num == EVENT_INTERFACE_AGAIN ) strcpy(text, "Restart\\Restart the mission from the beginning");
- if ( num == EVENT_INTERFACE_WRITE ) strcpy(text, "Save\\Save the current mission ");
- if ( num == EVENT_INTERFACE_READ ) strcpy(text, "Load\\Load a saved mission");
-#if _NEWLOOK
- if ( num == EVENT_INTERFACE_ABORT ) strcpy(text, "\\Return to CeeBot");
- if ( num == EVENT_INTERFACE_QUIT ) strcpy(text, "Quit\\Quit CeeBot");
-#else
- if ( num == EVENT_INTERFACE_ABORT ) strcpy(text, "\\Return to COLOBOT");
- if ( num == EVENT_INTERFACE_QUIT ) strcpy(text, "Quit\\Quit COLOBOT");
-#endif
- if ( num == EVENT_INTERFACE_BACK ) strcpy(text, "<< Back \\Back to the previous screen");
- if ( num == EVENT_INTERFACE_PLAY ) strcpy(text, "Play\\Start mission!");
- if ( num == EVENT_INTERFACE_SETUPd ) strcpy(text, "Device\\Driver and resolution settings");
- if ( num == EVENT_INTERFACE_SETUPg ) strcpy(text, "Graphics\\Graphics settings");
- if ( num == EVENT_INTERFACE_SETUPp ) strcpy(text, "Game\\Game settings");
- if ( num == EVENT_INTERFACE_SETUPc ) strcpy(text, "Controls\\Keyboard, joystick and mouse settings");
- if ( num == EVENT_INTERFACE_SETUPs ) strcpy(text, "Sound\\Music and game sound volume");
- if ( num == EVENT_INTERFACE_DEVICE ) strcpy(text, "Unit");
- if ( num == EVENT_INTERFACE_RESOL ) strcpy(text, "Resolution");
- if ( num == EVENT_INTERFACE_FULL ) strcpy(text, "Full screen\\Full screen or window mode");
- if ( num == EVENT_INTERFACE_APPLY ) strcpy(text, "Apply changes\\Activates the changed settings");
-
- if ( num == EVENT_INTERFACE_TOTO ) strcpy(text, "Robbie\\Your assistant");
- if ( num == EVENT_INTERFACE_SHADOW ) strcpy(text, "Shadows\\Shadows on the ground");
- if ( num == EVENT_INTERFACE_GROUND ) strcpy(text, "Marks on the ground\\Marks on the ground");
- if ( num == EVENT_INTERFACE_DIRTY ) strcpy(text, "Dust\\Dust and dirt on bots and buildings");
- if ( num == EVENT_INTERFACE_FOG ) strcpy(text, "Fog\\Fog");
- if ( num == EVENT_INTERFACE_LENS ) strcpy(text, "Sunbeams\\Sunbeams in the sky");
- if ( num == EVENT_INTERFACE_SKY ) strcpy(text, "Sky\\Clouds and nebulae");
- if ( num == EVENT_INTERFACE_PLANET ) strcpy(text, "Planets and stars\\Astronomical objects in the sky");
- if ( num == EVENT_INTERFACE_LIGHT ) strcpy(text, "Dynamic lighting\\Mobile light sources");
- if ( num == EVENT_INTERFACE_PARTI ) strcpy(text, "Number of particles\\Explosions, dust, reflections, etc.");
- if ( num == EVENT_INTERFACE_CLIP ) strcpy(text, "Depth of field\\Maximum visibility");
- if ( num == EVENT_INTERFACE_DETAIL ) strcpy(text, "Details\\Visual quality of 3D objects");
- if ( num == EVENT_INTERFACE_TEXTURE) strcpy(text, "Textures\\Quality of textures ");
- if ( num == EVENT_INTERFACE_GADGET ) strcpy(text, "Num of decorative objects\\Number of purely ornamental objects");
- if ( num == EVENT_INTERFACE_RAIN ) strcpy(text, "Particles in the interface\\Steam clouds and sparks in the interface");
- if ( num == EVENT_INTERFACE_GLINT ) strcpy(text, "Reflections on the buttons \\Shiny buttons");
- if ( num == EVENT_INTERFACE_TOOLTIP) strcpy(text, "Help balloons\\Explain the function of the buttons");
- if ( num == EVENT_INTERFACE_MOVIES ) strcpy(text, "Film sequences\\Films before and after the missions");
- if ( num == EVENT_INTERFACE_NICERST) strcpy(text, "Exit film\\Film at the exit of exercises");
- if ( num == EVENT_INTERFACE_HIMSELF) strcpy(text, "Friendly fire\\Your shooting can damage your own objects ");
- if ( num == EVENT_INTERFACE_SCROLL ) strcpy(text, "Scrolling\\Scrolling when the mouse touches right or left border");
- if ( num == EVENT_INTERFACE_INVERTX) strcpy(text, "Mouse inversion X\\Inversion of the scrolling direction on the X axis");
- if ( num == EVENT_INTERFACE_INVERTY) strcpy(text, "Mouse inversion Y\\Inversion of the scrolling direction on the Y axis");
- if ( num == EVENT_INTERFACE_EFFECT ) strcpy(text, "Quake at explosions\\The screen shakes at explosions");
- if ( num == EVENT_INTERFACE_MOUSE ) strcpy(text, "Mouse shadow\\Gives the mouse a shadow");
- if ( num == EVENT_INTERFACE_EDITMODE) strcpy(text, "Automatic indent\\When program editing");
- if ( num == EVENT_INTERFACE_EDITVALUE)strcpy(text, "Big indent\\Indent 2 or 4 spaces per level defined by braces");
- if ( num == EVENT_INTERFACE_SOLUCE4) strcpy(text, "Access to solutions\\Show program \"4: Solution\" in the exercises"); //**
-
- if ( num == EVENT_INTERFACE_KDEF ) strcpy(text, "Standard controls\\Standard key functions");
- if ( num == EVENT_INTERFACE_KLEFT ) strcpy(text, "Turn left\\turns the bot to the left");
- if ( num == EVENT_INTERFACE_KRIGHT ) strcpy(text, "Turn right\\turns the bot to the right");
- if ( num == EVENT_INTERFACE_KUP ) strcpy(text, "Forward\\Moves forward");
- if ( num == EVENT_INTERFACE_KDOWN ) strcpy(text, "Backward\\Moves backward");
- if ( num == EVENT_INTERFACE_KGUP ) strcpy(text, "Climb\\Increases the power of the jet");
- if ( num == EVENT_INTERFACE_KGDOWN ) strcpy(text, "Descend\\Reduces the power of the jet");
- if ( num == EVENT_INTERFACE_KCAMERA) strcpy(text, "Change camera\\Switches between onboard camera and following camera");
- if ( num == EVENT_INTERFACE_KDESEL ) strcpy(text, "Previous object\\Selects the previous object");
- if ( num == EVENT_INTERFACE_KACTION) strcpy(text, "Standard action\\Standard action of the bot (take/grab, shoot, sniff, etc)");
- if ( num == EVENT_INTERFACE_KNEAR ) strcpy(text, "Camera closer\\Moves the camera forward");
- if ( num == EVENT_INTERFACE_KAWAY ) strcpy(text, "Camera back\\Moves the camera backward");
- if ( num == EVENT_INTERFACE_KNEXT ) strcpy(text, "Next object\\Selects the next object");
- if ( num == EVENT_INTERFACE_KHUMAN ) strcpy(text, "Select the astronaut\\Selects the astronaut");
- if ( num == EVENT_INTERFACE_KQUIT ) strcpy(text, "Quit\\Quit the current mission or exercise");
- if ( num == EVENT_INTERFACE_KHELP ) strcpy(text, "Instructions\\Shows the instructions for the current mission");
- if ( num == EVENT_INTERFACE_KPROG ) strcpy(text, "Programming help\\Gives more detailed help with programming");
- if ( num == EVENT_INTERFACE_KCBOT ) strcpy(text, "Key word help\\More detailed help about key words");
- if ( num == EVENT_INTERFACE_KVISIT ) strcpy(text, "Origin of last message\\Shows where the last message was sent from");
- if ( num == EVENT_INTERFACE_KSPEED10) strcpy(text, "Speed 1.0x\\Normal speed");
- if ( num == EVENT_INTERFACE_KSPEED15) strcpy(text, "Speed 1.5x\\1.5 times faster");
- if ( num == EVENT_INTERFACE_KSPEED20) strcpy(text, "Speed 2.0x\\Double speed");
- if ( num == EVENT_INTERFACE_KSPEED30) strcpy(text, "Speed 3.0x\\Three times faster");
-
- if ( num == EVENT_INTERFACE_VOLSOUND) strcpy(text, "Sound effects:\\Volume of engines, voice, shooting, etc.");
- if ( num == EVENT_INTERFACE_VOLMUSIC) strcpy(text, "Background sound :\\Volume of audio tracks on the CD");
- if ( num == EVENT_INTERFACE_SOUND3D) strcpy(text, "3D sound\\3D positioning of the sound");
-
- if ( num == EVENT_INTERFACE_MIN ) strcpy(text, "Lowest\\Minimum graphic quality (highest frame rate)");
- if ( num == EVENT_INTERFACE_NORM ) strcpy(text, "Normal\\Normal graphic quality");
- if ( num == EVENT_INTERFACE_MAX ) strcpy(text, "Highest\\Highest graphic quality (lowest frame rate)");
-
- if ( num == EVENT_INTERFACE_SILENT ) strcpy(text, "Mute\\No sound");
- if ( num == EVENT_INTERFACE_NOISY ) strcpy(text, "Normal\\Normal sound volume");
-
- if ( num == EVENT_INTERFACE_JOYSTICK) strcpy(text, "Use a joystick\\Joystick or keyboard");
- if ( num == EVENT_INTERFACE_SOLUCE ) strcpy(text, "Access to solution\\Shows the solution (detailed instructions for missions)");
-
- if ( num == EVENT_INTERFACE_NEDIT ) strcpy(text, "\\New player name");
- if ( num == EVENT_INTERFACE_NOK ) strcpy(text, "OK\\Choose the selected player");
- if ( num == EVENT_INTERFACE_NCANCEL) strcpy(text, "Cancel\\Keep current player name");
- if ( num == EVENT_INTERFACE_NDELETE) strcpy(text, "Delete player\\Deletes the player from the list");
- if ( num == EVENT_INTERFACE_NLABEL ) strcpy(text, "Player name");
-
- if ( num == EVENT_INTERFACE_IOWRITE) strcpy(text, "Save\\Saves the current mission");
- if ( num == EVENT_INTERFACE_IOREAD ) strcpy(text, "Load\\Loads the selected mission");
- if ( num == EVENT_INTERFACE_IOLIST ) strcpy(text, "List of saved missions");
- if ( num == EVENT_INTERFACE_IOLABEL) strcpy(text, "Filename:");
- if ( num == EVENT_INTERFACE_IONAME ) strcpy(text, "Mission name");
- if ( num == EVENT_INTERFACE_IOIMAGE) strcpy(text, "Photography");
- if ( num == EVENT_INTERFACE_IODELETE) strcpy(text, "Delete\\Deletes the selected file");
-
- if ( num == EVENT_INTERFACE_PERSO ) strcpy(text, "Appearance\\Choose your appearance");
- if ( num == EVENT_INTERFACE_POK ) strcpy(text, "OK");
- if ( num == EVENT_INTERFACE_PCANCEL) strcpy(text, "Cancel");
- if ( num == EVENT_INTERFACE_PDEF ) strcpy(text, "Standard\\Standard appearance settings");
- if ( num == EVENT_INTERFACE_PHEAD ) strcpy(text, "Head\\Face and hair");
- if ( num == EVENT_INTERFACE_PBODY ) strcpy(text, "Suit\\Astronaut suit");
- if ( num == EVENT_INTERFACE_PLROT ) strcpy(text, "\\Turn left");
- if ( num == EVENT_INTERFACE_PRROT ) strcpy(text, "\\Turn right");
- if ( num == EVENT_INTERFACE_PCRa ) strcpy(text, "Red");
- if ( num == EVENT_INTERFACE_PCGa ) strcpy(text, "Green");
- if ( num == EVENT_INTERFACE_PCBa ) strcpy(text, "Blue");
- if ( num == EVENT_INTERFACE_PCRb ) strcpy(text, "Red");
- if ( num == EVENT_INTERFACE_PCGb ) strcpy(text, "Green");
- if ( num == EVENT_INTERFACE_PCBb ) strcpy(text, "Blue");
- if ( num == EVENT_INTERFACE_PFACE1 ) strcpy(text, "\\Face 1");
- if ( num == EVENT_INTERFACE_PFACE2 ) strcpy(text, "\\Face 4");
- if ( num == EVENT_INTERFACE_PFACE3 ) strcpy(text, "\\Face 3");
- if ( num == EVENT_INTERFACE_PFACE4 ) strcpy(text, "\\Face 2");
- if ( num == EVENT_INTERFACE_PGLASS0) strcpy(text, "\\No eyeglasses");
- if ( num == EVENT_INTERFACE_PGLASS1) strcpy(text, "\\Eyeglasses 1");
- if ( num == EVENT_INTERFACE_PGLASS2) strcpy(text, "\\Eyeglasses 2");
- if ( num == EVENT_INTERFACE_PGLASS3) strcpy(text, "\\Eyeglasses 3");
- if ( num == EVENT_INTERFACE_PGLASS4) strcpy(text, "\\Eyeglasses 4");
- if ( num == EVENT_INTERFACE_PGLASS5) strcpy(text, "\\Eyeglasses 5");
-
- if ( num == EVENT_OBJECT_DESELECT ) strcpy(text, "Previous selection (\\key desel;)");
- if ( num == EVENT_OBJECT_LEFT ) strcpy(text, "Turn left (\\key left;)");
- if ( num == EVENT_OBJECT_RIGHT ) strcpy(text, "Turn right (\\key right;)");
- if ( num == EVENT_OBJECT_UP ) strcpy(text, "Forward (\\key up;)");
- if ( num == EVENT_OBJECT_DOWN ) strcpy(text, "Backward (\\key down;)");
- if ( num == EVENT_OBJECT_GASUP ) strcpy(text, "Up (\\key gup;)");
- if ( num == EVENT_OBJECT_GASDOWN ) strcpy(text, "Down (\\key gdown;)");
- if ( num == EVENT_OBJECT_HTAKE ) strcpy(text, "Grab or drop (\\key action;)");
- if ( num == EVENT_OBJECT_MTAKE ) strcpy(text, "Grab or drop (\\key action;)");
- if ( num == EVENT_OBJECT_MFRONT ) strcpy(text, "..in front");
- if ( num == EVENT_OBJECT_MBACK ) strcpy(text, "..behind");
- if ( num == EVENT_OBJECT_MPOWER ) strcpy(text, "..power cell");
- if ( num == EVENT_OBJECT_BHELP ) strcpy(text, "Instructions for the mission (\\key help;)");
- if ( num == EVENT_OBJECT_BTAKEOFF ) strcpy(text, "Take off to finish the mission");
- if ( num == EVENT_OBJECT_BDERRICK ) strcpy(text, "Build a derrick");
- if ( num == EVENT_OBJECT_BSTATION ) strcpy(text, "Build a power station");
- if ( num == EVENT_OBJECT_BFACTORY ) strcpy(text, "Build a bot factory");
- if ( num == EVENT_OBJECT_BREPAIR ) strcpy(text, "Build a repair center");
- if ( num == EVENT_OBJECT_BCONVERT ) strcpy(text, "Build a converter");
- if ( num == EVENT_OBJECT_BTOWER ) strcpy(text, "Build a defense tower");
- if ( num == EVENT_OBJECT_BRESEARCH ) strcpy(text, "Build a research center");
- if ( num == EVENT_OBJECT_BRADAR ) strcpy(text, "Build a radar station");
- if ( num == EVENT_OBJECT_BENERGY ) strcpy(text, "Build a power cell factory");
- if ( num == EVENT_OBJECT_BLABO ) strcpy(text, "Build an autolab");
- if ( num == EVENT_OBJECT_BNUCLEAR ) strcpy(text, "Build a nuclear power plant");
- if ( num == EVENT_OBJECT_BPARA ) strcpy(text, "Build a lightning conductor");
- if ( num == EVENT_OBJECT_BINFO ) strcpy(text, "Build a exchange post");
- if ( num == EVENT_OBJECT_GFLAT ) strcpy(text, "Show if the ground is flat");
- if ( num == EVENT_OBJECT_FCREATE ) strcpy(text, "Plant a flag");
- if ( num == EVENT_OBJECT_FDELETE ) strcpy(text, "Remove a flag");
- if ( num == EVENT_OBJECT_FCOLORb ) strcpy(text, "\\Blue flags");
- if ( num == EVENT_OBJECT_FCOLORr ) strcpy(text, "\\Red flags");
- if ( num == EVENT_OBJECT_FCOLORg ) strcpy(text, "\\Green flags");
- if ( num == EVENT_OBJECT_FCOLORy ) strcpy(text, "\\Yellow flags");
- if ( num == EVENT_OBJECT_FCOLORv ) strcpy(text, "\\Violet flags");
- if ( num == EVENT_OBJECT_FACTORYfa ) strcpy(text, "Build a winged grabber");
- if ( num == EVENT_OBJECT_FACTORYta ) strcpy(text, "Build a tracked grabber");
- if ( num == EVENT_OBJECT_FACTORYwa ) strcpy(text, "Build a wheeled grabber");
- if ( num == EVENT_OBJECT_FACTORYia ) strcpy(text, "Build a legged grabber");
- if ( num == EVENT_OBJECT_FACTORYfc ) strcpy(text, "Build a winged shooter");
- if ( num == EVENT_OBJECT_FACTORYtc ) strcpy(text, "Build a tracked shooter");
- if ( num == EVENT_OBJECT_FACTORYwc ) strcpy(text, "Build a wheeled shooter");
- if ( num == EVENT_OBJECT_FACTORYic ) strcpy(text, "Build a legged shooter");
- if ( num == EVENT_OBJECT_FACTORYfi ) strcpy(text, "Build a winged orga shooter");
- if ( num == EVENT_OBJECT_FACTORYti ) strcpy(text, "Build a tracked orga shooter");
- if ( num == EVENT_OBJECT_FACTORYwi ) strcpy(text, "Build a wheeled orga shooter");
- if ( num == EVENT_OBJECT_FACTORYii ) strcpy(text, "Build a legged orga shooter");
- if ( num == EVENT_OBJECT_FACTORYfs ) strcpy(text, "Build a winged sniffer");
- if ( num == EVENT_OBJECT_FACTORYts ) strcpy(text, "Build a tracked sniffer");
- if ( num == EVENT_OBJECT_FACTORYws ) strcpy(text, "Build a wheeled sniffer");
- if ( num == EVENT_OBJECT_FACTORYis ) strcpy(text, "Build a legged sniffer");
- if ( num == EVENT_OBJECT_FACTORYrt ) strcpy(text, "Build a thumper");
- if ( num == EVENT_OBJECT_FACTORYrc ) strcpy(text, "Build a phazer shooter");
- if ( num == EVENT_OBJECT_FACTORYrr ) strcpy(text, "Build a recycler");
- if ( num == EVENT_OBJECT_FACTORYrs ) strcpy(text, "Build a shielder");
- if ( num == EVENT_OBJECT_FACTORYsa ) strcpy(text, "Build a subber");
- if ( num == EVENT_OBJECT_RTANK ) strcpy(text, "Run research program for tracked bots");
- if ( num == EVENT_OBJECT_RFLY ) strcpy(text, "Run research program for winged bots");
- if ( num == EVENT_OBJECT_RTHUMP ) strcpy(text, "Run research program for thumper");
- if ( num == EVENT_OBJECT_RCANON ) strcpy(text, "Run research program for shooter");
- if ( num == EVENT_OBJECT_RTOWER ) strcpy(text, "Run research program for defense tower");
- if ( num == EVENT_OBJECT_RPHAZER ) strcpy(text, "Run research program for phazer shooter");
- if ( num == EVENT_OBJECT_RSHIELD ) strcpy(text, "Run research program for shielder");
- if ( num == EVENT_OBJECT_RATOMIC ) strcpy(text, "Run research program for nuclear power");
- if ( num == EVENT_OBJECT_RiPAW ) strcpy(text, "Run research program for legged bots");
- if ( num == EVENT_OBJECT_RiGUN ) strcpy(text, "Run research program for orga shooter");
- if ( num == EVENT_OBJECT_RESET ) strcpy(text, "Return to start");
- if ( num == EVENT_OBJECT_SEARCH ) strcpy(text, "Sniff (\\key action;)");
- if ( num == EVENT_OBJECT_TERRAFORM ) strcpy(text, "Thump (\\key action;)");
- if ( num == EVENT_OBJECT_FIRE ) strcpy(text, "Shoot (\\key action;)");
- if ( num == EVENT_OBJECT_RECOVER ) strcpy(text, "Recycle (\\key action;)");
- if ( num == EVENT_OBJECT_BEGSHIELD ) strcpy(text, "Extend shield (\\key action;)");
- if ( num == EVENT_OBJECT_ENDSHIELD ) strcpy(text, "Withdraw shield (\\key action;)");
- if ( num == EVENT_OBJECT_DIMSHIELD ) strcpy(text, "Shield radius");
- if ( num == EVENT_OBJECT_PROGRUN ) strcpy(text, "Execute the selected program");
- if ( num == EVENT_OBJECT_PROGEDIT ) strcpy(text, "Edit the selected program");
- if ( num == EVENT_OBJECT_INFOOK ) strcpy(text, "\\SatCom on standby");
- if ( num == EVENT_OBJECT_DELETE ) strcpy(text, "Destroy the building");
- if ( num == EVENT_OBJECT_GENERGY ) strcpy(text, "Energy level");
- if ( num == EVENT_OBJECT_GSHIELD ) strcpy(text, "Shield level");
- if ( num == EVENT_OBJECT_GRANGE ) strcpy(text, "Jet temperature");
- if ( num == EVENT_OBJECT_GPROGRESS ) strcpy(text, "Still working ...");
- if ( num == EVENT_OBJECT_GRADAR ) strcpy(text, "Number of insects detected");
- if ( num == EVENT_OBJECT_GINFO ) strcpy(text, "Transmitted information");
- if ( num == EVENT_OBJECT_COMPASS ) strcpy(text, "Compass");
-//? if ( num == EVENT_OBJECT_MAP ) strcpy(text, "Mini-map");
- if ( num == EVENT_OBJECT_MAPZOOM ) strcpy(text, "Zoom mini-map");
- if ( num == EVENT_OBJECT_CAMERA ) strcpy(text, "Camera (\\key camera;)");
- if ( num == EVENT_OBJECT_CAMERAleft) strcpy(text, "Camera to left");
- if ( num == EVENT_OBJECT_CAMERAright) strcpy(text, "Camera to right");
- if ( num == EVENT_OBJECT_CAMERAnear) strcpy(text, "Camera nearest");
- if ( num == EVENT_OBJECT_CAMERAaway) strcpy(text, "Camera awayest");
- if ( num == EVENT_OBJECT_HELP ) strcpy(text, "Help about selected object");
- if ( num == EVENT_OBJECT_SOLUCE ) strcpy(text, "Show the solution");
- if ( num == EVENT_OBJECT_SHORTCUT00) strcpy(text, "Switch bots <-> buildings");
- if ( num == EVENT_OBJECT_LIMIT ) strcpy(text, "Show the range");
- if ( num == EVENT_OBJECT_PEN0 ) strcpy(text, "\\Raise the pencil");
- if ( num == EVENT_OBJECT_PEN1 ) strcpy(text, "\\Use the black pencil");
- if ( num == EVENT_OBJECT_PEN2 ) strcpy(text, "\\Use the yellow pencil");
- if ( num == EVENT_OBJECT_PEN3 ) strcpy(text, "\\Use the orange pencil");
- if ( num == EVENT_OBJECT_PEN4 ) strcpy(text, "\\Use the red pencil");
- if ( num == EVENT_OBJECT_PEN5 ) strcpy(text, "\\Use the purple pencil");
- if ( num == EVENT_OBJECT_PEN6 ) strcpy(text, "\\Use the blue pencil");
- if ( num == EVENT_OBJECT_PEN7 ) strcpy(text, "\\Use the green pencil");
- if ( num == EVENT_OBJECT_PEN8 ) strcpy(text, "\\Use the brown pencil");
- if ( num == EVENT_OBJECT_REC ) strcpy(text, "\\Start recording");
- if ( num == EVENT_OBJECT_STOP ) strcpy(text, "\\Stop recording");
- if ( num == EVENT_DT_VISIT0 ||
- num == EVENT_DT_VISIT1 ||
- num == EVENT_DT_VISIT2 ||
- num == EVENT_DT_VISIT3 ||
- num == EVENT_DT_VISIT4 ) strcpy(text, "Show the place");
- if ( num == EVENT_DT_END ) strcpy(text, "Continue");
- if ( num == EVENT_CMD ) strcpy(text, "Command line");
- if ( num == EVENT_SPEED ) strcpy(text, "Game speed");
-
- if ( num == EVENT_HYPER_PREV ) strcpy(text, "Back");
- if ( num == EVENT_HYPER_NEXT ) strcpy(text, "Forward");
- if ( num == EVENT_HYPER_HOME ) strcpy(text, "Home");
- if ( num == EVENT_HYPER_COPY ) strcpy(text, "Copy");
- if ( num == EVENT_HYPER_SIZE1 ) strcpy(text, "Size 1");
- if ( num == EVENT_HYPER_SIZE2 ) strcpy(text, "Size 2");
- if ( num == EVENT_HYPER_SIZE3 ) strcpy(text, "Size 3");
- if ( num == EVENT_HYPER_SIZE4 ) strcpy(text, "Size 4");
- if ( num == EVENT_HYPER_SIZE5 ) strcpy(text, "Size 5");
- if ( num == EVENT_SATCOM_HUSTON ) strcpy(text, "Instructions from Houston");
-#if _TEEN
- if ( num == EVENT_SATCOM_SAT ) strcpy(text, "Dictionnary");
-#else
- if ( num == EVENT_SATCOM_SAT ) strcpy(text, "Satellite report");
-#endif
- if ( num == EVENT_SATCOM_LOADING ) strcpy(text, "Programs dispatched by Houston");
- if ( num == EVENT_SATCOM_OBJECT ) strcpy(text, "List of objects");
- if ( num == EVENT_SATCOM_PROG ) strcpy(text, "Programming help");
- if ( num == EVENT_SATCOM_SOLUCE ) strcpy(text, "Solution");
-
- if ( num == EVENT_STUDIO_OK ) strcpy(text, "OK\\Close program editor and return to game");
- if ( num == EVENT_STUDIO_CANCEL ) strcpy(text, "Cancel\\Cancel all changes");
- if ( num == EVENT_STUDIO_NEW ) strcpy(text, "New");
- if ( num == EVENT_STUDIO_OPEN ) strcpy(text, "Open (Ctrl+o)");
- if ( num == EVENT_STUDIO_SAVE ) strcpy(text, "Save (Ctrl+s)");
- if ( num == EVENT_STUDIO_UNDO ) strcpy(text, "Undo (Ctrl+z)");
- if ( num == EVENT_STUDIO_CUT ) strcpy(text, "Cut (Ctrl+x)");
- if ( num == EVENT_STUDIO_COPY ) strcpy(text, "Copy (Ctrl+c)");
- if ( num == EVENT_STUDIO_PASTE ) strcpy(text, "Paste (Ctrl+v)");
- if ( num == EVENT_STUDIO_SIZE ) strcpy(text, "Font size");
- if ( num == EVENT_STUDIO_TOOL ) strcpy(text, "Instructions (\\key help;)");
- if ( num == EVENT_STUDIO_HELP ) strcpy(text, "Programming help (\\key prog;)");
- if ( num == EVENT_STUDIO_COMPILE ) strcpy(text, "Compile");
- if ( num == EVENT_STUDIO_RUN ) strcpy(text, "Execute/stop");
- if ( num == EVENT_STUDIO_REALTIME ) strcpy(text, "Pause/continue");
- if ( num == EVENT_STUDIO_STEP ) strcpy(text, "One step");
- }
-
- if ( type == RES_OBJECT )
- {
- if ( num == OBJECT_PORTICO ) strcpy(text, "Gantry crane");
- if ( num == OBJECT_BASE ) strcpy(text, "Spaceship");
- if ( num == OBJECT_DERRICK ) strcpy(text, "Derrick");
- if ( num == OBJECT_FACTORY ) strcpy(text, "Bot factory");
- if ( num == OBJECT_REPAIR ) strcpy(text, "Repair center");
- if ( num == OBJECT_DESTROYER ) strcpy(text, "Destroyer");
- if ( num == OBJECT_STATION ) strcpy(text, "Power station");
- if ( num == OBJECT_CONVERT ) strcpy(text, "Converts ore to titanium");
- if ( num == OBJECT_TOWER ) strcpy(text, "Defense tower");
- if ( num == OBJECT_NEST ) strcpy(text, "Nest");
- if ( num == OBJECT_RESEARCH ) strcpy(text, "Research center");
- if ( num == OBJECT_RADAR ) strcpy(text, "Radar station");
- if ( num == OBJECT_INFO ) strcpy(text, "Information exchange post");
-#if _TEEN
- if ( num == OBJECT_ENERGY ) strcpy(text, "Power cell factory");
-#else
- if ( num == OBJECT_ENERGY ) strcpy(text, "Power cell factory");
-#endif
- if ( num == OBJECT_LABO ) strcpy(text, "Autolab");
- if ( num == OBJECT_NUCLEAR ) strcpy(text, "Nuclear power station");
- if ( num == OBJECT_PARA ) strcpy(text, "Lightning conductor");
- if ( num == OBJECT_SAFE ) strcpy(text, "Vault");
- if ( num == OBJECT_HUSTON ) strcpy(text, "Houston Mission Control");
- if ( num == OBJECT_TARGET1 ) strcpy(text, "Target");
- if ( num == OBJECT_TARGET2 ) strcpy(text, "Target");
- if ( num == OBJECT_START ) strcpy(text, "Start");
- if ( num == OBJECT_END ) strcpy(text, "Finish");
- if ( num == OBJECT_STONE ) strcpy(text, "Titanium ore");
- if ( num == OBJECT_URANIUM ) strcpy(text, "Uranium ore");
- if ( num == OBJECT_BULLET ) strcpy(text, "Organic matter");
- if ( num == OBJECT_METAL ) strcpy(text, "Titanium");
- if ( num == OBJECT_POWER ) strcpy(text, "Power cell");
- if ( num == OBJECT_ATOMIC ) strcpy(text, "Nuclear power cell");
- if ( num == OBJECT_BBOX ) strcpy(text, "Black box");
- if ( num == OBJECT_KEYa ) strcpy(text, "Key A");
- if ( num == OBJECT_KEYb ) strcpy(text, "Key B");
- if ( num == OBJECT_KEYc ) strcpy(text, "Key C");
- if ( num == OBJECT_KEYd ) strcpy(text, "Key D");
- if ( num == OBJECT_TNT ) strcpy(text, "Explosive");
- if ( num == OBJECT_BOMB ) strcpy(text, "Fixed mine");
- if ( num == OBJECT_BAG ) strcpy(text, "Survival kit");
- if ( num == OBJECT_WAYPOINT ) strcpy(text, "Checkpoint");
- if ( num == OBJECT_FLAGb ) strcpy(text, "Blue flag");
- if ( num == OBJECT_FLAGr ) strcpy(text, "Red flag");
- if ( num == OBJECT_FLAGg ) strcpy(text, "Green flag");
- if ( num == OBJECT_FLAGy ) strcpy(text, "Yellow flag");
- if ( num == OBJECT_FLAGv ) strcpy(text, "Violet flag");
- if ( num == OBJECT_MARKPOWER ) strcpy(text, "Energy deposit (site for power station)");
- if ( num == OBJECT_MARKURANIUM ) strcpy(text, "Uranium deposit (site for derrick)");
- if ( num == OBJECT_MARKKEYa ) strcpy(text, "Found key A (site for derrick)");
- if ( num == OBJECT_MARKKEYb ) strcpy(text, "Found key B (site for derrick)");
- if ( num == OBJECT_MARKKEYc ) strcpy(text, "Found key C (site for derrick)");
- if ( num == OBJECT_MARKKEYd ) strcpy(text, "Found key D (site for derrick)");
- if ( num == OBJECT_MARKSTONE ) strcpy(text, "Titanium deposit (site for derrick)");
- if ( num == OBJECT_MOBILEft ) strcpy(text, "Practice bot");
- if ( num == OBJECT_MOBILEtt ) strcpy(text, "Practice bot");
- if ( num == OBJECT_MOBILEwt ) strcpy(text, "Practice bot");
- if ( num == OBJECT_MOBILEit ) strcpy(text, "Practice bot");
- if ( num == OBJECT_MOBILEfa ) strcpy(text, "Winged grabber");
- if ( num == OBJECT_MOBILEta ) strcpy(text, "Tracked grabber");
- if ( num == OBJECT_MOBILEwa ) strcpy(text, "Wheeled grabber");
- if ( num == OBJECT_MOBILEia ) strcpy(text, "Legged grabber");
- if ( num == OBJECT_MOBILEfc ) strcpy(text, "Winged shooter");
- if ( num == OBJECT_MOBILEtc ) strcpy(text, "Tracked shooter");
- if ( num == OBJECT_MOBILEwc ) strcpy(text, "Wheeled shooter");
- if ( num == OBJECT_MOBILEic ) strcpy(text, "Legged shooter");
- if ( num == OBJECT_MOBILEfi ) strcpy(text, "Winged orga shooter");
- if ( num == OBJECT_MOBILEti ) strcpy(text, "Tracked orga shooter");
- if ( num == OBJECT_MOBILEwi ) strcpy(text, "Wheeled orga shooter");
- if ( num == OBJECT_MOBILEii ) strcpy(text, "Legged orga shooter");
- if ( num == OBJECT_MOBILEfs ) strcpy(text, "Winged sniffer");
- if ( num == OBJECT_MOBILEts ) strcpy(text, "Tracked sniffer");
- if ( num == OBJECT_MOBILEws ) strcpy(text, "Wheeled sniffer");
- if ( num == OBJECT_MOBILEis ) strcpy(text, "Legged sniffer");
- if ( num == OBJECT_MOBILErt ) strcpy(text, "Thumper");
- if ( num == OBJECT_MOBILErc ) strcpy(text, "Phazer shooter");
- if ( num == OBJECT_MOBILErr ) strcpy(text, "Recycler");
- if ( num == OBJECT_MOBILErs ) strcpy(text, "Shielder");
- if ( num == OBJECT_MOBILEsa ) strcpy(text, "Subber");
- if ( num == OBJECT_MOBILEtg ) strcpy(text, "Target bot");
- if ( num == OBJECT_MOBILEdr ) strcpy(text, "Drawer bot");
- if ( num == OBJECT_HUMAN ) strcpy(text, g_gamerName);
- if ( num == OBJECT_TECH ) strcpy(text, "Engineer");
- if ( num == OBJECT_TOTO ) strcpy(text, "Robbie");
- if ( num == OBJECT_MOTHER ) strcpy(text, "Alien Queen");
- if ( num == OBJECT_ANT ) strcpy(text, "Ant");
- if ( num == OBJECT_SPIDER ) strcpy(text, "Spider");
- if ( num == OBJECT_BEE ) strcpy(text, "Wasp");
- if ( num == OBJECT_WORM ) strcpy(text, "Worm");
- if ( num == OBJECT_EGG ) strcpy(text, "Egg");
- if ( num == OBJECT_RUINmobilew1 ) strcpy(text, "Wreckage");
- if ( num == OBJECT_RUINmobilew2 ) strcpy(text, "Wreckage");
- if ( num == OBJECT_RUINmobilet1 ) strcpy(text, "Wreckage");
- if ( num == OBJECT_RUINmobilet2 ) strcpy(text, "Wreckage");
- if ( num == OBJECT_RUINmobiler1 ) strcpy(text, "Wreckage");
- if ( num == OBJECT_RUINmobiler2 ) strcpy(text, "Wreckage");
- if ( num == OBJECT_RUINfactory ) strcpy(text, "Ruin");
- if ( num == OBJECT_RUINdoor ) strcpy(text, "Ruin");
- if ( num == OBJECT_RUINsupport ) strcpy(text, "Waste");
- if ( num == OBJECT_RUINradar ) strcpy(text, "Ruin");
- if ( num == OBJECT_RUINconvert ) strcpy(text, "Ruin");
- if ( num == OBJECT_RUINbase ) strcpy(text, "Spaceship ruin");
- if ( num == OBJECT_RUINhead ) strcpy(text, "Spaceship ruin");
- if ( num == OBJECT_APOLLO1 ||
- num == OBJECT_APOLLO3 ||
- num == OBJECT_APOLLO4 ||
- num == OBJECT_APOLLO5 ) strcpy(text, "Remains of Apollo mission");
- if ( num == OBJECT_APOLLO2 ) strcpy(text, "Lunar Roving Vehicle");
- }
-
- if ( type == RES_ERR )
- {
- strcpy(text, "Error");
- if ( num == ERR_CMD ) strcpy(text, "Unknown command");
-#if _NEWLOOK
- if ( num == ERR_INSTALL ) strcpy(text, "CeeBot not installed.");
- if ( num == ERR_NOCD ) strcpy(text, "Please insert the CeeBot CD\nand re-run the game.");
-#else
- if ( num == ERR_INSTALL ) strcpy(text, "COLOBOT not installed.");
- if ( num == ERR_NOCD ) strcpy(text, "Please insert the COLOBOT CD\nand re-run the game.");
-#endif
- if ( num == ERR_MANIP_VEH ) strcpy(text, "Inappropriate bot");
- if ( num == ERR_MANIP_FLY ) strcpy(text, "Impossible when flying");
- if ( num == ERR_MANIP_BUSY ) strcpy(text, "Already carrying something");
- if ( num == ERR_MANIP_NIL ) strcpy(text, "Nothing to grab");
- if ( num == ERR_MANIP_MOTOR ) strcpy(text, "Impossible when moving");
- if ( num == ERR_MANIP_OCC ) strcpy(text, "Place occupied");
- if ( num == ERR_MANIP_FRIEND ) strcpy(text, "No other robot");
- if ( num == ERR_MANIP_RADIO ) strcpy(text, "You can not carry a radioactive object");
- if ( num == ERR_MANIP_WATER ) strcpy(text, "You can not carry an object under water");
- if ( num == ERR_MANIP_EMPTY ) strcpy(text, "Nothing to drop");
- if ( num == ERR_BUILD_FLY ) strcpy(text, "Impossible when flying");
- if ( num == ERR_BUILD_WATER ) strcpy(text, "Impossible under water");
- if ( num == ERR_BUILD_ENERGY ) strcpy(text, "Not enough energy");
- if ( num == ERR_BUILD_METALAWAY ) strcpy(text, "Titanium too far away");
- if ( num == ERR_BUILD_METALNEAR ) strcpy(text, "Titanium too close");
- if ( num == ERR_BUILD_METALINEX ) strcpy(text, "No titanium around");
- if ( num == ERR_BUILD_FLAT ) strcpy(text, "Ground not flat enough");
- if ( num == ERR_BUILD_FLATLIT ) strcpy(text, "Flat ground not large enough");
- if ( num == ERR_BUILD_BUSY ) strcpy(text, "Place occupied");
- if ( num == ERR_BUILD_BASE ) strcpy(text, "Too close to space ship");
- if ( num == ERR_BUILD_NARROW ) strcpy(text, "Too close to a building");
- if ( num == ERR_BUILD_MOTOR ) strcpy(text, "Impossible when moving");
- if ( num == ERR_SEARCH_FLY ) strcpy(text, "Impossible when flying");
- if ( num == ERR_SEARCH_VEH ) strcpy(text, "Inappropriate bot");
- if ( num == ERR_SEARCH_MOTOR ) strcpy(text, "Impossible when moving");
- if ( num == ERR_TERRA_VEH ) strcpy(text, "Inappropriate bot");
- if ( num == ERR_TERRA_ENERGY ) strcpy(text, "Not enough energy");
- if ( num == ERR_TERRA_FLOOR ) strcpy(text, "Ground inappropriate");
- if ( num == ERR_TERRA_BUILDING ) strcpy(text, "Building too close");
- if ( num == ERR_TERRA_OBJECT ) strcpy(text, "Object too close");
- if ( num == ERR_RECOVER_VEH ) strcpy(text, "Inappropriate bot");
- if ( num == ERR_RECOVER_ENERGY ) strcpy(text, "Not enough energy");
- if ( num == ERR_RECOVER_NULL ) strcpy(text, "Nothing to recycle");
- if ( num == ERR_SHIELD_VEH ) strcpy(text, "Inappropriate bot");
- if ( num == ERR_SHIELD_ENERGY ) strcpy(text, "No more energy");
- if ( num == ERR_MOVE_IMPOSSIBLE ) strcpy(text, "Error in instruction move");
- if ( num == ERR_FIND_IMPOSSIBLE ) strcpy(text, "Object not found");
- if ( num == ERR_GOTO_IMPOSSIBLE ) strcpy(text, "Goto: inaccessible destination");
- if ( num == ERR_GOTO_ITER ) strcpy(text, "Goto: inaccessible destination");
- if ( num == ERR_GOTO_BUSY ) strcpy(text, "Goto: destination occupied");
- if ( num == ERR_FIRE_VEH ) strcpy(text, "Inappropriate bot");
- if ( num == ERR_FIRE_ENERGY ) strcpy(text, "Not enough energy");
- if ( num == ERR_FIRE_FLY ) strcpy(text, "Impossible when flying");
- if ( num == ERR_CONVERT_EMPTY ) strcpy(text, "No titanium ore to convert");
- if ( num == ERR_DERRICK_NULL ) strcpy(text, "No ore in the subsoil");
- if ( num == ERR_STATION_NULL ) strcpy(text, "No energy in the subsoil");
- if ( num == ERR_TOWER_POWER ) strcpy(text, "No power cell");
- if ( num == ERR_TOWER_ENERGY ) strcpy(text, "No more energy");
- if ( num == ERR_RESEARCH_POWER ) strcpy(text, "No power cell");
- if ( num == ERR_RESEARCH_ENERGY ) strcpy(text, "Not enough energy");
- if ( num == ERR_RESEARCH_TYPE ) strcpy(text, "Inappropriate cell type");
- if ( num == ERR_RESEARCH_ALREADY) strcpy(text, "Research program already performed");
- if ( num == ERR_ENERGY_NULL ) strcpy(text, "No energy in the subsoil");
- if ( num == ERR_ENERGY_LOW ) strcpy(text, "Not enough energy yet");
- if ( num == ERR_ENERGY_EMPTY ) strcpy(text, "No titanium to transform");
- if ( num == ERR_ENERGY_BAD ) strcpy(text, "Transforms only titanium");
- if ( num == ERR_BASE_DLOCK ) strcpy(text, "Doors blocked by a robot or another object ");
- if ( num == ERR_BASE_DHUMAN ) strcpy(text, "You must get on the spaceship to take off ");
- if ( num == ERR_LABO_NULL ) strcpy(text, "Nothing to analyze");
- if ( num == ERR_LABO_BAD ) strcpy(text, "Analyzes only organic matter");
- if ( num == ERR_LABO_ALREADY ) strcpy(text, "Analysis already performed");
- if ( num == ERR_NUCLEAR_NULL ) strcpy(text, "No energy in the subsoil");
- if ( num == ERR_NUCLEAR_LOW ) strcpy(text, "Not yet enough energy");
- if ( num == ERR_NUCLEAR_EMPTY ) strcpy(text, "No uranium to transform");
- if ( num == ERR_NUCLEAR_BAD ) strcpy(text, "Transforms only uranium");
- if ( num == ERR_FACTORY_NULL ) strcpy(text, "No titanium");
- if ( num == ERR_FACTORY_NEAR ) strcpy(text, "Object too close");
- if ( num == ERR_RESET_NEAR ) strcpy(text, "Place occupied");
- if ( num == ERR_INFO_NULL ) strcpy(text, "No information exchange post within range");
- if ( num == ERR_VEH_VIRUS ) strcpy(text, "Program infected by a virus");
- if ( num == ERR_BAT_VIRUS ) strcpy(text, "Infected by a virus, temporarily out of order");
- if ( num == ERR_VEH_POWER ) strcpy(text, "No power cell");
- if ( num == ERR_VEH_ENERGY ) strcpy(text, "No more energy");
- if ( num == ERR_FLAG_FLY ) strcpy(text, "Impossible when flying");
- if ( num == ERR_FLAG_WATER ) strcpy(text, "Impossible when swimming");
- if ( num == ERR_FLAG_MOTOR ) strcpy(text, "Impossible when moving");
- if ( num == ERR_FLAG_BUSY ) strcpy(text, "Impossible when carrying an object");
- if ( num == ERR_FLAG_CREATE ) strcpy(text, "Too many flags of this color (maximum 5)");
- if ( num == ERR_FLAG_PROXY ) strcpy(text, "Too close to an existing flag");
- if ( num == ERR_FLAG_DELETE ) strcpy(text, "No flag nearby");
- if ( num == ERR_MISSION_NOTERM ) strcpy(text, "The mission is not accomplished yet (press \\key help; for more details)");
- if ( num == ERR_DELETEMOBILE ) strcpy(text, "Bot destroyed");
- if ( num == ERR_DELETEBUILDING ) strcpy(text, "Building destroyed");
- if ( num == ERR_TOOMANY ) strcpy(text, "Can not create this, there are too many objects");
- if ( num == ERR_OBLIGATORYTOKEN ) strcpy(text, "\"%s\" missing in this exercise"); //**
- if ( num == ERR_PROHIBITEDTOKEN ) strcpy(text, "Do not use in this exercise"); //**
-
- if ( num == INFO_BUILD ) strcpy(text, "Building completed");
- if ( num == INFO_CONVERT ) strcpy(text, "Titanium available");
- if ( num == INFO_RESEARCH ) strcpy(text, "Research program completed");
- if ( num == INFO_RESEARCHTANK ) strcpy(text, "Plans for tracked robots available ");
- if ( num == INFO_RESEARCHFLY ) strcpy(text, "You can fly with the keys (\\key gup;) and (\\key gdown;)");
- if ( num == INFO_RESEARCHTHUMP ) strcpy(text, "Plans for thumper available");
- if ( num == INFO_RESEARCHCANON ) strcpy(text, "Plans for shooter available");
- if ( num == INFO_RESEARCHTOWER ) strcpy(text, "Plans for defense tower available");
- if ( num == INFO_RESEARCHPHAZER ) strcpy(text, "Plans for phazer shooter available");
- if ( num == INFO_RESEARCHSHIELD ) strcpy(text, "Plans for shielder available");
- if ( num == INFO_RESEARCHATOMIC ) strcpy(text, "Plans for nuclear power plant available");
- if ( num == INFO_FACTORY ) strcpy(text, "New bot available");
- if ( num == INFO_LABO ) strcpy(text, "Analysis performed");
- if ( num == INFO_ENERGY ) strcpy(text, "Power cell available");
- if ( num == INFO_NUCLEAR ) strcpy(text, "Nuclear power cell available");
- if ( num == INFO_FINDING ) strcpy(text, "You found a usable object");
- if ( num == INFO_MARKPOWER ) strcpy(text, "Found a site for power station");
- if ( num == INFO_MARKURANIUM ) strcpy(text, "Found a site for a derrick");
- if ( num == INFO_MARKSTONE ) strcpy(text, "Found a site for a derrick");
- if ( num == INFO_MARKKEYa ) strcpy(text, "Found a site for a derrick");
- if ( num == INFO_MARKKEYb ) strcpy(text, "Found a site for a derrick");
- if ( num == INFO_MARKKEYc ) strcpy(text, "Found a site for a derrick");
- if ( num == INFO_MARKKEYd ) strcpy(text, "Found a site for a derrick");
- if ( num == INFO_WIN ) strcpy(text, "<<< Well done, mission accomplished >>>");
- if ( num == INFO_LOST ) strcpy(text, "<<< Sorry, mission failed >>>");
- if ( num == INFO_LOSTq ) strcpy(text, "<<< Sorry, mission failed >>>");
- if ( num == INFO_WRITEOK ) strcpy(text, "Current mission saved");
- if ( num == INFO_DELETEPATH ) strcpy(text, "Checkpoint crossed");
- if ( num == INFO_DELETEMOTHER ) strcpy(text, "Alien Queen killed");
- if ( num == INFO_DELETEANT ) strcpy(text, "Ant fatally wounded");
- if ( num == INFO_DELETEBEE ) strcpy(text, "Wasp fatally wounded");
- if ( num == INFO_DELETEWORM ) strcpy(text, "Worm fatally wounded");
- if ( num == INFO_DELETESPIDER ) strcpy(text, "Spider fatally wounded");
- if ( num == INFO_BEGINSATCOM ) strcpy(text, "Press \\key help; to read instructions on your SatCom");
- }
-
- if ( type == RES_CBOT )
- {
- strcpy(text, "Error");
- if ( num == TX_OPENPAR ) strcpy(text, "Opening bracket missing");
- if ( num == TX_CLOSEPAR ) strcpy(text, "Closing bracket missing ");
- if ( num == TX_NOTBOOL ) strcpy(text, "The expression must return a boolean value");
- if ( num == TX_UNDEFVAR ) strcpy(text, "Variable not declared");
- if ( num == TX_BADLEFT ) strcpy(text, "Assignment impossible");
- if ( num == TX_ENDOF ) strcpy(text, "Semicolon terminator missing");
- if ( num == TX_OUTCASE ) strcpy(text, "Instruction ""case"" outside a block ""switch""");
- if ( num == TX_NOTERM ) strcpy(text, "Instructions after the final closing brace");
- if ( num == TX_CLOSEBLK ) strcpy(text, "End of block missing");
- if ( num == TX_ELSEWITHOUTIF ) strcpy(text, "Instruction ""else"" without corresponding ""if"" ");
- if ( num == TX_OPENBLK ) strcpy(text, "Opening brace missing ");//début d'un bloc attendu?
- if ( num == TX_BADTYPE ) strcpy(text, "Wrong type for the assignment");
- if ( num == TX_REDEFVAR ) strcpy(text, "A variable can not be declared twice");
- if ( num == TX_BAD2TYPE ) strcpy(text, "The types of the two operands are incompatible ");
- if ( num == TX_UNDEFCALL ) strcpy(text, "Unknown function");
- if ( num == TX_MISDOTS ) strcpy(text, "Sign "" : "" missing");
- if ( num == TX_WHILE ) strcpy(text, "Keyword ""while"" missing");
- if ( num == TX_BREAK ) strcpy(text, "Instruction ""break"" outside a loop");
- if ( num == TX_LABEL ) strcpy(text, "A label must be followed by ""for"", ""while"", ""do"" or ""switch""");
- if ( num == TX_NOLABEL ) strcpy(text, "This label does not exist");// Cette étiquette n'existe pas
- if ( num == TX_NOCASE ) strcpy(text, "Instruction ""case"" missing");
- if ( num == TX_BADNUM ) strcpy(text, "Number missing");
- if ( num == TX_VOID ) strcpy(text, "Void parameter");
- if ( num == TX_NOTYP ) strcpy(text, "Type declaration missing");
- if ( num == TX_NOVAR ) strcpy(text, "Variable name missing");
- if ( num == TX_NOFONC ) strcpy(text, "Function name missing");
- if ( num == TX_OVERPARAM ) strcpy(text, "Too many parameters");
- if ( num == TX_REDEF ) strcpy(text, "Function already exists");
- if ( num == TX_LOWPARAM ) strcpy(text, "Parameters missing ");
- if ( num == TX_BADPARAM ) strcpy(text, "No function with this name accepts this kind of parameter");
- if ( num == TX_NUMPARAM ) strcpy(text, "No function with this name accepts this number of parameters");
- if ( num == TX_NOITEM ) strcpy(text, "This is not a member of this class");
- if ( num == TX_DOT ) strcpy(text, "This object is not a member of a class");
- if ( num == TX_NOCONST ) strcpy(text, "Appropriate constructor missing");
- if ( num == TX_REDEFCLASS ) strcpy(text, "This class already exists");
- if ( num == TX_CLBRK ) strcpy(text, """ ] "" missing");
- if ( num == TX_RESERVED ) strcpy(text, "Reserved keyword of CBOT language");
- if ( num == TX_BADNEW ) strcpy(text, "Bad argument for ""new""");
- if ( num == TX_OPBRK ) strcpy(text, """ [ "" expected");
- if ( num == TX_BADSTRING ) strcpy(text, "String missing");
- if ( num == TX_BADINDEX ) strcpy(text, "Incorrect index type");
- if ( num == TX_PRIVATE ) strcpy(text, "Private element");
- if ( num == TX_NOPUBLIC ) strcpy(text, "Public required");
- if ( num == TX_DIVZERO ) strcpy(text, "Dividing by zero");
- if ( num == TX_NOTINIT ) strcpy(text, "Variable not initialized");
- if ( num == TX_BADTHROW ) strcpy(text, "Negative value rejected by ""throw""");//C'est quoi, ça?
- if ( num == TX_NORETVAL ) strcpy(text, "The function returned no value ");
- if ( num == TX_NORUN ) strcpy(text, "No function running");
- if ( num == TX_NOCALL ) strcpy(text, "Calling an unknown function");
- if ( num == TX_NOCLASS ) strcpy(text, "This class does not exist");
- if ( num == TX_NULLPT ) strcpy(text, "Unknown Object");
- if ( num == TX_OPNAN ) strcpy(text, "Operation impossible with value ""nan""");
- if ( num == TX_OUTARRAY ) strcpy(text, "Access beyond array limit");
- if ( num == TX_STACKOVER ) strcpy(text, "Stack overflow");
- if ( num == TX_DELETEDPT ) strcpy(text, "Illegal object");
- if ( num == TX_FILEOPEN ) strcpy(text, "Can't open file");
- if ( num == TX_NOTOPEN ) strcpy(text, "File not open");
- if ( num == TX_ERRREAD ) strcpy(text, "Read error");
- if ( num == TX_ERRWRITE ) strcpy(text, "Write error");
- }
-
- if ( type == RES_KEY )
- {
- if ( num == 0 ) strcpy(text, "< none >");
- if ( num == VK_LEFT ) strcpy(text, "Arrow left");
- if ( num == VK_RIGHT ) strcpy(text, "Arrow right");
- if ( num == VK_UP ) strcpy(text, "Arrow up");
- if ( num == VK_DOWN ) strcpy(text, "Arrow down");
- if ( num == VK_CANCEL ) strcpy(text, "Control-break");
- if ( num == VK_BACK ) strcpy(text, "<--");
- if ( num == VK_TAB ) strcpy(text, "Tab");
- if ( num == VK_CLEAR ) strcpy(text, "Clear");
- if ( num == VK_RETURN ) strcpy(text, "Enter");
- if ( num == VK_SHIFT ) strcpy(text, "Shift");
- if ( num == VK_CONTROL ) strcpy(text, "Ctrl");
- if ( num == VK_MENU ) strcpy(text, "Alt");
- if ( num == VK_PAUSE ) strcpy(text, "Pause");
- if ( num == VK_CAPITAL ) strcpy(text, "Caps Lock");
- if ( num == VK_ESCAPE ) strcpy(text, "Esc");
- if ( num == VK_SPACE ) strcpy(text, "Space");
- if ( num == VK_PRIOR ) strcpy(text, "Page Up");
- if ( num == VK_NEXT ) strcpy(text, "Page Down");
- if ( num == VK_END ) strcpy(text, "End");
- if ( num == VK_HOME ) strcpy(text, "Home");
- if ( num == VK_SELECT ) strcpy(text, "Select");
- if ( num == VK_EXECUTE ) strcpy(text, "Execute");
- if ( num == VK_SNAPSHOT ) strcpy(text, "Print Scrn");
- if ( num == VK_INSERT ) strcpy(text, "Insert");
- if ( num == VK_DELETE ) strcpy(text, "Delete");
- if ( num == VK_HELP ) strcpy(text, "Help");
- if ( num == VK_LWIN ) strcpy(text, "Left Windows");
- if ( num == VK_RWIN ) strcpy(text, "Right Windows");
- if ( num == VK_APPS ) strcpy(text, "Application key");
- if ( num == VK_NUMPAD0 ) strcpy(text, "NumPad 0");
- if ( num == VK_NUMPAD1 ) strcpy(text, "NumPad 1");
- if ( num == VK_NUMPAD2 ) strcpy(text, "NumPad 2");
- if ( num == VK_NUMPAD3 ) strcpy(text, "NumPad 3");
- if ( num == VK_NUMPAD4 ) strcpy(text, "NumPad 4");
- if ( num == VK_NUMPAD5 ) strcpy(text, "NumPad 5");
- if ( num == VK_NUMPAD6 ) strcpy(text, "NumPad 6");
- if ( num == VK_NUMPAD7 ) strcpy(text, "NumPad 7");
- if ( num == VK_NUMPAD8 ) strcpy(text, "NumPad 8");
- if ( num == VK_NUMPAD9 ) strcpy(text, "NumPad 9");
- if ( num == VK_MULTIPLY ) strcpy(text, "NumPad *");
- if ( num == VK_ADD ) strcpy(text, "NumPad +");
- if ( num == VK_SEPARATOR ) strcpy(text, "NumPad sep");
- if ( num == VK_SUBTRACT ) strcpy(text, "NumPad -");
- if ( num == VK_DECIMAL ) strcpy(text, "NumPad .");
- if ( num == VK_DIVIDE ) strcpy(text, "NumPad /");
- if ( num == VK_F1 ) strcpy(text, "F1");
- if ( num == VK_F2 ) strcpy(text, "F2");
- if ( num == VK_F3 ) strcpy(text, "F3");
- if ( num == VK_F4 ) strcpy(text, "F4");
- if ( num == VK_F5 ) strcpy(text, "F5");
- if ( num == VK_F6 ) strcpy(text, "F6");
- if ( num == VK_F7 ) strcpy(text, "F7");
- if ( num == VK_F8 ) strcpy(text, "F8");
- if ( num == VK_F9 ) strcpy(text, "F9");
- if ( num == VK_F10 ) strcpy(text, "F10");
- if ( num == VK_F11 ) strcpy(text, "F11");
- if ( num == VK_F12 ) strcpy(text, "F12");
- if ( num == VK_F13 ) strcpy(text, "F13");
- if ( num == VK_F14 ) strcpy(text, "F14");
- if ( num == VK_F15 ) strcpy(text, "F15");
- if ( num == VK_F16 ) strcpy(text, "F16");
- if ( num == VK_F17 ) strcpy(text, "F17");
- if ( num == VK_F18 ) strcpy(text, "F18");
- if ( num == VK_F19 ) strcpy(text, "F19");
- if ( num == VK_F20 ) strcpy(text, "F20");
- if ( num == VK_NUMLOCK ) strcpy(text, "Num Lock");
- if ( num == VK_SCROLL ) strcpy(text, "Scroll");
- if ( num == VK_ATTN ) strcpy(text, "Attn");
- if ( num == VK_CRSEL ) strcpy(text, "CrSel");
- if ( num == VK_EXSEL ) strcpy(text, "ExSel");
- if ( num == VK_EREOF ) strcpy(text, "Erase EOF");
- if ( num == VK_PLAY ) strcpy(text, "Play");
- if ( num == VK_ZOOM ) strcpy(text, "Zoom");
- if ( num == VK_PA1 ) strcpy(text, "PA1");
- if ( num == VK_OEM_CLEAR ) strcpy(text, "Clear");
- if ( num == VK_BUTTON1 ) strcpy(text, "Button 1");
- if ( num == VK_BUTTON2 ) strcpy(text, "Button 2");
- if ( num == VK_BUTTON3 ) strcpy(text, "Button 3");
- if ( num == VK_BUTTON4 ) strcpy(text, "Button 4");
- if ( num == VK_BUTTON5 ) strcpy(text, "Button 5");
- if ( num == VK_BUTTON6 ) strcpy(text, "Button 6");
- if ( num == VK_BUTTON7 ) strcpy(text, "Button 7");
- if ( num == VK_BUTTON8 ) strcpy(text, "Button 8");
- if ( num == VK_BUTTON9 ) strcpy(text, "Button 9");
- if ( num == VK_BUTTON10 ) strcpy(text, "Button 10");
- if ( num == VK_BUTTON11 ) strcpy(text, "Button 11");
- if ( num == VK_BUTTON12 ) strcpy(text, "Button 12");
- if ( num == VK_BUTTON13 ) strcpy(text, "Button 13");
- if ( num == VK_BUTTON14 ) strcpy(text, "Button 14");
- if ( num == VK_BUTTON15 ) strcpy(text, "Button 15");
- if ( num == VK_BUTTON16 ) strcpy(text, "Button 16");
- if ( num == VK_BUTTON17 ) strcpy(text, "Button 17");
- if ( num == VK_BUTTON18 ) strcpy(text, "Button 18");
- if ( num == VK_BUTTON19 ) strcpy(text, "Button 19");
- if ( num == VK_BUTTON20 ) strcpy(text, "Button 20");
- if ( num == VK_BUTTON21 ) strcpy(text, "Button 21");
- if ( num == VK_BUTTON22 ) strcpy(text, "Button 22");
- if ( num == VK_BUTTON23 ) strcpy(text, "Button 23");
- if ( num == VK_BUTTON24 ) strcpy(text, "Button 24");
- if ( num == VK_BUTTON25 ) strcpy(text, "Button 25");
- if ( num == VK_BUTTON26 ) strcpy(text, "Button 26");
- if ( num == VK_BUTTON27 ) strcpy(text, "Button 27");
- if ( num == VK_BUTTON28 ) strcpy(text, "Button 28");
- if ( num == VK_BUTTON29 ) strcpy(text, "Button 29");
- if ( num == VK_BUTTON30 ) strcpy(text, "Button 30");
- if ( num == VK_BUTTON31 ) strcpy(text, "Button 31");
- if ( num == VK_BUTTON32 ) strcpy(text, "Button 32");
- if ( num == VK_WHEELUP ) strcpy(text, "Wheel up");
- if ( num == VK_WHEELDOWN ) strcpy(text, "Wheel down");
- }
-#endif
-
-#if _FRENCH
- if ( type == RES_TEXT )
- {
- #if _FULL
- if ( num == RT_VERSION_ID ) strcpy(text, "1.18 /f");
- #endif
- #if _NET
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A 1.18");
- #endif
- #if _SCHOOL & _EDU
- #if _TEEN
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen EDU 1.18");
- #else
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A EDU 1.18");
- #endif
- #endif
- #if _SCHOOL & _PERSO
- #if _TEEN
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen PERSO 1.18");
- #else
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A PERSO 1.18");
- #endif
- #endif
- #if _SCHOOL & _CEEBOTDEMO
- #if _TEEN
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen DEMO 1.18");
- #else
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A DEMO 1.18");
- #endif
- #endif
- #if _DEMO
- if ( num == RT_VERSION_ID ) strcpy(text, "Demo 1.18 /f");
- #endif
- if ( num == RT_DISINFO_TITLE ) strcpy(text, "SatCom");
- if ( num == RT_WINDOW_MAXIMIZED ) strcpy(text, "Taille maximale");
- if ( num == RT_WINDOW_MINIMIZED ) strcpy(text, "Taille réduite");
- if ( num == RT_WINDOW_STANDARD ) strcpy(text, "Taille normale");
- if ( num == RT_WINDOW_CLOSE ) strcpy(text, "Fermer");
-
- if ( num == RT_STUDIO_TITLE ) strcpy(text, "Edition du programme");
- if ( num == RT_SCRIPT_NEW ) strcpy(text, "Nouveau");
- if ( num == RT_NAME_DEFAULT ) strcpy(text, "Joueur");
- if ( num == RT_IO_NEW ) strcpy(text, "Nouveau ...");
- if ( num == RT_KEY_OR ) strcpy(text, " ou ");
-
-#if _NEWLOOK
- if ( num == RT_TITLE_BASE ) strcpy(text, "CeeBot");
- if ( num == RT_TITLE_INIT ) strcpy(text, "CeeBot");
-#else
- if ( num == RT_TITLE_BASE ) strcpy(text, "COLOBOT");
- if ( num == RT_TITLE_INIT ) strcpy(text, "COLOBOT");
-#endif
- if ( num == RT_TITLE_TRAINER ) strcpy(text, "Programmation");
- if ( num == RT_TITLE_DEFI ) strcpy(text, "Défis");
- if ( num == RT_TITLE_MISSION ) strcpy(text, "Missions");
- if ( num == RT_TITLE_FREE ) strcpy(text, "Jeu libre");
- if ( num == RT_TITLE_TEEN ) strcpy(text, "Jeu libre");
- if ( num == RT_TITLE_USER ) strcpy(text, "Niveaux supplémentaires");
- if ( num == RT_TITLE_PROTO ) strcpy(text, "Prototypes");
- if ( num == RT_TITLE_SETUP ) strcpy(text, "Options");
- if ( num == RT_TITLE_NAME ) strcpy(text, "Nom du joueur");
- if ( num == RT_TITLE_PERSO ) strcpy(text, "Personnalisation de votre apparence");
- if ( num == RT_TITLE_WRITE ) strcpy(text, "Enregistrement de la mission en cours");
- if ( num == RT_TITLE_READ ) strcpy(text, "Chargement d'une mission enregistrée");
-
- if ( num == RT_PLAY_CHAPt ) strcpy(text, " Liste des chapitres :");
- if ( num == RT_PLAY_CHAPd ) strcpy(text, " Liste des chapitres :");
- if ( num == RT_PLAY_CHAPm ) strcpy(text, " Liste des planètes :");
- if ( num == RT_PLAY_CHAPf ) strcpy(text, " Liste des planètes :");
- if ( num == RT_PLAY_CHAPu ) strcpy(text, " Niveaux supplémentaires :");
- if ( num == RT_PLAY_CHAPp ) strcpy(text, " Liste des planètes :");
- if ( num == RT_PLAY_CHAPte ) strcpy(text, " Liste des chapitres :");
- if ( num == RT_PLAY_LISTt ) strcpy(text, " Liste des exercices du chapitre :");
- if ( num == RT_PLAY_LISTd ) strcpy(text, " Liste des défis du chapitre :");
- if ( num == RT_PLAY_LISTm ) strcpy(text, " Liste des missions du chapitre :");
- if ( num == RT_PLAY_LISTf ) strcpy(text, " Liste des jeux libres du chapitre :");
- if ( num == RT_PLAY_LISTu ) strcpy(text, " Missions du niveau :");
- if ( num == RT_PLAY_LISTp ) strcpy(text, " Liste des prototypes du chapitre :");
- if ( num == RT_PLAY_LISTk ) strcpy(text, " Liste des jeux libres du chapitre :");
- if ( num == RT_PLAY_RESUME ) strcpy(text, " Résumé :");
-
- if ( num == RT_SETUP_DEVICE ) strcpy(text, " Pilotes :");
- if ( num == RT_SETUP_MODE ) strcpy(text, " Résolutions :");
- if ( num == RT_SETUP_KEY1 ) strcpy(text, "1) Cliquez d'abord sur la touche à redéfinir.");
- if ( num == RT_SETUP_KEY2 ) strcpy(text, "2) Appuyez ensuite sur la nouvelle touche souhaitée.");
-
- if ( num == RT_PERSO_FACE ) strcpy(text, "Type de visage :");
- if ( num == RT_PERSO_GLASSES ) strcpy(text, "Lunettes :");
- if ( num == RT_PERSO_HAIR ) strcpy(text, "Couleur des cheveux :");
- if ( num == RT_PERSO_COMBI ) strcpy(text, "Couleur de la combinaison :");
- if ( num == RT_PERSO_BAND ) strcpy(text, "Couleur des bandes :");
-
-#if _NEWLOOK
- if ( num == RT_DIALOG_TITLE ) strcpy(text, "CeeBot");
- if ( num == RT_DIALOG_QUIT ) strcpy(text, "Voulez-vous quitter CeeBot ?");
- if ( num == RT_DIALOG_YESQUIT ) strcpy(text, "Quitter\\Quitter CeeBot");
-#else
- if ( num == RT_DIALOG_TITLE ) strcpy(text, "COLOBOT");
- if ( num == RT_DIALOG_QUIT ) strcpy(text, "Voulez-vous quitter COLOBOT ?");
- if ( num == RT_DIALOG_YESQUIT ) strcpy(text, "Quitter\\Quitter COLOBOT");
-#endif
- if ( num == RT_DIALOG_ABORT ) strcpy(text, "Quitter la mission ?");
- if ( num == RT_DIALOG_YES ) strcpy(text, "Abandonner\\Abandonner la mission en cours");
- if ( num == RT_DIALOG_NO ) strcpy(text, "Continuer\\Continuer la mission en cours");
- if ( num == RT_DIALOG_NOQUIT ) strcpy(text, "Continuer\\Continuer de jouer");
- if ( num == RT_DIALOG_DELOBJ ) strcpy(text, "Voulez-vous vraiment détruire le bâtiment sélectionné ?");
- if ( num == RT_DIALOG_DELGAME ) strcpy(text, "Voulez-vous détruire les sauvegardes de %s ?");
- if ( num == RT_DIALOG_YESDEL ) strcpy(text, "Détruire");
- if ( num == RT_DIALOG_NODEL ) strcpy(text, "Annuler");
- if ( num == RT_DIALOG_LOADING ) strcpy(text, "CHARGEMENT");
-
- if ( num == RT_STUDIO_LISTTT ) strcpy(text, "Aide sur le mot-clé (\\key cbot;)");
- if ( num == RT_STUDIO_COMPOK ) strcpy(text, "Compilation ok (0 erreur)");
- if ( num == RT_STUDIO_PROGSTOP ) strcpy(text, "Programme terminé");
-
- if ( num == RT_SATCOM_LIST ) strcpy(text, "\\b;Listes des objets\n");
- if ( num == RT_SATCOM_BOT ) strcpy(text, "\\b;Listes des robots\n");
- if ( num == RT_SATCOM_BUILDING ) strcpy(text, "\\b;Listes des bâtiments\n");
- if ( num == RT_SATCOM_FRET ) strcpy(text, "\\b;Listes des objets transportables\n");
- if ( num == RT_SATCOM_ALIEN ) strcpy(text, "\\b;Listes des ennemis\n");
- if ( num == RT_SATCOM_NULL ) strcpy(text, "\\c; (aucun)\\n;\n");
- if ( num == RT_SATCOM_ERROR1 ) strcpy(text, "\\b;Erreur\n");
- if ( num == RT_SATCOM_ERROR2 ) strcpy(text, "Liste non disponible sans \\l;radar\\u object\\radar; !\n");
-
- if ( num == RT_IO_OPEN ) strcpy(text, "Ouvrir");
- if ( num == RT_IO_SAVE ) strcpy(text, "Enregistrer");
- if ( num == RT_IO_LIST ) strcpy(text, "Dossier: %s");
- if ( num == RT_IO_NAME ) strcpy(text, "Nom:");
- if ( num == RT_IO_DIR ) strcpy(text, "Dans:");
- if ( num == RT_IO_PRIVATE ) strcpy(text, "Privé\\Dossier privé");
- if ( num == RT_IO_PUBLIC ) strcpy(text, "Public\\Dossier commun à tous les joueurs");
-
- if ( num == RT_GENERIC_DEV1 ) strcpy(text, "Développé par :");
- if ( num == RT_GENERIC_DEV2 ) strcpy(text, "www.epsitec.com");
-#if _SCHOOL
- if ( num == RT_GENERIC_EDIT1 ) strcpy(text, " ");
- if ( num == RT_GENERIC_EDIT2 ) strcpy(text, " ");
-#else
- //?if ( num == RT_GENERIC_EDIT1 ) strcpy(text, "Version française éditée par :");
- //?if ( num == RT_GENERIC_EDIT2 ) strcpy(text, "www.alsyd.com");
- if ( num == RT_GENERIC_EDIT1 ) strcpy(text, " ");
- if ( num == RT_GENERIC_EDIT2 ) strcpy(text, " ");
-#endif
-
- if ( num == RT_INTERFACE_REC ) strcpy(text, "Enregistreur");
- }
-
- if ( type == RES_EVENT )
- {
- if ( num == EVENT_BUTTON_OK ) strcpy(text, "D'accord");
- if ( num == EVENT_BUTTON_CANCEL ) strcpy(text, "Annuler");
- if ( num == EVENT_BUTTON_NEXT ) strcpy(text, "Suivant");
- if ( num == EVENT_BUTTON_PREV ) strcpy(text, "Précédent");
- if ( num == EVENT_BUTTON_QUIT ) strcpy(text, "Menu (\\key quit;)");
-
- if ( num == EVENT_DIALOG_OK ) strcpy(text, "D'accord");
- if ( num == EVENT_DIALOG_CANCEL ) strcpy(text, "Annuler");
-
- if ( num == EVENT_INTERFACE_TRAINER) strcpy(text, "Programmation\\Exercices de programmation");
- if ( num == EVENT_INTERFACE_DEFI ) strcpy(text, "Défis\\Défis de programmation");
- if ( num == EVENT_INTERFACE_MISSION) strcpy(text, "Missions\\La grande aventure");
- if ( num == EVENT_INTERFACE_FREE ) strcpy(text, "Jeu libre\\Jeu libre sans but précis");
- if ( num == EVENT_INTERFACE_TEEN ) strcpy(text, "Jeu libre\\Jeu libre sans but précis");
- if ( num == EVENT_INTERFACE_USER ) strcpy(text, "Suppl.\\Niveaux supplémentaires");
- if ( num == EVENT_INTERFACE_PROTO ) strcpy(text, "Proto\\Prototypes en cours d'élaboration");
- if ( num == EVENT_INTERFACE_NAME ) strcpy(text, "Autre joueur\\Choix du nom du joueur");
- if ( num == EVENT_INTERFACE_SETUP ) strcpy(text, "Options\\Réglages");
- if ( num == EVENT_INTERFACE_AGAIN ) strcpy(text, "Recommencer\\Recommencer la mission au début");
- if ( num == EVENT_INTERFACE_WRITE ) strcpy(text, "Enregistrer\\Enregistrer la mission en cours");
- if ( num == EVENT_INTERFACE_READ ) strcpy(text, "Charger\\Charger une mission enregistrée");
-#if _NEWLOOK
- if ( num == EVENT_INTERFACE_ABORT ) strcpy(text, "\\Retourner dans CeeBot");
- if ( num == EVENT_INTERFACE_QUIT ) strcpy(text, "Quitter\\Quitter CeeBot");
-#else
- if ( num == EVENT_INTERFACE_ABORT ) strcpy(text, "\\Retourner dans COLOBOT");
- if ( num == EVENT_INTERFACE_QUIT ) strcpy(text, "Quitter\\Quitter COLOBOT");
-#endif
- if ( num == EVENT_INTERFACE_BACK ) strcpy(text, "<< Retour \\Retour au niveau précédent");
- if ( num == EVENT_INTERFACE_PLAY ) strcpy(text, "Jouer ...\\Démarrer l'action");
- if ( num == EVENT_INTERFACE_SETUPd ) strcpy(text, "Affichage\\Pilote et résolution d'affichage");
- if ( num == EVENT_INTERFACE_SETUPg ) strcpy(text, "Graphique\\Options graphiques");
- if ( num == EVENT_INTERFACE_SETUPp ) strcpy(text, "Jeu\\Options de jouabilité");
- if ( num == EVENT_INTERFACE_SETUPc ) strcpy(text, "Commandes\\Touches du clavier");
- if ( num == EVENT_INTERFACE_SETUPs ) strcpy(text, "Son\\Volumes bruitages & musiques");
- if ( num == EVENT_INTERFACE_DEVICE ) strcpy(text, "Unité");
- if ( num == EVENT_INTERFACE_RESOL ) strcpy(text, "Résolution");
- if ( num == EVENT_INTERFACE_FULL ) strcpy(text, "Plein écran\\Plein écran ou fenêtré");
- if ( num == EVENT_INTERFACE_APPLY ) strcpy(text, "Appliquer les changements\\Active les changements effectués");
-
- if ( num == EVENT_INTERFACE_TOTO ) strcpy(text, "Robbie\\Votre assistant");
- if ( num == EVENT_INTERFACE_SHADOW ) strcpy(text, "Ombres\\Ombres projetées au sol");
- if ( num == EVENT_INTERFACE_GROUND ) strcpy(text, "Marques sur le sol\\Marques dessinées sur le sol");
- if ( num == EVENT_INTERFACE_DIRTY ) strcpy(text, "Salissures\\Salissures des robots et bâtiments");
- if ( num == EVENT_INTERFACE_FOG ) strcpy(text, "Brouillard\\Nappes de brouillard");
- if ( num == EVENT_INTERFACE_LENS ) strcpy(text, "Rayons du soleil\\Rayons selon l'orientation");
- if ( num == EVENT_INTERFACE_SKY ) strcpy(text, "Ciel\\Ciel et nuages");
- if ( num == EVENT_INTERFACE_PLANET ) strcpy(text, "Planètes et étoiles\\Motifs mobiles dans le ciel");
- if ( num == EVENT_INTERFACE_LIGHT ) strcpy(text, "Lumières dynamiques\\Eclairages mobiles");
- if ( num == EVENT_INTERFACE_PARTI ) strcpy(text, "Quantité de particules\\Explosions, poussières, reflets, etc.");
- if ( num == EVENT_INTERFACE_CLIP ) strcpy(text, "Profondeur de champ\\Distance de vue maximale");
- if ( num == EVENT_INTERFACE_DETAIL ) strcpy(text, "Détails des objets\\Qualité des objets en 3D");
- if ( num == EVENT_INTERFACE_TEXTURE) strcpy(text, "Qualité des textures\\Qualité des images");
- if ( num == EVENT_INTERFACE_GADGET ) strcpy(text, "Nb d'objets décoratifs\\Qualité d'objets non indispensables");
- if ( num == EVENT_INTERFACE_RAIN ) strcpy(text, "Particules dans l'interface\\Pluie de particules");
- if ( num == EVENT_INTERFACE_GLINT ) strcpy(text, "Reflets sur les boutons\\Boutons brillants");
- if ( num == EVENT_INTERFACE_TOOLTIP) strcpy(text, "Bulles d'aide\\Bulles explicatives");
- if ( num == EVENT_INTERFACE_MOVIES ) strcpy(text, "Séquences cinématiques\\Films avant ou après une mission");
- if ( num == EVENT_INTERFACE_NICERST) strcpy(text, "Retour animé\\Retour animé dans les exercices");
- if ( num == EVENT_INTERFACE_HIMSELF) strcpy(text, "Dégâts à soi-même\\Vos tirs infligent des dommages à vos unités");
- if ( num == EVENT_INTERFACE_SCROLL ) strcpy(text, "Défilement dans les bords\\Défilement lorsque la souris touches les bords gauche ou droite");
- if ( num == EVENT_INTERFACE_INVERTX) strcpy(text, "Inversion souris X\\Inversion de la rotation lorsque la souris touche un bord");
- if ( num == EVENT_INTERFACE_INVERTY) strcpy(text, "Inversion souris Y\\Inversion de la rotation lorsque la souris touche un bord");
- if ( num == EVENT_INTERFACE_EFFECT ) strcpy(text, "Secousses lors d'explosions\\L'écran vibre lors d'une explosion");
- if ( num == EVENT_INTERFACE_MOUSE ) strcpy(text, "Souris ombrée\\Jolie souris avec une ombre");
- if ( num == EVENT_INTERFACE_EDITMODE) strcpy(text, "Indentation automatique\\Pendant l'édition d'un programme");
- if ( num == EVENT_INTERFACE_EDITVALUE)strcpy(text, "Grande indentation\\Indente avec 2 ou 4 espaces");
- if ( num == EVENT_INTERFACE_SOLUCE4) strcpy(text, "Accès aux solutions\\Programme \"4: Solution\" dans les exercices");
-
- if ( num == EVENT_INTERFACE_KDEF ) strcpy(text, "Tout réinitialiser\\Remet toutes les touches standards");
- if ( num == EVENT_INTERFACE_KLEFT ) strcpy(text, "Tourner à gauche\\Moteur à gauche");
- if ( num == EVENT_INTERFACE_KRIGHT ) strcpy(text, "Tourner à droite\\Moteur à droite");
- if ( num == EVENT_INTERFACE_KUP ) strcpy(text, "Avancer\\Moteur en avant");
- if ( num == EVENT_INTERFACE_KDOWN ) strcpy(text, "Reculer\\Moteur en arrière");
- if ( num == EVENT_INTERFACE_KGUP ) strcpy(text, "Monter\\Augmenter la puissance du réacteur");
- if ( num == EVENT_INTERFACE_KGDOWN ) strcpy(text, "Descendre\\Diminuer la puissance du réacteur");
- if ( num == EVENT_INTERFACE_KCAMERA) strcpy(text, "Changement de caméra\\Autre de point de vue");
- if ( num == EVENT_INTERFACE_KDESEL ) strcpy(text, "Sélection précédente\\Sélectionne l'objet précédent");
- if ( num == EVENT_INTERFACE_KACTION) strcpy(text, "Action standard\\Action du bouton avec le cadre rouge");
- if ( num == EVENT_INTERFACE_KNEAR ) strcpy(text, "Caméra plus proche\\Avance la caméra");
- if ( num == EVENT_INTERFACE_KAWAY ) strcpy(text, "Caméra plus loin\\Recule la caméra");
- if ( num == EVENT_INTERFACE_KNEXT ) strcpy(text, "Sélectionner l'objet suivant\\Sélectionner l'objet suivant");
- if ( num == EVENT_INTERFACE_KHUMAN ) strcpy(text, "Sélectionner le cosmonaute\\Sélectionner le cosmonaute");
- if ( num == EVENT_INTERFACE_KQUIT ) strcpy(text, "Quitter la mission en cours\\Terminer un exercice ou une mssion");
- if ( num == EVENT_INTERFACE_KHELP ) strcpy(text, "Instructions mission\\Marche à suivre");
- if ( num == EVENT_INTERFACE_KPROG ) strcpy(text, "Instructions programmation\\Explication sur la programmation");
- if ( num == EVENT_INTERFACE_KCBOT ) strcpy(text, "Instructions mot-clé\\Explication sur le mot-clé");
- if ( num == EVENT_INTERFACE_KVISIT ) strcpy(text, "Montrer le lieu d'un message\\Montrer le lieu du dernier message");
- if ( num == EVENT_INTERFACE_KSPEED10) strcpy(text, "Vitesse 1.0x\\Vitesse normale");
- if ( num == EVENT_INTERFACE_KSPEED15) strcpy(text, "Vitesse 1.5x\\Une fois et demi plus rapide");
- if ( num == EVENT_INTERFACE_KSPEED20) strcpy(text, "Vitesse 2.0x\\Deux fois plus rapide");
- if ( num == EVENT_INTERFACE_KSPEED30) strcpy(text, "Vitesse 3.0x\\Trois fois plus rapide");
-
- if ( num == EVENT_INTERFACE_VOLSOUND) strcpy(text, "Bruitages :\\Volume des moteurs, voix, etc.");
- if ( num == EVENT_INTERFACE_VOLMUSIC) strcpy(text, "Fond sonore :\\Volume des pistes audio du CD");
- if ( num == EVENT_INTERFACE_SOUND3D) strcpy(text, "Bruitages 3D\\Positionnement sonore dans l'espace");
-
- if ( num == EVENT_INTERFACE_MIN ) strcpy(text, "Mini\\Qualité minimale (+ rapide)");
- if ( num == EVENT_INTERFACE_NORM ) strcpy(text, "Normal\\Qualité standard");
- if ( num == EVENT_INTERFACE_MAX ) strcpy(text, "Maxi\\Haute qualité (+ lent)");
-
- if ( num == EVENT_INTERFACE_SILENT ) strcpy(text, "Silencieux\\Totalement silencieux");
- if ( num == EVENT_INTERFACE_NOISY ) strcpy(text, "Normal\\Niveaux normaux");
-
- if ( num == EVENT_INTERFACE_JOYSTICK) strcpy(text, "Utilise un joystick\\Joystick ou clavier");
- if ( num == EVENT_INTERFACE_SOLUCE ) strcpy(text, "Accès à la solution\\Donne la solution");
-
- if ( num == EVENT_INTERFACE_NEDIT ) strcpy(text, "\\Nom du joueur à créer");
- if ( num == EVENT_INTERFACE_NOK ) strcpy(text, "D'accord\\Choisir le joueur");
- if ( num == EVENT_INTERFACE_NCANCEL) strcpy(text, "Annuler\\Conserver le joueur actuel");
- if ( num == EVENT_INTERFACE_NDELETE) strcpy(text, "Supprimer le joueur\\Supprimer le joueur de la liste");
- if ( num == EVENT_INTERFACE_NLABEL ) strcpy(text, "Nom du joueur");
-
- if ( num == EVENT_INTERFACE_IOWRITE) strcpy(text, "Enregistrer\\Enregistrer la mission en cours");
- if ( num == EVENT_INTERFACE_IOREAD ) strcpy(text, "Charger\\Charger la mission sélectionnée");
- if ( num == EVENT_INTERFACE_IOLIST ) strcpy(text, "Liste des missions enregistrées");
- if ( num == EVENT_INTERFACE_IOLABEL) strcpy(text, "Nom du fichier :");
- if ( num == EVENT_INTERFACE_IONAME ) strcpy(text, "Nom de la mission");
- if ( num == EVENT_INTERFACE_IOIMAGE) strcpy(text, "Vue de la mission");
- if ( num == EVENT_INTERFACE_IODELETE) strcpy(text, "Supprimer\\Supprime l'enregistrement sélectionné");
-
- if ( num == EVENT_INTERFACE_PERSO ) strcpy(text, "Aspect\\Choisir votre aspect");
- if ( num == EVENT_INTERFACE_POK ) strcpy(text, "D'accord");
- if ( num == EVENT_INTERFACE_PCANCEL) strcpy(text, "Annuler");
- if ( num == EVENT_INTERFACE_PDEF ) strcpy(text, "Standard\\Remet les couleurs standards");
- if ( num == EVENT_INTERFACE_PHEAD ) strcpy(text, "Tête\\Visage et cheveux");
- if ( num == EVENT_INTERFACE_PBODY ) strcpy(text, "Corps\\Combinaison");
- if ( num == EVENT_INTERFACE_PLROT ) strcpy(text, "\\Rotation à gauche");
- if ( num == EVENT_INTERFACE_PRROT ) strcpy(text, "\\Rotation à droite");
- if ( num == EVENT_INTERFACE_PCRa ) strcpy(text, "Rouge");
- if ( num == EVENT_INTERFACE_PCGa ) strcpy(text, "Vert");
- if ( num == EVENT_INTERFACE_PCBa ) strcpy(text, "Bleu");
- if ( num == EVENT_INTERFACE_PCRb ) strcpy(text, "Rouge");
- if ( num == EVENT_INTERFACE_PCGb ) strcpy(text, "Vert");
- if ( num == EVENT_INTERFACE_PCBb ) strcpy(text, "Bleu");
- if ( num == EVENT_INTERFACE_PFACE1 ) strcpy(text, "\\Visage 1");
- if ( num == EVENT_INTERFACE_PFACE2 ) strcpy(text, "\\Visage 4");
- if ( num == EVENT_INTERFACE_PFACE3 ) strcpy(text, "\\Visage 3");
- if ( num == EVENT_INTERFACE_PFACE4 ) strcpy(text, "\\Visage 2");
- if ( num == EVENT_INTERFACE_PGLASS0) strcpy(text, "\\Pas de lunettes");
- if ( num == EVENT_INTERFACE_PGLASS1) strcpy(text, "\\Lunettes 1");
- if ( num == EVENT_INTERFACE_PGLASS2) strcpy(text, "\\Lunettes 2");
- if ( num == EVENT_INTERFACE_PGLASS3) strcpy(text, "\\Lunettes 3");
- if ( num == EVENT_INTERFACE_PGLASS4) strcpy(text, "\\Lunettes 4");
- if ( num == EVENT_INTERFACE_PGLASS5) strcpy(text, "\\Lunettes 5");
-
- if ( num == EVENT_OBJECT_DESELECT ) strcpy(text, "Sélection précédente (\\key desel;)");
- if ( num == EVENT_OBJECT_LEFT ) strcpy(text, "Tourne à gauche (\\key left;)");
- if ( num == EVENT_OBJECT_RIGHT ) strcpy(text, "Tourne à droite (\\key right;)");
- if ( num == EVENT_OBJECT_UP ) strcpy(text, "Avance (\\key up;)");
- if ( num == EVENT_OBJECT_DOWN ) strcpy(text, "Recule (\\key down;)");
- if ( num == EVENT_OBJECT_GASUP ) strcpy(text, "Monte (\\key gup;)");
- if ( num == EVENT_OBJECT_GASDOWN ) strcpy(text, "Descend (\\key gdown;)");
- if ( num == EVENT_OBJECT_HTAKE ) strcpy(text, "Prend ou dépose (\\key action;)");
- if ( num == EVENT_OBJECT_MTAKE ) strcpy(text, "Prend ou dépose (\\key action;)");
- if ( num == EVENT_OBJECT_MFRONT ) strcpy(text, "..devant");
- if ( num == EVENT_OBJECT_MBACK ) strcpy(text, "..derrière");
- if ( num == EVENT_OBJECT_MPOWER ) strcpy(text, "..pile");
- if ( num == EVENT_OBJECT_BHELP ) strcpy(text, "Instructions sur la mission (\\key help;)");
- if ( num == EVENT_OBJECT_BTAKEOFF ) strcpy(text, "Décolle pour terminer la mission");
- if ( num == EVENT_OBJECT_BDERRICK ) strcpy(text, "Construit un derrick");
- if ( num == EVENT_OBJECT_BSTATION ) strcpy(text, "Construit une station");
- if ( num == EVENT_OBJECT_BFACTORY ) strcpy(text, "Construit une fabrique de robots");
- if ( num == EVENT_OBJECT_BREPAIR ) strcpy(text, "Construit un centre de réparation");
- if ( num == EVENT_OBJECT_BCONVERT ) strcpy(text, "Construit un convertisseur");
- if ( num == EVENT_OBJECT_BTOWER ) strcpy(text, "Construit une tour");
- if ( num == EVENT_OBJECT_BRESEARCH ) strcpy(text, "Construit un centre de recherches");
- if ( num == EVENT_OBJECT_BRADAR ) strcpy(text, "Construit un radar");
- if ( num == EVENT_OBJECT_BENERGY ) strcpy(text, "Construit une fabrique de piles");
- if ( num == EVENT_OBJECT_BLABO ) strcpy(text, "Construit un laboratoire");
- if ( num == EVENT_OBJECT_BNUCLEAR ) strcpy(text, "Construit une centrale nucléaire");
- if ( num == EVENT_OBJECT_BPARA ) strcpy(text, "Construit un paratonnerre");
- if ( num == EVENT_OBJECT_BINFO ) strcpy(text, "Construit une borne d'information");
- if ( num == EVENT_OBJECT_GFLAT ) strcpy(text, "Montre si le sol est plat");
- if ( num == EVENT_OBJECT_FCREATE ) strcpy(text, "Pose un drapeau de couleur");
- if ( num == EVENT_OBJECT_FDELETE ) strcpy(text, "Enlève un drapeau");
- if ( num == EVENT_OBJECT_FCOLORb ) strcpy(text, "\\Drapeaux bleus");
- if ( num == EVENT_OBJECT_FCOLORr ) strcpy(text, "\\Drapeaux rouges");
- if ( num == EVENT_OBJECT_FCOLORg ) strcpy(text, "\\Drapeaux verts");
- if ( num == EVENT_OBJECT_FCOLORy ) strcpy(text, "\\Drapeaux jaunes");
- if ( num == EVENT_OBJECT_FCOLORv ) strcpy(text, "\\Drapeaux violets");
- if ( num == EVENT_OBJECT_FACTORYfa ) strcpy(text, "Fabrique un déménageur volant");
- if ( num == EVENT_OBJECT_FACTORYta ) strcpy(text, "Fabrique un déménageur à chenilles");
- if ( num == EVENT_OBJECT_FACTORYwa ) strcpy(text, "Fabrique un déménageur à roues");
- if ( num == EVENT_OBJECT_FACTORYia ) strcpy(text, "Fabrique un déménageur à pattes");
- if ( num == EVENT_OBJECT_FACTORYfc ) strcpy(text, "Fabrique un shooter volant");
- if ( num == EVENT_OBJECT_FACTORYtc ) strcpy(text, "Fabrique un shooter à chenilles");
- if ( num == EVENT_OBJECT_FACTORYwc ) strcpy(text, "Fabrique un shooter à roues");
- if ( num == EVENT_OBJECT_FACTORYic ) strcpy(text, "Fabrique un shooter à pattes");
- if ( num == EVENT_OBJECT_FACTORYfi ) strcpy(text, "Fabrique un orgaShooter volant");
- if ( num == EVENT_OBJECT_FACTORYti ) strcpy(text, "Fabrique un orgaShooter à chenilles");
- if ( num == EVENT_OBJECT_FACTORYwi ) strcpy(text, "Fabrique un orgaShooter à roues");
- if ( num == EVENT_OBJECT_FACTORYii ) strcpy(text, "Fabrique un orgaShooter à pattes");
- if ( num == EVENT_OBJECT_FACTORYfs ) strcpy(text, "Fabrique un renifleur volant");
- if ( num == EVENT_OBJECT_FACTORYts ) strcpy(text, "Fabrique un renifleur à chenilles");
- if ( num == EVENT_OBJECT_FACTORYws ) strcpy(text, "Fabrique un renifleur à roues");
- if ( num == EVENT_OBJECT_FACTORYis ) strcpy(text, "Fabrique un renifleur à pattes");
- if ( num == EVENT_OBJECT_FACTORYrt ) strcpy(text, "Fabrique un robot secoueur");
- if ( num == EVENT_OBJECT_FACTORYrc ) strcpy(text, "Fabrique un robot phazer");
- if ( num == EVENT_OBJECT_FACTORYrr ) strcpy(text, "Fabrique un robot recycleur");
- if ( num == EVENT_OBJECT_FACTORYrs ) strcpy(text, "Fabrique un robot bouclier");
- if ( num == EVENT_OBJECT_FACTORYsa ) strcpy(text, "Fabrique un robot sous-marin");
- if ( num == EVENT_OBJECT_RTANK ) strcpy(text, "Recherche les chenilles");
- if ( num == EVENT_OBJECT_RFLY ) strcpy(text, "Recherche les robots volants");
- if ( num == EVENT_OBJECT_RTHUMP ) strcpy(text, "Recherche le secoueur");
- if ( num == EVENT_OBJECT_RCANON ) strcpy(text, "Recherche le canon shooter");
- if ( num == EVENT_OBJECT_RTOWER ) strcpy(text, "Recherche la tour de défense");
- if ( num == EVENT_OBJECT_RPHAZER ) strcpy(text, "Recherche le canon phazer");
- if ( num == EVENT_OBJECT_RSHIELD ) strcpy(text, "Recherche le bouclier");
- if ( num == EVENT_OBJECT_RATOMIC ) strcpy(text, "Recherche le nucléaire");
- if ( num == EVENT_OBJECT_RiPAW ) strcpy(text, "Recherche les pattes");
- if ( num == EVENT_OBJECT_RiGUN ) strcpy(text, "Recherche le canon orgaShooter");
- if ( num == EVENT_OBJECT_RESET ) strcpy(text, "Remet au départ");
- if ( num == EVENT_OBJECT_SEARCH ) strcpy(text, "Cherche (\\key action;)");
- if ( num == EVENT_OBJECT_TERRAFORM ) strcpy(text, "Secoue (\\key action;)");
- if ( num == EVENT_OBJECT_FIRE ) strcpy(text, "Tir (\\key action;)");
- if ( num == EVENT_OBJECT_RECOVER ) strcpy(text, "Recycle (\\key action;)");
- if ( num == EVENT_OBJECT_BEGSHIELD ) strcpy(text, "Déploie le bouclier (\\key action;)");
- if ( num == EVENT_OBJECT_ENDSHIELD ) strcpy(text, "Stoppe le bouclier (\\key action;)");
- if ( num == EVENT_OBJECT_DIMSHIELD ) strcpy(text, "Rayon du bouclier");
- if ( num == EVENT_OBJECT_PROGRUN ) strcpy(text, "Exécute le programme sélectionné");
- if ( num == EVENT_OBJECT_PROGEDIT ) strcpy(text, "Edite le programme sélectionné");
- if ( num == EVENT_OBJECT_INFOOK ) strcpy(text, "\\Mettre le SatCom en veille");
- if ( num == EVENT_OBJECT_DELETE ) strcpy(text, "Démolit le bâtiment");
- if ( num == EVENT_OBJECT_GENERGY ) strcpy(text, "Niveau d'énergie");
- if ( num == EVENT_OBJECT_GSHIELD ) strcpy(text, "Niveau du bouclier");
- if ( num == EVENT_OBJECT_GRANGE ) strcpy(text, "Température du réacteur");
- if ( num == EVENT_OBJECT_GPROGRESS ) strcpy(text, "Travail en cours ...");
- if ( num == EVENT_OBJECT_GRADAR ) strcpy(text, "Nombre d'insectes détectés");
- if ( num == EVENT_OBJECT_GINFO ) strcpy(text, "Informations diffusées");
- if ( num == EVENT_OBJECT_COMPASS ) strcpy(text, "Boussole");
-//? if ( num == EVENT_OBJECT_MAP ) strcpy(text, "Mini-carte");
- if ( num == EVENT_OBJECT_MAPZOOM ) strcpy(text, "Zoom mini-carte");
- if ( num == EVENT_OBJECT_CAMERA ) strcpy(text, "Caméra (\\key camera;)");
- if ( num == EVENT_OBJECT_CAMERAleft) strcpy(text, "Caméra à gauche");
- if ( num == EVENT_OBJECT_CAMERAright) strcpy(text, "Caméra à droite");
- if ( num == EVENT_OBJECT_CAMERAnear) strcpy(text, "Caméra plus proche");
- if ( num == EVENT_OBJECT_CAMERAaway) strcpy(text, "Caméra plus loin");
- if ( num == EVENT_OBJECT_HELP ) strcpy(text, "Instructions sur la sélection");
- if ( num == EVENT_OBJECT_SOLUCE ) strcpy(text, "Donne la solution");
- if ( num == EVENT_OBJECT_SHORTCUT00) strcpy(text, "Permute robots <-> bâtiments");
- if ( num == EVENT_OBJECT_LIMIT ) strcpy(text, "Montre le rayon d'action");
- if ( num == EVENT_OBJECT_PEN0 ) strcpy(text, "\\Relève le crayon");
- if ( num == EVENT_OBJECT_PEN1 ) strcpy(text, "\\Abaisse le crayon noir");
- if ( num == EVENT_OBJECT_PEN2 ) strcpy(text, "\\Abaisse le crayon jaune");
- if ( num == EVENT_OBJECT_PEN3 ) strcpy(text, "\\Abaisse le crayon orange");
- if ( num == EVENT_OBJECT_PEN4 ) strcpy(text, "\\Abaisse le crayon rouge");
- if ( num == EVENT_OBJECT_PEN5 ) strcpy(text, "\\Abaisse le crayon violet");
- if ( num == EVENT_OBJECT_PEN6 ) strcpy(text, "\\Abaisse le crayon bleu");
- if ( num == EVENT_OBJECT_PEN7 ) strcpy(text, "\\Abaisse le crayon vert");
- if ( num == EVENT_OBJECT_PEN8 ) strcpy(text, "\\Abaisse le crayon brun");
- if ( num == EVENT_OBJECT_REC ) strcpy(text, "\\Démarre l'enregistrement");
- if ( num == EVENT_OBJECT_STOP ) strcpy(text, "\\Stoppe l'enregistrement");
- if ( num == EVENT_DT_VISIT0 ||
- num == EVENT_DT_VISIT1 ||
- num == EVENT_DT_VISIT2 ||
- num == EVENT_DT_VISIT3 ||
- num == EVENT_DT_VISIT4 ) strcpy(text, "Montre l'endroit");
- if ( num == EVENT_DT_END ) strcpy(text, "Continuer");
- if ( num == EVENT_CMD ) strcpy(text, "Console de commande");
- if ( num == EVENT_SPEED ) strcpy(text, "Vitesse du jeu");
-
- if ( num == EVENT_HYPER_PREV ) strcpy(text, "Page précédente");
- if ( num == EVENT_HYPER_NEXT ) strcpy(text, "Page suivante");
- if ( num == EVENT_HYPER_HOME ) strcpy(text, "Page initiale");
- if ( num == EVENT_HYPER_COPY ) strcpy(text, "Copier");
- if ( num == EVENT_HYPER_SIZE1 ) strcpy(text, "Taille 1");
- if ( num == EVENT_HYPER_SIZE2 ) strcpy(text, "Taille 2");
- if ( num == EVENT_HYPER_SIZE3 ) strcpy(text, "Taille 3");
- if ( num == EVENT_HYPER_SIZE4 ) strcpy(text, "Taille 4");
- if ( num == EVENT_HYPER_SIZE5 ) strcpy(text, "Taille 5");
- if ( num == EVENT_SATCOM_HUSTON ) strcpy(text, "Instructions de Houston");
-#if _TEEN
- if ( num == EVENT_SATCOM_SAT ) strcpy(text, "Dictionnaire anglais-français");
-#else
- if ( num == EVENT_SATCOM_SAT ) strcpy(text, "Rapport du satellite");
-#endif
- if ( num == EVENT_SATCOM_LOADING ) strcpy(text, "Programmes envoyés par Houston");
- if ( num == EVENT_SATCOM_OBJECT ) strcpy(text, "Liste des objets");
- if ( num == EVENT_SATCOM_PROG ) strcpy(text, "Aide à la programmation");
- if ( num == EVENT_SATCOM_SOLUCE ) strcpy(text, "Solution");
-
- if ( num == EVENT_STUDIO_OK ) strcpy(text, "D'accord\\Compiler le programme");
- if ( num == EVENT_STUDIO_CANCEL ) strcpy(text, "Annuler\\Annuler toutes les modifications");
- if ( num == EVENT_STUDIO_NEW ) strcpy(text, "Nouveau");
- if ( num == EVENT_STUDIO_OPEN ) strcpy(text, "Ouvrir (Ctrl+o)");
- if ( num == EVENT_STUDIO_SAVE ) strcpy(text, "Enregistrer (Ctrl+s)");
- if ( num == EVENT_STUDIO_UNDO ) strcpy(text, "Annuler (Ctrl+z)");
- if ( num == EVENT_STUDIO_CUT ) strcpy(text, "Couper (Ctrl+x)");
- if ( num == EVENT_STUDIO_COPY ) strcpy(text, "Copier (Ctrl+c)");
- if ( num == EVENT_STUDIO_PASTE ) strcpy(text, "Coller (Ctrl+v)");
- if ( num == EVENT_STUDIO_SIZE ) strcpy(text, "Taille des caractères");
- if ( num == EVENT_STUDIO_TOOL ) strcpy(text, "Instructions (\\key help;)");
- if ( num == EVENT_STUDIO_HELP ) strcpy(text, "Aide à la programmation (\\key prog;)");
- if ( num == EVENT_STUDIO_COMPILE ) strcpy(text, "Compiler");
- if ( num == EVENT_STUDIO_RUN ) strcpy(text, "Démarrer/stopper");
- if ( num == EVENT_STUDIO_REALTIME ) strcpy(text, "Pause/continuer");
- if ( num == EVENT_STUDIO_STEP ) strcpy(text, "Un pas");
- }
-
- if ( type == RES_OBJECT )
- {
- if ( num == OBJECT_PORTICO ) strcpy(text, "Portique");
- if ( num == OBJECT_BASE ) strcpy(text, "Vaisseau spatial");
- if ( num == OBJECT_DERRICK ) strcpy(text, "Derrick");
- if ( num == OBJECT_FACTORY ) strcpy(text, "Fabrique de robots");
- if ( num == OBJECT_REPAIR ) strcpy(text, "Centre de réparation");
- if ( num == OBJECT_DESTROYER ) strcpy(text, "Destructeur");
- if ( num == OBJECT_STATION ) strcpy(text, "Station de recharge");
- if ( num == OBJECT_CONVERT ) strcpy(text, "Conversion minerai en titanium");
- if ( num == OBJECT_TOWER ) strcpy(text, "Tour de défense");
- if ( num == OBJECT_NEST ) strcpy(text, "Nid");
- if ( num == OBJECT_RESEARCH ) strcpy(text, "Centre de recherches");
- if ( num == OBJECT_RADAR ) strcpy(text, "Radar");
- if ( num == OBJECT_INFO ) strcpy(text, "Borne d'information");
-#if _TEEN
- if ( num == OBJECT_ENERGY ) strcpy(text, "Désintégrateur");
-#else
- if ( num == OBJECT_ENERGY ) strcpy(text, "Fabrique de piles");
-#endif
- if ( num == OBJECT_LABO ) strcpy(text, "Laboratoire de matières organiques");
- if ( num == OBJECT_NUCLEAR ) strcpy(text, "Centrale nucléaire");
- if ( num == OBJECT_PARA ) strcpy(text, "Paratonnerre");
- if ( num == OBJECT_SAFE ) strcpy(text, "Coffre-fort");
- if ( num == OBJECT_HUSTON ) strcpy(text, "Centre de contrôle");
- if ( num == OBJECT_TARGET1 ) strcpy(text, "Cible");
- if ( num == OBJECT_TARGET2 ) strcpy(text, "Cible");
- if ( num == OBJECT_START ) strcpy(text, "Départ");
- if ( num == OBJECT_END ) strcpy(text, "But");
- if ( num == OBJECT_STONE ) strcpy(text, "Minerai de titanium");
- if ( num == OBJECT_URANIUM ) strcpy(text, "Minerai d'uranium");
- if ( num == OBJECT_BULLET ) strcpy(text, "Matière organique");
- if ( num == OBJECT_METAL ) strcpy(text, "Titanium");
- if ( num == OBJECT_POWER ) strcpy(text, "Pile normale");
- if ( num == OBJECT_ATOMIC ) strcpy(text, "Pile nucléaire");
- if ( num == OBJECT_BBOX ) strcpy(text, "Boîte noire");
- if ( num == OBJECT_KEYa ) strcpy(text, "Clé A");
- if ( num == OBJECT_KEYb ) strcpy(text, "Clé B");
- if ( num == OBJECT_KEYc ) strcpy(text, "Clé C");
- if ( num == OBJECT_KEYd ) strcpy(text, "Clé D");
- if ( num == OBJECT_TNT ) strcpy(text, "Explosif");
- if ( num == OBJECT_BOMB ) strcpy(text, "Mine fixe");
- if ( num == OBJECT_BAG ) strcpy(text, "Sac de survie");
- if ( num == OBJECT_WAYPOINT ) strcpy(text, "Indicateur");
- if ( num == OBJECT_FLAGb ) strcpy(text, "Drapeau bleu");
- if ( num == OBJECT_FLAGr ) strcpy(text, "Drapeau rouge");
- if ( num == OBJECT_FLAGg ) strcpy(text, "Drapeau vert");
- if ( num == OBJECT_FLAGy ) strcpy(text, "Drapeau jaune");
- if ( num == OBJECT_FLAGv ) strcpy(text, "Drapeau violet");
- if ( num == OBJECT_MARKPOWER ) strcpy(text, "Emplacement pour station");
- if ( num == OBJECT_MARKURANIUM ) strcpy(text, "Emplacement pour derrick (uranium)");
- if ( num == OBJECT_MARKKEYa ) strcpy(text, "Emplacement pour derrick (clé A)");
- if ( num == OBJECT_MARKKEYb ) strcpy(text, "Emplacement pour derrick (clé B)");
- if ( num == OBJECT_MARKKEYc ) strcpy(text, "Emplacement pour derrick (clé C)");
- if ( num == OBJECT_MARKKEYd ) strcpy(text, "Emplacement pour derrick (clé D)");
- if ( num == OBJECT_MARKSTONE ) strcpy(text, "Emplacement pour derrick (titanium)");
- if ( num == OBJECT_MOBILEft ) strcpy(text, "Robot d'entraînement");
- if ( num == OBJECT_MOBILEtt ) strcpy(text, "Robot d'entraînement");
- if ( num == OBJECT_MOBILEwt ) strcpy(text, "Robot d'entraînement");
- if ( num == OBJECT_MOBILEit ) strcpy(text, "Robot d'entraînement");
- if ( num == OBJECT_MOBILEfa ) strcpy(text, "Robot déménageur");
- if ( num == OBJECT_MOBILEta ) strcpy(text, "Robot déménageur");
- if ( num == OBJECT_MOBILEwa ) strcpy(text, "Robot déménageur");
- if ( num == OBJECT_MOBILEia ) strcpy(text, "Robot déménageur");
- if ( num == OBJECT_MOBILEfc ) strcpy(text, "Robot shooter");
- if ( num == OBJECT_MOBILEtc ) strcpy(text, "Robot shooter");
- if ( num == OBJECT_MOBILEwc ) strcpy(text, "Robot shooter");
- if ( num == OBJECT_MOBILEic ) strcpy(text, "Robot shooter");
- if ( num == OBJECT_MOBILEfi ) strcpy(text, "Robot orgaShooter");
- if ( num == OBJECT_MOBILEti ) strcpy(text, "Robot orgaShooter");
- if ( num == OBJECT_MOBILEwi ) strcpy(text, "Robot orgaShooter");
- if ( num == OBJECT_MOBILEii ) strcpy(text, "Robot orgaShooter");
- if ( num == OBJECT_MOBILEfs ) strcpy(text, "Robot renifleur");
- if ( num == OBJECT_MOBILEts ) strcpy(text, "Robot renifleur");
- if ( num == OBJECT_MOBILEws ) strcpy(text, "Robot renifleur");
- if ( num == OBJECT_MOBILEis ) strcpy(text, "Robot renifleur");
- if ( num == OBJECT_MOBILErt ) strcpy(text, "Robot secoueur");
- if ( num == OBJECT_MOBILErc ) strcpy(text, "Robot phazer");
- if ( num == OBJECT_MOBILErr ) strcpy(text, "Robot recycleur");
- if ( num == OBJECT_MOBILErs ) strcpy(text, "Robot bouclier");
- if ( num == OBJECT_MOBILEsa ) strcpy(text, "Robot sous-marin");
- if ( num == OBJECT_MOBILEtg ) strcpy(text, "Cible d'entraînement");
- if ( num == OBJECT_MOBILEdr ) strcpy(text, "Robot dessinateur");
- if ( num == OBJECT_HUMAN ) strcpy(text, g_gamerName);
- if ( num == OBJECT_TECH ) strcpy(text, "Technicien");
- if ( num == OBJECT_TOTO ) strcpy(text, "Robbie");
- if ( num == OBJECT_MOTHER ) strcpy(text, "Pondeuse");
- if ( num == OBJECT_ANT ) strcpy(text, "Fourmi");
- if ( num == OBJECT_SPIDER ) strcpy(text, "Araignée");
- if ( num == OBJECT_BEE ) strcpy(text, "Guêpe");
- if ( num == OBJECT_WORM ) strcpy(text, "Ver");
- if ( num == OBJECT_EGG ) strcpy(text, "Oeuf");
- if ( num == OBJECT_RUINmobilew1 ) strcpy(text, "Epave de robot");
- if ( num == OBJECT_RUINmobilew2 ) strcpy(text, "Epave de robot");
- if ( num == OBJECT_RUINmobilet1 ) strcpy(text, "Epave de robot");
- if ( num == OBJECT_RUINmobilet2 ) strcpy(text, "Epave de robot");
- if ( num == OBJECT_RUINmobiler1 ) strcpy(text, "Epave de robot");
- if ( num == OBJECT_RUINmobiler2 ) strcpy(text, "Epave de robot");
- if ( num == OBJECT_RUINfactory ) strcpy(text, "Bâtiment en ruine");
- if ( num == OBJECT_RUINdoor ) strcpy(text, "Bâtiment en ruine");
- if ( num == OBJECT_RUINsupport ) strcpy(text, "Déchet");
- if ( num == OBJECT_RUINradar ) strcpy(text, "Bâtiment en ruine");
- if ( num == OBJECT_RUINconvert ) strcpy(text, "Bâtiment en ruine");
- if ( num == OBJECT_RUINbase ) strcpy(text, "Epave de vaisseau spatial");
- if ( num == OBJECT_RUINhead ) strcpy(text, "Epave de vaisseau spatial");
- if ( num == OBJECT_APOLLO1 ||
- num == OBJECT_APOLLO3 ||
- num == OBJECT_APOLLO4 ||
- num == OBJECT_APOLLO5 ) strcpy(text, "Vestige d'une mission Apollo");
- if ( num == OBJECT_APOLLO2 ) strcpy(text, "Lunar Roving Vehicle");
- }
-
- if ( type == RES_ERR )
- {
- strcpy(text, "Erreur");
- if ( num == ERR_CMD ) strcpy(text, "Commande inconnue");
-#if _NEWLOOK
- if ( num == ERR_INSTALL ) strcpy(text, "CeeBot n'est pas installé.");
- if ( num == ERR_NOCD ) strcpy(text, "Veuillez mettre le CD de CeeBot\net relancer le jeu.");
-#else
- if ( num == ERR_INSTALL ) strcpy(text, "COLOBOT n'est pas installé.");
- if ( num == ERR_NOCD ) strcpy(text, "Veuillez mettre le CD de COLOBOT\net relancer le jeu.");
-#endif
- if ( num == ERR_MANIP_VEH ) strcpy(text, "Robot inadapté");
- if ( num == ERR_MANIP_FLY ) strcpy(text, "Impossible en vol");
- if ( num == ERR_MANIP_BUSY ) strcpy(text, "Porte déjà quelque chose");
- if ( num == ERR_MANIP_NIL ) strcpy(text, "Rien à prendre");
- if ( num == ERR_MANIP_MOTOR ) strcpy(text, "Impossible en mouvement");
- if ( num == ERR_MANIP_OCC ) strcpy(text, "Emplacement occupé");
- if ( num == ERR_MANIP_FRIEND ) strcpy(text, "Pas d'autre robot");
- if ( num == ERR_MANIP_RADIO ) strcpy(text, "Vous ne pouvez pas transporter un objet radioactif");
- if ( num == ERR_MANIP_WATER ) strcpy(text, "Vous ne pouvez pas transporter un objet sous l'eau");
- if ( num == ERR_MANIP_EMPTY ) strcpy(text, "Rien à déposer");
- if ( num == ERR_BUILD_FLY ) strcpy(text, "Impossible en vol");
- if ( num == ERR_BUILD_WATER ) strcpy(text, "Impossible sous l'eau");
- if ( num == ERR_BUILD_ENERGY ) strcpy(text, "Pas assez d'énergie");
- if ( num == ERR_BUILD_METALAWAY ) strcpy(text, "Titanium trop loin");
- if ( num == ERR_BUILD_METALNEAR ) strcpy(text, "Titanium trop proche");
- if ( num == ERR_BUILD_METALINEX ) strcpy(text, "Titanium inexistant");
- if ( num == ERR_BUILD_FLAT ) strcpy(text, "Sol pas assez plat");
- if ( num == ERR_BUILD_FLATLIT ) strcpy(text, "Sol plat pas assez grand");
- if ( num == ERR_BUILD_BUSY ) strcpy(text, "Emplacement occupé");
- if ( num == ERR_BUILD_BASE ) strcpy(text, "Trop proche du vaisseau spatial");
- if ( num == ERR_BUILD_NARROW ) strcpy(text, "Trop proche d'un bâtiment");
- if ( num == ERR_BUILD_MOTOR ) strcpy(text, "Impossible en mouvement");
- if ( num == ERR_SEARCH_FLY ) strcpy(text, "Impossible en vol");
- if ( num == ERR_SEARCH_VEH ) strcpy(text, "Robot inadapté");
- if ( num == ERR_SEARCH_MOTOR ) strcpy(text, "Impossible en mouvement");
- if ( num == ERR_TERRA_VEH ) strcpy(text, "Robot inadapté");
- if ( num == ERR_TERRA_ENERGY ) strcpy(text, "Pas assez d'énergie");
- if ( num == ERR_TERRA_FLOOR ) strcpy(text, "Terrain inadapté");
- if ( num == ERR_TERRA_BUILDING ) strcpy(text, "Bâtiment trop proche");
- if ( num == ERR_TERRA_OBJECT ) strcpy(text, "Objet trop proche");
- if ( num == ERR_RECOVER_VEH ) strcpy(text, "Robot inadapté");
- if ( num == ERR_RECOVER_ENERGY ) strcpy(text, "Pas assez d'énergie");
- if ( num == ERR_RECOVER_NULL ) strcpy(text, "Rien à recycler");
- if ( num == ERR_SHIELD_VEH ) strcpy(text, "Robot inadapté");
- if ( num == ERR_SHIELD_ENERGY ) strcpy(text, "Plus d'énergie");
- if ( num == ERR_MOVE_IMPOSSIBLE ) strcpy(text, "Déplacement impossible");
- if ( num == ERR_FIND_IMPOSSIBLE ) strcpy(text, "Objet n'existe pas");
- if ( num == ERR_GOTO_IMPOSSIBLE ) strcpy(text, "Chemin introuvable");
- if ( num == ERR_GOTO_ITER ) strcpy(text, "Position inaccessible");
- if ( num == ERR_GOTO_BUSY ) strcpy(text, "Destination occupée");
- if ( num == ERR_FIRE_VEH ) strcpy(text, "Robot inadapté");
- if ( num == ERR_FIRE_ENERGY ) strcpy(text, "Pas assez d'énergie");
- if ( num == ERR_FIRE_FLY ) strcpy(text, "Impossible en vol");
- if ( num == ERR_CONVERT_EMPTY ) strcpy(text, "Pas de minerai de titanium à convertir");
- if ( num == ERR_DERRICK_NULL ) strcpy(text, "Pas de minerai en sous-sol");
- if ( num == ERR_STATION_NULL ) strcpy(text, "Pas d'énergie en sous-sol");
- if ( num == ERR_TOWER_POWER ) strcpy(text, "Pas de pile");
- if ( num == ERR_TOWER_ENERGY ) strcpy(text, "Plus d'énergie");
- if ( num == ERR_RESEARCH_POWER ) strcpy(text, "Pas de pile");
- if ( num == ERR_RESEARCH_ENERGY ) strcpy(text, "Plus assez d'énergie");
- if ( num == ERR_RESEARCH_TYPE ) strcpy(text, "Pas le bon type de pile");
- if ( num == ERR_RESEARCH_ALREADY) strcpy(text, "Recherche déjà effectuée");
- if ( num == ERR_ENERGY_NULL ) strcpy(text, "Pas d'énergie en sous-sol");
- if ( num == ERR_ENERGY_LOW ) strcpy(text, "Pas encore assez d'énergie");
- if ( num == ERR_ENERGY_EMPTY ) strcpy(text, "Pas de titanium à transformer");
- if ( num == ERR_ENERGY_BAD ) strcpy(text, "Ne transforme que le titanium");
- if ( num == ERR_BASE_DLOCK ) strcpy(text, "Portes bloquées par un robot ou un objet");
- if ( num == ERR_BASE_DHUMAN ) strcpy(text, "Vous devez embarquer pour pouvoir décoller");
- if ( num == ERR_LABO_NULL ) strcpy(text, "Rien à analyser");
- if ( num == ERR_LABO_BAD ) strcpy(text, "N'analyse que la matière organique");
- if ( num == ERR_LABO_ALREADY ) strcpy(text, "Analyse déjà effectuée");
- if ( num == ERR_NUCLEAR_NULL ) strcpy(text, "Pas d'énergie en sous-sol");
- if ( num == ERR_NUCLEAR_LOW ) strcpy(text, "Pas encore assez d'énergie");
- if ( num == ERR_NUCLEAR_EMPTY ) strcpy(text, "Pas d'uranium à transformer");
- if ( num == ERR_NUCLEAR_BAD ) strcpy(text, "Ne transforme que l'uranium");
- if ( num == ERR_FACTORY_NULL ) strcpy(text, "Pas de titanium");
- if ( num == ERR_FACTORY_NEAR ) strcpy(text, "Quelque chose est trop proche");
- if ( num == ERR_RESET_NEAR ) strcpy(text, "Emplacement occupé");
- if ( num == ERR_INFO_NULL ) strcpy(text, "Pas trouvé de borne d'information");
- if ( num == ERR_VEH_VIRUS ) strcpy(text, "Un programme est infecté par un virus");
- if ( num == ERR_BAT_VIRUS ) strcpy(text, "Infecté par un virus, ne fonctionne plus temporairement");
- if ( num == ERR_VEH_POWER ) strcpy(text, "Pas de pile");
- if ( num == ERR_VEH_ENERGY ) strcpy(text, "Plus d'énergie");
- if ( num == ERR_FLAG_FLY ) strcpy(text, "Impossible en vol");
- if ( num == ERR_FLAG_WATER ) strcpy(text, "Impossible en nageant");
- if ( num == ERR_FLAG_MOTOR ) strcpy(text, "Impossible en mouvement");
- if ( num == ERR_FLAG_BUSY ) strcpy(text, "Impossible en portant un objet");
- if ( num == ERR_FLAG_CREATE ) strcpy(text, "Trop de drapeaux de cette couleur (maximum 5)");
- if ( num == ERR_FLAG_PROXY ) strcpy(text, "Trop proche d'un drapeau existant");
- if ( num == ERR_FLAG_DELETE ) strcpy(text, "Aucun drapeau à proximité");
- if ( num == ERR_MISSION_NOTERM ) strcpy(text, "La misssion n'est pas terminée (appuyez sur \\key help; pour plus de détails)");
- if ( num == ERR_DELETEMOBILE ) strcpy(text, "Robot détruit");
- if ( num == ERR_DELETEBUILDING ) strcpy(text, "Bâtiment détruit");
- if ( num == ERR_TOOMANY ) strcpy(text, "Création impossible, il y a trop d'objets");
- if ( num == ERR_OBLIGATORYTOKEN ) strcpy(text, "Il manque \"%s\" dans le programme");
- if ( num == ERR_PROHIBITEDTOKEN ) strcpy(text, "Interdit dans cet exercice");
-
- if ( num == INFO_BUILD ) strcpy(text, "Bâtiment terminé");
- if ( num == INFO_CONVERT ) strcpy(text, "Titanium disponible");
- if ( num == INFO_RESEARCH ) strcpy(text, "Recherche terminée");
- if ( num == INFO_RESEARCHTANK ) strcpy(text, "Fabrication d'un robot à chenilles possible");
- if ( num == INFO_RESEARCHFLY ) strcpy(text, "Il est possible de voler avec les touches (\\key gup;) et (\\key gdown;)");
- if ( num == INFO_RESEARCHTHUMP ) strcpy(text, "Fabrication d'un robot secoueur possible");
- if ( num == INFO_RESEARCHCANON ) strcpy(text, "Fabrication de robots shooter possible");
- if ( num == INFO_RESEARCHTOWER ) strcpy(text, "Construction d'une tour de défense possible");
- if ( num == INFO_RESEARCHPHAZER ) strcpy(text, "Fabrication d'un robot phazer possible");
- if ( num == INFO_RESEARCHSHIELD ) strcpy(text, "Fabrication d'un robot bouclier possible");
- if ( num == INFO_RESEARCHATOMIC ) strcpy(text, "Construction d'une centrale nucléaire possible");
- if ( num == INFO_FACTORY ) strcpy(text, "Nouveau robot disponible");
- if ( num == INFO_LABO ) strcpy(text, "Analyse terminée");
- if ( num == INFO_ENERGY ) strcpy(text, "Pile disponible");
- if ( num == INFO_NUCLEAR ) strcpy(text, "Pile nucléaire disponible");
- if ( num == INFO_FINDING ) strcpy(text, "Vous avez trouvé un objet utilisable");
- if ( num == INFO_MARKPOWER ) strcpy(text, "Emplacement pour station trouvé");
- if ( num == INFO_MARKURANIUM ) strcpy(text, "Emplacement pour derrick trouvé");
- if ( num == INFO_MARKSTONE ) strcpy(text, "Emplacement pour derrick trouvé");
- if ( num == INFO_MARKKEYa ) strcpy(text, "Emplacement pour derrick trouvé");
- if ( num == INFO_MARKKEYb ) strcpy(text, "Emplacement pour derrick trouvé");
- if ( num == INFO_MARKKEYc ) strcpy(text, "Emplacement pour derrick trouvé");
- if ( num == INFO_MARKKEYd ) strcpy(text, "Emplacement pour derrick trouvé");
- if ( num == INFO_WIN ) strcpy(text, "<<< Bravo, mission terminée >>>");
- if ( num == INFO_LOST ) strcpy(text, "<<< Désolé, mission échouée >>>");
- if ( num == INFO_LOSTq ) strcpy(text, "<<< Désolé, mission échouée >>>");
- if ( num == INFO_WRITEOK ) strcpy(text, "Enregistrement effectué");
- if ( num == INFO_DELETEPATH ) strcpy(text, "Indicateur atteint");
- if ( num == INFO_DELETEMOTHER ) strcpy(text, "Pondeuse mortellement touchée");
- if ( num == INFO_DELETEANT ) strcpy(text, "Fourmi mortellement touchée");
- if ( num == INFO_DELETEBEE ) strcpy(text, "Guêpe mortellement touchée");
- if ( num == INFO_DELETEWORM ) strcpy(text, "Ver mortellement touché");
- if ( num == INFO_DELETESPIDER ) strcpy(text, "Araignée mortellement touchée");
- if ( num == INFO_BEGINSATCOM ) strcpy(text, "Consultez votre SatCom en appuyant sur \\key help;");
- }
-
- if ( type == RES_CBOT )
- {
- strcpy(text, "Erreur");
- if ( num == TX_OPENPAR ) strcpy(text, "Il manque une parenthèse ouvrante");
- if ( num == TX_CLOSEPAR ) strcpy(text, "Il manque une parenthèse fermante");
- if ( num == TX_NOTBOOL ) strcpy(text, "L'expression doit être un boolean");
- if ( num == TX_UNDEFVAR ) strcpy(text, "Variable non déclarée");
- if ( num == TX_BADLEFT ) strcpy(text, "Assignation impossible");
- if ( num == TX_ENDOF ) strcpy(text, "Terminateur point-virgule non trouvé");
- if ( num == TX_OUTCASE ) strcpy(text, "Instruction ""case"" hors d'un bloc ""switch""");
- if ( num == TX_NOTERM ) strcpy(text, "Instructions après la fin");
- if ( num == TX_CLOSEBLK ) strcpy(text, "Il manque la fin du bloc");
- if ( num == TX_ELSEWITHOUTIF ) strcpy(text, "Instruction ""else"" sans ""if"" correspondant");
- if ( num == TX_OPENBLK ) strcpy(text, "Début d'un bloc attendu");
- if ( num == TX_BADTYPE ) strcpy(text, "Mauvais type de résultat pour l'assignation");
- if ( num == TX_REDEFVAR ) strcpy(text, "Redéfinition d'une variable");
- if ( num == TX_BAD2TYPE ) strcpy(text, "Les deux opérandes ne sont pas de types compatibles");
- if ( num == TX_UNDEFCALL ) strcpy(text, "Routine inconnue");
- if ( num == TX_MISDOTS ) strcpy(text, "Séparateur "" : "" attendu");
- if ( num == TX_WHILE ) strcpy(text, "Manque le mot ""while""");
- if ( num == TX_BREAK ) strcpy(text, "Instruction ""break"" en dehors d'une boucle");
- if ( num == TX_LABEL ) strcpy(text, "Un label ne peut se placer que devant un ""for"", un ""while"", un ""do"" ou un ""switch""");
- if ( num == TX_NOLABEL ) strcpy(text, "Cette étiquette n'existe pas");
- if ( num == TX_NOCASE ) strcpy(text, "Manque une instruction ""case""");
- if ( num == TX_BADNUM ) strcpy(text, "Un nombre est attendu");
- if ( num == TX_VOID ) strcpy(text, "Paramètre void");
- if ( num == TX_NOTYP ) strcpy(text, "Déclaration de type attendu");
- if ( num == TX_NOVAR ) strcpy(text, "Nom d'une variable attendu");
- if ( num == TX_NOFONC ) strcpy(text, "Nom de la fonction attendu");
- if ( num == TX_OVERPARAM ) strcpy(text, "Trop de paramètres");
- if ( num == TX_REDEF ) strcpy(text, "Cette fonction existe déjà");
- if ( num == TX_LOWPARAM ) strcpy(text, "Pas assez de paramètres");
- if ( num == TX_BADPARAM ) strcpy(text, "Aucune fonction de ce nom n'accepte ce(s) type(s) de paramètre(s)");
- if ( num == TX_NUMPARAM ) strcpy(text, "Aucune fonction de ce nom n'accepte ce nombre de paramètres");
- if ( num == TX_NOITEM ) strcpy(text, "Cet élément n'existe pas dans cette classe");
- if ( num == TX_DOT ) strcpy(text, "L'objet n'est pas une instance d'une classe");
- if ( num == TX_NOCONST ) strcpy(text, "Il n'y a pas de constructeur approprié");
- if ( num == TX_REDEFCLASS ) strcpy(text, "Cette classe existe déjà");
- if ( num == TX_CLBRK ) strcpy(text, """ ] "" attendu");
- if ( num == TX_RESERVED ) strcpy(text, "Ce mot est réservé");
- if ( num == TX_BADNEW ) strcpy(text, "Mauvais argument pour ""new""");
- if ( num == TX_OPBRK ) strcpy(text, """ [ "" attendu");
- if ( num == TX_BADSTRING ) strcpy(text, "Une chaîne de caractère est attendue");
- if ( num == TX_BADINDEX ) strcpy(text, "Mauvais type d'index");
- if ( num == TX_PRIVATE ) strcpy(text, "Elément protégé");
- if ( num == TX_NOPUBLIC ) strcpy(text, "Public requis");
- if ( num == TX_DIVZERO ) strcpy(text, "Division par zéro");
- if ( num == TX_NOTINIT ) strcpy(text, "Variable non initialisée");
- if ( num == TX_BADTHROW ) strcpy(text, "Valeur négative refusée pour ""throw""");
- if ( num == TX_NORETVAL ) strcpy(text, "La fonction n'a pas retourné de résultat");
- if ( num == TX_NORUN ) strcpy(text, "Pas de fonction en exécution");
- if ( num == TX_NOCALL ) strcpy(text, "Appel d'une fonction inexistante");
- if ( num == TX_NOCLASS ) strcpy(text, "Cette classe n'existe pas");
- if ( num == TX_NULLPT ) strcpy(text, "Objet n'existe pas");
- if ( num == TX_OPNAN ) strcpy(text, "Opération sur un ""nan""");
- if ( num == TX_OUTARRAY ) strcpy(text, "Accès hors du tableau");
- if ( num == TX_STACKOVER ) strcpy(text, "Débordement de la pile");
- if ( num == TX_DELETEDPT ) strcpy(text, "Objet inaccessible");
- if ( num == TX_FILEOPEN ) strcpy(text, "Ouverture du fichier impossible");
- if ( num == TX_NOTOPEN ) strcpy(text, "Le fichier n'est pas ouvert");
- if ( num == TX_ERRREAD ) strcpy(text, "Erreur à la lecture");
- if ( num == TX_ERRWRITE ) strcpy(text, "Erreur à l'écriture");
- }
-
- if ( type == RES_KEY )
- {
- if ( num == 0 ) strcpy(text, "< aucune >");
- if ( num == VK_LEFT ) strcpy(text, "Flèche Gauche");
- if ( num == VK_RIGHT ) strcpy(text, "Flèche Droite");
- if ( num == VK_UP ) strcpy(text, "Flèche Haut");
- if ( num == VK_DOWN ) strcpy(text, "Flèche Bas");
- if ( num == VK_CANCEL ) strcpy(text, "Control-break");
- if ( num == VK_BACK ) strcpy(text, "<--");
- if ( num == VK_TAB ) strcpy(text, "Tab");
- if ( num == VK_CLEAR ) strcpy(text, "Clear");
- if ( num == VK_RETURN ) strcpy(text, "Entrée");
- if ( num == VK_SHIFT ) strcpy(text, "Shift");
- if ( num == VK_CONTROL ) strcpy(text, "Ctrl");
- if ( num == VK_MENU ) strcpy(text, "Alt");
- if ( num == VK_PAUSE ) strcpy(text, "Pause");
- if ( num == VK_CAPITAL ) strcpy(text, "Caps Lock");
- if ( num == VK_ESCAPE ) strcpy(text, "Esc");
- if ( num == VK_SPACE ) strcpy(text, "Espace");
- if ( num == VK_PRIOR ) strcpy(text, "Page Up");
- if ( num == VK_NEXT ) strcpy(text, "Page Down");
- if ( num == VK_END ) strcpy(text, "End");
- if ( num == VK_HOME ) strcpy(text, "Home");
- if ( num == VK_SELECT ) strcpy(text, "Select");
- if ( num == VK_EXECUTE ) strcpy(text, "Execute");
- if ( num == VK_SNAPSHOT ) strcpy(text, "Print Scrn");
- if ( num == VK_INSERT ) strcpy(text, "Insert");
- if ( num == VK_DELETE ) strcpy(text, "Delete");
- if ( num == VK_HELP ) strcpy(text, "Help");
- if ( num == VK_LWIN ) strcpy(text, "Left Windows");
- if ( num == VK_RWIN ) strcpy(text, "Right Windows");
- if ( num == VK_APPS ) strcpy(text, "Application key");
- if ( num == VK_NUMPAD0 ) strcpy(text, "NumPad 0");
- if ( num == VK_NUMPAD1 ) strcpy(text, "NumPad 1");
- if ( num == VK_NUMPAD2 ) strcpy(text, "NumPad 2");
- if ( num == VK_NUMPAD3 ) strcpy(text, "NumPad 3");
- if ( num == VK_NUMPAD4 ) strcpy(text, "NumPad 4");
- if ( num == VK_NUMPAD5 ) strcpy(text, "NumPad 5");
- if ( num == VK_NUMPAD6 ) strcpy(text, "NumPad 6");
- if ( num == VK_NUMPAD7 ) strcpy(text, "NumPad 7");
- if ( num == VK_NUMPAD8 ) strcpy(text, "NumPad 8");
- if ( num == VK_NUMPAD9 ) strcpy(text, "NumPad 9");
- if ( num == VK_MULTIPLY ) strcpy(text, "NumPad *");
- if ( num == VK_ADD ) strcpy(text, "NumPad +");
- if ( num == VK_SEPARATOR ) strcpy(text, "NumPad sep");
- if ( num == VK_SUBTRACT ) strcpy(text, "NumPad -");
- if ( num == VK_DECIMAL ) strcpy(text, "NumPad .");
- if ( num == VK_DIVIDE ) strcpy(text, "NumPad /");
- if ( num == VK_F1 ) strcpy(text, "F1");
- if ( num == VK_F2 ) strcpy(text, "F2");
- if ( num == VK_F3 ) strcpy(text, "F3");
- if ( num == VK_F4 ) strcpy(text, "F4");
- if ( num == VK_F5 ) strcpy(text, "F5");
- if ( num == VK_F6 ) strcpy(text, "F6");
- if ( num == VK_F7 ) strcpy(text, "F7");
- if ( num == VK_F8 ) strcpy(text, "F8");
- if ( num == VK_F9 ) strcpy(text, "F9");
- if ( num == VK_F10 ) strcpy(text, "F10");
- if ( num == VK_F11 ) strcpy(text, "F11");
- if ( num == VK_F12 ) strcpy(text, "F12");
- if ( num == VK_F13 ) strcpy(text, "F13");
- if ( num == VK_F14 ) strcpy(text, "F14");
- if ( num == VK_F15 ) strcpy(text, "F15");
- if ( num == VK_F16 ) strcpy(text, "F16");
- if ( num == VK_F17 ) strcpy(text, "F17");
- if ( num == VK_F18 ) strcpy(text, "F18");
- if ( num == VK_F19 ) strcpy(text, "F19");
- if ( num == VK_F20 ) strcpy(text, "F20");
- if ( num == VK_NUMLOCK ) strcpy(text, "Num Lock");
- if ( num == VK_SCROLL ) strcpy(text, "Scroll");
- if ( num == VK_ATTN ) strcpy(text, "Attn");
- if ( num == VK_CRSEL ) strcpy(text, "CrSel");
- if ( num == VK_EXSEL ) strcpy(text, "ExSel");
- if ( num == VK_EREOF ) strcpy(text, "Erase EOF");
- if ( num == VK_PLAY ) strcpy(text, "Play");
- if ( num == VK_ZOOM ) strcpy(text, "Zoom");
- if ( num == VK_PA1 ) strcpy(text, "PA1");
- if ( num == VK_OEM_CLEAR ) strcpy(text, "Clear");
- if ( num == VK_BUTTON1 ) strcpy(text, "Bouton 1");
- if ( num == VK_BUTTON2 ) strcpy(text, "Bouton 2");
- if ( num == VK_BUTTON3 ) strcpy(text, "Bouton 3");
- if ( num == VK_BUTTON4 ) strcpy(text, "Bouton 4");
- if ( num == VK_BUTTON5 ) strcpy(text, "Bouton 5");
- if ( num == VK_BUTTON6 ) strcpy(text, "Bouton 6");
- if ( num == VK_BUTTON7 ) strcpy(text, "Bouton 7");
- if ( num == VK_BUTTON8 ) strcpy(text, "Bouton 8");
- if ( num == VK_BUTTON9 ) strcpy(text, "Bouton 9");
- if ( num == VK_BUTTON10 ) strcpy(text, "Bouton 10");
- if ( num == VK_BUTTON11 ) strcpy(text, "Bouton 11");
- if ( num == VK_BUTTON12 ) strcpy(text, "Bouton 12");
- if ( num == VK_BUTTON13 ) strcpy(text, "Bouton 13");
- if ( num == VK_BUTTON14 ) strcpy(text, "Bouton 14");
- if ( num == VK_BUTTON15 ) strcpy(text, "Bouton 15");
- if ( num == VK_BUTTON16 ) strcpy(text, "Bouton 16");
- if ( num == VK_BUTTON17 ) strcpy(text, "Bouton 17");
- if ( num == VK_BUTTON18 ) strcpy(text, "Bouton 18");
- if ( num == VK_BUTTON19 ) strcpy(text, "Bouton 19");
- if ( num == VK_BUTTON20 ) strcpy(text, "Bouton 20");
- if ( num == VK_BUTTON21 ) strcpy(text, "Bouton 21");
- if ( num == VK_BUTTON22 ) strcpy(text, "Bouton 22");
- if ( num == VK_BUTTON23 ) strcpy(text, "Bouton 23");
- if ( num == VK_BUTTON24 ) strcpy(text, "Bouton 24");
- if ( num == VK_BUTTON25 ) strcpy(text, "Bouton 25");
- if ( num == VK_BUTTON26 ) strcpy(text, "Bouton 26");
- if ( num == VK_BUTTON27 ) strcpy(text, "Bouton 27");
- if ( num == VK_BUTTON28 ) strcpy(text, "Bouton 28");
- if ( num == VK_BUTTON29 ) strcpy(text, "Bouton 29");
- if ( num == VK_BUTTON30 ) strcpy(text, "Bouton 30");
- if ( num == VK_BUTTON31 ) strcpy(text, "Bouton 31");
- if ( num == VK_BUTTON32 ) strcpy(text, "Bouton 32");
- if ( num == VK_WHEELUP ) strcpy(text, "Molette haut");
- if ( num == VK_WHEELDOWN ) strcpy(text, "Molette bas");
- }
-#endif
-
-#if _GERMAN | _WG
- if ( type == RES_TEXT )
- {
- #if _FULL
- if ( num == RT_VERSION_ID ) strcpy(text, "1.18 /d");
- #endif
- #if _NET
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A 1.18");
- #endif
- #if _SCHOOL & _EDU
- #if _TEEN
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen EDU 1.18");
- #else
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A EDU 1.18");
- #endif
- #endif
- #if _SCHOOL & _PERSO
- #if _TEEN
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen PERSO 1.18");
- #else
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A PERSO 1.18");
- #endif
- #endif
- #if _SCHOOL & _CEEBOTDEMO
- #if _TEEN
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen DEMO 1.18");
- #else
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A DEMO 1.18");
- #endif
- #endif
- #if _DEMO
- if ( num == RT_VERSION_ID ) strcpy(text, "Demo 1.18 /d");
- #endif
- if ( num == RT_DISINFO_TITLE ) strcpy(text, "SatCom");
- if ( num == RT_WINDOW_MAXIMIZED ) strcpy(text, "Großes Fenster");
- if ( num == RT_WINDOW_MINIMIZED ) strcpy(text, "Reduzieren");
- if ( num == RT_WINDOW_STANDARD ) strcpy(text, "Normale Größe");
- if ( num == RT_WINDOW_CLOSE ) strcpy(text, "Schließen");
-
- if ( num == RT_STUDIO_TITLE ) strcpy(text, "Programmeditor");
- if ( num == RT_SCRIPT_NEW ) strcpy(text, "Neu");
- if ( num == RT_NAME_DEFAULT ) strcpy(text, "Spieler");
- if ( num == RT_IO_NEW ) strcpy(text, "Neu ...");
- if ( num == RT_KEY_OR ) strcpy(text, " oder ");
-
-#if _NEWLOOK
- if ( num == RT_TITLE_BASE ) strcpy(text, "CeeBot");
- if ( num == RT_TITLE_INIT ) strcpy(text, "CeeBot");
-#else
- if ( num == RT_TITLE_BASE ) strcpy(text, "COLOBOT");
- if ( num == RT_TITLE_INIT ) strcpy(text, "COLOBOT");
-#endif
-#if _SCHOOL
- if ( num == RT_TITLE_TRAINER ) strcpy(text, "Übungen");
-#else
- if ( num == RT_TITLE_TRAINER ) strcpy(text, "Programmieren");
-#endif
- if ( num == RT_TITLE_DEFI ) strcpy(text, "Challenges");
- if ( num == RT_TITLE_MISSION ) strcpy(text, "Missionen");
- if ( num == RT_TITLE_FREE ) strcpy(text, "Freestyle");
- if ( num == RT_TITLE_TEEN ) strcpy(text, "Freestyle");
- if ( num == RT_TITLE_USER ) strcpy(text, "Userlevels");
- if ( num == RT_TITLE_PROTO ) strcpy(text, "Prototypen");
- if ( num == RT_TITLE_SETUP ) strcpy(text, "Einstellungen");
- if ( num == RT_TITLE_NAME ) strcpy(text, "Name ");
- if ( num == RT_TITLE_PERSO ) strcpy(text, "Aussehen einstellen");
- if ( num == RT_TITLE_WRITE ) strcpy(text, "Aktuelle Mission speichern");
- if ( num == RT_TITLE_READ ) strcpy(text, "Gespeicherte Mission laden");
-
- if ( num == RT_PLAY_CHAPt ) strcpy(text, " Liste der Kapitel:");
- if ( num == RT_PLAY_CHAPd ) strcpy(text, " Liste der Kapitel:");
- if ( num == RT_PLAY_CHAPm ) strcpy(text, " Liste der Planeten:");
- if ( num == RT_PLAY_CHAPf ) strcpy(text, " Liste der Planeten:");
- if ( num == RT_PLAY_CHAPu ) strcpy(text, " Userlevels:");
- if ( num == RT_PLAY_CHAPp ) strcpy(text, " Liste der Planeten:");
- if ( num == RT_PLAY_CHAPte ) strcpy(text, " Liste der Kapitel:");
- if ( num == RT_PLAY_LISTt ) strcpy(text, " Liste der Übungen des Kapitels:");
- if ( num == RT_PLAY_LISTd ) strcpy(text, " Liste der Challenges des Kapitels:");
- if ( num == RT_PLAY_LISTm ) strcpy(text, " Liste der Missionen des Planeten:");
- if ( num == RT_PLAY_LISTf ) strcpy(text, " Liste der freien Levels des Planeten:");
- if ( num == RT_PLAY_LISTu ) strcpy(text, " Missionen des Userlevels:");
- if ( num == RT_PLAY_LISTp ) strcpy(text, " Liste der Prototypen des Planeten:");
- if ( num == RT_PLAY_LISTk ) strcpy(text, " Liste der freien Levels des Kapitel:");
- if ( num == RT_PLAY_RESUME ) strcpy(text, " Zusammenfassung:");
-
- if ( num == RT_SETUP_DEVICE ) strcpy(text, " Driver:");
- if ( num == RT_SETUP_MODE ) strcpy(text, " Auflösung:");
- if ( num == RT_SETUP_KEY1 ) strcpy(text, "1) Klicken Sie auf die neu zu definierende Taste.");
- if ( num == RT_SETUP_KEY2 ) strcpy(text, "2) Drücken Sie auf die neue Taste.");
-
- if ( num == RT_PERSO_FACE ) strcpy(text, "Kopf:");
- if ( num == RT_PERSO_GLASSES ) strcpy(text, "Brille:");
- if ( num == RT_PERSO_HAIR ) strcpy(text, "Haarfarbe:");
- if ( num == RT_PERSO_COMBI ) strcpy(text, "Farbe des Anzugs:");
- if ( num == RT_PERSO_BAND ) strcpy(text, "Farbe der Streifen:");
-
-#if _NEWLOOK
- if ( num == RT_DIALOG_TITLE ) strcpy(text, "CeeBot");
- if ( num == RT_DIALOG_QUIT ) strcpy(text, "Wollen Sie CeeBot schließen ?");
- if ( num == RT_DIALOG_YESQUIT ) strcpy(text, "Schließen\\CeeBot schließen");
-#else
- if ( num == RT_DIALOG_TITLE ) strcpy(text, "COLOBOT");
- if ( num == RT_DIALOG_QUIT ) strcpy(text, "Wollen Sie COLOBOT schließen ?");
- if ( num == RT_DIALOG_YESQUIT ) strcpy(text, "Schließen\\COLOBOT schließen");
-#endif
- if ( num == RT_DIALOG_ABORT ) strcpy(text, "Mission abbrechen ?");
- if ( num == RT_DIALOG_YES ) strcpy(text, "Abbrechen\\Mission abbrechen");
- if ( num == RT_DIALOG_NO ) strcpy(text, "Weitermachen\\Mission weitermachen");
- if ( num == RT_DIALOG_NOQUIT ) strcpy(text, "Weitermachen\\Weitermachen");
- if ( num == RT_DIALOG_DELOBJ ) strcpy(text, "Wollen Sie das angewählte Gebäude wirklich zerstören ?");
- if ( num == RT_DIALOG_DELGAME ) strcpy(text, "Wollen Sie die gespeicherten Missionen von %s löschen ?");
- if ( num == RT_DIALOG_YESDEL ) strcpy(text, "Zerstören");
- if ( num == RT_DIALOG_NODEL ) strcpy(text, "Abbrechen");
- if ( num == RT_DIALOG_LOADING ) strcpy(text, "Laden");
-
- if ( num == RT_STUDIO_LISTTT ) strcpy(text, "Hilfe über den Begriff (\\key cbot;)");
- if ( num == RT_STUDIO_COMPOK ) strcpy(text, "Kompilieren OK (0 Fehler)");
- if ( num == RT_STUDIO_PROGSTOP ) strcpy(text, "Programm beendet");
-
- if ( num == RT_SATCOM_LIST ) strcpy(text, "\\b;Liste der Objekte\n");
- if ( num == RT_SATCOM_BOT ) strcpy(text, "\\b;Liste der Roboter\n");
- if ( num == RT_SATCOM_BUILDING ) strcpy(text, "\\b;Listes der Gebäude\n");
- if ( num == RT_SATCOM_FRET ) strcpy(text, "\\b;Listes der tragbaren Gegenstände\n");
- if ( num == RT_SATCOM_ALIEN ) strcpy(text, "\\b;Listes der Feinde\n");
- if ( num == RT_SATCOM_NULL ) strcpy(text, "\\c; (keine)\\n;\n");
- if ( num == RT_SATCOM_ERROR1 ) strcpy(text, "\\b;Fehler\n");
- if ( num == RT_SATCOM_ERROR2 ) strcpy(text, "Die Liste ist ohne \\l;Radar\\u object\\radar; nicht verfügbar !\n");
-
- if ( num == RT_IO_OPEN ) strcpy(text, "Öffnen");
- if ( num == RT_IO_SAVE ) strcpy(text, "Speichern");
- if ( num == RT_IO_LIST ) strcpy(text, "Ordner: %s");
- if ( num == RT_IO_NAME ) strcpy(text, "Name:");
- if ( num == RT_IO_DIR ) strcpy(text, "In:");
- if ( num == RT_IO_PRIVATE ) strcpy(text, "Privat\\Privater Ordner");
- if ( num == RT_IO_PUBLIC ) strcpy(text, "Öffentlich\\Gemeinsamer Ordner für alle Spieler");
-
- if ( num == RT_GENERIC_DEV1 ) strcpy(text, "Entwickelt von:");
- if ( num == RT_GENERIC_DEV2 ) strcpy(text, "www.epsitec.com");
-#if _WG
- if ( num == RT_GENERIC_EDIT1 ) strcpy(text, "Herausgegeben von:");
- if ( num == RT_GENERIC_EDIT2 ) strcpy(text, "www.wg-verlag.ch");
-#else
- if ( num == RT_GENERIC_EDIT1 ) strcpy(text, " ");
- if ( num == RT_GENERIC_EDIT2 ) strcpy(text, " ");
-#endif
-
- if ( num == RT_INTERFACE_REC ) strcpy(text, "Recorder");
- }
-
- if ( type == RES_EVENT )
- {
- if ( num == EVENT_BUTTON_OK ) strcpy(text, "OK");
- if ( num == EVENT_BUTTON_CANCEL ) strcpy(text, "Abbrechen");
- if ( num == EVENT_BUTTON_NEXT ) strcpy(text, "Nächster");
- if ( num == EVENT_BUTTON_PREV ) strcpy(text, "Vorherg.");
- if ( num == EVENT_BUTTON_QUIT ) strcpy(text, "Menü (\\key quit;)");
-
- if ( num == EVENT_DIALOG_OK ) strcpy(text, "OK");
- if ( num == EVENT_DIALOG_CANCEL ) strcpy(text, "Abbrechen");
-
-#if _SCHOOL
- if ( num == EVENT_INTERFACE_TRAINER) strcpy(text, "Übungen\\Programmierübungen");
-#else
- if ( num == EVENT_INTERFACE_TRAINER) strcpy(text, "Programmieren\\Programmierübungen");
-#endif
- if ( num == EVENT_INTERFACE_DEFI ) strcpy(text, "Challenges\\Herausforderungen");
- if ( num == EVENT_INTERFACE_MISSION) strcpy(text, "Missionen\\Aufbruch ins Weltall");
- if ( num == EVENT_INTERFACE_FREE ) strcpy(text, "Freestyle\\Freies Spielen ohne vorgegebenes Ziel");
- if ( num == EVENT_INTERFACE_TEEN ) strcpy(text, "Freestyle\\Freies Spielen ohne vorgegebenes Ziel");
- if ( num == EVENT_INTERFACE_USER ) strcpy(text, "User\\Userlevels");
- if ( num == EVENT_INTERFACE_PROTO ) strcpy(text, "Proto\\In Entwicklung befindliche Prototypen");
- if ( num == EVENT_INTERFACE_NAME ) strcpy(text, "Anderer Spieler\\Spielername ändern");
- if ( num == EVENT_INTERFACE_SETUP ) strcpy(text, "Einstellungen\\Einstellungen");
- if ( num == EVENT_INTERFACE_AGAIN ) strcpy(text, "Neu anfangen\\Die Mission von vorne anfangen");
- if ( num == EVENT_INTERFACE_WRITE ) strcpy(text, "Speichern\\Aktuelle Mission speichern");
- if ( num == EVENT_INTERFACE_READ ) strcpy(text, "Laden\\Eine gespeicherte Mission öffnen");
-#if _NEWLOOK
- if ( num == EVENT_INTERFACE_ABORT ) strcpy(text, "\\Zurück zu CeeBot");
- if ( num == EVENT_INTERFACE_QUIT ) strcpy(text, "Schließen\\CeeBot schließen");
-#else
- if ( num == EVENT_INTERFACE_ABORT ) strcpy(text, "\\Zurück zu COLOBOT");
- if ( num == EVENT_INTERFACE_QUIT ) strcpy(text, "Schließen\\COLOBOT schließen");
-#endif
- if ( num == EVENT_INTERFACE_BACK ) strcpy(text, "<< Zurück \\Zurück zum Hauptmenü");
- if ( num == EVENT_INTERFACE_PLAY ) strcpy(text, "Spielen ...\\Los geht's");
- if ( num == EVENT_INTERFACE_SETUPd ) strcpy(text, "Bildschirm\\Driver und Bildschirmauflösung");
- if ( num == EVENT_INTERFACE_SETUPg ) strcpy(text, "Grafik\\Grafische Einstellungen");
- if ( num == EVENT_INTERFACE_SETUPp ) strcpy(text, "Spiel\\Gameplay Einstellungen");
- if ( num == EVENT_INTERFACE_SETUPc ) strcpy(text, "Steuerung\\Auswahl der Tasten");
- if ( num == EVENT_INTERFACE_SETUPs ) strcpy(text, "Geräusche\\Lautstärke Geräusche und Musik");
- if ( num == EVENT_INTERFACE_DEVICE ) strcpy(text, "Einheit");
- if ( num == EVENT_INTERFACE_RESOL ) strcpy(text, "Auflösung");
- if ( num == EVENT_INTERFACE_FULL ) strcpy(text, "Vollbildschirm\\Vollbildschirm oder Fenster");
- if ( num == EVENT_INTERFACE_APPLY ) strcpy(text, "Änderungen ausführen\\Getätigte Einstellungen ausführen");
-
- if ( num == EVENT_INTERFACE_TOTO ) strcpy(text, "Robby\\Ihr Assistent");
- if ( num == EVENT_INTERFACE_SHADOW ) strcpy(text, "Schatten\\Schlagschatten auf dem Boden");
- if ( num == EVENT_INTERFACE_GROUND ) strcpy(text, "Markierungen\\Markierungen auf dem Boden");
- if ( num == EVENT_INTERFACE_DIRTY ) strcpy(text, "Schmutz\\Schmutz auf Robotern und Bauten");
- if ( num == EVENT_INTERFACE_FOG ) strcpy(text, "Nebel\\Nebelschwaden");
- if ( num == EVENT_INTERFACE_LENS ) strcpy(text, "Sonnenstrahlen\\Sonnenstrahlen");
- if ( num == EVENT_INTERFACE_SKY ) strcpy(text, "Himmel\\Himmel und Wolken");
- if ( num == EVENT_INTERFACE_PLANET ) strcpy(text, "Planeten und Sterne\\Kreisende Planeten und Sterne");
- if ( num == EVENT_INTERFACE_LIGHT ) strcpy(text, "Dynamische Beleuchtung\\Dynamische Beleuchtung");
- if ( num == EVENT_INTERFACE_PARTI ) strcpy(text, "Anzahl Partikel\\Explosionen, Staub, usw.");
- if ( num == EVENT_INTERFACE_CLIP ) strcpy(text, "Sichtweite\\Maximale Sichtweite");
- if ( num == EVENT_INTERFACE_DETAIL ) strcpy(text, "Details\\Detailliertheit der Objekte in 3D");
- if ( num == EVENT_INTERFACE_TEXTURE) strcpy(text, "Qualität der Texturen\\Qualität der Anzeige");
- if ( num == EVENT_INTERFACE_GADGET ) strcpy(text, "Anzahl Ziergegenstände\\Anzahl Gegenstände ohne Funktion");
- if ( num == EVENT_INTERFACE_RAIN ) strcpy(text, "Partikel in den Menüs\\Funken und Sterne in den Menüs");
- if ( num == EVENT_INTERFACE_GLINT ) strcpy(text, "Glänzende Tasten\\Glänzende Tasten in den Menüs");
- if ( num == EVENT_INTERFACE_TOOLTIP) strcpy(text, "Hilfsblasen\\Hilfsblasen");
- if ( num == EVENT_INTERFACE_MOVIES ) strcpy(text, "Filme\\Filme vor und nach den Missionen");
- if ( num == EVENT_INTERFACE_NICERST) strcpy(text, "Zurücksetzen \\Kleine Show beim Zurücksetzen in den Übungen");
- if ( num == EVENT_INTERFACE_HIMSELF) strcpy(text, "Eigenbeschuss\\Ihre Einheiten werden von Ihren Waffen beschädigt.");
- if ( num == EVENT_INTERFACE_SCROLL ) strcpy(text, "Kameradrehung mit der Maus\\Die Kamera dreht wenn die Maus den Rand erreicht");
- if ( num == EVENT_INTERFACE_INVERTX) strcpy(text, "Umkehr X\\Umkehr der Kameradrehung X-Achse");
- if ( num == EVENT_INTERFACE_INVERTY) strcpy(text, "Umkehr Y\\Umkehr der Kameradrehung Y-Achse");
- if ( num == EVENT_INTERFACE_EFFECT ) strcpy(text, "Beben bei Explosionen\\Die Kamera bebt bei Explosionen");
- if ( num == EVENT_INTERFACE_MOUSE ) strcpy(text, "Schatten unter der Maus\\Ein Schatten erscheint unter der Maus");
- if ( num == EVENT_INTERFACE_EDITMODE) strcpy(text, "Automatisches Einrücken\\Beim Bearbeiten der Programme");
- if ( num == EVENT_INTERFACE_EDITVALUE)strcpy(text, "Einrücken mit 4 Leerstellen\\Einrücken mit 2 oder 4 Leerstellen");
- if ( num == EVENT_INTERFACE_SOLUCE4) strcpy(text, "Lösung zugänglich\\Die Lösung ist im Programmslot \"4: Lösung\" zugänglich");
-
- if ( num == EVENT_INTERFACE_KDEF ) strcpy(text, "Alles zurücksetzen\\Standarddefinition aller Tasten");
- if ( num == EVENT_INTERFACE_KLEFT ) strcpy(text, "Drehung nach links\\Steuer links");
- if ( num == EVENT_INTERFACE_KRIGHT ) strcpy(text, "Drehung nach rechts\\Steuer rechts");
- if ( num == EVENT_INTERFACE_KUP ) strcpy(text, "Vorwärts\\Bewegung nach vorne");
- if ( num == EVENT_INTERFACE_KDOWN ) strcpy(text, "Rückwärts\\Bewegung nach hinten");
- if ( num == EVENT_INTERFACE_KGUP ) strcpy(text, "Steigen\\Leistung des Triebwerks steigern");
- if ( num == EVENT_INTERFACE_KGDOWN ) strcpy(text, "Sinken\\Leistung des Triebwerks drosseln");
- if ( num == EVENT_INTERFACE_KCAMERA) strcpy(text, "Andere Kamera\\Sichtpunkt einstellen");
- if ( num == EVENT_INTERFACE_KDESEL ) strcpy(text, "Vorherg. Auswahl\\Das vorhergehende Objekt auswählen");
- if ( num == EVENT_INTERFACE_KACTION) strcpy(text, "Standardhandlung\\Führt die Standardhandlung des Roboters aus.");
- if ( num == EVENT_INTERFACE_KNEAR ) strcpy(text, "Kamera näher\\Bewegung der Kamera vorwärts");
- if ( num == EVENT_INTERFACE_KAWAY ) strcpy(text, "Kamera weiter\\Bewegung der Kamera rückwärts");
- if ( num == EVENT_INTERFACE_KNEXT ) strcpy(text, "Nächstes auswählen\\Nächstes Objekt auswählen");
- if ( num == EVENT_INTERFACE_KHUMAN ) strcpy(text, "Astronauten auswählen\\Astronauten auswählen");
- if ( num == EVENT_INTERFACE_KQUIT ) strcpy(text, "Mission verlassen\\Eine Mission oder Übung verlassen");
- if ( num == EVENT_INTERFACE_KHELP ) strcpy(text, "Anweisungen\\Anweisungen für die Mission oder Übung");
- if ( num == EVENT_INTERFACE_KPROG ) strcpy(text, "Hilfe CBOT-Sprache\\Hilfe über die Programmiersprache CBOT");
- if ( num == EVENT_INTERFACE_KCBOT ) strcpy(text, "Hilfe über Begriff\\Hilfe über einen Begriff");
- if ( num == EVENT_INTERFACE_KVISIT ) strcpy(text, "Ort der Meldung\\Zeigt den Ort, von dem die letzte Meldung stammt");
- if ( num == EVENT_INTERFACE_KSPEED10) strcpy(text, "Geschwindigkeit 1.0x\\Normale Spielgeschwindigkeit");
- if ( num == EVENT_INTERFACE_KSPEED15) strcpy(text, "Geschwindigkeit 1.5x\\Spielgeschwindigkeit anderthalb Mal schneller");
- if ( num == EVENT_INTERFACE_KSPEED20) strcpy(text, "Geschwindigkeit 2.0x\\Spielgeschwindigkeit doppelt so schnell");
- if ( num == EVENT_INTERFACE_KSPEED30) strcpy(text, "Geschwindigkeit 3.0x\\Spielgeschwindigkeit drei Mal schneller");
-
- if ( num == EVENT_INTERFACE_VOLSOUND) strcpy(text, "Geräusche:\\Lautstärke Motoren, Stimmen, usw.");
- if ( num == EVENT_INTERFACE_VOLMUSIC) strcpy(text, "Geräuschkulisse:\\Lautstärke der Soundtracks der CD");
- if ( num == EVENT_INTERFACE_SOUND3D) strcpy(text, "3D-Geräusche\\Orten der Geräusche im Raum");
-
- if ( num == EVENT_INTERFACE_MIN ) strcpy(text, "Min.\\Minimale Qualität (großes Framerate)");
- if ( num == EVENT_INTERFACE_NORM ) strcpy(text, "Normal\\Standardqualität");
- if ( num == EVENT_INTERFACE_MAX ) strcpy(text, "Max.\\Beste Qualität (niedriges Framerate)");
-
- if ( num == EVENT_INTERFACE_SILENT ) strcpy(text, "Kein Ton\\Keine Geräusche und Geräuschkulisse");
- if ( num == EVENT_INTERFACE_NOISY ) strcpy(text, "Normal\\Normale Lautstärke");
-
- if ( num == EVENT_INTERFACE_JOYSTICK) strcpy(text, "Joystick\\Joystick oder Tastatur");
- if ( num == EVENT_INTERFACE_SOLUCE ) strcpy(text, "Zeigt die Lösung\\Zeigt nach 3mal Scheitern die Lösung");
-
- if ( num == EVENT_INTERFACE_NEDIT ) strcpy(text, "\\Name des Spielers");
- if ( num == EVENT_INTERFACE_NOK ) strcpy(text, "OK\\Spieler auswählen");
- if ( num == EVENT_INTERFACE_NCANCEL) strcpy(text, "Abbrechen\\Behält den bisherigen Spieler bei");
- if ( num == EVENT_INTERFACE_NDELETE) strcpy(text, "Spieler löschen\\Löscht den Spieler aus der Liste");
- if ( num == EVENT_INTERFACE_NLABEL ) strcpy(text, "Name ");
-
- if ( num == EVENT_INTERFACE_IOWRITE) strcpy(text, "Speichern\\Speichert die Mission");
- if ( num == EVENT_INTERFACE_IOREAD ) strcpy(text, "Laden\\Öffnet eine gespeicherte Mission");
- if ( num == EVENT_INTERFACE_IOLIST ) strcpy(text, "Liste der gespeicherten Missionen");
- if ( num == EVENT_INTERFACE_IOLABEL) strcpy(text, "Dateiname:");
- if ( num == EVENT_INTERFACE_IONAME ) strcpy(text, "Name der Mission");
- if ( num == EVENT_INTERFACE_IOIMAGE) strcpy(text, "Ansicht der Mission");
- if ( num == EVENT_INTERFACE_IODELETE) strcpy(text, "Löschen\\Löscht die gespeicherte Mission");
-
- if ( num == EVENT_INTERFACE_PERSO ) strcpy(text, "Aussehen\\Erscheinungsbild des Astronauten einstellen");
- if ( num == EVENT_INTERFACE_POK ) strcpy(text, "OK");
- if ( num == EVENT_INTERFACE_PCANCEL) strcpy(text, "Abbrechen");
- if ( num == EVENT_INTERFACE_PDEF ) strcpy(text, "Standard\\Standardfarben einsetzen");
- if ( num == EVENT_INTERFACE_PHEAD ) strcpy(text, "Kopf\\Gesicht und Haare");
- if ( num == EVENT_INTERFACE_PBODY ) strcpy(text, "Anzug\\Raumfahrtanzug");
- if ( num == EVENT_INTERFACE_PLROT ) strcpy(text, "\\Drehung links");
- if ( num == EVENT_INTERFACE_PRROT ) strcpy(text, "\\Drehung rechts");
- if ( num == EVENT_INTERFACE_PCRa ) strcpy(text, "Rot");
- if ( num == EVENT_INTERFACE_PCGa ) strcpy(text, "Grün");
- if ( num == EVENT_INTERFACE_PCBa ) strcpy(text, "Blau");
- if ( num == EVENT_INTERFACE_PCRb ) strcpy(text, "Rot");
- if ( num == EVENT_INTERFACE_PCGb ) strcpy(text, "Grün");
- if ( num == EVENT_INTERFACE_PCBb ) strcpy(text, "Blau");
- if ( num == EVENT_INTERFACE_PFACE1 ) strcpy(text, "\\Kopf 1");
- if ( num == EVENT_INTERFACE_PFACE2 ) strcpy(text, "\\Kopf 4");
- if ( num == EVENT_INTERFACE_PFACE3 ) strcpy(text, "\\Kopf 3");
- if ( num == EVENT_INTERFACE_PFACE4 ) strcpy(text, "\\Kopf 2");
- if ( num == EVENT_INTERFACE_PGLASS0) strcpy(text, "\\Keine Brille");
- if ( num == EVENT_INTERFACE_PGLASS1) strcpy(text, "\\Brille 1");
- if ( num == EVENT_INTERFACE_PGLASS2) strcpy(text, "\\Brille 2");
- if ( num == EVENT_INTERFACE_PGLASS3) strcpy(text, "\\Brille 3");
- if ( num == EVENT_INTERFACE_PGLASS4) strcpy(text, "\\Brille 4");
- if ( num == EVENT_INTERFACE_PGLASS5) strcpy(text, "\\Brille 5");
-
- if ( num == EVENT_OBJECT_DESELECT ) strcpy(text, "Vorherg. Auwahl (\\key desel;)");
- if ( num == EVENT_OBJECT_LEFT ) strcpy(text, "Drehung links (\\key left;)");
- if ( num == EVENT_OBJECT_RIGHT ) strcpy(text, "Drehung rechts (\\key right;)");
- if ( num == EVENT_OBJECT_UP ) strcpy(text, "Vorwärts (\\key up;)");
- if ( num == EVENT_OBJECT_DOWN ) strcpy(text, "Rückwärts (\\key down;)");
- if ( num == EVENT_OBJECT_GASUP ) strcpy(text, "Steigt (\\key gup;)");
- if ( num == EVENT_OBJECT_GASDOWN ) strcpy(text, "Sinkt (\\key gdown;)");
- if ( num == EVENT_OBJECT_HTAKE ) strcpy(text, "Nehmen oder hinlegen (\\key action;)");
- if ( num == EVENT_OBJECT_MTAKE ) strcpy(text, "Nehmen oder hinlegen (\\key action;)");
- if ( num == EVENT_OBJECT_MFRONT ) strcpy(text, "..vorne");
- if ( num == EVENT_OBJECT_MBACK ) strcpy(text, "..hinten");
- if ( num == EVENT_OBJECT_MPOWER ) strcpy(text, "..Batterie");
- if ( num == EVENT_OBJECT_BHELP ) strcpy(text, "Anweisungen über die Mission(\\key help;)");
- if ( num == EVENT_OBJECT_BTAKEOFF ) strcpy(text, "Abheben nach vollbrachter Mission");
- if ( num == EVENT_OBJECT_BDERRICK ) strcpy(text, "Baut einen Bohrturm");
- if ( num == EVENT_OBJECT_BSTATION ) strcpy(text, "Baut ein Kraftwerk");
- if ( num == EVENT_OBJECT_BFACTORY ) strcpy(text, "Baut eine Roboterfabrik");
- if ( num == EVENT_OBJECT_BREPAIR ) strcpy(text, "Baut ein Reparaturzentrum");
- if ( num == EVENT_OBJECT_BCONVERT ) strcpy(text, "Baut einen Konverter");
- if ( num == EVENT_OBJECT_BTOWER ) strcpy(text, "Baut einen Geschützturm");
- if ( num == EVENT_OBJECT_BRESEARCH ) strcpy(text, "Baut ein Forschungszentrum");
- if ( num == EVENT_OBJECT_BRADAR ) strcpy(text, "Baut ein Radar");
- if ( num == EVENT_OBJECT_BENERGY ) strcpy(text, "Baut eine Batteriefabrik");
- if ( num == EVENT_OBJECT_BLABO ) strcpy(text, "Baut ein automatisches Labor");
- if ( num == EVENT_OBJECT_BNUCLEAR ) strcpy(text, "Baut eine Brennstoffzellenfabrik");
- if ( num == EVENT_OBJECT_BPARA ) strcpy(text, "Baut einen Blitzableiter");
- if ( num == EVENT_OBJECT_BINFO ) strcpy(text, "Baut einen Infoserver");
- if ( num == EVENT_OBJECT_GFLAT ) strcpy(text, "Zeigt ob der Boden eben ist");
- if ( num == EVENT_OBJECT_FCREATE ) strcpy(text, "Setzt eine Fahne");
- if ( num == EVENT_OBJECT_FDELETE ) strcpy(text, "Sammelt die Fahne ein");
- if ( num == EVENT_OBJECT_FCOLORb ) strcpy(text, "\\Blaue Fahne");
- if ( num == EVENT_OBJECT_FCOLORr ) strcpy(text, "\\Rote Fahne");
- if ( num == EVENT_OBJECT_FCOLORg ) strcpy(text, "\\Grüne Fahne");
- if ( num == EVENT_OBJECT_FCOLORy ) strcpy(text, "\\Gelbe Fahne");
- if ( num == EVENT_OBJECT_FCOLORv ) strcpy(text, "\\Violette Fahne");
- if ( num == EVENT_OBJECT_FACTORYfa ) strcpy(text, "Baut einen Jettransporter");
- if ( num == EVENT_OBJECT_FACTORYta ) strcpy(text, "Baut einen Kettentransporter");
- if ( num == EVENT_OBJECT_FACTORYwa ) strcpy(text, "Baut einen Radtransporter");
- if ( num == EVENT_OBJECT_FACTORYia ) strcpy(text, "Baut einen Krabbeltransporter");
- if ( num == EVENT_OBJECT_FACTORYfc ) strcpy(text, "Baut einen Jetshooter");
- if ( num == EVENT_OBJECT_FACTORYtc ) strcpy(text, "Baut einen Kettenshooter");
- if ( num == EVENT_OBJECT_FACTORYwc ) strcpy(text, "Baut einen Radshooter");
- if ( num == EVENT_OBJECT_FACTORYic ) strcpy(text, "Baut einen Krabbelshooter");
- if ( num == EVENT_OBJECT_FACTORYfi ) strcpy(text, "Baut einen Jetorgashooter");
- if ( num == EVENT_OBJECT_FACTORYti ) strcpy(text, "Baut einen Kettenorgashooter");
- if ( num == EVENT_OBJECT_FACTORYwi ) strcpy(text, "Baut einen Radorgashooter");
- if ( num == EVENT_OBJECT_FACTORYii ) strcpy(text, "Baut einen Krabbelorgashooter");
- if ( num == EVENT_OBJECT_FACTORYfs ) strcpy(text, "Baut einen Jetschnüffler");
- if ( num == EVENT_OBJECT_FACTORYts ) strcpy(text, "Baut einen Kettenschnüffler");
- if ( num == EVENT_OBJECT_FACTORYws ) strcpy(text, "Baut einen Radschnüffler");
- if ( num == EVENT_OBJECT_FACTORYis ) strcpy(text, "Baut einen Krabbelschnüffler");
- if ( num == EVENT_OBJECT_FACTORYrt ) strcpy(text, "Baut einen Stampfer");
- if ( num == EVENT_OBJECT_FACTORYrc ) strcpy(text, "Baut einen Phazershooter");
- if ( num == EVENT_OBJECT_FACTORYrr ) strcpy(text, "Baut einen Recycler");
- if ( num == EVENT_OBJECT_FACTORYrs ) strcpy(text, "Baut einen Schutzschild");
- if ( num == EVENT_OBJECT_FACTORYsa ) strcpy(text, "Baut einen Kettentaucher");
- if ( num == EVENT_OBJECT_RTANK ) strcpy(text, "Forschungsprogramm Kettenantrieb");
- if ( num == EVENT_OBJECT_RFLY ) strcpy(text, "Forschungsprogramm Jetantrieb");
- if ( num == EVENT_OBJECT_RTHUMP ) strcpy(text, "Forschungsprogramm Stampfer");
- if ( num == EVENT_OBJECT_RCANON ) strcpy(text, "Forschungsprogramm Shooterkanone");
- if ( num == EVENT_OBJECT_RTOWER ) strcpy(text, "Forschungsprogramm Geschützturm");
- if ( num == EVENT_OBJECT_RPHAZER ) strcpy(text, "Forschungsprogramm Phazerkanone");
- if ( num == EVENT_OBJECT_RSHIELD ) strcpy(text, "Forschungsprogramm Schutzschild");
- if ( num == EVENT_OBJECT_RATOMIC ) strcpy(text, "Forschungsprogramm Brennstoffzelle");
- if ( num == EVENT_OBJECT_RiPAW ) strcpy(text, "Forschungsprogramm Krabbelantrieb");
- if ( num == EVENT_OBJECT_RiGUN ) strcpy(text, "Forschungsprogramm Orgashooterkanone");
- if ( num == EVENT_OBJECT_RESET ) strcpy(text, "Alles zurücksetzen");
- if ( num == EVENT_OBJECT_SEARCH ) strcpy(text, "Schnüffeln (\\key action;)");
- if ( num == EVENT_OBJECT_TERRAFORM ) strcpy(text, "Stampfen (\\key action;)");
- if ( num == EVENT_OBJECT_FIRE ) strcpy(text, "Feuer (\\key action;)");
- if ( num == EVENT_OBJECT_RECOVER ) strcpy(text, "Recyceln (\\key action;)");
- if ( num == EVENT_OBJECT_BEGSHIELD ) strcpy(text, "Schutzschild ausfahren (\\key action;)");
- if ( num == EVENT_OBJECT_ENDSHIELD ) strcpy(text, "Schutzschild einholen (\\key action;)");
- if ( num == EVENT_OBJECT_DIMSHIELD ) strcpy(text, "Reichweite Schutzschild");
- if ( num == EVENT_OBJECT_PROGRUN ) strcpy(text, "Gewähltes Programm ausführen");
- if ( num == EVENT_OBJECT_PROGEDIT ) strcpy(text, "Gewähltes Programm bearbeiten");
- if ( num == EVENT_OBJECT_INFOOK ) strcpy(text, "\\SatCom in Standby");
- if ( num == EVENT_OBJECT_DELETE ) strcpy(text, "Gebäude sprengen");
- if ( num == EVENT_OBJECT_GENERGY ) strcpy(text, "Energievorrat");
- if ( num == EVENT_OBJECT_GSHIELD ) strcpy(text, "Schäden");
- if ( num == EVENT_OBJECT_GRANGE ) strcpy(text, "Triebwerktemperatur");
- if ( num == EVENT_OBJECT_GPROGRESS ) strcpy(text, "Prozess im Gang ...");
- if ( num == EVENT_OBJECT_GRADAR ) strcpy(text, "Anzahl erfasster Insekten");
- if ( num == EVENT_OBJECT_GINFO ) strcpy(text, "Gesendete Informationen");
- if ( num == EVENT_OBJECT_COMPASS ) strcpy(text, "Kompass");
-//? if ( num == EVENT_OBJECT_MAP ) strcpy(text, "Minikarte");
- if ( num == EVENT_OBJECT_MAPZOOM ) strcpy(text, "Zoom Minikarte");
- if ( num == EVENT_OBJECT_CAMERA ) strcpy(text, "Kamera (\\key camera;)");
- if ( num == EVENT_OBJECT_CAMERAleft) strcpy(text, "Kamera links");
- if ( num == EVENT_OBJECT_CAMERAright) strcpy(text, "Kamera rechts");
- if ( num == EVENT_OBJECT_CAMERAnear) strcpy(text, "Kamera näher");
- if ( num == EVENT_OBJECT_CAMERAaway) strcpy(text, "Kamera weiter weg");
- if ( num == EVENT_OBJECT_HELP ) strcpy(text, "Anweisungen über das ausgewählte Objekt");
- if ( num == EVENT_OBJECT_SOLUCE ) strcpy(text, "Zeigt die Lösung");
- if ( num == EVENT_OBJECT_SHORTCUT00) strcpy(text, "Anzeige Roboter <-> Bauten");
- if ( num == EVENT_OBJECT_LIMIT ) strcpy(text, "Zeigt die Reichweite");
- if ( num == EVENT_OBJECT_PEN0 ) strcpy(text, "\\Bleistift abheben");
- if ( num == EVENT_OBJECT_PEN1 ) strcpy(text, "\\Schwarzen Bleistift hinunterlassen");
- if ( num == EVENT_OBJECT_PEN2 ) strcpy(text, "\\Gelben Bleistift hinunterlassen");
- if ( num == EVENT_OBJECT_PEN3 ) strcpy(text, "\\Orangefarbenen Bleistift hinunterlassen");
- if ( num == EVENT_OBJECT_PEN4 ) strcpy(text, "\\Roten Bleistift hinunterlassen");
- if ( num == EVENT_OBJECT_PEN5 ) strcpy(text, "\\Violetten Bleistift hinunterlassen");
- if ( num == EVENT_OBJECT_PEN6 ) strcpy(text, "\\Blauen Bleistift hinunterlassen");
- if ( num == EVENT_OBJECT_PEN7 ) strcpy(text, "\\Grünen Bleistift hinunterlassen");
- if ( num == EVENT_OBJECT_PEN8 ) strcpy(text, "\\Braunen Bleistift hinunterlassen");
- if ( num == EVENT_OBJECT_REC ) strcpy(text, "\\Aufnahme starten");
- if ( num == EVENT_OBJECT_STOP ) strcpy(text, "\\Aufnahme stoppen");
- if ( num == EVENT_DT_VISIT0 ||
- num == EVENT_DT_VISIT1 ||
- num == EVENT_DT_VISIT2 ||
- num == EVENT_DT_VISIT3 ||
- num == EVENT_DT_VISIT4 ) strcpy(text, "Zeigt den Ort");
- if ( num == EVENT_DT_END ) strcpy(text, "Weitermachen");
- if ( num == EVENT_CMD ) strcpy(text, "Befehleingabe");
- if ( num == EVENT_SPEED ) strcpy(text, "Spielgeschwindigkeit");
-
- if ( num == EVENT_HYPER_PREV ) strcpy(text, "Vorherg. Seite");
- if ( num == EVENT_HYPER_NEXT ) strcpy(text, "Nächste Seite");
- if ( num == EVENT_HYPER_HOME ) strcpy(text, "Home");
- if ( num == EVENT_HYPER_COPY ) strcpy(text, "Kopieren");
- if ( num == EVENT_HYPER_SIZE1 ) strcpy(text, "Größe 1");
- if ( num == EVENT_HYPER_SIZE2 ) strcpy(text, "Größe 2");
- if ( num == EVENT_HYPER_SIZE3 ) strcpy(text, "Größe 3");
- if ( num == EVENT_HYPER_SIZE4 ) strcpy(text, "Größe 4");
- if ( num == EVENT_HYPER_SIZE5 ) strcpy(text, "Größe 5");
- if ( num == EVENT_SATCOM_HUSTON ) strcpy(text, "Anweisungen von Houston");
-#if _TEEN
- if ( num == EVENT_SATCOM_SAT ) strcpy(text, "Wörterbuch Englisch-Deutsch");
-#else
- if ( num == EVENT_SATCOM_SAT ) strcpy(text, "Satellitenbericht");
-#endif
- if ( num == EVENT_SATCOM_LOADING ) strcpy(text, "Von Houston übermittelte Programme");
- if ( num == EVENT_SATCOM_OBJECT ) strcpy(text, "Liste der Objekte");
- if ( num == EVENT_SATCOM_PROG ) strcpy(text, "Hilfe über Programmieren");
- if ( num == EVENT_SATCOM_SOLUCE ) strcpy(text, "Lösung");
-
- if ( num == EVENT_STUDIO_OK ) strcpy(text, "OK\\Programm kompilieren");
- if ( num == EVENT_STUDIO_CANCEL ) strcpy(text, "Abbrechen\\Editor schließen");
- if ( num == EVENT_STUDIO_NEW ) strcpy(text, "Neu");
- if ( num == EVENT_STUDIO_OPEN ) strcpy(text, "Öffnen (Ctrl+o)");
- if ( num == EVENT_STUDIO_SAVE ) strcpy(text, "Speichern (Ctrl+s)");
- if ( num == EVENT_STUDIO_UNDO ) strcpy(text, "Widerrufen (Ctrl+z)");
- if ( num == EVENT_STUDIO_CUT ) strcpy(text, "Ausschneiden (Ctrl+x)");
- if ( num == EVENT_STUDIO_COPY ) strcpy(text, "Kopieren (Ctrl+c)");
- if ( num == EVENT_STUDIO_PASTE ) strcpy(text, "Einfügen (Ctrl+v)");
- if ( num == EVENT_STUDIO_SIZE ) strcpy(text, "Zeichengröße");
- if ( num == EVENT_STUDIO_TOOL ) strcpy(text, "Anweisungen (\\key help;)");
- if ( num == EVENT_STUDIO_HELP ) strcpy(text, "Hilfe über Programmieren (\\key prog;)");
- if ( num == EVENT_STUDIO_COMPILE ) strcpy(text, "Kompilieren");
- if ( num == EVENT_STUDIO_RUN ) strcpy(text, "Start/Stop");
- if ( num == EVENT_STUDIO_REALTIME ) strcpy(text, "Pause/Weitermachen");
- if ( num == EVENT_STUDIO_STEP ) strcpy(text, "Ein Schritt");
- }
-
- if ( type == RES_OBJECT )
- {
- if ( num == OBJECT_PORTICO ) strcpy(text, "Träger");
- if ( num == OBJECT_BASE ) strcpy(text, "Raumschiff");
- if ( num == OBJECT_DERRICK ) strcpy(text, "Bohrturm");
- if ( num == OBJECT_FACTORY ) strcpy(text, "Roboterfabrik");
- if ( num == OBJECT_REPAIR ) strcpy(text, "Reparaturzentrum");
- if ( num == OBJECT_DESTROYER ) strcpy(text, "Einstampfer");
- if ( num == OBJECT_STATION ) strcpy(text, "Kraftwerk");
- if ( num == OBJECT_CONVERT ) strcpy(text, "Konverter Erz-Titan");
- if ( num == OBJECT_TOWER ) strcpy(text, "Geschützturm");
- if ( num == OBJECT_NEST ) strcpy(text, "Orgastoffquelle");
- if ( num == OBJECT_RESEARCH ) strcpy(text, "Forschungszentrum");
- if ( num == OBJECT_RADAR ) strcpy(text, "Radar");
- if ( num == OBJECT_INFO ) strcpy(text, "Infoserver");
-#if _TEEN
- if ( num == OBJECT_ENERGY ) strcpy(text, "Auflöser");
-#else
- if ( num == OBJECT_ENERGY ) strcpy(text, "Batteriefabrik");
-#endif
- if ( num == OBJECT_LABO ) strcpy(text, "Automatisches Labor");
- if ( num == OBJECT_NUCLEAR ) strcpy(text, "Brennstoffzellenfabrik");
- if ( num == OBJECT_PARA ) strcpy(text, "Blitzableiter");
- if ( num == OBJECT_SAFE ) strcpy(text, "Bunker");
- if ( num == OBJECT_HUSTON ) strcpy(text, "Kontrollzentrum");
- if ( num == OBJECT_TARGET1 ) strcpy(text, "Zielscheibe");
- if ( num == OBJECT_TARGET2 ) strcpy(text, "Zielscheibe");
- if ( num == OBJECT_START ) strcpy(text, "Startfläche");
- if ( num == OBJECT_END ) strcpy(text, "Zielfläche");
- if ( num == OBJECT_STONE ) strcpy(text, "Titanerz");
- if ( num == OBJECT_URANIUM ) strcpy(text, "Platinerz");
- if ( num == OBJECT_BULLET ) strcpy(text, "Orgastoff");
- if ( num == OBJECT_METAL ) strcpy(text, "Titan");
- if ( num == OBJECT_POWER ) strcpy(text, "Elektrolytische Batterie");
- if ( num == OBJECT_ATOMIC ) strcpy(text, "Brennstoffzelle");
- if ( num == OBJECT_BBOX ) strcpy(text, "Flugschreiber");
- if ( num == OBJECT_KEYa ) strcpy(text, "Schlüssel A");
- if ( num == OBJECT_KEYb ) strcpy(text, "Schlüssel B");
- if ( num == OBJECT_KEYc ) strcpy(text, "Schlüssel C");
- if ( num == OBJECT_KEYd ) strcpy(text, "Schlüssel D");
- if ( num == OBJECT_TNT ) strcpy(text, "Sprengstoff");
- if ( num == OBJECT_BOMB ) strcpy(text, "Landmine");
- if ( num == OBJECT_BAG ) strcpy(text, "Überlebenskit");
- if ( num == OBJECT_WAYPOINT ) strcpy(text, "Checkpoint");
- if ( num == OBJECT_FLAGb ) strcpy(text, "Blaue Fahne");
- if ( num == OBJECT_FLAGr ) strcpy(text, "Rote Fahne");
- if ( num == OBJECT_FLAGg ) strcpy(text, "Grüne Fahne");
- if ( num == OBJECT_FLAGy ) strcpy(text, "Gelbe Fahne");
- if ( num == OBJECT_FLAGv ) strcpy(text, "Violette Fahne");
- if ( num == OBJECT_MARKPOWER ) strcpy(text, "Markierung für unterirdische Energiequelle");
- if ( num == OBJECT_MARKURANIUM ) strcpy(text, "Markierung für unterirdisches Platinvorkommen");
- if ( num == OBJECT_MARKKEYa ) strcpy(text, "Markierung für vergrabenen Schlüssel A");
- if ( num == OBJECT_MARKKEYb ) strcpy(text, "Markierung für vergrabenen Schlüssel B");
- if ( num == OBJECT_MARKKEYc ) strcpy(text, "Markierung für vergrabenen Schlüssel C");
- if ( num == OBJECT_MARKKEYd ) strcpy(text, "Markierung für vergrabenen Schlüssel D");
- if ( num == OBJECT_MARKSTONE ) strcpy(text, "Markierung für unterirdisches Titanvorkommen");
- if ( num == OBJECT_MOBILEft ) strcpy(text, "Übungsroboter");
- if ( num == OBJECT_MOBILEtt ) strcpy(text, "Übungsroboter");
- if ( num == OBJECT_MOBILEwt ) strcpy(text, "Übungsroboter");
- if ( num == OBJECT_MOBILEit ) strcpy(text, "Übungsroboter");
- if ( num == OBJECT_MOBILEfa ) strcpy(text, "Transporter");
- if ( num == OBJECT_MOBILEta ) strcpy(text, "Transporter");
- if ( num == OBJECT_MOBILEwa ) strcpy(text, "Transporter");
- if ( num == OBJECT_MOBILEia ) strcpy(text, "Transporter");
- if ( num == OBJECT_MOBILEfc ) strcpy(text, "Shooter");
- if ( num == OBJECT_MOBILEtc ) strcpy(text, "Shooter");
- if ( num == OBJECT_MOBILEwc ) strcpy(text, "Shooter");
- if ( num == OBJECT_MOBILEic ) strcpy(text, "Shooter");
- if ( num == OBJECT_MOBILEfi ) strcpy(text, "OrgaShooter");
- if ( num == OBJECT_MOBILEti ) strcpy(text, "OrgaShooter");
- if ( num == OBJECT_MOBILEwi ) strcpy(text, "OrgaShooter");
- if ( num == OBJECT_MOBILEii ) strcpy(text, "OrgaShooter");
- if ( num == OBJECT_MOBILEfs ) strcpy(text, "Schnüffler");
- if ( num == OBJECT_MOBILEts ) strcpy(text, "Schnüffler");
- if ( num == OBJECT_MOBILEws ) strcpy(text, "Schnüffler");
- if ( num == OBJECT_MOBILEis ) strcpy(text, "Schnüffler");
- if ( num == OBJECT_MOBILErt ) strcpy(text, "Stampfer");
- if ( num == OBJECT_MOBILErc ) strcpy(text, "Phazershooter");
- if ( num == OBJECT_MOBILErr ) strcpy(text, "Recycler");
- if ( num == OBJECT_MOBILErs ) strcpy(text, "Schutzschild");
- if ( num == OBJECT_MOBILEsa ) strcpy(text, "Kettentaucher");
- if ( num == OBJECT_MOBILEtg ) strcpy(text, "Mobile Zielscheibe");
- if ( num == OBJECT_MOBILEdr ) strcpy(text, "Zeichner");
- if ( num == OBJECT_HUMAN ) strcpy(text, g_gamerName);
- if ( num == OBJECT_TECH ) strcpy(text, "Techniker");
- if ( num == OBJECT_TOTO ) strcpy(text, "Robby");
- if ( num == OBJECT_MOTHER ) strcpy(text, "Insektenkönigin");
- if ( num == OBJECT_ANT ) strcpy(text, "Ameise");
- if ( num == OBJECT_SPIDER ) strcpy(text, "Spinne");
- if ( num == OBJECT_BEE ) strcpy(text, "Wespe");
- if ( num == OBJECT_WORM ) strcpy(text, "Wurm");
- if ( num == OBJECT_EGG ) strcpy(text, "Ei");
- if ( num == OBJECT_RUINmobilew1 ) strcpy(text, "Roboterwrack");
- if ( num == OBJECT_RUINmobilew2 ) strcpy(text, "Roboterwrack");
- if ( num == OBJECT_RUINmobilet1 ) strcpy(text, "Roboterwrack");
- if ( num == OBJECT_RUINmobilet2 ) strcpy(text, "Roboterwrack");
- if ( num == OBJECT_RUINmobiler1 ) strcpy(text, "Roboterwrack");
- if ( num == OBJECT_RUINmobiler2 ) strcpy(text, "Roboterwrack");
- if ( num == OBJECT_RUINfactory ) strcpy(text, "Gebäuderuine");
- if ( num == OBJECT_RUINdoor ) strcpy(text, "Gebäuderuine");
- if ( num == OBJECT_RUINsupport ) strcpy(text, "Abfall");
- if ( num == OBJECT_RUINradar ) strcpy(text, "Gebäuderuine");
- if ( num == OBJECT_RUINconvert ) strcpy(text, "Gebäuderuine");
- if ( num == OBJECT_RUINbase ) strcpy(text, "Raumschiffruine");
- if ( num == OBJECT_RUINhead ) strcpy(text, "Raumschiffruine");
- if ( num == OBJECT_APOLLO1 ||
- num == OBJECT_APOLLO3 ||
- num == OBJECT_APOLLO4 ||
- num == OBJECT_APOLLO5 ) strcpy(text, "Überreste einer Apollo-Mission");
- if ( num == OBJECT_APOLLO2 ) strcpy(text, "Lunar Roving Vehicle");
- }
-
- if ( type == RES_ERR )
- {
- strcpy(text, "Fehler");
- if ( num == ERR_CMD ) strcpy(text, "Befehl unbekannt");
-#if _NEWLOOK
- if ( num == ERR_INSTALL ) strcpy(text, "CeeBot wurde nicht installiert.");
- if ( num == ERR_NOCD ) strcpy(text, "Legen Sie die CeeBot-CD ein\nund starten Sie das Spiel neu.");
-#else
- if ( num == ERR_INSTALL ) strcpy(text, "COLOBOT wurde nicht installiert.");
- if ( num == ERR_NOCD ) strcpy(text, "Legen Sie die COLOBOT-CD ein\nund starten Sie das Spiel neu.");
-#endif
- if ( num == ERR_MANIP_VEH ) strcpy(text, "Roboter ungeeignet");
- if ( num == ERR_MANIP_FLY ) strcpy(text, "Im Flug unmöglich");
- if ( num == ERR_MANIP_BUSY ) strcpy(text, "Trägt schon etwas");
- if ( num == ERR_MANIP_NIL ) strcpy(text, "Nichts zu ergreifen");
- if ( num == ERR_MANIP_MOTOR ) strcpy(text, "In Fahrt unmöglich");
- if ( num == ERR_MANIP_OCC ) strcpy(text, "Stelle schon besetzt");
- if ( num == ERR_MANIP_FRIEND ) strcpy(text, "Kein anderer Roboter");
- if ( num == ERR_MANIP_RADIO ) strcpy(text, "Sie können keinen radioaktiven Gegenstand tragen");
- if ( num == ERR_MANIP_WATER ) strcpy(text, "Sie können unter Wasser nichts tragen");
- if ( num == ERR_MANIP_EMPTY ) strcpy(text, "Nichts abzulegen");
- if ( num == ERR_BUILD_FLY ) strcpy(text, "Im Flug unmöglich");
- if ( num == ERR_BUILD_WATER ) strcpy(text, "Unter Wasser unmöglich");
- if ( num == ERR_BUILD_ENERGY ) strcpy(text, "Nicht genug Energie");
- if ( num == ERR_BUILD_METALAWAY ) strcpy(text, "Titan zu weit weg");
- if ( num == ERR_BUILD_METALNEAR ) strcpy(text, "Titan zu nahe");
- if ( num == ERR_BUILD_METALINEX ) strcpy(text, "Kein Titan vorhanden");
- if ( num == ERR_BUILD_FLAT ) strcpy(text, "Boden nicht eben genug");
- if ( num == ERR_BUILD_FLATLIT ) strcpy(text, "Ebener Boden nicht groß genug");
- if ( num == ERR_BUILD_BUSY ) strcpy(text, "Stelle schon besetzt");
- if ( num == ERR_BUILD_BASE ) strcpy(text, "Zu nahe am Raumschiff");
- if ( num == ERR_BUILD_NARROW ) strcpy(text, "Zu nahe an einem Gebäude");
- if ( num == ERR_BUILD_MOTOR ) strcpy(text, "In Fahrt unmöglich");
- if ( num == ERR_SEARCH_FLY ) strcpy(text, "Im Flug unmöglich");
- if ( num == ERR_SEARCH_VEH ) strcpy(text, "Roboter ungeeignet");
- if ( num == ERR_SEARCH_MOTOR ) strcpy(text, "In Fahrt unmöglich");
- if ( num == ERR_TERRA_VEH ) strcpy(text, "Roboter ungeeignet");
- if ( num == ERR_TERRA_ENERGY ) strcpy(text, "Nicht genug Energie");
- if ( num == ERR_TERRA_FLOOR ) strcpy(text, "Boden ungeeignet");
- if ( num == ERR_TERRA_BUILDING ) strcpy(text, "Gebäude zu nahe");
- if ( num == ERR_TERRA_OBJECT ) strcpy(text, "Gegenstand zu nahe");
- if ( num == ERR_RECOVER_VEH ) strcpy(text, "Roboter ungeeignet");
- if ( num == ERR_RECOVER_ENERGY ) strcpy(text, "Nicht genug Energie");
- if ( num == ERR_RECOVER_NULL ) strcpy(text, "Nichts zu recyceln");
- if ( num == ERR_SHIELD_VEH ) strcpy(text, "Roboter ungeeignet");
- if ( num == ERR_SHIELD_ENERGY ) strcpy(text, "Keine Energie mehr");
-//? if ( num == ERR_COM ) strcpy(text, "Kommunikationsproblem mit dem Roboter");
- if ( num == ERR_MOVE_IMPOSSIBLE ) strcpy(text, "Ziel kann nicht erreicht werden");
- if ( num == ERR_FIND_IMPOSSIBLE ) strcpy(text, "Das Objekt existiert nicht");
- if ( num == ERR_GOTO_IMPOSSIBLE ) strcpy(text, "Ziel kann nicht erreicht werden");
- if ( num == ERR_GOTO_ITER ) strcpy(text, "Ziel kann nicht erreicht werden");
- if ( num == ERR_GOTO_BUSY ) strcpy(text, "Ziel ist schon besetzt");
- if ( num == ERR_FIRE_VEH ) strcpy(text, "Roboter ungeeignet");
- if ( num == ERR_FIRE_ENERGY ) strcpy(text, "Nicht genug Energie");
- if ( num == ERR_FIRE_FLY ) strcpy(text, "Im Flug unmöglich");
- if ( num == ERR_CONVERT_EMPTY ) strcpy(text, "Kein konvertierbares Titanerz vorhanden");
- if ( num == ERR_DERRICK_NULL ) strcpy(text, "Keine unterirdische Erzlagerstätte");
- if ( num == ERR_STATION_NULL ) strcpy(text, "Kein unterirdisches Energievorkommen");
- if ( num == ERR_TOWER_POWER ) strcpy(text, "Keine Batterie");
- if ( num == ERR_TOWER_ENERGY ) strcpy(text, "Keine Energie mehr");
- if ( num == ERR_RESEARCH_POWER ) strcpy(text, "Keine Batterie");
- if ( num == ERR_RESEARCH_ENERGY ) strcpy(text, "Nicht mehr genug Energie");
- if ( num == ERR_RESEARCH_TYPE ) strcpy(text, "Falscher Batterietyp");
- if ( num == ERR_RESEARCH_ALREADY) strcpy(text, "Forschungsprogramm schon ausgeführt");
- if ( num == ERR_ENERGY_NULL ) strcpy(text, "Kein unterirdisches Energievorkommen");
- if ( num == ERR_ENERGY_LOW ) strcpy(text, "Noch nicht genug Energie");
- if ( num == ERR_ENERGY_EMPTY ) strcpy(text, "Kein konvertierbares Titanerz vorhanden");
- if ( num == ERR_ENERGY_BAD ) strcpy(text, "Wandelt nur Titanerz um");
- if ( num == ERR_BASE_DLOCK ) strcpy(text, "Die Türen werden von einem Gegenstand blockiert");
- if ( num == ERR_BASE_DHUMAN ) strcpy(text, "Gehen Sie an Bord, bevor Sie abheben");
- if ( num == ERR_LABO_NULL ) strcpy(text, "Nichts zu analysieren");
- if ( num == ERR_LABO_BAD ) strcpy(text, "Analysiert nur Orgastoff");
- if ( num == ERR_LABO_ALREADY ) strcpy(text, "Analyse schon durchgeführt");
- if ( num == ERR_NUCLEAR_NULL ) strcpy(text, "Kein unterirdisches Energievorkommen");
- if ( num == ERR_NUCLEAR_LOW ) strcpy(text, "Noch nicht genug Energie");
- if ( num == ERR_NUCLEAR_EMPTY ) strcpy(text, "Kein konvertierbares Platin");
- if ( num == ERR_NUCLEAR_BAD ) strcpy(text, "Wandelt nur Platin um");
- if ( num == ERR_FACTORY_NULL ) strcpy(text, "Kein Titan vorhanden");
- if ( num == ERR_FACTORY_NEAR ) strcpy(text, "Ein Gegenstand ist zu nahe");
- if ( num == ERR_RESET_NEAR ) strcpy(text, "Stelle schon besetzt");
- if ( num == ERR_INFO_NULL ) strcpy(text, "Kein Infoserver in Reichweite");
- if ( num == ERR_VEH_VIRUS ) strcpy(text, "Ein Programm wurde von einem Virus infiziert");
- if ( num == ERR_BAT_VIRUS ) strcpy(text, "Von Virus infiziert, zeitweise außer Betrieb");
- if ( num == ERR_VEH_POWER ) strcpy(text, "Keine Batterie");
- if ( num == ERR_VEH_ENERGY ) strcpy(text, "Keine Energie mehr");
- if ( num == ERR_FLAG_FLY ) strcpy(text, "Im Flug unmöglich");
- if ( num == ERR_FLAG_WATER ) strcpy(text, "Im Wasser unmöglich");
- if ( num == ERR_FLAG_MOTOR ) strcpy(text, "Beim Gehen unmöglich");
- if ( num == ERR_FLAG_BUSY ) strcpy(text, "Unmöglich wenn Sie etwas tragen");
- if ( num == ERR_FLAG_CREATE ) strcpy(text, "Zu viele Fahnen dieser Farbe (Maximum 5)");
- if ( num == ERR_FLAG_PROXY ) strcpy(text, "Zu nahe an einer anderen Fahne");
- if ( num == ERR_FLAG_DELETE ) strcpy(text, "Keine Fahne in Reichweite");
- if ( num == ERR_MISSION_NOTERM ) strcpy(text, "Mission noch nicht beendet (Drücken Sie auf \\key help; für weitere Informationen)");
- if ( num == ERR_DELETEMOBILE ) strcpy(text, "Roboter zerstört");
- if ( num == ERR_DELETEBUILDING ) strcpy(text, "Gebäude zerstört");
- if ( num == ERR_TOOMANY ) strcpy(text, "Kein neues Objekt kann erstellt werden (zu viele vorhanden)");
- if ( num == ERR_OBLIGATORYTOKEN ) strcpy(text, "Es fehlt \"%s\" in Ihrem Programm");
- if ( num == ERR_PROHIBITEDTOKEN ) strcpy(text, "In dieser Übung verboten");
-
- if ( num == INFO_BUILD ) strcpy(text, "Gebäude fertiggestellt");
- if ( num == INFO_CONVERT ) strcpy(text, "Titan verfügbar");
- if ( num == INFO_RESEARCH ) strcpy(text, "Forschungsprogramm abgeschlossen");
- if ( num == INFO_RESEARCHTANK ) strcpy(text, "Herstellung eines Roboters mit Kettenantrieb möglich");
- if ( num == INFO_RESEARCHFLY ) strcpy(text, "Sie können jetzt mit den Tasten \\key gup; und \\key gdown; fliegen");
- if ( num == INFO_RESEARCHTHUMP ) strcpy(text, "Herstellung eines Stampfers möglich");
- if ( num == INFO_RESEARCHCANON ) strcpy(text, "Herstellung eines Shooters möglich");
- if ( num == INFO_RESEARCHTOWER ) strcpy(text, "Errichtung eines Geschützturms möglich");
- if ( num == INFO_RESEARCHPHAZER ) strcpy(text, "Herstellung eines Phazershooters möglich");
- if ( num == INFO_RESEARCHSHIELD ) strcpy(text, "Herstellung eines Schutzschildes möglich");
- if ( num == INFO_RESEARCHATOMIC ) strcpy(text, "Errichtung einer Brennstoffzellenfabrik möglich");
- if ( num == INFO_FACTORY ) strcpy(text, "Neuer Roboter verfügbar");
- if ( num == INFO_LABO ) strcpy(text, "Analyse vollendet");
- if ( num == INFO_ENERGY ) strcpy(text, "Batterie verfügbar");
- if ( num == INFO_NUCLEAR ) strcpy(text, "Brennstoffzelle verfügbar");
- if ( num == INFO_FINDING ) strcpy(text, "Sie haben ein brauchbares Objekt gefunden");
- if ( num == INFO_MARKPOWER ) strcpy(text, "Geeignete Stelle für Kraftwerk gefunden");
- if ( num == INFO_MARKURANIUM ) strcpy(text, "Geeignete Stelle für Bohrturm gefunden");
- if ( num == INFO_MARKSTONE ) strcpy(text, "Geeignete Stelle für Bohrturm gefunden");
- if ( num == INFO_MARKKEYa ) strcpy(text, "Geeignete Stelle für Bohrturm gefunden");
- if ( num == INFO_MARKKEYb ) strcpy(text, "Geeignete Stelle für Bohrturm gefunden");
- if ( num == INFO_MARKKEYc ) strcpy(text, "Geeignete Stelle für Bohrturm gefunden");
- if ( num == INFO_MARKKEYd ) strcpy(text, "Geeignete Stelle für Bohrturm gefunden");
- if ( num == INFO_WIN ) strcpy(text, "<<< Bravo, Mission vollendet >>>");
- if ( num == INFO_LOST ) strcpy(text, "<<< Mission gescheitert >>>");
- if ( num == INFO_LOSTq ) strcpy(text, "<<< Mission gescheitert >>>");
- if ( num == INFO_WRITEOK ) strcpy(text, "Mission gespeichert");
- if ( num == INFO_DELETEPATH ) strcpy(text, "Checkpoint erreicht");
- if ( num == INFO_DELETEMOTHER ) strcpy(text, "Insektenkönigin tödlich verwundet");
- if ( num == INFO_DELETEANT ) strcpy(text, "Ameise tödlich verwundet");
- if ( num == INFO_DELETEBEE ) strcpy(text, "Wespe tödlich verwundet");
- if ( num == INFO_DELETEWORM ) strcpy(text, "Wurm tödlich verwundet");
- if ( num == INFO_DELETESPIDER ) strcpy(text, "Spinne tödlich verwundet");
- if ( num == INFO_BEGINSATCOM ) strcpy(text, "Beziehen Sie sich auf Ihren SatCom, indem Sie auf \\key help; drücken");
- }
-
- if ( type == RES_CBOT )
- {
- strcpy(text, "Fehler");
- if ( num == TX_OPENPAR ) strcpy(text, "Es fehlt eine offene Klammer ""(""");
- if ( num == TX_CLOSEPAR ) strcpy(text, "Es fehlt eine geschlossene Klammer "")""");
- if ( num == TX_NOTBOOL ) strcpy(text, "Der Ausdruck muss einen boolschen Wert ergeben");
- if ( num == TX_UNDEFVAR ) strcpy(text, "Variable nicht deklariert");
- if ( num == TX_BADLEFT ) strcpy(text, "Zuweisung unmöglich");
- if ( num == TX_ENDOF ) strcpy(text, "Es fehlt ein Strichpunkt "";"" am Ende der Anweisung");
- if ( num == TX_OUTCASE ) strcpy(text, "Anweisung ""case"" ohne vorhergehende Anweisung ""switch""");
- if ( num == TX_NOTERM ) strcpy(text, "Hier ist eine Anweisung nach dem Ende des Programms");
- if ( num == TX_CLOSEBLK ) strcpy(text, "Es fehlt eine geschlossene geschweifte Klammer ""}"" (Ende des Blocks)");
- if ( num == TX_ELSEWITHOUTIF ) strcpy(text, "Anweisung ""else"" ohne vorhergehende Anweisung ""if""");
- if ( num == TX_OPENBLK ) strcpy(text, "Es fehlt eine offene geschweifte Klammer""{""");
- if ( num == TX_BADTYPE ) strcpy(text, "Der Ausdruck ergibt einen falschen Typ für die Zuweisung");
- if ( num == TX_REDEFVAR ) strcpy(text, "Eine Variable wird zum zweiten Mal deklariert");
- if ( num == TX_BAD2TYPE ) strcpy(text, "Die zwei Operanden sind nicht kompatibel");
- if ( num == TX_UNDEFCALL ) strcpy(text, "Unbekannte Funktion");
- if ( num == TX_MISDOTS ) strcpy(text, "Es fehlt ein Doppelpunkt "" : """);
- if ( num == TX_WHILE ) strcpy(text, "Es fehlt das Wort ""while""");
- if ( num == TX_BREAK ) strcpy(text, "Anweisung ""break"" außerhalb einer Schleife");
- if ( num == TX_LABEL ) strcpy(text, "Ein Label kann nur vor den Anweisungen ""for"", ""while"", ""do"" oder ""switch"" vorkommen");
- if ( num == TX_NOLABEL ) strcpy(text, "Dieses Label existiert nicht");
- if ( num == TX_NOCASE ) strcpy(text, "Es fehlt eine Anweisung ""case""");
- if ( num == TX_BADNUM ) strcpy(text, "Es fehlt eine Zahl");
- if ( num == TX_VOID ) strcpy(text, "Parameter void");
- if ( num == TX_NOTYP ) strcpy(text, "Hier muss ein Variablentyp stehen");
- if ( num == TX_NOVAR ) strcpy(text, "Es fehlt der Name einer Variable");
- if ( num == TX_NOFONC ) strcpy(text, "Hier muss der Name der Funktion stehen");
- if ( num == TX_OVERPARAM ) strcpy(text, "Zu viele Parameter");
- if ( num == TX_REDEF ) strcpy(text, "Diese Funktion gibt es schon");
- if ( num == TX_LOWPARAM ) strcpy(text, "Nicht genug Parameter");
- if ( num == TX_BADPARAM ) strcpy(text, "Keine Funktion mit diesem Namen verträgt Parameter diesen Typs");
- if ( num == TX_NUMPARAM ) strcpy(text, "Keine Funktion mit diesem Namen verträgt diese Anzahl Parameter");
- if ( num == TX_NOITEM ) strcpy(text, "Dieses Element gibt es nicht in dieser Klasse");
- if ( num == TX_DOT ) strcpy(text, "Das Objekt ist nicht eine Instanz einer Klasse");
- if ( num == TX_NOCONST ) strcpy(text, "Es gibt keinen geeigneten Konstruktor");
- if ( num == TX_REDEFCLASS ) strcpy(text, "Diese Klasse gibt es schon");
- if ( num == TX_CLBRK ) strcpy(text, "Es fehlt eine geschlossene eckige Klammer "" ] """);
- if ( num == TX_RESERVED ) strcpy(text, "Dieses Wort ist reserviert");
- if ( num == TX_BADNEW ) strcpy(text, "Falsche Argumente für ""new""");
- if ( num == TX_OPBRK ) strcpy(text, "Es fehlt eine offene eckige Klammer "" [ """);
- if ( num == TX_BADSTRING ) strcpy(text, "Hier wird eine Zeichenkette erwartet");
- if ( num == TX_BADINDEX ) strcpy(text, "Falscher Typ für einen Index");
- if ( num == TX_PRIVATE ) strcpy(text, "Geschütztes Element (private)");
- if ( num == TX_NOPUBLIC ) strcpy(text, "Hier muss das Wort ""public"" stehen");
- if ( num == TX_DIVZERO ) strcpy(text, "Teilung durch Null");
- if ( num == TX_NOTINIT ) strcpy(text, "Der Wert dieser Variable wurde nicht definiert");
- if ( num == TX_BADTHROW ) strcpy(text, "Negativer Wert ungeeignet für Anweisung ""throw""");
- if ( num == TX_NORETVAL ) strcpy(text, "Die Funktion hat kein Ergebnis zurückgegeben");
- if ( num == TX_NORUN ) strcpy(text, "Keine Funktion wird ausgeführt");
- if ( num == TX_NOCALL ) strcpy(text, "Die aufgerufene Funktion existiert nicht");
- if ( num == TX_NOCLASS ) strcpy(text, "Diese Klasse existiert nicht");
- if ( num == TX_NULLPT ) strcpy(text, "Das Objekt existiert nicht");
- if ( num == TX_OPNAN ) strcpy(text, "Operation mit dem Wert ""nan""");
- if ( num == TX_OUTARRAY ) strcpy(text, "Zugriff im Array außerhalb der Grenzen");
- if ( num == TX_STACKOVER ) strcpy(text, "Stack overflow");
- if ( num == TX_DELETEDPT ) strcpy(text, "Objekt nicht verfügbar");
- if ( num == TX_FILEOPEN ) strcpy(text, "Die Datei kann nicht geöffnet werden");
- if ( num == TX_NOTOPEN ) strcpy(text, "Die Datei wurde nicht geöffnet");
- if ( num == TX_ERRREAD ) strcpy(text, "Fehler beim Lesezugriff");
- if ( num == TX_ERRWRITE ) strcpy(text, "Fehler beim Schreibzugriff");
- }
-
- if ( type == RES_KEY )
- {
- if ( num == 0 ) strcpy(text, "< keine >");
- if ( num == VK_LEFT ) strcpy(text, "Pfeiltaste links");
- if ( num == VK_RIGHT ) strcpy(text, "Pfeiltaste rechts");
- if ( num == VK_UP ) strcpy(text, "Pfeil nach oben");
- if ( num == VK_DOWN ) strcpy(text, "Pfeil nach unten");
- if ( num == VK_CANCEL ) strcpy(text, "Ctrl-Break");
- if ( num == VK_BACK ) strcpy(text, "<--");
- if ( num == VK_TAB ) strcpy(text, "Tab");
- if ( num == VK_CLEAR ) strcpy(text, "Clear");
- if ( num == VK_RETURN ) strcpy(text, "Eingabe");
- if ( num == VK_SHIFT ) strcpy(text, "Shift");
- if ( num == VK_CONTROL ) strcpy(text, "Ctrl");
- if ( num == VK_MENU ) strcpy(text, "Alt");
- if ( num == VK_PAUSE ) strcpy(text, "Pause");
- if ( num == VK_CAPITAL ) strcpy(text, "Caps Lock");
- if ( num == VK_ESCAPE ) strcpy(text, "Esc");
- if ( num == VK_SPACE ) strcpy(text, "Leertaste");
- if ( num == VK_PRIOR ) strcpy(text, "Page Up");
- if ( num == VK_NEXT ) strcpy(text, "Page Down");
- if ( num == VK_END ) strcpy(text, "End");
- if ( num == VK_HOME ) strcpy(text, "Home");
- if ( num == VK_SELECT ) strcpy(text, "Select");
- if ( num == VK_EXECUTE ) strcpy(text, "Execute");
- if ( num == VK_SNAPSHOT ) strcpy(text, "Print Scrn");
- if ( num == VK_INSERT ) strcpy(text, "Insert");
- if ( num == VK_DELETE ) strcpy(text, "Delete");
- if ( num == VK_HELP ) strcpy(text, "Help");
- if ( num == VK_LWIN ) strcpy(text, "Left Windows");
- if ( num == VK_RWIN ) strcpy(text, "Right Windows");
- if ( num == VK_APPS ) strcpy(text, "Application key");
- if ( num == VK_NUMPAD0 ) strcpy(text, "NumPad 0");
- if ( num == VK_NUMPAD1 ) strcpy(text, "NumPad 1");
- if ( num == VK_NUMPAD2 ) strcpy(text, "NumPad 2");
- if ( num == VK_NUMPAD3 ) strcpy(text, "NumPad 3");
- if ( num == VK_NUMPAD4 ) strcpy(text, "NumPad 4");
- if ( num == VK_NUMPAD5 ) strcpy(text, "NumPad 5");
- if ( num == VK_NUMPAD6 ) strcpy(text, "NumPad 6");
- if ( num == VK_NUMPAD7 ) strcpy(text, "NumPad 7");
- if ( num == VK_NUMPAD8 ) strcpy(text, "NumPad 8");
- if ( num == VK_NUMPAD9 ) strcpy(text, "NumPad 9");
- if ( num == VK_MULTIPLY ) strcpy(text, "NumPad *");
- if ( num == VK_ADD ) strcpy(text, "NumPad +");
- if ( num == VK_SEPARATOR ) strcpy(text, "NumPad sep");
- if ( num == VK_SUBTRACT ) strcpy(text, "NumPad -");
- if ( num == VK_DECIMAL ) strcpy(text, "NumPad .");
- if ( num == VK_DIVIDE ) strcpy(text, "NumPad /");
- if ( num == VK_F1 ) strcpy(text, "F1");
- if ( num == VK_F2 ) strcpy(text, "F2");
- if ( num == VK_F3 ) strcpy(text, "F3");
- if ( num == VK_F4 ) strcpy(text, "F4");
- if ( num == VK_F5 ) strcpy(text, "F5");
- if ( num == VK_F6 ) strcpy(text, "F6");
- if ( num == VK_F7 ) strcpy(text, "F7");
- if ( num == VK_F8 ) strcpy(text, "F8");
- if ( num == VK_F9 ) strcpy(text, "F9");
- if ( num == VK_F10 ) strcpy(text, "F10");
- if ( num == VK_F11 ) strcpy(text, "F11");
- if ( num == VK_F12 ) strcpy(text, "F12");
- if ( num == VK_F13 ) strcpy(text, "F13");
- if ( num == VK_F14 ) strcpy(text, "F14");
- if ( num == VK_F15 ) strcpy(text, "F15");
- if ( num == VK_F16 ) strcpy(text, "F16");
- if ( num == VK_F17 ) strcpy(text, "F17");
- if ( num == VK_F18 ) strcpy(text, "F18");
- if ( num == VK_F19 ) strcpy(text, "F19");
- if ( num == VK_F20 ) strcpy(text, "F20");
- if ( num == VK_NUMLOCK ) strcpy(text, "Num Lock");
- if ( num == VK_SCROLL ) strcpy(text, "Scroll");
- if ( num == VK_ATTN ) strcpy(text, "Attn");
- if ( num == VK_CRSEL ) strcpy(text, "CrSel");
- if ( num == VK_EXSEL ) strcpy(text, "ExSel");
- if ( num == VK_EREOF ) strcpy(text, "Erase EOF");
- if ( num == VK_PLAY ) strcpy(text, "Play");
- if ( num == VK_ZOOM ) strcpy(text, "Zoom");
- if ( num == VK_PA1 ) strcpy(text, "PA1");
- if ( num == VK_OEM_CLEAR ) strcpy(text, "Clear");
- if ( num == VK_BUTTON1 ) strcpy(text, "Knopf 1");
- if ( num == VK_BUTTON2 ) strcpy(text, "Knopf 2");
- if ( num == VK_BUTTON3 ) strcpy(text, "Knopf 3");
- if ( num == VK_BUTTON4 ) strcpy(text, "Knopf 4");
- if ( num == VK_BUTTON5 ) strcpy(text, "Knopf 5");
- if ( num == VK_BUTTON6 ) strcpy(text, "Knopf 6");
- if ( num == VK_BUTTON7 ) strcpy(text, "Knopf 7");
- if ( num == VK_BUTTON8 ) strcpy(text, "Knopf 8");
- if ( num == VK_BUTTON9 ) strcpy(text, "Knopf 9");
- if ( num == VK_BUTTON10 ) strcpy(text, "Knopf 10");
- if ( num == VK_BUTTON11 ) strcpy(text, "Knopf 11");
- if ( num == VK_BUTTON12 ) strcpy(text, "Knopf 12");
- if ( num == VK_BUTTON13 ) strcpy(text, "Knopf 13");
- if ( num == VK_BUTTON14 ) strcpy(text, "Knopf 14");
- if ( num == VK_BUTTON15 ) strcpy(text, "Knopf 15");
- if ( num == VK_BUTTON16 ) strcpy(text, "Knopf 16");
- if ( num == VK_BUTTON17 ) strcpy(text, "Knopf 17");
- if ( num == VK_BUTTON18 ) strcpy(text, "Knopf 18");
- if ( num == VK_BUTTON19 ) strcpy(text, "Knopf 19");
- if ( num == VK_BUTTON20 ) strcpy(text, "Knopf 20");
- if ( num == VK_BUTTON21 ) strcpy(text, "Knopf 21");
- if ( num == VK_BUTTON22 ) strcpy(text, "Knopf 22");
- if ( num == VK_BUTTON23 ) strcpy(text, "Knopf 23");
- if ( num == VK_BUTTON24 ) strcpy(text, "Knopf 24");
- if ( num == VK_BUTTON25 ) strcpy(text, "Knopf 25");
- if ( num == VK_BUTTON26 ) strcpy(text, "Knopf 26");
- if ( num == VK_BUTTON27 ) strcpy(text, "Knopf 27");
- if ( num == VK_BUTTON28 ) strcpy(text, "Knopf 28");
- if ( num == VK_BUTTON29 ) strcpy(text, "Knopf 29");
- if ( num == VK_BUTTON30 ) strcpy(text, "Knopf 30");
- if ( num == VK_BUTTON31 ) strcpy(text, "Knopf 31");
- if ( num == VK_BUTTON32 ) strcpy(text, "Knopf 32");
- if ( num == VK_WHEELUP ) strcpy(text, "Mausrad nach vorne");
- if ( num == VK_WHEELDOWN ) strcpy(text, "Mausrad zurück");
- }
-#endif
-
-#if _POLISH
- if ( type == RES_TEXT )
- {
- #if _FULL
- if ( num == RT_VERSION_ID ) strcpy(text, "Wersja 1.18 /pl");
- #endif
- #if _NET
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A 1.18");
- #endif
- #if _SCHOOL & _EDU
- #if _TEEN
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen EDU 1.18");
- #else
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A EDU 1.18");
- #endif
- #endif
- #if _SCHOOL & _PERSO
- #if _TEEN
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen PERSO 1.18");
- #else
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A PERSO 1.18");
- #endif
- #endif
- #if _SCHOOL & _CEEBOTDEMO
- #if _TEEN
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen DEMO 1.18");
- #else
- if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A DEMO 1.18");
- #endif
- #endif
- #if _DEMO
- if ( num == RT_VERSION_ID ) strcpy(text, "Demo 1.18 /pl");
- #endif
- if ( num == RT_DISINFO_TITLE ) strcpy(text, "SatCom");
- if ( num == RT_WINDOW_MAXIMIZED ) strcpy(text, "Powiêksz");
- if ( num == RT_WINDOW_MINIMIZED ) strcpy(text, "Pomniejsz");
- if ( num == RT_WINDOW_STANDARD ) strcpy(text, "Normalna wielkoϾ");
- if ( num == RT_WINDOW_CLOSE ) strcpy(text, "Zamknij");
-
- if ( num == RT_STUDIO_TITLE ) strcpy(text, "Edytor programu");
- if ( num == RT_SCRIPT_NEW ) strcpy(text, "Nowy");
- if ( num == RT_NAME_DEFAULT ) strcpy(text, "Gracz");
- if ( num == RT_IO_NEW ) strcpy(text, "Nowy ...");
- if ( num == RT_KEY_OR ) strcpy(text, " lub ");
-
-#if _NEWLOOK
- if ( num == RT_TITLE_BASE ) strcpy(text, "CeeBot");
- if ( num == RT_TITLE_INIT ) strcpy(text, "CeeBot");
-#else
- if ( num == RT_TITLE_BASE ) strcpy(text, "COLOBOT");
- if ( num == RT_TITLE_INIT ) strcpy(text, "COLOBOT");
-#endif
- if ( num == RT_TITLE_TRAINER ) strcpy(text, "Æwiczenia programistyczne");
- if ( num == RT_TITLE_DEFI ) strcpy(text, "Wyzwania");
- if ( num == RT_TITLE_MISSION ) strcpy(text, "Misje");
- if ( num == RT_TITLE_FREE ) strcpy(text, "Swobodna gra");
- if ( num == RT_TITLE_TEEN ) strcpy(text, "Swobodna gra");
- if ( num == RT_TITLE_USER ) strcpy(text, "Poziomy u¿ytkownika");
- if ( num == RT_TITLE_PROTO ) strcpy(text, "Prototypy");
- if ( num == RT_TITLE_SETUP ) strcpy(text, "Opcje");
- if ( num == RT_TITLE_NAME ) strcpy(text, "Imiê gracza");
- if ( num == RT_TITLE_PERSO ) strcpy(text, "Dostosuj wygl¹d");
- if ( num == RT_TITLE_WRITE ) strcpy(text, "Zapisz bie¿¹c¹ misjê");
- if ( num == RT_TITLE_READ ) strcpy(text, "Wczytaj zapisan¹ misjê");
-
- if ( num == RT_PLAY_CHAPt ) strcpy(text, " Rozdzia³y:");
- if ( num == RT_PLAY_CHAPd ) strcpy(text, " Rozdzia³y:");
- if ( num == RT_PLAY_CHAPm ) strcpy(text, " Planety:");
- if ( num == RT_PLAY_CHAPf ) strcpy(text, " Planety:");
- if ( num == RT_PLAY_CHAPu ) strcpy(text, " Poziomy u¿ytkownika:");
- if ( num == RT_PLAY_CHAPp ) strcpy(text, " Planety:");
- if ( num == RT_PLAY_CHAPte ) strcpy(text, " Planety:");
- if ( num == RT_PLAY_LISTt ) strcpy(text, " Æwiczenia w tym rozdziale:");
- if ( num == RT_PLAY_LISTd ) strcpy(text, " Wyzwania w tym rozdziale:");
- if ( num == RT_PLAY_LISTm ) strcpy(text, " Misje na tej planecie:");
- if ( num == RT_PLAY_LISTf ) strcpy(text, " Swobodna gra na tej planecie:");
- if ( num == RT_PLAY_LISTu ) strcpy(text, " Misje na tym poziomie:");
- if ( num == RT_PLAY_LISTp ) strcpy(text, " Prototypy na tej planecie:");
- if ( num == RT_PLAY_LISTk ) strcpy(text, " Prototypy na tej planecie:");
- if ( num == RT_PLAY_RESUME ) strcpy(text, " Streszczenie:");
-
- if ( num == RT_SETUP_DEVICE ) strcpy(text, " Sterowniki:");
- if ( num == RT_SETUP_MODE ) strcpy(text, " RozdzielczoϾ:");
- if ( num == RT_SETUP_KEY1 ) strcpy(text, "1) Najpierw kliknij klawisz, który chcesz przedefiniowaæ.");
- if ( num == RT_SETUP_KEY2 ) strcpy(text, "2) Nastêpnie naciœnij klawisz, którego chcesz u¿ywaæ.");
-
- if ( num == RT_PERSO_FACE ) strcpy(text, "Rodzaj twarzy:");
- if ( num == RT_PERSO_GLASSES ) strcpy(text, "Okulary:");
- if ( num == RT_PERSO_HAIR ) strcpy(text, "Kolor w³osów:");
- if ( num == RT_PERSO_COMBI ) strcpy(text, "Kolor skafandra:");
- if ( num == RT_PERSO_BAND ) strcpy(text, "Kolor pasków:");
-
-#if _NEWLOOK
- if ( num == RT_DIALOG_TITLE ) strcpy(text, "CeeBot");
- if ( num == RT_DIALOG_QUIT ) strcpy(text, "Czy na pewno chcesz opuœciæ grê CeeBot?");
- if ( num == RT_DIALOG_YESQUIT ) strcpy(text, "Zakoñcz\\Koñczy grê CeeBot");
-#else
- if ( num == RT_DIALOG_TITLE ) strcpy(text, "COLOBOT");
- if ( num == RT_DIALOG_QUIT ) strcpy(text, "Czy na pewno chcesz opuœciæ grê COLOBOT?");
- if ( num == RT_DIALOG_YESQUIT ) strcpy(text, "Zakoñcz\\Koñczy grê COLOBOT");
-#endif
- if ( num == RT_DIALOG_ABORT ) strcpy(text, "Opuœciæ misjê?");
- if ( num == RT_DIALOG_YES ) strcpy(text, "Przerwij\\Przerywa bie¿¹c¹ misjê");
- if ( num == RT_DIALOG_NO ) strcpy(text, "Kontynuuj\\Kontynuuje bie¿¹c¹ misjê");
- if ( num == RT_DIALOG_NOQUIT ) strcpy(text, "Kontynuuj\\Kontynuuje grê");
- if ( num == RT_DIALOG_DELOBJ ) strcpy(text, "Czy na pewno chcesz zniszczyæ zaznaczony budynek?");
- if ( num == RT_DIALOG_DELGAME ) strcpy(text, "Czy na pewno chcesz skasowaæ zapisane gry gracza %s? ");
- if ( num == RT_DIALOG_YESDEL ) strcpy(text, "Usuñ");
- if ( num == RT_DIALOG_NODEL ) strcpy(text, "Anuluj");
- if ( num == RT_DIALOG_LOADING ) strcpy(text, "WCZYTYWANIE");
-
- if ( num == RT_STUDIO_LISTTT ) strcpy(text, "Skróty klawiszowe (\\key cbot;)");
- if ( num == RT_STUDIO_COMPOK ) strcpy(text, "Program skompilowany (0 b³êdów)");
- if ( num == RT_STUDIO_PROGSTOP ) strcpy(text, "Program zakoñczony");
-
- if ( num == RT_SATCOM_LIST ) strcpy(text, "\\b;Lista obiektów\n");
- if ( num == RT_SATCOM_BOT ) strcpy(text, "\\b;Roboty\n");
- if ( num == RT_SATCOM_BUILDING ) strcpy(text, "\\b;Budynki\n");
- if ( num == RT_SATCOM_FRET ) strcpy(text, "\\b;Obiekty ruchome\n");
- if ( num == RT_SATCOM_ALIEN ) strcpy(text, "\\b;Obcy\n");
- if ( num == RT_SATCOM_NULL ) strcpy(text, "\\c; (brak)\\n;\n");
- if ( num == RT_SATCOM_ERROR1 ) strcpy(text, "\\b;B³¹d\n");
- if ( num == RT_SATCOM_ERROR2 ) strcpy(text, "Lista jest dostêpna jedynie gdy dzia³a \\l;stacja radarowa\\u object\\radar;.\n");
-
- if ( num == RT_IO_OPEN ) strcpy(text, "Otwórz");
- if ( num == RT_IO_SAVE ) strcpy(text, "Zapisz");
- if ( num == RT_IO_LIST ) strcpy(text, "Folder: %s");
- if ( num == RT_IO_NAME ) strcpy(text, "Nazwa:");
- if ( num == RT_IO_DIR ) strcpy(text, "Folder:");
- if ( num == RT_IO_PRIVATE ) strcpy(text, "Prywatny\\Folder prywatny");
- if ( num == RT_IO_PUBLIC ) strcpy(text, "Publiczny\\Folder ogólnodostêpny");
-
- if ( num == RT_GENERIC_DEV1 ) strcpy(text, "Twórcy:");
- if ( num == RT_GENERIC_DEV2 ) strcpy(text, "www.epsitec.com");
- if ( num == RT_GENERIC_EDIT1 ) strcpy(text, "Wersja polska wydana przez:");
- if ( num == RT_GENERIC_EDIT2 ) strcpy(text, "www.manta.com.pl");
- if ( num == RT_GENERIC_EDIT1 ) strcpy(text, " ");
- if ( num == RT_GENERIC_EDIT2 ) strcpy(text, " ");
-
- if ( num == RT_INTERFACE_REC ) strcpy(text, "Recorder");
- }
-
- if ( type == RES_EVENT )
- {
- if ( num == EVENT_BUTTON_OK ) strcpy(text, "OK");
- if ( num == EVENT_BUTTON_CANCEL ) strcpy(text, "Anuluj");
- if ( num == EVENT_BUTTON_NEXT ) strcpy(text, "Nastêpny");
- if ( num == EVENT_BUTTON_PREV ) strcpy(text, "Poprzedni");
- if ( num == EVENT_BUTTON_QUIT ) strcpy(text, "Menu (\\key quit;)");
-
- if ( num == EVENT_DIALOG_OK ) strcpy(text, "OK");
- if ( num == EVENT_DIALOG_CANCEL ) strcpy(text, "Anuluj");
-
- if ( num == EVENT_INTERFACE_TRAINER) strcpy(text, "Æwiczenia\\Æwiczenia programistyczne");
- if ( num == EVENT_INTERFACE_DEFI ) strcpy(text, "Wyzwania\\Wyzwania programistyczne");
- if ( num == EVENT_INTERFACE_MISSION) strcpy(text, "Misje\\Wybierz misjê");
- if ( num == EVENT_INTERFACE_FREE ) strcpy(text, "Swobodna gra\\Swobodna gra bez konkretnych celów");
- if ( num == EVENT_INTERFACE_TEEN ) strcpy(text, "Swobodna gra\\Swobodna gra bez konkretnych celów");
- if ( num == EVENT_INTERFACE_USER ) strcpy(text, "Poziomy\\Poziomy u¿ytkownika");
- if ( num == EVENT_INTERFACE_PROTO ) strcpy(text, "Prototypy\\Prototypy w trakcie rozwijania");
- if ( num == EVENT_INTERFACE_NAME ) strcpy(text, "Nowy gracz\\Wybierz imiê gracza");
- if ( num == EVENT_INTERFACE_SETUP ) strcpy(text, "Opcje\\Preferencje");
- if ( num == EVENT_INTERFACE_AGAIN ) strcpy(text, "Uruchom ponownie\\Uruchamia ponownie misjê od pocz¹tku");
- if ( num == EVENT_INTERFACE_WRITE ) strcpy(text, "Zapisz\\Zapisuje bie¿¹c¹ misjê");
- if ( num == EVENT_INTERFACE_READ ) strcpy(text, "Wczytaj\\Wczytuje zapisan¹ misjê");
-#if _NEWLOOK
- if ( num == EVENT_INTERFACE_ABORT ) strcpy(text, "\\Powróæ do gry CeeBot");
- if ( num == EVENT_INTERFACE_QUIT ) strcpy(text, "Zakoñcz\\Koñczy grê CeeBot");
-#else
- if ( num == EVENT_INTERFACE_ABORT ) strcpy(text, "\\Powróæ do gry COLOBOT");
- if ( num == EVENT_INTERFACE_QUIT ) strcpy(text, "Zakoñcz\\Koñczy grê COLOBOT");
-#endif
- if ( num == EVENT_INTERFACE_BACK ) strcpy(text, "<< Wstecz \\Wraca do poprzedniego ekranu");
- if ( num == EVENT_INTERFACE_PLAY ) strcpy(text, "Graj\\Rozpoczyna misjê!");
- if ( num == EVENT_INTERFACE_SETUPd ) strcpy(text, "Urz¹dzenie\\Ustawienia sterownika i rozdzielczoœci");
- if ( num == EVENT_INTERFACE_SETUPg ) strcpy(text, "Grafika\\Ustawienia grafiki");
- if ( num == EVENT_INTERFACE_SETUPp ) strcpy(text, "Gra\\Ustawienia gry");
- if ( num == EVENT_INTERFACE_SETUPc ) strcpy(text, "Sterowanie\\Ustawienia klawiatury, joysticka i myszy");
- if ( num == EVENT_INTERFACE_SETUPs ) strcpy(text, "DŸwiêk\\G³oœnoœæ muzyki i dŸwiêków gry");
- if ( num == EVENT_INTERFACE_DEVICE ) strcpy(text, "Jednostka");
- if ( num == EVENT_INTERFACE_RESOL ) strcpy(text, "RozdzielczoϾ");
- if ( num == EVENT_INTERFACE_FULL ) strcpy(text, "Pe³ny ekran\\Pe³ny ekran lub tryb okna");
- if ( num == EVENT_INTERFACE_APPLY ) strcpy(text, "Zastosuj zmiany\\Aktywuje zmienione ustawienia");
-
- if ( num == EVENT_INTERFACE_TOTO ) strcpy(text, "Robbie\\Twój asystent");
- if ( num == EVENT_INTERFACE_SHADOW ) strcpy(text, "Cienie\\Cienie na ziemi");
- if ( num == EVENT_INTERFACE_GROUND ) strcpy(text, "Znaki na ziemi\\Znaki na ziemi");
- if ( num == EVENT_INTERFACE_DIRTY ) strcpy(text, "Kurz\\Kurz i bród na robotach i budynkach");
- if ( num == EVENT_INTERFACE_FOG ) strcpy(text, "Mg³a\\Mg³a");
- if ( num == EVENT_INTERFACE_LENS ) strcpy(text, "Promienie s³oneczne\\Promienie s³oneczne na niebie");
- if ( num == EVENT_INTERFACE_SKY ) strcpy(text, "Niebo\\Chmury i mg³awice");
- if ( num == EVENT_INTERFACE_PLANET ) strcpy(text, "Planety i gwiazdy\\Obiekty astronomiczne na niebie");
- if ( num == EVENT_INTERFACE_LIGHT ) strcpy(text, "Dynamiczne oœwietlenie\\Ruchome Ÿród³a œwiat³a");
- if ( num == EVENT_INTERFACE_PARTI ) strcpy(text, "Liczba cz¹stek\\Wybuchy, kurz, odbicia, itp.");
- if ( num == EVENT_INTERFACE_CLIP ) strcpy(text, "G³êbokoœæ pola\\Maksymalna widocznoœæ");
- if ( num == EVENT_INTERFACE_DETAIL ) strcpy(text, "Szczegó³y\\Jakoœæ wizualna obiektów 3D");
- if ( num == EVENT_INTERFACE_TEXTURE) strcpy(text, "Tekstury\\JakoϾ tekstur ");
- if ( num == EVENT_INTERFACE_GADGET ) strcpy(text, "Iloœæ elementów dekoracyjnych \\Iloœæ elementów czysto dekoracyjnych");
- if ( num == EVENT_INTERFACE_RAIN ) strcpy(text, "Cz¹stki w interfejsie\\Para i iskry z silników w interfejsie");
- if ( num == EVENT_INTERFACE_GLINT ) strcpy(text, "Odbicia na przyciskach \\Œwiec¹ce przyciski");
- if ( num == EVENT_INTERFACE_TOOLTIP) strcpy(text, "Dymki pomocy\\Wyjaœnia funkcje przycisków");
- if ( num == EVENT_INTERFACE_MOVIES ) strcpy(text, "Sekwencje filmowe\\Filmy przed rozpoczêciem i na zakoñczenie misji");
- if ( num == EVENT_INTERFACE_NICERST) strcpy(text, "Koñcowy film\\Film na zakoñczenie æwiczeñ");
- if ( num == EVENT_INTERFACE_HIMSELF) strcpy(text, "Przyjacielski ogieñ\\W³asne strza³y uszkadzaj¹ Twoje obiekty");
- if ( num == EVENT_INTERFACE_SCROLL ) strcpy(text, "Przewijanie\\Ekran jest przewijany gdy mysz dotknie prawej lub lewej jego krawêdzi");
- if ( num == EVENT_INTERFACE_INVERTX) strcpy(text, "Odwrócenie myszy X\\Odwrócenie kierunków przewijania w poziomie");
- if ( num == EVENT_INTERFACE_INVERTY) strcpy(text, "Odwrócenie myszy Y\\Odwrócenie kierunków przewijania w pionie");
- if ( num == EVENT_INTERFACE_EFFECT ) strcpy(text, "Wstrz¹sy przy wybuchach\\Ekran trzêsie siê podczas wybuchów");
- if ( num == EVENT_INTERFACE_MOUSE ) strcpy(text, "Cieñ kursora myszy\\Dodaje cieñ kursorowi myszy");
- if ( num == EVENT_INTERFACE_EDITMODE) strcpy(text, "Automatyczne wciêcia\\Automatyczne wciêcia podczas edycji programu");
- if ( num == EVENT_INTERFACE_EDITVALUE)strcpy(text, "Du¿e wciêcie\\2 lub 4 spacje wciêcia na ka¿dy poziom zdefiniowany przez klamry");
- if ( num == EVENT_INTERFACE_SOLUCE4) strcpy(text, "Accès aux solutions\\Programme \"4: Solution\" dans les exercices");
-
- if ( num == EVENT_INTERFACE_KDEF ) strcpy(text, "Standardowa kontrola\\Standardowe klawisze funkcyjne");
- if ( num == EVENT_INTERFACE_KLEFT ) strcpy(text, "Skrêæ w lewo\\Obraca robota w lewo");
- if ( num == EVENT_INTERFACE_KRIGHT ) strcpy(text, "Obróæ w prawo\\Obraca robota w prawo");
- if ( num == EVENT_INTERFACE_KUP ) strcpy(text, "Naprzód\\Porusza do przodu");
- if ( num == EVENT_INTERFACE_KDOWN ) strcpy(text, "Wstecz\\Porusza do ty³u");
- if ( num == EVENT_INTERFACE_KGUP ) strcpy(text, "W górê\\Zwiêksza moc silnika");
- if ( num == EVENT_INTERFACE_KGDOWN ) strcpy(text, "W dó³\\Zmniejsza moc silnika");
- if ( num == EVENT_INTERFACE_KCAMERA) strcpy(text, "Zmieñ kamerê\\Prze³¹cza pomiêdzy kamer¹ pok³adow¹ i œledz¹c¹");
- if ( num == EVENT_INTERFACE_KDESEL ) strcpy(text, "Poprzedni obiekt\\Zaznacz poprzedni obiekt");
- if ( num == EVENT_INTERFACE_KACTION) strcpy(text, "Standardowa akcja\\Standardowa akcja robota (podnieœ/upuœæ, strzelaj, szukaj, itp.)");
- if ( num == EVENT_INTERFACE_KNEAR ) strcpy(text, "Kamera bli¿ej\\Przybli¿a kamerê");
- if ( num == EVENT_INTERFACE_KAWAY ) strcpy(text, "Kamera dalej\\Oddala kamerê");
- if ( num == EVENT_INTERFACE_KNEXT ) strcpy(text, "Nastêpny obiekt\\Zaznacza nastêpny obiekt");
- if ( num == EVENT_INTERFACE_KHUMAN ) strcpy(text, "Zaznacz astronautê\\Zaznacza astronautê");
- if ( num == EVENT_INTERFACE_KQUIT ) strcpy(text, "Zakoñcz\\Koñczy bie¿¹c¹ misjê lub æwiczenie");
- if ( num == EVENT_INTERFACE_KHELP ) strcpy(text, "Rozkazy\\Pokazuje rozkazy dotycz¹ce bie¿¹cej misji");
- if ( num == EVENT_INTERFACE_KPROG ) strcpy(text, "Podrêcznik programowania\\Dostarcza szczegó³ow¹ pomoc w programowaniu");
- if ( num == EVENT_INTERFACE_KCBOT ) strcpy(text, "Pomoc dot. s³ów kluczowych\\Dok³adniejsza pomoc na temat s³ów kluczowych");
- if ( num == EVENT_INTERFACE_KVISIT ) strcpy(text, "Miejsce nadania wiadomoœci\\Pokazuje sk¹d zosta³a wys³ana ostatnia wiadomoœæ");
- if ( num == EVENT_INTERFACE_KSPEED10) strcpy(text, "Prêdkoœæ 1,0x\\Prêdkoœæ normalna");
- if ( num == EVENT_INTERFACE_KSPEED15) strcpy(text, "Prêdkoœæ 1,5x\\1,5 raza szybciej");
- if ( num == EVENT_INTERFACE_KSPEED20) strcpy(text, "Prêdkoœæ 2,0x\\Dwa razy szybciej");
- if ( num == EVENT_INTERFACE_KSPEED30) strcpy(text, "Prêdkoœæ 3,0x\\Trzy razy szybciej");
-
- if ( num == EVENT_INTERFACE_VOLSOUND) strcpy(text, "Efekty dŸwiêkowe:\\G³oœnoœæ silników, g³osów, strza³ów, itp.");
- if ( num == EVENT_INTERFACE_VOLMUSIC) strcpy(text, "Muzyka w tle :\\G³oœnoœæ œcie¿ek dŸwiêkowych z p³yty CD");
- if ( num == EVENT_INTERFACE_SOUND3D) strcpy(text, "DŸwiêk 3D\\Przestrzenne pozycjonowanie dŸwiêków");
-
- if ( num == EVENT_INTERFACE_MIN ) strcpy(text, "Najni¿sza\\Minimalna jakoœæ grafiki (najwy¿sza czêstotliwoœæ odœwie¿ania)");
- if ( num == EVENT_INTERFACE_NORM ) strcpy(text, "Normalna\\Normalna jakoϾ grafiki");
- if ( num == EVENT_INTERFACE_MAX ) strcpy(text, "Najwy¿sza\\Maksymalna jakoœæ grafiki (najni¿sza czêstotliwoœæ odœwie¿ania)");
-
- if ( num == EVENT_INTERFACE_SILENT ) strcpy(text, "Cisza\\Brak dŸwiêków");
- if ( num == EVENT_INTERFACE_NOISY ) strcpy(text, "Normalne\\Normalna g³oœnoœæ dŸwiêków");
-
- if ( num == EVENT_INTERFACE_JOYSTICK) strcpy(text, "U¿ywaj joysticka\\Joystick lub klawiatura");
- if ( num == EVENT_INTERFACE_SOLUCE ) strcpy(text, "Dostêp do rozwi¹zania\\Pokazuje rozwi¹zanie (szczegó³owe instrukcje dotycz¹ce misji)");
-
- if ( num == EVENT_INTERFACE_NEDIT ) strcpy(text, "\\Nowe imiê gracza");
- if ( num == EVENT_INTERFACE_NOK ) strcpy(text, "OK\\Wybiera zaznaczonego gracza");
- if ( num == EVENT_INTERFACE_NCANCEL) strcpy(text, "Anuluj\\Zachowuje bie¿¹ce imiê gracza");
- if ( num == EVENT_INTERFACE_NDELETE) strcpy(text, "Usuñ gracza\\Usuwa gracza z listy");
- if ( num == EVENT_INTERFACE_NLABEL ) strcpy(text, "Imiê gracza");
-
- if ( num == EVENT_INTERFACE_IOWRITE) strcpy(text, "Zapisz\\Zapisuje bie¿¹c¹ misjê");
- if ( num == EVENT_INTERFACE_IOREAD ) strcpy(text, "Wczytaj\\Wczytuje zaznaczon¹ misjê");
- if ( num == EVENT_INTERFACE_IOLIST ) strcpy(text, "Lista zapisanych misji");
- if ( num == EVENT_INTERFACE_IOLABEL) strcpy(text, "Nazwa pliku:");
- if ( num == EVENT_INTERFACE_IONAME ) strcpy(text, "Nazwa misji");
- if ( num == EVENT_INTERFACE_IOIMAGE) strcpy(text, "Fotografia");
- if ( num == EVENT_INTERFACE_IODELETE) strcpy(text, "Usuñ\\Usuwa zaznaczony plik");
-
- if ( num == EVENT_INTERFACE_PERSO ) strcpy(text, "Wygl¹d\\Wybierz swoj¹ postaæ");
- if ( num == EVENT_INTERFACE_POK ) strcpy(text, "OK");
- if ( num == EVENT_INTERFACE_PCANCEL) strcpy(text, "Anuluj");
- if ( num == EVENT_INTERFACE_PDEF ) strcpy(text, "Standardowe\\Standardowe ustawienia wygl¹du");
- if ( num == EVENT_INTERFACE_PHEAD ) strcpy(text, "G³owa\\Twarz i w³osy");
- if ( num == EVENT_INTERFACE_PBODY ) strcpy(text, "Skafander\\Skafander astronauty");
- if ( num == EVENT_INTERFACE_PLROT ) strcpy(text, "\\Obróæ w lewo");
- if ( num == EVENT_INTERFACE_PRROT ) strcpy(text, "\\Obróæ w prawo");
- if ( num == EVENT_INTERFACE_PCRa ) strcpy(text, "Czerwony");
- if ( num == EVENT_INTERFACE_PCGa ) strcpy(text, "Zielony");
- if ( num == EVENT_INTERFACE_PCBa ) strcpy(text, "Niebieski");
- if ( num == EVENT_INTERFACE_PCRb ) strcpy(text, "Czerwony");
- if ( num == EVENT_INTERFACE_PCGb ) strcpy(text, "Zielony");
- if ( num == EVENT_INTERFACE_PCBb ) strcpy(text, "Niebieski");
- if ( num == EVENT_INTERFACE_PFACE1 ) strcpy(text, "\\Twarz 1");
- if ( num == EVENT_INTERFACE_PFACE2 ) strcpy(text, "\\Twarz 4");
- if ( num == EVENT_INTERFACE_PFACE3 ) strcpy(text, "\\Twarz 3");
- if ( num == EVENT_INTERFACE_PFACE4 ) strcpy(text, "\\Twarz 2");
- if ( num == EVENT_INTERFACE_PGLASS0) strcpy(text, "\\Bez okularów");
- if ( num == EVENT_INTERFACE_PGLASS1) strcpy(text, "\\Okulary 1");
- if ( num == EVENT_INTERFACE_PGLASS2) strcpy(text, "\\Okulary 2");
- if ( num == EVENT_INTERFACE_PGLASS3) strcpy(text, "\\Okulary 3");
- if ( num == EVENT_INTERFACE_PGLASS4) strcpy(text, "\\Okulary 4");
- if ( num == EVENT_INTERFACE_PGLASS5) strcpy(text, "\\Okulary 5");
-
- if ( num == EVENT_OBJECT_DESELECT ) strcpy(text, "Poprzednie zaznaczenie (\\key desel;)");
- if ( num == EVENT_OBJECT_LEFT ) strcpy(text, "Skrêæ w lewo (\\key left;)");
- if ( num == EVENT_OBJECT_RIGHT ) strcpy(text, "Skrêæ w prawo (\\key right;)");
- if ( num == EVENT_OBJECT_UP ) strcpy(text, "Naprzód (\\key up;)");
- if ( num == EVENT_OBJECT_DOWN ) strcpy(text, "Cofnij (\\key down;)");
- if ( num == EVENT_OBJECT_GASUP ) strcpy(text, "Góra (\\key gup;)");
- if ( num == EVENT_OBJECT_GASDOWN ) strcpy(text, "Dó³ (\\key gdown;)");
- if ( num == EVENT_OBJECT_HTAKE ) strcpy(text, "Podnieœ lub upuœæ (\\key action;)");
- if ( num == EVENT_OBJECT_MTAKE ) strcpy(text, "Podnieœ lub upuœæ (\\key action;)");
- if ( num == EVENT_OBJECT_MFRONT ) strcpy(text, "..przed");
- if ( num == EVENT_OBJECT_MBACK ) strcpy(text, "..za");
- if ( num == EVENT_OBJECT_MPOWER ) strcpy(text, "..ogniwo elektryczne");
- if ( num == EVENT_OBJECT_BHELP ) strcpy(text, "Rozkazy dotycz¹ce misji (\\key help;)");
- if ( num == EVENT_OBJECT_BTAKEOFF ) strcpy(text, "Odleæ, aby zakoñczyæ misjê");
- if ( num == EVENT_OBJECT_BDERRICK ) strcpy(text, "Zbuduj kopalniê");
- if ( num == EVENT_OBJECT_BSTATION ) strcpy(text, "Zbuduj elektrowniê");
- if ( num == EVENT_OBJECT_BFACTORY ) strcpy(text, "Zbuduj fabrykê robotów");
- if ( num == EVENT_OBJECT_BREPAIR ) strcpy(text, "Zbuduj warsztat");
- if ( num == EVENT_OBJECT_BCONVERT ) strcpy(text, "Zbuduj hutê");
- if ( num == EVENT_OBJECT_BTOWER ) strcpy(text, "Zbuduj wie¿ê obronn¹");
- if ( num == EVENT_OBJECT_BRESEARCH ) strcpy(text, "Zbuduj centrum badawcze");
- if ( num == EVENT_OBJECT_BRADAR ) strcpy(text, "Zbuduj stacjê radarow¹");
- if ( num == EVENT_OBJECT_BENERGY ) strcpy(text, "Zbuduj fabrykê ogniw elektrycznych");
- if ( num == EVENT_OBJECT_BLABO ) strcpy(text, "Zbuduj laboratorium");
- if ( num == EVENT_OBJECT_BNUCLEAR ) strcpy(text, "Zbuduj elektrowniê atomow¹");
- if ( num == EVENT_OBJECT_BPARA ) strcpy(text, "Zbuduj odgromnik");
- if ( num == EVENT_OBJECT_BINFO ) strcpy(text, "Zbuduj stacjê przekaŸnikow¹");
- if ( num == EVENT_OBJECT_GFLAT ) strcpy(text, "Poka¿ czy teren jest p³aski");
- if ( num == EVENT_OBJECT_FCREATE ) strcpy(text, "Postaw flagê");
- if ( num == EVENT_OBJECT_FDELETE ) strcpy(text, "Usuñ flagê");
- if ( num == EVENT_OBJECT_FCOLORb ) strcpy(text, "\\Niebieskie flagi");
- if ( num == EVENT_OBJECT_FCOLORr ) strcpy(text, "\\Czerwone flagi");
- if ( num == EVENT_OBJECT_FCOLORg ) strcpy(text, "\\Zielone flagi");
- if ( num == EVENT_OBJECT_FCOLORy ) strcpy(text, "\\¯ó³te flagi");
- if ( num == EVENT_OBJECT_FCOLORv ) strcpy(text, "\\Fioletowe flagi");
- if ( num == EVENT_OBJECT_FACTORYfa ) strcpy(text, "Zbuduj transporter lataj¹cy");
- if ( num == EVENT_OBJECT_FACTORYta ) strcpy(text, "Zbuduj transporter na g¹sienicach");
- if ( num == EVENT_OBJECT_FACTORYwa ) strcpy(text, "Zbuduj transporter na ko³ach");
- if ( num == EVENT_OBJECT_FACTORYia ) strcpy(text, "Zbuduj transporter na nogach");
- if ( num == EVENT_OBJECT_FACTORYfc ) strcpy(text, "Zbuduj dzia³o lataj¹ce");
- if ( num == EVENT_OBJECT_FACTORYtc ) strcpy(text, "Zbuduj dzia³o na g¹sienicach");
- if ( num == EVENT_OBJECT_FACTORYwc ) strcpy(text, "Zbuduj dzia³o na ko³ach");
- if ( num == EVENT_OBJECT_FACTORYic ) strcpy(text, "Zbuduj dzia³o na nogach");
- if ( num == EVENT_OBJECT_FACTORYfi ) strcpy(text, "Zbuduj lataj¹ce dzia³o organiczne");
- if ( num == EVENT_OBJECT_FACTORYti ) strcpy(text, "Zbuduj dzia³o organiczne na g¹sienicach");
- if ( num == EVENT_OBJECT_FACTORYwi ) strcpy(text, "Zbuduj dzia³o organiczne na ko³ach");
- if ( num == EVENT_OBJECT_FACTORYii ) strcpy(text, "Zbuduj dzia³o organiczne na nogach");
- if ( num == EVENT_OBJECT_FACTORYfs ) strcpy(text, "Zbuduj szperacz lataj¹cy");
- if ( num == EVENT_OBJECT_FACTORYts ) strcpy(text, "Zbuduj szperacz na g¹sienicach");
- if ( num == EVENT_OBJECT_FACTORYws ) strcpy(text, "Zbuduj szperacz na ko³ach");
- if ( num == EVENT_OBJECT_FACTORYis ) strcpy(text, "Zbuduj szperacz na nogach");
- if ( num == EVENT_OBJECT_FACTORYrt ) strcpy(text, "Zbuduj robota uderzacza");
- if ( num == EVENT_OBJECT_FACTORYrc ) strcpy(text, "Zbuduj dzia³o fazowe");
- if ( num == EVENT_OBJECT_FACTORYrr ) strcpy(text, "Zbuduj robota recyklera");
- if ( num == EVENT_OBJECT_FACTORYrs ) strcpy(text, "Zbuduj robota os³aniajacza");
- if ( num == EVENT_OBJECT_FACTORYsa ) strcpy(text, "Zbuduj robota nurka");
- if ( num == EVENT_OBJECT_RTANK ) strcpy(text, "Rozpocznij prace badawcze nad transporterem na g¹sienicach");
- if ( num == EVENT_OBJECT_RFLY ) strcpy(text, "Rozpocznij prace badawcze nad transporterem lataj¹cym");
- if ( num == EVENT_OBJECT_RTHUMP ) strcpy(text, "Rozpocznij prace badawcze nad robotem uderzaczem");
- if ( num == EVENT_OBJECT_RCANON ) strcpy(text, "Rozpocznij prace badawcze nad dzia³em");
- if ( num == EVENT_OBJECT_RTOWER ) strcpy(text, "Rozpocznij prace badawcze nad wie¿¹ obronn¹");
- if ( num == EVENT_OBJECT_RPHAZER ) strcpy(text, "Rozpocznij prace badawcze nad dzia³em fazowym");
- if ( num == EVENT_OBJECT_RSHIELD ) strcpy(text, "Rozpocznij prace badawcze nad robotem os³aniaczem");
- if ( num == EVENT_OBJECT_RATOMIC ) strcpy(text, "Rozpocznij prace badawcze nad energi¹ atomow¹");
- if ( num == EVENT_OBJECT_RiPAW ) strcpy(text, "Rozpocznij prace badawcze nad transporterem na nogach");
- if ( num == EVENT_OBJECT_RiGUN ) strcpy(text, "Rozpocznij prace badawcze nad dzia³em organicznym");
- if ( num == EVENT_OBJECT_RESET ) strcpy(text, "Powrót do pocz¹tku");
- if ( num == EVENT_OBJECT_SEARCH ) strcpy(text, "Szukaj (\\key action;)");
- if ( num == EVENT_OBJECT_TERRAFORM ) strcpy(text, "Uderz (\\key action;)");
- if ( num == EVENT_OBJECT_FIRE ) strcpy(text, "Strzelaj (\\key action;)");
- if ( num == EVENT_OBJECT_RECOVER ) strcpy(text, "Odzyskaj (\\key action;)");
- if ( num == EVENT_OBJECT_BEGSHIELD ) strcpy(text, "Rozszerz os³onê (\\key action;)");
- if ( num == EVENT_OBJECT_ENDSHIELD ) strcpy(text, "Wy³¹cz os³onê (\\key action;)");
- if ( num == EVENT_OBJECT_DIMSHIELD ) strcpy(text, "Zasiêg os³ony");
- if ( num == EVENT_OBJECT_PROGRUN ) strcpy(text, "Wykonaj zaznaczony program");
- if ( num == EVENT_OBJECT_PROGEDIT ) strcpy(text, "Edytuj zaznaczony program");
- if ( num == EVENT_OBJECT_INFOOK ) strcpy(text, "\\Prze³¹cz przekaŸnik SatCom w stan gotowoœci");
- if ( num == EVENT_OBJECT_DELETE ) strcpy(text, "Zniszcz budynek");
- if ( num == EVENT_OBJECT_GENERGY ) strcpy(text, "Poziom energii");
- if ( num == EVENT_OBJECT_GSHIELD ) strcpy(text, "Poziom os³ony");
- if ( num == EVENT_OBJECT_GRANGE ) strcpy(text, "Temperatura silnika");
- if ( num == EVENT_OBJECT_GPROGRESS ) strcpy(text, "Wci¹¿ pracuje...");
- if ( num == EVENT_OBJECT_GRADAR ) strcpy(text, "Liczba wykrytych insektów");
- if ( num == EVENT_OBJECT_GINFO ) strcpy(text, "Przes³ane informacje");
- if ( num == EVENT_OBJECT_COMPASS ) strcpy(text, "Kompas");
-//? if ( num == EVENT_OBJECT_MAP ) strcpy(text, "Mapka");
- if ( num == EVENT_OBJECT_MAPZOOM ) strcpy(text, "Powiêkszenie mapki");
- if ( num == EVENT_OBJECT_CAMERA ) strcpy(text, "Kamera (\\key camera;)");
- if ( num == EVENT_OBJECT_CAMERAleft) strcpy(text, "Camera to left");
- if ( num == EVENT_OBJECT_CAMERAright) strcpy(text, "Camera to right");
- if ( num == EVENT_OBJECT_CAMERAnear) strcpy(text, "Camera nearest");
- if ( num == EVENT_OBJECT_CAMERAaway) strcpy(text, "Camera awayest");
- if ( num == EVENT_OBJECT_HELP ) strcpy(text, "Pomoc na temat zaznaczonego obiektu");
- if ( num == EVENT_OBJECT_SOLUCE ) strcpy(text, "Poka¿ rozwi¹zanie");
- if ( num == EVENT_OBJECT_SHORTCUT00) strcpy(text, "Prze³¹cz roboty <-> budynki");
- if ( num == EVENT_OBJECT_LIMIT ) strcpy(text, "Poka¿ zasiêg");
- if ( num == EVENT_OBJECT_PEN0 ) strcpy(text, "\\Relève le crayon");
- if ( num == EVENT_OBJECT_PEN1 ) strcpy(text, "\\Abaisse le crayon noir");
- if ( num == EVENT_OBJECT_PEN2 ) strcpy(text, "\\Abaisse le crayon jaune");
- if ( num == EVENT_OBJECT_PEN3 ) strcpy(text, "\\Abaisse le crayon orange");
- if ( num == EVENT_OBJECT_PEN4 ) strcpy(text, "\\Abaisse le crayon rouge");
- if ( num == EVENT_OBJECT_PEN5 ) strcpy(text, "\\Abaisse le crayon violet");
- if ( num == EVENT_OBJECT_PEN6 ) strcpy(text, "\\Abaisse le crayon bleu");
- if ( num == EVENT_OBJECT_PEN7 ) strcpy(text, "\\Abaisse le crayon vert");
- if ( num == EVENT_OBJECT_PEN8 ) strcpy(text, "\\Abaisse le crayon brun");
- if ( num == EVENT_OBJECT_REC ) strcpy(text, "\\Démarre l'enregistrement");
- if ( num == EVENT_OBJECT_STOP ) strcpy(text, "\\Stoppe l'enregistrement");
- if ( num == EVENT_DT_VISIT0 ||
- num == EVENT_DT_VISIT1 ||
- num == EVENT_DT_VISIT2 ||
- num == EVENT_DT_VISIT3 ||
- num == EVENT_DT_VISIT4 ) strcpy(text, "Poka¿ miejsce");
- if ( num == EVENT_DT_END ) strcpy(text, "Kontynuuj");
- if ( num == EVENT_CMD ) strcpy(text, "Linia polecenia");
- if ( num == EVENT_SPEED ) strcpy(text, "Prêdkoœæ gry");
-
- if ( num == EVENT_HYPER_PREV ) strcpy(text, "Wstecz");
- if ( num == EVENT_HYPER_NEXT ) strcpy(text, "Naprzód");
- if ( num == EVENT_HYPER_HOME ) strcpy(text, "Pocz¹tek");
- if ( num == EVENT_HYPER_COPY ) strcpy(text, "Kopiuj");
- if ( num == EVENT_HYPER_SIZE1 ) strcpy(text, "WielkoϾ 1");
- if ( num == EVENT_HYPER_SIZE2 ) strcpy(text, "WielkoϾ 2");
- if ( num == EVENT_HYPER_SIZE3 ) strcpy(text, "WielkoϾ 3");
- if ( num == EVENT_HYPER_SIZE4 ) strcpy(text, "WielkoϾ 4");
- if ( num == EVENT_HYPER_SIZE5 ) strcpy(text, "WielkoϾ 5");
- if ( num == EVENT_SATCOM_HUSTON ) strcpy(text, "Rozkazy z Houston");
-#if _TEEN
- if ( num == EVENT_SATCOM_SAT ) strcpy(text, "Raport z satelity");
-#else
- if ( num == EVENT_SATCOM_SAT ) strcpy(text, "Raport z satelity");
-#endif
- if ( num == EVENT_SATCOM_LOADING ) strcpy(text, "Program dostarczony z Houston");
- if ( num == EVENT_SATCOM_OBJECT ) strcpy(text, "Lista obiektów");
- if ( num == EVENT_SATCOM_PROG ) strcpy(text, "Podrêcznik programowania");
- if ( num == EVENT_SATCOM_SOLUCE ) strcpy(text, "Rozwi¹zanie");
-
- if ( num == EVENT_STUDIO_OK ) strcpy(text, "OK\\Zamyka edytor programu i powraca do gry");
- if ( num == EVENT_STUDIO_CANCEL ) strcpy(text, "Anuluj\\Pomija wszystkie zmiany");
- if ( num == EVENT_STUDIO_NEW ) strcpy(text, "Nowy");
- if ( num == EVENT_STUDIO_OPEN ) strcpy(text, "Otwórz (Ctrl+O)");
- if ( num == EVENT_STUDIO_SAVE ) strcpy(text, "Zapisz (Ctrl+S)");
- if ( num == EVENT_STUDIO_UNDO ) strcpy(text, "Cofnij (Ctrl+Z)");
- if ( num == EVENT_STUDIO_CUT ) strcpy(text, "Wytnij (Ctrl+X)");
- if ( num == EVENT_STUDIO_COPY ) strcpy(text, "Kopiuj (Ctrl+C)");
- if ( num == EVENT_STUDIO_PASTE ) strcpy(text, "Wklej (Ctrl+V)");
- if ( num == EVENT_STUDIO_SIZE ) strcpy(text, "WielkoϾ czcionki");
- if ( num == EVENT_STUDIO_TOOL ) strcpy(text, "Rozkazy (\\key help;)");
- if ( num == EVENT_STUDIO_HELP ) strcpy(text, "Podrêcznik programowania (\\key prog;)");
- if ( num == EVENT_STUDIO_COMPILE ) strcpy(text, "Kompiluj");
- if ( num == EVENT_STUDIO_RUN ) strcpy(text, "Wykonaj/Zatrzymaj");
- if ( num == EVENT_STUDIO_REALTIME ) strcpy(text, "Pauza/Kontynuuj");
- if ( num == EVENT_STUDIO_STEP ) strcpy(text, "Jeden krok");
- }
-
- if ( type == RES_OBJECT )
- {
- if ( num == OBJECT_PORTICO ) strcpy(text, "¯uraw przesuwalny");
- if ( num == OBJECT_BASE ) strcpy(text, "Statek kosmiczny");
- if ( num == OBJECT_DERRICK ) strcpy(text, "Kopalnia");
- if ( num == OBJECT_FACTORY ) strcpy(text, "Fabryka robotów");
- if ( num == OBJECT_REPAIR ) strcpy(text, "Warsztat");
- if ( num == OBJECT_DESTROYER ) strcpy(text, "Destroyer");
- if ( num == OBJECT_STATION ) strcpy(text, "Stacja energetyczna");
- if ( num == OBJECT_CONVERT ) strcpy(text, "Przetop rudê na tytan");
- if ( num == OBJECT_TOWER ) strcpy(text, "Wie¿a obronna");
- if ( num == OBJECT_NEST ) strcpy(text, "Gniazdo");
- if ( num == OBJECT_RESEARCH ) strcpy(text, "Centrum badawcze");
- if ( num == OBJECT_RADAR ) strcpy(text, "Stacja radarowa");
- if ( num == OBJECT_INFO ) strcpy(text, "Stacja przekaŸnikowa informacji");
-#if _TEEN
- if ( num == OBJECT_ENERGY ) strcpy(text, "Fabryka ogniw elektrycznych");
-#else
- if ( num == OBJECT_ENERGY ) strcpy(text, "Fabryka ogniw elektrycznych");
-#endif
- if ( num == OBJECT_LABO ) strcpy(text, "Laboratorium");
- if ( num == OBJECT_NUCLEAR ) strcpy(text, "Elektrownia atomowa");
- if ( num == OBJECT_PARA ) strcpy(text, "Odgromnik");
- if ( num == OBJECT_SAFE ) strcpy(text, "Skrytka");
- if ( num == OBJECT_HUSTON ) strcpy(text, "Centrum Kontroli Misji w Houston");
- if ( num == OBJECT_TARGET1 ) strcpy(text, "Cel");
- if ( num == OBJECT_TARGET2 ) strcpy(text, "Cel");
- if ( num == OBJECT_START ) strcpy(text, "Pocz¹tek");
- if ( num == OBJECT_END ) strcpy(text, "Koniec");
- if ( num == OBJECT_STONE ) strcpy(text, "Ruda tytanu");
- if ( num == OBJECT_URANIUM ) strcpy(text, "Ruda uranu");
- if ( num == OBJECT_BULLET ) strcpy(text, "Materia organiczna");
- if ( num == OBJECT_METAL ) strcpy(text, "Tytan");
- if ( num == OBJECT_POWER ) strcpy(text, "Ogniwo elektryczne");
- if ( num == OBJECT_ATOMIC ) strcpy(text, "Atomowe ogniwa elektryczne");
- if ( num == OBJECT_BBOX ) strcpy(text, "Czarna skrzynka");
- if ( num == OBJECT_KEYa ) strcpy(text, "Klucz A");
- if ( num == OBJECT_KEYb ) strcpy(text, "Klucz B");
- if ( num == OBJECT_KEYc ) strcpy(text, "Klucz C");
- if ( num == OBJECT_KEYd ) strcpy(text, "Klucz D");
- if ( num == OBJECT_TNT ) strcpy(text, "Materia³y wybuchowe");
- if ( num == OBJECT_BOMB ) strcpy(text, "Mina");
- if ( num == OBJECT_BAG ) strcpy(text, "Zestaw przetrwania");
- if ( num == OBJECT_WAYPOINT ) strcpy(text, "Punkt kontrolny");
- if ( num == OBJECT_FLAGb ) strcpy(text, "Niebieska flaga");
- if ( num == OBJECT_FLAGr ) strcpy(text, "Czerwona flaga");
- if ( num == OBJECT_FLAGg ) strcpy(text, "Zielona flaga");
- if ( num == OBJECT_FLAGy ) strcpy(text, "¯ó³ta flaga");
- if ( num == OBJECT_FLAGv ) strcpy(text, "Fioletowa flaga");
- if ( num == OBJECT_MARKPOWER ) strcpy(text, "ród³o energii (miejsce na elektrowniê)");
- if ( num == OBJECT_MARKURANIUM ) strcpy(text, "Z³o¿e uranu (miejsce na kopalniê)");
- if ( num == OBJECT_MARKKEYa ) strcpy(text, "Znaleziono klucz A (miejsce na kopalniê)");
- if ( num == OBJECT_MARKKEYb ) strcpy(text, "Znaleziono klucz B (miejsce na kopalniê)");
- if ( num == OBJECT_MARKKEYc ) strcpy(text, "Znaleziono klucz C (miejsce na kopalniê)");
- if ( num == OBJECT_MARKKEYd ) strcpy(text, "Znaleziono klucz D (miejsce na kopalniê)");
- if ( num == OBJECT_MARKSTONE ) strcpy(text, "Z³o¿e tytanu (miejsce na kopalniê)");
- if ( num == OBJECT_MOBILEft ) strcpy(text, "Robot treningowy");
- if ( num == OBJECT_MOBILEtt ) strcpy(text, "Robot treningowy");
- if ( num == OBJECT_MOBILEwt ) strcpy(text, "Robot treningowy");
- if ( num == OBJECT_MOBILEit ) strcpy(text, "Robot treningowy");
- if ( num == OBJECT_MOBILEfa ) strcpy(text, "Transporter lataj¹cy");
- if ( num == OBJECT_MOBILEta ) strcpy(text, "Transporter na g¹sienicach");
- if ( num == OBJECT_MOBILEwa ) strcpy(text, "Transporter na ko³ach");
- if ( num == OBJECT_MOBILEia ) strcpy(text, "Transporter na nogach");
- if ( num == OBJECT_MOBILEfc ) strcpy(text, "Dzia³o lataj¹ce");
- if ( num == OBJECT_MOBILEtc ) strcpy(text, "Dzia³o na g¹sienicach");
- if ( num == OBJECT_MOBILEwc ) strcpy(text, "Dzia³o na ko³ach");
- if ( num == OBJECT_MOBILEic ) strcpy(text, "Dzia³o na nogach");
- if ( num == OBJECT_MOBILEfi ) strcpy(text, "Lataj¹ce dzia³o organiczne");
- if ( num == OBJECT_MOBILEti ) strcpy(text, "Dzia³o organiczne na g¹sienicach");
- if ( num == OBJECT_MOBILEwi ) strcpy(text, "Dzia³o organiczne na ko³ach");
- if ( num == OBJECT_MOBILEii ) strcpy(text, "Dzia³o organiczne na nogach");
- if ( num == OBJECT_MOBILEfs ) strcpy(text, "Szperacz lataj¹cy");
- if ( num == OBJECT_MOBILEts ) strcpy(text, "Szperacz na g¹sienicach");
- if ( num == OBJECT_MOBILEws ) strcpy(text, "Szperacz na ko³ach");
- if ( num == OBJECT_MOBILEis ) strcpy(text, "Szperacz na nogach");
- if ( num == OBJECT_MOBILErt ) strcpy(text, "Uderzacz");
- if ( num == OBJECT_MOBILErc ) strcpy(text, "Dzia³o fazowe");
- if ( num == OBJECT_MOBILErr ) strcpy(text, "Recykler");
- if ( num == OBJECT_MOBILErs ) strcpy(text, "Os³aniacz");
- if ( num == OBJECT_MOBILEsa ) strcpy(text, "Robot nurek");
- if ( num == OBJECT_MOBILEtg ) strcpy(text, "Robot cel");
- if ( num == OBJECT_MOBILEdr ) strcpy(text, "Drawer bot");
- if ( num == OBJECT_HUMAN ) strcpy(text, g_gamerName);
- if ( num == OBJECT_TECH ) strcpy(text, "In¿ynier");
- if ( num == OBJECT_TOTO ) strcpy(text, "Robbie");
- if ( num == OBJECT_MOTHER ) strcpy(text, "Królowa Obcych");
- if ( num == OBJECT_ANT ) strcpy(text, "Mrówka");
- if ( num == OBJECT_SPIDER ) strcpy(text, "Paj¹k");
- if ( num == OBJECT_BEE ) strcpy(text, "Osa");
- if ( num == OBJECT_WORM ) strcpy(text, "Robal");
- if ( num == OBJECT_EGG ) strcpy(text, "Jajo");
- if ( num == OBJECT_RUINmobilew1 ) strcpy(text, "Wrak");
- if ( num == OBJECT_RUINmobilew2 ) strcpy(text, "Wrak");
- if ( num == OBJECT_RUINmobilet1 ) strcpy(text, "Wrak");
- if ( num == OBJECT_RUINmobilet2 ) strcpy(text, "Wrak");
- if ( num == OBJECT_RUINmobiler1 ) strcpy(text, "Wrak");
- if ( num == OBJECT_RUINmobiler2 ) strcpy(text, "Wrak");
- if ( num == OBJECT_RUINfactory ) strcpy(text, "Ruiny");
- if ( num == OBJECT_RUINdoor ) strcpy(text, "Ruiny");
- if ( num == OBJECT_RUINsupport ) strcpy(text, "Odpady");
- if ( num == OBJECT_RUINradar ) strcpy(text, "Ruiny");
- if ( num == OBJECT_RUINconvert ) strcpy(text, "Ruiny");
- if ( num == OBJECT_RUINbase ) strcpy(text, "Ruiny statku kosmicznego");
- if ( num == OBJECT_RUINhead ) strcpy(text, "Ruiny statku kosmicznego");
- if ( num == OBJECT_APOLLO1 ||
- num == OBJECT_APOLLO3 ||
- num == OBJECT_APOLLO4 ||
- num == OBJECT_APOLLO5 ) strcpy(text, "Pozosta³oœci z misji Apollo");
- if ( num == OBJECT_APOLLO2 ) strcpy(text, "Pojazd Ksiê¿ycowy");
- }
-
- if ( type == RES_ERR )
- {
- strcpy(text, "B³¹d");
- if ( num == ERR_CMD ) strcpy(text, "Nieznane polecenie");
-#if _NEWLOOK
- if ( num == ERR_INSTALL ) strcpy(text, "Gra CeeBot nie jest zainstalowana.");
- if ( num == ERR_NOCD ) strcpy(text, "W³ó¿ dysk CD z gr¹ CeeBot\ni uruchom grê jeszcze raz.");
-#else
- if ( num == ERR_INSTALL ) strcpy(text, "Gra COLOBOT nie jest zainstalowana.");
- if ( num == ERR_NOCD ) strcpy(text, "W³ó¿ dysk CD z gr¹ COLOBOT\ni uruchom grê jeszcze raz.");
-#endif
- if ( num == ERR_MANIP_VEH ) strcpy(text, "Nieodpowiedni robot");
- if ( num == ERR_MANIP_FLY ) strcpy(text, "Niemo¿liwe podczas lotu");
- if ( num == ERR_MANIP_BUSY ) strcpy(text, "Nie mo¿na nieœæ wiêcej przedmiotów");
- if ( num == ERR_MANIP_NIL ) strcpy(text, "Nie ma nic do podniesienia");
- if ( num == ERR_MANIP_MOTOR ) strcpy(text, "Niemo¿liwe podczas ruchu");
- if ( num == ERR_MANIP_OCC ) strcpy(text, "Miejsce zajête");
- if ( num == ERR_MANIP_FRIEND ) strcpy(text, "Brak innego robota");
- if ( num == ERR_MANIP_RADIO ) strcpy(text, "Nie mo¿esz przenosiæ przedmiotów radioaktywnych");
- if ( num == ERR_MANIP_WATER ) strcpy(text, "Nie mo¿esz przenosiæ przedmiotów pod wod¹");
- if ( num == ERR_MANIP_EMPTY ) strcpy(text, "Nie ma nic do upuszczenia");
- if ( num == ERR_BUILD_FLY ) strcpy(text, "Niemo¿liwe podczas lotu");
- if ( num == ERR_BUILD_WATER ) strcpy(text, "Niemo¿liwe pod wod¹");
- if ( num == ERR_BUILD_ENERGY ) strcpy(text, "Za ma³o energii");
- if ( num == ERR_BUILD_METALAWAY ) strcpy(text, "Tytan za daleko");
- if ( num == ERR_BUILD_METALNEAR ) strcpy(text, "Tytan za blisko");
- if ( num == ERR_BUILD_METALINEX ) strcpy(text, "Brak tytanu w pobli¿u");
- if ( num == ERR_BUILD_FLAT ) strcpy(text, "Powierzchnia nie jest wystarczaj¹co p³aska");
- if ( num == ERR_BUILD_FLATLIT ) strcpy(text, "Za ma³o p³askiego terenu");
- if ( num == ERR_BUILD_BUSY ) strcpy(text, "Miejsce zajête");
- if ( num == ERR_BUILD_BASE ) strcpy(text, "Za blisko statku kosmicznego");
- if ( num == ERR_BUILD_NARROW ) strcpy(text, "Za blisko budynku");
- if ( num == ERR_BUILD_MOTOR ) strcpy(text, "Niemo¿liwe podczas ruchu");
- if ( num == ERR_SEARCH_FLY ) strcpy(text, "Niemo¿liwe podczas lotu");
- if ( num == ERR_SEARCH_VEH ) strcpy(text, "Nieodpowiedni robot");
- if ( num == ERR_SEARCH_MOTOR ) strcpy(text, "Niemo¿liwe podczas ruchu");
- if ( num == ERR_TERRA_VEH ) strcpy(text, "Nieodpowiedni robot");
- if ( num == ERR_TERRA_ENERGY ) strcpy(text, "Za ma³o energii");
- if ( num == ERR_TERRA_FLOOR ) strcpy(text, "Nieodpowiedni teren");
- if ( num == ERR_TERRA_BUILDING ) strcpy(text, "Budynek za blisko");
- if ( num == ERR_TERRA_OBJECT ) strcpy(text, "Obiekt za blisko");
- if ( num == ERR_RECOVER_VEH ) strcpy(text, "Nieodpowiedni robot");
- if ( num == ERR_RECOVER_ENERGY ) strcpy(text, "Za ma³o energii");
- if ( num == ERR_RECOVER_NULL ) strcpy(text, "Nie ma niczego do odzysku");
- if ( num == ERR_SHIELD_VEH ) strcpy(text, "Nieodpowiedni robot");
- if ( num == ERR_SHIELD_ENERGY ) strcpy(text, "Nie ma wiêcej energii");
- if ( num == ERR_MOVE_IMPOSSIBLE ) strcpy(text, "B³¹d w poleceniu ruchu");
- if ( num == ERR_FIND_IMPOSSIBLE ) strcpy(text, "Obiekt nieznany");
- if ( num == ERR_GOTO_IMPOSSIBLE ) strcpy(text, "Goto: miejsce docelowe niedostêpne");
- if ( num == ERR_GOTO_ITER ) strcpy(text, "Goto: miejsce docelowe niedostêpne");
- if ( num == ERR_GOTO_BUSY ) strcpy(text, "Goto: miejsce docelowe zajête");
- if ( num == ERR_FIRE_VEH ) strcpy(text, "Nieodpowiedni robot");
- if ( num == ERR_FIRE_ENERGY ) strcpy(text, "Za ma³o energii");
- if ( num == ERR_FIRE_FLY ) strcpy(text, "Niemo¿liwe podczas lotu");
- if ( num == ERR_CONVERT_EMPTY ) strcpy(text, "Brak rudy tytanu do przetopienia");
- if ( num == ERR_DERRICK_NULL ) strcpy(text, "W ziemi nie ma ¿adnej rudy");
- if ( num == ERR_STATION_NULL ) strcpy(text, "Brak energii w ziemi");
- if ( num == ERR_TOWER_POWER ) strcpy(text, "Brak ogniwa elektrycznego");
- if ( num == ERR_TOWER_ENERGY ) strcpy(text, "Nie ma wiêcej energii");
- if ( num == ERR_RESEARCH_POWER ) strcpy(text, "Brak ogniwa elektrycznego");
- if ( num == ERR_RESEARCH_ENERGY ) strcpy(text, "Za ma³o energii");
- if ( num == ERR_RESEARCH_TYPE ) strcpy(text, "Nieodpowiedni rodzaj ogniw");
- if ( num == ERR_RESEARCH_ALREADY) strcpy(text, "Program badawczy zosta³ ju¿ wykonany");
- if ( num == ERR_ENERGY_NULL ) strcpy(text, "Brak energii w ziemi");
- if ( num == ERR_ENERGY_LOW ) strcpy(text, "Wci¹¿ za ma³o energii");
- if ( num == ERR_ENERGY_EMPTY ) strcpy(text, "Brak tytanu do przetworzenia");
- if ( num == ERR_ENERGY_BAD ) strcpy(text, "Przetwarza jedynie tytan");
- if ( num == ERR_BASE_DLOCK ) strcpy(text, "Drzwi zablokowane przez robota lub inny obiekt ");
- if ( num == ERR_BASE_DHUMAN ) strcpy(text, "Musisz byæ na statku kosmicznym aby nim odlecieæ");
- if ( num == ERR_LABO_NULL ) strcpy(text, "Nie ma niczego do zanalizowania");
- if ( num == ERR_LABO_BAD ) strcpy(text, "Analizuje jedynie materiê organiczn¹");
- if ( num == ERR_LABO_ALREADY ) strcpy(text, "Analiza zosta³a ju¿ wykonana");
- if ( num == ERR_NUCLEAR_NULL ) strcpy(text, "Brak energii w ziemi");
- if ( num == ERR_NUCLEAR_LOW ) strcpy(text, "Wci¹¿ za ma³o energii");
- if ( num == ERR_NUCLEAR_EMPTY ) strcpy(text, "Brak uranu do przetworzenia");
- if ( num == ERR_NUCLEAR_BAD ) strcpy(text, "Przetwarza jedynie uran");
- if ( num == ERR_FACTORY_NULL ) strcpy(text, "Brak tytanu");
- if ( num == ERR_FACTORY_NEAR ) strcpy(text, "Obiekt za blisko");
- if ( num == ERR_RESET_NEAR ) strcpy(text, "Miejsce zajête");
- if ( num == ERR_INFO_NULL ) strcpy(text, "Nie ma ¿adnej stacji przekaŸnikowej w zasiêgu");
- if ( num == ERR_VEH_VIRUS ) strcpy(text, "Program zawirusowany");
- if ( num == ERR_BAT_VIRUS ) strcpy(text, "Zainfekowane wirusem, chwilowo niesprawne");
- if ( num == ERR_VEH_POWER ) strcpy(text, "Brak ogniwa elektrycznego");
- if ( num == ERR_VEH_ENERGY ) strcpy(text, "Nie ma wiêcej energii");
- if ( num == ERR_FLAG_FLY ) strcpy(text, "Niemo¿liwe podczas lotu");
- if ( num == ERR_FLAG_WATER ) strcpy(text, "Niemo¿liwe podczas p³ywania");
- if ( num == ERR_FLAG_MOTOR ) strcpy(text, "Niemo¿liwe podczas ruchu");
- if ( num == ERR_FLAG_BUSY ) strcpy(text, "Niemo¿liwe podczas przenoszenia przedmiotu");
- if ( num == ERR_FLAG_CREATE ) strcpy(text, "Za du¿o flag w tym kolorze (maksymalnie 5)");
- if ( num == ERR_FLAG_PROXY ) strcpy(text, "Za blisko istniej¹cej flagi");
- if ( num == ERR_FLAG_DELETE ) strcpy(text, "Nie ma flagi w pobli¿u");
- if ( num == ERR_MISSION_NOTERM ) strcpy(text, "Misja nie jest wype³niona (naciœnij \\key help; aby uzyskaæ szczegó³y)");
- if ( num == ERR_DELETEMOBILE ) strcpy(text, "Robot zniszczony");
- if ( num == ERR_DELETEBUILDING ) strcpy(text, "Budynek zniszczony");
- if ( num == ERR_TOOMANY ) strcpy(text, "Nie mo¿na tego utworzyæ, za du¿o obiektów");
- if ( num == ERR_OBLIGATORYTOKEN ) strcpy(text, "It misses \"%s\" in this exercise");
- if ( num == ERR_PROHIBITEDTOKEN ) strcpy(text, "Do not use in this exercise");
-
- if ( num == INFO_BUILD ) strcpy(text, "Budowa zakoñczona");
- if ( num == INFO_CONVERT ) strcpy(text, "Tytan dostêpny");
- if ( num == INFO_RESEARCH ) strcpy(text, "Program badawczy zakoñczony");
- if ( num == INFO_RESEARCHTANK ) strcpy(text, "Dostêpne plany tranporterów na g¹sienicach");
- if ( num == INFO_RESEARCHFLY ) strcpy(text, "Mo¿esz lataæ u¿ywaj¹c klawiszy (\\key gup;) oraz (\\key gdown;)");
- if ( num == INFO_RESEARCHTHUMP ) strcpy(text, "Dostêpne plany robota uderzacza");
- if ( num == INFO_RESEARCHCANON ) strcpy(text, "Dostêpne plany dzia³a");
- if ( num == INFO_RESEARCHTOWER ) strcpy(text, "Dostêpne plany wie¿y obronnej");
- if ( num == INFO_RESEARCHPHAZER ) strcpy(text, "Dostêpne plany dzia³a fazowego");
- if ( num == INFO_RESEARCHSHIELD ) strcpy(text, "Dostêpne plany robota os³aniacza");
- if ( num == INFO_RESEARCHATOMIC ) strcpy(text, "Dostêpne plany elektrowni atomowej");
- if ( num == INFO_FACTORY ) strcpy(text, "Dostêpny nowy robot");
- if ( num == INFO_LABO ) strcpy(text, "Analiza wykonana");
- if ( num == INFO_ENERGY ) strcpy(text, "Wytworzono ogniwo elektryczne");
- if ( num == INFO_NUCLEAR ) strcpy(text, "Wytworzono atomowe ogniwo elektryczne");
- if ( num == INFO_FINDING ) strcpy(text, "Znaleziono u¿yteczny przedmiot");
- if ( num == INFO_MARKPOWER ) strcpy(text, "Znaleziono miejsce na elektrowniê");
- if ( num == INFO_MARKURANIUM ) strcpy(text, "Znaleziono miejsce na kopalniê");
- if ( num == INFO_MARKSTONE ) strcpy(text, "Znaleziono miejsce na kopalniê");
- if ( num == INFO_MARKKEYa ) strcpy(text, "Znaleziono miejsce na kopalniê");
- if ( num == INFO_MARKKEYb ) strcpy(text, "Znaleziono miejsce na kopalniê");
- if ( num == INFO_MARKKEYc ) strcpy(text, "Znaleziono miejsce na kopalniê");
- if ( num == INFO_MARKKEYd ) strcpy(text, "Znaleziono miejsce na kopalniê");
- if ( num == INFO_WIN ) strcpy(text, "<<< Dobra robota, misja wype³niona >>>");
- if ( num == INFO_LOST ) strcpy(text, "<<< Niestety, misja nie powiod³a siê >>>");
- if ( num == INFO_LOSTq ) strcpy(text, "<<< Niestety, misja nie powiod³a siê >>>");
- if ( num == INFO_WRITEOK ) strcpy(text, "Bie¿¹ca misja zapisana");
- if ( num == INFO_DELETEPATH ) strcpy(text, "Przekroczono punkt kontrolny");
- if ( num == INFO_DELETEMOTHER ) strcpy(text, "Królowa Obcych zosta³a zabita");
- if ( num == INFO_DELETEANT ) strcpy(text, "Mrówka œmiertelnie raniona");
- if ( num == INFO_DELETEBEE ) strcpy(text, "Osa œmiertelnie raniona");
- if ( num == INFO_DELETEWORM ) strcpy(text, "Robal œmiertelnie raniony");
- if ( num == INFO_DELETESPIDER ) strcpy(text, "Paj¹k œmiertelnie raniony");
- if ( num == INFO_BEGINSATCOM ) strcpy(text, "Naciœnij klawisz \\key help; aby wyœwietliæ rozkazy na przekaŸniku SatCom");
- }
-
- if ( type == RES_CBOT )
- {
- strcpy(text, "B³¹d");
- if ( num == TX_OPENPAR ) strcpy(text, "Brak nawiasu otwieraj¹cego");
- if ( num == TX_CLOSEPAR ) strcpy(text, "Brak nawiasu zamykaj¹cego");
- if ( num == TX_NOTBOOL ) strcpy(text, "Wyra¿enie musi zwróciæ wartoœæ logiczn¹");
- if ( num == TX_UNDEFVAR ) strcpy(text, "Zmienna nie zosta³a zadeklarowana");
- if ( num == TX_BADLEFT ) strcpy(text, "Przypisanie niemo¿liwe");
- if ( num == TX_ENDOF ) strcpy(text, "Brak œrednika na koñcu wiersza");
- if ( num == TX_OUTCASE ) strcpy(text, "Polecenie ""case"" na zewn¹trz bloku ""switch""");
- if ( num == TX_NOTERM ) strcpy(text, "Polecenie po koñcowej klamrze zamykaj¹cej");
- if ( num == TX_CLOSEBLK ) strcpy(text, "Brak koñca bloku");
- if ( num == TX_ELSEWITHOUTIF ) strcpy(text, "Polecenie ""else"" bez wyst¹pienia ""if"" ");
- if ( num == TX_OPENBLK ) strcpy(text, "Brak klamry otwieraj¹cej");//début d'un bloc attendu?
- if ( num == TX_BADTYPE ) strcpy(text, "Z³y typ dla przypisania");
- if ( num == TX_REDEFVAR ) strcpy(text, "Zmienna nie mo¿e byæ zadeklarowana dwukrotnie");
- if ( num == TX_BAD2TYPE ) strcpy(text, "Niezgodne typy operatorów");
- if ( num == TX_UNDEFCALL ) strcpy(text, "Funkcja nieznana");
- if ( num == TX_MISDOTS ) strcpy(text, "Brak znaku "" : ");
- if ( num == TX_WHILE ) strcpy(text, "Brak kluczowego s³owa ""while");
- if ( num == TX_BREAK ) strcpy(text, "Polecenie ""break"" na zewn¹trz pêtli");
- if ( num == TX_LABEL ) strcpy(text, "Po etykiecie musi wyst¹piæ ""for"", ""while"", ""do"" lub ""switch""");
- if ( num == TX_NOLABEL ) strcpy(text, "Taka etykieta nie istnieje");// Cette étiquette n'existe pas
- if ( num == TX_NOCASE ) strcpy(text, "Brak polecenia ""case");
- if ( num == TX_BADNUM ) strcpy(text, "Brak liczby");
- if ( num == TX_VOID ) strcpy(text, "Pusty parametr");
- if ( num == TX_NOTYP ) strcpy(text, "Brak deklaracji typu");
- if ( num == TX_NOVAR ) strcpy(text, "Brak nazwy zmiennej");
- if ( num == TX_NOFONC ) strcpy(text, "Brakuj¹ca nazwa funkcji");
- if ( num == TX_OVERPARAM ) strcpy(text, "Za du¿o parametrów");
- if ( num == TX_REDEF ) strcpy(text, "Funkcja ju¿ istnieje");
- if ( num == TX_LOWPARAM ) strcpy(text, "Brak wymaganego parametru");
- if ( num == TX_BADPARAM ) strcpy(text, "Funkcja o tej nazwie nie akceptuje parametrów tego typu");
- if ( num == TX_NUMPARAM ) strcpy(text, "Funkcja o tej nazwie nie akceptuje takiej liczby parametrów");
- if ( num == TX_NOITEM ) strcpy(text, "To nie jest obiekt tej klasy");
- if ( num == TX_DOT ) strcpy(text, "Ten obiekt nie jest cz³onkiem klasy");
- if ( num == TX_NOCONST ) strcpy(text, "Brak odpowiedniego konstruktora");
- if ( num == TX_REDEFCLASS ) strcpy(text, "Taka klasa ju¿ istnieje");
- if ( num == TX_CLBRK ) strcpy(text, "Brak "" ] """);
- if ( num == TX_RESERVED ) strcpy(text, "S³owo zarezerwowane jêzyka CBOT");
- if ( num == TX_BADNEW ) strcpy(text, "Z³y argument dla funkcji ""new""");
- if ( num == TX_OPBRK ) strcpy(text, "Oczekiwane "" [ """);
- if ( num == TX_BADSTRING ) strcpy(text, "Brak ³añcucha");
- if ( num == TX_BADINDEX ) strcpy(text, "Nieprawid³owy typ indeksu");
- if ( num == TX_PRIVATE ) strcpy(text, "Element prywatny");
- if ( num == TX_NOPUBLIC ) strcpy(text, "Wymagany publiczny");
- if ( num == TX_DIVZERO ) strcpy(text, "Dzielenie przez zero");
- if ( num == TX_NOTINIT ) strcpy(text, "Zmienna nie zosta³a zainicjalizowana");
- if ( num == TX_BADTHROW ) strcpy(text, "Wartoœæ ujemna odrzucona przez ""throw""");//C'est quoi, ça?
- if ( num == TX_NORETVAL ) strcpy(text, "Funkcja nie zwróci³a ¿adnej wartoœci ");
- if ( num == TX_NORUN ) strcpy(text, "¯adna funkcja nie dzia³a");
- if ( num == TX_NOCALL ) strcpy(text, "Odwo³anie do nieznanej funkcji");
- if ( num == TX_NOCLASS ) strcpy(text, "Taka klasa nie istnieje");
- if ( num == TX_NULLPT ) strcpy(text, "Obiekt nieznany");
- if ( num == TX_OPNAN ) strcpy(text, "Dzia³anie niemo¿liwe z wartoœci¹ ""nan""");
- if ( num == TX_OUTARRAY ) strcpy(text, "Dostêp poza tablicê");
- if ( num == TX_STACKOVER ) strcpy(text, "Przepe³nienie stosu");
- if ( num == TX_DELETEDPT ) strcpy(text, "Nieprawid³owy obiekt");
- if ( num == TX_FILEOPEN ) strcpy(text, "Nie mo¿na otworzyæ pliku");
- if ( num == TX_NOTOPEN ) strcpy(text, "Plik nie jest otwarty");
- if ( num == TX_ERRREAD ) strcpy(text, "B³¹d odczytu");
- if ( num == TX_ERRWRITE ) strcpy(text, "B³¹d zapisu");
- }
-
- if ( type == RES_KEY )
- {
- if ( num == 0 ) strcpy(text, "< brak >");
- if ( num == VK_LEFT ) strcpy(text, "Strza³ka w lewo");
- if ( num == VK_RIGHT ) strcpy(text, "Strza³ka w prawo");
- if ( num == VK_UP ) strcpy(text, "Strza³ka w górê");
- if ( num == VK_DOWN ) strcpy(text, "Strza³ka w dó³");
- if ( num == VK_CANCEL ) strcpy(text, "Ctrl-break");
- if ( num == VK_BACK ) strcpy(text, "<--");
- if ( num == VK_TAB ) strcpy(text, "Tab");
- if ( num == VK_CLEAR ) strcpy(text, "Delete");
- if ( num == VK_RETURN ) strcpy(text, "Enter");
- if ( num == VK_SHIFT ) strcpy(text, "Shift");
- if ( num == VK_CONTROL ) strcpy(text, "Ctrl");
- if ( num == VK_MENU ) strcpy(text, "Alt");
- if ( num == VK_PAUSE ) strcpy(text, "Pause");
- if ( num == VK_CAPITAL ) strcpy(text, "Caps Lock");
- if ( num == VK_ESCAPE ) strcpy(text, "Esc");
- if ( num == VK_SPACE ) strcpy(text, "Spacja");
- if ( num == VK_PRIOR ) strcpy(text, "Page Up");
- if ( num == VK_NEXT ) strcpy(text, "Page Down");
- if ( num == VK_END ) strcpy(text, "End");
- if ( num == VK_HOME ) strcpy(text, "Home");
- if ( num == VK_SELECT ) strcpy(text, "Zaznacz");
- if ( num == VK_EXECUTE ) strcpy(text, "Wykonaj");
- if ( num == VK_SNAPSHOT ) strcpy(text, "Print Scrn");
- if ( num == VK_INSERT ) strcpy(text, "Insert");
- if ( num == VK_DELETE ) strcpy(text, "Delete");
- if ( num == VK_HELP ) strcpy(text, "Pomoc");
- if ( num == VK_LWIN ) strcpy(text, "Lewy klawisz Windows");
- if ( num == VK_RWIN ) strcpy(text, "Prawy klawisz Windows");
- if ( num == VK_APPS ) strcpy(text, "Klawisz menu kontekstowego");
- if ( num == VK_NUMPAD0 ) strcpy(text, "Klaw. Num. 0");
- if ( num == VK_NUMPAD1 ) strcpy(text, "Klaw. Num. 1");
- if ( num == VK_NUMPAD2 ) strcpy(text, "Klaw. Num. 2");
- if ( num == VK_NUMPAD3 ) strcpy(text, "Klaw. Num. 3");
- if ( num == VK_NUMPAD4 ) strcpy(text, "Klaw. Num. 4");
- if ( num == VK_NUMPAD5 ) strcpy(text, "Klaw. Num. 5");
- if ( num == VK_NUMPAD6 ) strcpy(text, "Klaw. Num. 6");
- if ( num == VK_NUMPAD7 ) strcpy(text, "Klaw. Num. 7");
- if ( num == VK_NUMPAD8 ) strcpy(text, "Klaw. Num. 8");
- if ( num == VK_NUMPAD9 ) strcpy(text, "Klaw. Num. 9");
- if ( num == VK_MULTIPLY ) strcpy(text, "Klaw. Num. *");
- if ( num == VK_ADD ) strcpy(text, "Klaw. Num. +");
- if ( num == VK_SEPARATOR ) strcpy(text, "Klaw. Num. separator");
- if ( num == VK_SUBTRACT ) strcpy(text, "Klaw. Num. -");
- if ( num == VK_DECIMAL ) strcpy(text, "Klaw. Num. .");
- if ( num == VK_DIVIDE ) strcpy(text, "Klaw. Num. /");
- if ( num == VK_F1 ) strcpy(text, "F1");
- if ( num == VK_F2 ) strcpy(text, "F2");
- if ( num == VK_F3 ) strcpy(text, "F3");
- if ( num == VK_F4 ) strcpy(text, "F4");
- if ( num == VK_F5 ) strcpy(text, "F5");
- if ( num == VK_F6 ) strcpy(text, "F6");
- if ( num == VK_F7 ) strcpy(text, "F7");
- if ( num == VK_F8 ) strcpy(text, "F8");
- if ( num == VK_F9 ) strcpy(text, "F9");
- if ( num == VK_F10 ) strcpy(text, "F10");
- if ( num == VK_F11 ) strcpy(text, "F11");
- if ( num == VK_F12 ) strcpy(text, "F12");
- if ( num == VK_F13 ) strcpy(text, "F13");
- if ( num == VK_F14 ) strcpy(text, "F14");
- if ( num == VK_F15 ) strcpy(text, "F15");
- if ( num == VK_F16 ) strcpy(text, "F16");
- if ( num == VK_F17 ) strcpy(text, "F17");
- if ( num == VK_F18 ) strcpy(text, "F18");
- if ( num == VK_F19 ) strcpy(text, "F19");
- if ( num == VK_F20 ) strcpy(text, "F20");
- if ( num == VK_NUMLOCK ) strcpy(text, "Num Lock");
- if ( num == VK_SCROLL ) strcpy(text, "Scroll Lock");
- if ( num == VK_ATTN ) strcpy(text, "Attn");
- if ( num == VK_CRSEL ) strcpy(text, "CrSel");
- if ( num == VK_EXSEL ) strcpy(text, "ExSel");
- if ( num == VK_EREOF ) strcpy(text, "Erase EOF");
- if ( num == VK_PLAY ) strcpy(text, "Graj");
- if ( num == VK_ZOOM ) strcpy(text, "Powiêkszenie");
- if ( num == VK_PA1 ) strcpy(text, "PA1");
- if ( num == VK_OEM_CLEAR ) strcpy(text, "WyczyϾ");
- if ( num == VK_BUTTON1 ) strcpy(text, "Przycisk 1");
- if ( num == VK_BUTTON2 ) strcpy(text, "Przycisk 2");
- if ( num == VK_BUTTON3 ) strcpy(text, "Przycisk 3");
- if ( num == VK_BUTTON4 ) strcpy(text, "Przycisk 4");
- if ( num == VK_BUTTON5 ) strcpy(text, "Przycisk 5");
- if ( num == VK_BUTTON6 ) strcpy(text, "Przycisk 6");
- if ( num == VK_BUTTON7 ) strcpy(text, "Przycisk 7");
- if ( num == VK_BUTTON8 ) strcpy(text, "Przycisk 8");
- if ( num == VK_BUTTON9 ) strcpy(text, "Przycisk 9");
- if ( num == VK_BUTTON10 ) strcpy(text, "Przycisk 10");
- if ( num == VK_BUTTON11 ) strcpy(text, "Przycisk 11");
- if ( num == VK_BUTTON12 ) strcpy(text, "Przycisk 12");
- if ( num == VK_BUTTON13 ) strcpy(text, "Przycisk 13");
- if ( num == VK_BUTTON14 ) strcpy(text, "Przycisk 14");
- if ( num == VK_BUTTON15 ) strcpy(text, "Przycisk 15");
- if ( num == VK_BUTTON16 ) strcpy(text, "Przycisk 16");
- if ( num == VK_BUTTON17 ) strcpy(text, "Przycisk 17");
- if ( num == VK_BUTTON18 ) strcpy(text, "Przycisk 18");
- if ( num == VK_BUTTON19 ) strcpy(text, "Przycisk 19");
- if ( num == VK_BUTTON20 ) strcpy(text, "Przycisk 20");
- if ( num == VK_BUTTON21 ) strcpy(text, "Przycisk 21");
- if ( num == VK_BUTTON22 ) strcpy(text, "Przycisk 22");
- if ( num == VK_BUTTON23 ) strcpy(text, "Przycisk 23");
- if ( num == VK_BUTTON24 ) strcpy(text, "Przycisk 24");
- if ( num == VK_BUTTON25 ) strcpy(text, "Przycisk 25");
- if ( num == VK_BUTTON26 ) strcpy(text, "Przycisk 26");
- if ( num == VK_BUTTON27 ) strcpy(text, "Przycisk 27");
- if ( num == VK_BUTTON28 ) strcpy(text, "Przycisk 28");
- if ( num == VK_BUTTON29 ) strcpy(text, "Przycisk 29");
- if ( num == VK_BUTTON30 ) strcpy(text, "Przycisk 30");
- if ( num == VK_BUTTON31 ) strcpy(text, "Przycisk 31");
- if ( num == VK_BUTTON32 ) strcpy(text, "Przycisk 32");
- if ( num == VK_WHEELUP ) strcpy(text, "Kó³ko w górê");
- if ( num == VK_WHEELDOWN ) strcpy(text, "Kó³ko w dó³");
- }
-#endif
-
- return ( text[0] != 0 );
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.// restext.cpp
+
+#include <stdio.h>
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "common/language.h"
+#include "common/misc.h"
+#include "common/event.h"
+#include "object/object.h"
+#include "CBot/resource.h"
+#include "common/restext.h"
+
+
+
+//** -> text to translate!
+
+
+
+// Gives the pointer to the engine.
+
+void SetEngine(CD3DEngine *engine)
+{
+ g_engine = engine;
+}
+
+// Give the player's name.
+
+void SetGlobalGamerName(char *name)
+{
+ strcpy(g_gamerName, name);
+}
+
+
+
+struct KeyDesc
+{
+ KeyRank key;
+ char name[20];
+};
+
+static KeyDesc keyTable[22] =
+{
+ { KEYRANK_LEFT, "left;" },
+ { KEYRANK_RIGHT, "right;" },
+ { KEYRANK_UP, "up;" },
+ { KEYRANK_DOWN, "down;" },
+ { KEYRANK_GUP, "gup;" },
+ { KEYRANK_GDOWN, "gdown;" },
+ { KEYRANK_CAMERA, "camera;" },
+ { KEYRANK_DESEL, "desel;" },
+ { KEYRANK_ACTION, "action;" },
+ { KEYRANK_NEAR, "near;" },
+ { KEYRANK_AWAY, "away;" },
+ { KEYRANK_NEXT, "next;" },
+ { KEYRANK_HUMAN, "human;" },
+ { KEYRANK_QUIT, "quit;" },
+ { KEYRANK_HELP, "help;" },
+ { KEYRANK_PROG, "prog;" },
+ { KEYRANK_CBOT, "cbot;" },
+ { KEYRANK_VISIT, "visit;" },
+ { KEYRANK_SPEED10, "speed10;" },
+ { KEYRANK_SPEED15, "speed15;" },
+ { KEYRANK_SPEED20, "speed20;" },
+ { KEYRANK_SPEED30, "speed30;" },
+};
+
+// Seeks a key.
+
+bool SearchKey(char *cmd, KeyRank &key)
+{
+ int i;
+
+ for ( i=0 ; i<22 ; i++ )
+ {
+ if ( strstr(cmd, keyTable[i].name) == cmd )
+ {
+ key = keyTable[i].key;
+ return true;
+ }
+ }
+ return false;
+}
+
+// Replaces the commands "\key name;" in a text.
+
+void PutKeyName(char* dst, char* src)
+{
+ KeyRank key;
+ char name[50];
+ int s, d, n, res;
+
+ s = d = 0;
+ while ( src[s] != 0 )
+ {
+ if ( src[s+0] == '\\' &&
+ src[s+1] == 'k' &&
+ src[s+2] == 'e' &&
+ src[s+3] == 'y' &&
+ src[s+4] == ' ' )
+ {
+ if ( SearchKey(src+s+5, key) )
+ {
+ res = g_engine->RetKey(key, 0);
+ if ( res != 0 )
+ {
+ if ( GetResource(RES_KEY, res, name) )
+ {
+ n = 0;
+ while ( name[n] != 0 )
+ {
+ dst[d++] = name[n++];
+ }
+ while ( src[s++] != ';' );
+ continue;
+ }
+ }
+ }
+ }
+
+ dst[d++] = src[s++];
+ }
+ dst[d++] = 0;
+}
+
+
+// Returns the text of a resource.
+
+bool GetResource(ResType type, int num, char* text)
+{
+ char buffer[100];
+
+ if ( !GetResourceBase(type, num, buffer) )
+ {
+ text[0] = 0;
+ return false;
+ }
+
+ PutKeyName(text, buffer);
+ return true;
+}
+
+
+// Returns the text of a resource.
+
+bool GetResourceBase(ResType type, int num, char* text)
+{
+ text[0] = 0;
+
+#if _ENGLISH
+ if ( type == RES_TEXT )
+ {
+ #if _FULL
+ if ( num == RT_VERSION_ID ) strcpy(text, "1.18 /e");
+ #endif
+ #if _NET
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A 1.18");
+ #endif
+ #if _SCHOOL & _EDU
+ #if _TEEN
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen EDU 1.18");
+ #else
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A EDU 1.18");
+ #endif
+ #endif
+ #if _SCHOOL & _PERSO
+ #if _TEEN
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen PERSO 1.18");
+ #else
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A PERSO 1.18");
+ #endif
+ #endif
+ #if _SCHOOL & _CEEBOTDEMO
+ #if _TEEN
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen DEMO 1.18");
+ #else
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A DEMO 1.18");
+ #endif
+ #endif
+ #if _DEMO
+ if ( num == RT_VERSION_ID ) strcpy(text, "Demo 1.18 /e");
+ #endif
+ if ( num == RT_DISINFO_TITLE ) strcpy(text, "SatCom");
+ if ( num == RT_WINDOW_MAXIMIZED ) strcpy(text, "Maximize");
+ if ( num == RT_WINDOW_MINIMIZED ) strcpy(text, "Minimize");
+ if ( num == RT_WINDOW_STANDARD ) strcpy(text, "Normal size");
+ if ( num == RT_WINDOW_CLOSE ) strcpy(text, "Close");
+
+ if ( num == RT_STUDIO_TITLE ) strcpy(text, "Program editor");
+ if ( num == RT_SCRIPT_NEW ) strcpy(text, "New");
+ if ( num == RT_NAME_DEFAULT ) strcpy(text, "Player");
+ if ( num == RT_IO_NEW ) strcpy(text, "New ...");
+ if ( num == RT_KEY_OR ) strcpy(text, " or ");
+
+#if _NEWLOOK
+ if ( num == RT_TITLE_BASE ) strcpy(text, "CeeBot");
+ if ( num == RT_TITLE_INIT ) strcpy(text, "CeeBot");
+#else
+ if ( num == RT_TITLE_BASE ) strcpy(text, "COLOBOT");
+ if ( num == RT_TITLE_INIT ) strcpy(text, "COLOBOT");
+#endif
+ if ( num == RT_TITLE_TRAINER ) strcpy(text, "Programming exercises");
+ if ( num == RT_TITLE_DEFI ) strcpy(text, "Challenges");
+ if ( num == RT_TITLE_MISSION ) strcpy(text, "Missions");
+ if ( num == RT_TITLE_FREE ) strcpy(text, "Free game");
+ if ( num == RT_TITLE_TEEN ) strcpy(text, "Free game");
+ if ( num == RT_TITLE_USER ) strcpy(text, "User levels");
+ if ( num == RT_TITLE_PROTO ) strcpy(text, "Prototypes");
+ if ( num == RT_TITLE_SETUP ) strcpy(text, "Options");
+ if ( num == RT_TITLE_NAME ) strcpy(text, "Player's name");
+ if ( num == RT_TITLE_PERSO ) strcpy(text, "Customize your appearance");
+ if ( num == RT_TITLE_WRITE ) strcpy(text, "Save the current mission");
+ if ( num == RT_TITLE_READ ) strcpy(text, "Load a saved mission");
+
+ if ( num == RT_PLAY_CHAPt ) strcpy(text, " Chapters:");
+ if ( num == RT_PLAY_CHAPd ) strcpy(text, " Chapters:");
+ if ( num == RT_PLAY_CHAPm ) strcpy(text, " Planets:");
+ if ( num == RT_PLAY_CHAPf ) strcpy(text, " Planets:");
+ if ( num == RT_PLAY_CHAPu ) strcpy(text, " User levels:");
+ if ( num == RT_PLAY_CHAPp ) strcpy(text, " Planets:");
+ if ( num == RT_PLAY_CHAPte ) strcpy(text, " Chapters:");
+ if ( num == RT_PLAY_LISTt ) strcpy(text, " Exercises in the chapter:");
+ if ( num == RT_PLAY_LISTd ) strcpy(text, " Challenges in the chapter:");
+ if ( num == RT_PLAY_LISTm ) strcpy(text, " Missions on this planet:");
+ if ( num == RT_PLAY_LISTf ) strcpy(text, " Free game on this planet:");
+ if ( num == RT_PLAY_LISTu ) strcpy(text, " Missions on this level:");
+ if ( num == RT_PLAY_LISTp ) strcpy(text, " Prototypes on this planet:");
+ if ( num == RT_PLAY_LISTk ) strcpy(text, " Free game on this chapter:");
+ if ( num == RT_PLAY_RESUME ) strcpy(text, " Summary:");
+
+ if ( num == RT_SETUP_DEVICE ) strcpy(text, " Drivers:");
+ if ( num == RT_SETUP_MODE ) strcpy(text, " Resolution:");
+ if ( num == RT_SETUP_KEY1 ) strcpy(text, "1) First click on the key you want to redefine.");
+ if ( num == RT_SETUP_KEY2 ) strcpy(text, "2) Then press the key you want to use instead.");
+
+ if ( num == RT_PERSO_FACE ) strcpy(text, "Face type:");
+ if ( num == RT_PERSO_GLASSES ) strcpy(text, "Eyeglasses:");
+ if ( num == RT_PERSO_HAIR ) strcpy(text, "Hair color:");
+ if ( num == RT_PERSO_COMBI ) strcpy(text, "Suit color:");
+ if ( num == RT_PERSO_BAND ) strcpy(text, "Strip color:");
+
+#if _NEWLOOK
+ if ( num == RT_DIALOG_QUIT ) strcpy(text, "Do you want to quit CeeBot ?");
+ if ( num == RT_DIALOG_TITLE ) strcpy(text, "CeeBot");
+ if ( num == RT_DIALOG_YESQUIT ) strcpy(text, "Quit\\Quit CeeBot");
+#else
+ if ( num == RT_DIALOG_QUIT ) strcpy(text, "Do you want to quit COLOBOT ?");
+ if ( num == RT_DIALOG_TITLE ) strcpy(text, "COLOBOT");
+ if ( num == RT_DIALOG_YESQUIT ) strcpy(text, "Quit\\Quit COLOBOT");
+#endif
+ if ( num == RT_DIALOG_ABORT ) strcpy(text, "Quit the mission?");
+ if ( num == RT_DIALOG_YES ) strcpy(text, "Abort\\Abort the current mission");
+ if ( num == RT_DIALOG_NO ) strcpy(text, "Continue\\Continue the current mission");
+ if ( num == RT_DIALOG_NOQUIT ) strcpy(text, "Continue\\Continue the game");
+ if ( num == RT_DIALOG_DELOBJ ) strcpy(text, "Do you really want to destroy the selected building?");
+ if ( num == RT_DIALOG_DELGAME ) strcpy(text, "Do you want to delete %s's saved games? ");
+ if ( num == RT_DIALOG_YESDEL ) strcpy(text, "Delete");
+ if ( num == RT_DIALOG_NODEL ) strcpy(text, "Cancel");
+ if ( num == RT_DIALOG_LOADING ) strcpy(text, "LOADING");
+
+ if ( num == RT_STUDIO_LISTTT ) strcpy(text, "Keyword help(\\key cbot;)");
+ if ( num == RT_STUDIO_COMPOK ) strcpy(text, "Compilation ok (0 errors)");
+ if ( num == RT_STUDIO_PROGSTOP ) strcpy(text, "Program finished");
+
+ if ( num == RT_SATCOM_LIST ) strcpy(text, "\\b;List of objects\n");
+ if ( num == RT_SATCOM_BOT ) strcpy(text, "\\b;Robots\n");
+ if ( num == RT_SATCOM_BUILDING ) strcpy(text, "\\b;Buildings\n");
+ if ( num == RT_SATCOM_FRET ) strcpy(text, "\\b;Moveable objects\n");
+ if ( num == RT_SATCOM_ALIEN ) strcpy(text, "\\b;Aliens\n");
+ if ( num == RT_SATCOM_NULL ) strcpy(text, "\\c; (none)\\n;\n");
+ if ( num == RT_SATCOM_ERROR1 ) strcpy(text, "\\b;Error\n");
+ if ( num == RT_SATCOM_ERROR2 ) strcpy(text, "The list is only available if a \\l;radar station\\u object\\radar; is working.\n");
+
+ if ( num == RT_IO_OPEN ) strcpy(text, "Open");
+ if ( num == RT_IO_SAVE ) strcpy(text, "Save");
+ if ( num == RT_IO_LIST ) strcpy(text, "Folder: %s");
+ if ( num == RT_IO_NAME ) strcpy(text, "Name:");
+ if ( num == RT_IO_DIR ) strcpy(text, "Folder:");
+ if ( num == RT_IO_PRIVATE ) strcpy(text, "Private\\Private folder");
+ if ( num == RT_IO_PUBLIC ) strcpy(text, "Public\\Common folder");
+
+ if ( num == RT_GENERIC_DEV1 ) strcpy(text, "Developed by :");
+ if ( num == RT_GENERIC_DEV2 ) strcpy(text, "www.epsitec.com");
+//? if ( num == RT_GENERIC_EDIT1 ) strcpy(text, "English version published by:");
+//? if ( num == RT_GENERIC_EDIT2 ) strcpy(text, "www.?.com");
+ if ( num == RT_GENERIC_EDIT1 ) strcpy(text, " ");
+ if ( num == RT_GENERIC_EDIT2 ) strcpy(text, " ");
+
+ if ( num == RT_INTERFACE_REC ) strcpy(text, "Recorder");
+ }
+
+ if ( type == RES_EVENT )
+ {
+ if ( num == EVENT_BUTTON_OK ) strcpy(text, "OK");
+ if ( num == EVENT_BUTTON_CANCEL ) strcpy(text, "Cancel");
+ if ( num == EVENT_BUTTON_NEXT ) strcpy(text, "Next");
+ if ( num == EVENT_BUTTON_PREV ) strcpy(text, "Previous");
+ if ( num == EVENT_BUTTON_QUIT ) strcpy(text, "Menu (\\key quit;)");
+
+ if ( num == EVENT_DIALOG_OK ) strcpy(text, "OK");
+ if ( num == EVENT_DIALOG_CANCEL ) strcpy(text, "Cancel");
+
+ if ( num == EVENT_INTERFACE_TRAINER) strcpy(text, "Exercises\\Programming exercises");
+ if ( num == EVENT_INTERFACE_DEFI ) strcpy(text, "Challenges\\Programming challenges");
+ if ( num == EVENT_INTERFACE_MISSION) strcpy(text, "Missions\\Select mission");
+ if ( num == EVENT_INTERFACE_FREE ) strcpy(text, "Free game\\Free game without a specific goal");
+ if ( num == EVENT_INTERFACE_TEEN ) strcpy(text, "Free game\\Free game without a specific goal");
+ if ( num == EVENT_INTERFACE_USER ) strcpy(text, "User\\User levels");
+ if ( num == EVENT_INTERFACE_PROTO ) strcpy(text, "Proto\\Prototypes under development");
+ if ( num == EVENT_INTERFACE_NAME ) strcpy(text, "New player\\Choose player's name");
+ if ( num == EVENT_INTERFACE_SETUP ) strcpy(text, "Options\\Preferences");
+ if ( num == EVENT_INTERFACE_AGAIN ) strcpy(text, "Restart\\Restart the mission from the beginning");
+ if ( num == EVENT_INTERFACE_WRITE ) strcpy(text, "Save\\Save the current mission ");
+ if ( num == EVENT_INTERFACE_READ ) strcpy(text, "Load\\Load a saved mission");
+#if _NEWLOOK
+ if ( num == EVENT_INTERFACE_ABORT ) strcpy(text, "\\Return to CeeBot");
+ if ( num == EVENT_INTERFACE_QUIT ) strcpy(text, "Quit\\Quit CeeBot");
+#else
+ if ( num == EVENT_INTERFACE_ABORT ) strcpy(text, "\\Return to COLOBOT");
+ if ( num == EVENT_INTERFACE_QUIT ) strcpy(text, "Quit\\Quit COLOBOT");
+#endif
+ if ( num == EVENT_INTERFACE_BACK ) strcpy(text, "<< Back \\Back to the previous screen");
+ if ( num == EVENT_INTERFACE_PLAY ) strcpy(text, "Play\\Start mission!");
+ if ( num == EVENT_INTERFACE_SETUPd ) strcpy(text, "Device\\Driver and resolution settings");
+ if ( num == EVENT_INTERFACE_SETUPg ) strcpy(text, "Graphics\\Graphics settings");
+ if ( num == EVENT_INTERFACE_SETUPp ) strcpy(text, "Game\\Game settings");
+ if ( num == EVENT_INTERFACE_SETUPc ) strcpy(text, "Controls\\Keyboard, joystick and mouse settings");
+ if ( num == EVENT_INTERFACE_SETUPs ) strcpy(text, "Sound\\Music and game sound volume");
+ if ( num == EVENT_INTERFACE_DEVICE ) strcpy(text, "Unit");
+ if ( num == EVENT_INTERFACE_RESOL ) strcpy(text, "Resolution");
+ if ( num == EVENT_INTERFACE_FULL ) strcpy(text, "Full screen\\Full screen or window mode");
+ if ( num == EVENT_INTERFACE_APPLY ) strcpy(text, "Apply changes\\Activates the changed settings");
+
+ if ( num == EVENT_INTERFACE_TOTO ) strcpy(text, "Robbie\\Your assistant");
+ if ( num == EVENT_INTERFACE_SHADOW ) strcpy(text, "Shadows\\Shadows on the ground");
+ if ( num == EVENT_INTERFACE_GROUND ) strcpy(text, "Marks on the ground\\Marks on the ground");
+ if ( num == EVENT_INTERFACE_DIRTY ) strcpy(text, "Dust\\Dust and dirt on bots and buildings");
+ if ( num == EVENT_INTERFACE_FOG ) strcpy(text, "Fog\\Fog");
+ if ( num == EVENT_INTERFACE_LENS ) strcpy(text, "Sunbeams\\Sunbeams in the sky");
+ if ( num == EVENT_INTERFACE_SKY ) strcpy(text, "Sky\\Clouds and nebulae");
+ if ( num == EVENT_INTERFACE_PLANET ) strcpy(text, "Planets and stars\\Astronomical objects in the sky");
+ if ( num == EVENT_INTERFACE_LIGHT ) strcpy(text, "Dynamic lighting\\Mobile light sources");
+ if ( num == EVENT_INTERFACE_PARTI ) strcpy(text, "Number of particles\\Explosions, dust, reflections, etc.");
+ if ( num == EVENT_INTERFACE_CLIP ) strcpy(text, "Depth of field\\Maximum visibility");
+ if ( num == EVENT_INTERFACE_DETAIL ) strcpy(text, "Details\\Visual quality of 3D objects");
+ if ( num == EVENT_INTERFACE_TEXTURE) strcpy(text, "Textures\\Quality of textures ");
+ if ( num == EVENT_INTERFACE_GADGET ) strcpy(text, "Num of decorative objects\\Number of purely ornamental objects");
+ if ( num == EVENT_INTERFACE_RAIN ) strcpy(text, "Particles in the interface\\Steam clouds and sparks in the interface");
+ if ( num == EVENT_INTERFACE_GLINT ) strcpy(text, "Reflections on the buttons \\Shiny buttons");
+ if ( num == EVENT_INTERFACE_TOOLTIP) strcpy(text, "Help balloons\\Explain the function of the buttons");
+ if ( num == EVENT_INTERFACE_MOVIES ) strcpy(text, "Film sequences\\Films before and after the missions");
+ if ( num == EVENT_INTERFACE_NICERST) strcpy(text, "Exit film\\Film at the exit of exercises");
+ if ( num == EVENT_INTERFACE_HIMSELF) strcpy(text, "Friendly fire\\Your shooting can damage your own objects ");
+ if ( num == EVENT_INTERFACE_SCROLL ) strcpy(text, "Scrolling\\Scrolling when the mouse touches right or left border");
+ if ( num == EVENT_INTERFACE_INVERTX) strcpy(text, "Mouse inversion X\\Inversion of the scrolling direction on the X axis");
+ if ( num == EVENT_INTERFACE_INVERTY) strcpy(text, "Mouse inversion Y\\Inversion of the scrolling direction on the Y axis");
+ if ( num == EVENT_INTERFACE_EFFECT ) strcpy(text, "Quake at explosions\\The screen shakes at explosions");
+ if ( num == EVENT_INTERFACE_MOUSE ) strcpy(text, "Mouse shadow\\Gives the mouse a shadow");
+ if ( num == EVENT_INTERFACE_EDITMODE) strcpy(text, "Automatic indent\\When program editing");
+ if ( num == EVENT_INTERFACE_EDITVALUE)strcpy(text, "Big indent\\Indent 2 or 4 spaces per level defined by braces");
+ if ( num == EVENT_INTERFACE_SOLUCE4) strcpy(text, "Access to solutions\\Show program \"4: Solution\" in the exercises"); //**
+
+ if ( num == EVENT_INTERFACE_KDEF ) strcpy(text, "Standard controls\\Standard key functions");
+ if ( num == EVENT_INTERFACE_KLEFT ) strcpy(text, "Turn left\\turns the bot to the left");
+ if ( num == EVENT_INTERFACE_KRIGHT ) strcpy(text, "Turn right\\turns the bot to the right");
+ if ( num == EVENT_INTERFACE_KUP ) strcpy(text, "Forward\\Moves forward");
+ if ( num == EVENT_INTERFACE_KDOWN ) strcpy(text, "Backward\\Moves backward");
+ if ( num == EVENT_INTERFACE_KGUP ) strcpy(text, "Climb\\Increases the power of the jet");
+ if ( num == EVENT_INTERFACE_KGDOWN ) strcpy(text, "Descend\\Reduces the power of the jet");
+ if ( num == EVENT_INTERFACE_KCAMERA) strcpy(text, "Change camera\\Switches between onboard camera and following camera");
+ if ( num == EVENT_INTERFACE_KDESEL ) strcpy(text, "Previous object\\Selects the previous object");
+ if ( num == EVENT_INTERFACE_KACTION) strcpy(text, "Standard action\\Standard action of the bot (take/grab, shoot, sniff, etc)");
+ if ( num == EVENT_INTERFACE_KNEAR ) strcpy(text, "Camera closer\\Moves the camera forward");
+ if ( num == EVENT_INTERFACE_KAWAY ) strcpy(text, "Camera back\\Moves the camera backward");
+ if ( num == EVENT_INTERFACE_KNEXT ) strcpy(text, "Next object\\Selects the next object");
+ if ( num == EVENT_INTERFACE_KHUMAN ) strcpy(text, "Select the astronaut\\Selects the astronaut");
+ if ( num == EVENT_INTERFACE_KQUIT ) strcpy(text, "Quit\\Quit the current mission or exercise");
+ if ( num == EVENT_INTERFACE_KHELP ) strcpy(text, "Instructions\\Shows the instructions for the current mission");
+ if ( num == EVENT_INTERFACE_KPROG ) strcpy(text, "Programming help\\Gives more detailed help with programming");
+ if ( num == EVENT_INTERFACE_KCBOT ) strcpy(text, "Key word help\\More detailed help about key words");
+ if ( num == EVENT_INTERFACE_KVISIT ) strcpy(text, "Origin of last message\\Shows where the last message was sent from");
+ if ( num == EVENT_INTERFACE_KSPEED10) strcpy(text, "Speed 1.0x\\Normal speed");
+ if ( num == EVENT_INTERFACE_KSPEED15) strcpy(text, "Speed 1.5x\\1.5 times faster");
+ if ( num == EVENT_INTERFACE_KSPEED20) strcpy(text, "Speed 2.0x\\Double speed");
+ if ( num == EVENT_INTERFACE_KSPEED30) strcpy(text, "Speed 3.0x\\Three times faster");
+
+ if ( num == EVENT_INTERFACE_VOLSOUND) strcpy(text, "Sound effects:\\Volume of engines, voice, shooting, etc.");
+ if ( num == EVENT_INTERFACE_VOLMUSIC) strcpy(text, "Background sound :\\Volume of audio tracks on the CD");
+ if ( num == EVENT_INTERFACE_SOUND3D) strcpy(text, "3D sound\\3D positioning of the sound");
+
+ if ( num == EVENT_INTERFACE_MIN ) strcpy(text, "Lowest\\Minimum graphic quality (highest frame rate)");
+ if ( num == EVENT_INTERFACE_NORM ) strcpy(text, "Normal\\Normal graphic quality");
+ if ( num == EVENT_INTERFACE_MAX ) strcpy(text, "Highest\\Highest graphic quality (lowest frame rate)");
+
+ if ( num == EVENT_INTERFACE_SILENT ) strcpy(text, "Mute\\No sound");
+ if ( num == EVENT_INTERFACE_NOISY ) strcpy(text, "Normal\\Normal sound volume");
+
+ if ( num == EVENT_INTERFACE_JOYSTICK) strcpy(text, "Use a joystick\\Joystick or keyboard");
+ if ( num == EVENT_INTERFACE_SOLUCE ) strcpy(text, "Access to solution\\Shows the solution (detailed instructions for missions)");
+
+ if ( num == EVENT_INTERFACE_NEDIT ) strcpy(text, "\\New player name");
+ if ( num == EVENT_INTERFACE_NOK ) strcpy(text, "OK\\Choose the selected player");
+ if ( num == EVENT_INTERFACE_NCANCEL) strcpy(text, "Cancel\\Keep current player name");
+ if ( num == EVENT_INTERFACE_NDELETE) strcpy(text, "Delete player\\Deletes the player from the list");
+ if ( num == EVENT_INTERFACE_NLABEL ) strcpy(text, "Player name");
+
+ if ( num == EVENT_INTERFACE_IOWRITE) strcpy(text, "Save\\Saves the current mission");
+ if ( num == EVENT_INTERFACE_IOREAD ) strcpy(text, "Load\\Loads the selected mission");
+ if ( num == EVENT_INTERFACE_IOLIST ) strcpy(text, "List of saved missions");
+ if ( num == EVENT_INTERFACE_IOLABEL) strcpy(text, "Filename:");
+ if ( num == EVENT_INTERFACE_IONAME ) strcpy(text, "Mission name");
+ if ( num == EVENT_INTERFACE_IOIMAGE) strcpy(text, "Photography");
+ if ( num == EVENT_INTERFACE_IODELETE) strcpy(text, "Delete\\Deletes the selected file");
+
+ if ( num == EVENT_INTERFACE_PERSO ) strcpy(text, "Appearance\\Choose your appearance");
+ if ( num == EVENT_INTERFACE_POK ) strcpy(text, "OK");
+ if ( num == EVENT_INTERFACE_PCANCEL) strcpy(text, "Cancel");
+ if ( num == EVENT_INTERFACE_PDEF ) strcpy(text, "Standard\\Standard appearance settings");
+ if ( num == EVENT_INTERFACE_PHEAD ) strcpy(text, "Head\\Face and hair");
+ if ( num == EVENT_INTERFACE_PBODY ) strcpy(text, "Suit\\Astronaut suit");
+ if ( num == EVENT_INTERFACE_PLROT ) strcpy(text, "\\Turn left");
+ if ( num == EVENT_INTERFACE_PRROT ) strcpy(text, "\\Turn right");
+ if ( num == EVENT_INTERFACE_PCRa ) strcpy(text, "Red");
+ if ( num == EVENT_INTERFACE_PCGa ) strcpy(text, "Green");
+ if ( num == EVENT_INTERFACE_PCBa ) strcpy(text, "Blue");
+ if ( num == EVENT_INTERFACE_PCRb ) strcpy(text, "Red");
+ if ( num == EVENT_INTERFACE_PCGb ) strcpy(text, "Green");
+ if ( num == EVENT_INTERFACE_PCBb ) strcpy(text, "Blue");
+ if ( num == EVENT_INTERFACE_PFACE1 ) strcpy(text, "\\Face 1");
+ if ( num == EVENT_INTERFACE_PFACE2 ) strcpy(text, "\\Face 4");
+ if ( num == EVENT_INTERFACE_PFACE3 ) strcpy(text, "\\Face 3");
+ if ( num == EVENT_INTERFACE_PFACE4 ) strcpy(text, "\\Face 2");
+ if ( num == EVENT_INTERFACE_PGLASS0) strcpy(text, "\\No eyeglasses");
+ if ( num == EVENT_INTERFACE_PGLASS1) strcpy(text, "\\Eyeglasses 1");
+ if ( num == EVENT_INTERFACE_PGLASS2) strcpy(text, "\\Eyeglasses 2");
+ if ( num == EVENT_INTERFACE_PGLASS3) strcpy(text, "\\Eyeglasses 3");
+ if ( num == EVENT_INTERFACE_PGLASS4) strcpy(text, "\\Eyeglasses 4");
+ if ( num == EVENT_INTERFACE_PGLASS5) strcpy(text, "\\Eyeglasses 5");
+
+ if ( num == EVENT_OBJECT_DESELECT ) strcpy(text, "Previous selection (\\key desel;)");
+ if ( num == EVENT_OBJECT_LEFT ) strcpy(text, "Turn left (\\key left;)");
+ if ( num == EVENT_OBJECT_RIGHT ) strcpy(text, "Turn right (\\key right;)");
+ if ( num == EVENT_OBJECT_UP ) strcpy(text, "Forward (\\key up;)");
+ if ( num == EVENT_OBJECT_DOWN ) strcpy(text, "Backward (\\key down;)");
+ if ( num == EVENT_OBJECT_GASUP ) strcpy(text, "Up (\\key gup;)");
+ if ( num == EVENT_OBJECT_GASDOWN ) strcpy(text, "Down (\\key gdown;)");
+ if ( num == EVENT_OBJECT_HTAKE ) strcpy(text, "Grab or drop (\\key action;)");
+ if ( num == EVENT_OBJECT_MTAKE ) strcpy(text, "Grab or drop (\\key action;)");
+ if ( num == EVENT_OBJECT_MFRONT ) strcpy(text, "..in front");
+ if ( num == EVENT_OBJECT_MBACK ) strcpy(text, "..behind");
+ if ( num == EVENT_OBJECT_MPOWER ) strcpy(text, "..power cell");
+ if ( num == EVENT_OBJECT_BHELP ) strcpy(text, "Instructions for the mission (\\key help;)");
+ if ( num == EVENT_OBJECT_BTAKEOFF ) strcpy(text, "Take off to finish the mission");
+ if ( num == EVENT_OBJECT_BDERRICK ) strcpy(text, "Build a derrick");
+ if ( num == EVENT_OBJECT_BSTATION ) strcpy(text, "Build a power station");
+ if ( num == EVENT_OBJECT_BFACTORY ) strcpy(text, "Build a bot factory");
+ if ( num == EVENT_OBJECT_BREPAIR ) strcpy(text, "Build a repair center");
+ if ( num == EVENT_OBJECT_BCONVERT ) strcpy(text, "Build a converter");
+ if ( num == EVENT_OBJECT_BTOWER ) strcpy(text, "Build a defense tower");
+ if ( num == EVENT_OBJECT_BRESEARCH ) strcpy(text, "Build a research center");
+ if ( num == EVENT_OBJECT_BRADAR ) strcpy(text, "Build a radar station");
+ if ( num == EVENT_OBJECT_BENERGY ) strcpy(text, "Build a power cell factory");
+ if ( num == EVENT_OBJECT_BLABO ) strcpy(text, "Build an autolab");
+ if ( num == EVENT_OBJECT_BNUCLEAR ) strcpy(text, "Build a nuclear power plant");
+ if ( num == EVENT_OBJECT_BPARA ) strcpy(text, "Build a lightning conductor");
+ if ( num == EVENT_OBJECT_BINFO ) strcpy(text, "Build a exchange post");
+ if ( num == EVENT_OBJECT_GFLAT ) strcpy(text, "Show if the ground is flat");
+ if ( num == EVENT_OBJECT_FCREATE ) strcpy(text, "Plant a flag");
+ if ( num == EVENT_OBJECT_FDELETE ) strcpy(text, "Remove a flag");
+ if ( num == EVENT_OBJECT_FCOLORb ) strcpy(text, "\\Blue flags");
+ if ( num == EVENT_OBJECT_FCOLORr ) strcpy(text, "\\Red flags");
+ if ( num == EVENT_OBJECT_FCOLORg ) strcpy(text, "\\Green flags");
+ if ( num == EVENT_OBJECT_FCOLORy ) strcpy(text, "\\Yellow flags");
+ if ( num == EVENT_OBJECT_FCOLORv ) strcpy(text, "\\Violet flags");
+ if ( num == EVENT_OBJECT_FACTORYfa ) strcpy(text, "Build a winged grabber");
+ if ( num == EVENT_OBJECT_FACTORYta ) strcpy(text, "Build a tracked grabber");
+ if ( num == EVENT_OBJECT_FACTORYwa ) strcpy(text, "Build a wheeled grabber");
+ if ( num == EVENT_OBJECT_FACTORYia ) strcpy(text, "Build a legged grabber");
+ if ( num == EVENT_OBJECT_FACTORYfc ) strcpy(text, "Build a winged shooter");
+ if ( num == EVENT_OBJECT_FACTORYtc ) strcpy(text, "Build a tracked shooter");
+ if ( num == EVENT_OBJECT_FACTORYwc ) strcpy(text, "Build a wheeled shooter");
+ if ( num == EVENT_OBJECT_FACTORYic ) strcpy(text, "Build a legged shooter");
+ if ( num == EVENT_OBJECT_FACTORYfi ) strcpy(text, "Build a winged orga shooter");
+ if ( num == EVENT_OBJECT_FACTORYti ) strcpy(text, "Build a tracked orga shooter");
+ if ( num == EVENT_OBJECT_FACTORYwi ) strcpy(text, "Build a wheeled orga shooter");
+ if ( num == EVENT_OBJECT_FACTORYii ) strcpy(text, "Build a legged orga shooter");
+ if ( num == EVENT_OBJECT_FACTORYfs ) strcpy(text, "Build a winged sniffer");
+ if ( num == EVENT_OBJECT_FACTORYts ) strcpy(text, "Build a tracked sniffer");
+ if ( num == EVENT_OBJECT_FACTORYws ) strcpy(text, "Build a wheeled sniffer");
+ if ( num == EVENT_OBJECT_FACTORYis ) strcpy(text, "Build a legged sniffer");
+ if ( num == EVENT_OBJECT_FACTORYrt ) strcpy(text, "Build a thumper");
+ if ( num == EVENT_OBJECT_FACTORYrc ) strcpy(text, "Build a phazer shooter");
+ if ( num == EVENT_OBJECT_FACTORYrr ) strcpy(text, "Build a recycler");
+ if ( num == EVENT_OBJECT_FACTORYrs ) strcpy(text, "Build a shielder");
+ if ( num == EVENT_OBJECT_FACTORYsa ) strcpy(text, "Build a subber");
+ if ( num == EVENT_OBJECT_RTANK ) strcpy(text, "Run research program for tracked bots");
+ if ( num == EVENT_OBJECT_RFLY ) strcpy(text, "Run research program for winged bots");
+ if ( num == EVENT_OBJECT_RTHUMP ) strcpy(text, "Run research program for thumper");
+ if ( num == EVENT_OBJECT_RCANON ) strcpy(text, "Run research program for shooter");
+ if ( num == EVENT_OBJECT_RTOWER ) strcpy(text, "Run research program for defense tower");
+ if ( num == EVENT_OBJECT_RPHAZER ) strcpy(text, "Run research program for phazer shooter");
+ if ( num == EVENT_OBJECT_RSHIELD ) strcpy(text, "Run research program for shielder");
+ if ( num == EVENT_OBJECT_RATOMIC ) strcpy(text, "Run research program for nuclear power");
+ if ( num == EVENT_OBJECT_RiPAW ) strcpy(text, "Run research program for legged bots");
+ if ( num == EVENT_OBJECT_RiGUN ) strcpy(text, "Run research program for orga shooter");
+ if ( num == EVENT_OBJECT_RESET ) strcpy(text, "Return to start");
+ if ( num == EVENT_OBJECT_SEARCH ) strcpy(text, "Sniff (\\key action;)");
+ if ( num == EVENT_OBJECT_TERRAFORM ) strcpy(text, "Thump (\\key action;)");
+ if ( num == EVENT_OBJECT_FIRE ) strcpy(text, "Shoot (\\key action;)");
+ if ( num == EVENT_OBJECT_RECOVER ) strcpy(text, "Recycle (\\key action;)");
+ if ( num == EVENT_OBJECT_BEGSHIELD ) strcpy(text, "Extend shield (\\key action;)");
+ if ( num == EVENT_OBJECT_ENDSHIELD ) strcpy(text, "Withdraw shield (\\key action;)");
+ if ( num == EVENT_OBJECT_DIMSHIELD ) strcpy(text, "Shield radius");
+ if ( num == EVENT_OBJECT_PROGRUN ) strcpy(text, "Execute the selected program");
+ if ( num == EVENT_OBJECT_PROGEDIT ) strcpy(text, "Edit the selected program");
+ if ( num == EVENT_OBJECT_INFOOK ) strcpy(text, "\\SatCom on standby");
+ if ( num == EVENT_OBJECT_DELETE ) strcpy(text, "Destroy the building");
+ if ( num == EVENT_OBJECT_GENERGY ) strcpy(text, "Energy level");
+ if ( num == EVENT_OBJECT_GSHIELD ) strcpy(text, "Shield level");
+ if ( num == EVENT_OBJECT_GRANGE ) strcpy(text, "Jet temperature");
+ if ( num == EVENT_OBJECT_GPROGRESS ) strcpy(text, "Still working ...");
+ if ( num == EVENT_OBJECT_GRADAR ) strcpy(text, "Number of insects detected");
+ if ( num == EVENT_OBJECT_GINFO ) strcpy(text, "Transmitted information");
+ if ( num == EVENT_OBJECT_COMPASS ) strcpy(text, "Compass");
+//? if ( num == EVENT_OBJECT_MAP ) strcpy(text, "Mini-map");
+ if ( num == EVENT_OBJECT_MAPZOOM ) strcpy(text, "Zoom mini-map");
+ if ( num == EVENT_OBJECT_CAMERA ) strcpy(text, "Camera (\\key camera;)");
+ if ( num == EVENT_OBJECT_CAMERAleft) strcpy(text, "Camera to left");
+ if ( num == EVENT_OBJECT_CAMERAright) strcpy(text, "Camera to right");
+ if ( num == EVENT_OBJECT_CAMERAnear) strcpy(text, "Camera nearest");
+ if ( num == EVENT_OBJECT_CAMERAaway) strcpy(text, "Camera awayest");
+ if ( num == EVENT_OBJECT_HELP ) strcpy(text, "Help about selected object");
+ if ( num == EVENT_OBJECT_SOLUCE ) strcpy(text, "Show the solution");
+ if ( num == EVENT_OBJECT_SHORTCUT00) strcpy(text, "Switch bots <-> buildings");
+ if ( num == EVENT_OBJECT_LIMIT ) strcpy(text, "Show the range");
+ if ( num == EVENT_OBJECT_PEN0 ) strcpy(text, "\\Raise the pencil");
+ if ( num == EVENT_OBJECT_PEN1 ) strcpy(text, "\\Use the black pencil");
+ if ( num == EVENT_OBJECT_PEN2 ) strcpy(text, "\\Use the yellow pencil");
+ if ( num == EVENT_OBJECT_PEN3 ) strcpy(text, "\\Use the orange pencil");
+ if ( num == EVENT_OBJECT_PEN4 ) strcpy(text, "\\Use the red pencil");
+ if ( num == EVENT_OBJECT_PEN5 ) strcpy(text, "\\Use the purple pencil");
+ if ( num == EVENT_OBJECT_PEN6 ) strcpy(text, "\\Use the blue pencil");
+ if ( num == EVENT_OBJECT_PEN7 ) strcpy(text, "\\Use the green pencil");
+ if ( num == EVENT_OBJECT_PEN8 ) strcpy(text, "\\Use the brown pencil");
+ if ( num == EVENT_OBJECT_REC ) strcpy(text, "\\Start recording");
+ if ( num == EVENT_OBJECT_STOP ) strcpy(text, "\\Stop recording");
+ if ( num == EVENT_DT_VISIT0 ||
+ num == EVENT_DT_VISIT1 ||
+ num == EVENT_DT_VISIT2 ||
+ num == EVENT_DT_VISIT3 ||
+ num == EVENT_DT_VISIT4 ) strcpy(text, "Show the place");
+ if ( num == EVENT_DT_END ) strcpy(text, "Continue");
+ if ( num == EVENT_CMD ) strcpy(text, "Command line");
+ if ( num == EVENT_SPEED ) strcpy(text, "Game speed");
+
+ if ( num == EVENT_HYPER_PREV ) strcpy(text, "Back");
+ if ( num == EVENT_HYPER_NEXT ) strcpy(text, "Forward");
+ if ( num == EVENT_HYPER_HOME ) strcpy(text, "Home");
+ if ( num == EVENT_HYPER_COPY ) strcpy(text, "Copy");
+ if ( num == EVENT_HYPER_SIZE1 ) strcpy(text, "Size 1");
+ if ( num == EVENT_HYPER_SIZE2 ) strcpy(text, "Size 2");
+ if ( num == EVENT_HYPER_SIZE3 ) strcpy(text, "Size 3");
+ if ( num == EVENT_HYPER_SIZE4 ) strcpy(text, "Size 4");
+ if ( num == EVENT_HYPER_SIZE5 ) strcpy(text, "Size 5");
+ if ( num == EVENT_SATCOM_HUSTON ) strcpy(text, "Instructions from Houston");
+#if _TEEN
+ if ( num == EVENT_SATCOM_SAT ) strcpy(text, "Dictionnary");
+#else
+ if ( num == EVENT_SATCOM_SAT ) strcpy(text, "Satellite report");
+#endif
+ if ( num == EVENT_SATCOM_LOADING ) strcpy(text, "Programs dispatched by Houston");
+ if ( num == EVENT_SATCOM_OBJECT ) strcpy(text, "List of objects");
+ if ( num == EVENT_SATCOM_PROG ) strcpy(text, "Programming help");
+ if ( num == EVENT_SATCOM_SOLUCE ) strcpy(text, "Solution");
+
+ if ( num == EVENT_STUDIO_OK ) strcpy(text, "OK\\Close program editor and return to game");
+ if ( num == EVENT_STUDIO_CANCEL ) strcpy(text, "Cancel\\Cancel all changes");
+ if ( num == EVENT_STUDIO_NEW ) strcpy(text, "New");
+ if ( num == EVENT_STUDIO_OPEN ) strcpy(text, "Open (Ctrl+o)");
+ if ( num == EVENT_STUDIO_SAVE ) strcpy(text, "Save (Ctrl+s)");
+ if ( num == EVENT_STUDIO_UNDO ) strcpy(text, "Undo (Ctrl+z)");
+ if ( num == EVENT_STUDIO_CUT ) strcpy(text, "Cut (Ctrl+x)");
+ if ( num == EVENT_STUDIO_COPY ) strcpy(text, "Copy (Ctrl+c)");
+ if ( num == EVENT_STUDIO_PASTE ) strcpy(text, "Paste (Ctrl+v)");
+ if ( num == EVENT_STUDIO_SIZE ) strcpy(text, "Font size");
+ if ( num == EVENT_STUDIO_TOOL ) strcpy(text, "Instructions (\\key help;)");
+ if ( num == EVENT_STUDIO_HELP ) strcpy(text, "Programming help (\\key prog;)");
+ if ( num == EVENT_STUDIO_COMPILE ) strcpy(text, "Compile");
+ if ( num == EVENT_STUDIO_RUN ) strcpy(text, "Execute/stop");
+ if ( num == EVENT_STUDIO_REALTIME ) strcpy(text, "Pause/continue");
+ if ( num == EVENT_STUDIO_STEP ) strcpy(text, "One step");
+ }
+
+ if ( type == RES_OBJECT )
+ {
+ if ( num == OBJECT_PORTICO ) strcpy(text, "Gantry crane");
+ if ( num == OBJECT_BASE ) strcpy(text, "Spaceship");
+ if ( num == OBJECT_DERRICK ) strcpy(text, "Derrick");
+ if ( num == OBJECT_FACTORY ) strcpy(text, "Bot factory");
+ if ( num == OBJECT_REPAIR ) strcpy(text, "Repair center");
+ if ( num == OBJECT_DESTROYER ) strcpy(text, "Destroyer");
+ if ( num == OBJECT_STATION ) strcpy(text, "Power station");
+ if ( num == OBJECT_CONVERT ) strcpy(text, "Converts ore to titanium");
+ if ( num == OBJECT_TOWER ) strcpy(text, "Defense tower");
+ if ( num == OBJECT_NEST ) strcpy(text, "Nest");
+ if ( num == OBJECT_RESEARCH ) strcpy(text, "Research center");
+ if ( num == OBJECT_RADAR ) strcpy(text, "Radar station");
+ if ( num == OBJECT_INFO ) strcpy(text, "Information exchange post");
+#if _TEEN
+ if ( num == OBJECT_ENERGY ) strcpy(text, "Power cell factory");
+#else
+ if ( num == OBJECT_ENERGY ) strcpy(text, "Power cell factory");
+#endif
+ if ( num == OBJECT_LABO ) strcpy(text, "Autolab");
+ if ( num == OBJECT_NUCLEAR ) strcpy(text, "Nuclear power station");
+ if ( num == OBJECT_PARA ) strcpy(text, "Lightning conductor");
+ if ( num == OBJECT_SAFE ) strcpy(text, "Vault");
+ if ( num == OBJECT_HUSTON ) strcpy(text, "Houston Mission Control");
+ if ( num == OBJECT_TARGET1 ) strcpy(text, "Target");
+ if ( num == OBJECT_TARGET2 ) strcpy(text, "Target");
+ if ( num == OBJECT_START ) strcpy(text, "Start");
+ if ( num == OBJECT_END ) strcpy(text, "Finish");
+ if ( num == OBJECT_STONE ) strcpy(text, "Titanium ore");
+ if ( num == OBJECT_URANIUM ) strcpy(text, "Uranium ore");
+ if ( num == OBJECT_BULLET ) strcpy(text, "Organic matter");
+ if ( num == OBJECT_METAL ) strcpy(text, "Titanium");
+ if ( num == OBJECT_POWER ) strcpy(text, "Power cell");
+ if ( num == OBJECT_ATOMIC ) strcpy(text, "Nuclear power cell");
+ if ( num == OBJECT_BBOX ) strcpy(text, "Black box");
+ if ( num == OBJECT_KEYa ) strcpy(text, "Key A");
+ if ( num == OBJECT_KEYb ) strcpy(text, "Key B");
+ if ( num == OBJECT_KEYc ) strcpy(text, "Key C");
+ if ( num == OBJECT_KEYd ) strcpy(text, "Key D");
+ if ( num == OBJECT_TNT ) strcpy(text, "Explosive");
+ if ( num == OBJECT_BOMB ) strcpy(text, "Fixed mine");
+ if ( num == OBJECT_BAG ) strcpy(text, "Survival kit");
+ if ( num == OBJECT_WAYPOINT ) strcpy(text, "Checkpoint");
+ if ( num == OBJECT_FLAGb ) strcpy(text, "Blue flag");
+ if ( num == OBJECT_FLAGr ) strcpy(text, "Red flag");
+ if ( num == OBJECT_FLAGg ) strcpy(text, "Green flag");
+ if ( num == OBJECT_FLAGy ) strcpy(text, "Yellow flag");
+ if ( num == OBJECT_FLAGv ) strcpy(text, "Violet flag");
+ if ( num == OBJECT_MARKPOWER ) strcpy(text, "Energy deposit (site for power station)");
+ if ( num == OBJECT_MARKURANIUM ) strcpy(text, "Uranium deposit (site for derrick)");
+ if ( num == OBJECT_MARKKEYa ) strcpy(text, "Found key A (site for derrick)");
+ if ( num == OBJECT_MARKKEYb ) strcpy(text, "Found key B (site for derrick)");
+ if ( num == OBJECT_MARKKEYc ) strcpy(text, "Found key C (site for derrick)");
+ if ( num == OBJECT_MARKKEYd ) strcpy(text, "Found key D (site for derrick)");
+ if ( num == OBJECT_MARKSTONE ) strcpy(text, "Titanium deposit (site for derrick)");
+ if ( num == OBJECT_MOBILEft ) strcpy(text, "Practice bot");
+ if ( num == OBJECT_MOBILEtt ) strcpy(text, "Practice bot");
+ if ( num == OBJECT_MOBILEwt ) strcpy(text, "Practice bot");
+ if ( num == OBJECT_MOBILEit ) strcpy(text, "Practice bot");
+ if ( num == OBJECT_MOBILEfa ) strcpy(text, "Winged grabber");
+ if ( num == OBJECT_MOBILEta ) strcpy(text, "Tracked grabber");
+ if ( num == OBJECT_MOBILEwa ) strcpy(text, "Wheeled grabber");
+ if ( num == OBJECT_MOBILEia ) strcpy(text, "Legged grabber");
+ if ( num == OBJECT_MOBILEfc ) strcpy(text, "Winged shooter");
+ if ( num == OBJECT_MOBILEtc ) strcpy(text, "Tracked shooter");
+ if ( num == OBJECT_MOBILEwc ) strcpy(text, "Wheeled shooter");
+ if ( num == OBJECT_MOBILEic ) strcpy(text, "Legged shooter");
+ if ( num == OBJECT_MOBILEfi ) strcpy(text, "Winged orga shooter");
+ if ( num == OBJECT_MOBILEti ) strcpy(text, "Tracked orga shooter");
+ if ( num == OBJECT_MOBILEwi ) strcpy(text, "Wheeled orga shooter");
+ if ( num == OBJECT_MOBILEii ) strcpy(text, "Legged orga shooter");
+ if ( num == OBJECT_MOBILEfs ) strcpy(text, "Winged sniffer");
+ if ( num == OBJECT_MOBILEts ) strcpy(text, "Tracked sniffer");
+ if ( num == OBJECT_MOBILEws ) strcpy(text, "Wheeled sniffer");
+ if ( num == OBJECT_MOBILEis ) strcpy(text, "Legged sniffer");
+ if ( num == OBJECT_MOBILErt ) strcpy(text, "Thumper");
+ if ( num == OBJECT_MOBILErc ) strcpy(text, "Phazer shooter");
+ if ( num == OBJECT_MOBILErr ) strcpy(text, "Recycler");
+ if ( num == OBJECT_MOBILErs ) strcpy(text, "Shielder");
+ if ( num == OBJECT_MOBILEsa ) strcpy(text, "Subber");
+ if ( num == OBJECT_MOBILEtg ) strcpy(text, "Target bot");
+ if ( num == OBJECT_MOBILEdr ) strcpy(text, "Drawer bot");
+ if ( num == OBJECT_HUMAN ) strcpy(text, g_gamerName);
+ if ( num == OBJECT_TECH ) strcpy(text, "Engineer");
+ if ( num == OBJECT_TOTO ) strcpy(text, "Robbie");
+ if ( num == OBJECT_MOTHER ) strcpy(text, "Alien Queen");
+ if ( num == OBJECT_ANT ) strcpy(text, "Ant");
+ if ( num == OBJECT_SPIDER ) strcpy(text, "Spider");
+ if ( num == OBJECT_BEE ) strcpy(text, "Wasp");
+ if ( num == OBJECT_WORM ) strcpy(text, "Worm");
+ if ( num == OBJECT_EGG ) strcpy(text, "Egg");
+ if ( num == OBJECT_RUINmobilew1 ) strcpy(text, "Wreckage");
+ if ( num == OBJECT_RUINmobilew2 ) strcpy(text, "Wreckage");
+ if ( num == OBJECT_RUINmobilet1 ) strcpy(text, "Wreckage");
+ if ( num == OBJECT_RUINmobilet2 ) strcpy(text, "Wreckage");
+ if ( num == OBJECT_RUINmobiler1 ) strcpy(text, "Wreckage");
+ if ( num == OBJECT_RUINmobiler2 ) strcpy(text, "Wreckage");
+ if ( num == OBJECT_RUINfactory ) strcpy(text, "Ruin");
+ if ( num == OBJECT_RUINdoor ) strcpy(text, "Ruin");
+ if ( num == OBJECT_RUINsupport ) strcpy(text, "Waste");
+ if ( num == OBJECT_RUINradar ) strcpy(text, "Ruin");
+ if ( num == OBJECT_RUINconvert ) strcpy(text, "Ruin");
+ if ( num == OBJECT_RUINbase ) strcpy(text, "Spaceship ruin");
+ if ( num == OBJECT_RUINhead ) strcpy(text, "Spaceship ruin");
+ if ( num == OBJECT_APOLLO1 ||
+ num == OBJECT_APOLLO3 ||
+ num == OBJECT_APOLLO4 ||
+ num == OBJECT_APOLLO5 ) strcpy(text, "Remains of Apollo mission");
+ if ( num == OBJECT_APOLLO2 ) strcpy(text, "Lunar Roving Vehicle");
+ }
+
+ if ( type == RES_ERR )
+ {
+ strcpy(text, "Error");
+ if ( num == ERR_CMD ) strcpy(text, "Unknown command");
+#if _NEWLOOK
+ if ( num == ERR_INSTALL ) strcpy(text, "CeeBot not installed.");
+ if ( num == ERR_NOCD ) strcpy(text, "Please insert the CeeBot CD\nand re-run the game.");
+#else
+ if ( num == ERR_INSTALL ) strcpy(text, "COLOBOT not installed.");
+ if ( num == ERR_NOCD ) strcpy(text, "Please insert the COLOBOT CD\nand re-run the game.");
+#endif
+ if ( num == ERR_MANIP_VEH ) strcpy(text, "Inappropriate bot");
+ if ( num == ERR_MANIP_FLY ) strcpy(text, "Impossible when flying");
+ if ( num == ERR_MANIP_BUSY ) strcpy(text, "Already carrying something");
+ if ( num == ERR_MANIP_NIL ) strcpy(text, "Nothing to grab");
+ if ( num == ERR_MANIP_MOTOR ) strcpy(text, "Impossible when moving");
+ if ( num == ERR_MANIP_OCC ) strcpy(text, "Place occupied");
+ if ( num == ERR_MANIP_FRIEND ) strcpy(text, "No other robot");
+ if ( num == ERR_MANIP_RADIO ) strcpy(text, "You can not carry a radioactive object");
+ if ( num == ERR_MANIP_WATER ) strcpy(text, "You can not carry an object under water");
+ if ( num == ERR_MANIP_EMPTY ) strcpy(text, "Nothing to drop");
+ if ( num == ERR_BUILD_FLY ) strcpy(text, "Impossible when flying");
+ if ( num == ERR_BUILD_WATER ) strcpy(text, "Impossible under water");
+ if ( num == ERR_BUILD_ENERGY ) strcpy(text, "Not enough energy");
+ if ( num == ERR_BUILD_METALAWAY ) strcpy(text, "Titanium too far away");
+ if ( num == ERR_BUILD_METALNEAR ) strcpy(text, "Titanium too close");
+ if ( num == ERR_BUILD_METALINEX ) strcpy(text, "No titanium around");
+ if ( num == ERR_BUILD_FLAT ) strcpy(text, "Ground not flat enough");
+ if ( num == ERR_BUILD_FLATLIT ) strcpy(text, "Flat ground not large enough");
+ if ( num == ERR_BUILD_BUSY ) strcpy(text, "Place occupied");
+ if ( num == ERR_BUILD_BASE ) strcpy(text, "Too close to space ship");
+ if ( num == ERR_BUILD_NARROW ) strcpy(text, "Too close to a building");
+ if ( num == ERR_BUILD_MOTOR ) strcpy(text, "Impossible when moving");
+ if ( num == ERR_SEARCH_FLY ) strcpy(text, "Impossible when flying");
+ if ( num == ERR_SEARCH_VEH ) strcpy(text, "Inappropriate bot");
+ if ( num == ERR_SEARCH_MOTOR ) strcpy(text, "Impossible when moving");
+ if ( num == ERR_TERRA_VEH ) strcpy(text, "Inappropriate bot");
+ if ( num == ERR_TERRA_ENERGY ) strcpy(text, "Not enough energy");
+ if ( num == ERR_TERRA_FLOOR ) strcpy(text, "Ground inappropriate");
+ if ( num == ERR_TERRA_BUILDING ) strcpy(text, "Building too close");
+ if ( num == ERR_TERRA_OBJECT ) strcpy(text, "Object too close");
+ if ( num == ERR_RECOVER_VEH ) strcpy(text, "Inappropriate bot");
+ if ( num == ERR_RECOVER_ENERGY ) strcpy(text, "Not enough energy");
+ if ( num == ERR_RECOVER_NULL ) strcpy(text, "Nothing to recycle");
+ if ( num == ERR_SHIELD_VEH ) strcpy(text, "Inappropriate bot");
+ if ( num == ERR_SHIELD_ENERGY ) strcpy(text, "No more energy");
+ if ( num == ERR_MOVE_IMPOSSIBLE ) strcpy(text, "Error in instruction move");
+ if ( num == ERR_FIND_IMPOSSIBLE ) strcpy(text, "Object not found");
+ if ( num == ERR_GOTO_IMPOSSIBLE ) strcpy(text, "Goto: inaccessible destination");
+ if ( num == ERR_GOTO_ITER ) strcpy(text, "Goto: inaccessible destination");
+ if ( num == ERR_GOTO_BUSY ) strcpy(text, "Goto: destination occupied");
+ if ( num == ERR_FIRE_VEH ) strcpy(text, "Inappropriate bot");
+ if ( num == ERR_FIRE_ENERGY ) strcpy(text, "Not enough energy");
+ if ( num == ERR_FIRE_FLY ) strcpy(text, "Impossible when flying");
+ if ( num == ERR_CONVERT_EMPTY ) strcpy(text, "No titanium ore to convert");
+ if ( num == ERR_DERRICK_NULL ) strcpy(text, "No ore in the subsoil");
+ if ( num == ERR_STATION_NULL ) strcpy(text, "No energy in the subsoil");
+ if ( num == ERR_TOWER_POWER ) strcpy(text, "No power cell");
+ if ( num == ERR_TOWER_ENERGY ) strcpy(text, "No more energy");
+ if ( num == ERR_RESEARCH_POWER ) strcpy(text, "No power cell");
+ if ( num == ERR_RESEARCH_ENERGY ) strcpy(text, "Not enough energy");
+ if ( num == ERR_RESEARCH_TYPE ) strcpy(text, "Inappropriate cell type");
+ if ( num == ERR_RESEARCH_ALREADY) strcpy(text, "Research program already performed");
+ if ( num == ERR_ENERGY_NULL ) strcpy(text, "No energy in the subsoil");
+ if ( num == ERR_ENERGY_LOW ) strcpy(text, "Not enough energy yet");
+ if ( num == ERR_ENERGY_EMPTY ) strcpy(text, "No titanium to transform");
+ if ( num == ERR_ENERGY_BAD ) strcpy(text, "Transforms only titanium");
+ if ( num == ERR_BASE_DLOCK ) strcpy(text, "Doors blocked by a robot or another object ");
+ if ( num == ERR_BASE_DHUMAN ) strcpy(text, "You must get on the spaceship to take off ");
+ if ( num == ERR_LABO_NULL ) strcpy(text, "Nothing to analyze");
+ if ( num == ERR_LABO_BAD ) strcpy(text, "Analyzes only organic matter");
+ if ( num == ERR_LABO_ALREADY ) strcpy(text, "Analysis already performed");
+ if ( num == ERR_NUCLEAR_NULL ) strcpy(text, "No energy in the subsoil");
+ if ( num == ERR_NUCLEAR_LOW ) strcpy(text, "Not yet enough energy");
+ if ( num == ERR_NUCLEAR_EMPTY ) strcpy(text, "No uranium to transform");
+ if ( num == ERR_NUCLEAR_BAD ) strcpy(text, "Transforms only uranium");
+ if ( num == ERR_FACTORY_NULL ) strcpy(text, "No titanium");
+ if ( num == ERR_FACTORY_NEAR ) strcpy(text, "Object too close");
+ if ( num == ERR_RESET_NEAR ) strcpy(text, "Place occupied");
+ if ( num == ERR_INFO_NULL ) strcpy(text, "No information exchange post within range");
+ if ( num == ERR_VEH_VIRUS ) strcpy(text, "Program infected by a virus");
+ if ( num == ERR_BAT_VIRUS ) strcpy(text, "Infected by a virus, temporarily out of order");
+ if ( num == ERR_VEH_POWER ) strcpy(text, "No power cell");
+ if ( num == ERR_VEH_ENERGY ) strcpy(text, "No more energy");
+ if ( num == ERR_FLAG_FLY ) strcpy(text, "Impossible when flying");
+ if ( num == ERR_FLAG_WATER ) strcpy(text, "Impossible when swimming");
+ if ( num == ERR_FLAG_MOTOR ) strcpy(text, "Impossible when moving");
+ if ( num == ERR_FLAG_BUSY ) strcpy(text, "Impossible when carrying an object");
+ if ( num == ERR_FLAG_CREATE ) strcpy(text, "Too many flags of this color (maximum 5)");
+ if ( num == ERR_FLAG_PROXY ) strcpy(text, "Too close to an existing flag");
+ if ( num == ERR_FLAG_DELETE ) strcpy(text, "No flag nearby");
+ if ( num == ERR_MISSION_NOTERM ) strcpy(text, "The mission is not accomplished yet (press \\key help; for more details)");
+ if ( num == ERR_DELETEMOBILE ) strcpy(text, "Bot destroyed");
+ if ( num == ERR_DELETEBUILDING ) strcpy(text, "Building destroyed");
+ if ( num == ERR_TOOMANY ) strcpy(text, "Can not create this, there are too many objects");
+ if ( num == ERR_OBLIGATORYTOKEN ) strcpy(text, "\"%s\" missing in this exercise"); //**
+ if ( num == ERR_PROHIBITEDTOKEN ) strcpy(text, "Do not use in this exercise"); //**
+
+ if ( num == INFO_BUILD ) strcpy(text, "Building completed");
+ if ( num == INFO_CONVERT ) strcpy(text, "Titanium available");
+ if ( num == INFO_RESEARCH ) strcpy(text, "Research program completed");
+ if ( num == INFO_RESEARCHTANK ) strcpy(text, "Plans for tracked robots available ");
+ if ( num == INFO_RESEARCHFLY ) strcpy(text, "You can fly with the keys (\\key gup;) and (\\key gdown;)");
+ if ( num == INFO_RESEARCHTHUMP ) strcpy(text, "Plans for thumper available");
+ if ( num == INFO_RESEARCHCANON ) strcpy(text, "Plans for shooter available");
+ if ( num == INFO_RESEARCHTOWER ) strcpy(text, "Plans for defense tower available");
+ if ( num == INFO_RESEARCHPHAZER ) strcpy(text, "Plans for phazer shooter available");
+ if ( num == INFO_RESEARCHSHIELD ) strcpy(text, "Plans for shielder available");
+ if ( num == INFO_RESEARCHATOMIC ) strcpy(text, "Plans for nuclear power plant available");
+ if ( num == INFO_FACTORY ) strcpy(text, "New bot available");
+ if ( num == INFO_LABO ) strcpy(text, "Analysis performed");
+ if ( num == INFO_ENERGY ) strcpy(text, "Power cell available");
+ if ( num == INFO_NUCLEAR ) strcpy(text, "Nuclear power cell available");
+ if ( num == INFO_FINDING ) strcpy(text, "You found a usable object");
+ if ( num == INFO_MARKPOWER ) strcpy(text, "Found a site for power station");
+ if ( num == INFO_MARKURANIUM ) strcpy(text, "Found a site for a derrick");
+ if ( num == INFO_MARKSTONE ) strcpy(text, "Found a site for a derrick");
+ if ( num == INFO_MARKKEYa ) strcpy(text, "Found a site for a derrick");
+ if ( num == INFO_MARKKEYb ) strcpy(text, "Found a site for a derrick");
+ if ( num == INFO_MARKKEYc ) strcpy(text, "Found a site for a derrick");
+ if ( num == INFO_MARKKEYd ) strcpy(text, "Found a site for a derrick");
+ if ( num == INFO_WIN ) strcpy(text, "<<< Well done, mission accomplished >>>");
+ if ( num == INFO_LOST ) strcpy(text, "<<< Sorry, mission failed >>>");
+ if ( num == INFO_LOSTq ) strcpy(text, "<<< Sorry, mission failed >>>");
+ if ( num == INFO_WRITEOK ) strcpy(text, "Current mission saved");
+ if ( num == INFO_DELETEPATH ) strcpy(text, "Checkpoint crossed");
+ if ( num == INFO_DELETEMOTHER ) strcpy(text, "Alien Queen killed");
+ if ( num == INFO_DELETEANT ) strcpy(text, "Ant fatally wounded");
+ if ( num == INFO_DELETEBEE ) strcpy(text, "Wasp fatally wounded");
+ if ( num == INFO_DELETEWORM ) strcpy(text, "Worm fatally wounded");
+ if ( num == INFO_DELETESPIDER ) strcpy(text, "Spider fatally wounded");
+ if ( num == INFO_BEGINSATCOM ) strcpy(text, "Press \\key help; to read instructions on your SatCom");
+ }
+
+ if ( type == RES_CBOT )
+ {
+ strcpy(text, "Error");
+ if ( num == TX_OPENPAR ) strcpy(text, "Opening bracket missing");
+ if ( num == TX_CLOSEPAR ) strcpy(text, "Closing bracket missing ");
+ if ( num == TX_NOTBOOL ) strcpy(text, "The expression must return a boolean value");
+ if ( num == TX_UNDEFVAR ) strcpy(text, "Variable not declared");
+ if ( num == TX_BADLEFT ) strcpy(text, "Assignment impossible");
+ if ( num == TX_ENDOF ) strcpy(text, "Semicolon terminator missing");
+ if ( num == TX_OUTCASE ) strcpy(text, "Instruction ""case"" outside a block ""switch""");
+ if ( num == TX_NOTERM ) strcpy(text, "Instructions after the final closing brace");
+ if ( num == TX_CLOSEBLK ) strcpy(text, "End of block missing");
+ if ( num == TX_ELSEWITHOUTIF ) strcpy(text, "Instruction ""else"" without corresponding ""if"" ");
+ if ( num == TX_OPENBLK ) strcpy(text, "Opening brace missing ");//début d'un bloc attendu?
+ if ( num == TX_BADTYPE ) strcpy(text, "Wrong type for the assignment");
+ if ( num == TX_REDEFVAR ) strcpy(text, "A variable can not be declared twice");
+ if ( num == TX_BAD2TYPE ) strcpy(text, "The types of the two operands are incompatible ");
+ if ( num == TX_UNDEFCALL ) strcpy(text, "Unknown function");
+ if ( num == TX_MISDOTS ) strcpy(text, "Sign "" : "" missing");
+ if ( num == TX_WHILE ) strcpy(text, "Keyword ""while"" missing");
+ if ( num == TX_BREAK ) strcpy(text, "Instruction ""break"" outside a loop");
+ if ( num == TX_LABEL ) strcpy(text, "A label must be followed by ""for"", ""while"", ""do"" or ""switch""");
+ if ( num == TX_NOLABEL ) strcpy(text, "This label does not exist");// Cette étiquette n'existe pas
+ if ( num == TX_NOCASE ) strcpy(text, "Instruction ""case"" missing");
+ if ( num == TX_BADNUM ) strcpy(text, "Number missing");
+ if ( num == TX_VOID ) strcpy(text, "Void parameter");
+ if ( num == TX_NOTYP ) strcpy(text, "Type declaration missing");
+ if ( num == TX_NOVAR ) strcpy(text, "Variable name missing");
+ if ( num == TX_NOFONC ) strcpy(text, "Function name missing");
+ if ( num == TX_OVERPARAM ) strcpy(text, "Too many parameters");
+ if ( num == TX_REDEF ) strcpy(text, "Function already exists");
+ if ( num == TX_LOWPARAM ) strcpy(text, "Parameters missing ");
+ if ( num == TX_BADPARAM ) strcpy(text, "No function with this name accepts this kind of parameter");
+ if ( num == TX_NUMPARAM ) strcpy(text, "No function with this name accepts this number of parameters");
+ if ( num == TX_NOITEM ) strcpy(text, "This is not a member of this class");
+ if ( num == TX_DOT ) strcpy(text, "This object is not a member of a class");
+ if ( num == TX_NOCONST ) strcpy(text, "Appropriate constructor missing");
+ if ( num == TX_REDEFCLASS ) strcpy(text, "This class already exists");
+ if ( num == TX_CLBRK ) strcpy(text, """ ] "" missing");
+ if ( num == TX_RESERVED ) strcpy(text, "Reserved keyword of CBOT language");
+ if ( num == TX_BADNEW ) strcpy(text, "Bad argument for ""new""");
+ if ( num == TX_OPBRK ) strcpy(text, """ [ "" expected");
+ if ( num == TX_BADSTRING ) strcpy(text, "String missing");
+ if ( num == TX_BADINDEX ) strcpy(text, "Incorrect index type");
+ if ( num == TX_PRIVATE ) strcpy(text, "Private element");
+ if ( num == TX_NOPUBLIC ) strcpy(text, "Public required");
+ if ( num == TX_DIVZERO ) strcpy(text, "Dividing by zero");
+ if ( num == TX_NOTINIT ) strcpy(text, "Variable not initialized");
+ if ( num == TX_BADTHROW ) strcpy(text, "Negative value rejected by ""throw""");//C'est quoi, ça?
+ if ( num == TX_NORETVAL ) strcpy(text, "The function returned no value ");
+ if ( num == TX_NORUN ) strcpy(text, "No function running");
+ if ( num == TX_NOCALL ) strcpy(text, "Calling an unknown function");
+ if ( num == TX_NOCLASS ) strcpy(text, "This class does not exist");
+ if ( num == TX_NULLPT ) strcpy(text, "Unknown Object");
+ if ( num == TX_OPNAN ) strcpy(text, "Operation impossible with value ""nan""");
+ if ( num == TX_OUTARRAY ) strcpy(text, "Access beyond array limit");
+ if ( num == TX_STACKOVER ) strcpy(text, "Stack overflow");
+ if ( num == TX_DELETEDPT ) strcpy(text, "Illegal object");
+ if ( num == TX_FILEOPEN ) strcpy(text, "Can't open file");
+ if ( num == TX_NOTOPEN ) strcpy(text, "File not open");
+ if ( num == TX_ERRREAD ) strcpy(text, "Read error");
+ if ( num == TX_ERRWRITE ) strcpy(text, "Write error");
+ }
+
+ if ( type == RES_KEY )
+ {
+ if ( num == 0 ) strcpy(text, "< none >");
+ if ( num == VK_LEFT ) strcpy(text, "Arrow left");
+ if ( num == VK_RIGHT ) strcpy(text, "Arrow right");
+ if ( num == VK_UP ) strcpy(text, "Arrow up");
+ if ( num == VK_DOWN ) strcpy(text, "Arrow down");
+ if ( num == VK_CANCEL ) strcpy(text, "Control-break");
+ if ( num == VK_BACK ) strcpy(text, "<--");
+ if ( num == VK_TAB ) strcpy(text, "Tab");
+ if ( num == VK_CLEAR ) strcpy(text, "Clear");
+ if ( num == VK_RETURN ) strcpy(text, "Enter");
+ if ( num == VK_SHIFT ) strcpy(text, "Shift");
+ if ( num == VK_CONTROL ) strcpy(text, "Ctrl");
+ if ( num == VK_MENU ) strcpy(text, "Alt");
+ if ( num == VK_PAUSE ) strcpy(text, "Pause");
+ if ( num == VK_CAPITAL ) strcpy(text, "Caps Lock");
+ if ( num == VK_ESCAPE ) strcpy(text, "Esc");
+ if ( num == VK_SPACE ) strcpy(text, "Space");
+ if ( num == VK_PRIOR ) strcpy(text, "Page Up");
+ if ( num == VK_NEXT ) strcpy(text, "Page Down");
+ if ( num == VK_END ) strcpy(text, "End");
+ if ( num == VK_HOME ) strcpy(text, "Home");
+ if ( num == VK_SELECT ) strcpy(text, "Select");
+ if ( num == VK_EXECUTE ) strcpy(text, "Execute");
+ if ( num == VK_SNAPSHOT ) strcpy(text, "Print Scrn");
+ if ( num == VK_INSERT ) strcpy(text, "Insert");
+ if ( num == VK_DELETE ) strcpy(text, "Delete");
+ if ( num == VK_HELP ) strcpy(text, "Help");
+ if ( num == VK_LWIN ) strcpy(text, "Left Windows");
+ if ( num == VK_RWIN ) strcpy(text, "Right Windows");
+ if ( num == VK_APPS ) strcpy(text, "Application key");
+ if ( num == VK_NUMPAD0 ) strcpy(text, "NumPad 0");
+ if ( num == VK_NUMPAD1 ) strcpy(text, "NumPad 1");
+ if ( num == VK_NUMPAD2 ) strcpy(text, "NumPad 2");
+ if ( num == VK_NUMPAD3 ) strcpy(text, "NumPad 3");
+ if ( num == VK_NUMPAD4 ) strcpy(text, "NumPad 4");
+ if ( num == VK_NUMPAD5 ) strcpy(text, "NumPad 5");
+ if ( num == VK_NUMPAD6 ) strcpy(text, "NumPad 6");
+ if ( num == VK_NUMPAD7 ) strcpy(text, "NumPad 7");
+ if ( num == VK_NUMPAD8 ) strcpy(text, "NumPad 8");
+ if ( num == VK_NUMPAD9 ) strcpy(text, "NumPad 9");
+ if ( num == VK_MULTIPLY ) strcpy(text, "NumPad *");
+ if ( num == VK_ADD ) strcpy(text, "NumPad +");
+ if ( num == VK_SEPARATOR ) strcpy(text, "NumPad sep");
+ if ( num == VK_SUBTRACT ) strcpy(text, "NumPad -");
+ if ( num == VK_DECIMAL ) strcpy(text, "NumPad .");
+ if ( num == VK_DIVIDE ) strcpy(text, "NumPad /");
+ if ( num == VK_F1 ) strcpy(text, "F1");
+ if ( num == VK_F2 ) strcpy(text, "F2");
+ if ( num == VK_F3 ) strcpy(text, "F3");
+ if ( num == VK_F4 ) strcpy(text, "F4");
+ if ( num == VK_F5 ) strcpy(text, "F5");
+ if ( num == VK_F6 ) strcpy(text, "F6");
+ if ( num == VK_F7 ) strcpy(text, "F7");
+ if ( num == VK_F8 ) strcpy(text, "F8");
+ if ( num == VK_F9 ) strcpy(text, "F9");
+ if ( num == VK_F10 ) strcpy(text, "F10");
+ if ( num == VK_F11 ) strcpy(text, "F11");
+ if ( num == VK_F12 ) strcpy(text, "F12");
+ if ( num == VK_F13 ) strcpy(text, "F13");
+ if ( num == VK_F14 ) strcpy(text, "F14");
+ if ( num == VK_F15 ) strcpy(text, "F15");
+ if ( num == VK_F16 ) strcpy(text, "F16");
+ if ( num == VK_F17 ) strcpy(text, "F17");
+ if ( num == VK_F18 ) strcpy(text, "F18");
+ if ( num == VK_F19 ) strcpy(text, "F19");
+ if ( num == VK_F20 ) strcpy(text, "F20");
+ if ( num == VK_NUMLOCK ) strcpy(text, "Num Lock");
+ if ( num == VK_SCROLL ) strcpy(text, "Scroll");
+ if ( num == VK_ATTN ) strcpy(text, "Attn");
+ if ( num == VK_CRSEL ) strcpy(text, "CrSel");
+ if ( num == VK_EXSEL ) strcpy(text, "ExSel");
+ if ( num == VK_EREOF ) strcpy(text, "Erase EOF");
+ if ( num == VK_PLAY ) strcpy(text, "Play");
+ if ( num == VK_ZOOM ) strcpy(text, "Zoom");
+ if ( num == VK_PA1 ) strcpy(text, "PA1");
+ if ( num == VK_OEM_CLEAR ) strcpy(text, "Clear");
+ if ( num == VK_BUTTON1 ) strcpy(text, "Button 1");
+ if ( num == VK_BUTTON2 ) strcpy(text, "Button 2");
+ if ( num == VK_BUTTON3 ) strcpy(text, "Button 3");
+ if ( num == VK_BUTTON4 ) strcpy(text, "Button 4");
+ if ( num == VK_BUTTON5 ) strcpy(text, "Button 5");
+ if ( num == VK_BUTTON6 ) strcpy(text, "Button 6");
+ if ( num == VK_BUTTON7 ) strcpy(text, "Button 7");
+ if ( num == VK_BUTTON8 ) strcpy(text, "Button 8");
+ if ( num == VK_BUTTON9 ) strcpy(text, "Button 9");
+ if ( num == VK_BUTTON10 ) strcpy(text, "Button 10");
+ if ( num == VK_BUTTON11 ) strcpy(text, "Button 11");
+ if ( num == VK_BUTTON12 ) strcpy(text, "Button 12");
+ if ( num == VK_BUTTON13 ) strcpy(text, "Button 13");
+ if ( num == VK_BUTTON14 ) strcpy(text, "Button 14");
+ if ( num == VK_BUTTON15 ) strcpy(text, "Button 15");
+ if ( num == VK_BUTTON16 ) strcpy(text, "Button 16");
+ if ( num == VK_BUTTON17 ) strcpy(text, "Button 17");
+ if ( num == VK_BUTTON18 ) strcpy(text, "Button 18");
+ if ( num == VK_BUTTON19 ) strcpy(text, "Button 19");
+ if ( num == VK_BUTTON20 ) strcpy(text, "Button 20");
+ if ( num == VK_BUTTON21 ) strcpy(text, "Button 21");
+ if ( num == VK_BUTTON22 ) strcpy(text, "Button 22");
+ if ( num == VK_BUTTON23 ) strcpy(text, "Button 23");
+ if ( num == VK_BUTTON24 ) strcpy(text, "Button 24");
+ if ( num == VK_BUTTON25 ) strcpy(text, "Button 25");
+ if ( num == VK_BUTTON26 ) strcpy(text, "Button 26");
+ if ( num == VK_BUTTON27 ) strcpy(text, "Button 27");
+ if ( num == VK_BUTTON28 ) strcpy(text, "Button 28");
+ if ( num == VK_BUTTON29 ) strcpy(text, "Button 29");
+ if ( num == VK_BUTTON30 ) strcpy(text, "Button 30");
+ if ( num == VK_BUTTON31 ) strcpy(text, "Button 31");
+ if ( num == VK_BUTTON32 ) strcpy(text, "Button 32");
+ if ( num == VK_WHEELUP ) strcpy(text, "Wheel up");
+ if ( num == VK_WHEELDOWN ) strcpy(text, "Wheel down");
+ }
+#endif
+
+#if _FRENCH
+ if ( type == RES_TEXT )
+ {
+ #if _FULL
+ if ( num == RT_VERSION_ID ) strcpy(text, "1.18 /f");
+ #endif
+ #if _NET
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A 1.18");
+ #endif
+ #if _SCHOOL & _EDU
+ #if _TEEN
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen EDU 1.18");
+ #else
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A EDU 1.18");
+ #endif
+ #endif
+ #if _SCHOOL & _PERSO
+ #if _TEEN
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen PERSO 1.18");
+ #else
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A PERSO 1.18");
+ #endif
+ #endif
+ #if _SCHOOL & _CEEBOTDEMO
+ #if _TEEN
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen DEMO 1.18");
+ #else
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A DEMO 1.18");
+ #endif
+ #endif
+ #if _DEMO
+ if ( num == RT_VERSION_ID ) strcpy(text, "Demo 1.18 /f");
+ #endif
+ if ( num == RT_DISINFO_TITLE ) strcpy(text, "SatCom");
+ if ( num == RT_WINDOW_MAXIMIZED ) strcpy(text, "Taille maximale");
+ if ( num == RT_WINDOW_MINIMIZED ) strcpy(text, "Taille réduite");
+ if ( num == RT_WINDOW_STANDARD ) strcpy(text, "Taille normale");
+ if ( num == RT_WINDOW_CLOSE ) strcpy(text, "Fermer");
+
+ if ( num == RT_STUDIO_TITLE ) strcpy(text, "Edition du programme");
+ if ( num == RT_SCRIPT_NEW ) strcpy(text, "Nouveau");
+ if ( num == RT_NAME_DEFAULT ) strcpy(text, "Joueur");
+ if ( num == RT_IO_NEW ) strcpy(text, "Nouveau ...");
+ if ( num == RT_KEY_OR ) strcpy(text, " ou ");
+
+#if _NEWLOOK
+ if ( num == RT_TITLE_BASE ) strcpy(text, "CeeBot");
+ if ( num == RT_TITLE_INIT ) strcpy(text, "CeeBot");
+#else
+ if ( num == RT_TITLE_BASE ) strcpy(text, "COLOBOT");
+ if ( num == RT_TITLE_INIT ) strcpy(text, "COLOBOT");
+#endif
+ if ( num == RT_TITLE_TRAINER ) strcpy(text, "Programmation");
+ if ( num == RT_TITLE_DEFI ) strcpy(text, "Défis");
+ if ( num == RT_TITLE_MISSION ) strcpy(text, "Missions");
+ if ( num == RT_TITLE_FREE ) strcpy(text, "Jeu libre");
+ if ( num == RT_TITLE_TEEN ) strcpy(text, "Jeu libre");
+ if ( num == RT_TITLE_USER ) strcpy(text, "Niveaux supplémentaires");
+ if ( num == RT_TITLE_PROTO ) strcpy(text, "Prototypes");
+ if ( num == RT_TITLE_SETUP ) strcpy(text, "Options");
+ if ( num == RT_TITLE_NAME ) strcpy(text, "Nom du joueur");
+ if ( num == RT_TITLE_PERSO ) strcpy(text, "Personnalisation de votre apparence");
+ if ( num == RT_TITLE_WRITE ) strcpy(text, "Enregistrement de la mission en cours");
+ if ( num == RT_TITLE_READ ) strcpy(text, "Chargement d'une mission enregistrée");
+
+ if ( num == RT_PLAY_CHAPt ) strcpy(text, " Liste des chapitres :");
+ if ( num == RT_PLAY_CHAPd ) strcpy(text, " Liste des chapitres :");
+ if ( num == RT_PLAY_CHAPm ) strcpy(text, " Liste des planètes :");
+ if ( num == RT_PLAY_CHAPf ) strcpy(text, " Liste des planètes :");
+ if ( num == RT_PLAY_CHAPu ) strcpy(text, " Niveaux supplémentaires :");
+ if ( num == RT_PLAY_CHAPp ) strcpy(text, " Liste des planètes :");
+ if ( num == RT_PLAY_CHAPte ) strcpy(text, " Liste des chapitres :");
+ if ( num == RT_PLAY_LISTt ) strcpy(text, " Liste des exercices du chapitre :");
+ if ( num == RT_PLAY_LISTd ) strcpy(text, " Liste des défis du chapitre :");
+ if ( num == RT_PLAY_LISTm ) strcpy(text, " Liste des missions du chapitre :");
+ if ( num == RT_PLAY_LISTf ) strcpy(text, " Liste des jeux libres du chapitre :");
+ if ( num == RT_PLAY_LISTu ) strcpy(text, " Missions du niveau :");
+ if ( num == RT_PLAY_LISTp ) strcpy(text, " Liste des prototypes du chapitre :");
+ if ( num == RT_PLAY_LISTk ) strcpy(text, " Liste des jeux libres du chapitre :");
+ if ( num == RT_PLAY_RESUME ) strcpy(text, " Résumé :");
+
+ if ( num == RT_SETUP_DEVICE ) strcpy(text, " Pilotes :");
+ if ( num == RT_SETUP_MODE ) strcpy(text, " Résolutions :");
+ if ( num == RT_SETUP_KEY1 ) strcpy(text, "1) Cliquez d'abord sur la touche à redéfinir.");
+ if ( num == RT_SETUP_KEY2 ) strcpy(text, "2) Appuyez ensuite sur la nouvelle touche souhaitée.");
+
+ if ( num == RT_PERSO_FACE ) strcpy(text, "Type de visage :");
+ if ( num == RT_PERSO_GLASSES ) strcpy(text, "Lunettes :");
+ if ( num == RT_PERSO_HAIR ) strcpy(text, "Couleur des cheveux :");
+ if ( num == RT_PERSO_COMBI ) strcpy(text, "Couleur de la combinaison :");
+ if ( num == RT_PERSO_BAND ) strcpy(text, "Couleur des bandes :");
+
+#if _NEWLOOK
+ if ( num == RT_DIALOG_TITLE ) strcpy(text, "CeeBot");
+ if ( num == RT_DIALOG_QUIT ) strcpy(text, "Voulez-vous quitter CeeBot ?");
+ if ( num == RT_DIALOG_YESQUIT ) strcpy(text, "Quitter\\Quitter CeeBot");
+#else
+ if ( num == RT_DIALOG_TITLE ) strcpy(text, "COLOBOT");
+ if ( num == RT_DIALOG_QUIT ) strcpy(text, "Voulez-vous quitter COLOBOT ?");
+ if ( num == RT_DIALOG_YESQUIT ) strcpy(text, "Quitter\\Quitter COLOBOT");
+#endif
+ if ( num == RT_DIALOG_ABORT ) strcpy(text, "Quitter la mission ?");
+ if ( num == RT_DIALOG_YES ) strcpy(text, "Abandonner\\Abandonner la mission en cours");
+ if ( num == RT_DIALOG_NO ) strcpy(text, "Continuer\\Continuer la mission en cours");
+ if ( num == RT_DIALOG_NOQUIT ) strcpy(text, "Continuer\\Continuer de jouer");
+ if ( num == RT_DIALOG_DELOBJ ) strcpy(text, "Voulez-vous vraiment détruire le bâtiment sélectionné ?");
+ if ( num == RT_DIALOG_DELGAME ) strcpy(text, "Voulez-vous détruire les sauvegardes de %s ?");
+ if ( num == RT_DIALOG_YESDEL ) strcpy(text, "Détruire");
+ if ( num == RT_DIALOG_NODEL ) strcpy(text, "Annuler");
+ if ( num == RT_DIALOG_LOADING ) strcpy(text, "CHARGEMENT");
+
+ if ( num == RT_STUDIO_LISTTT ) strcpy(text, "Aide sur le mot-clé (\\key cbot;)");
+ if ( num == RT_STUDIO_COMPOK ) strcpy(text, "Compilation ok (0 erreur)");
+ if ( num == RT_STUDIO_PROGSTOP ) strcpy(text, "Programme terminé");
+
+ if ( num == RT_SATCOM_LIST ) strcpy(text, "\\b;Listes des objets\n");
+ if ( num == RT_SATCOM_BOT ) strcpy(text, "\\b;Listes des robots\n");
+ if ( num == RT_SATCOM_BUILDING ) strcpy(text, "\\b;Listes des bâtiments\n");
+ if ( num == RT_SATCOM_FRET ) strcpy(text, "\\b;Listes des objets transportables\n");
+ if ( num == RT_SATCOM_ALIEN ) strcpy(text, "\\b;Listes des ennemis\n");
+ if ( num == RT_SATCOM_NULL ) strcpy(text, "\\c; (aucun)\\n;\n");
+ if ( num == RT_SATCOM_ERROR1 ) strcpy(text, "\\b;Erreur\n");
+ if ( num == RT_SATCOM_ERROR2 ) strcpy(text, "Liste non disponible sans \\l;radar\\u object\\radar; !\n");
+
+ if ( num == RT_IO_OPEN ) strcpy(text, "Ouvrir");
+ if ( num == RT_IO_SAVE ) strcpy(text, "Enregistrer");
+ if ( num == RT_IO_LIST ) strcpy(text, "Dossier: %s");
+ if ( num == RT_IO_NAME ) strcpy(text, "Nom:");
+ if ( num == RT_IO_DIR ) strcpy(text, "Dans:");
+ if ( num == RT_IO_PRIVATE ) strcpy(text, "Privé\\Dossier privé");
+ if ( num == RT_IO_PUBLIC ) strcpy(text, "Public\\Dossier commun à tous les joueurs");
+
+ if ( num == RT_GENERIC_DEV1 ) strcpy(text, "Développé par :");
+ if ( num == RT_GENERIC_DEV2 ) strcpy(text, "www.epsitec.com");
+#if _SCHOOL
+ if ( num == RT_GENERIC_EDIT1 ) strcpy(text, " ");
+ if ( num == RT_GENERIC_EDIT2 ) strcpy(text, " ");
+#else
+ //?if ( num == RT_GENERIC_EDIT1 ) strcpy(text, "Version française éditée par :");
+ //?if ( num == RT_GENERIC_EDIT2 ) strcpy(text, "www.alsyd.com");
+ if ( num == RT_GENERIC_EDIT1 ) strcpy(text, " ");
+ if ( num == RT_GENERIC_EDIT2 ) strcpy(text, " ");
+#endif
+
+ if ( num == RT_INTERFACE_REC ) strcpy(text, "Enregistreur");
+ }
+
+ if ( type == RES_EVENT )
+ {
+ if ( num == EVENT_BUTTON_OK ) strcpy(text, "D'accord");
+ if ( num == EVENT_BUTTON_CANCEL ) strcpy(text, "Annuler");
+ if ( num == EVENT_BUTTON_NEXT ) strcpy(text, "Suivant");
+ if ( num == EVENT_BUTTON_PREV ) strcpy(text, "Précédent");
+ if ( num == EVENT_BUTTON_QUIT ) strcpy(text, "Menu (\\key quit;)");
+
+ if ( num == EVENT_DIALOG_OK ) strcpy(text, "D'accord");
+ if ( num == EVENT_DIALOG_CANCEL ) strcpy(text, "Annuler");
+
+ if ( num == EVENT_INTERFACE_TRAINER) strcpy(text, "Programmation\\Exercices de programmation");
+ if ( num == EVENT_INTERFACE_DEFI ) strcpy(text, "Défis\\Défis de programmation");
+ if ( num == EVENT_INTERFACE_MISSION) strcpy(text, "Missions\\La grande aventure");
+ if ( num == EVENT_INTERFACE_FREE ) strcpy(text, "Jeu libre\\Jeu libre sans but précis");
+ if ( num == EVENT_INTERFACE_TEEN ) strcpy(text, "Jeu libre\\Jeu libre sans but précis");
+ if ( num == EVENT_INTERFACE_USER ) strcpy(text, "Suppl.\\Niveaux supplémentaires");
+ if ( num == EVENT_INTERFACE_PROTO ) strcpy(text, "Proto\\Prototypes en cours d'élaboration");
+ if ( num == EVENT_INTERFACE_NAME ) strcpy(text, "Autre joueur\\Choix du nom du joueur");
+ if ( num == EVENT_INTERFACE_SETUP ) strcpy(text, "Options\\Réglages");
+ if ( num == EVENT_INTERFACE_AGAIN ) strcpy(text, "Recommencer\\Recommencer la mission au début");
+ if ( num == EVENT_INTERFACE_WRITE ) strcpy(text, "Enregistrer\\Enregistrer la mission en cours");
+ if ( num == EVENT_INTERFACE_READ ) strcpy(text, "Charger\\Charger une mission enregistrée");
+#if _NEWLOOK
+ if ( num == EVENT_INTERFACE_ABORT ) strcpy(text, "\\Retourner dans CeeBot");
+ if ( num == EVENT_INTERFACE_QUIT ) strcpy(text, "Quitter\\Quitter CeeBot");
+#else
+ if ( num == EVENT_INTERFACE_ABORT ) strcpy(text, "\\Retourner dans COLOBOT");
+ if ( num == EVENT_INTERFACE_QUIT ) strcpy(text, "Quitter\\Quitter COLOBOT");
+#endif
+ if ( num == EVENT_INTERFACE_BACK ) strcpy(text, "<< Retour \\Retour au niveau précédent");
+ if ( num == EVENT_INTERFACE_PLAY ) strcpy(text, "Jouer ...\\Démarrer l'action");
+ if ( num == EVENT_INTERFACE_SETUPd ) strcpy(text, "Affichage\\Pilote et résolution d'affichage");
+ if ( num == EVENT_INTERFACE_SETUPg ) strcpy(text, "Graphique\\Options graphiques");
+ if ( num == EVENT_INTERFACE_SETUPp ) strcpy(text, "Jeu\\Options de jouabilité");
+ if ( num == EVENT_INTERFACE_SETUPc ) strcpy(text, "Commandes\\Touches du clavier");
+ if ( num == EVENT_INTERFACE_SETUPs ) strcpy(text, "Son\\Volumes bruitages & musiques");
+ if ( num == EVENT_INTERFACE_DEVICE ) strcpy(text, "Unité");
+ if ( num == EVENT_INTERFACE_RESOL ) strcpy(text, "Résolution");
+ if ( num == EVENT_INTERFACE_FULL ) strcpy(text, "Plein écran\\Plein écran ou fenêtré");
+ if ( num == EVENT_INTERFACE_APPLY ) strcpy(text, "Appliquer les changements\\Active les changements effectués");
+
+ if ( num == EVENT_INTERFACE_TOTO ) strcpy(text, "Robbie\\Votre assistant");
+ if ( num == EVENT_INTERFACE_SHADOW ) strcpy(text, "Ombres\\Ombres projetées au sol");
+ if ( num == EVENT_INTERFACE_GROUND ) strcpy(text, "Marques sur le sol\\Marques dessinées sur le sol");
+ if ( num == EVENT_INTERFACE_DIRTY ) strcpy(text, "Salissures\\Salissures des robots et bâtiments");
+ if ( num == EVENT_INTERFACE_FOG ) strcpy(text, "Brouillard\\Nappes de brouillard");
+ if ( num == EVENT_INTERFACE_LENS ) strcpy(text, "Rayons du soleil\\Rayons selon l'orientation");
+ if ( num == EVENT_INTERFACE_SKY ) strcpy(text, "Ciel\\Ciel et nuages");
+ if ( num == EVENT_INTERFACE_PLANET ) strcpy(text, "Planètes et étoiles\\Motifs mobiles dans le ciel");
+ if ( num == EVENT_INTERFACE_LIGHT ) strcpy(text, "Lumières dynamiques\\Eclairages mobiles");
+ if ( num == EVENT_INTERFACE_PARTI ) strcpy(text, "Quantité de particules\\Explosions, poussières, reflets, etc.");
+ if ( num == EVENT_INTERFACE_CLIP ) strcpy(text, "Profondeur de champ\\Distance de vue maximale");
+ if ( num == EVENT_INTERFACE_DETAIL ) strcpy(text, "Détails des objets\\Qualité des objets en 3D");
+ if ( num == EVENT_INTERFACE_TEXTURE) strcpy(text, "Qualité des textures\\Qualité des images");
+ if ( num == EVENT_INTERFACE_GADGET ) strcpy(text, "Nb d'objets décoratifs\\Qualité d'objets non indispensables");
+ if ( num == EVENT_INTERFACE_RAIN ) strcpy(text, "Particules dans l'interface\\Pluie de particules");
+ if ( num == EVENT_INTERFACE_GLINT ) strcpy(text, "Reflets sur les boutons\\Boutons brillants");
+ if ( num == EVENT_INTERFACE_TOOLTIP) strcpy(text, "Bulles d'aide\\Bulles explicatives");
+ if ( num == EVENT_INTERFACE_MOVIES ) strcpy(text, "Séquences cinématiques\\Films avant ou après une mission");
+ if ( num == EVENT_INTERFACE_NICERST) strcpy(text, "Retour animé\\Retour animé dans les exercices");
+ if ( num == EVENT_INTERFACE_HIMSELF) strcpy(text, "Dégâts à soi-même\\Vos tirs infligent des dommages à vos unités");
+ if ( num == EVENT_INTERFACE_SCROLL ) strcpy(text, "Défilement dans les bords\\Défilement lorsque la souris touches les bords gauche ou droite");
+ if ( num == EVENT_INTERFACE_INVERTX) strcpy(text, "Inversion souris X\\Inversion de la rotation lorsque la souris touche un bord");
+ if ( num == EVENT_INTERFACE_INVERTY) strcpy(text, "Inversion souris Y\\Inversion de la rotation lorsque la souris touche un bord");
+ if ( num == EVENT_INTERFACE_EFFECT ) strcpy(text, "Secousses lors d'explosions\\L'écran vibre lors d'une explosion");
+ if ( num == EVENT_INTERFACE_MOUSE ) strcpy(text, "Souris ombrée\\Jolie souris avec une ombre");
+ if ( num == EVENT_INTERFACE_EDITMODE) strcpy(text, "Indentation automatique\\Pendant l'édition d'un programme");
+ if ( num == EVENT_INTERFACE_EDITVALUE)strcpy(text, "Grande indentation\\Indente avec 2 ou 4 espaces");
+ if ( num == EVENT_INTERFACE_SOLUCE4) strcpy(text, "Accès aux solutions\\Programme \"4: Solution\" dans les exercices");
+
+ if ( num == EVENT_INTERFACE_KDEF ) strcpy(text, "Tout réinitialiser\\Remet toutes les touches standards");
+ if ( num == EVENT_INTERFACE_KLEFT ) strcpy(text, "Tourner à gauche\\Moteur à gauche");
+ if ( num == EVENT_INTERFACE_KRIGHT ) strcpy(text, "Tourner à droite\\Moteur à droite");
+ if ( num == EVENT_INTERFACE_KUP ) strcpy(text, "Avancer\\Moteur en avant");
+ if ( num == EVENT_INTERFACE_KDOWN ) strcpy(text, "Reculer\\Moteur en arrière");
+ if ( num == EVENT_INTERFACE_KGUP ) strcpy(text, "Monter\\Augmenter la puissance du réacteur");
+ if ( num == EVENT_INTERFACE_KGDOWN ) strcpy(text, "Descendre\\Diminuer la puissance du réacteur");
+ if ( num == EVENT_INTERFACE_KCAMERA) strcpy(text, "Changement de caméra\\Autre de point de vue");
+ if ( num == EVENT_INTERFACE_KDESEL ) strcpy(text, "Sélection précédente\\Sélectionne l'objet précédent");
+ if ( num == EVENT_INTERFACE_KACTION) strcpy(text, "Action standard\\Action du bouton avec le cadre rouge");
+ if ( num == EVENT_INTERFACE_KNEAR ) strcpy(text, "Caméra plus proche\\Avance la caméra");
+ if ( num == EVENT_INTERFACE_KAWAY ) strcpy(text, "Caméra plus loin\\Recule la caméra");
+ if ( num == EVENT_INTERFACE_KNEXT ) strcpy(text, "Sélectionner l'objet suivant\\Sélectionner l'objet suivant");
+ if ( num == EVENT_INTERFACE_KHUMAN ) strcpy(text, "Sélectionner le cosmonaute\\Sélectionner le cosmonaute");
+ if ( num == EVENT_INTERFACE_KQUIT ) strcpy(text, "Quitter la mission en cours\\Terminer un exercice ou une mssion");
+ if ( num == EVENT_INTERFACE_KHELP ) strcpy(text, "Instructions mission\\Marche à suivre");
+ if ( num == EVENT_INTERFACE_KPROG ) strcpy(text, "Instructions programmation\\Explication sur la programmation");
+ if ( num == EVENT_INTERFACE_KCBOT ) strcpy(text, "Instructions mot-clé\\Explication sur le mot-clé");
+ if ( num == EVENT_INTERFACE_KVISIT ) strcpy(text, "Montrer le lieu d'un message\\Montrer le lieu du dernier message");
+ if ( num == EVENT_INTERFACE_KSPEED10) strcpy(text, "Vitesse 1.0x\\Vitesse normale");
+ if ( num == EVENT_INTERFACE_KSPEED15) strcpy(text, "Vitesse 1.5x\\Une fois et demi plus rapide");
+ if ( num == EVENT_INTERFACE_KSPEED20) strcpy(text, "Vitesse 2.0x\\Deux fois plus rapide");
+ if ( num == EVENT_INTERFACE_KSPEED30) strcpy(text, "Vitesse 3.0x\\Trois fois plus rapide");
+
+ if ( num == EVENT_INTERFACE_VOLSOUND) strcpy(text, "Bruitages :\\Volume des moteurs, voix, etc.");
+ if ( num == EVENT_INTERFACE_VOLMUSIC) strcpy(text, "Fond sonore :\\Volume des pistes audio du CD");
+ if ( num == EVENT_INTERFACE_SOUND3D) strcpy(text, "Bruitages 3D\\Positionnement sonore dans l'espace");
+
+ if ( num == EVENT_INTERFACE_MIN ) strcpy(text, "Mini\\Qualité minimale (+ rapide)");
+ if ( num == EVENT_INTERFACE_NORM ) strcpy(text, "Normal\\Qualité standard");
+ if ( num == EVENT_INTERFACE_MAX ) strcpy(text, "Maxi\\Haute qualité (+ lent)");
+
+ if ( num == EVENT_INTERFACE_SILENT ) strcpy(text, "Silencieux\\Totalement silencieux");
+ if ( num == EVENT_INTERFACE_NOISY ) strcpy(text, "Normal\\Niveaux normaux");
+
+ if ( num == EVENT_INTERFACE_JOYSTICK) strcpy(text, "Utilise un joystick\\Joystick ou clavier");
+ if ( num == EVENT_INTERFACE_SOLUCE ) strcpy(text, "Accès à la solution\\Donne la solution");
+
+ if ( num == EVENT_INTERFACE_NEDIT ) strcpy(text, "\\Nom du joueur à créer");
+ if ( num == EVENT_INTERFACE_NOK ) strcpy(text, "D'accord\\Choisir le joueur");
+ if ( num == EVENT_INTERFACE_NCANCEL) strcpy(text, "Annuler\\Conserver le joueur actuel");
+ if ( num == EVENT_INTERFACE_NDELETE) strcpy(text, "Supprimer le joueur\\Supprimer le joueur de la liste");
+ if ( num == EVENT_INTERFACE_NLABEL ) strcpy(text, "Nom du joueur");
+
+ if ( num == EVENT_INTERFACE_IOWRITE) strcpy(text, "Enregistrer\\Enregistrer la mission en cours");
+ if ( num == EVENT_INTERFACE_IOREAD ) strcpy(text, "Charger\\Charger la mission sélectionnée");
+ if ( num == EVENT_INTERFACE_IOLIST ) strcpy(text, "Liste des missions enregistrées");
+ if ( num == EVENT_INTERFACE_IOLABEL) strcpy(text, "Nom du fichier :");
+ if ( num == EVENT_INTERFACE_IONAME ) strcpy(text, "Nom de la mission");
+ if ( num == EVENT_INTERFACE_IOIMAGE) strcpy(text, "Vue de la mission");
+ if ( num == EVENT_INTERFACE_IODELETE) strcpy(text, "Supprimer\\Supprime l'enregistrement sélectionné");
+
+ if ( num == EVENT_INTERFACE_PERSO ) strcpy(text, "Aspect\\Choisir votre aspect");
+ if ( num == EVENT_INTERFACE_POK ) strcpy(text, "D'accord");
+ if ( num == EVENT_INTERFACE_PCANCEL) strcpy(text, "Annuler");
+ if ( num == EVENT_INTERFACE_PDEF ) strcpy(text, "Standard\\Remet les couleurs standards");
+ if ( num == EVENT_INTERFACE_PHEAD ) strcpy(text, "Tête\\Visage et cheveux");
+ if ( num == EVENT_INTERFACE_PBODY ) strcpy(text, "Corps\\Combinaison");
+ if ( num == EVENT_INTERFACE_PLROT ) strcpy(text, "\\Rotation à gauche");
+ if ( num == EVENT_INTERFACE_PRROT ) strcpy(text, "\\Rotation à droite");
+ if ( num == EVENT_INTERFACE_PCRa ) strcpy(text, "Rouge");
+ if ( num == EVENT_INTERFACE_PCGa ) strcpy(text, "Vert");
+ if ( num == EVENT_INTERFACE_PCBa ) strcpy(text, "Bleu");
+ if ( num == EVENT_INTERFACE_PCRb ) strcpy(text, "Rouge");
+ if ( num == EVENT_INTERFACE_PCGb ) strcpy(text, "Vert");
+ if ( num == EVENT_INTERFACE_PCBb ) strcpy(text, "Bleu");
+ if ( num == EVENT_INTERFACE_PFACE1 ) strcpy(text, "\\Visage 1");
+ if ( num == EVENT_INTERFACE_PFACE2 ) strcpy(text, "\\Visage 4");
+ if ( num == EVENT_INTERFACE_PFACE3 ) strcpy(text, "\\Visage 3");
+ if ( num == EVENT_INTERFACE_PFACE4 ) strcpy(text, "\\Visage 2");
+ if ( num == EVENT_INTERFACE_PGLASS0) strcpy(text, "\\Pas de lunettes");
+ if ( num == EVENT_INTERFACE_PGLASS1) strcpy(text, "\\Lunettes 1");
+ if ( num == EVENT_INTERFACE_PGLASS2) strcpy(text, "\\Lunettes 2");
+ if ( num == EVENT_INTERFACE_PGLASS3) strcpy(text, "\\Lunettes 3");
+ if ( num == EVENT_INTERFACE_PGLASS4) strcpy(text, "\\Lunettes 4");
+ if ( num == EVENT_INTERFACE_PGLASS5) strcpy(text, "\\Lunettes 5");
+
+ if ( num == EVENT_OBJECT_DESELECT ) strcpy(text, "Sélection précédente (\\key desel;)");
+ if ( num == EVENT_OBJECT_LEFT ) strcpy(text, "Tourne à gauche (\\key left;)");
+ if ( num == EVENT_OBJECT_RIGHT ) strcpy(text, "Tourne à droite (\\key right;)");
+ if ( num == EVENT_OBJECT_UP ) strcpy(text, "Avance (\\key up;)");
+ if ( num == EVENT_OBJECT_DOWN ) strcpy(text, "Recule (\\key down;)");
+ if ( num == EVENT_OBJECT_GASUP ) strcpy(text, "Monte (\\key gup;)");
+ if ( num == EVENT_OBJECT_GASDOWN ) strcpy(text, "Descend (\\key gdown;)");
+ if ( num == EVENT_OBJECT_HTAKE ) strcpy(text, "Prend ou dépose (\\key action;)");
+ if ( num == EVENT_OBJECT_MTAKE ) strcpy(text, "Prend ou dépose (\\key action;)");
+ if ( num == EVENT_OBJECT_MFRONT ) strcpy(text, "..devant");
+ if ( num == EVENT_OBJECT_MBACK ) strcpy(text, "..derrière");
+ if ( num == EVENT_OBJECT_MPOWER ) strcpy(text, "..pile");
+ if ( num == EVENT_OBJECT_BHELP ) strcpy(text, "Instructions sur la mission (\\key help;)");
+ if ( num == EVENT_OBJECT_BTAKEOFF ) strcpy(text, "Décolle pour terminer la mission");
+ if ( num == EVENT_OBJECT_BDERRICK ) strcpy(text, "Construit un derrick");
+ if ( num == EVENT_OBJECT_BSTATION ) strcpy(text, "Construit une station");
+ if ( num == EVENT_OBJECT_BFACTORY ) strcpy(text, "Construit une fabrique de robots");
+ if ( num == EVENT_OBJECT_BREPAIR ) strcpy(text, "Construit un centre de réparation");
+ if ( num == EVENT_OBJECT_BCONVERT ) strcpy(text, "Construit un convertisseur");
+ if ( num == EVENT_OBJECT_BTOWER ) strcpy(text, "Construit une tour");
+ if ( num == EVENT_OBJECT_BRESEARCH ) strcpy(text, "Construit un centre de recherches");
+ if ( num == EVENT_OBJECT_BRADAR ) strcpy(text, "Construit un radar");
+ if ( num == EVENT_OBJECT_BENERGY ) strcpy(text, "Construit une fabrique de piles");
+ if ( num == EVENT_OBJECT_BLABO ) strcpy(text, "Construit un laboratoire");
+ if ( num == EVENT_OBJECT_BNUCLEAR ) strcpy(text, "Construit une centrale nucléaire");
+ if ( num == EVENT_OBJECT_BPARA ) strcpy(text, "Construit un paratonnerre");
+ if ( num == EVENT_OBJECT_BINFO ) strcpy(text, "Construit une borne d'information");
+ if ( num == EVENT_OBJECT_GFLAT ) strcpy(text, "Montre si le sol est plat");
+ if ( num == EVENT_OBJECT_FCREATE ) strcpy(text, "Pose un drapeau de couleur");
+ if ( num == EVENT_OBJECT_FDELETE ) strcpy(text, "Enlève un drapeau");
+ if ( num == EVENT_OBJECT_FCOLORb ) strcpy(text, "\\Drapeaux bleus");
+ if ( num == EVENT_OBJECT_FCOLORr ) strcpy(text, "\\Drapeaux rouges");
+ if ( num == EVENT_OBJECT_FCOLORg ) strcpy(text, "\\Drapeaux verts");
+ if ( num == EVENT_OBJECT_FCOLORy ) strcpy(text, "\\Drapeaux jaunes");
+ if ( num == EVENT_OBJECT_FCOLORv ) strcpy(text, "\\Drapeaux violets");
+ if ( num == EVENT_OBJECT_FACTORYfa ) strcpy(text, "Fabrique un déménageur volant");
+ if ( num == EVENT_OBJECT_FACTORYta ) strcpy(text, "Fabrique un déménageur à chenilles");
+ if ( num == EVENT_OBJECT_FACTORYwa ) strcpy(text, "Fabrique un déménageur à roues");
+ if ( num == EVENT_OBJECT_FACTORYia ) strcpy(text, "Fabrique un déménageur à pattes");
+ if ( num == EVENT_OBJECT_FACTORYfc ) strcpy(text, "Fabrique un shooter volant");
+ if ( num == EVENT_OBJECT_FACTORYtc ) strcpy(text, "Fabrique un shooter à chenilles");
+ if ( num == EVENT_OBJECT_FACTORYwc ) strcpy(text, "Fabrique un shooter à roues");
+ if ( num == EVENT_OBJECT_FACTORYic ) strcpy(text, "Fabrique un shooter à pattes");
+ if ( num == EVENT_OBJECT_FACTORYfi ) strcpy(text, "Fabrique un orgaShooter volant");
+ if ( num == EVENT_OBJECT_FACTORYti ) strcpy(text, "Fabrique un orgaShooter à chenilles");
+ if ( num == EVENT_OBJECT_FACTORYwi ) strcpy(text, "Fabrique un orgaShooter à roues");
+ if ( num == EVENT_OBJECT_FACTORYii ) strcpy(text, "Fabrique un orgaShooter à pattes");
+ if ( num == EVENT_OBJECT_FACTORYfs ) strcpy(text, "Fabrique un renifleur volant");
+ if ( num == EVENT_OBJECT_FACTORYts ) strcpy(text, "Fabrique un renifleur à chenilles");
+ if ( num == EVENT_OBJECT_FACTORYws ) strcpy(text, "Fabrique un renifleur à roues");
+ if ( num == EVENT_OBJECT_FACTORYis ) strcpy(text, "Fabrique un renifleur à pattes");
+ if ( num == EVENT_OBJECT_FACTORYrt ) strcpy(text, "Fabrique un robot secoueur");
+ if ( num == EVENT_OBJECT_FACTORYrc ) strcpy(text, "Fabrique un robot phazer");
+ if ( num == EVENT_OBJECT_FACTORYrr ) strcpy(text, "Fabrique un robot recycleur");
+ if ( num == EVENT_OBJECT_FACTORYrs ) strcpy(text, "Fabrique un robot bouclier");
+ if ( num == EVENT_OBJECT_FACTORYsa ) strcpy(text, "Fabrique un robot sous-marin");
+ if ( num == EVENT_OBJECT_RTANK ) strcpy(text, "Recherche les chenilles");
+ if ( num == EVENT_OBJECT_RFLY ) strcpy(text, "Recherche les robots volants");
+ if ( num == EVENT_OBJECT_RTHUMP ) strcpy(text, "Recherche le secoueur");
+ if ( num == EVENT_OBJECT_RCANON ) strcpy(text, "Recherche le canon shooter");
+ if ( num == EVENT_OBJECT_RTOWER ) strcpy(text, "Recherche la tour de défense");
+ if ( num == EVENT_OBJECT_RPHAZER ) strcpy(text, "Recherche le canon phazer");
+ if ( num == EVENT_OBJECT_RSHIELD ) strcpy(text, "Recherche le bouclier");
+ if ( num == EVENT_OBJECT_RATOMIC ) strcpy(text, "Recherche le nucléaire");
+ if ( num == EVENT_OBJECT_RiPAW ) strcpy(text, "Recherche les pattes");
+ if ( num == EVENT_OBJECT_RiGUN ) strcpy(text, "Recherche le canon orgaShooter");
+ if ( num == EVENT_OBJECT_RESET ) strcpy(text, "Remet au départ");
+ if ( num == EVENT_OBJECT_SEARCH ) strcpy(text, "Cherche (\\key action;)");
+ if ( num == EVENT_OBJECT_TERRAFORM ) strcpy(text, "Secoue (\\key action;)");
+ if ( num == EVENT_OBJECT_FIRE ) strcpy(text, "Tir (\\key action;)");
+ if ( num == EVENT_OBJECT_RECOVER ) strcpy(text, "Recycle (\\key action;)");
+ if ( num == EVENT_OBJECT_BEGSHIELD ) strcpy(text, "Déploie le bouclier (\\key action;)");
+ if ( num == EVENT_OBJECT_ENDSHIELD ) strcpy(text, "Stoppe le bouclier (\\key action;)");
+ if ( num == EVENT_OBJECT_DIMSHIELD ) strcpy(text, "Rayon du bouclier");
+ if ( num == EVENT_OBJECT_PROGRUN ) strcpy(text, "Exécute le programme sélectionné");
+ if ( num == EVENT_OBJECT_PROGEDIT ) strcpy(text, "Edite le programme sélectionné");
+ if ( num == EVENT_OBJECT_INFOOK ) strcpy(text, "\\Mettre le SatCom en veille");
+ if ( num == EVENT_OBJECT_DELETE ) strcpy(text, "Démolit le bâtiment");
+ if ( num == EVENT_OBJECT_GENERGY ) strcpy(text, "Niveau d'énergie");
+ if ( num == EVENT_OBJECT_GSHIELD ) strcpy(text, "Niveau du bouclier");
+ if ( num == EVENT_OBJECT_GRANGE ) strcpy(text, "Température du réacteur");
+ if ( num == EVENT_OBJECT_GPROGRESS ) strcpy(text, "Travail en cours ...");
+ if ( num == EVENT_OBJECT_GRADAR ) strcpy(text, "Nombre d'insectes détectés");
+ if ( num == EVENT_OBJECT_GINFO ) strcpy(text, "Informations diffusées");
+ if ( num == EVENT_OBJECT_COMPASS ) strcpy(text, "Boussole");
+//? if ( num == EVENT_OBJECT_MAP ) strcpy(text, "Mini-carte");
+ if ( num == EVENT_OBJECT_MAPZOOM ) strcpy(text, "Zoom mini-carte");
+ if ( num == EVENT_OBJECT_CAMERA ) strcpy(text, "Caméra (\\key camera;)");
+ if ( num == EVENT_OBJECT_CAMERAleft) strcpy(text, "Caméra à gauche");
+ if ( num == EVENT_OBJECT_CAMERAright) strcpy(text, "Caméra à droite");
+ if ( num == EVENT_OBJECT_CAMERAnear) strcpy(text, "Caméra plus proche");
+ if ( num == EVENT_OBJECT_CAMERAaway) strcpy(text, "Caméra plus loin");
+ if ( num == EVENT_OBJECT_HELP ) strcpy(text, "Instructions sur la sélection");
+ if ( num == EVENT_OBJECT_SOLUCE ) strcpy(text, "Donne la solution");
+ if ( num == EVENT_OBJECT_SHORTCUT00) strcpy(text, "Permute robots <-> bâtiments");
+ if ( num == EVENT_OBJECT_LIMIT ) strcpy(text, "Montre le rayon d'action");
+ if ( num == EVENT_OBJECT_PEN0 ) strcpy(text, "\\Relève le crayon");
+ if ( num == EVENT_OBJECT_PEN1 ) strcpy(text, "\\Abaisse le crayon noir");
+ if ( num == EVENT_OBJECT_PEN2 ) strcpy(text, "\\Abaisse le crayon jaune");
+ if ( num == EVENT_OBJECT_PEN3 ) strcpy(text, "\\Abaisse le crayon orange");
+ if ( num == EVENT_OBJECT_PEN4 ) strcpy(text, "\\Abaisse le crayon rouge");
+ if ( num == EVENT_OBJECT_PEN5 ) strcpy(text, "\\Abaisse le crayon violet");
+ if ( num == EVENT_OBJECT_PEN6 ) strcpy(text, "\\Abaisse le crayon bleu");
+ if ( num == EVENT_OBJECT_PEN7 ) strcpy(text, "\\Abaisse le crayon vert");
+ if ( num == EVENT_OBJECT_PEN8 ) strcpy(text, "\\Abaisse le crayon brun");
+ if ( num == EVENT_OBJECT_REC ) strcpy(text, "\\Démarre l'enregistrement");
+ if ( num == EVENT_OBJECT_STOP ) strcpy(text, "\\Stoppe l'enregistrement");
+ if ( num == EVENT_DT_VISIT0 ||
+ num == EVENT_DT_VISIT1 ||
+ num == EVENT_DT_VISIT2 ||
+ num == EVENT_DT_VISIT3 ||
+ num == EVENT_DT_VISIT4 ) strcpy(text, "Montre l'endroit");
+ if ( num == EVENT_DT_END ) strcpy(text, "Continuer");
+ if ( num == EVENT_CMD ) strcpy(text, "Console de commande");
+ if ( num == EVENT_SPEED ) strcpy(text, "Vitesse du jeu");
+
+ if ( num == EVENT_HYPER_PREV ) strcpy(text, "Page précédente");
+ if ( num == EVENT_HYPER_NEXT ) strcpy(text, "Page suivante");
+ if ( num == EVENT_HYPER_HOME ) strcpy(text, "Page initiale");
+ if ( num == EVENT_HYPER_COPY ) strcpy(text, "Copier");
+ if ( num == EVENT_HYPER_SIZE1 ) strcpy(text, "Taille 1");
+ if ( num == EVENT_HYPER_SIZE2 ) strcpy(text, "Taille 2");
+ if ( num == EVENT_HYPER_SIZE3 ) strcpy(text, "Taille 3");
+ if ( num == EVENT_HYPER_SIZE4 ) strcpy(text, "Taille 4");
+ if ( num == EVENT_HYPER_SIZE5 ) strcpy(text, "Taille 5");
+ if ( num == EVENT_SATCOM_HUSTON ) strcpy(text, "Instructions de Houston");
+#if _TEEN
+ if ( num == EVENT_SATCOM_SAT ) strcpy(text, "Dictionnaire anglais-français");
+#else
+ if ( num == EVENT_SATCOM_SAT ) strcpy(text, "Rapport du satellite");
+#endif
+ if ( num == EVENT_SATCOM_LOADING ) strcpy(text, "Programmes envoyés par Houston");
+ if ( num == EVENT_SATCOM_OBJECT ) strcpy(text, "Liste des objets");
+ if ( num == EVENT_SATCOM_PROG ) strcpy(text, "Aide à la programmation");
+ if ( num == EVENT_SATCOM_SOLUCE ) strcpy(text, "Solution");
+
+ if ( num == EVENT_STUDIO_OK ) strcpy(text, "D'accord\\Compiler le programme");
+ if ( num == EVENT_STUDIO_CANCEL ) strcpy(text, "Annuler\\Annuler toutes les modifications");
+ if ( num == EVENT_STUDIO_NEW ) strcpy(text, "Nouveau");
+ if ( num == EVENT_STUDIO_OPEN ) strcpy(text, "Ouvrir (Ctrl+o)");
+ if ( num == EVENT_STUDIO_SAVE ) strcpy(text, "Enregistrer (Ctrl+s)");
+ if ( num == EVENT_STUDIO_UNDO ) strcpy(text, "Annuler (Ctrl+z)");
+ if ( num == EVENT_STUDIO_CUT ) strcpy(text, "Couper (Ctrl+x)");
+ if ( num == EVENT_STUDIO_COPY ) strcpy(text, "Copier (Ctrl+c)");
+ if ( num == EVENT_STUDIO_PASTE ) strcpy(text, "Coller (Ctrl+v)");
+ if ( num == EVENT_STUDIO_SIZE ) strcpy(text, "Taille des caractères");
+ if ( num == EVENT_STUDIO_TOOL ) strcpy(text, "Instructions (\\key help;)");
+ if ( num == EVENT_STUDIO_HELP ) strcpy(text, "Aide à la programmation (\\key prog;)");
+ if ( num == EVENT_STUDIO_COMPILE ) strcpy(text, "Compiler");
+ if ( num == EVENT_STUDIO_RUN ) strcpy(text, "Démarrer/stopper");
+ if ( num == EVENT_STUDIO_REALTIME ) strcpy(text, "Pause/continuer");
+ if ( num == EVENT_STUDIO_STEP ) strcpy(text, "Un pas");
+ }
+
+ if ( type == RES_OBJECT )
+ {
+ if ( num == OBJECT_PORTICO ) strcpy(text, "Portique");
+ if ( num == OBJECT_BASE ) strcpy(text, "Vaisseau spatial");
+ if ( num == OBJECT_DERRICK ) strcpy(text, "Derrick");
+ if ( num == OBJECT_FACTORY ) strcpy(text, "Fabrique de robots");
+ if ( num == OBJECT_REPAIR ) strcpy(text, "Centre de réparation");
+ if ( num == OBJECT_DESTROYER ) strcpy(text, "Destructeur");
+ if ( num == OBJECT_STATION ) strcpy(text, "Station de recharge");
+ if ( num == OBJECT_CONVERT ) strcpy(text, "Conversion minerai en titanium");
+ if ( num == OBJECT_TOWER ) strcpy(text, "Tour de défense");
+ if ( num == OBJECT_NEST ) strcpy(text, "Nid");
+ if ( num == OBJECT_RESEARCH ) strcpy(text, "Centre de recherches");
+ if ( num == OBJECT_RADAR ) strcpy(text, "Radar");
+ if ( num == OBJECT_INFO ) strcpy(text, "Borne d'information");
+#if _TEEN
+ if ( num == OBJECT_ENERGY ) strcpy(text, "Désintégrateur");
+#else
+ if ( num == OBJECT_ENERGY ) strcpy(text, "Fabrique de piles");
+#endif
+ if ( num == OBJECT_LABO ) strcpy(text, "Laboratoire de matières organiques");
+ if ( num == OBJECT_NUCLEAR ) strcpy(text, "Centrale nucléaire");
+ if ( num == OBJECT_PARA ) strcpy(text, "Paratonnerre");
+ if ( num == OBJECT_SAFE ) strcpy(text, "Coffre-fort");
+ if ( num == OBJECT_HUSTON ) strcpy(text, "Centre de contrôle");
+ if ( num == OBJECT_TARGET1 ) strcpy(text, "Cible");
+ if ( num == OBJECT_TARGET2 ) strcpy(text, "Cible");
+ if ( num == OBJECT_START ) strcpy(text, "Départ");
+ if ( num == OBJECT_END ) strcpy(text, "But");
+ if ( num == OBJECT_STONE ) strcpy(text, "Minerai de titanium");
+ if ( num == OBJECT_URANIUM ) strcpy(text, "Minerai d'uranium");
+ if ( num == OBJECT_BULLET ) strcpy(text, "Matière organique");
+ if ( num == OBJECT_METAL ) strcpy(text, "Titanium");
+ if ( num == OBJECT_POWER ) strcpy(text, "Pile normale");
+ if ( num == OBJECT_ATOMIC ) strcpy(text, "Pile nucléaire");
+ if ( num == OBJECT_BBOX ) strcpy(text, "Boîte noire");
+ if ( num == OBJECT_KEYa ) strcpy(text, "Clé A");
+ if ( num == OBJECT_KEYb ) strcpy(text, "Clé B");
+ if ( num == OBJECT_KEYc ) strcpy(text, "Clé C");
+ if ( num == OBJECT_KEYd ) strcpy(text, "Clé D");
+ if ( num == OBJECT_TNT ) strcpy(text, "Explosif");
+ if ( num == OBJECT_BOMB ) strcpy(text, "Mine fixe");
+ if ( num == OBJECT_BAG ) strcpy(text, "Sac de survie");
+ if ( num == OBJECT_WAYPOINT ) strcpy(text, "Indicateur");
+ if ( num == OBJECT_FLAGb ) strcpy(text, "Drapeau bleu");
+ if ( num == OBJECT_FLAGr ) strcpy(text, "Drapeau rouge");
+ if ( num == OBJECT_FLAGg ) strcpy(text, "Drapeau vert");
+ if ( num == OBJECT_FLAGy ) strcpy(text, "Drapeau jaune");
+ if ( num == OBJECT_FLAGv ) strcpy(text, "Drapeau violet");
+ if ( num == OBJECT_MARKPOWER ) strcpy(text, "Emplacement pour station");
+ if ( num == OBJECT_MARKURANIUM ) strcpy(text, "Emplacement pour derrick (uranium)");
+ if ( num == OBJECT_MARKKEYa ) strcpy(text, "Emplacement pour derrick (clé A)");
+ if ( num == OBJECT_MARKKEYb ) strcpy(text, "Emplacement pour derrick (clé B)");
+ if ( num == OBJECT_MARKKEYc ) strcpy(text, "Emplacement pour derrick (clé C)");
+ if ( num == OBJECT_MARKKEYd ) strcpy(text, "Emplacement pour derrick (clé D)");
+ if ( num == OBJECT_MARKSTONE ) strcpy(text, "Emplacement pour derrick (titanium)");
+ if ( num == OBJECT_MOBILEft ) strcpy(text, "Robot d'entraînement");
+ if ( num == OBJECT_MOBILEtt ) strcpy(text, "Robot d'entraînement");
+ if ( num == OBJECT_MOBILEwt ) strcpy(text, "Robot d'entraînement");
+ if ( num == OBJECT_MOBILEit ) strcpy(text, "Robot d'entraînement");
+ if ( num == OBJECT_MOBILEfa ) strcpy(text, "Robot déménageur");
+ if ( num == OBJECT_MOBILEta ) strcpy(text, "Robot déménageur");
+ if ( num == OBJECT_MOBILEwa ) strcpy(text, "Robot déménageur");
+ if ( num == OBJECT_MOBILEia ) strcpy(text, "Robot déménageur");
+ if ( num == OBJECT_MOBILEfc ) strcpy(text, "Robot shooter");
+ if ( num == OBJECT_MOBILEtc ) strcpy(text, "Robot shooter");
+ if ( num == OBJECT_MOBILEwc ) strcpy(text, "Robot shooter");
+ if ( num == OBJECT_MOBILEic ) strcpy(text, "Robot shooter");
+ if ( num == OBJECT_MOBILEfi ) strcpy(text, "Robot orgaShooter");
+ if ( num == OBJECT_MOBILEti ) strcpy(text, "Robot orgaShooter");
+ if ( num == OBJECT_MOBILEwi ) strcpy(text, "Robot orgaShooter");
+ if ( num == OBJECT_MOBILEii ) strcpy(text, "Robot orgaShooter");
+ if ( num == OBJECT_MOBILEfs ) strcpy(text, "Robot renifleur");
+ if ( num == OBJECT_MOBILEts ) strcpy(text, "Robot renifleur");
+ if ( num == OBJECT_MOBILEws ) strcpy(text, "Robot renifleur");
+ if ( num == OBJECT_MOBILEis ) strcpy(text, "Robot renifleur");
+ if ( num == OBJECT_MOBILErt ) strcpy(text, "Robot secoueur");
+ if ( num == OBJECT_MOBILErc ) strcpy(text, "Robot phazer");
+ if ( num == OBJECT_MOBILErr ) strcpy(text, "Robot recycleur");
+ if ( num == OBJECT_MOBILErs ) strcpy(text, "Robot bouclier");
+ if ( num == OBJECT_MOBILEsa ) strcpy(text, "Robot sous-marin");
+ if ( num == OBJECT_MOBILEtg ) strcpy(text, "Cible d'entraînement");
+ if ( num == OBJECT_MOBILEdr ) strcpy(text, "Robot dessinateur");
+ if ( num == OBJECT_HUMAN ) strcpy(text, g_gamerName);
+ if ( num == OBJECT_TECH ) strcpy(text, "Technicien");
+ if ( num == OBJECT_TOTO ) strcpy(text, "Robbie");
+ if ( num == OBJECT_MOTHER ) strcpy(text, "Pondeuse");
+ if ( num == OBJECT_ANT ) strcpy(text, "Fourmi");
+ if ( num == OBJECT_SPIDER ) strcpy(text, "Araignée");
+ if ( num == OBJECT_BEE ) strcpy(text, "Guêpe");
+ if ( num == OBJECT_WORM ) strcpy(text, "Ver");
+ if ( num == OBJECT_EGG ) strcpy(text, "Oeuf");
+ if ( num == OBJECT_RUINmobilew1 ) strcpy(text, "Epave de robot");
+ if ( num == OBJECT_RUINmobilew2 ) strcpy(text, "Epave de robot");
+ if ( num == OBJECT_RUINmobilet1 ) strcpy(text, "Epave de robot");
+ if ( num == OBJECT_RUINmobilet2 ) strcpy(text, "Epave de robot");
+ if ( num == OBJECT_RUINmobiler1 ) strcpy(text, "Epave de robot");
+ if ( num == OBJECT_RUINmobiler2 ) strcpy(text, "Epave de robot");
+ if ( num == OBJECT_RUINfactory ) strcpy(text, "Bâtiment en ruine");
+ if ( num == OBJECT_RUINdoor ) strcpy(text, "Bâtiment en ruine");
+ if ( num == OBJECT_RUINsupport ) strcpy(text, "Déchet");
+ if ( num == OBJECT_RUINradar ) strcpy(text, "Bâtiment en ruine");
+ if ( num == OBJECT_RUINconvert ) strcpy(text, "Bâtiment en ruine");
+ if ( num == OBJECT_RUINbase ) strcpy(text, "Epave de vaisseau spatial");
+ if ( num == OBJECT_RUINhead ) strcpy(text, "Epave de vaisseau spatial");
+ if ( num == OBJECT_APOLLO1 ||
+ num == OBJECT_APOLLO3 ||
+ num == OBJECT_APOLLO4 ||
+ num == OBJECT_APOLLO5 ) strcpy(text, "Vestige d'une mission Apollo");
+ if ( num == OBJECT_APOLLO2 ) strcpy(text, "Lunar Roving Vehicle");
+ }
+
+ if ( type == RES_ERR )
+ {
+ strcpy(text, "Erreur");
+ if ( num == ERR_CMD ) strcpy(text, "Commande inconnue");
+#if _NEWLOOK
+ if ( num == ERR_INSTALL ) strcpy(text, "CeeBot n'est pas installé.");
+ if ( num == ERR_NOCD ) strcpy(text, "Veuillez mettre le CD de CeeBot\net relancer le jeu.");
+#else
+ if ( num == ERR_INSTALL ) strcpy(text, "COLOBOT n'est pas installé.");
+ if ( num == ERR_NOCD ) strcpy(text, "Veuillez mettre le CD de COLOBOT\net relancer le jeu.");
+#endif
+ if ( num == ERR_MANIP_VEH ) strcpy(text, "Robot inadapté");
+ if ( num == ERR_MANIP_FLY ) strcpy(text, "Impossible en vol");
+ if ( num == ERR_MANIP_BUSY ) strcpy(text, "Porte déjà quelque chose");
+ if ( num == ERR_MANIP_NIL ) strcpy(text, "Rien à prendre");
+ if ( num == ERR_MANIP_MOTOR ) strcpy(text, "Impossible en mouvement");
+ if ( num == ERR_MANIP_OCC ) strcpy(text, "Emplacement occupé");
+ if ( num == ERR_MANIP_FRIEND ) strcpy(text, "Pas d'autre robot");
+ if ( num == ERR_MANIP_RADIO ) strcpy(text, "Vous ne pouvez pas transporter un objet radioactif");
+ if ( num == ERR_MANIP_WATER ) strcpy(text, "Vous ne pouvez pas transporter un objet sous l'eau");
+ if ( num == ERR_MANIP_EMPTY ) strcpy(text, "Rien à déposer");
+ if ( num == ERR_BUILD_FLY ) strcpy(text, "Impossible en vol");
+ if ( num == ERR_BUILD_WATER ) strcpy(text, "Impossible sous l'eau");
+ if ( num == ERR_BUILD_ENERGY ) strcpy(text, "Pas assez d'énergie");
+ if ( num == ERR_BUILD_METALAWAY ) strcpy(text, "Titanium trop loin");
+ if ( num == ERR_BUILD_METALNEAR ) strcpy(text, "Titanium trop proche");
+ if ( num == ERR_BUILD_METALINEX ) strcpy(text, "Titanium inexistant");
+ if ( num == ERR_BUILD_FLAT ) strcpy(text, "Sol pas assez plat");
+ if ( num == ERR_BUILD_FLATLIT ) strcpy(text, "Sol plat pas assez grand");
+ if ( num == ERR_BUILD_BUSY ) strcpy(text, "Emplacement occupé");
+ if ( num == ERR_BUILD_BASE ) strcpy(text, "Trop proche du vaisseau spatial");
+ if ( num == ERR_BUILD_NARROW ) strcpy(text, "Trop proche d'un bâtiment");
+ if ( num == ERR_BUILD_MOTOR ) strcpy(text, "Impossible en mouvement");
+ if ( num == ERR_SEARCH_FLY ) strcpy(text, "Impossible en vol");
+ if ( num == ERR_SEARCH_VEH ) strcpy(text, "Robot inadapté");
+ if ( num == ERR_SEARCH_MOTOR ) strcpy(text, "Impossible en mouvement");
+ if ( num == ERR_TERRA_VEH ) strcpy(text, "Robot inadapté");
+ if ( num == ERR_TERRA_ENERGY ) strcpy(text, "Pas assez d'énergie");
+ if ( num == ERR_TERRA_FLOOR ) strcpy(text, "Terrain inadapté");
+ if ( num == ERR_TERRA_BUILDING ) strcpy(text, "Bâtiment trop proche");
+ if ( num == ERR_TERRA_OBJECT ) strcpy(text, "Objet trop proche");
+ if ( num == ERR_RECOVER_VEH ) strcpy(text, "Robot inadapté");
+ if ( num == ERR_RECOVER_ENERGY ) strcpy(text, "Pas assez d'énergie");
+ if ( num == ERR_RECOVER_NULL ) strcpy(text, "Rien à recycler");
+ if ( num == ERR_SHIELD_VEH ) strcpy(text, "Robot inadapté");
+ if ( num == ERR_SHIELD_ENERGY ) strcpy(text, "Plus d'énergie");
+ if ( num == ERR_MOVE_IMPOSSIBLE ) strcpy(text, "Déplacement impossible");
+ if ( num == ERR_FIND_IMPOSSIBLE ) strcpy(text, "Objet n'existe pas");
+ if ( num == ERR_GOTO_IMPOSSIBLE ) strcpy(text, "Chemin introuvable");
+ if ( num == ERR_GOTO_ITER ) strcpy(text, "Position inaccessible");
+ if ( num == ERR_GOTO_BUSY ) strcpy(text, "Destination occupée");
+ if ( num == ERR_FIRE_VEH ) strcpy(text, "Robot inadapté");
+ if ( num == ERR_FIRE_ENERGY ) strcpy(text, "Pas assez d'énergie");
+ if ( num == ERR_FIRE_FLY ) strcpy(text, "Impossible en vol");
+ if ( num == ERR_CONVERT_EMPTY ) strcpy(text, "Pas de minerai de titanium à convertir");
+ if ( num == ERR_DERRICK_NULL ) strcpy(text, "Pas de minerai en sous-sol");
+ if ( num == ERR_STATION_NULL ) strcpy(text, "Pas d'énergie en sous-sol");
+ if ( num == ERR_TOWER_POWER ) strcpy(text, "Pas de pile");
+ if ( num == ERR_TOWER_ENERGY ) strcpy(text, "Plus d'énergie");
+ if ( num == ERR_RESEARCH_POWER ) strcpy(text, "Pas de pile");
+ if ( num == ERR_RESEARCH_ENERGY ) strcpy(text, "Plus assez d'énergie");
+ if ( num == ERR_RESEARCH_TYPE ) strcpy(text, "Pas le bon type de pile");
+ if ( num == ERR_RESEARCH_ALREADY) strcpy(text, "Recherche déjà effectuée");
+ if ( num == ERR_ENERGY_NULL ) strcpy(text, "Pas d'énergie en sous-sol");
+ if ( num == ERR_ENERGY_LOW ) strcpy(text, "Pas encore assez d'énergie");
+ if ( num == ERR_ENERGY_EMPTY ) strcpy(text, "Pas de titanium à transformer");
+ if ( num == ERR_ENERGY_BAD ) strcpy(text, "Ne transforme que le titanium");
+ if ( num == ERR_BASE_DLOCK ) strcpy(text, "Portes bloquées par un robot ou un objet");
+ if ( num == ERR_BASE_DHUMAN ) strcpy(text, "Vous devez embarquer pour pouvoir décoller");
+ if ( num == ERR_LABO_NULL ) strcpy(text, "Rien à analyser");
+ if ( num == ERR_LABO_BAD ) strcpy(text, "N'analyse que la matière organique");
+ if ( num == ERR_LABO_ALREADY ) strcpy(text, "Analyse déjà effectuée");
+ if ( num == ERR_NUCLEAR_NULL ) strcpy(text, "Pas d'énergie en sous-sol");
+ if ( num == ERR_NUCLEAR_LOW ) strcpy(text, "Pas encore assez d'énergie");
+ if ( num == ERR_NUCLEAR_EMPTY ) strcpy(text, "Pas d'uranium à transformer");
+ if ( num == ERR_NUCLEAR_BAD ) strcpy(text, "Ne transforme que l'uranium");
+ if ( num == ERR_FACTORY_NULL ) strcpy(text, "Pas de titanium");
+ if ( num == ERR_FACTORY_NEAR ) strcpy(text, "Quelque chose est trop proche");
+ if ( num == ERR_RESET_NEAR ) strcpy(text, "Emplacement occupé");
+ if ( num == ERR_INFO_NULL ) strcpy(text, "Pas trouvé de borne d'information");
+ if ( num == ERR_VEH_VIRUS ) strcpy(text, "Un programme est infecté par un virus");
+ if ( num == ERR_BAT_VIRUS ) strcpy(text, "Infecté par un virus, ne fonctionne plus temporairement");
+ if ( num == ERR_VEH_POWER ) strcpy(text, "Pas de pile");
+ if ( num == ERR_VEH_ENERGY ) strcpy(text, "Plus d'énergie");
+ if ( num == ERR_FLAG_FLY ) strcpy(text, "Impossible en vol");
+ if ( num == ERR_FLAG_WATER ) strcpy(text, "Impossible en nageant");
+ if ( num == ERR_FLAG_MOTOR ) strcpy(text, "Impossible en mouvement");
+ if ( num == ERR_FLAG_BUSY ) strcpy(text, "Impossible en portant un objet");
+ if ( num == ERR_FLAG_CREATE ) strcpy(text, "Trop de drapeaux de cette couleur (maximum 5)");
+ if ( num == ERR_FLAG_PROXY ) strcpy(text, "Trop proche d'un drapeau existant");
+ if ( num == ERR_FLAG_DELETE ) strcpy(text, "Aucun drapeau à proximité");
+ if ( num == ERR_MISSION_NOTERM ) strcpy(text, "La misssion n'est pas terminée (appuyez sur \\key help; pour plus de détails)");
+ if ( num == ERR_DELETEMOBILE ) strcpy(text, "Robot détruit");
+ if ( num == ERR_DELETEBUILDING ) strcpy(text, "Bâtiment détruit");
+ if ( num == ERR_TOOMANY ) strcpy(text, "Création impossible, il y a trop d'objets");
+ if ( num == ERR_OBLIGATORYTOKEN ) strcpy(text, "Il manque \"%s\" dans le programme");
+ if ( num == ERR_PROHIBITEDTOKEN ) strcpy(text, "Interdit dans cet exercice");
+
+ if ( num == INFO_BUILD ) strcpy(text, "Bâtiment terminé");
+ if ( num == INFO_CONVERT ) strcpy(text, "Titanium disponible");
+ if ( num == INFO_RESEARCH ) strcpy(text, "Recherche terminée");
+ if ( num == INFO_RESEARCHTANK ) strcpy(text, "Fabrication d'un robot à chenilles possible");
+ if ( num == INFO_RESEARCHFLY ) strcpy(text, "Il est possible de voler avec les touches (\\key gup;) et (\\key gdown;)");
+ if ( num == INFO_RESEARCHTHUMP ) strcpy(text, "Fabrication d'un robot secoueur possible");
+ if ( num == INFO_RESEARCHCANON ) strcpy(text, "Fabrication de robots shooter possible");
+ if ( num == INFO_RESEARCHTOWER ) strcpy(text, "Construction d'une tour de défense possible");
+ if ( num == INFO_RESEARCHPHAZER ) strcpy(text, "Fabrication d'un robot phazer possible");
+ if ( num == INFO_RESEARCHSHIELD ) strcpy(text, "Fabrication d'un robot bouclier possible");
+ if ( num == INFO_RESEARCHATOMIC ) strcpy(text, "Construction d'une centrale nucléaire possible");
+ if ( num == INFO_FACTORY ) strcpy(text, "Nouveau robot disponible");
+ if ( num == INFO_LABO ) strcpy(text, "Analyse terminée");
+ if ( num == INFO_ENERGY ) strcpy(text, "Pile disponible");
+ if ( num == INFO_NUCLEAR ) strcpy(text, "Pile nucléaire disponible");
+ if ( num == INFO_FINDING ) strcpy(text, "Vous avez trouvé un objet utilisable");
+ if ( num == INFO_MARKPOWER ) strcpy(text, "Emplacement pour station trouvé");
+ if ( num == INFO_MARKURANIUM ) strcpy(text, "Emplacement pour derrick trouvé");
+ if ( num == INFO_MARKSTONE ) strcpy(text, "Emplacement pour derrick trouvé");
+ if ( num == INFO_MARKKEYa ) strcpy(text, "Emplacement pour derrick trouvé");
+ if ( num == INFO_MARKKEYb ) strcpy(text, "Emplacement pour derrick trouvé");
+ if ( num == INFO_MARKKEYc ) strcpy(text, "Emplacement pour derrick trouvé");
+ if ( num == INFO_MARKKEYd ) strcpy(text, "Emplacement pour derrick trouvé");
+ if ( num == INFO_WIN ) strcpy(text, "<<< Bravo, mission terminée >>>");
+ if ( num == INFO_LOST ) strcpy(text, "<<< Désolé, mission échouée >>>");
+ if ( num == INFO_LOSTq ) strcpy(text, "<<< Désolé, mission échouée >>>");
+ if ( num == INFO_WRITEOK ) strcpy(text, "Enregistrement effectué");
+ if ( num == INFO_DELETEPATH ) strcpy(text, "Indicateur atteint");
+ if ( num == INFO_DELETEMOTHER ) strcpy(text, "Pondeuse mortellement touchée");
+ if ( num == INFO_DELETEANT ) strcpy(text, "Fourmi mortellement touchée");
+ if ( num == INFO_DELETEBEE ) strcpy(text, "Guêpe mortellement touchée");
+ if ( num == INFO_DELETEWORM ) strcpy(text, "Ver mortellement touché");
+ if ( num == INFO_DELETESPIDER ) strcpy(text, "Araignée mortellement touchée");
+ if ( num == INFO_BEGINSATCOM ) strcpy(text, "Consultez votre SatCom en appuyant sur \\key help;");
+ }
+
+ if ( type == RES_CBOT )
+ {
+ strcpy(text, "Erreur");
+ if ( num == TX_OPENPAR ) strcpy(text, "Il manque une parenthèse ouvrante");
+ if ( num == TX_CLOSEPAR ) strcpy(text, "Il manque une parenthèse fermante");
+ if ( num == TX_NOTBOOL ) strcpy(text, "L'expression doit être un boolean");
+ if ( num == TX_UNDEFVAR ) strcpy(text, "Variable non déclarée");
+ if ( num == TX_BADLEFT ) strcpy(text, "Assignation impossible");
+ if ( num == TX_ENDOF ) strcpy(text, "Terminateur point-virgule non trouvé");
+ if ( num == TX_OUTCASE ) strcpy(text, "Instruction ""case"" hors d'un bloc ""switch""");
+ if ( num == TX_NOTERM ) strcpy(text, "Instructions après la fin");
+ if ( num == TX_CLOSEBLK ) strcpy(text, "Il manque la fin du bloc");
+ if ( num == TX_ELSEWITHOUTIF ) strcpy(text, "Instruction ""else"" sans ""if"" correspondant");
+ if ( num == TX_OPENBLK ) strcpy(text, "Début d'un bloc attendu");
+ if ( num == TX_BADTYPE ) strcpy(text, "Mauvais type de résultat pour l'assignation");
+ if ( num == TX_REDEFVAR ) strcpy(text, "Redéfinition d'une variable");
+ if ( num == TX_BAD2TYPE ) strcpy(text, "Les deux opérandes ne sont pas de types compatibles");
+ if ( num == TX_UNDEFCALL ) strcpy(text, "Routine inconnue");
+ if ( num == TX_MISDOTS ) strcpy(text, "Séparateur "" : "" attendu");
+ if ( num == TX_WHILE ) strcpy(text, "Manque le mot ""while""");
+ if ( num == TX_BREAK ) strcpy(text, "Instruction ""break"" en dehors d'une boucle");
+ if ( num == TX_LABEL ) strcpy(text, "Un label ne peut se placer que devant un ""for"", un ""while"", un ""do"" ou un ""switch""");
+ if ( num == TX_NOLABEL ) strcpy(text, "Cette étiquette n'existe pas");
+ if ( num == TX_NOCASE ) strcpy(text, "Manque une instruction ""case""");
+ if ( num == TX_BADNUM ) strcpy(text, "Un nombre est attendu");
+ if ( num == TX_VOID ) strcpy(text, "Paramètre void");
+ if ( num == TX_NOTYP ) strcpy(text, "Déclaration de type attendu");
+ if ( num == TX_NOVAR ) strcpy(text, "Nom d'une variable attendu");
+ if ( num == TX_NOFONC ) strcpy(text, "Nom de la fonction attendu");
+ if ( num == TX_OVERPARAM ) strcpy(text, "Trop de paramètres");
+ if ( num == TX_REDEF ) strcpy(text, "Cette fonction existe déjà");
+ if ( num == TX_LOWPARAM ) strcpy(text, "Pas assez de paramètres");
+ if ( num == TX_BADPARAM ) strcpy(text, "Aucune fonction de ce nom n'accepte ce(s) type(s) de paramètre(s)");
+ if ( num == TX_NUMPARAM ) strcpy(text, "Aucune fonction de ce nom n'accepte ce nombre de paramètres");
+ if ( num == TX_NOITEM ) strcpy(text, "Cet élément n'existe pas dans cette classe");
+ if ( num == TX_DOT ) strcpy(text, "L'objet n'est pas une instance d'une classe");
+ if ( num == TX_NOCONST ) strcpy(text, "Il n'y a pas de constructeur approprié");
+ if ( num == TX_REDEFCLASS ) strcpy(text, "Cette classe existe déjà");
+ if ( num == TX_CLBRK ) strcpy(text, """ ] "" attendu");
+ if ( num == TX_RESERVED ) strcpy(text, "Ce mot est réservé");
+ if ( num == TX_BADNEW ) strcpy(text, "Mauvais argument pour ""new""");
+ if ( num == TX_OPBRK ) strcpy(text, """ [ "" attendu");
+ if ( num == TX_BADSTRING ) strcpy(text, "Une chaîne de caractère est attendue");
+ if ( num == TX_BADINDEX ) strcpy(text, "Mauvais type d'index");
+ if ( num == TX_PRIVATE ) strcpy(text, "Elément protégé");
+ if ( num == TX_NOPUBLIC ) strcpy(text, "Public requis");
+ if ( num == TX_DIVZERO ) strcpy(text, "Division par zéro");
+ if ( num == TX_NOTINIT ) strcpy(text, "Variable non initialisée");
+ if ( num == TX_BADTHROW ) strcpy(text, "Valeur négative refusée pour ""throw""");
+ if ( num == TX_NORETVAL ) strcpy(text, "La fonction n'a pas retourné de résultat");
+ if ( num == TX_NORUN ) strcpy(text, "Pas de fonction en exécution");
+ if ( num == TX_NOCALL ) strcpy(text, "Appel d'une fonction inexistante");
+ if ( num == TX_NOCLASS ) strcpy(text, "Cette classe n'existe pas");
+ if ( num == TX_NULLPT ) strcpy(text, "Objet n'existe pas");
+ if ( num == TX_OPNAN ) strcpy(text, "Opération sur un ""nan""");
+ if ( num == TX_OUTARRAY ) strcpy(text, "Accès hors du tableau");
+ if ( num == TX_STACKOVER ) strcpy(text, "Débordement de la pile");
+ if ( num == TX_DELETEDPT ) strcpy(text, "Objet inaccessible");
+ if ( num == TX_FILEOPEN ) strcpy(text, "Ouverture du fichier impossible");
+ if ( num == TX_NOTOPEN ) strcpy(text, "Le fichier n'est pas ouvert");
+ if ( num == TX_ERRREAD ) strcpy(text, "Erreur à la lecture");
+ if ( num == TX_ERRWRITE ) strcpy(text, "Erreur à l'écriture");
+ }
+
+ if ( type == RES_KEY )
+ {
+ if ( num == 0 ) strcpy(text, "< aucune >");
+ if ( num == VK_LEFT ) strcpy(text, "Flèche Gauche");
+ if ( num == VK_RIGHT ) strcpy(text, "Flèche Droite");
+ if ( num == VK_UP ) strcpy(text, "Flèche Haut");
+ if ( num == VK_DOWN ) strcpy(text, "Flèche Bas");
+ if ( num == VK_CANCEL ) strcpy(text, "Control-break");
+ if ( num == VK_BACK ) strcpy(text, "<--");
+ if ( num == VK_TAB ) strcpy(text, "Tab");
+ if ( num == VK_CLEAR ) strcpy(text, "Clear");
+ if ( num == VK_RETURN ) strcpy(text, "Entrée");
+ if ( num == VK_SHIFT ) strcpy(text, "Shift");
+ if ( num == VK_CONTROL ) strcpy(text, "Ctrl");
+ if ( num == VK_MENU ) strcpy(text, "Alt");
+ if ( num == VK_PAUSE ) strcpy(text, "Pause");
+ if ( num == VK_CAPITAL ) strcpy(text, "Caps Lock");
+ if ( num == VK_ESCAPE ) strcpy(text, "Esc");
+ if ( num == VK_SPACE ) strcpy(text, "Espace");
+ if ( num == VK_PRIOR ) strcpy(text, "Page Up");
+ if ( num == VK_NEXT ) strcpy(text, "Page Down");
+ if ( num == VK_END ) strcpy(text, "End");
+ if ( num == VK_HOME ) strcpy(text, "Home");
+ if ( num == VK_SELECT ) strcpy(text, "Select");
+ if ( num == VK_EXECUTE ) strcpy(text, "Execute");
+ if ( num == VK_SNAPSHOT ) strcpy(text, "Print Scrn");
+ if ( num == VK_INSERT ) strcpy(text, "Insert");
+ if ( num == VK_DELETE ) strcpy(text, "Delete");
+ if ( num == VK_HELP ) strcpy(text, "Help");
+ if ( num == VK_LWIN ) strcpy(text, "Left Windows");
+ if ( num == VK_RWIN ) strcpy(text, "Right Windows");
+ if ( num == VK_APPS ) strcpy(text, "Application key");
+ if ( num == VK_NUMPAD0 ) strcpy(text, "NumPad 0");
+ if ( num == VK_NUMPAD1 ) strcpy(text, "NumPad 1");
+ if ( num == VK_NUMPAD2 ) strcpy(text, "NumPad 2");
+ if ( num == VK_NUMPAD3 ) strcpy(text, "NumPad 3");
+ if ( num == VK_NUMPAD4 ) strcpy(text, "NumPad 4");
+ if ( num == VK_NUMPAD5 ) strcpy(text, "NumPad 5");
+ if ( num == VK_NUMPAD6 ) strcpy(text, "NumPad 6");
+ if ( num == VK_NUMPAD7 ) strcpy(text, "NumPad 7");
+ if ( num == VK_NUMPAD8 ) strcpy(text, "NumPad 8");
+ if ( num == VK_NUMPAD9 ) strcpy(text, "NumPad 9");
+ if ( num == VK_MULTIPLY ) strcpy(text, "NumPad *");
+ if ( num == VK_ADD ) strcpy(text, "NumPad +");
+ if ( num == VK_SEPARATOR ) strcpy(text, "NumPad sep");
+ if ( num == VK_SUBTRACT ) strcpy(text, "NumPad -");
+ if ( num == VK_DECIMAL ) strcpy(text, "NumPad .");
+ if ( num == VK_DIVIDE ) strcpy(text, "NumPad /");
+ if ( num == VK_F1 ) strcpy(text, "F1");
+ if ( num == VK_F2 ) strcpy(text, "F2");
+ if ( num == VK_F3 ) strcpy(text, "F3");
+ if ( num == VK_F4 ) strcpy(text, "F4");
+ if ( num == VK_F5 ) strcpy(text, "F5");
+ if ( num == VK_F6 ) strcpy(text, "F6");
+ if ( num == VK_F7 ) strcpy(text, "F7");
+ if ( num == VK_F8 ) strcpy(text, "F8");
+ if ( num == VK_F9 ) strcpy(text, "F9");
+ if ( num == VK_F10 ) strcpy(text, "F10");
+ if ( num == VK_F11 ) strcpy(text, "F11");
+ if ( num == VK_F12 ) strcpy(text, "F12");
+ if ( num == VK_F13 ) strcpy(text, "F13");
+ if ( num == VK_F14 ) strcpy(text, "F14");
+ if ( num == VK_F15 ) strcpy(text, "F15");
+ if ( num == VK_F16 ) strcpy(text, "F16");
+ if ( num == VK_F17 ) strcpy(text, "F17");
+ if ( num == VK_F18 ) strcpy(text, "F18");
+ if ( num == VK_F19 ) strcpy(text, "F19");
+ if ( num == VK_F20 ) strcpy(text, "F20");
+ if ( num == VK_NUMLOCK ) strcpy(text, "Num Lock");
+ if ( num == VK_SCROLL ) strcpy(text, "Scroll");
+ if ( num == VK_ATTN ) strcpy(text, "Attn");
+ if ( num == VK_CRSEL ) strcpy(text, "CrSel");
+ if ( num == VK_EXSEL ) strcpy(text, "ExSel");
+ if ( num == VK_EREOF ) strcpy(text, "Erase EOF");
+ if ( num == VK_PLAY ) strcpy(text, "Play");
+ if ( num == VK_ZOOM ) strcpy(text, "Zoom");
+ if ( num == VK_PA1 ) strcpy(text, "PA1");
+ if ( num == VK_OEM_CLEAR ) strcpy(text, "Clear");
+ if ( num == VK_BUTTON1 ) strcpy(text, "Bouton 1");
+ if ( num == VK_BUTTON2 ) strcpy(text, "Bouton 2");
+ if ( num == VK_BUTTON3 ) strcpy(text, "Bouton 3");
+ if ( num == VK_BUTTON4 ) strcpy(text, "Bouton 4");
+ if ( num == VK_BUTTON5 ) strcpy(text, "Bouton 5");
+ if ( num == VK_BUTTON6 ) strcpy(text, "Bouton 6");
+ if ( num == VK_BUTTON7 ) strcpy(text, "Bouton 7");
+ if ( num == VK_BUTTON8 ) strcpy(text, "Bouton 8");
+ if ( num == VK_BUTTON9 ) strcpy(text, "Bouton 9");
+ if ( num == VK_BUTTON10 ) strcpy(text, "Bouton 10");
+ if ( num == VK_BUTTON11 ) strcpy(text, "Bouton 11");
+ if ( num == VK_BUTTON12 ) strcpy(text, "Bouton 12");
+ if ( num == VK_BUTTON13 ) strcpy(text, "Bouton 13");
+ if ( num == VK_BUTTON14 ) strcpy(text, "Bouton 14");
+ if ( num == VK_BUTTON15 ) strcpy(text, "Bouton 15");
+ if ( num == VK_BUTTON16 ) strcpy(text, "Bouton 16");
+ if ( num == VK_BUTTON17 ) strcpy(text, "Bouton 17");
+ if ( num == VK_BUTTON18 ) strcpy(text, "Bouton 18");
+ if ( num == VK_BUTTON19 ) strcpy(text, "Bouton 19");
+ if ( num == VK_BUTTON20 ) strcpy(text, "Bouton 20");
+ if ( num == VK_BUTTON21 ) strcpy(text, "Bouton 21");
+ if ( num == VK_BUTTON22 ) strcpy(text, "Bouton 22");
+ if ( num == VK_BUTTON23 ) strcpy(text, "Bouton 23");
+ if ( num == VK_BUTTON24 ) strcpy(text, "Bouton 24");
+ if ( num == VK_BUTTON25 ) strcpy(text, "Bouton 25");
+ if ( num == VK_BUTTON26 ) strcpy(text, "Bouton 26");
+ if ( num == VK_BUTTON27 ) strcpy(text, "Bouton 27");
+ if ( num == VK_BUTTON28 ) strcpy(text, "Bouton 28");
+ if ( num == VK_BUTTON29 ) strcpy(text, "Bouton 29");
+ if ( num == VK_BUTTON30 ) strcpy(text, "Bouton 30");
+ if ( num == VK_BUTTON31 ) strcpy(text, "Bouton 31");
+ if ( num == VK_BUTTON32 ) strcpy(text, "Bouton 32");
+ if ( num == VK_WHEELUP ) strcpy(text, "Molette haut");
+ if ( num == VK_WHEELDOWN ) strcpy(text, "Molette bas");
+ }
+#endif
+
+#if _GERMAN | _WG
+ if ( type == RES_TEXT )
+ {
+ #if _FULL
+ if ( num == RT_VERSION_ID ) strcpy(text, "1.18 /d");
+ #endif
+ #if _NET
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A 1.18");
+ #endif
+ #if _SCHOOL & _EDU
+ #if _TEEN
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen EDU 1.18");
+ #else
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A EDU 1.18");
+ #endif
+ #endif
+ #if _SCHOOL & _PERSO
+ #if _TEEN
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen PERSO 1.18");
+ #else
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A PERSO 1.18");
+ #endif
+ #endif
+ #if _SCHOOL & _CEEBOTDEMO
+ #if _TEEN
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen DEMO 1.18");
+ #else
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A DEMO 1.18");
+ #endif
+ #endif
+ #if _DEMO
+ if ( num == RT_VERSION_ID ) strcpy(text, "Demo 1.18 /d");
+ #endif
+ if ( num == RT_DISINFO_TITLE ) strcpy(text, "SatCom");
+ if ( num == RT_WINDOW_MAXIMIZED ) strcpy(text, "Großes Fenster");
+ if ( num == RT_WINDOW_MINIMIZED ) strcpy(text, "Reduzieren");
+ if ( num == RT_WINDOW_STANDARD ) strcpy(text, "Normale Größe");
+ if ( num == RT_WINDOW_CLOSE ) strcpy(text, "Schließen");
+
+ if ( num == RT_STUDIO_TITLE ) strcpy(text, "Programmeditor");
+ if ( num == RT_SCRIPT_NEW ) strcpy(text, "Neu");
+ if ( num == RT_NAME_DEFAULT ) strcpy(text, "Spieler");
+ if ( num == RT_IO_NEW ) strcpy(text, "Neu ...");
+ if ( num == RT_KEY_OR ) strcpy(text, " oder ");
+
+#if _NEWLOOK
+ if ( num == RT_TITLE_BASE ) strcpy(text, "CeeBot");
+ if ( num == RT_TITLE_INIT ) strcpy(text, "CeeBot");
+#else
+ if ( num == RT_TITLE_BASE ) strcpy(text, "COLOBOT");
+ if ( num == RT_TITLE_INIT ) strcpy(text, "COLOBOT");
+#endif
+#if _SCHOOL
+ if ( num == RT_TITLE_TRAINER ) strcpy(text, "Übungen");
+#else
+ if ( num == RT_TITLE_TRAINER ) strcpy(text, "Programmieren");
+#endif
+ if ( num == RT_TITLE_DEFI ) strcpy(text, "Challenges");
+ if ( num == RT_TITLE_MISSION ) strcpy(text, "Missionen");
+ if ( num == RT_TITLE_FREE ) strcpy(text, "Freestyle");
+ if ( num == RT_TITLE_TEEN ) strcpy(text, "Freestyle");
+ if ( num == RT_TITLE_USER ) strcpy(text, "Userlevels");
+ if ( num == RT_TITLE_PROTO ) strcpy(text, "Prototypen");
+ if ( num == RT_TITLE_SETUP ) strcpy(text, "Einstellungen");
+ if ( num == RT_TITLE_NAME ) strcpy(text, "Name ");
+ if ( num == RT_TITLE_PERSO ) strcpy(text, "Aussehen einstellen");
+ if ( num == RT_TITLE_WRITE ) strcpy(text, "Aktuelle Mission speichern");
+ if ( num == RT_TITLE_READ ) strcpy(text, "Gespeicherte Mission laden");
+
+ if ( num == RT_PLAY_CHAPt ) strcpy(text, " Liste der Kapitel:");
+ if ( num == RT_PLAY_CHAPd ) strcpy(text, " Liste der Kapitel:");
+ if ( num == RT_PLAY_CHAPm ) strcpy(text, " Liste der Planeten:");
+ if ( num == RT_PLAY_CHAPf ) strcpy(text, " Liste der Planeten:");
+ if ( num == RT_PLAY_CHAPu ) strcpy(text, " Userlevels:");
+ if ( num == RT_PLAY_CHAPp ) strcpy(text, " Liste der Planeten:");
+ if ( num == RT_PLAY_CHAPte ) strcpy(text, " Liste der Kapitel:");
+ if ( num == RT_PLAY_LISTt ) strcpy(text, " Liste der Übungen des Kapitels:");
+ if ( num == RT_PLAY_LISTd ) strcpy(text, " Liste der Challenges des Kapitels:");
+ if ( num == RT_PLAY_LISTm ) strcpy(text, " Liste der Missionen des Planeten:");
+ if ( num == RT_PLAY_LISTf ) strcpy(text, " Liste der freien Levels des Planeten:");
+ if ( num == RT_PLAY_LISTu ) strcpy(text, " Missionen des Userlevels:");
+ if ( num == RT_PLAY_LISTp ) strcpy(text, " Liste der Prototypen des Planeten:");
+ if ( num == RT_PLAY_LISTk ) strcpy(text, " Liste der freien Levels des Kapitel:");
+ if ( num == RT_PLAY_RESUME ) strcpy(text, " Zusammenfassung:");
+
+ if ( num == RT_SETUP_DEVICE ) strcpy(text, " Driver:");
+ if ( num == RT_SETUP_MODE ) strcpy(text, " Auflösung:");
+ if ( num == RT_SETUP_KEY1 ) strcpy(text, "1) Klicken Sie auf die neu zu definierende Taste.");
+ if ( num == RT_SETUP_KEY2 ) strcpy(text, "2) Drücken Sie auf die neue Taste.");
+
+ if ( num == RT_PERSO_FACE ) strcpy(text, "Kopf:");
+ if ( num == RT_PERSO_GLASSES ) strcpy(text, "Brille:");
+ if ( num == RT_PERSO_HAIR ) strcpy(text, "Haarfarbe:");
+ if ( num == RT_PERSO_COMBI ) strcpy(text, "Farbe des Anzugs:");
+ if ( num == RT_PERSO_BAND ) strcpy(text, "Farbe der Streifen:");
+
+#if _NEWLOOK
+ if ( num == RT_DIALOG_TITLE ) strcpy(text, "CeeBot");
+ if ( num == RT_DIALOG_QUIT ) strcpy(text, "Wollen Sie CeeBot schließen ?");
+ if ( num == RT_DIALOG_YESQUIT ) strcpy(text, "Schließen\\CeeBot schließen");
+#else
+ if ( num == RT_DIALOG_TITLE ) strcpy(text, "COLOBOT");
+ if ( num == RT_DIALOG_QUIT ) strcpy(text, "Wollen Sie COLOBOT schließen ?");
+ if ( num == RT_DIALOG_YESQUIT ) strcpy(text, "Schließen\\COLOBOT schließen");
+#endif
+ if ( num == RT_DIALOG_ABORT ) strcpy(text, "Mission abbrechen ?");
+ if ( num == RT_DIALOG_YES ) strcpy(text, "Abbrechen\\Mission abbrechen");
+ if ( num == RT_DIALOG_NO ) strcpy(text, "Weitermachen\\Mission weitermachen");
+ if ( num == RT_DIALOG_NOQUIT ) strcpy(text, "Weitermachen\\Weitermachen");
+ if ( num == RT_DIALOG_DELOBJ ) strcpy(text, "Wollen Sie das angewählte Gebäude wirklich zerstören ?");
+ if ( num == RT_DIALOG_DELGAME ) strcpy(text, "Wollen Sie die gespeicherten Missionen von %s löschen ?");
+ if ( num == RT_DIALOG_YESDEL ) strcpy(text, "Zerstören");
+ if ( num == RT_DIALOG_NODEL ) strcpy(text, "Abbrechen");
+ if ( num == RT_DIALOG_LOADING ) strcpy(text, "Laden");
+
+ if ( num == RT_STUDIO_LISTTT ) strcpy(text, "Hilfe über den Begriff (\\key cbot;)");
+ if ( num == RT_STUDIO_COMPOK ) strcpy(text, "Kompilieren OK (0 Fehler)");
+ if ( num == RT_STUDIO_PROGSTOP ) strcpy(text, "Programm beendet");
+
+ if ( num == RT_SATCOM_LIST ) strcpy(text, "\\b;Liste der Objekte\n");
+ if ( num == RT_SATCOM_BOT ) strcpy(text, "\\b;Liste der Roboter\n");
+ if ( num == RT_SATCOM_BUILDING ) strcpy(text, "\\b;Listes der Gebäude\n");
+ if ( num == RT_SATCOM_FRET ) strcpy(text, "\\b;Listes der tragbaren Gegenstände\n");
+ if ( num == RT_SATCOM_ALIEN ) strcpy(text, "\\b;Listes der Feinde\n");
+ if ( num == RT_SATCOM_NULL ) strcpy(text, "\\c; (keine)\\n;\n");
+ if ( num == RT_SATCOM_ERROR1 ) strcpy(text, "\\b;Fehler\n");
+ if ( num == RT_SATCOM_ERROR2 ) strcpy(text, "Die Liste ist ohne \\l;Radar\\u object\\radar; nicht verfügbar !\n");
+
+ if ( num == RT_IO_OPEN ) strcpy(text, "Öffnen");
+ if ( num == RT_IO_SAVE ) strcpy(text, "Speichern");
+ if ( num == RT_IO_LIST ) strcpy(text, "Ordner: %s");
+ if ( num == RT_IO_NAME ) strcpy(text, "Name:");
+ if ( num == RT_IO_DIR ) strcpy(text, "In:");
+ if ( num == RT_IO_PRIVATE ) strcpy(text, "Privat\\Privater Ordner");
+ if ( num == RT_IO_PUBLIC ) strcpy(text, "Öffentlich\\Gemeinsamer Ordner für alle Spieler");
+
+ if ( num == RT_GENERIC_DEV1 ) strcpy(text, "Entwickelt von:");
+ if ( num == RT_GENERIC_DEV2 ) strcpy(text, "www.epsitec.com");
+#if _WG
+ if ( num == RT_GENERIC_EDIT1 ) strcpy(text, "Herausgegeben von:");
+ if ( num == RT_GENERIC_EDIT2 ) strcpy(text, "www.wg-verlag.ch");
+#else
+ if ( num == RT_GENERIC_EDIT1 ) strcpy(text, " ");
+ if ( num == RT_GENERIC_EDIT2 ) strcpy(text, " ");
+#endif
+
+ if ( num == RT_INTERFACE_REC ) strcpy(text, "Recorder");
+ }
+
+ if ( type == RES_EVENT )
+ {
+ if ( num == EVENT_BUTTON_OK ) strcpy(text, "OK");
+ if ( num == EVENT_BUTTON_CANCEL ) strcpy(text, "Abbrechen");
+ if ( num == EVENT_BUTTON_NEXT ) strcpy(text, "Nächster");
+ if ( num == EVENT_BUTTON_PREV ) strcpy(text, "Vorherg.");
+ if ( num == EVENT_BUTTON_QUIT ) strcpy(text, "Menü (\\key quit;)");
+
+ if ( num == EVENT_DIALOG_OK ) strcpy(text, "OK");
+ if ( num == EVENT_DIALOG_CANCEL ) strcpy(text, "Abbrechen");
+
+#if _SCHOOL
+ if ( num == EVENT_INTERFACE_TRAINER) strcpy(text, "Übungen\\Programmierübungen");
+#else
+ if ( num == EVENT_INTERFACE_TRAINER) strcpy(text, "Programmieren\\Programmierübungen");
+#endif
+ if ( num == EVENT_INTERFACE_DEFI ) strcpy(text, "Challenges\\Herausforderungen");
+ if ( num == EVENT_INTERFACE_MISSION) strcpy(text, "Missionen\\Aufbruch ins Weltall");
+ if ( num == EVENT_INTERFACE_FREE ) strcpy(text, "Freestyle\\Freies Spielen ohne vorgegebenes Ziel");
+ if ( num == EVENT_INTERFACE_TEEN ) strcpy(text, "Freestyle\\Freies Spielen ohne vorgegebenes Ziel");
+ if ( num == EVENT_INTERFACE_USER ) strcpy(text, "User\\Userlevels");
+ if ( num == EVENT_INTERFACE_PROTO ) strcpy(text, "Proto\\In Entwicklung befindliche Prototypen");
+ if ( num == EVENT_INTERFACE_NAME ) strcpy(text, "Anderer Spieler\\Spielername ändern");
+ if ( num == EVENT_INTERFACE_SETUP ) strcpy(text, "Einstellungen\\Einstellungen");
+ if ( num == EVENT_INTERFACE_AGAIN ) strcpy(text, "Neu anfangen\\Die Mission von vorne anfangen");
+ if ( num == EVENT_INTERFACE_WRITE ) strcpy(text, "Speichern\\Aktuelle Mission speichern");
+ if ( num == EVENT_INTERFACE_READ ) strcpy(text, "Laden\\Eine gespeicherte Mission öffnen");
+#if _NEWLOOK
+ if ( num == EVENT_INTERFACE_ABORT ) strcpy(text, "\\Zurück zu CeeBot");
+ if ( num == EVENT_INTERFACE_QUIT ) strcpy(text, "Schließen\\CeeBot schließen");
+#else
+ if ( num == EVENT_INTERFACE_ABORT ) strcpy(text, "\\Zurück zu COLOBOT");
+ if ( num == EVENT_INTERFACE_QUIT ) strcpy(text, "Schließen\\COLOBOT schließen");
+#endif
+ if ( num == EVENT_INTERFACE_BACK ) strcpy(text, "<< Zurück \\Zurück zum Hauptmenü");
+ if ( num == EVENT_INTERFACE_PLAY ) strcpy(text, "Spielen ...\\Los geht's");
+ if ( num == EVENT_INTERFACE_SETUPd ) strcpy(text, "Bildschirm\\Driver und Bildschirmauflösung");
+ if ( num == EVENT_INTERFACE_SETUPg ) strcpy(text, "Grafik\\Grafische Einstellungen");
+ if ( num == EVENT_INTERFACE_SETUPp ) strcpy(text, "Spiel\\Gameplay Einstellungen");
+ if ( num == EVENT_INTERFACE_SETUPc ) strcpy(text, "Steuerung\\Auswahl der Tasten");
+ if ( num == EVENT_INTERFACE_SETUPs ) strcpy(text, "Geräusche\\Lautstärke Geräusche und Musik");
+ if ( num == EVENT_INTERFACE_DEVICE ) strcpy(text, "Einheit");
+ if ( num == EVENT_INTERFACE_RESOL ) strcpy(text, "Auflösung");
+ if ( num == EVENT_INTERFACE_FULL ) strcpy(text, "Vollbildschirm\\Vollbildschirm oder Fenster");
+ if ( num == EVENT_INTERFACE_APPLY ) strcpy(text, "Änderungen ausführen\\Getätigte Einstellungen ausführen");
+
+ if ( num == EVENT_INTERFACE_TOTO ) strcpy(text, "Robby\\Ihr Assistent");
+ if ( num == EVENT_INTERFACE_SHADOW ) strcpy(text, "Schatten\\Schlagschatten auf dem Boden");
+ if ( num == EVENT_INTERFACE_GROUND ) strcpy(text, "Markierungen\\Markierungen auf dem Boden");
+ if ( num == EVENT_INTERFACE_DIRTY ) strcpy(text, "Schmutz\\Schmutz auf Robotern und Bauten");
+ if ( num == EVENT_INTERFACE_FOG ) strcpy(text, "Nebel\\Nebelschwaden");
+ if ( num == EVENT_INTERFACE_LENS ) strcpy(text, "Sonnenstrahlen\\Sonnenstrahlen");
+ if ( num == EVENT_INTERFACE_SKY ) strcpy(text, "Himmel\\Himmel und Wolken");
+ if ( num == EVENT_INTERFACE_PLANET ) strcpy(text, "Planeten und Sterne\\Kreisende Planeten und Sterne");
+ if ( num == EVENT_INTERFACE_LIGHT ) strcpy(text, "Dynamische Beleuchtung\\Dynamische Beleuchtung");
+ if ( num == EVENT_INTERFACE_PARTI ) strcpy(text, "Anzahl Partikel\\Explosionen, Staub, usw.");
+ if ( num == EVENT_INTERFACE_CLIP ) strcpy(text, "Sichtweite\\Maximale Sichtweite");
+ if ( num == EVENT_INTERFACE_DETAIL ) strcpy(text, "Details\\Detailliertheit der Objekte in 3D");
+ if ( num == EVENT_INTERFACE_TEXTURE) strcpy(text, "Qualität der Texturen\\Qualität der Anzeige");
+ if ( num == EVENT_INTERFACE_GADGET ) strcpy(text, "Anzahl Ziergegenstände\\Anzahl Gegenstände ohne Funktion");
+ if ( num == EVENT_INTERFACE_RAIN ) strcpy(text, "Partikel in den Menüs\\Funken und Sterne in den Menüs");
+ if ( num == EVENT_INTERFACE_GLINT ) strcpy(text, "Glänzende Tasten\\Glänzende Tasten in den Menüs");
+ if ( num == EVENT_INTERFACE_TOOLTIP) strcpy(text, "Hilfsblasen\\Hilfsblasen");
+ if ( num == EVENT_INTERFACE_MOVIES ) strcpy(text, "Filme\\Filme vor und nach den Missionen");
+ if ( num == EVENT_INTERFACE_NICERST) strcpy(text, "Zurücksetzen \\Kleine Show beim Zurücksetzen in den Übungen");
+ if ( num == EVENT_INTERFACE_HIMSELF) strcpy(text, "Eigenbeschuss\\Ihre Einheiten werden von Ihren Waffen beschädigt.");
+ if ( num == EVENT_INTERFACE_SCROLL ) strcpy(text, "Kameradrehung mit der Maus\\Die Kamera dreht wenn die Maus den Rand erreicht");
+ if ( num == EVENT_INTERFACE_INVERTX) strcpy(text, "Umkehr X\\Umkehr der Kameradrehung X-Achse");
+ if ( num == EVENT_INTERFACE_INVERTY) strcpy(text, "Umkehr Y\\Umkehr der Kameradrehung Y-Achse");
+ if ( num == EVENT_INTERFACE_EFFECT ) strcpy(text, "Beben bei Explosionen\\Die Kamera bebt bei Explosionen");
+ if ( num == EVENT_INTERFACE_MOUSE ) strcpy(text, "Schatten unter der Maus\\Ein Schatten erscheint unter der Maus");
+ if ( num == EVENT_INTERFACE_EDITMODE) strcpy(text, "Automatisches Einrücken\\Beim Bearbeiten der Programme");
+ if ( num == EVENT_INTERFACE_EDITVALUE)strcpy(text, "Einrücken mit 4 Leerstellen\\Einrücken mit 2 oder 4 Leerstellen");
+ if ( num == EVENT_INTERFACE_SOLUCE4) strcpy(text, "Lösung zugänglich\\Die Lösung ist im Programmslot \"4: Lösung\" zugänglich");
+
+ if ( num == EVENT_INTERFACE_KDEF ) strcpy(text, "Alles zurücksetzen\\Standarddefinition aller Tasten");
+ if ( num == EVENT_INTERFACE_KLEFT ) strcpy(text, "Drehung nach links\\Steuer links");
+ if ( num == EVENT_INTERFACE_KRIGHT ) strcpy(text, "Drehung nach rechts\\Steuer rechts");
+ if ( num == EVENT_INTERFACE_KUP ) strcpy(text, "Vorwärts\\Bewegung nach vorne");
+ if ( num == EVENT_INTERFACE_KDOWN ) strcpy(text, "Rückwärts\\Bewegung nach hinten");
+ if ( num == EVENT_INTERFACE_KGUP ) strcpy(text, "Steigen\\Leistung des Triebwerks steigern");
+ if ( num == EVENT_INTERFACE_KGDOWN ) strcpy(text, "Sinken\\Leistung des Triebwerks drosseln");
+ if ( num == EVENT_INTERFACE_KCAMERA) strcpy(text, "Andere Kamera\\Sichtpunkt einstellen");
+ if ( num == EVENT_INTERFACE_KDESEL ) strcpy(text, "Vorherg. Auswahl\\Das vorhergehende Objekt auswählen");
+ if ( num == EVENT_INTERFACE_KACTION) strcpy(text, "Standardhandlung\\Führt die Standardhandlung des Roboters aus.");
+ if ( num == EVENT_INTERFACE_KNEAR ) strcpy(text, "Kamera näher\\Bewegung der Kamera vorwärts");
+ if ( num == EVENT_INTERFACE_KAWAY ) strcpy(text, "Kamera weiter\\Bewegung der Kamera rückwärts");
+ if ( num == EVENT_INTERFACE_KNEXT ) strcpy(text, "Nächstes auswählen\\Nächstes Objekt auswählen");
+ if ( num == EVENT_INTERFACE_KHUMAN ) strcpy(text, "Astronauten auswählen\\Astronauten auswählen");
+ if ( num == EVENT_INTERFACE_KQUIT ) strcpy(text, "Mission verlassen\\Eine Mission oder Übung verlassen");
+ if ( num == EVENT_INTERFACE_KHELP ) strcpy(text, "Anweisungen\\Anweisungen für die Mission oder Übung");
+ if ( num == EVENT_INTERFACE_KPROG ) strcpy(text, "Hilfe CBOT-Sprache\\Hilfe über die Programmiersprache CBOT");
+ if ( num == EVENT_INTERFACE_KCBOT ) strcpy(text, "Hilfe über Begriff\\Hilfe über einen Begriff");
+ if ( num == EVENT_INTERFACE_KVISIT ) strcpy(text, "Ort der Meldung\\Zeigt den Ort, von dem die letzte Meldung stammt");
+ if ( num == EVENT_INTERFACE_KSPEED10) strcpy(text, "Geschwindigkeit 1.0x\\Normale Spielgeschwindigkeit");
+ if ( num == EVENT_INTERFACE_KSPEED15) strcpy(text, "Geschwindigkeit 1.5x\\Spielgeschwindigkeit anderthalb Mal schneller");
+ if ( num == EVENT_INTERFACE_KSPEED20) strcpy(text, "Geschwindigkeit 2.0x\\Spielgeschwindigkeit doppelt so schnell");
+ if ( num == EVENT_INTERFACE_KSPEED30) strcpy(text, "Geschwindigkeit 3.0x\\Spielgeschwindigkeit drei Mal schneller");
+
+ if ( num == EVENT_INTERFACE_VOLSOUND) strcpy(text, "Geräusche:\\Lautstärke Motoren, Stimmen, usw.");
+ if ( num == EVENT_INTERFACE_VOLMUSIC) strcpy(text, "Geräuschkulisse:\\Lautstärke der Soundtracks der CD");
+ if ( num == EVENT_INTERFACE_SOUND3D) strcpy(text, "3D-Geräusche\\Orten der Geräusche im Raum");
+
+ if ( num == EVENT_INTERFACE_MIN ) strcpy(text, "Min.\\Minimale Qualität (großes Framerate)");
+ if ( num == EVENT_INTERFACE_NORM ) strcpy(text, "Normal\\Standardqualität");
+ if ( num == EVENT_INTERFACE_MAX ) strcpy(text, "Max.\\Beste Qualität (niedriges Framerate)");
+
+ if ( num == EVENT_INTERFACE_SILENT ) strcpy(text, "Kein Ton\\Keine Geräusche und Geräuschkulisse");
+ if ( num == EVENT_INTERFACE_NOISY ) strcpy(text, "Normal\\Normale Lautstärke");
+
+ if ( num == EVENT_INTERFACE_JOYSTICK) strcpy(text, "Joystick\\Joystick oder Tastatur");
+ if ( num == EVENT_INTERFACE_SOLUCE ) strcpy(text, "Zeigt die Lösung\\Zeigt nach 3mal Scheitern die Lösung");
+
+ if ( num == EVENT_INTERFACE_NEDIT ) strcpy(text, "\\Name des Spielers");
+ if ( num == EVENT_INTERFACE_NOK ) strcpy(text, "OK\\Spieler auswählen");
+ if ( num == EVENT_INTERFACE_NCANCEL) strcpy(text, "Abbrechen\\Behält den bisherigen Spieler bei");
+ if ( num == EVENT_INTERFACE_NDELETE) strcpy(text, "Spieler löschen\\Löscht den Spieler aus der Liste");
+ if ( num == EVENT_INTERFACE_NLABEL ) strcpy(text, "Name ");
+
+ if ( num == EVENT_INTERFACE_IOWRITE) strcpy(text, "Speichern\\Speichert die Mission");
+ if ( num == EVENT_INTERFACE_IOREAD ) strcpy(text, "Laden\\Öffnet eine gespeicherte Mission");
+ if ( num == EVENT_INTERFACE_IOLIST ) strcpy(text, "Liste der gespeicherten Missionen");
+ if ( num == EVENT_INTERFACE_IOLABEL) strcpy(text, "Dateiname:");
+ if ( num == EVENT_INTERFACE_IONAME ) strcpy(text, "Name der Mission");
+ if ( num == EVENT_INTERFACE_IOIMAGE) strcpy(text, "Ansicht der Mission");
+ if ( num == EVENT_INTERFACE_IODELETE) strcpy(text, "Löschen\\Löscht die gespeicherte Mission");
+
+ if ( num == EVENT_INTERFACE_PERSO ) strcpy(text, "Aussehen\\Erscheinungsbild des Astronauten einstellen");
+ if ( num == EVENT_INTERFACE_POK ) strcpy(text, "OK");
+ if ( num == EVENT_INTERFACE_PCANCEL) strcpy(text, "Abbrechen");
+ if ( num == EVENT_INTERFACE_PDEF ) strcpy(text, "Standard\\Standardfarben einsetzen");
+ if ( num == EVENT_INTERFACE_PHEAD ) strcpy(text, "Kopf\\Gesicht und Haare");
+ if ( num == EVENT_INTERFACE_PBODY ) strcpy(text, "Anzug\\Raumfahrtanzug");
+ if ( num == EVENT_INTERFACE_PLROT ) strcpy(text, "\\Drehung links");
+ if ( num == EVENT_INTERFACE_PRROT ) strcpy(text, "\\Drehung rechts");
+ if ( num == EVENT_INTERFACE_PCRa ) strcpy(text, "Rot");
+ if ( num == EVENT_INTERFACE_PCGa ) strcpy(text, "Grün");
+ if ( num == EVENT_INTERFACE_PCBa ) strcpy(text, "Blau");
+ if ( num == EVENT_INTERFACE_PCRb ) strcpy(text, "Rot");
+ if ( num == EVENT_INTERFACE_PCGb ) strcpy(text, "Grün");
+ if ( num == EVENT_INTERFACE_PCBb ) strcpy(text, "Blau");
+ if ( num == EVENT_INTERFACE_PFACE1 ) strcpy(text, "\\Kopf 1");
+ if ( num == EVENT_INTERFACE_PFACE2 ) strcpy(text, "\\Kopf 4");
+ if ( num == EVENT_INTERFACE_PFACE3 ) strcpy(text, "\\Kopf 3");
+ if ( num == EVENT_INTERFACE_PFACE4 ) strcpy(text, "\\Kopf 2");
+ if ( num == EVENT_INTERFACE_PGLASS0) strcpy(text, "\\Keine Brille");
+ if ( num == EVENT_INTERFACE_PGLASS1) strcpy(text, "\\Brille 1");
+ if ( num == EVENT_INTERFACE_PGLASS2) strcpy(text, "\\Brille 2");
+ if ( num == EVENT_INTERFACE_PGLASS3) strcpy(text, "\\Brille 3");
+ if ( num == EVENT_INTERFACE_PGLASS4) strcpy(text, "\\Brille 4");
+ if ( num == EVENT_INTERFACE_PGLASS5) strcpy(text, "\\Brille 5");
+
+ if ( num == EVENT_OBJECT_DESELECT ) strcpy(text, "Vorherg. Auwahl (\\key desel;)");
+ if ( num == EVENT_OBJECT_LEFT ) strcpy(text, "Drehung links (\\key left;)");
+ if ( num == EVENT_OBJECT_RIGHT ) strcpy(text, "Drehung rechts (\\key right;)");
+ if ( num == EVENT_OBJECT_UP ) strcpy(text, "Vorwärts (\\key up;)");
+ if ( num == EVENT_OBJECT_DOWN ) strcpy(text, "Rückwärts (\\key down;)");
+ if ( num == EVENT_OBJECT_GASUP ) strcpy(text, "Steigt (\\key gup;)");
+ if ( num == EVENT_OBJECT_GASDOWN ) strcpy(text, "Sinkt (\\key gdown;)");
+ if ( num == EVENT_OBJECT_HTAKE ) strcpy(text, "Nehmen oder hinlegen (\\key action;)");
+ if ( num == EVENT_OBJECT_MTAKE ) strcpy(text, "Nehmen oder hinlegen (\\key action;)");
+ if ( num == EVENT_OBJECT_MFRONT ) strcpy(text, "..vorne");
+ if ( num == EVENT_OBJECT_MBACK ) strcpy(text, "..hinten");
+ if ( num == EVENT_OBJECT_MPOWER ) strcpy(text, "..Batterie");
+ if ( num == EVENT_OBJECT_BHELP ) strcpy(text, "Anweisungen über die Mission(\\key help;)");
+ if ( num == EVENT_OBJECT_BTAKEOFF ) strcpy(text, "Abheben nach vollbrachter Mission");
+ if ( num == EVENT_OBJECT_BDERRICK ) strcpy(text, "Baut einen Bohrturm");
+ if ( num == EVENT_OBJECT_BSTATION ) strcpy(text, "Baut ein Kraftwerk");
+ if ( num == EVENT_OBJECT_BFACTORY ) strcpy(text, "Baut eine Roboterfabrik");
+ if ( num == EVENT_OBJECT_BREPAIR ) strcpy(text, "Baut ein Reparaturzentrum");
+ if ( num == EVENT_OBJECT_BCONVERT ) strcpy(text, "Baut einen Konverter");
+ if ( num == EVENT_OBJECT_BTOWER ) strcpy(text, "Baut einen Geschützturm");
+ if ( num == EVENT_OBJECT_BRESEARCH ) strcpy(text, "Baut ein Forschungszentrum");
+ if ( num == EVENT_OBJECT_BRADAR ) strcpy(text, "Baut ein Radar");
+ if ( num == EVENT_OBJECT_BENERGY ) strcpy(text, "Baut eine Batteriefabrik");
+ if ( num == EVENT_OBJECT_BLABO ) strcpy(text, "Baut ein automatisches Labor");
+ if ( num == EVENT_OBJECT_BNUCLEAR ) strcpy(text, "Baut eine Brennstoffzellenfabrik");
+ if ( num == EVENT_OBJECT_BPARA ) strcpy(text, "Baut einen Blitzableiter");
+ if ( num == EVENT_OBJECT_BINFO ) strcpy(text, "Baut einen Infoserver");
+ if ( num == EVENT_OBJECT_GFLAT ) strcpy(text, "Zeigt ob der Boden eben ist");
+ if ( num == EVENT_OBJECT_FCREATE ) strcpy(text, "Setzt eine Fahne");
+ if ( num == EVENT_OBJECT_FDELETE ) strcpy(text, "Sammelt die Fahne ein");
+ if ( num == EVENT_OBJECT_FCOLORb ) strcpy(text, "\\Blaue Fahne");
+ if ( num == EVENT_OBJECT_FCOLORr ) strcpy(text, "\\Rote Fahne");
+ if ( num == EVENT_OBJECT_FCOLORg ) strcpy(text, "\\Grüne Fahne");
+ if ( num == EVENT_OBJECT_FCOLORy ) strcpy(text, "\\Gelbe Fahne");
+ if ( num == EVENT_OBJECT_FCOLORv ) strcpy(text, "\\Violette Fahne");
+ if ( num == EVENT_OBJECT_FACTORYfa ) strcpy(text, "Baut einen Jettransporter");
+ if ( num == EVENT_OBJECT_FACTORYta ) strcpy(text, "Baut einen Kettentransporter");
+ if ( num == EVENT_OBJECT_FACTORYwa ) strcpy(text, "Baut einen Radtransporter");
+ if ( num == EVENT_OBJECT_FACTORYia ) strcpy(text, "Baut einen Krabbeltransporter");
+ if ( num == EVENT_OBJECT_FACTORYfc ) strcpy(text, "Baut einen Jetshooter");
+ if ( num == EVENT_OBJECT_FACTORYtc ) strcpy(text, "Baut einen Kettenshooter");
+ if ( num == EVENT_OBJECT_FACTORYwc ) strcpy(text, "Baut einen Radshooter");
+ if ( num == EVENT_OBJECT_FACTORYic ) strcpy(text, "Baut einen Krabbelshooter");
+ if ( num == EVENT_OBJECT_FACTORYfi ) strcpy(text, "Baut einen Jetorgashooter");
+ if ( num == EVENT_OBJECT_FACTORYti ) strcpy(text, "Baut einen Kettenorgashooter");
+ if ( num == EVENT_OBJECT_FACTORYwi ) strcpy(text, "Baut einen Radorgashooter");
+ if ( num == EVENT_OBJECT_FACTORYii ) strcpy(text, "Baut einen Krabbelorgashooter");
+ if ( num == EVENT_OBJECT_FACTORYfs ) strcpy(text, "Baut einen Jetschnüffler");
+ if ( num == EVENT_OBJECT_FACTORYts ) strcpy(text, "Baut einen Kettenschnüffler");
+ if ( num == EVENT_OBJECT_FACTORYws ) strcpy(text, "Baut einen Radschnüffler");
+ if ( num == EVENT_OBJECT_FACTORYis ) strcpy(text, "Baut einen Krabbelschnüffler");
+ if ( num == EVENT_OBJECT_FACTORYrt ) strcpy(text, "Baut einen Stampfer");
+ if ( num == EVENT_OBJECT_FACTORYrc ) strcpy(text, "Baut einen Phazershooter");
+ if ( num == EVENT_OBJECT_FACTORYrr ) strcpy(text, "Baut einen Recycler");
+ if ( num == EVENT_OBJECT_FACTORYrs ) strcpy(text, "Baut einen Schutzschild");
+ if ( num == EVENT_OBJECT_FACTORYsa ) strcpy(text, "Baut einen Kettentaucher");
+ if ( num == EVENT_OBJECT_RTANK ) strcpy(text, "Forschungsprogramm Kettenantrieb");
+ if ( num == EVENT_OBJECT_RFLY ) strcpy(text, "Forschungsprogramm Jetantrieb");
+ if ( num == EVENT_OBJECT_RTHUMP ) strcpy(text, "Forschungsprogramm Stampfer");
+ if ( num == EVENT_OBJECT_RCANON ) strcpy(text, "Forschungsprogramm Shooterkanone");
+ if ( num == EVENT_OBJECT_RTOWER ) strcpy(text, "Forschungsprogramm Geschützturm");
+ if ( num == EVENT_OBJECT_RPHAZER ) strcpy(text, "Forschungsprogramm Phazerkanone");
+ if ( num == EVENT_OBJECT_RSHIELD ) strcpy(text, "Forschungsprogramm Schutzschild");
+ if ( num == EVENT_OBJECT_RATOMIC ) strcpy(text, "Forschungsprogramm Brennstoffzelle");
+ if ( num == EVENT_OBJECT_RiPAW ) strcpy(text, "Forschungsprogramm Krabbelantrieb");
+ if ( num == EVENT_OBJECT_RiGUN ) strcpy(text, "Forschungsprogramm Orgashooterkanone");
+ if ( num == EVENT_OBJECT_RESET ) strcpy(text, "Alles zurücksetzen");
+ if ( num == EVENT_OBJECT_SEARCH ) strcpy(text, "Schnüffeln (\\key action;)");
+ if ( num == EVENT_OBJECT_TERRAFORM ) strcpy(text, "Stampfen (\\key action;)");
+ if ( num == EVENT_OBJECT_FIRE ) strcpy(text, "Feuer (\\key action;)");
+ if ( num == EVENT_OBJECT_RECOVER ) strcpy(text, "Recyceln (\\key action;)");
+ if ( num == EVENT_OBJECT_BEGSHIELD ) strcpy(text, "Schutzschild ausfahren (\\key action;)");
+ if ( num == EVENT_OBJECT_ENDSHIELD ) strcpy(text, "Schutzschild einholen (\\key action;)");
+ if ( num == EVENT_OBJECT_DIMSHIELD ) strcpy(text, "Reichweite Schutzschild");
+ if ( num == EVENT_OBJECT_PROGRUN ) strcpy(text, "Gewähltes Programm ausführen");
+ if ( num == EVENT_OBJECT_PROGEDIT ) strcpy(text, "Gewähltes Programm bearbeiten");
+ if ( num == EVENT_OBJECT_INFOOK ) strcpy(text, "\\SatCom in Standby");
+ if ( num == EVENT_OBJECT_DELETE ) strcpy(text, "Gebäude sprengen");
+ if ( num == EVENT_OBJECT_GENERGY ) strcpy(text, "Energievorrat");
+ if ( num == EVENT_OBJECT_GSHIELD ) strcpy(text, "Schäden");
+ if ( num == EVENT_OBJECT_GRANGE ) strcpy(text, "Triebwerktemperatur");
+ if ( num == EVENT_OBJECT_GPROGRESS ) strcpy(text, "Prozess im Gang ...");
+ if ( num == EVENT_OBJECT_GRADAR ) strcpy(text, "Anzahl erfasster Insekten");
+ if ( num == EVENT_OBJECT_GINFO ) strcpy(text, "Gesendete Informationen");
+ if ( num == EVENT_OBJECT_COMPASS ) strcpy(text, "Kompass");
+//? if ( num == EVENT_OBJECT_MAP ) strcpy(text, "Minikarte");
+ if ( num == EVENT_OBJECT_MAPZOOM ) strcpy(text, "Zoom Minikarte");
+ if ( num == EVENT_OBJECT_CAMERA ) strcpy(text, "Kamera (\\key camera;)");
+ if ( num == EVENT_OBJECT_CAMERAleft) strcpy(text, "Kamera links");
+ if ( num == EVENT_OBJECT_CAMERAright) strcpy(text, "Kamera rechts");
+ if ( num == EVENT_OBJECT_CAMERAnear) strcpy(text, "Kamera näher");
+ if ( num == EVENT_OBJECT_CAMERAaway) strcpy(text, "Kamera weiter weg");
+ if ( num == EVENT_OBJECT_HELP ) strcpy(text, "Anweisungen über das ausgewählte Objekt");
+ if ( num == EVENT_OBJECT_SOLUCE ) strcpy(text, "Zeigt die Lösung");
+ if ( num == EVENT_OBJECT_SHORTCUT00) strcpy(text, "Anzeige Roboter <-> Bauten");
+ if ( num == EVENT_OBJECT_LIMIT ) strcpy(text, "Zeigt die Reichweite");
+ if ( num == EVENT_OBJECT_PEN0 ) strcpy(text, "\\Bleistift abheben");
+ if ( num == EVENT_OBJECT_PEN1 ) strcpy(text, "\\Schwarzen Bleistift hinunterlassen");
+ if ( num == EVENT_OBJECT_PEN2 ) strcpy(text, "\\Gelben Bleistift hinunterlassen");
+ if ( num == EVENT_OBJECT_PEN3 ) strcpy(text, "\\Orangefarbenen Bleistift hinunterlassen");
+ if ( num == EVENT_OBJECT_PEN4 ) strcpy(text, "\\Roten Bleistift hinunterlassen");
+ if ( num == EVENT_OBJECT_PEN5 ) strcpy(text, "\\Violetten Bleistift hinunterlassen");
+ if ( num == EVENT_OBJECT_PEN6 ) strcpy(text, "\\Blauen Bleistift hinunterlassen");
+ if ( num == EVENT_OBJECT_PEN7 ) strcpy(text, "\\Grünen Bleistift hinunterlassen");
+ if ( num == EVENT_OBJECT_PEN8 ) strcpy(text, "\\Braunen Bleistift hinunterlassen");
+ if ( num == EVENT_OBJECT_REC ) strcpy(text, "\\Aufnahme starten");
+ if ( num == EVENT_OBJECT_STOP ) strcpy(text, "\\Aufnahme stoppen");
+ if ( num == EVENT_DT_VISIT0 ||
+ num == EVENT_DT_VISIT1 ||
+ num == EVENT_DT_VISIT2 ||
+ num == EVENT_DT_VISIT3 ||
+ num == EVENT_DT_VISIT4 ) strcpy(text, "Zeigt den Ort");
+ if ( num == EVENT_DT_END ) strcpy(text, "Weitermachen");
+ if ( num == EVENT_CMD ) strcpy(text, "Befehleingabe");
+ if ( num == EVENT_SPEED ) strcpy(text, "Spielgeschwindigkeit");
+
+ if ( num == EVENT_HYPER_PREV ) strcpy(text, "Vorherg. Seite");
+ if ( num == EVENT_HYPER_NEXT ) strcpy(text, "Nächste Seite");
+ if ( num == EVENT_HYPER_HOME ) strcpy(text, "Home");
+ if ( num == EVENT_HYPER_COPY ) strcpy(text, "Kopieren");
+ if ( num == EVENT_HYPER_SIZE1 ) strcpy(text, "Größe 1");
+ if ( num == EVENT_HYPER_SIZE2 ) strcpy(text, "Größe 2");
+ if ( num == EVENT_HYPER_SIZE3 ) strcpy(text, "Größe 3");
+ if ( num == EVENT_HYPER_SIZE4 ) strcpy(text, "Größe 4");
+ if ( num == EVENT_HYPER_SIZE5 ) strcpy(text, "Größe 5");
+ if ( num == EVENT_SATCOM_HUSTON ) strcpy(text, "Anweisungen von Houston");
+#if _TEEN
+ if ( num == EVENT_SATCOM_SAT ) strcpy(text, "Wörterbuch Englisch-Deutsch");
+#else
+ if ( num == EVENT_SATCOM_SAT ) strcpy(text, "Satellitenbericht");
+#endif
+ if ( num == EVENT_SATCOM_LOADING ) strcpy(text, "Von Houston übermittelte Programme");
+ if ( num == EVENT_SATCOM_OBJECT ) strcpy(text, "Liste der Objekte");
+ if ( num == EVENT_SATCOM_PROG ) strcpy(text, "Hilfe über Programmieren");
+ if ( num == EVENT_SATCOM_SOLUCE ) strcpy(text, "Lösung");
+
+ if ( num == EVENT_STUDIO_OK ) strcpy(text, "OK\\Programm kompilieren");
+ if ( num == EVENT_STUDIO_CANCEL ) strcpy(text, "Abbrechen\\Editor schließen");
+ if ( num == EVENT_STUDIO_NEW ) strcpy(text, "Neu");
+ if ( num == EVENT_STUDIO_OPEN ) strcpy(text, "Öffnen (Ctrl+o)");
+ if ( num == EVENT_STUDIO_SAVE ) strcpy(text, "Speichern (Ctrl+s)");
+ if ( num == EVENT_STUDIO_UNDO ) strcpy(text, "Widerrufen (Ctrl+z)");
+ if ( num == EVENT_STUDIO_CUT ) strcpy(text, "Ausschneiden (Ctrl+x)");
+ if ( num == EVENT_STUDIO_COPY ) strcpy(text, "Kopieren (Ctrl+c)");
+ if ( num == EVENT_STUDIO_PASTE ) strcpy(text, "Einfügen (Ctrl+v)");
+ if ( num == EVENT_STUDIO_SIZE ) strcpy(text, "Zeichengröße");
+ if ( num == EVENT_STUDIO_TOOL ) strcpy(text, "Anweisungen (\\key help;)");
+ if ( num == EVENT_STUDIO_HELP ) strcpy(text, "Hilfe über Programmieren (\\key prog;)");
+ if ( num == EVENT_STUDIO_COMPILE ) strcpy(text, "Kompilieren");
+ if ( num == EVENT_STUDIO_RUN ) strcpy(text, "Start/Stop");
+ if ( num == EVENT_STUDIO_REALTIME ) strcpy(text, "Pause/Weitermachen");
+ if ( num == EVENT_STUDIO_STEP ) strcpy(text, "Ein Schritt");
+ }
+
+ if ( type == RES_OBJECT )
+ {
+ if ( num == OBJECT_PORTICO ) strcpy(text, "Träger");
+ if ( num == OBJECT_BASE ) strcpy(text, "Raumschiff");
+ if ( num == OBJECT_DERRICK ) strcpy(text, "Bohrturm");
+ if ( num == OBJECT_FACTORY ) strcpy(text, "Roboterfabrik");
+ if ( num == OBJECT_REPAIR ) strcpy(text, "Reparaturzentrum");
+ if ( num == OBJECT_DESTROYER ) strcpy(text, "Einstampfer");
+ if ( num == OBJECT_STATION ) strcpy(text, "Kraftwerk");
+ if ( num == OBJECT_CONVERT ) strcpy(text, "Konverter Erz-Titan");
+ if ( num == OBJECT_TOWER ) strcpy(text, "Geschützturm");
+ if ( num == OBJECT_NEST ) strcpy(text, "Orgastoffquelle");
+ if ( num == OBJECT_RESEARCH ) strcpy(text, "Forschungszentrum");
+ if ( num == OBJECT_RADAR ) strcpy(text, "Radar");
+ if ( num == OBJECT_INFO ) strcpy(text, "Infoserver");
+#if _TEEN
+ if ( num == OBJECT_ENERGY ) strcpy(text, "Auflöser");
+#else
+ if ( num == OBJECT_ENERGY ) strcpy(text, "Batteriefabrik");
+#endif
+ if ( num == OBJECT_LABO ) strcpy(text, "Automatisches Labor");
+ if ( num == OBJECT_NUCLEAR ) strcpy(text, "Brennstoffzellenfabrik");
+ if ( num == OBJECT_PARA ) strcpy(text, "Blitzableiter");
+ if ( num == OBJECT_SAFE ) strcpy(text, "Bunker");
+ if ( num == OBJECT_HUSTON ) strcpy(text, "Kontrollzentrum");
+ if ( num == OBJECT_TARGET1 ) strcpy(text, "Zielscheibe");
+ if ( num == OBJECT_TARGET2 ) strcpy(text, "Zielscheibe");
+ if ( num == OBJECT_START ) strcpy(text, "Startfläche");
+ if ( num == OBJECT_END ) strcpy(text, "Zielfläche");
+ if ( num == OBJECT_STONE ) strcpy(text, "Titanerz");
+ if ( num == OBJECT_URANIUM ) strcpy(text, "Platinerz");
+ if ( num == OBJECT_BULLET ) strcpy(text, "Orgastoff");
+ if ( num == OBJECT_METAL ) strcpy(text, "Titan");
+ if ( num == OBJECT_POWER ) strcpy(text, "Elektrolytische Batterie");
+ if ( num == OBJECT_ATOMIC ) strcpy(text, "Brennstoffzelle");
+ if ( num == OBJECT_BBOX ) strcpy(text, "Flugschreiber");
+ if ( num == OBJECT_KEYa ) strcpy(text, "Schlüssel A");
+ if ( num == OBJECT_KEYb ) strcpy(text, "Schlüssel B");
+ if ( num == OBJECT_KEYc ) strcpy(text, "Schlüssel C");
+ if ( num == OBJECT_KEYd ) strcpy(text, "Schlüssel D");
+ if ( num == OBJECT_TNT ) strcpy(text, "Sprengstoff");
+ if ( num == OBJECT_BOMB ) strcpy(text, "Landmine");
+ if ( num == OBJECT_BAG ) strcpy(text, "Überlebenskit");
+ if ( num == OBJECT_WAYPOINT ) strcpy(text, "Checkpoint");
+ if ( num == OBJECT_FLAGb ) strcpy(text, "Blaue Fahne");
+ if ( num == OBJECT_FLAGr ) strcpy(text, "Rote Fahne");
+ if ( num == OBJECT_FLAGg ) strcpy(text, "Grüne Fahne");
+ if ( num == OBJECT_FLAGy ) strcpy(text, "Gelbe Fahne");
+ if ( num == OBJECT_FLAGv ) strcpy(text, "Violette Fahne");
+ if ( num == OBJECT_MARKPOWER ) strcpy(text, "Markierung für unterirdische Energiequelle");
+ if ( num == OBJECT_MARKURANIUM ) strcpy(text, "Markierung für unterirdisches Platinvorkommen");
+ if ( num == OBJECT_MARKKEYa ) strcpy(text, "Markierung für vergrabenen Schlüssel A");
+ if ( num == OBJECT_MARKKEYb ) strcpy(text, "Markierung für vergrabenen Schlüssel B");
+ if ( num == OBJECT_MARKKEYc ) strcpy(text, "Markierung für vergrabenen Schlüssel C");
+ if ( num == OBJECT_MARKKEYd ) strcpy(text, "Markierung für vergrabenen Schlüssel D");
+ if ( num == OBJECT_MARKSTONE ) strcpy(text, "Markierung für unterirdisches Titanvorkommen");
+ if ( num == OBJECT_MOBILEft ) strcpy(text, "Übungsroboter");
+ if ( num == OBJECT_MOBILEtt ) strcpy(text, "Übungsroboter");
+ if ( num == OBJECT_MOBILEwt ) strcpy(text, "Übungsroboter");
+ if ( num == OBJECT_MOBILEit ) strcpy(text, "Übungsroboter");
+ if ( num == OBJECT_MOBILEfa ) strcpy(text, "Transporter");
+ if ( num == OBJECT_MOBILEta ) strcpy(text, "Transporter");
+ if ( num == OBJECT_MOBILEwa ) strcpy(text, "Transporter");
+ if ( num == OBJECT_MOBILEia ) strcpy(text, "Transporter");
+ if ( num == OBJECT_MOBILEfc ) strcpy(text, "Shooter");
+ if ( num == OBJECT_MOBILEtc ) strcpy(text, "Shooter");
+ if ( num == OBJECT_MOBILEwc ) strcpy(text, "Shooter");
+ if ( num == OBJECT_MOBILEic ) strcpy(text, "Shooter");
+ if ( num == OBJECT_MOBILEfi ) strcpy(text, "OrgaShooter");
+ if ( num == OBJECT_MOBILEti ) strcpy(text, "OrgaShooter");
+ if ( num == OBJECT_MOBILEwi ) strcpy(text, "OrgaShooter");
+ if ( num == OBJECT_MOBILEii ) strcpy(text, "OrgaShooter");
+ if ( num == OBJECT_MOBILEfs ) strcpy(text, "Schnüffler");
+ if ( num == OBJECT_MOBILEts ) strcpy(text, "Schnüffler");
+ if ( num == OBJECT_MOBILEws ) strcpy(text, "Schnüffler");
+ if ( num == OBJECT_MOBILEis ) strcpy(text, "Schnüffler");
+ if ( num == OBJECT_MOBILErt ) strcpy(text, "Stampfer");
+ if ( num == OBJECT_MOBILErc ) strcpy(text, "Phazershooter");
+ if ( num == OBJECT_MOBILErr ) strcpy(text, "Recycler");
+ if ( num == OBJECT_MOBILErs ) strcpy(text, "Schutzschild");
+ if ( num == OBJECT_MOBILEsa ) strcpy(text, "Kettentaucher");
+ if ( num == OBJECT_MOBILEtg ) strcpy(text, "Mobile Zielscheibe");
+ if ( num == OBJECT_MOBILEdr ) strcpy(text, "Zeichner");
+ if ( num == OBJECT_HUMAN ) strcpy(text, g_gamerName);
+ if ( num == OBJECT_TECH ) strcpy(text, "Techniker");
+ if ( num == OBJECT_TOTO ) strcpy(text, "Robby");
+ if ( num == OBJECT_MOTHER ) strcpy(text, "Insektenkönigin");
+ if ( num == OBJECT_ANT ) strcpy(text, "Ameise");
+ if ( num == OBJECT_SPIDER ) strcpy(text, "Spinne");
+ if ( num == OBJECT_BEE ) strcpy(text, "Wespe");
+ if ( num == OBJECT_WORM ) strcpy(text, "Wurm");
+ if ( num == OBJECT_EGG ) strcpy(text, "Ei");
+ if ( num == OBJECT_RUINmobilew1 ) strcpy(text, "Roboterwrack");
+ if ( num == OBJECT_RUINmobilew2 ) strcpy(text, "Roboterwrack");
+ if ( num == OBJECT_RUINmobilet1 ) strcpy(text, "Roboterwrack");
+ if ( num == OBJECT_RUINmobilet2 ) strcpy(text, "Roboterwrack");
+ if ( num == OBJECT_RUINmobiler1 ) strcpy(text, "Roboterwrack");
+ if ( num == OBJECT_RUINmobiler2 ) strcpy(text, "Roboterwrack");
+ if ( num == OBJECT_RUINfactory ) strcpy(text, "Gebäuderuine");
+ if ( num == OBJECT_RUINdoor ) strcpy(text, "Gebäuderuine");
+ if ( num == OBJECT_RUINsupport ) strcpy(text, "Abfall");
+ if ( num == OBJECT_RUINradar ) strcpy(text, "Gebäuderuine");
+ if ( num == OBJECT_RUINconvert ) strcpy(text, "Gebäuderuine");
+ if ( num == OBJECT_RUINbase ) strcpy(text, "Raumschiffruine");
+ if ( num == OBJECT_RUINhead ) strcpy(text, "Raumschiffruine");
+ if ( num == OBJECT_APOLLO1 ||
+ num == OBJECT_APOLLO3 ||
+ num == OBJECT_APOLLO4 ||
+ num == OBJECT_APOLLO5 ) strcpy(text, "Überreste einer Apollo-Mission");
+ if ( num == OBJECT_APOLLO2 ) strcpy(text, "Lunar Roving Vehicle");
+ }
+
+ if ( type == RES_ERR )
+ {
+ strcpy(text, "Fehler");
+ if ( num == ERR_CMD ) strcpy(text, "Befehl unbekannt");
+#if _NEWLOOK
+ if ( num == ERR_INSTALL ) strcpy(text, "CeeBot wurde nicht installiert.");
+ if ( num == ERR_NOCD ) strcpy(text, "Legen Sie die CeeBot-CD ein\nund starten Sie das Spiel neu.");
+#else
+ if ( num == ERR_INSTALL ) strcpy(text, "COLOBOT wurde nicht installiert.");
+ if ( num == ERR_NOCD ) strcpy(text, "Legen Sie die COLOBOT-CD ein\nund starten Sie das Spiel neu.");
+#endif
+ if ( num == ERR_MANIP_VEH ) strcpy(text, "Roboter ungeeignet");
+ if ( num == ERR_MANIP_FLY ) strcpy(text, "Im Flug unmöglich");
+ if ( num == ERR_MANIP_BUSY ) strcpy(text, "Trägt schon etwas");
+ if ( num == ERR_MANIP_NIL ) strcpy(text, "Nichts zu ergreifen");
+ if ( num == ERR_MANIP_MOTOR ) strcpy(text, "In Fahrt unmöglich");
+ if ( num == ERR_MANIP_OCC ) strcpy(text, "Stelle schon besetzt");
+ if ( num == ERR_MANIP_FRIEND ) strcpy(text, "Kein anderer Roboter");
+ if ( num == ERR_MANIP_RADIO ) strcpy(text, "Sie können keinen radioaktiven Gegenstand tragen");
+ if ( num == ERR_MANIP_WATER ) strcpy(text, "Sie können unter Wasser nichts tragen");
+ if ( num == ERR_MANIP_EMPTY ) strcpy(text, "Nichts abzulegen");
+ if ( num == ERR_BUILD_FLY ) strcpy(text, "Im Flug unmöglich");
+ if ( num == ERR_BUILD_WATER ) strcpy(text, "Unter Wasser unmöglich");
+ if ( num == ERR_BUILD_ENERGY ) strcpy(text, "Nicht genug Energie");
+ if ( num == ERR_BUILD_METALAWAY ) strcpy(text, "Titan zu weit weg");
+ if ( num == ERR_BUILD_METALNEAR ) strcpy(text, "Titan zu nahe");
+ if ( num == ERR_BUILD_METALINEX ) strcpy(text, "Kein Titan vorhanden");
+ if ( num == ERR_BUILD_FLAT ) strcpy(text, "Boden nicht eben genug");
+ if ( num == ERR_BUILD_FLATLIT ) strcpy(text, "Ebener Boden nicht groß genug");
+ if ( num == ERR_BUILD_BUSY ) strcpy(text, "Stelle schon besetzt");
+ if ( num == ERR_BUILD_BASE ) strcpy(text, "Zu nahe am Raumschiff");
+ if ( num == ERR_BUILD_NARROW ) strcpy(text, "Zu nahe an einem Gebäude");
+ if ( num == ERR_BUILD_MOTOR ) strcpy(text, "In Fahrt unmöglich");
+ if ( num == ERR_SEARCH_FLY ) strcpy(text, "Im Flug unmöglich");
+ if ( num == ERR_SEARCH_VEH ) strcpy(text, "Roboter ungeeignet");
+ if ( num == ERR_SEARCH_MOTOR ) strcpy(text, "In Fahrt unmöglich");
+ if ( num == ERR_TERRA_VEH ) strcpy(text, "Roboter ungeeignet");
+ if ( num == ERR_TERRA_ENERGY ) strcpy(text, "Nicht genug Energie");
+ if ( num == ERR_TERRA_FLOOR ) strcpy(text, "Boden ungeeignet");
+ if ( num == ERR_TERRA_BUILDING ) strcpy(text, "Gebäude zu nahe");
+ if ( num == ERR_TERRA_OBJECT ) strcpy(text, "Gegenstand zu nahe");
+ if ( num == ERR_RECOVER_VEH ) strcpy(text, "Roboter ungeeignet");
+ if ( num == ERR_RECOVER_ENERGY ) strcpy(text, "Nicht genug Energie");
+ if ( num == ERR_RECOVER_NULL ) strcpy(text, "Nichts zu recyceln");
+ if ( num == ERR_SHIELD_VEH ) strcpy(text, "Roboter ungeeignet");
+ if ( num == ERR_SHIELD_ENERGY ) strcpy(text, "Keine Energie mehr");
+//? if ( num == ERR_COM ) strcpy(text, "Kommunikationsproblem mit dem Roboter");
+ if ( num == ERR_MOVE_IMPOSSIBLE ) strcpy(text, "Ziel kann nicht erreicht werden");
+ if ( num == ERR_FIND_IMPOSSIBLE ) strcpy(text, "Das Objekt existiert nicht");
+ if ( num == ERR_GOTO_IMPOSSIBLE ) strcpy(text, "Ziel kann nicht erreicht werden");
+ if ( num == ERR_GOTO_ITER ) strcpy(text, "Ziel kann nicht erreicht werden");
+ if ( num == ERR_GOTO_BUSY ) strcpy(text, "Ziel ist schon besetzt");
+ if ( num == ERR_FIRE_VEH ) strcpy(text, "Roboter ungeeignet");
+ if ( num == ERR_FIRE_ENERGY ) strcpy(text, "Nicht genug Energie");
+ if ( num == ERR_FIRE_FLY ) strcpy(text, "Im Flug unmöglich");
+ if ( num == ERR_CONVERT_EMPTY ) strcpy(text, "Kein konvertierbares Titanerz vorhanden");
+ if ( num == ERR_DERRICK_NULL ) strcpy(text, "Keine unterirdische Erzlagerstätte");
+ if ( num == ERR_STATION_NULL ) strcpy(text, "Kein unterirdisches Energievorkommen");
+ if ( num == ERR_TOWER_POWER ) strcpy(text, "Keine Batterie");
+ if ( num == ERR_TOWER_ENERGY ) strcpy(text, "Keine Energie mehr");
+ if ( num == ERR_RESEARCH_POWER ) strcpy(text, "Keine Batterie");
+ if ( num == ERR_RESEARCH_ENERGY ) strcpy(text, "Nicht mehr genug Energie");
+ if ( num == ERR_RESEARCH_TYPE ) strcpy(text, "Falscher Batterietyp");
+ if ( num == ERR_RESEARCH_ALREADY) strcpy(text, "Forschungsprogramm schon ausgeführt");
+ if ( num == ERR_ENERGY_NULL ) strcpy(text, "Kein unterirdisches Energievorkommen");
+ if ( num == ERR_ENERGY_LOW ) strcpy(text, "Noch nicht genug Energie");
+ if ( num == ERR_ENERGY_EMPTY ) strcpy(text, "Kein konvertierbares Titanerz vorhanden");
+ if ( num == ERR_ENERGY_BAD ) strcpy(text, "Wandelt nur Titanerz um");
+ if ( num == ERR_BASE_DLOCK ) strcpy(text, "Die Türen werden von einem Gegenstand blockiert");
+ if ( num == ERR_BASE_DHUMAN ) strcpy(text, "Gehen Sie an Bord, bevor Sie abheben");
+ if ( num == ERR_LABO_NULL ) strcpy(text, "Nichts zu analysieren");
+ if ( num == ERR_LABO_BAD ) strcpy(text, "Analysiert nur Orgastoff");
+ if ( num == ERR_LABO_ALREADY ) strcpy(text, "Analyse schon durchgeführt");
+ if ( num == ERR_NUCLEAR_NULL ) strcpy(text, "Kein unterirdisches Energievorkommen");
+ if ( num == ERR_NUCLEAR_LOW ) strcpy(text, "Noch nicht genug Energie");
+ if ( num == ERR_NUCLEAR_EMPTY ) strcpy(text, "Kein konvertierbares Platin");
+ if ( num == ERR_NUCLEAR_BAD ) strcpy(text, "Wandelt nur Platin um");
+ if ( num == ERR_FACTORY_NULL ) strcpy(text, "Kein Titan vorhanden");
+ if ( num == ERR_FACTORY_NEAR ) strcpy(text, "Ein Gegenstand ist zu nahe");
+ if ( num == ERR_RESET_NEAR ) strcpy(text, "Stelle schon besetzt");
+ if ( num == ERR_INFO_NULL ) strcpy(text, "Kein Infoserver in Reichweite");
+ if ( num == ERR_VEH_VIRUS ) strcpy(text, "Ein Programm wurde von einem Virus infiziert");
+ if ( num == ERR_BAT_VIRUS ) strcpy(text, "Von Virus infiziert, zeitweise außer Betrieb");
+ if ( num == ERR_VEH_POWER ) strcpy(text, "Keine Batterie");
+ if ( num == ERR_VEH_ENERGY ) strcpy(text, "Keine Energie mehr");
+ if ( num == ERR_FLAG_FLY ) strcpy(text, "Im Flug unmöglich");
+ if ( num == ERR_FLAG_WATER ) strcpy(text, "Im Wasser unmöglich");
+ if ( num == ERR_FLAG_MOTOR ) strcpy(text, "Beim Gehen unmöglich");
+ if ( num == ERR_FLAG_BUSY ) strcpy(text, "Unmöglich wenn Sie etwas tragen");
+ if ( num == ERR_FLAG_CREATE ) strcpy(text, "Zu viele Fahnen dieser Farbe (Maximum 5)");
+ if ( num == ERR_FLAG_PROXY ) strcpy(text, "Zu nahe an einer anderen Fahne");
+ if ( num == ERR_FLAG_DELETE ) strcpy(text, "Keine Fahne in Reichweite");
+ if ( num == ERR_MISSION_NOTERM ) strcpy(text, "Mission noch nicht beendet (Drücken Sie auf \\key help; für weitere Informationen)");
+ if ( num == ERR_DELETEMOBILE ) strcpy(text, "Roboter zerstört");
+ if ( num == ERR_DELETEBUILDING ) strcpy(text, "Gebäude zerstört");
+ if ( num == ERR_TOOMANY ) strcpy(text, "Kein neues Objekt kann erstellt werden (zu viele vorhanden)");
+ if ( num == ERR_OBLIGATORYTOKEN ) strcpy(text, "Es fehlt \"%s\" in Ihrem Programm");
+ if ( num == ERR_PROHIBITEDTOKEN ) strcpy(text, "In dieser Übung verboten");
+
+ if ( num == INFO_BUILD ) strcpy(text, "Gebäude fertiggestellt");
+ if ( num == INFO_CONVERT ) strcpy(text, "Titan verfügbar");
+ if ( num == INFO_RESEARCH ) strcpy(text, "Forschungsprogramm abgeschlossen");
+ if ( num == INFO_RESEARCHTANK ) strcpy(text, "Herstellung eines Roboters mit Kettenantrieb möglich");
+ if ( num == INFO_RESEARCHFLY ) strcpy(text, "Sie können jetzt mit den Tasten \\key gup; und \\key gdown; fliegen");
+ if ( num == INFO_RESEARCHTHUMP ) strcpy(text, "Herstellung eines Stampfers möglich");
+ if ( num == INFO_RESEARCHCANON ) strcpy(text, "Herstellung eines Shooters möglich");
+ if ( num == INFO_RESEARCHTOWER ) strcpy(text, "Errichtung eines Geschützturms möglich");
+ if ( num == INFO_RESEARCHPHAZER ) strcpy(text, "Herstellung eines Phazershooters möglich");
+ if ( num == INFO_RESEARCHSHIELD ) strcpy(text, "Herstellung eines Schutzschildes möglich");
+ if ( num == INFO_RESEARCHATOMIC ) strcpy(text, "Errichtung einer Brennstoffzellenfabrik möglich");
+ if ( num == INFO_FACTORY ) strcpy(text, "Neuer Roboter verfügbar");
+ if ( num == INFO_LABO ) strcpy(text, "Analyse vollendet");
+ if ( num == INFO_ENERGY ) strcpy(text, "Batterie verfügbar");
+ if ( num == INFO_NUCLEAR ) strcpy(text, "Brennstoffzelle verfügbar");
+ if ( num == INFO_FINDING ) strcpy(text, "Sie haben ein brauchbares Objekt gefunden");
+ if ( num == INFO_MARKPOWER ) strcpy(text, "Geeignete Stelle für Kraftwerk gefunden");
+ if ( num == INFO_MARKURANIUM ) strcpy(text, "Geeignete Stelle für Bohrturm gefunden");
+ if ( num == INFO_MARKSTONE ) strcpy(text, "Geeignete Stelle für Bohrturm gefunden");
+ if ( num == INFO_MARKKEYa ) strcpy(text, "Geeignete Stelle für Bohrturm gefunden");
+ if ( num == INFO_MARKKEYb ) strcpy(text, "Geeignete Stelle für Bohrturm gefunden");
+ if ( num == INFO_MARKKEYc ) strcpy(text, "Geeignete Stelle für Bohrturm gefunden");
+ if ( num == INFO_MARKKEYd ) strcpy(text, "Geeignete Stelle für Bohrturm gefunden");
+ if ( num == INFO_WIN ) strcpy(text, "<<< Bravo, Mission vollendet >>>");
+ if ( num == INFO_LOST ) strcpy(text, "<<< Mission gescheitert >>>");
+ if ( num == INFO_LOSTq ) strcpy(text, "<<< Mission gescheitert >>>");
+ if ( num == INFO_WRITEOK ) strcpy(text, "Mission gespeichert");
+ if ( num == INFO_DELETEPATH ) strcpy(text, "Checkpoint erreicht");
+ if ( num == INFO_DELETEMOTHER ) strcpy(text, "Insektenkönigin tödlich verwundet");
+ if ( num == INFO_DELETEANT ) strcpy(text, "Ameise tödlich verwundet");
+ if ( num == INFO_DELETEBEE ) strcpy(text, "Wespe tödlich verwundet");
+ if ( num == INFO_DELETEWORM ) strcpy(text, "Wurm tödlich verwundet");
+ if ( num == INFO_DELETESPIDER ) strcpy(text, "Spinne tödlich verwundet");
+ if ( num == INFO_BEGINSATCOM ) strcpy(text, "Beziehen Sie sich auf Ihren SatCom, indem Sie auf \\key help; drücken");
+ }
+
+ if ( type == RES_CBOT )
+ {
+ strcpy(text, "Fehler");
+ if ( num == TX_OPENPAR ) strcpy(text, "Es fehlt eine offene Klammer ""(""");
+ if ( num == TX_CLOSEPAR ) strcpy(text, "Es fehlt eine geschlossene Klammer "")""");
+ if ( num == TX_NOTBOOL ) strcpy(text, "Der Ausdruck muss einen boolschen Wert ergeben");
+ if ( num == TX_UNDEFVAR ) strcpy(text, "Variable nicht deklariert");
+ if ( num == TX_BADLEFT ) strcpy(text, "Zuweisung unmöglich");
+ if ( num == TX_ENDOF ) strcpy(text, "Es fehlt ein Strichpunkt "";"" am Ende der Anweisung");
+ if ( num == TX_OUTCASE ) strcpy(text, "Anweisung ""case"" ohne vorhergehende Anweisung ""switch""");
+ if ( num == TX_NOTERM ) strcpy(text, "Hier ist eine Anweisung nach dem Ende des Programms");
+ if ( num == TX_CLOSEBLK ) strcpy(text, "Es fehlt eine geschlossene geschweifte Klammer ""}"" (Ende des Blocks)");
+ if ( num == TX_ELSEWITHOUTIF ) strcpy(text, "Anweisung ""else"" ohne vorhergehende Anweisung ""if""");
+ if ( num == TX_OPENBLK ) strcpy(text, "Es fehlt eine offene geschweifte Klammer""{""");
+ if ( num == TX_BADTYPE ) strcpy(text, "Der Ausdruck ergibt einen falschen Typ für die Zuweisung");
+ if ( num == TX_REDEFVAR ) strcpy(text, "Eine Variable wird zum zweiten Mal deklariert");
+ if ( num == TX_BAD2TYPE ) strcpy(text, "Die zwei Operanden sind nicht kompatibel");
+ if ( num == TX_UNDEFCALL ) strcpy(text, "Unbekannte Funktion");
+ if ( num == TX_MISDOTS ) strcpy(text, "Es fehlt ein Doppelpunkt "" : """);
+ if ( num == TX_WHILE ) strcpy(text, "Es fehlt das Wort ""while""");
+ if ( num == TX_BREAK ) strcpy(text, "Anweisung ""break"" außerhalb einer Schleife");
+ if ( num == TX_LABEL ) strcpy(text, "Ein Label kann nur vor den Anweisungen ""for"", ""while"", ""do"" oder ""switch"" vorkommen");
+ if ( num == TX_NOLABEL ) strcpy(text, "Dieses Label existiert nicht");
+ if ( num == TX_NOCASE ) strcpy(text, "Es fehlt eine Anweisung ""case""");
+ if ( num == TX_BADNUM ) strcpy(text, "Es fehlt eine Zahl");
+ if ( num == TX_VOID ) strcpy(text, "Parameter void");
+ if ( num == TX_NOTYP ) strcpy(text, "Hier muss ein Variablentyp stehen");
+ if ( num == TX_NOVAR ) strcpy(text, "Es fehlt der Name einer Variable");
+ if ( num == TX_NOFONC ) strcpy(text, "Hier muss der Name der Funktion stehen");
+ if ( num == TX_OVERPARAM ) strcpy(text, "Zu viele Parameter");
+ if ( num == TX_REDEF ) strcpy(text, "Diese Funktion gibt es schon");
+ if ( num == TX_LOWPARAM ) strcpy(text, "Nicht genug Parameter");
+ if ( num == TX_BADPARAM ) strcpy(text, "Keine Funktion mit diesem Namen verträgt Parameter diesen Typs");
+ if ( num == TX_NUMPARAM ) strcpy(text, "Keine Funktion mit diesem Namen verträgt diese Anzahl Parameter");
+ if ( num == TX_NOITEM ) strcpy(text, "Dieses Element gibt es nicht in dieser Klasse");
+ if ( num == TX_DOT ) strcpy(text, "Das Objekt ist nicht eine Instanz einer Klasse");
+ if ( num == TX_NOCONST ) strcpy(text, "Es gibt keinen geeigneten Konstruktor");
+ if ( num == TX_REDEFCLASS ) strcpy(text, "Diese Klasse gibt es schon");
+ if ( num == TX_CLBRK ) strcpy(text, "Es fehlt eine geschlossene eckige Klammer "" ] """);
+ if ( num == TX_RESERVED ) strcpy(text, "Dieses Wort ist reserviert");
+ if ( num == TX_BADNEW ) strcpy(text, "Falsche Argumente für ""new""");
+ if ( num == TX_OPBRK ) strcpy(text, "Es fehlt eine offene eckige Klammer "" [ """);
+ if ( num == TX_BADSTRING ) strcpy(text, "Hier wird eine Zeichenkette erwartet");
+ if ( num == TX_BADINDEX ) strcpy(text, "Falscher Typ für einen Index");
+ if ( num == TX_PRIVATE ) strcpy(text, "Geschütztes Element (private)");
+ if ( num == TX_NOPUBLIC ) strcpy(text, "Hier muss das Wort ""public"" stehen");
+ if ( num == TX_DIVZERO ) strcpy(text, "Teilung durch Null");
+ if ( num == TX_NOTINIT ) strcpy(text, "Der Wert dieser Variable wurde nicht definiert");
+ if ( num == TX_BADTHROW ) strcpy(text, "Negativer Wert ungeeignet für Anweisung ""throw""");
+ if ( num == TX_NORETVAL ) strcpy(text, "Die Funktion hat kein Ergebnis zurückgegeben");
+ if ( num == TX_NORUN ) strcpy(text, "Keine Funktion wird ausgeführt");
+ if ( num == TX_NOCALL ) strcpy(text, "Die aufgerufene Funktion existiert nicht");
+ if ( num == TX_NOCLASS ) strcpy(text, "Diese Klasse existiert nicht");
+ if ( num == TX_NULLPT ) strcpy(text, "Das Objekt existiert nicht");
+ if ( num == TX_OPNAN ) strcpy(text, "Operation mit dem Wert ""nan""");
+ if ( num == TX_OUTARRAY ) strcpy(text, "Zugriff im Array außerhalb der Grenzen");
+ if ( num == TX_STACKOVER ) strcpy(text, "Stack overflow");
+ if ( num == TX_DELETEDPT ) strcpy(text, "Objekt nicht verfügbar");
+ if ( num == TX_FILEOPEN ) strcpy(text, "Die Datei kann nicht geöffnet werden");
+ if ( num == TX_NOTOPEN ) strcpy(text, "Die Datei wurde nicht geöffnet");
+ if ( num == TX_ERRREAD ) strcpy(text, "Fehler beim Lesezugriff");
+ if ( num == TX_ERRWRITE ) strcpy(text, "Fehler beim Schreibzugriff");
+ }
+
+ if ( type == RES_KEY )
+ {
+ if ( num == 0 ) strcpy(text, "< keine >");
+ if ( num == VK_LEFT ) strcpy(text, "Pfeiltaste links");
+ if ( num == VK_RIGHT ) strcpy(text, "Pfeiltaste rechts");
+ if ( num == VK_UP ) strcpy(text, "Pfeil nach oben");
+ if ( num == VK_DOWN ) strcpy(text, "Pfeil nach unten");
+ if ( num == VK_CANCEL ) strcpy(text, "Ctrl-Break");
+ if ( num == VK_BACK ) strcpy(text, "<--");
+ if ( num == VK_TAB ) strcpy(text, "Tab");
+ if ( num == VK_CLEAR ) strcpy(text, "Clear");
+ if ( num == VK_RETURN ) strcpy(text, "Eingabe");
+ if ( num == VK_SHIFT ) strcpy(text, "Shift");
+ if ( num == VK_CONTROL ) strcpy(text, "Ctrl");
+ if ( num == VK_MENU ) strcpy(text, "Alt");
+ if ( num == VK_PAUSE ) strcpy(text, "Pause");
+ if ( num == VK_CAPITAL ) strcpy(text, "Caps Lock");
+ if ( num == VK_ESCAPE ) strcpy(text, "Esc");
+ if ( num == VK_SPACE ) strcpy(text, "Leertaste");
+ if ( num == VK_PRIOR ) strcpy(text, "Page Up");
+ if ( num == VK_NEXT ) strcpy(text, "Page Down");
+ if ( num == VK_END ) strcpy(text, "End");
+ if ( num == VK_HOME ) strcpy(text, "Home");
+ if ( num == VK_SELECT ) strcpy(text, "Select");
+ if ( num == VK_EXECUTE ) strcpy(text, "Execute");
+ if ( num == VK_SNAPSHOT ) strcpy(text, "Print Scrn");
+ if ( num == VK_INSERT ) strcpy(text, "Insert");
+ if ( num == VK_DELETE ) strcpy(text, "Delete");
+ if ( num == VK_HELP ) strcpy(text, "Help");
+ if ( num == VK_LWIN ) strcpy(text, "Left Windows");
+ if ( num == VK_RWIN ) strcpy(text, "Right Windows");
+ if ( num == VK_APPS ) strcpy(text, "Application key");
+ if ( num == VK_NUMPAD0 ) strcpy(text, "NumPad 0");
+ if ( num == VK_NUMPAD1 ) strcpy(text, "NumPad 1");
+ if ( num == VK_NUMPAD2 ) strcpy(text, "NumPad 2");
+ if ( num == VK_NUMPAD3 ) strcpy(text, "NumPad 3");
+ if ( num == VK_NUMPAD4 ) strcpy(text, "NumPad 4");
+ if ( num == VK_NUMPAD5 ) strcpy(text, "NumPad 5");
+ if ( num == VK_NUMPAD6 ) strcpy(text, "NumPad 6");
+ if ( num == VK_NUMPAD7 ) strcpy(text, "NumPad 7");
+ if ( num == VK_NUMPAD8 ) strcpy(text, "NumPad 8");
+ if ( num == VK_NUMPAD9 ) strcpy(text, "NumPad 9");
+ if ( num == VK_MULTIPLY ) strcpy(text, "NumPad *");
+ if ( num == VK_ADD ) strcpy(text, "NumPad +");
+ if ( num == VK_SEPARATOR ) strcpy(text, "NumPad sep");
+ if ( num == VK_SUBTRACT ) strcpy(text, "NumPad -");
+ if ( num == VK_DECIMAL ) strcpy(text, "NumPad .");
+ if ( num == VK_DIVIDE ) strcpy(text, "NumPad /");
+ if ( num == VK_F1 ) strcpy(text, "F1");
+ if ( num == VK_F2 ) strcpy(text, "F2");
+ if ( num == VK_F3 ) strcpy(text, "F3");
+ if ( num == VK_F4 ) strcpy(text, "F4");
+ if ( num == VK_F5 ) strcpy(text, "F5");
+ if ( num == VK_F6 ) strcpy(text, "F6");
+ if ( num == VK_F7 ) strcpy(text, "F7");
+ if ( num == VK_F8 ) strcpy(text, "F8");
+ if ( num == VK_F9 ) strcpy(text, "F9");
+ if ( num == VK_F10 ) strcpy(text, "F10");
+ if ( num == VK_F11 ) strcpy(text, "F11");
+ if ( num == VK_F12 ) strcpy(text, "F12");
+ if ( num == VK_F13 ) strcpy(text, "F13");
+ if ( num == VK_F14 ) strcpy(text, "F14");
+ if ( num == VK_F15 ) strcpy(text, "F15");
+ if ( num == VK_F16 ) strcpy(text, "F16");
+ if ( num == VK_F17 ) strcpy(text, "F17");
+ if ( num == VK_F18 ) strcpy(text, "F18");
+ if ( num == VK_F19 ) strcpy(text, "F19");
+ if ( num == VK_F20 ) strcpy(text, "F20");
+ if ( num == VK_NUMLOCK ) strcpy(text, "Num Lock");
+ if ( num == VK_SCROLL ) strcpy(text, "Scroll");
+ if ( num == VK_ATTN ) strcpy(text, "Attn");
+ if ( num == VK_CRSEL ) strcpy(text, "CrSel");
+ if ( num == VK_EXSEL ) strcpy(text, "ExSel");
+ if ( num == VK_EREOF ) strcpy(text, "Erase EOF");
+ if ( num == VK_PLAY ) strcpy(text, "Play");
+ if ( num == VK_ZOOM ) strcpy(text, "Zoom");
+ if ( num == VK_PA1 ) strcpy(text, "PA1");
+ if ( num == VK_OEM_CLEAR ) strcpy(text, "Clear");
+ if ( num == VK_BUTTON1 ) strcpy(text, "Knopf 1");
+ if ( num == VK_BUTTON2 ) strcpy(text, "Knopf 2");
+ if ( num == VK_BUTTON3 ) strcpy(text, "Knopf 3");
+ if ( num == VK_BUTTON4 ) strcpy(text, "Knopf 4");
+ if ( num == VK_BUTTON5 ) strcpy(text, "Knopf 5");
+ if ( num == VK_BUTTON6 ) strcpy(text, "Knopf 6");
+ if ( num == VK_BUTTON7 ) strcpy(text, "Knopf 7");
+ if ( num == VK_BUTTON8 ) strcpy(text, "Knopf 8");
+ if ( num == VK_BUTTON9 ) strcpy(text, "Knopf 9");
+ if ( num == VK_BUTTON10 ) strcpy(text, "Knopf 10");
+ if ( num == VK_BUTTON11 ) strcpy(text, "Knopf 11");
+ if ( num == VK_BUTTON12 ) strcpy(text, "Knopf 12");
+ if ( num == VK_BUTTON13 ) strcpy(text, "Knopf 13");
+ if ( num == VK_BUTTON14 ) strcpy(text, "Knopf 14");
+ if ( num == VK_BUTTON15 ) strcpy(text, "Knopf 15");
+ if ( num == VK_BUTTON16 ) strcpy(text, "Knopf 16");
+ if ( num == VK_BUTTON17 ) strcpy(text, "Knopf 17");
+ if ( num == VK_BUTTON18 ) strcpy(text, "Knopf 18");
+ if ( num == VK_BUTTON19 ) strcpy(text, "Knopf 19");
+ if ( num == VK_BUTTON20 ) strcpy(text, "Knopf 20");
+ if ( num == VK_BUTTON21 ) strcpy(text, "Knopf 21");
+ if ( num == VK_BUTTON22 ) strcpy(text, "Knopf 22");
+ if ( num == VK_BUTTON23 ) strcpy(text, "Knopf 23");
+ if ( num == VK_BUTTON24 ) strcpy(text, "Knopf 24");
+ if ( num == VK_BUTTON25 ) strcpy(text, "Knopf 25");
+ if ( num == VK_BUTTON26 ) strcpy(text, "Knopf 26");
+ if ( num == VK_BUTTON27 ) strcpy(text, "Knopf 27");
+ if ( num == VK_BUTTON28 ) strcpy(text, "Knopf 28");
+ if ( num == VK_BUTTON29 ) strcpy(text, "Knopf 29");
+ if ( num == VK_BUTTON30 ) strcpy(text, "Knopf 30");
+ if ( num == VK_BUTTON31 ) strcpy(text, "Knopf 31");
+ if ( num == VK_BUTTON32 ) strcpy(text, "Knopf 32");
+ if ( num == VK_WHEELUP ) strcpy(text, "Mausrad nach vorne");
+ if ( num == VK_WHEELDOWN ) strcpy(text, "Mausrad zurück");
+ }
+#endif
+
+#if _POLISH
+ if ( type == RES_TEXT )
+ {
+ #if _FULL
+ if ( num == RT_VERSION_ID ) strcpy(text, "Wersja 1.18 /pl");
+ #endif
+ #if _NET
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A 1.18");
+ #endif
+ #if _SCHOOL & _EDU
+ #if _TEEN
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen EDU 1.18");
+ #else
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A EDU 1.18");
+ #endif
+ #endif
+ #if _SCHOOL & _PERSO
+ #if _TEEN
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen PERSO 1.18");
+ #else
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A PERSO 1.18");
+ #endif
+ #endif
+ #if _SCHOOL & _CEEBOTDEMO
+ #if _TEEN
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-Teen DEMO 1.18");
+ #else
+ if ( num == RT_VERSION_ID ) strcpy(text, "CeeBot-A DEMO 1.18");
+ #endif
+ #endif
+ #if _DEMO
+ if ( num == RT_VERSION_ID ) strcpy(text, "Demo 1.18 /pl");
+ #endif
+ if ( num == RT_DISINFO_TITLE ) strcpy(text, "SatCom");
+ if ( num == RT_WINDOW_MAXIMIZED ) strcpy(text, "Powiêksz");
+ if ( num == RT_WINDOW_MINIMIZED ) strcpy(text, "Pomniejsz");
+ if ( num == RT_WINDOW_STANDARD ) strcpy(text, "Normalna wielkoϾ");
+ if ( num == RT_WINDOW_CLOSE ) strcpy(text, "Zamknij");
+
+ if ( num == RT_STUDIO_TITLE ) strcpy(text, "Edytor programu");
+ if ( num == RT_SCRIPT_NEW ) strcpy(text, "Nowy");
+ if ( num == RT_NAME_DEFAULT ) strcpy(text, "Gracz");
+ if ( num == RT_IO_NEW ) strcpy(text, "Nowy ...");
+ if ( num == RT_KEY_OR ) strcpy(text, " lub ");
+
+#if _NEWLOOK
+ if ( num == RT_TITLE_BASE ) strcpy(text, "CeeBot");
+ if ( num == RT_TITLE_INIT ) strcpy(text, "CeeBot");
+#else
+ if ( num == RT_TITLE_BASE ) strcpy(text, "COLOBOT");
+ if ( num == RT_TITLE_INIT ) strcpy(text, "COLOBOT");
+#endif
+ if ( num == RT_TITLE_TRAINER ) strcpy(text, "Æwiczenia programistyczne");
+ if ( num == RT_TITLE_DEFI ) strcpy(text, "Wyzwania");
+ if ( num == RT_TITLE_MISSION ) strcpy(text, "Misje");
+ if ( num == RT_TITLE_FREE ) strcpy(text, "Swobodna gra");
+ if ( num == RT_TITLE_TEEN ) strcpy(text, "Swobodna gra");
+ if ( num == RT_TITLE_USER ) strcpy(text, "Poziomy u¿ytkownika");
+ if ( num == RT_TITLE_PROTO ) strcpy(text, "Prototypy");
+ if ( num == RT_TITLE_SETUP ) strcpy(text, "Opcje");
+ if ( num == RT_TITLE_NAME ) strcpy(text, "Imiê gracza");
+ if ( num == RT_TITLE_PERSO ) strcpy(text, "Dostosuj wygl¹d");
+ if ( num == RT_TITLE_WRITE ) strcpy(text, "Zapisz bie¿¹c¹ misjê");
+ if ( num == RT_TITLE_READ ) strcpy(text, "Wczytaj zapisan¹ misjê");
+
+ if ( num == RT_PLAY_CHAPt ) strcpy(text, " Rozdzia³y:");
+ if ( num == RT_PLAY_CHAPd ) strcpy(text, " Rozdzia³y:");
+ if ( num == RT_PLAY_CHAPm ) strcpy(text, " Planety:");
+ if ( num == RT_PLAY_CHAPf ) strcpy(text, " Planety:");
+ if ( num == RT_PLAY_CHAPu ) strcpy(text, " Poziomy u¿ytkownika:");
+ if ( num == RT_PLAY_CHAPp ) strcpy(text, " Planety:");
+ if ( num == RT_PLAY_CHAPte ) strcpy(text, " Planety:");
+ if ( num == RT_PLAY_LISTt ) strcpy(text, " Æwiczenia w tym rozdziale:");
+ if ( num == RT_PLAY_LISTd ) strcpy(text, " Wyzwania w tym rozdziale:");
+ if ( num == RT_PLAY_LISTm ) strcpy(text, " Misje na tej planecie:");
+ if ( num == RT_PLAY_LISTf ) strcpy(text, " Swobodna gra na tej planecie:");
+ if ( num == RT_PLAY_LISTu ) strcpy(text, " Misje na tym poziomie:");
+ if ( num == RT_PLAY_LISTp ) strcpy(text, " Prototypy na tej planecie:");
+ if ( num == RT_PLAY_LISTk ) strcpy(text, " Prototypy na tej planecie:");
+ if ( num == RT_PLAY_RESUME ) strcpy(text, " Streszczenie:");
+
+ if ( num == RT_SETUP_DEVICE ) strcpy(text, " Sterowniki:");
+ if ( num == RT_SETUP_MODE ) strcpy(text, " RozdzielczoϾ:");
+ if ( num == RT_SETUP_KEY1 ) strcpy(text, "1) Najpierw kliknij klawisz, który chcesz przedefiniowaæ.");
+ if ( num == RT_SETUP_KEY2 ) strcpy(text, "2) Nastêpnie naciœnij klawisz, którego chcesz u¿ywaæ.");
+
+ if ( num == RT_PERSO_FACE ) strcpy(text, "Rodzaj twarzy:");
+ if ( num == RT_PERSO_GLASSES ) strcpy(text, "Okulary:");
+ if ( num == RT_PERSO_HAIR ) strcpy(text, "Kolor w³osów:");
+ if ( num == RT_PERSO_COMBI ) strcpy(text, "Kolor skafandra:");
+ if ( num == RT_PERSO_BAND ) strcpy(text, "Kolor pasków:");
+
+#if _NEWLOOK
+ if ( num == RT_DIALOG_TITLE ) strcpy(text, "CeeBot");
+ if ( num == RT_DIALOG_QUIT ) strcpy(text, "Czy na pewno chcesz opuœciæ grê CeeBot?");
+ if ( num == RT_DIALOG_YESQUIT ) strcpy(text, "Zakoñcz\\Koñczy grê CeeBot");
+#else
+ if ( num == RT_DIALOG_TITLE ) strcpy(text, "COLOBOT");
+ if ( num == RT_DIALOG_QUIT ) strcpy(text, "Czy na pewno chcesz opuœciæ grê COLOBOT?");
+ if ( num == RT_DIALOG_YESQUIT ) strcpy(text, "Zakoñcz\\Koñczy grê COLOBOT");
+#endif
+ if ( num == RT_DIALOG_ABORT ) strcpy(text, "Opuœciæ misjê?");
+ if ( num == RT_DIALOG_YES ) strcpy(text, "Przerwij\\Przerywa bie¿¹c¹ misjê");
+ if ( num == RT_DIALOG_NO ) strcpy(text, "Kontynuuj\\Kontynuuje bie¿¹c¹ misjê");
+ if ( num == RT_DIALOG_NOQUIT ) strcpy(text, "Kontynuuj\\Kontynuuje grê");
+ if ( num == RT_DIALOG_DELOBJ ) strcpy(text, "Czy na pewno chcesz zniszczyæ zaznaczony budynek?");
+ if ( num == RT_DIALOG_DELGAME ) strcpy(text, "Czy na pewno chcesz skasowaæ zapisane gry gracza %s? ");
+ if ( num == RT_DIALOG_YESDEL ) strcpy(text, "Usuñ");
+ if ( num == RT_DIALOG_NODEL ) strcpy(text, "Anuluj");
+ if ( num == RT_DIALOG_LOADING ) strcpy(text, "WCZYTYWANIE");
+
+ if ( num == RT_STUDIO_LISTTT ) strcpy(text, "Skróty klawiszowe (\\key cbot;)");
+ if ( num == RT_STUDIO_COMPOK ) strcpy(text, "Program skompilowany (0 b³êdów)");
+ if ( num == RT_STUDIO_PROGSTOP ) strcpy(text, "Program zakoñczony");
+
+ if ( num == RT_SATCOM_LIST ) strcpy(text, "\\b;Lista obiektów\n");
+ if ( num == RT_SATCOM_BOT ) strcpy(text, "\\b;Roboty\n");
+ if ( num == RT_SATCOM_BUILDING ) strcpy(text, "\\b;Budynki\n");
+ if ( num == RT_SATCOM_FRET ) strcpy(text, "\\b;Obiekty ruchome\n");
+ if ( num == RT_SATCOM_ALIEN ) strcpy(text, "\\b;Obcy\n");
+ if ( num == RT_SATCOM_NULL ) strcpy(text, "\\c; (brak)\\n;\n");
+ if ( num == RT_SATCOM_ERROR1 ) strcpy(text, "\\b;B³¹d\n");
+ if ( num == RT_SATCOM_ERROR2 ) strcpy(text, "Lista jest dostêpna jedynie gdy dzia³a \\l;stacja radarowa\\u object\\radar;.\n");
+
+ if ( num == RT_IO_OPEN ) strcpy(text, "Otwórz");
+ if ( num == RT_IO_SAVE ) strcpy(text, "Zapisz");
+ if ( num == RT_IO_LIST ) strcpy(text, "Folder: %s");
+ if ( num == RT_IO_NAME ) strcpy(text, "Nazwa:");
+ if ( num == RT_IO_DIR ) strcpy(text, "Folder:");
+ if ( num == RT_IO_PRIVATE ) strcpy(text, "Prywatny\\Folder prywatny");
+ if ( num == RT_IO_PUBLIC ) strcpy(text, "Publiczny\\Folder ogólnodostêpny");
+
+ if ( num == RT_GENERIC_DEV1 ) strcpy(text, "Twórcy:");
+ if ( num == RT_GENERIC_DEV2 ) strcpy(text, "www.epsitec.com");
+ if ( num == RT_GENERIC_EDIT1 ) strcpy(text, "Wersja polska wydana przez:");
+ if ( num == RT_GENERIC_EDIT2 ) strcpy(text, "www.manta.com.pl");
+ if ( num == RT_GENERIC_EDIT1 ) strcpy(text, " ");
+ if ( num == RT_GENERIC_EDIT2 ) strcpy(text, " ");
+
+ if ( num == RT_INTERFACE_REC ) strcpy(text, "Recorder");
+ }
+
+ if ( type == RES_EVENT )
+ {
+ if ( num == EVENT_BUTTON_OK ) strcpy(text, "OK");
+ if ( num == EVENT_BUTTON_CANCEL ) strcpy(text, "Anuluj");
+ if ( num == EVENT_BUTTON_NEXT ) strcpy(text, "Nastêpny");
+ if ( num == EVENT_BUTTON_PREV ) strcpy(text, "Poprzedni");
+ if ( num == EVENT_BUTTON_QUIT ) strcpy(text, "Menu (\\key quit;)");
+
+ if ( num == EVENT_DIALOG_OK ) strcpy(text, "OK");
+ if ( num == EVENT_DIALOG_CANCEL ) strcpy(text, "Anuluj");
+
+ if ( num == EVENT_INTERFACE_TRAINER) strcpy(text, "Æwiczenia\\Æwiczenia programistyczne");
+ if ( num == EVENT_INTERFACE_DEFI ) strcpy(text, "Wyzwania\\Wyzwania programistyczne");
+ if ( num == EVENT_INTERFACE_MISSION) strcpy(text, "Misje\\Wybierz misjê");
+ if ( num == EVENT_INTERFACE_FREE ) strcpy(text, "Swobodna gra\\Swobodna gra bez konkretnych celów");
+ if ( num == EVENT_INTERFACE_TEEN ) strcpy(text, "Swobodna gra\\Swobodna gra bez konkretnych celów");
+ if ( num == EVENT_INTERFACE_USER ) strcpy(text, "Poziomy\\Poziomy u¿ytkownika");
+ if ( num == EVENT_INTERFACE_PROTO ) strcpy(text, "Prototypy\\Prototypy w trakcie rozwijania");
+ if ( num == EVENT_INTERFACE_NAME ) strcpy(text, "Nowy gracz\\Wybierz imiê gracza");
+ if ( num == EVENT_INTERFACE_SETUP ) strcpy(text, "Opcje\\Preferencje");
+ if ( num == EVENT_INTERFACE_AGAIN ) strcpy(text, "Uruchom ponownie\\Uruchamia ponownie misjê od pocz¹tku");
+ if ( num == EVENT_INTERFACE_WRITE ) strcpy(text, "Zapisz\\Zapisuje bie¿¹c¹ misjê");
+ if ( num == EVENT_INTERFACE_READ ) strcpy(text, "Wczytaj\\Wczytuje zapisan¹ misjê");
+#if _NEWLOOK
+ if ( num == EVENT_INTERFACE_ABORT ) strcpy(text, "\\Powróæ do gry CeeBot");
+ if ( num == EVENT_INTERFACE_QUIT ) strcpy(text, "Zakoñcz\\Koñczy grê CeeBot");
+#else
+ if ( num == EVENT_INTERFACE_ABORT ) strcpy(text, "\\Powróæ do gry COLOBOT");
+ if ( num == EVENT_INTERFACE_QUIT ) strcpy(text, "Zakoñcz\\Koñczy grê COLOBOT");
+#endif
+ if ( num == EVENT_INTERFACE_BACK ) strcpy(text, "<< Wstecz \\Wraca do poprzedniego ekranu");
+ if ( num == EVENT_INTERFACE_PLAY ) strcpy(text, "Graj\\Rozpoczyna misjê!");
+ if ( num == EVENT_INTERFACE_SETUPd ) strcpy(text, "Urz¹dzenie\\Ustawienia sterownika i rozdzielczoœci");
+ if ( num == EVENT_INTERFACE_SETUPg ) strcpy(text, "Grafika\\Ustawienia grafiki");
+ if ( num == EVENT_INTERFACE_SETUPp ) strcpy(text, "Gra\\Ustawienia gry");
+ if ( num == EVENT_INTERFACE_SETUPc ) strcpy(text, "Sterowanie\\Ustawienia klawiatury, joysticka i myszy");
+ if ( num == EVENT_INTERFACE_SETUPs ) strcpy(text, "DŸwiêk\\G³oœnoœæ muzyki i dŸwiêków gry");
+ if ( num == EVENT_INTERFACE_DEVICE ) strcpy(text, "Jednostka");
+ if ( num == EVENT_INTERFACE_RESOL ) strcpy(text, "RozdzielczoϾ");
+ if ( num == EVENT_INTERFACE_FULL ) strcpy(text, "Pe³ny ekran\\Pe³ny ekran lub tryb okna");
+ if ( num == EVENT_INTERFACE_APPLY ) strcpy(text, "Zastosuj zmiany\\Aktywuje zmienione ustawienia");
+
+ if ( num == EVENT_INTERFACE_TOTO ) strcpy(text, "Robbie\\Twój asystent");
+ if ( num == EVENT_INTERFACE_SHADOW ) strcpy(text, "Cienie\\Cienie na ziemi");
+ if ( num == EVENT_INTERFACE_GROUND ) strcpy(text, "Znaki na ziemi\\Znaki na ziemi");
+ if ( num == EVENT_INTERFACE_DIRTY ) strcpy(text, "Kurz\\Kurz i bród na robotach i budynkach");
+ if ( num == EVENT_INTERFACE_FOG ) strcpy(text, "Mg³a\\Mg³a");
+ if ( num == EVENT_INTERFACE_LENS ) strcpy(text, "Promienie s³oneczne\\Promienie s³oneczne na niebie");
+ if ( num == EVENT_INTERFACE_SKY ) strcpy(text, "Niebo\\Chmury i mg³awice");
+ if ( num == EVENT_INTERFACE_PLANET ) strcpy(text, "Planety i gwiazdy\\Obiekty astronomiczne na niebie");
+ if ( num == EVENT_INTERFACE_LIGHT ) strcpy(text, "Dynamiczne oœwietlenie\\Ruchome Ÿród³a œwiat³a");
+ if ( num == EVENT_INTERFACE_PARTI ) strcpy(text, "Liczba cz¹stek\\Wybuchy, kurz, odbicia, itp.");
+ if ( num == EVENT_INTERFACE_CLIP ) strcpy(text, "G³êbokoœæ pola\\Maksymalna widocznoœæ");
+ if ( num == EVENT_INTERFACE_DETAIL ) strcpy(text, "Szczegó³y\\Jakoœæ wizualna obiektów 3D");
+ if ( num == EVENT_INTERFACE_TEXTURE) strcpy(text, "Tekstury\\JakoϾ tekstur ");
+ if ( num == EVENT_INTERFACE_GADGET ) strcpy(text, "Iloœæ elementów dekoracyjnych \\Iloœæ elementów czysto dekoracyjnych");
+ if ( num == EVENT_INTERFACE_RAIN ) strcpy(text, "Cz¹stki w interfejsie\\Para i iskry z silników w interfejsie");
+ if ( num == EVENT_INTERFACE_GLINT ) strcpy(text, "Odbicia na przyciskach \\Œwiec¹ce przyciski");
+ if ( num == EVENT_INTERFACE_TOOLTIP) strcpy(text, "Dymki pomocy\\Wyjaœnia funkcje przycisków");
+ if ( num == EVENT_INTERFACE_MOVIES ) strcpy(text, "Sekwencje filmowe\\Filmy przed rozpoczêciem i na zakoñczenie misji");
+ if ( num == EVENT_INTERFACE_NICERST) strcpy(text, "Koñcowy film\\Film na zakoñczenie æwiczeñ");
+ if ( num == EVENT_INTERFACE_HIMSELF) strcpy(text, "Przyjacielski ogieñ\\W³asne strza³y uszkadzaj¹ Twoje obiekty");
+ if ( num == EVENT_INTERFACE_SCROLL ) strcpy(text, "Przewijanie\\Ekran jest przewijany gdy mysz dotknie prawej lub lewej jego krawêdzi");
+ if ( num == EVENT_INTERFACE_INVERTX) strcpy(text, "Odwrócenie myszy X\\Odwrócenie kierunków przewijania w poziomie");
+ if ( num == EVENT_INTERFACE_INVERTY) strcpy(text, "Odwrócenie myszy Y\\Odwrócenie kierunków przewijania w pionie");
+ if ( num == EVENT_INTERFACE_EFFECT ) strcpy(text, "Wstrz¹sy przy wybuchach\\Ekran trzêsie siê podczas wybuchów");
+ if ( num == EVENT_INTERFACE_MOUSE ) strcpy(text, "Cieñ kursora myszy\\Dodaje cieñ kursorowi myszy");
+ if ( num == EVENT_INTERFACE_EDITMODE) strcpy(text, "Automatyczne wciêcia\\Automatyczne wciêcia podczas edycji programu");
+ if ( num == EVENT_INTERFACE_EDITVALUE)strcpy(text, "Du¿e wciêcie\\2 lub 4 spacje wciêcia na ka¿dy poziom zdefiniowany przez klamry");
+ if ( num == EVENT_INTERFACE_SOLUCE4) strcpy(text, "Accès aux solutions\\Programme \"4: Solution\" dans les exercices");
+
+ if ( num == EVENT_INTERFACE_KDEF ) strcpy(text, "Standardowa kontrola\\Standardowe klawisze funkcyjne");
+ if ( num == EVENT_INTERFACE_KLEFT ) strcpy(text, "Skrêæ w lewo\\Obraca robota w lewo");
+ if ( num == EVENT_INTERFACE_KRIGHT ) strcpy(text, "Obróæ w prawo\\Obraca robota w prawo");
+ if ( num == EVENT_INTERFACE_KUP ) strcpy(text, "Naprzód\\Porusza do przodu");
+ if ( num == EVENT_INTERFACE_KDOWN ) strcpy(text, "Wstecz\\Porusza do ty³u");
+ if ( num == EVENT_INTERFACE_KGUP ) strcpy(text, "W górê\\Zwiêksza moc silnika");
+ if ( num == EVENT_INTERFACE_KGDOWN ) strcpy(text, "W dó³\\Zmniejsza moc silnika");
+ if ( num == EVENT_INTERFACE_KCAMERA) strcpy(text, "Zmieñ kamerê\\Prze³¹cza pomiêdzy kamer¹ pok³adow¹ i œledz¹c¹");
+ if ( num == EVENT_INTERFACE_KDESEL ) strcpy(text, "Poprzedni obiekt\\Zaznacz poprzedni obiekt");
+ if ( num == EVENT_INTERFACE_KACTION) strcpy(text, "Standardowa akcja\\Standardowa akcja robota (podnieœ/upuœæ, strzelaj, szukaj, itp.)");
+ if ( num == EVENT_INTERFACE_KNEAR ) strcpy(text, "Kamera bli¿ej\\Przybli¿a kamerê");
+ if ( num == EVENT_INTERFACE_KAWAY ) strcpy(text, "Kamera dalej\\Oddala kamerê");
+ if ( num == EVENT_INTERFACE_KNEXT ) strcpy(text, "Nastêpny obiekt\\Zaznacza nastêpny obiekt");
+ if ( num == EVENT_INTERFACE_KHUMAN ) strcpy(text, "Zaznacz astronautê\\Zaznacza astronautê");
+ if ( num == EVENT_INTERFACE_KQUIT ) strcpy(text, "Zakoñcz\\Koñczy bie¿¹c¹ misjê lub æwiczenie");
+ if ( num == EVENT_INTERFACE_KHELP ) strcpy(text, "Rozkazy\\Pokazuje rozkazy dotycz¹ce bie¿¹cej misji");
+ if ( num == EVENT_INTERFACE_KPROG ) strcpy(text, "Podrêcznik programowania\\Dostarcza szczegó³ow¹ pomoc w programowaniu");
+ if ( num == EVENT_INTERFACE_KCBOT ) strcpy(text, "Pomoc dot. s³ów kluczowych\\Dok³adniejsza pomoc na temat s³ów kluczowych");
+ if ( num == EVENT_INTERFACE_KVISIT ) strcpy(text, "Miejsce nadania wiadomoœci\\Pokazuje sk¹d zosta³a wys³ana ostatnia wiadomoœæ");
+ if ( num == EVENT_INTERFACE_KSPEED10) strcpy(text, "Prêdkoœæ 1,0x\\Prêdkoœæ normalna");
+ if ( num == EVENT_INTERFACE_KSPEED15) strcpy(text, "Prêdkoœæ 1,5x\\1,5 raza szybciej");
+ if ( num == EVENT_INTERFACE_KSPEED20) strcpy(text, "Prêdkoœæ 2,0x\\Dwa razy szybciej");
+ if ( num == EVENT_INTERFACE_KSPEED30) strcpy(text, "Prêdkoœæ 3,0x\\Trzy razy szybciej");
+
+ if ( num == EVENT_INTERFACE_VOLSOUND) strcpy(text, "Efekty dŸwiêkowe:\\G³oœnoœæ silników, g³osów, strza³ów, itp.");
+ if ( num == EVENT_INTERFACE_VOLMUSIC) strcpy(text, "Muzyka w tle :\\G³oœnoœæ œcie¿ek dŸwiêkowych z p³yty CD");
+ if ( num == EVENT_INTERFACE_SOUND3D) strcpy(text, "DŸwiêk 3D\\Przestrzenne pozycjonowanie dŸwiêków");
+
+ if ( num == EVENT_INTERFACE_MIN ) strcpy(text, "Najni¿sza\\Minimalna jakoœæ grafiki (najwy¿sza czêstotliwoœæ odœwie¿ania)");
+ if ( num == EVENT_INTERFACE_NORM ) strcpy(text, "Normalna\\Normalna jakoϾ grafiki");
+ if ( num == EVENT_INTERFACE_MAX ) strcpy(text, "Najwy¿sza\\Maksymalna jakoœæ grafiki (najni¿sza czêstotliwoœæ odœwie¿ania)");
+
+ if ( num == EVENT_INTERFACE_SILENT ) strcpy(text, "Cisza\\Brak dŸwiêków");
+ if ( num == EVENT_INTERFACE_NOISY ) strcpy(text, "Normalne\\Normalna g³oœnoœæ dŸwiêków");
+
+ if ( num == EVENT_INTERFACE_JOYSTICK) strcpy(text, "U¿ywaj joysticka\\Joystick lub klawiatura");
+ if ( num == EVENT_INTERFACE_SOLUCE ) strcpy(text, "Dostêp do rozwi¹zania\\Pokazuje rozwi¹zanie (szczegó³owe instrukcje dotycz¹ce misji)");
+
+ if ( num == EVENT_INTERFACE_NEDIT ) strcpy(text, "\\Nowe imiê gracza");
+ if ( num == EVENT_INTERFACE_NOK ) strcpy(text, "OK\\Wybiera zaznaczonego gracza");
+ if ( num == EVENT_INTERFACE_NCANCEL) strcpy(text, "Anuluj\\Zachowuje bie¿¹ce imiê gracza");
+ if ( num == EVENT_INTERFACE_NDELETE) strcpy(text, "Usuñ gracza\\Usuwa gracza z listy");
+ if ( num == EVENT_INTERFACE_NLABEL ) strcpy(text, "Imiê gracza");
+
+ if ( num == EVENT_INTERFACE_IOWRITE) strcpy(text, "Zapisz\\Zapisuje bie¿¹c¹ misjê");
+ if ( num == EVENT_INTERFACE_IOREAD ) strcpy(text, "Wczytaj\\Wczytuje zaznaczon¹ misjê");
+ if ( num == EVENT_INTERFACE_IOLIST ) strcpy(text, "Lista zapisanych misji");
+ if ( num == EVENT_INTERFACE_IOLABEL) strcpy(text, "Nazwa pliku:");
+ if ( num == EVENT_INTERFACE_IONAME ) strcpy(text, "Nazwa misji");
+ if ( num == EVENT_INTERFACE_IOIMAGE) strcpy(text, "Fotografia");
+ if ( num == EVENT_INTERFACE_IODELETE) strcpy(text, "Usuñ\\Usuwa zaznaczony plik");
+
+ if ( num == EVENT_INTERFACE_PERSO ) strcpy(text, "Wygl¹d\\Wybierz swoj¹ postaæ");
+ if ( num == EVENT_INTERFACE_POK ) strcpy(text, "OK");
+ if ( num == EVENT_INTERFACE_PCANCEL) strcpy(text, "Anuluj");
+ if ( num == EVENT_INTERFACE_PDEF ) strcpy(text, "Standardowe\\Standardowe ustawienia wygl¹du");
+ if ( num == EVENT_INTERFACE_PHEAD ) strcpy(text, "G³owa\\Twarz i w³osy");
+ if ( num == EVENT_INTERFACE_PBODY ) strcpy(text, "Skafander\\Skafander astronauty");
+ if ( num == EVENT_INTERFACE_PLROT ) strcpy(text, "\\Obróæ w lewo");
+ if ( num == EVENT_INTERFACE_PRROT ) strcpy(text, "\\Obróæ w prawo");
+ if ( num == EVENT_INTERFACE_PCRa ) strcpy(text, "Czerwony");
+ if ( num == EVENT_INTERFACE_PCGa ) strcpy(text, "Zielony");
+ if ( num == EVENT_INTERFACE_PCBa ) strcpy(text, "Niebieski");
+ if ( num == EVENT_INTERFACE_PCRb ) strcpy(text, "Czerwony");
+ if ( num == EVENT_INTERFACE_PCGb ) strcpy(text, "Zielony");
+ if ( num == EVENT_INTERFACE_PCBb ) strcpy(text, "Niebieski");
+ if ( num == EVENT_INTERFACE_PFACE1 ) strcpy(text, "\\Twarz 1");
+ if ( num == EVENT_INTERFACE_PFACE2 ) strcpy(text, "\\Twarz 4");
+ if ( num == EVENT_INTERFACE_PFACE3 ) strcpy(text, "\\Twarz 3");
+ if ( num == EVENT_INTERFACE_PFACE4 ) strcpy(text, "\\Twarz 2");
+ if ( num == EVENT_INTERFACE_PGLASS0) strcpy(text, "\\Bez okularów");
+ if ( num == EVENT_INTERFACE_PGLASS1) strcpy(text, "\\Okulary 1");
+ if ( num == EVENT_INTERFACE_PGLASS2) strcpy(text, "\\Okulary 2");
+ if ( num == EVENT_INTERFACE_PGLASS3) strcpy(text, "\\Okulary 3");
+ if ( num == EVENT_INTERFACE_PGLASS4) strcpy(text, "\\Okulary 4");
+ if ( num == EVENT_INTERFACE_PGLASS5) strcpy(text, "\\Okulary 5");
+
+ if ( num == EVENT_OBJECT_DESELECT ) strcpy(text, "Poprzednie zaznaczenie (\\key desel;)");
+ if ( num == EVENT_OBJECT_LEFT ) strcpy(text, "Skrêæ w lewo (\\key left;)");
+ if ( num == EVENT_OBJECT_RIGHT ) strcpy(text, "Skrêæ w prawo (\\key right;)");
+ if ( num == EVENT_OBJECT_UP ) strcpy(text, "Naprzód (\\key up;)");
+ if ( num == EVENT_OBJECT_DOWN ) strcpy(text, "Cofnij (\\key down;)");
+ if ( num == EVENT_OBJECT_GASUP ) strcpy(text, "Góra (\\key gup;)");
+ if ( num == EVENT_OBJECT_GASDOWN ) strcpy(text, "Dó³ (\\key gdown;)");
+ if ( num == EVENT_OBJECT_HTAKE ) strcpy(text, "Podnieœ lub upuœæ (\\key action;)");
+ if ( num == EVENT_OBJECT_MTAKE ) strcpy(text, "Podnieœ lub upuœæ (\\key action;)");
+ if ( num == EVENT_OBJECT_MFRONT ) strcpy(text, "..przed");
+ if ( num == EVENT_OBJECT_MBACK ) strcpy(text, "..za");
+ if ( num == EVENT_OBJECT_MPOWER ) strcpy(text, "..ogniwo elektryczne");
+ if ( num == EVENT_OBJECT_BHELP ) strcpy(text, "Rozkazy dotycz¹ce misji (\\key help;)");
+ if ( num == EVENT_OBJECT_BTAKEOFF ) strcpy(text, "Odleæ, aby zakoñczyæ misjê");
+ if ( num == EVENT_OBJECT_BDERRICK ) strcpy(text, "Zbuduj kopalniê");
+ if ( num == EVENT_OBJECT_BSTATION ) strcpy(text, "Zbuduj elektrowniê");
+ if ( num == EVENT_OBJECT_BFACTORY ) strcpy(text, "Zbuduj fabrykê robotów");
+ if ( num == EVENT_OBJECT_BREPAIR ) strcpy(text, "Zbuduj warsztat");
+ if ( num == EVENT_OBJECT_BCONVERT ) strcpy(text, "Zbuduj hutê");
+ if ( num == EVENT_OBJECT_BTOWER ) strcpy(text, "Zbuduj wie¿ê obronn¹");
+ if ( num == EVENT_OBJECT_BRESEARCH ) strcpy(text, "Zbuduj centrum badawcze");
+ if ( num == EVENT_OBJECT_BRADAR ) strcpy(text, "Zbuduj stacjê radarow¹");
+ if ( num == EVENT_OBJECT_BENERGY ) strcpy(text, "Zbuduj fabrykê ogniw elektrycznych");
+ if ( num == EVENT_OBJECT_BLABO ) strcpy(text, "Zbuduj laboratorium");
+ if ( num == EVENT_OBJECT_BNUCLEAR ) strcpy(text, "Zbuduj elektrowniê atomow¹");
+ if ( num == EVENT_OBJECT_BPARA ) strcpy(text, "Zbuduj odgromnik");
+ if ( num == EVENT_OBJECT_BINFO ) strcpy(text, "Zbuduj stacjê przekaŸnikow¹");
+ if ( num == EVENT_OBJECT_GFLAT ) strcpy(text, "Poka¿ czy teren jest p³aski");
+ if ( num == EVENT_OBJECT_FCREATE ) strcpy(text, "Postaw flagê");
+ if ( num == EVENT_OBJECT_FDELETE ) strcpy(text, "Usuñ flagê");
+ if ( num == EVENT_OBJECT_FCOLORb ) strcpy(text, "\\Niebieskie flagi");
+ if ( num == EVENT_OBJECT_FCOLORr ) strcpy(text, "\\Czerwone flagi");
+ if ( num == EVENT_OBJECT_FCOLORg ) strcpy(text, "\\Zielone flagi");
+ if ( num == EVENT_OBJECT_FCOLORy ) strcpy(text, "\\¯ó³te flagi");
+ if ( num == EVENT_OBJECT_FCOLORv ) strcpy(text, "\\Fioletowe flagi");
+ if ( num == EVENT_OBJECT_FACTORYfa ) strcpy(text, "Zbuduj transporter lataj¹cy");
+ if ( num == EVENT_OBJECT_FACTORYta ) strcpy(text, "Zbuduj transporter na g¹sienicach");
+ if ( num == EVENT_OBJECT_FACTORYwa ) strcpy(text, "Zbuduj transporter na ko³ach");
+ if ( num == EVENT_OBJECT_FACTORYia ) strcpy(text, "Zbuduj transporter na nogach");
+ if ( num == EVENT_OBJECT_FACTORYfc ) strcpy(text, "Zbuduj dzia³o lataj¹ce");
+ if ( num == EVENT_OBJECT_FACTORYtc ) strcpy(text, "Zbuduj dzia³o na g¹sienicach");
+ if ( num == EVENT_OBJECT_FACTORYwc ) strcpy(text, "Zbuduj dzia³o na ko³ach");
+ if ( num == EVENT_OBJECT_FACTORYic ) strcpy(text, "Zbuduj dzia³o na nogach");
+ if ( num == EVENT_OBJECT_FACTORYfi ) strcpy(text, "Zbuduj lataj¹ce dzia³o organiczne");
+ if ( num == EVENT_OBJECT_FACTORYti ) strcpy(text, "Zbuduj dzia³o organiczne na g¹sienicach");
+ if ( num == EVENT_OBJECT_FACTORYwi ) strcpy(text, "Zbuduj dzia³o organiczne na ko³ach");
+ if ( num == EVENT_OBJECT_FACTORYii ) strcpy(text, "Zbuduj dzia³o organiczne na nogach");
+ if ( num == EVENT_OBJECT_FACTORYfs ) strcpy(text, "Zbuduj szperacz lataj¹cy");
+ if ( num == EVENT_OBJECT_FACTORYts ) strcpy(text, "Zbuduj szperacz na g¹sienicach");
+ if ( num == EVENT_OBJECT_FACTORYws ) strcpy(text, "Zbuduj szperacz na ko³ach");
+ if ( num == EVENT_OBJECT_FACTORYis ) strcpy(text, "Zbuduj szperacz na nogach");
+ if ( num == EVENT_OBJECT_FACTORYrt ) strcpy(text, "Zbuduj robota uderzacza");
+ if ( num == EVENT_OBJECT_FACTORYrc ) strcpy(text, "Zbuduj dzia³o fazowe");
+ if ( num == EVENT_OBJECT_FACTORYrr ) strcpy(text, "Zbuduj robota recyklera");
+ if ( num == EVENT_OBJECT_FACTORYrs ) strcpy(text, "Zbuduj robota os³aniajacza");
+ if ( num == EVENT_OBJECT_FACTORYsa ) strcpy(text, "Zbuduj robota nurka");
+ if ( num == EVENT_OBJECT_RTANK ) strcpy(text, "Rozpocznij prace badawcze nad transporterem na g¹sienicach");
+ if ( num == EVENT_OBJECT_RFLY ) strcpy(text, "Rozpocznij prace badawcze nad transporterem lataj¹cym");
+ if ( num == EVENT_OBJECT_RTHUMP ) strcpy(text, "Rozpocznij prace badawcze nad robotem uderzaczem");
+ if ( num == EVENT_OBJECT_RCANON ) strcpy(text, "Rozpocznij prace badawcze nad dzia³em");
+ if ( num == EVENT_OBJECT_RTOWER ) strcpy(text, "Rozpocznij prace badawcze nad wie¿¹ obronn¹");
+ if ( num == EVENT_OBJECT_RPHAZER ) strcpy(text, "Rozpocznij prace badawcze nad dzia³em fazowym");
+ if ( num == EVENT_OBJECT_RSHIELD ) strcpy(text, "Rozpocznij prace badawcze nad robotem os³aniaczem");
+ if ( num == EVENT_OBJECT_RATOMIC ) strcpy(text, "Rozpocznij prace badawcze nad energi¹ atomow¹");
+ if ( num == EVENT_OBJECT_RiPAW ) strcpy(text, "Rozpocznij prace badawcze nad transporterem na nogach");
+ if ( num == EVENT_OBJECT_RiGUN ) strcpy(text, "Rozpocznij prace badawcze nad dzia³em organicznym");
+ if ( num == EVENT_OBJECT_RESET ) strcpy(text, "Powrót do pocz¹tku");
+ if ( num == EVENT_OBJECT_SEARCH ) strcpy(text, "Szukaj (\\key action;)");
+ if ( num == EVENT_OBJECT_TERRAFORM ) strcpy(text, "Uderz (\\key action;)");
+ if ( num == EVENT_OBJECT_FIRE ) strcpy(text, "Strzelaj (\\key action;)");
+ if ( num == EVENT_OBJECT_RECOVER ) strcpy(text, "Odzyskaj (\\key action;)");
+ if ( num == EVENT_OBJECT_BEGSHIELD ) strcpy(text, "Rozszerz os³onê (\\key action;)");
+ if ( num == EVENT_OBJECT_ENDSHIELD ) strcpy(text, "Wy³¹cz os³onê (\\key action;)");
+ if ( num == EVENT_OBJECT_DIMSHIELD ) strcpy(text, "Zasiêg os³ony");
+ if ( num == EVENT_OBJECT_PROGRUN ) strcpy(text, "Wykonaj zaznaczony program");
+ if ( num == EVENT_OBJECT_PROGEDIT ) strcpy(text, "Edytuj zaznaczony program");
+ if ( num == EVENT_OBJECT_INFOOK ) strcpy(text, "\\Prze³¹cz przekaŸnik SatCom w stan gotowoœci");
+ if ( num == EVENT_OBJECT_DELETE ) strcpy(text, "Zniszcz budynek");
+ if ( num == EVENT_OBJECT_GENERGY ) strcpy(text, "Poziom energii");
+ if ( num == EVENT_OBJECT_GSHIELD ) strcpy(text, "Poziom os³ony");
+ if ( num == EVENT_OBJECT_GRANGE ) strcpy(text, "Temperatura silnika");
+ if ( num == EVENT_OBJECT_GPROGRESS ) strcpy(text, "Wci¹¿ pracuje...");
+ if ( num == EVENT_OBJECT_GRADAR ) strcpy(text, "Liczba wykrytych insektów");
+ if ( num == EVENT_OBJECT_GINFO ) strcpy(text, "Przes³ane informacje");
+ if ( num == EVENT_OBJECT_COMPASS ) strcpy(text, "Kompas");
+//? if ( num == EVENT_OBJECT_MAP ) strcpy(text, "Mapka");
+ if ( num == EVENT_OBJECT_MAPZOOM ) strcpy(text, "Powiêkszenie mapki");
+ if ( num == EVENT_OBJECT_CAMERA ) strcpy(text, "Kamera (\\key camera;)");
+ if ( num == EVENT_OBJECT_CAMERAleft) strcpy(text, "Camera to left");
+ if ( num == EVENT_OBJECT_CAMERAright) strcpy(text, "Camera to right");
+ if ( num == EVENT_OBJECT_CAMERAnear) strcpy(text, "Camera nearest");
+ if ( num == EVENT_OBJECT_CAMERAaway) strcpy(text, "Camera awayest");
+ if ( num == EVENT_OBJECT_HELP ) strcpy(text, "Pomoc na temat zaznaczonego obiektu");
+ if ( num == EVENT_OBJECT_SOLUCE ) strcpy(text, "Poka¿ rozwi¹zanie");
+ if ( num == EVENT_OBJECT_SHORTCUT00) strcpy(text, "Prze³¹cz roboty <-> budynki");
+ if ( num == EVENT_OBJECT_LIMIT ) strcpy(text, "Poka¿ zasiêg");
+ if ( num == EVENT_OBJECT_PEN0 ) strcpy(text, "\\Relève le crayon");
+ if ( num == EVENT_OBJECT_PEN1 ) strcpy(text, "\\Abaisse le crayon noir");
+ if ( num == EVENT_OBJECT_PEN2 ) strcpy(text, "\\Abaisse le crayon jaune");
+ if ( num == EVENT_OBJECT_PEN3 ) strcpy(text, "\\Abaisse le crayon orange");
+ if ( num == EVENT_OBJECT_PEN4 ) strcpy(text, "\\Abaisse le crayon rouge");
+ if ( num == EVENT_OBJECT_PEN5 ) strcpy(text, "\\Abaisse le crayon violet");
+ if ( num == EVENT_OBJECT_PEN6 ) strcpy(text, "\\Abaisse le crayon bleu");
+ if ( num == EVENT_OBJECT_PEN7 ) strcpy(text, "\\Abaisse le crayon vert");
+ if ( num == EVENT_OBJECT_PEN8 ) strcpy(text, "\\Abaisse le crayon brun");
+ if ( num == EVENT_OBJECT_REC ) strcpy(text, "\\Démarre l'enregistrement");
+ if ( num == EVENT_OBJECT_STOP ) strcpy(text, "\\Stoppe l'enregistrement");
+ if ( num == EVENT_DT_VISIT0 ||
+ num == EVENT_DT_VISIT1 ||
+ num == EVENT_DT_VISIT2 ||
+ num == EVENT_DT_VISIT3 ||
+ num == EVENT_DT_VISIT4 ) strcpy(text, "Poka¿ miejsce");
+ if ( num == EVENT_DT_END ) strcpy(text, "Kontynuuj");
+ if ( num == EVENT_CMD ) strcpy(text, "Linia polecenia");
+ if ( num == EVENT_SPEED ) strcpy(text, "Prêdkoœæ gry");
+
+ if ( num == EVENT_HYPER_PREV ) strcpy(text, "Wstecz");
+ if ( num == EVENT_HYPER_NEXT ) strcpy(text, "Naprzód");
+ if ( num == EVENT_HYPER_HOME ) strcpy(text, "Pocz¹tek");
+ if ( num == EVENT_HYPER_COPY ) strcpy(text, "Kopiuj");
+ if ( num == EVENT_HYPER_SIZE1 ) strcpy(text, "WielkoϾ 1");
+ if ( num == EVENT_HYPER_SIZE2 ) strcpy(text, "WielkoϾ 2");
+ if ( num == EVENT_HYPER_SIZE3 ) strcpy(text, "WielkoϾ 3");
+ if ( num == EVENT_HYPER_SIZE4 ) strcpy(text, "WielkoϾ 4");
+ if ( num == EVENT_HYPER_SIZE5 ) strcpy(text, "WielkoϾ 5");
+ if ( num == EVENT_SATCOM_HUSTON ) strcpy(text, "Rozkazy z Houston");
+#if _TEEN
+ if ( num == EVENT_SATCOM_SAT ) strcpy(text, "Raport z satelity");
+#else
+ if ( num == EVENT_SATCOM_SAT ) strcpy(text, "Raport z satelity");
+#endif
+ if ( num == EVENT_SATCOM_LOADING ) strcpy(text, "Program dostarczony z Houston");
+ if ( num == EVENT_SATCOM_OBJECT ) strcpy(text, "Lista obiektów");
+ if ( num == EVENT_SATCOM_PROG ) strcpy(text, "Podrêcznik programowania");
+ if ( num == EVENT_SATCOM_SOLUCE ) strcpy(text, "Rozwi¹zanie");
+
+ if ( num == EVENT_STUDIO_OK ) strcpy(text, "OK\\Zamyka edytor programu i powraca do gry");
+ if ( num == EVENT_STUDIO_CANCEL ) strcpy(text, "Anuluj\\Pomija wszystkie zmiany");
+ if ( num == EVENT_STUDIO_NEW ) strcpy(text, "Nowy");
+ if ( num == EVENT_STUDIO_OPEN ) strcpy(text, "Otwórz (Ctrl+O)");
+ if ( num == EVENT_STUDIO_SAVE ) strcpy(text, "Zapisz (Ctrl+S)");
+ if ( num == EVENT_STUDIO_UNDO ) strcpy(text, "Cofnij (Ctrl+Z)");
+ if ( num == EVENT_STUDIO_CUT ) strcpy(text, "Wytnij (Ctrl+X)");
+ if ( num == EVENT_STUDIO_COPY ) strcpy(text, "Kopiuj (Ctrl+C)");
+ if ( num == EVENT_STUDIO_PASTE ) strcpy(text, "Wklej (Ctrl+V)");
+ if ( num == EVENT_STUDIO_SIZE ) strcpy(text, "WielkoϾ czcionki");
+ if ( num == EVENT_STUDIO_TOOL ) strcpy(text, "Rozkazy (\\key help;)");
+ if ( num == EVENT_STUDIO_HELP ) strcpy(text, "Podrêcznik programowania (\\key prog;)");
+ if ( num == EVENT_STUDIO_COMPILE ) strcpy(text, "Kompiluj");
+ if ( num == EVENT_STUDIO_RUN ) strcpy(text, "Wykonaj/Zatrzymaj");
+ if ( num == EVENT_STUDIO_REALTIME ) strcpy(text, "Pauza/Kontynuuj");
+ if ( num == EVENT_STUDIO_STEP ) strcpy(text, "Jeden krok");
+ }
+
+ if ( type == RES_OBJECT )
+ {
+ if ( num == OBJECT_PORTICO ) strcpy(text, "¯uraw przesuwalny");
+ if ( num == OBJECT_BASE ) strcpy(text, "Statek kosmiczny");
+ if ( num == OBJECT_DERRICK ) strcpy(text, "Kopalnia");
+ if ( num == OBJECT_FACTORY ) strcpy(text, "Fabryka robotów");
+ if ( num == OBJECT_REPAIR ) strcpy(text, "Warsztat");
+ if ( num == OBJECT_DESTROYER ) strcpy(text, "Destroyer");
+ if ( num == OBJECT_STATION ) strcpy(text, "Stacja energetyczna");
+ if ( num == OBJECT_CONVERT ) strcpy(text, "Przetop rudê na tytan");
+ if ( num == OBJECT_TOWER ) strcpy(text, "Wie¿a obronna");
+ if ( num == OBJECT_NEST ) strcpy(text, "Gniazdo");
+ if ( num == OBJECT_RESEARCH ) strcpy(text, "Centrum badawcze");
+ if ( num == OBJECT_RADAR ) strcpy(text, "Stacja radarowa");
+ if ( num == OBJECT_INFO ) strcpy(text, "Stacja przekaŸnikowa informacji");
+#if _TEEN
+ if ( num == OBJECT_ENERGY ) strcpy(text, "Fabryka ogniw elektrycznych");
+#else
+ if ( num == OBJECT_ENERGY ) strcpy(text, "Fabryka ogniw elektrycznych");
+#endif
+ if ( num == OBJECT_LABO ) strcpy(text, "Laboratorium");
+ if ( num == OBJECT_NUCLEAR ) strcpy(text, "Elektrownia atomowa");
+ if ( num == OBJECT_PARA ) strcpy(text, "Odgromnik");
+ if ( num == OBJECT_SAFE ) strcpy(text, "Skrytka");
+ if ( num == OBJECT_HUSTON ) strcpy(text, "Centrum Kontroli Misji w Houston");
+ if ( num == OBJECT_TARGET1 ) strcpy(text, "Cel");
+ if ( num == OBJECT_TARGET2 ) strcpy(text, "Cel");
+ if ( num == OBJECT_START ) strcpy(text, "Pocz¹tek");
+ if ( num == OBJECT_END ) strcpy(text, "Koniec");
+ if ( num == OBJECT_STONE ) strcpy(text, "Ruda tytanu");
+ if ( num == OBJECT_URANIUM ) strcpy(text, "Ruda uranu");
+ if ( num == OBJECT_BULLET ) strcpy(text, "Materia organiczna");
+ if ( num == OBJECT_METAL ) strcpy(text, "Tytan");
+ if ( num == OBJECT_POWER ) strcpy(text, "Ogniwo elektryczne");
+ if ( num == OBJECT_ATOMIC ) strcpy(text, "Atomowe ogniwa elektryczne");
+ if ( num == OBJECT_BBOX ) strcpy(text, "Czarna skrzynka");
+ if ( num == OBJECT_KEYa ) strcpy(text, "Klucz A");
+ if ( num == OBJECT_KEYb ) strcpy(text, "Klucz B");
+ if ( num == OBJECT_KEYc ) strcpy(text, "Klucz C");
+ if ( num == OBJECT_KEYd ) strcpy(text, "Klucz D");
+ if ( num == OBJECT_TNT ) strcpy(text, "Materia³y wybuchowe");
+ if ( num == OBJECT_BOMB ) strcpy(text, "Mina");
+ if ( num == OBJECT_BAG ) strcpy(text, "Zestaw przetrwania");
+ if ( num == OBJECT_WAYPOINT ) strcpy(text, "Punkt kontrolny");
+ if ( num == OBJECT_FLAGb ) strcpy(text, "Niebieska flaga");
+ if ( num == OBJECT_FLAGr ) strcpy(text, "Czerwona flaga");
+ if ( num == OBJECT_FLAGg ) strcpy(text, "Zielona flaga");
+ if ( num == OBJECT_FLAGy ) strcpy(text, "¯ó³ta flaga");
+ if ( num == OBJECT_FLAGv ) strcpy(text, "Fioletowa flaga");
+ if ( num == OBJECT_MARKPOWER ) strcpy(text, "ród³o energii (miejsce na elektrowniê)");
+ if ( num == OBJECT_MARKURANIUM ) strcpy(text, "Z³o¿e uranu (miejsce na kopalniê)");
+ if ( num == OBJECT_MARKKEYa ) strcpy(text, "Znaleziono klucz A (miejsce na kopalniê)");
+ if ( num == OBJECT_MARKKEYb ) strcpy(text, "Znaleziono klucz B (miejsce na kopalniê)");
+ if ( num == OBJECT_MARKKEYc ) strcpy(text, "Znaleziono klucz C (miejsce na kopalniê)");
+ if ( num == OBJECT_MARKKEYd ) strcpy(text, "Znaleziono klucz D (miejsce na kopalniê)");
+ if ( num == OBJECT_MARKSTONE ) strcpy(text, "Z³o¿e tytanu (miejsce na kopalniê)");
+ if ( num == OBJECT_MOBILEft ) strcpy(text, "Robot treningowy");
+ if ( num == OBJECT_MOBILEtt ) strcpy(text, "Robot treningowy");
+ if ( num == OBJECT_MOBILEwt ) strcpy(text, "Robot treningowy");
+ if ( num == OBJECT_MOBILEit ) strcpy(text, "Robot treningowy");
+ if ( num == OBJECT_MOBILEfa ) strcpy(text, "Transporter lataj¹cy");
+ if ( num == OBJECT_MOBILEta ) strcpy(text, "Transporter na g¹sienicach");
+ if ( num == OBJECT_MOBILEwa ) strcpy(text, "Transporter na ko³ach");
+ if ( num == OBJECT_MOBILEia ) strcpy(text, "Transporter na nogach");
+ if ( num == OBJECT_MOBILEfc ) strcpy(text, "Dzia³o lataj¹ce");
+ if ( num == OBJECT_MOBILEtc ) strcpy(text, "Dzia³o na g¹sienicach");
+ if ( num == OBJECT_MOBILEwc ) strcpy(text, "Dzia³o na ko³ach");
+ if ( num == OBJECT_MOBILEic ) strcpy(text, "Dzia³o na nogach");
+ if ( num == OBJECT_MOBILEfi ) strcpy(text, "Lataj¹ce dzia³o organiczne");
+ if ( num == OBJECT_MOBILEti ) strcpy(text, "Dzia³o organiczne na g¹sienicach");
+ if ( num == OBJECT_MOBILEwi ) strcpy(text, "Dzia³o organiczne na ko³ach");
+ if ( num == OBJECT_MOBILEii ) strcpy(text, "Dzia³o organiczne na nogach");
+ if ( num == OBJECT_MOBILEfs ) strcpy(text, "Szperacz lataj¹cy");
+ if ( num == OBJECT_MOBILEts ) strcpy(text, "Szperacz na g¹sienicach");
+ if ( num == OBJECT_MOBILEws ) strcpy(text, "Szperacz na ko³ach");
+ if ( num == OBJECT_MOBILEis ) strcpy(text, "Szperacz na nogach");
+ if ( num == OBJECT_MOBILErt ) strcpy(text, "Uderzacz");
+ if ( num == OBJECT_MOBILErc ) strcpy(text, "Dzia³o fazowe");
+ if ( num == OBJECT_MOBILErr ) strcpy(text, "Recykler");
+ if ( num == OBJECT_MOBILErs ) strcpy(text, "Os³aniacz");
+ if ( num == OBJECT_MOBILEsa ) strcpy(text, "Robot nurek");
+ if ( num == OBJECT_MOBILEtg ) strcpy(text, "Robot cel");
+ if ( num == OBJECT_MOBILEdr ) strcpy(text, "Drawer bot");
+ if ( num == OBJECT_HUMAN ) strcpy(text, g_gamerName);
+ if ( num == OBJECT_TECH ) strcpy(text, "In¿ynier");
+ if ( num == OBJECT_TOTO ) strcpy(text, "Robbie");
+ if ( num == OBJECT_MOTHER ) strcpy(text, "Królowa Obcych");
+ if ( num == OBJECT_ANT ) strcpy(text, "Mrówka");
+ if ( num == OBJECT_SPIDER ) strcpy(text, "Paj¹k");
+ if ( num == OBJECT_BEE ) strcpy(text, "Osa");
+ if ( num == OBJECT_WORM ) strcpy(text, "Robal");
+ if ( num == OBJECT_EGG ) strcpy(text, "Jajo");
+ if ( num == OBJECT_RUINmobilew1 ) strcpy(text, "Wrak");
+ if ( num == OBJECT_RUINmobilew2 ) strcpy(text, "Wrak");
+ if ( num == OBJECT_RUINmobilet1 ) strcpy(text, "Wrak");
+ if ( num == OBJECT_RUINmobilet2 ) strcpy(text, "Wrak");
+ if ( num == OBJECT_RUINmobiler1 ) strcpy(text, "Wrak");
+ if ( num == OBJECT_RUINmobiler2 ) strcpy(text, "Wrak");
+ if ( num == OBJECT_RUINfactory ) strcpy(text, "Ruiny");
+ if ( num == OBJECT_RUINdoor ) strcpy(text, "Ruiny");
+ if ( num == OBJECT_RUINsupport ) strcpy(text, "Odpady");
+ if ( num == OBJECT_RUINradar ) strcpy(text, "Ruiny");
+ if ( num == OBJECT_RUINconvert ) strcpy(text, "Ruiny");
+ if ( num == OBJECT_RUINbase ) strcpy(text, "Ruiny statku kosmicznego");
+ if ( num == OBJECT_RUINhead ) strcpy(text, "Ruiny statku kosmicznego");
+ if ( num == OBJECT_APOLLO1 ||
+ num == OBJECT_APOLLO3 ||
+ num == OBJECT_APOLLO4 ||
+ num == OBJECT_APOLLO5 ) strcpy(text, "Pozosta³oœci z misji Apollo");
+ if ( num == OBJECT_APOLLO2 ) strcpy(text, "Pojazd Ksiê¿ycowy");
+ }
+
+ if ( type == RES_ERR )
+ {
+ strcpy(text, "B³¹d");
+ if ( num == ERR_CMD ) strcpy(text, "Nieznane polecenie");
+#if _NEWLOOK
+ if ( num == ERR_INSTALL ) strcpy(text, "Gra CeeBot nie jest zainstalowana.");
+ if ( num == ERR_NOCD ) strcpy(text, "W³ó¿ dysk CD z gr¹ CeeBot\ni uruchom grê jeszcze raz.");
+#else
+ if ( num == ERR_INSTALL ) strcpy(text, "Gra COLOBOT nie jest zainstalowana.");
+ if ( num == ERR_NOCD ) strcpy(text, "W³ó¿ dysk CD z gr¹ COLOBOT\ni uruchom grê jeszcze raz.");
+#endif
+ if ( num == ERR_MANIP_VEH ) strcpy(text, "Nieodpowiedni robot");
+ if ( num == ERR_MANIP_FLY ) strcpy(text, "Niemo¿liwe podczas lotu");
+ if ( num == ERR_MANIP_BUSY ) strcpy(text, "Nie mo¿na nieœæ wiêcej przedmiotów");
+ if ( num == ERR_MANIP_NIL ) strcpy(text, "Nie ma nic do podniesienia");
+ if ( num == ERR_MANIP_MOTOR ) strcpy(text, "Niemo¿liwe podczas ruchu");
+ if ( num == ERR_MANIP_OCC ) strcpy(text, "Miejsce zajête");
+ if ( num == ERR_MANIP_FRIEND ) strcpy(text, "Brak innego robota");
+ if ( num == ERR_MANIP_RADIO ) strcpy(text, "Nie mo¿esz przenosiæ przedmiotów radioaktywnych");
+ if ( num == ERR_MANIP_WATER ) strcpy(text, "Nie mo¿esz przenosiæ przedmiotów pod wod¹");
+ if ( num == ERR_MANIP_EMPTY ) strcpy(text, "Nie ma nic do upuszczenia");
+ if ( num == ERR_BUILD_FLY ) strcpy(text, "Niemo¿liwe podczas lotu");
+ if ( num == ERR_BUILD_WATER ) strcpy(text, "Niemo¿liwe pod wod¹");
+ if ( num == ERR_BUILD_ENERGY ) strcpy(text, "Za ma³o energii");
+ if ( num == ERR_BUILD_METALAWAY ) strcpy(text, "Tytan za daleko");
+ if ( num == ERR_BUILD_METALNEAR ) strcpy(text, "Tytan za blisko");
+ if ( num == ERR_BUILD_METALINEX ) strcpy(text, "Brak tytanu w pobli¿u");
+ if ( num == ERR_BUILD_FLAT ) strcpy(text, "Powierzchnia nie jest wystarczaj¹co p³aska");
+ if ( num == ERR_BUILD_FLATLIT ) strcpy(text, "Za ma³o p³askiego terenu");
+ if ( num == ERR_BUILD_BUSY ) strcpy(text, "Miejsce zajête");
+ if ( num == ERR_BUILD_BASE ) strcpy(text, "Za blisko statku kosmicznego");
+ if ( num == ERR_BUILD_NARROW ) strcpy(text, "Za blisko budynku");
+ if ( num == ERR_BUILD_MOTOR ) strcpy(text, "Niemo¿liwe podczas ruchu");
+ if ( num == ERR_SEARCH_FLY ) strcpy(text, "Niemo¿liwe podczas lotu");
+ if ( num == ERR_SEARCH_VEH ) strcpy(text, "Nieodpowiedni robot");
+ if ( num == ERR_SEARCH_MOTOR ) strcpy(text, "Niemo¿liwe podczas ruchu");
+ if ( num == ERR_TERRA_VEH ) strcpy(text, "Nieodpowiedni robot");
+ if ( num == ERR_TERRA_ENERGY ) strcpy(text, "Za ma³o energii");
+ if ( num == ERR_TERRA_FLOOR ) strcpy(text, "Nieodpowiedni teren");
+ if ( num == ERR_TERRA_BUILDING ) strcpy(text, "Budynek za blisko");
+ if ( num == ERR_TERRA_OBJECT ) strcpy(text, "Obiekt za blisko");
+ if ( num == ERR_RECOVER_VEH ) strcpy(text, "Nieodpowiedni robot");
+ if ( num == ERR_RECOVER_ENERGY ) strcpy(text, "Za ma³o energii");
+ if ( num == ERR_RECOVER_NULL ) strcpy(text, "Nie ma niczego do odzysku");
+ if ( num == ERR_SHIELD_VEH ) strcpy(text, "Nieodpowiedni robot");
+ if ( num == ERR_SHIELD_ENERGY ) strcpy(text, "Nie ma wiêcej energii");
+ if ( num == ERR_MOVE_IMPOSSIBLE ) strcpy(text, "B³¹d w poleceniu ruchu");
+ if ( num == ERR_FIND_IMPOSSIBLE ) strcpy(text, "Obiekt nieznany");
+ if ( num == ERR_GOTO_IMPOSSIBLE ) strcpy(text, "Goto: miejsce docelowe niedostêpne");
+ if ( num == ERR_GOTO_ITER ) strcpy(text, "Goto: miejsce docelowe niedostêpne");
+ if ( num == ERR_GOTO_BUSY ) strcpy(text, "Goto: miejsce docelowe zajête");
+ if ( num == ERR_FIRE_VEH ) strcpy(text, "Nieodpowiedni robot");
+ if ( num == ERR_FIRE_ENERGY ) strcpy(text, "Za ma³o energii");
+ if ( num == ERR_FIRE_FLY ) strcpy(text, "Niemo¿liwe podczas lotu");
+ if ( num == ERR_CONVERT_EMPTY ) strcpy(text, "Brak rudy tytanu do przetopienia");
+ if ( num == ERR_DERRICK_NULL ) strcpy(text, "W ziemi nie ma ¿adnej rudy");
+ if ( num == ERR_STATION_NULL ) strcpy(text, "Brak energii w ziemi");
+ if ( num == ERR_TOWER_POWER ) strcpy(text, "Brak ogniwa elektrycznego");
+ if ( num == ERR_TOWER_ENERGY ) strcpy(text, "Nie ma wiêcej energii");
+ if ( num == ERR_RESEARCH_POWER ) strcpy(text, "Brak ogniwa elektrycznego");
+ if ( num == ERR_RESEARCH_ENERGY ) strcpy(text, "Za ma³o energii");
+ if ( num == ERR_RESEARCH_TYPE ) strcpy(text, "Nieodpowiedni rodzaj ogniw");
+ if ( num == ERR_RESEARCH_ALREADY) strcpy(text, "Program badawczy zosta³ ju¿ wykonany");
+ if ( num == ERR_ENERGY_NULL ) strcpy(text, "Brak energii w ziemi");
+ if ( num == ERR_ENERGY_LOW ) strcpy(text, "Wci¹¿ za ma³o energii");
+ if ( num == ERR_ENERGY_EMPTY ) strcpy(text, "Brak tytanu do przetworzenia");
+ if ( num == ERR_ENERGY_BAD ) strcpy(text, "Przetwarza jedynie tytan");
+ if ( num == ERR_BASE_DLOCK ) strcpy(text, "Drzwi zablokowane przez robota lub inny obiekt ");
+ if ( num == ERR_BASE_DHUMAN ) strcpy(text, "Musisz byæ na statku kosmicznym aby nim odlecieæ");
+ if ( num == ERR_LABO_NULL ) strcpy(text, "Nie ma niczego do zanalizowania");
+ if ( num == ERR_LABO_BAD ) strcpy(text, "Analizuje jedynie materiê organiczn¹");
+ if ( num == ERR_LABO_ALREADY ) strcpy(text, "Analiza zosta³a ju¿ wykonana");
+ if ( num == ERR_NUCLEAR_NULL ) strcpy(text, "Brak energii w ziemi");
+ if ( num == ERR_NUCLEAR_LOW ) strcpy(text, "Wci¹¿ za ma³o energii");
+ if ( num == ERR_NUCLEAR_EMPTY ) strcpy(text, "Brak uranu do przetworzenia");
+ if ( num == ERR_NUCLEAR_BAD ) strcpy(text, "Przetwarza jedynie uran");
+ if ( num == ERR_FACTORY_NULL ) strcpy(text, "Brak tytanu");
+ if ( num == ERR_FACTORY_NEAR ) strcpy(text, "Obiekt za blisko");
+ if ( num == ERR_RESET_NEAR ) strcpy(text, "Miejsce zajête");
+ if ( num == ERR_INFO_NULL ) strcpy(text, "Nie ma ¿adnej stacji przekaŸnikowej w zasiêgu");
+ if ( num == ERR_VEH_VIRUS ) strcpy(text, "Program zawirusowany");
+ if ( num == ERR_BAT_VIRUS ) strcpy(text, "Zainfekowane wirusem, chwilowo niesprawne");
+ if ( num == ERR_VEH_POWER ) strcpy(text, "Brak ogniwa elektrycznego");
+ if ( num == ERR_VEH_ENERGY ) strcpy(text, "Nie ma wiêcej energii");
+ if ( num == ERR_FLAG_FLY ) strcpy(text, "Niemo¿liwe podczas lotu");
+ if ( num == ERR_FLAG_WATER ) strcpy(text, "Niemo¿liwe podczas p³ywania");
+ if ( num == ERR_FLAG_MOTOR ) strcpy(text, "Niemo¿liwe podczas ruchu");
+ if ( num == ERR_FLAG_BUSY ) strcpy(text, "Niemo¿liwe podczas przenoszenia przedmiotu");
+ if ( num == ERR_FLAG_CREATE ) strcpy(text, "Za du¿o flag w tym kolorze (maksymalnie 5)");
+ if ( num == ERR_FLAG_PROXY ) strcpy(text, "Za blisko istniej¹cej flagi");
+ if ( num == ERR_FLAG_DELETE ) strcpy(text, "Nie ma flagi w pobli¿u");
+ if ( num == ERR_MISSION_NOTERM ) strcpy(text, "Misja nie jest wype³niona (naciœnij \\key help; aby uzyskaæ szczegó³y)");
+ if ( num == ERR_DELETEMOBILE ) strcpy(text, "Robot zniszczony");
+ if ( num == ERR_DELETEBUILDING ) strcpy(text, "Budynek zniszczony");
+ if ( num == ERR_TOOMANY ) strcpy(text, "Nie mo¿na tego utworzyæ, za du¿o obiektów");
+ if ( num == ERR_OBLIGATORYTOKEN ) strcpy(text, "It misses \"%s\" in this exercise");
+ if ( num == ERR_PROHIBITEDTOKEN ) strcpy(text, "Do not use in this exercise");
+
+ if ( num == INFO_BUILD ) strcpy(text, "Budowa zakoñczona");
+ if ( num == INFO_CONVERT ) strcpy(text, "Tytan dostêpny");
+ if ( num == INFO_RESEARCH ) strcpy(text, "Program badawczy zakoñczony");
+ if ( num == INFO_RESEARCHTANK ) strcpy(text, "Dostêpne plany tranporterów na g¹sienicach");
+ if ( num == INFO_RESEARCHFLY ) strcpy(text, "Mo¿esz lataæ u¿ywaj¹c klawiszy (\\key gup;) oraz (\\key gdown;)");
+ if ( num == INFO_RESEARCHTHUMP ) strcpy(text, "Dostêpne plany robota uderzacza");
+ if ( num == INFO_RESEARCHCANON ) strcpy(text, "Dostêpne plany dzia³a");
+ if ( num == INFO_RESEARCHTOWER ) strcpy(text, "Dostêpne plany wie¿y obronnej");
+ if ( num == INFO_RESEARCHPHAZER ) strcpy(text, "Dostêpne plany dzia³a fazowego");
+ if ( num == INFO_RESEARCHSHIELD ) strcpy(text, "Dostêpne plany robota os³aniacza");
+ if ( num == INFO_RESEARCHATOMIC ) strcpy(text, "Dostêpne plany elektrowni atomowej");
+ if ( num == INFO_FACTORY ) strcpy(text, "Dostêpny nowy robot");
+ if ( num == INFO_LABO ) strcpy(text, "Analiza wykonana");
+ if ( num == INFO_ENERGY ) strcpy(text, "Wytworzono ogniwo elektryczne");
+ if ( num == INFO_NUCLEAR ) strcpy(text, "Wytworzono atomowe ogniwo elektryczne");
+ if ( num == INFO_FINDING ) strcpy(text, "Znaleziono u¿yteczny przedmiot");
+ if ( num == INFO_MARKPOWER ) strcpy(text, "Znaleziono miejsce na elektrowniê");
+ if ( num == INFO_MARKURANIUM ) strcpy(text, "Znaleziono miejsce na kopalniê");
+ if ( num == INFO_MARKSTONE ) strcpy(text, "Znaleziono miejsce na kopalniê");
+ if ( num == INFO_MARKKEYa ) strcpy(text, "Znaleziono miejsce na kopalniê");
+ if ( num == INFO_MARKKEYb ) strcpy(text, "Znaleziono miejsce na kopalniê");
+ if ( num == INFO_MARKKEYc ) strcpy(text, "Znaleziono miejsce na kopalniê");
+ if ( num == INFO_MARKKEYd ) strcpy(text, "Znaleziono miejsce na kopalniê");
+ if ( num == INFO_WIN ) strcpy(text, "<<< Dobra robota, misja wype³niona >>>");
+ if ( num == INFO_LOST ) strcpy(text, "<<< Niestety, misja nie powiod³a siê >>>");
+ if ( num == INFO_LOSTq ) strcpy(text, "<<< Niestety, misja nie powiod³a siê >>>");
+ if ( num == INFO_WRITEOK ) strcpy(text, "Bie¿¹ca misja zapisana");
+ if ( num == INFO_DELETEPATH ) strcpy(text, "Przekroczono punkt kontrolny");
+ if ( num == INFO_DELETEMOTHER ) strcpy(text, "Królowa Obcych zosta³a zabita");
+ if ( num == INFO_DELETEANT ) strcpy(text, "Mrówka œmiertelnie raniona");
+ if ( num == INFO_DELETEBEE ) strcpy(text, "Osa œmiertelnie raniona");
+ if ( num == INFO_DELETEWORM ) strcpy(text, "Robal œmiertelnie raniony");
+ if ( num == INFO_DELETESPIDER ) strcpy(text, "Paj¹k œmiertelnie raniony");
+ if ( num == INFO_BEGINSATCOM ) strcpy(text, "Naciœnij klawisz \\key help; aby wyœwietliæ rozkazy na przekaŸniku SatCom");
+ }
+
+ if ( type == RES_CBOT )
+ {
+ strcpy(text, "B³¹d");
+ if ( num == TX_OPENPAR ) strcpy(text, "Brak nawiasu otwieraj¹cego");
+ if ( num == TX_CLOSEPAR ) strcpy(text, "Brak nawiasu zamykaj¹cego");
+ if ( num == TX_NOTBOOL ) strcpy(text, "Wyra¿enie musi zwróciæ wartoœæ logiczn¹");
+ if ( num == TX_UNDEFVAR ) strcpy(text, "Zmienna nie zosta³a zadeklarowana");
+ if ( num == TX_BADLEFT ) strcpy(text, "Przypisanie niemo¿liwe");
+ if ( num == TX_ENDOF ) strcpy(text, "Brak œrednika na koñcu wiersza");
+ if ( num == TX_OUTCASE ) strcpy(text, "Polecenie ""case"" na zewn¹trz bloku ""switch""");
+ if ( num == TX_NOTERM ) strcpy(text, "Polecenie po koñcowej klamrze zamykaj¹cej");
+ if ( num == TX_CLOSEBLK ) strcpy(text, "Brak koñca bloku");
+ if ( num == TX_ELSEWITHOUTIF ) strcpy(text, "Polecenie ""else"" bez wyst¹pienia ""if"" ");
+ if ( num == TX_OPENBLK ) strcpy(text, "Brak klamry otwieraj¹cej");//début d'un bloc attendu?
+ if ( num == TX_BADTYPE ) strcpy(text, "Z³y typ dla przypisania");
+ if ( num == TX_REDEFVAR ) strcpy(text, "Zmienna nie mo¿e byæ zadeklarowana dwukrotnie");
+ if ( num == TX_BAD2TYPE ) strcpy(text, "Niezgodne typy operatorów");
+ if ( num == TX_UNDEFCALL ) strcpy(text, "Funkcja nieznana");
+ if ( num == TX_MISDOTS ) strcpy(text, "Brak znaku "" : ");
+ if ( num == TX_WHILE ) strcpy(text, "Brak kluczowego s³owa ""while");
+ if ( num == TX_BREAK ) strcpy(text, "Polecenie ""break"" na zewn¹trz pêtli");
+ if ( num == TX_LABEL ) strcpy(text, "Po etykiecie musi wyst¹piæ ""for"", ""while"", ""do"" lub ""switch""");
+ if ( num == TX_NOLABEL ) strcpy(text, "Taka etykieta nie istnieje");// Cette étiquette n'existe pas
+ if ( num == TX_NOCASE ) strcpy(text, "Brak polecenia ""case");
+ if ( num == TX_BADNUM ) strcpy(text, "Brak liczby");
+ if ( num == TX_VOID ) strcpy(text, "Pusty parametr");
+ if ( num == TX_NOTYP ) strcpy(text, "Brak deklaracji typu");
+ if ( num == TX_NOVAR ) strcpy(text, "Brak nazwy zmiennej");
+ if ( num == TX_NOFONC ) strcpy(text, "Brakuj¹ca nazwa funkcji");
+ if ( num == TX_OVERPARAM ) strcpy(text, "Za du¿o parametrów");
+ if ( num == TX_REDEF ) strcpy(text, "Funkcja ju¿ istnieje");
+ if ( num == TX_LOWPARAM ) strcpy(text, "Brak wymaganego parametru");
+ if ( num == TX_BADPARAM ) strcpy(text, "Funkcja o tej nazwie nie akceptuje parametrów tego typu");
+ if ( num == TX_NUMPARAM ) strcpy(text, "Funkcja o tej nazwie nie akceptuje takiej liczby parametrów");
+ if ( num == TX_NOITEM ) strcpy(text, "To nie jest obiekt tej klasy");
+ if ( num == TX_DOT ) strcpy(text, "Ten obiekt nie jest cz³onkiem klasy");
+ if ( num == TX_NOCONST ) strcpy(text, "Brak odpowiedniego konstruktora");
+ if ( num == TX_REDEFCLASS ) strcpy(text, "Taka klasa ju¿ istnieje");
+ if ( num == TX_CLBRK ) strcpy(text, "Brak "" ] """);
+ if ( num == TX_RESERVED ) strcpy(text, "S³owo zarezerwowane jêzyka CBOT");
+ if ( num == TX_BADNEW ) strcpy(text, "Z³y argument dla funkcji ""new""");
+ if ( num == TX_OPBRK ) strcpy(text, "Oczekiwane "" [ """);
+ if ( num == TX_BADSTRING ) strcpy(text, "Brak ³añcucha");
+ if ( num == TX_BADINDEX ) strcpy(text, "Nieprawid³owy typ indeksu");
+ if ( num == TX_PRIVATE ) strcpy(text, "Element prywatny");
+ if ( num == TX_NOPUBLIC ) strcpy(text, "Wymagany publiczny");
+ if ( num == TX_DIVZERO ) strcpy(text, "Dzielenie przez zero");
+ if ( num == TX_NOTINIT ) strcpy(text, "Zmienna nie zosta³a zainicjalizowana");
+ if ( num == TX_BADTHROW ) strcpy(text, "Wartoœæ ujemna odrzucona przez ""throw""");//C'est quoi, ça?
+ if ( num == TX_NORETVAL ) strcpy(text, "Funkcja nie zwróci³a ¿adnej wartoœci ");
+ if ( num == TX_NORUN ) strcpy(text, "¯adna funkcja nie dzia³a");
+ if ( num == TX_NOCALL ) strcpy(text, "Odwo³anie do nieznanej funkcji");
+ if ( num == TX_NOCLASS ) strcpy(text, "Taka klasa nie istnieje");
+ if ( num == TX_NULLPT ) strcpy(text, "Obiekt nieznany");
+ if ( num == TX_OPNAN ) strcpy(text, "Dzia³anie niemo¿liwe z wartoœci¹ ""nan""");
+ if ( num == TX_OUTARRAY ) strcpy(text, "Dostêp poza tablicê");
+ if ( num == TX_STACKOVER ) strcpy(text, "Przepe³nienie stosu");
+ if ( num == TX_DELETEDPT ) strcpy(text, "Nieprawid³owy obiekt");
+ if ( num == TX_FILEOPEN ) strcpy(text, "Nie mo¿na otworzyæ pliku");
+ if ( num == TX_NOTOPEN ) strcpy(text, "Plik nie jest otwarty");
+ if ( num == TX_ERRREAD ) strcpy(text, "B³¹d odczytu");
+ if ( num == TX_ERRWRITE ) strcpy(text, "B³¹d zapisu");
+ }
+
+ if ( type == RES_KEY )
+ {
+ if ( num == 0 ) strcpy(text, "< brak >");
+ if ( num == VK_LEFT ) strcpy(text, "Strza³ka w lewo");
+ if ( num == VK_RIGHT ) strcpy(text, "Strza³ka w prawo");
+ if ( num == VK_UP ) strcpy(text, "Strza³ka w górê");
+ if ( num == VK_DOWN ) strcpy(text, "Strza³ka w dó³");
+ if ( num == VK_CANCEL ) strcpy(text, "Ctrl-break");
+ if ( num == VK_BACK ) strcpy(text, "<--");
+ if ( num == VK_TAB ) strcpy(text, "Tab");
+ if ( num == VK_CLEAR ) strcpy(text, "Delete");
+ if ( num == VK_RETURN ) strcpy(text, "Enter");
+ if ( num == VK_SHIFT ) strcpy(text, "Shift");
+ if ( num == VK_CONTROL ) strcpy(text, "Ctrl");
+ if ( num == VK_MENU ) strcpy(text, "Alt");
+ if ( num == VK_PAUSE ) strcpy(text, "Pause");
+ if ( num == VK_CAPITAL ) strcpy(text, "Caps Lock");
+ if ( num == VK_ESCAPE ) strcpy(text, "Esc");
+ if ( num == VK_SPACE ) strcpy(text, "Spacja");
+ if ( num == VK_PRIOR ) strcpy(text, "Page Up");
+ if ( num == VK_NEXT ) strcpy(text, "Page Down");
+ if ( num == VK_END ) strcpy(text, "End");
+ if ( num == VK_HOME ) strcpy(text, "Home");
+ if ( num == VK_SELECT ) strcpy(text, "Zaznacz");
+ if ( num == VK_EXECUTE ) strcpy(text, "Wykonaj");
+ if ( num == VK_SNAPSHOT ) strcpy(text, "Print Scrn");
+ if ( num == VK_INSERT ) strcpy(text, "Insert");
+ if ( num == VK_DELETE ) strcpy(text, "Delete");
+ if ( num == VK_HELP ) strcpy(text, "Pomoc");
+ if ( num == VK_LWIN ) strcpy(text, "Lewy klawisz Windows");
+ if ( num == VK_RWIN ) strcpy(text, "Prawy klawisz Windows");
+ if ( num == VK_APPS ) strcpy(text, "Klawisz menu kontekstowego");
+ if ( num == VK_NUMPAD0 ) strcpy(text, "Klaw. Num. 0");
+ if ( num == VK_NUMPAD1 ) strcpy(text, "Klaw. Num. 1");
+ if ( num == VK_NUMPAD2 ) strcpy(text, "Klaw. Num. 2");
+ if ( num == VK_NUMPAD3 ) strcpy(text, "Klaw. Num. 3");
+ if ( num == VK_NUMPAD4 ) strcpy(text, "Klaw. Num. 4");
+ if ( num == VK_NUMPAD5 ) strcpy(text, "Klaw. Num. 5");
+ if ( num == VK_NUMPAD6 ) strcpy(text, "Klaw. Num. 6");
+ if ( num == VK_NUMPAD7 ) strcpy(text, "Klaw. Num. 7");
+ if ( num == VK_NUMPAD8 ) strcpy(text, "Klaw. Num. 8");
+ if ( num == VK_NUMPAD9 ) strcpy(text, "Klaw. Num. 9");
+ if ( num == VK_MULTIPLY ) strcpy(text, "Klaw. Num. *");
+ if ( num == VK_ADD ) strcpy(text, "Klaw. Num. +");
+ if ( num == VK_SEPARATOR ) strcpy(text, "Klaw. Num. separator");
+ if ( num == VK_SUBTRACT ) strcpy(text, "Klaw. Num. -");
+ if ( num == VK_DECIMAL ) strcpy(text, "Klaw. Num. .");
+ if ( num == VK_DIVIDE ) strcpy(text, "Klaw. Num. /");
+ if ( num == VK_F1 ) strcpy(text, "F1");
+ if ( num == VK_F2 ) strcpy(text, "F2");
+ if ( num == VK_F3 ) strcpy(text, "F3");
+ if ( num == VK_F4 ) strcpy(text, "F4");
+ if ( num == VK_F5 ) strcpy(text, "F5");
+ if ( num == VK_F6 ) strcpy(text, "F6");
+ if ( num == VK_F7 ) strcpy(text, "F7");
+ if ( num == VK_F8 ) strcpy(text, "F8");
+ if ( num == VK_F9 ) strcpy(text, "F9");
+ if ( num == VK_F10 ) strcpy(text, "F10");
+ if ( num == VK_F11 ) strcpy(text, "F11");
+ if ( num == VK_F12 ) strcpy(text, "F12");
+ if ( num == VK_F13 ) strcpy(text, "F13");
+ if ( num == VK_F14 ) strcpy(text, "F14");
+ if ( num == VK_F15 ) strcpy(text, "F15");
+ if ( num == VK_F16 ) strcpy(text, "F16");
+ if ( num == VK_F17 ) strcpy(text, "F17");
+ if ( num == VK_F18 ) strcpy(text, "F18");
+ if ( num == VK_F19 ) strcpy(text, "F19");
+ if ( num == VK_F20 ) strcpy(text, "F20");
+ if ( num == VK_NUMLOCK ) strcpy(text, "Num Lock");
+ if ( num == VK_SCROLL ) strcpy(text, "Scroll Lock");
+ if ( num == VK_ATTN ) strcpy(text, "Attn");
+ if ( num == VK_CRSEL ) strcpy(text, "CrSel");
+ if ( num == VK_EXSEL ) strcpy(text, "ExSel");
+ if ( num == VK_EREOF ) strcpy(text, "Erase EOF");
+ if ( num == VK_PLAY ) strcpy(text, "Graj");
+ if ( num == VK_ZOOM ) strcpy(text, "Powiêkszenie");
+ if ( num == VK_PA1 ) strcpy(text, "PA1");
+ if ( num == VK_OEM_CLEAR ) strcpy(text, "WyczyϾ");
+ if ( num == VK_BUTTON1 ) strcpy(text, "Przycisk 1");
+ if ( num == VK_BUTTON2 ) strcpy(text, "Przycisk 2");
+ if ( num == VK_BUTTON3 ) strcpy(text, "Przycisk 3");
+ if ( num == VK_BUTTON4 ) strcpy(text, "Przycisk 4");
+ if ( num == VK_BUTTON5 ) strcpy(text, "Przycisk 5");
+ if ( num == VK_BUTTON6 ) strcpy(text, "Przycisk 6");
+ if ( num == VK_BUTTON7 ) strcpy(text, "Przycisk 7");
+ if ( num == VK_BUTTON8 ) strcpy(text, "Przycisk 8");
+ if ( num == VK_BUTTON9 ) strcpy(text, "Przycisk 9");
+ if ( num == VK_BUTTON10 ) strcpy(text, "Przycisk 10");
+ if ( num == VK_BUTTON11 ) strcpy(text, "Przycisk 11");
+ if ( num == VK_BUTTON12 ) strcpy(text, "Przycisk 12");
+ if ( num == VK_BUTTON13 ) strcpy(text, "Przycisk 13");
+ if ( num == VK_BUTTON14 ) strcpy(text, "Przycisk 14");
+ if ( num == VK_BUTTON15 ) strcpy(text, "Przycisk 15");
+ if ( num == VK_BUTTON16 ) strcpy(text, "Przycisk 16");
+ if ( num == VK_BUTTON17 ) strcpy(text, "Przycisk 17");
+ if ( num == VK_BUTTON18 ) strcpy(text, "Przycisk 18");
+ if ( num == VK_BUTTON19 ) strcpy(text, "Przycisk 19");
+ if ( num == VK_BUTTON20 ) strcpy(text, "Przycisk 20");
+ if ( num == VK_BUTTON21 ) strcpy(text, "Przycisk 21");
+ if ( num == VK_BUTTON22 ) strcpy(text, "Przycisk 22");
+ if ( num == VK_BUTTON23 ) strcpy(text, "Przycisk 23");
+ if ( num == VK_BUTTON24 ) strcpy(text, "Przycisk 24");
+ if ( num == VK_BUTTON25 ) strcpy(text, "Przycisk 25");
+ if ( num == VK_BUTTON26 ) strcpy(text, "Przycisk 26");
+ if ( num == VK_BUTTON27 ) strcpy(text, "Przycisk 27");
+ if ( num == VK_BUTTON28 ) strcpy(text, "Przycisk 28");
+ if ( num == VK_BUTTON29 ) strcpy(text, "Przycisk 29");
+ if ( num == VK_BUTTON30 ) strcpy(text, "Przycisk 30");
+ if ( num == VK_BUTTON31 ) strcpy(text, "Przycisk 31");
+ if ( num == VK_BUTTON32 ) strcpy(text, "Przycisk 32");
+ if ( num == VK_WHEELUP ) strcpy(text, "Kó³ko w górê");
+ if ( num == VK_WHEELDOWN ) strcpy(text, "Kó³ko w dó³");
+ }
+#endif
+
+ return ( text[0] != 0 );
+}
+
+
diff --git a/src/common/restext.h b/src/common/restext.h
index 241951a..d5f22de 100644
--- a/src/common/restext.h
+++ b/src/common/restext.h
@@ -1,158 +1,158 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// restext.h
-
-#pragma once
-
-
-#include "common/event.h"
-
-
-class CD3DEngine;
-
-
-
-
-// Possible types of the text resources.
-
-enum ResType
-{
- RES_TEXT = 0, // RT_*
- RES_EVENT = 1, // EVENT_* (EventMsg)
- RES_OBJECT = 2, // OBJECT_* (ObjectType)
- RES_ERR = 3, // ERR_* (Error)
- RES_KEY = 4, // VK_* (keys)
- RES_CBOT = 5, // TX_* (cbot.dll)
-};
-
-
-// Resources of type RES_TEXT.
-
-enum ResTextType
-{
- RT_VERSION_ID = 1,
- RT_DISINFO_TITLE = 2,
- RT_WINDOW_MAXIMIZED = 3,
- RT_WINDOW_MINIMIZED = 4,
- RT_WINDOW_STANDARD = 5,
- RT_WINDOW_CLOSE = 6,
-
- RT_STUDIO_TITLE = 10,
- RT_SCRIPT_NEW = 20,
- RT_NAME_DEFAULT = 21,
- RT_IO_NEW = 22,
- RT_KEY_OR = 23,
-
- RT_TITLE_BASE = 40,
- RT_TITLE_INIT = 41,
- RT_TITLE_TRAINER = 42,
- RT_TITLE_DEFI = 43,
- RT_TITLE_MISSION = 44,
- RT_TITLE_FREE = 45,
- RT_TITLE_PROTO = 46,
- RT_TITLE_SETUP = 47,
- RT_TITLE_NAME = 48,
- RT_TITLE_PERSO = 49,
- RT_TITLE_WRITE = 50,
- RT_TITLE_READ = 51,
- RT_TITLE_USER = 52,
- RT_TITLE_TEEN = 53,
-
- RT_PLAY_CHAPt = 60,
- RT_PLAY_CHAPd = 61,
- RT_PLAY_CHAPm = 62,
- RT_PLAY_CHAPf = 63,
- RT_PLAY_CHAPp = 64,
- RT_PLAY_LISTt = 65,
- RT_PLAY_LISTd = 66,
- RT_PLAY_LISTm = 67,
- RT_PLAY_LISTf = 68,
- RT_PLAY_LISTp = 69,
- RT_PLAY_RESUME = 70,
- RT_PLAY_CHAPu = 71,
- RT_PLAY_LISTu = 72,
- RT_PLAY_CHAPte = 73,
- RT_PLAY_LISTk = 74,
-
- RT_SETUP_DEVICE = 80,
- RT_SETUP_MODE = 81,
- RT_SETUP_KEY1 = 82,
- RT_SETUP_KEY2 = 83,
-
- RT_PERSO_FACE = 90,
- RT_PERSO_GLASSES = 91,
- RT_PERSO_HAIR = 92,
- RT_PERSO_COMBI = 93,
- RT_PERSO_BAND = 94,
-
- RT_DIALOG_TITLE = 100,
- RT_DIALOG_ABORT = 101,
- RT_DIALOG_QUIT = 102,
- RT_DIALOG_YES = 103,
- RT_DIALOG_NO = 104,
- RT_DIALOG_DELOBJ = 105,
- RT_DIALOG_DELGAME = 106,
- RT_DIALOG_YESDEL = 107,
- RT_DIALOG_NODEL = 108,
- RT_DIALOG_LOADING = 109,
- RT_DIALOG_YESQUIT = 110,
- RT_DIALOG_NOQUIT = 111,
-
- RT_STUDIO_LISTTT = 120,
- RT_STUDIO_COMPOK = 121,
- RT_STUDIO_PROGSTOP = 122,
-
- RT_SATCOM_LIST = 140,
- RT_SATCOM_BOT = 141,
- RT_SATCOM_BUILDING = 142,
- RT_SATCOM_FRET = 143,
- RT_SATCOM_ALIEN = 144,
- RT_SATCOM_NULL = 145,
- RT_SATCOM_ERROR1 = 146,
- RT_SATCOM_ERROR2 = 147,
-
- RT_IO_OPEN = 150,
- RT_IO_SAVE = 151,
- RT_IO_LIST = 152,
- RT_IO_NAME = 153,
- RT_IO_DIR = 154,
- RT_IO_PRIVATE = 155,
- RT_IO_PUBLIC = 156,
-
- RT_GENERIC_DEV1 = 170,
- RT_GENERIC_DEV2 = 171,
- RT_GENERIC_EDIT1 = 172,
- RT_GENERIC_EDIT2 = 173,
-
- RT_INTERFACE_REC = 180,
-
- RT_MESSAGE_WIN = 200,
- RT_MESSAGE_LOST = 201,
-};
-
-
-static CD3DEngine* g_engine = 0;
-static char g_gamerName[100];
-
-extern void SetEngine(CD3DEngine *engine);
-extern void SetGlobalGamerName(char *name);
-extern bool SearchKey(char *cmd, KeyRank &key);
-extern void PutKeyName(char* dst, char* src);
-extern bool GetResource(ResType type, int num, char* text);
-extern bool GetResourceBase(ResType type, int num, char* text);
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// restext.h
+
+#pragma once
+
+
+#include "common/event.h"
+
+
+class CD3DEngine;
+
+
+
+
+// Possible types of the text resources.
+
+enum ResType
+{
+ RES_TEXT = 0, // RT_*
+ RES_EVENT = 1, // EVENT_* (EventMsg)
+ RES_OBJECT = 2, // OBJECT_* (ObjectType)
+ RES_ERR = 3, // ERR_* (Error)
+ RES_KEY = 4, // VK_* (keys)
+ RES_CBOT = 5, // TX_* (cbot.dll)
+};
+
+
+// Resources of type RES_TEXT.
+
+enum ResTextType
+{
+ RT_VERSION_ID = 1,
+ RT_DISINFO_TITLE = 2,
+ RT_WINDOW_MAXIMIZED = 3,
+ RT_WINDOW_MINIMIZED = 4,
+ RT_WINDOW_STANDARD = 5,
+ RT_WINDOW_CLOSE = 6,
+
+ RT_STUDIO_TITLE = 10,
+ RT_SCRIPT_NEW = 20,
+ RT_NAME_DEFAULT = 21,
+ RT_IO_NEW = 22,
+ RT_KEY_OR = 23,
+
+ RT_TITLE_BASE = 40,
+ RT_TITLE_INIT = 41,
+ RT_TITLE_TRAINER = 42,
+ RT_TITLE_DEFI = 43,
+ RT_TITLE_MISSION = 44,
+ RT_TITLE_FREE = 45,
+ RT_TITLE_PROTO = 46,
+ RT_TITLE_SETUP = 47,
+ RT_TITLE_NAME = 48,
+ RT_TITLE_PERSO = 49,
+ RT_TITLE_WRITE = 50,
+ RT_TITLE_READ = 51,
+ RT_TITLE_USER = 52,
+ RT_TITLE_TEEN = 53,
+
+ RT_PLAY_CHAPt = 60,
+ RT_PLAY_CHAPd = 61,
+ RT_PLAY_CHAPm = 62,
+ RT_PLAY_CHAPf = 63,
+ RT_PLAY_CHAPp = 64,
+ RT_PLAY_LISTt = 65,
+ RT_PLAY_LISTd = 66,
+ RT_PLAY_LISTm = 67,
+ RT_PLAY_LISTf = 68,
+ RT_PLAY_LISTp = 69,
+ RT_PLAY_RESUME = 70,
+ RT_PLAY_CHAPu = 71,
+ RT_PLAY_LISTu = 72,
+ RT_PLAY_CHAPte = 73,
+ RT_PLAY_LISTk = 74,
+
+ RT_SETUP_DEVICE = 80,
+ RT_SETUP_MODE = 81,
+ RT_SETUP_KEY1 = 82,
+ RT_SETUP_KEY2 = 83,
+
+ RT_PERSO_FACE = 90,
+ RT_PERSO_GLASSES = 91,
+ RT_PERSO_HAIR = 92,
+ RT_PERSO_COMBI = 93,
+ RT_PERSO_BAND = 94,
+
+ RT_DIALOG_TITLE = 100,
+ RT_DIALOG_ABORT = 101,
+ RT_DIALOG_QUIT = 102,
+ RT_DIALOG_YES = 103,
+ RT_DIALOG_NO = 104,
+ RT_DIALOG_DELOBJ = 105,
+ RT_DIALOG_DELGAME = 106,
+ RT_DIALOG_YESDEL = 107,
+ RT_DIALOG_NODEL = 108,
+ RT_DIALOG_LOADING = 109,
+ RT_DIALOG_YESQUIT = 110,
+ RT_DIALOG_NOQUIT = 111,
+
+ RT_STUDIO_LISTTT = 120,
+ RT_STUDIO_COMPOK = 121,
+ RT_STUDIO_PROGSTOP = 122,
+
+ RT_SATCOM_LIST = 140,
+ RT_SATCOM_BOT = 141,
+ RT_SATCOM_BUILDING = 142,
+ RT_SATCOM_FRET = 143,
+ RT_SATCOM_ALIEN = 144,
+ RT_SATCOM_NULL = 145,
+ RT_SATCOM_ERROR1 = 146,
+ RT_SATCOM_ERROR2 = 147,
+
+ RT_IO_OPEN = 150,
+ RT_IO_SAVE = 151,
+ RT_IO_LIST = 152,
+ RT_IO_NAME = 153,
+ RT_IO_DIR = 154,
+ RT_IO_PRIVATE = 155,
+ RT_IO_PUBLIC = 156,
+
+ RT_GENERIC_DEV1 = 170,
+ RT_GENERIC_DEV2 = 171,
+ RT_GENERIC_EDIT1 = 172,
+ RT_GENERIC_EDIT2 = 173,
+
+ RT_INTERFACE_REC = 180,
+
+ RT_MESSAGE_WIN = 200,
+ RT_MESSAGE_LOST = 201,
+};
+
+
+static CD3DEngine* g_engine = 0;
+static char g_gamerName[100];
+
+extern void SetEngine(CD3DEngine *engine);
+extern void SetGlobalGamerName(char *name);
+extern bool SearchKey(char *cmd, KeyRank &key);
+extern void PutKeyName(char* dst, char* src);
+extern bool GetResource(ResType type, int num, char* text);
+extern bool GetResourceBase(ResType type, int num, char* text);
+
+
diff --git a/src/common/struct.h b/src/common/struct.h
index b143334..45ac314 100644
--- a/src/common/struct.h
+++ b/src/common/struct.h
@@ -1,54 +1,54 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// struct.h
-
-#pragma once
-
-
-#include <math/vector.h>
-
-
-#define D3DFVF_VERTEX2 (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX2)
-
-struct D3DVERTEX2
-{
- float x,y,z;
- float nx,ny,nz;
- float tu, tv;
- float tu2, tv2;
-
- D3DVERTEX2() { }
- D3DVERTEX2(const Math::Vector& _v, const Math::Vector& _n, float _tu=0.0f, float _tv=0.0f, float _tu2=0.0f, float _tv2=0.0f)
- {
- x = _v.x;
- y = _v.y;
- z = _v.z;
- nx = _n.x;
- ny = _n.y;
- nz = _n.z;
- tu = _tu;
- tv = _tv;
- tu2 = _tu2;
- tv2 = _tv2;
- }
-};
-
-
-struct ColorHSV
-{
- float h,s,v;
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// struct.h
+
+#pragma once
+
+
+#include <math/vector.h>
+
+
+#define D3DFVF_VERTEX2 (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX2)
+
+struct D3DVERTEX2
+{
+ float x,y,z;
+ float nx,ny,nz;
+ float tu, tv;
+ float tu2, tv2;
+
+ D3DVERTEX2() { }
+ D3DVERTEX2(const Math::Vector& _v, const Math::Vector& _n, float _tu=0.0f, float _tv=0.0f, float _tu2=0.0f, float _tv2=0.0f)
+ {
+ x = _v.x;
+ y = _v.y;
+ z = _v.z;
+ nx = _n.x;
+ ny = _n.y;
+ nz = _n.z;
+ tu = _tu;
+ tv = _tv;
+ tu2 = _tu2;
+ tv2 = _tv2;
+ }
+};
+
+
+struct ColorHSV
+{
+ float h,s,v;
}; \ No newline at end of file
diff --git a/src/graphics/common/camera.h b/src/graphics/common/camera.h
index 28397b9..f17ecef 100644
--- a/src/graphics/common/camera.h
+++ b/src/graphics/common/camera.h
@@ -34,238 +34,238 @@ namespace Gfx {
enum CameraType
{
- CAMERA_NULL = 0, // camera undefined
- CAMERA_FREE = 1, // camera free (never in principle)
- CAMERA_EDIT = 2, // camera while editing a program
- CAMERA_ONBOARD = 3, // camera on board a robot
- CAMERA_BACK = 4, // camera behind a robot
- CAMERA_FIX = 5, // static camera following robot
- CAMERA_EXPLO = 6, // camera steady after explosion
- CAMERA_SCRIPT = 7, // camera during a film script
- CAMERA_INFO = 8, // camera for displaying information
- CAMERA_VISIT = 9, // visit instead of an error
- CAMERA_DIALOG = 10, // camera for dialogue
- CAMERA_PLANE = 11, // static camera height
+ CAMERA_NULL = 0, // camera undefined
+ CAMERA_FREE = 1, // camera free (never in principle)
+ CAMERA_EDIT = 2, // camera while editing a program
+ CAMERA_ONBOARD = 3, // camera on board a robot
+ CAMERA_BACK = 4, // camera behind a robot
+ CAMERA_FIX = 5, // static camera following robot
+ CAMERA_EXPLO = 6, // camera steady after explosion
+ CAMERA_SCRIPT = 7, // camera during a film script
+ CAMERA_INFO = 8, // camera for displaying information
+ CAMERA_VISIT = 9, // visit instead of an error
+ CAMERA_DIALOG = 10, // camera for dialogue
+ CAMERA_PLANE = 11, // static camera height
};
enum CameraSmooth
{
- CS_NONE = 0, // sharp
- CS_NORM = 1, // normal
- CS_HARD = 2, // hard
- CS_SPEC = 3, // special
+ CS_NONE = 0, // sharp
+ CS_NORM = 1, // normal
+ CS_HARD = 2, // hard
+ CS_SPEC = 3, // special
};
enum CenteringPhase
{
- CP_NULL = 0,
- CP_START = 1,
- CP_WAIT = 2,
- CP_STOP = 3,
+ CP_NULL = 0,
+ CP_START = 1,
+ CP_WAIT = 2,
+ CP_STOP = 3,
};
enum CameraEffect
{
- CE_NULL = 0, // no effect
- CE_TERRAFORM = 1, // digging in
- CE_CRASH = 2, // Vehicle driving is severely
- CE_EXPLO = 3, // explosion
- CE_SHOT = 4, // not mortal shot
- CE_VIBRATION = 5, // vibration during construction
- CE_PET = 6, // spleen reactor
+ CE_NULL = 0, // no effect
+ CE_TERRAFORM = 1, // digging in
+ CE_CRASH = 2, // Vehicle driving is severely
+ CE_EXPLO = 3, // explosion
+ CE_SHOT = 4, // not mortal shot
+ CE_VIBRATION = 5, // vibration during construction
+ CE_PET = 6, // spleen reactor
};
enum OverEffect
{
- OE_NULL = 0, // no effect
- OE_BLOOD = 1, // flash red
- OE_FADEINw = 2, // white -> nothing
- OE_FADEOUTw = 3, // nothing -> white
- OE_FADEOUTb = 4, // nothing -> blue
- OE_BLITZ = 5, // lightning
+ OE_NULL = 0, // no effect
+ OE_BLOOD = 1, // flash red
+ OE_FADEINw = 2, // white -> nothing
+ OE_FADEOUTw = 3, // nothing -> white
+ OE_FADEOUTb = 4, // nothing -> blue
+ OE_BLITZ = 5, // lightning
};
class CCamera {
- public:
- CCamera(CInstanceManager* iMan);
- ~CCamera();
+ public:
+ CCamera(CInstanceManager* iMan);
+ ~CCamera();
- bool EventProcess(const Event &event);
+ bool EventProcess(const Event &event);
- void Init(Math::Vector eye, Math::Vector lookat, float delay);
+ void Init(Math::Vector eye, Math::Vector lookat, float delay);
- void SetObject(CObject* object);
- CObject* RetObject();
+ void SetObject(CObject* object);
+ CObject* RetObject();
- void SetType(CameraType type);
- CameraType RetType();
+ void SetType(CameraType type);
+ CameraType RetType();
- void SetSmooth(CameraSmooth type);
- CameraSmooth RetSmoth();
+ void SetSmooth(CameraSmooth type);
+ CameraSmooth RetSmoth();
- void SetDist(float dist);
- float RetDist();
+ void SetDist(float dist);
+ float RetDist();
- void SetFixDirection(float angle);
- float RetFixDirection();
+ void SetFixDirection(float angle);
+ float RetFixDirection();
- void SetRemotePan(float value);
- float RetRemotePan();
+ void SetRemotePan(float value);
+ float RetRemotePan();
- void SetRemoteZoom(float value);
- float RetRemoteZoom();
+ void SetRemoteZoom(float value);
+ float RetRemoteZoom();
- void StartVisit(Math::Vector goal, float dist);
- void StopVisit();
+ void StartVisit(Math::Vector goal, float dist);
+ void StopVisit();
- void RetCamera(Math::Vector &eye, Math::Vector &lookat);
+ void RetCamera(Math::Vector &eye, Math::Vector &lookat);
- bool StartCentering(CObject *object, float angleH, float angleV, float dist, float time);
- bool StopCentering(CObject *object, float time);
- void AbortCentering();
+ bool StartCentering(CObject *object, float angleH, float angleV, float dist, float time);
+ bool StopCentering(CObject *object, float time);
+ void AbortCentering();
- void FlushEffect();
- void StartEffect(CameraEffect effect, Math::Vector pos, float force);
+ void FlushEffect();
+ void StartEffect(CameraEffect effect, Math::Vector pos, float force);
- void FlushOver();
- void SetOverBaseColor(Gfx::Color color);
- void StartOver(OverEffect effect, Math::Vector pos, float force);
+ void FlushOver();
+ void SetOverBaseColor(Gfx::Color color);
+ void StartOver(OverEffect effect, Math::Vector pos, float force);
- void FixCamera();
- void SetScriptEye(Math::Vector eye);
- void SetScriptLookat(Math::Vector lookat);
+ void FixCamera();
+ void SetScriptEye(Math::Vector eye);
+ void SetScriptLookat(Math::Vector lookat);
- void SetEffect(bool bEnable);
- void SetCameraScroll(bool bScroll);
- void SetCameraInvertX(bool bInvert);
- void SetCameraInvertY(bool bInvert);
+ void SetEffect(bool bEnable);
+ void SetCameraScroll(bool bScroll);
+ void SetCameraInvertX(bool bInvert);
+ void SetCameraInvertY(bool bInvert);
- float RetMotorTurn();
- Gfx::MouseType RetMouseDef(Math::Point pos);
+ float RetMotorTurn();
+ Gfx::MouseType RetMouseDef(Math::Point pos);
protected:
- bool EventMouseMove(const Event &event);
- void EventMouseWheel(int dir);
- bool EventFrame(const Event &event);
- bool EventFrameFree(const Event &event);
- bool EventFrameEdit(const Event &event);
- bool EventFrameDialog(const Event &event);
- bool EventFrameBack(const Event &event);
- bool EventFrameFix(const Event &event);
- bool EventFrameExplo(const Event &event);
- bool EventFrameOnBoard(const Event &event);
- bool EventFrameInfo(const Event &event);
- bool EventFrameVisit(const Event &event);
- bool EventFrameScript(const Event &event);
-
- void SetViewTime(const Math::Vector &vEyePt, const Math::Vector &vLookatPt, float rTime);
- bool IsCollision(Math::Vector &eye, Math::Vector lookat);
- bool IsCollisionBack(Math::Vector &eye, Math::Vector lookat);
- bool IsCollisionFix(Math::Vector &eye, Math::Vector lookat);
-
- Math::Vector ExcludeTerrain(Math::Vector eye, Math::Vector lookat, float &angleH, float &angleV);
- Math::Vector ExcludeObject(Math::Vector eye, Math::Vector lookat, float &angleH, float &angleV);
-
- void SetViewParams(const Math::Vector &eye, const Math::Vector &lookat, const Math::Vector &up);
- void EffectFrame(const Event &event);
- void OverFrame(const Event &event);
+ bool EventMouseMove(const Event &event);
+ void EventMouseWheel(int dir);
+ bool EventFrame(const Event &event);
+ bool EventFrameFree(const Event &event);
+ bool EventFrameEdit(const Event &event);
+ bool EventFrameDialog(const Event &event);
+ bool EventFrameBack(const Event &event);
+ bool EventFrameFix(const Event &event);
+ bool EventFrameExplo(const Event &event);
+ bool EventFrameOnBoard(const Event &event);
+ bool EventFrameInfo(const Event &event);
+ bool EventFrameVisit(const Event &event);
+ bool EventFrameScript(const Event &event);
+
+ void SetViewTime(const Math::Vector &vEyePt, const Math::Vector &vLookatPt, float rTime);
+ bool IsCollision(Math::Vector &eye, Math::Vector lookat);
+ bool IsCollisionBack(Math::Vector &eye, Math::Vector lookat);
+ bool IsCollisionFix(Math::Vector &eye, Math::Vector lookat);
+
+ Math::Vector ExcludeTerrain(Math::Vector eye, Math::Vector lookat, float &angleH, float &angleV);
+ Math::Vector ExcludeObject(Math::Vector eye, Math::Vector lookat, float &angleH, float &angleV);
+
+ void SetViewParams(const Math::Vector &eye, const Math::Vector &lookat, const Math::Vector &up);
+ void EffectFrame(const Event &event);
+ void OverFrame(const Event &event);
protected:
- CInstanceManager* m_iMan;
- Gfx::CEngine* m_engine;
- CTerrain* m_terrain;
- CWater* m_water;
-
- CameraType m_type; // the type of camera (CAMERA *)
- CameraSmooth m_smooth; // type of smoothing
- CObject* m_cameraObj; // object linked to the camera
-
- float m_eyeDistance; // distance between the eyes
- float m_initDelay; // time of initial centering
-
- Math::Vector m_actualEye; // current eye
- Math::Vector m_actualLookat; // aim current
- Math::Vector m_finalEye; // final eye
- Math::Vector m_finalLookat; // aim final
- Math::Vector m_normEye; // normal eye
- Math::Vector m_normLookat; // aim normal
- float m_focus;
-
- bool m_bRightDown;
- Math::Point m_rightPosInit;
- Math::Point m_rightPosCenter;
- Math::Point m_rightPosMove;
-
- Math::Vector m_eyePt; // CAMERA_FREE: eye
- float m_directionH; // CAMERA_FREE: horizontal direction
- float m_directionV; // CAMERA_FREE: vertical direction
- float m_heightEye; // CAMERA_FREE: height above the ground
- float m_heightLookat; // CAMERA_FREE: height above the ground
- float m_speed; // CAMERA_FREE: speed of movement
-
- float m_backDist; // CAMERA_BACK: distance
- float m_backMin; // CAMERA_BACK: distance minimal
- float m_addDirectionH; // CAMERA_BACK: additional direction
- float m_addDirectionV; // CAMERA_BACK: additional direction
- bool m_bTransparency;
-
- float m_fixDist; // CAMERA_FIX: distance
- float m_fixDirectionH; // CAMERA_FIX: direction
- float m_fixDirectionV; // CAMERA_FIX: direction
-
- Math::Vector m_visitGoal; // CAMERA_VISIT: target position
- float m_visitDist; // CAMERA_VISIT: distance
- float m_visitTime; // CAMERA_VISIT: relative time
- CameraType m_visitType; // CAMERA_VISIT: initial type
- float m_visitDirectionH; // CAMERA_VISIT: direction
- float m_visitDirectionV; // CAMERA_VISIT: direction
-
- float m_editHeight; // CAMERA_EDIT: height
-
- float m_remotePan;
- float m_remoteZoom;
-
- Math::Point m_mousePos;
- float m_mouseDirH;
- float m_mouseDirV;
- float m_mouseMarging;
-
- float m_motorTurn;
-
- CenteringPhase m_centeringPhase;
- float m_centeringAngleH;
- float m_centeringAngleV;
- float m_centeringDist;
- float m_centeringCurrentH;
- float m_centeringCurrentV;
- float m_centeringTime;
- float m_centeringProgress;
-
- CameraEffect m_effectType;
- Math::Vector m_effectPos;
- float m_effectForce;
- float m_effectProgress;
- Math::Vector m_effectOffset;
-
- OverEffect m_overType;
- float m_overForce;
- float m_overTime;
- Gfx::Color m_overColorBase;
- Gfx::Color m_overColor;
- int m_overMode;
- float m_overFadeIn;
- float m_overFadeOut;
-
- Math::Vector m_scriptEye;
- Math::Vector m_scriptLookat;
-
- bool m_bEffect; // shocks if explosion?
- bool m_bCameraScroll; // scroll in the edges?
- bool m_bCameraInvertX; // X inversion in the edges?
- bool m_bCameraInvertY; // Y inversion in the edges?
+ CInstanceManager* m_iMan;
+ Gfx::CEngine* m_engine;
+ CTerrain* m_terrain;
+ CWater* m_water;
+
+ CameraType m_type; // the type of camera (CAMERA *)
+ CameraSmooth m_smooth; // type of smoothing
+ CObject* m_cameraObj; // object linked to the camera
+
+ float m_eyeDistance; // distance between the eyes
+ float m_initDelay; // time of initial centering
+
+ Math::Vector m_actualEye; // current eye
+ Math::Vector m_actualLookat; // aim current
+ Math::Vector m_finalEye; // final eye
+ Math::Vector m_finalLookat; // aim final
+ Math::Vector m_normEye; // normal eye
+ Math::Vector m_normLookat; // aim normal
+ float m_focus;
+
+ bool m_bRightDown;
+ Math::Point m_rightPosInit;
+ Math::Point m_rightPosCenter;
+ Math::Point m_rightPosMove;
+
+ Math::Vector m_eyePt; // CAMERA_FREE: eye
+ float m_directionH; // CAMERA_FREE: horizontal direction
+ float m_directionV; // CAMERA_FREE: vertical direction
+ float m_heightEye; // CAMERA_FREE: height above the ground
+ float m_heightLookat; // CAMERA_FREE: height above the ground
+ float m_speed; // CAMERA_FREE: speed of movement
+
+ float m_backDist; // CAMERA_BACK: distance
+ float m_backMin; // CAMERA_BACK: distance minimal
+ float m_addDirectionH; // CAMERA_BACK: additional direction
+ float m_addDirectionV; // CAMERA_BACK: additional direction
+ bool m_bTransparency;
+
+ float m_fixDist; // CAMERA_FIX: distance
+ float m_fixDirectionH; // CAMERA_FIX: direction
+ float m_fixDirectionV; // CAMERA_FIX: direction
+
+ Math::Vector m_visitGoal; // CAMERA_VISIT: target position
+ float m_visitDist; // CAMERA_VISIT: distance
+ float m_visitTime; // CAMERA_VISIT: relative time
+ CameraType m_visitType; // CAMERA_VISIT: initial type
+ float m_visitDirectionH; // CAMERA_VISIT: direction
+ float m_visitDirectionV; // CAMERA_VISIT: direction
+
+ float m_editHeight; // CAMERA_EDIT: height
+
+ float m_remotePan;
+ float m_remoteZoom;
+
+ Math::Point m_mousePos;
+ float m_mouseDirH;
+ float m_mouseDirV;
+ float m_mouseMarging;
+
+ float m_motorTurn;
+
+ CenteringPhase m_centeringPhase;
+ float m_centeringAngleH;
+ float m_centeringAngleV;
+ float m_centeringDist;
+ float m_centeringCurrentH;
+ float m_centeringCurrentV;
+ float m_centeringTime;
+ float m_centeringProgress;
+
+ CameraEffect m_effectType;
+ Math::Vector m_effectPos;
+ float m_effectForce;
+ float m_effectProgress;
+ Math::Vector m_effectOffset;
+
+ OverEffect m_overType;
+ float m_overForce;
+ float m_overTime;
+ Gfx::Color m_overColorBase;
+ Gfx::Color m_overColor;
+ int m_overMode;
+ float m_overFadeIn;
+ float m_overFadeOut;
+
+ Math::Vector m_scriptEye;
+ Math::Vector m_scriptLookat;
+
+ bool m_bEffect; // shocks if explosion?
+ bool m_bCameraScroll; // scroll in the edges?
+ bool m_bCameraInvertX; // X inversion in the edges?
+ bool m_bCameraInvertY; // Y inversion in the edges?
};
diff --git a/src/graphics/common/cloud.h b/src/graphics/common/cloud.h
index 9ca8c11..19b689f 100644
--- a/src/graphics/common/cloud.h
+++ b/src/graphics/common/cloud.h
@@ -38,56 +38,56 @@ const short MAXCLOUDLINE = 100;
struct CloudLine
{
- short x, y; // beginning
- short len; // in length x
- float px1, px2, pz;
+ short x, y; // beginning
+ short len; // in length x
+ float px1, px2, pz;
};
class CCloud
{
public:
- CCloud(CInstanceManager* iMan, CEngine* engine);
- ~CCloud();
+ CCloud(CInstanceManager* iMan, CEngine* engine);
+ ~CCloud();
- bool EventProcess(const Event &event);
- void Flush();
- bool Create(const char *filename, Gfx::Color diffuse, Gfx::Color ambient, float level);
- void Draw();
+ bool EventProcess(const Event &event);
+ void Flush();
+ bool Create(const char *filename, Gfx::Color diffuse, Gfx::Color ambient, float level);
+ void Draw();
- bool SetLevel(float level);
- float RetLevel();
+ bool SetLevel(float level);
+ float RetLevel();
- void SetEnable(bool bEnable);
- bool RetEnable();
+ void SetEnable(bool bEnable);
+ bool RetEnable();
protected:
- bool EventFrame(const Event &event);
- void AdjustLevel(Math::Vector &pos, Math::Vector &eye, float deep, Math::Point &uv1, Math::Point &uv2);
- bool CreateLine(int x, int y, int len);
+ bool EventFrame(const Event &event);
+ void AdjustLevel(Math::Vector &pos, Math::Vector &eye, float deep, Math::Point &uv1, Math::Point &uv2);
+ bool CreateLine(int x, int y, int len);
protected:
- CInstanceManager* m_iMan;
- CEngine* m_engine;
- CTerrain* m_terrain;
-
- char m_filename[100];
- float m_level; // overall level
- Math::Point m_speed; // feedrate (wind)
- Gfx::Color m_diffuse; // diffuse color
- Gfx::Color m_ambient; // ambient color
- float m_time;
- float m_lastTest;
- int m_subdiv;
-
- Math::Vector m_wind; // wind speed
- int m_brick; // brick mosaic
- float m_size; // size of a brick element
-
- int m_lineUsed;
- CloudLine m_line[MAXCLOUDLINE];
-
- bool m_bEnable;
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
+ CTerrain* m_terrain;
+
+ char m_filename[100];
+ float m_level; // overall level
+ Math::Point m_speed; // feedrate (wind)
+ Gfx::Color m_diffuse; // diffuse color
+ Gfx::Color m_ambient; // ambient color
+ float m_time;
+ float m_lastTest;
+ int m_subdiv;
+
+ Math::Vector m_wind; // wind speed
+ int m_brick; // brick mosaic
+ float m_size; // size of a brick element
+
+ int m_lineUsed;
+ CloudLine m_line[MAXCLOUDLINE];
+
+ bool m_bEnable;
};
diff --git a/src/graphics/common/color.h b/src/graphics/common/color.h
index 146e515..12f008f 100644
--- a/src/graphics/common/color.h
+++ b/src/graphics/common/color.h
@@ -23,19 +23,19 @@ namespace Gfx {
struct Color
{
- float r, g, b, a;
+ float r, g, b, a;
- Color(float aR = 0.0f, float aG = 0.0f, float aB = 0.0f, float aA = 0.0f)
- : r(aR), g(aG), b(aB), a(aA) {}
+ Color(float aR = 0.0f, float aG = 0.0f, float aB = 0.0f, float aA = 0.0f)
+ : r(aR), g(aG), b(aB), a(aA) {}
};
struct ColorHSV
{
- float h, s, v;
+ float h, s, v;
- ColorHSV(float aH = 0.0f, float aS = 0.0f, float aV = 0.0f)
- : h(aH), s(aS), v(aV) {}
+ ColorHSV(float aH = 0.0f, float aS = 0.0f, float aV = 0.0f)
+ : h(aH), s(aS), v(aV) {}
};
diff --git a/src/graphics/common/device.cpp b/src/graphics/common/device.cpp
index 2e3db61..53274b3 100644
--- a/src/graphics/common/device.cpp
+++ b/src/graphics/common/device.cpp
@@ -3,12 +3,12 @@
//! Sets the default values
Gfx::DeviceConfig::DeviceConfig()
{
- width = 800;
- height = 600;
- bpp = 16;
- fullScreen = false;
- resizeable = false;
- hardwareAccel = true;
- doubleBuf = true;
- noFrame = false;
+ width = 800;
+ height = 600;
+ bpp = 16;
+ fullScreen = false;
+ resizeable = false;
+ hardwareAccel = true;
+ doubleBuf = true;
+ noFrame = false;
} \ No newline at end of file
diff --git a/src/graphics/common/device.h b/src/graphics/common/device.h
index cd52fa5..5900570 100644
--- a/src/graphics/common/device.h
+++ b/src/graphics/common/device.h
@@ -24,24 +24,24 @@ namespace Gfx {
struct DeviceConfig
{
- //! Screen width
- int width;
- //! Screen height
- int height;
- //! Bits per pixel
- int bpp;
- //! Full screen
- bool fullScreen;
- //! Resizeable window
- bool resizeable;
- //! Hardware acceleration
- bool hardwareAccel;
- //! Double buffering
- bool doubleBuf;
- //! No window frame (also set with full screen)
- bool noFrame;
-
- DeviceConfig();
+ //! Screen width
+ int width;
+ //! Screen height
+ int height;
+ //! Bits per pixel
+ int bpp;
+ //! Full screen
+ bool fullScreen;
+ //! Resizeable window
+ bool resizeable;
+ //! Hardware acceleration
+ bool hardwareAccel;
+ //! Double buffering
+ bool doubleBuf;
+ //! No window frame (also set with full screen)
+ bool noFrame;
+
+ DeviceConfig();
};
class CDevice
diff --git a/src/graphics/common/engine.cpp b/src/graphics/common/engine.cpp
index 29857ce..3b9a89d 100644
--- a/src/graphics/common/engine.cpp
+++ b/src/graphics/common/engine.cpp
@@ -27,47 +27,47 @@
Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app)
{
- // TODO
+ // TODO
}
Gfx::CEngine::~CEngine()
{
- // TODO
+ // TODO
}
int Gfx::CEngine::Render()
{
- /* Just a hello world for now */
+ /* Just a hello world for now */
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glShadeModel(GL_SMOOTH);
- glDisable(GL_DEPTH_TEST);
- glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glShadeModel(GL_SMOOTH);
+ glDisable(GL_DEPTH_TEST);
+ glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluOrtho2D(-10.0f, 10.0f, -10.0f, 10.0f);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluOrtho2D(-10.0f, 10.0f, -10.0f, 10.0f);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- //glTranslatef(0.0f, 0.0f, -6.0f);
+ //glTranslatef(0.0f, 0.0f, -6.0f);
- glBegin(GL_TRIANGLES);
- {
- glColor3f(1.0f, 0.0f, 0.0f);
- glVertex2f(-2.0f, -1.0f);
- glColor3f(0.0f, 1.0f, 0.0f);
- glVertex2f(2.0f, -1.0f);
- glColor3f(0.0f, 0.0f, 1.0f);
- glVertex2f(0.0f, 1.5f);
- }
- glEnd();
+ glBegin(GL_TRIANGLES);
+ {
+ glColor3f(1.0f, 0.0f, 0.0f);
+ glVertex2f(-2.0f, -1.0f);
+ glColor3f(0.0f, 1.0f, 0.0f);
+ glVertex2f(2.0f, -1.0f);
+ glColor3f(0.0f, 0.0f, 1.0f);
+ glVertex2f(0.0f, 1.5f);
+ }
+ glEnd();
- glFlush();
+ glFlush();
- return 1;
+ return 1;
}
diff --git a/src/graphics/common/engine.h b/src/graphics/common/engine.h
index fd99399..6d2937c 100644
--- a/src/graphics/common/engine.h
+++ b/src/graphics/common/engine.h
@@ -48,237 +48,237 @@ class CPlanet;
class CTerrain;
-//const int MAXOBJECT = 1200;
-//const int MAXSHADOW = 500;
-//const int MAXGROUNDSPOT = 100;
+//const int MAXOBJECT = 1200;
+//const int MAXSHADOW = 500;
+//const int MAXGROUNDSPOT = 100;
enum ObjectType
{
- //! Object doesn't exist
- OBJTYPE_NULL = 0,
- //! Terrain
- OBJTYPE_TERRAIN = 1,
- //! Fixed object
- OBJTYPE_FIX = 2,
- //! Moving object
- OBJTYPE_VEHICULE = 3,
- //! Part of a moving object
- OBJTYPE_DESCENDANT = 4,
- //! Fixed object type quartz
- OBJTYPE_QUARTZ = 5,
- //! Fixed object type metal
- OBJTYPE_METAL = 6
+ //! Object doesn't exist
+ OBJTYPE_NULL = 0,
+ //! Terrain
+ OBJTYPE_TERRAIN = 1,
+ //! Fixed object
+ OBJTYPE_FIX = 2,
+ //! Moving object
+ OBJTYPE_VEHICULE = 3,
+ //! Part of a moving object
+ OBJTYPE_DESCENDANT = 4,
+ //! Fixed object type quartz
+ OBJTYPE_QUARTZ = 5,
+ //! Fixed object type metal
+ OBJTYPE_METAL = 6
};
enum TriangleType
{
- //! triangles
- TRIANGLE_TYPE_6T = 1,
- //! surfaces
- TRIANGLE_TYPE_6S = 2
+ //! triangles
+ TRIANGLE_TYPE_6T = 1,
+ //! surfaces
+ TRIANGLE_TYPE_6S = 2
};
enum Mapping
{
- MAPPING_X = 1,
- MAPPING_Y = 2,
- MAPPING_Z = 3,
- MAPPING_1X = 4,
- MAPPING_1Y = 5,
- MAPPING_1Z = 6
+ MAPPING_X = 1,
+ MAPPING_Y = 2,
+ MAPPING_Z = 3,
+ MAPPING_1X = 4,
+ MAPPING_1Y = 5,
+ MAPPING_1Z = 6
};
enum MouseType
{
- MOUSE_HIDE = 0, // no mouse
- MOUSE_NORM = 1,
- MOUSE_WAIT = 2,
- MOUSE_EDIT = 3,
- MOUSE_HAND = 4,
- MOUSE_CROSS = 5,
- MOUSE_SHOW = 6,
- MOUSE_NO = 7,
- MOUSE_MOVE = 8, // +
- MOUSE_MOVEH = 9, // -
- MOUSE_MOVEV = 10, // |
- MOUSE_MOVED = 11, // /
- MOUSE_MOVEI = 12, // \ //
- MOUSE_SCROLLL = 13, // <<
- MOUSE_SCROLLR = 14, // >>
- MOUSE_SCROLLU = 15, // ^
- MOUSE_SCROLLD = 16, // v
- MOUSE_TARGET = 17
+ MOUSE_HIDE = 0, // no mouse
+ MOUSE_NORM = 1,
+ MOUSE_WAIT = 2,
+ MOUSE_EDIT = 3,
+ MOUSE_HAND = 4,
+ MOUSE_CROSS = 5,
+ MOUSE_SHOW = 6,
+ MOUSE_NO = 7,
+ MOUSE_MOVE = 8, // +
+ MOUSE_MOVEH = 9, // -
+ MOUSE_MOVEV = 10, // |
+ MOUSE_MOVED = 11, // /
+ MOUSE_MOVEI = 12, // \ //
+ MOUSE_SCROLLL = 13, // <<
+ MOUSE_SCROLLR = 14, // >>
+ MOUSE_SCROLLU = 15, // ^
+ MOUSE_SCROLLD = 16, // v
+ MOUSE_TARGET = 17
};
enum ShadowType
{
- SHADOW_NORM = 0,
- SHADOW_WORM = 1
+ SHADOW_NORM = 0,
+ SHADOW_WORM = 1
};
enum RenderState
{
- //! Normal opaque materials
- RSTATE_NORMAL = 0,
- //! The transparent texture (black = no)
- RSTATE_TTEXTURE_BLACK = (1<<0),
- //! The transparent texture (white = no)
- RSTATE_TTEXTURE_WHITE = (1<<1),
- //! The transparent diffuse color
- RSTATE_TDIFFUSE = (1<<2),
- //! Texture wrap
- RSTATE_WRAP = (1<<3),
- //! Texture borders with solid color
- RSTATE_CLAMP = (1<<4),
- //! Light texture (ambient max)
- RSTATE_LIGHT = (1<<5),
- //! Double black texturing
- RSTATE_DUAL_BLACK = (1<<6),
- //! Double white texturing
- RSTATE_DUAL_WHITE = (1<<7),
- //! Part 1 (no change in. MOD!)
- RSTATE_PART1 = (1<<8),
- //! Part 2
- RSTATE_PART2 = (1<<9),
- //! Part 3
- RSTATE_PART3 = (1<<10),
- //! Part 4
- RSTATE_PART4 = (1<<11),
- //! Double-sided face
- RSTATE_2FACE = (1<<12),
- //! Image using alpha channel
- RSTATE_ALPHA = (1<<13),
- //! Always use 2nd floor texturing
- RSTATE_SECOND = (1<<14),
- //! Causes the fog
- RSTATE_FOG = (1<<15),
- //! The transparent color (black = no)
- RSTATE_TCOLOR_BLACK = (1<<16),
- //! The transparent color (white = no)
- RSTATE_TCOLOR_WHITE = (1<<17)
+ //! Normal opaque materials
+ RSTATE_NORMAL = 0,
+ //! The transparent texture (black = no)
+ RSTATE_TTEXTURE_BLACK = (1<<0),
+ //! The transparent texture (white = no)
+ RSTATE_TTEXTURE_WHITE = (1<<1),
+ //! The transparent diffuse color
+ RSTATE_TDIFFUSE = (1<<2),
+ //! Texture wrap
+ RSTATE_WRAP = (1<<3),
+ //! Texture borders with solid color
+ RSTATE_CLAMP = (1<<4),
+ //! Light texture (ambient max)
+ RSTATE_LIGHT = (1<<5),
+ //! Double black texturing
+ RSTATE_DUAL_BLACK = (1<<6),
+ //! Double white texturing
+ RSTATE_DUAL_WHITE = (1<<7),
+ //! Part 1 (no change in. MOD!)
+ RSTATE_PART1 = (1<<8),
+ //! Part 2
+ RSTATE_PART2 = (1<<9),
+ //! Part 3
+ RSTATE_PART3 = (1<<10),
+ //! Part 4
+ RSTATE_PART4 = (1<<11),
+ //! Double-sided face
+ RSTATE_2FACE = (1<<12),
+ //! Image using alpha channel
+ RSTATE_ALPHA = (1<<13),
+ //! Always use 2nd floor texturing
+ RSTATE_SECOND = (1<<14),
+ //! Causes the fog
+ RSTATE_FOG = (1<<15),
+ //! The transparent color (black = no)
+ RSTATE_TCOLOR_BLACK = (1<<16),
+ //! The transparent color (white = no)
+ RSTATE_TCOLOR_WHITE = (1<<17)
};
struct Triangle
{
- Gfx::VertexTex2 triangle[3];
- Gfx::Material material;
- int state;
- char texName1[20];
- char texName2[20];
+ Gfx::VertexTex2 triangle[3];
+ Gfx::Material material;
+ int state;
+ char texName1[20];
+ char texName2[20];
};
struct ObjLevel6
{
- int totalPossible;
- int totalUsed;
- Gfx::Material material;
- int state;
- Gfx::TriangleType type;
- Gfx::VertexTex2 vertex[1];
+ int totalPossible;
+ int totalUsed;
+ Gfx::Material material;
+ int state;
+ Gfx::TriangleType type;
+ Gfx::VertexTex2 vertex[1];
};
struct ObjLevel5
{
- int totalPossible;
- int totalUsed;
- int reserve;
- Gfx::ObjLevel6* table[1];
+ int totalPossible;
+ int totalUsed;
+ int reserve;
+ Gfx::ObjLevel6* table[1];
};
struct ObjLevel4
{
- int totalPossible;
- int totalUsed;
- float min, max;
- Gfx::ObjLevel5* table[1];
+ int totalPossible;
+ int totalUsed;
+ float min, max;
+ Gfx::ObjLevel5* table[1];
};
struct ObjLevel3
{
- int totalPossible;
- int totalUsed;
- int objRank;
- Gfx::ObjLevel4* table[1];
+ int totalPossible;
+ int totalUsed;
+ int objRank;
+ Gfx::ObjLevel4* table[1];
};
struct ObjLevel2
{
- int totalPossible;
- int totalUsed;
- char texName1[20];
- char texName2[20];
- Gfx::ObjLevel3* table[1];
+ int totalPossible;
+ int totalUsed;
+ char texName1[20];
+ char texName2[20];
+ Gfx::ObjLevel3* table[1];
};
struct ObjLevel1
{
- int totalPossible;
- int totalUsed;
- Gfx::ObjLevel2* table[1];
+ int totalPossible;
+ int totalUsed;
+ Gfx::ObjLevel2* table[1];
};
struct Object
{
- bool used; // true -> object exists
- bool visible; // true -> visible object
- bool drawWorld; // true -> shape behind the interface
- bool drawFront; // true -> shape before the interface
- int totalTriangle; // number of triangles used
- Gfx::ObjectType type; // type of the object (TYPE*)
- Math::Matrix transform; // transformation matrix
- float distance; // distance point of view - original
- Math::Vector bboxMin; // bounding box of the object
- Math::Vector bboxMax; // (the origin 0, 0, 0 is always included)
- float radius; // radius of the sphere at the origin
- int shadowRank; // rank of the associated shadow
- float transparency; // transparency of the object (0 .. 1)
+ bool used; // true -> object exists
+ bool visible; // true -> visible object
+ bool drawWorld; // true -> shape behind the interface
+ bool drawFront; // true -> shape before the interface
+ int totalTriangle; // number of triangles used
+ Gfx::ObjectType type; // type of the object (TYPE*)
+ Math::Matrix transform; // transformation matrix
+ float distance; // distance point of view - original
+ Math::Vector bboxMin; // bounding box of the object
+ Math::Vector bboxMax; // (the origin 0, 0, 0 is always included)
+ float radius; // radius of the sphere at the origin
+ int shadowRank; // rank of the associated shadow
+ float transparency; // transparency of the object (0 .. 1)
};
struct Shadow
{
- bool used; // true -> object exists
- bool hide; // true -> invisible shadow (object carried by ex.)
- int objRank; // rank of the object
- Gfx::ShadowType type; // type of shadow
- Math::Vector pos; // position for the shadow
- Math::Vector normal; // normal terrain
- float angle; // angle of the shadow
- float radius; // radius of the shadow
- float intensity; // intensity of the shadow
- float height; // height from the ground
+ bool used; // true -> object exists
+ bool hide; // true -> invisible shadow (object carried by ex.)
+ int objRank; // rank of the object
+ Gfx::ShadowType type; // type of shadow
+ Math::Vector pos; // position for the shadow
+ Math::Vector normal; // normal terrain
+ float angle; // angle of the shadow
+ float radius; // radius of the shadow
+ float intensity; // intensity of the shadow
+ float height; // height from the ground
};
struct GroundSpot
{
- bool used; // true -> object exists
- Gfx::Color color; // color of the shadow
- float min, max; // altitudes min / max
- float smooth; // transition area
- Math::Vector pos; // position for the shadow
- float radius; // radius of the shadow
- Math::Vector drawPos; // drawn to position the shade
- float drawRadius; // radius of the shadow drawn
+ bool used; // true -> object exists
+ Gfx::Color color; // color of the shadow
+ float min, max; // altitudes min / max
+ float smooth; // transition area
+ Math::Vector pos; // position for the shadow
+ float radius; // radius of the shadow
+ Math::Vector drawPos; // drawn to position the shade
+ float drawRadius; // radius of the shadow drawn
};
struct GroundMark
{
- bool used; // true -> object exists
- bool draw; // true -> drawn mark
- int phase; // 1 = increase, 2 = fixed, 3 = decrease
- float delay[3]; // time for 3 phases
- float fix; // fixed time
- Math::Vector pos; // position for marks
- float radius; // radius of marks
- float intensity; // color intensity
- Math::Vector drawPos; // drawn in position marks
- float drawRadius; // radius marks drawn
- float drawIntensity; // current drawn
- int dx, dy; // dimensions table
- char* table; // pointer to the table
+ bool used; // true -> object exists
+ bool draw; // true -> drawn mark
+ int phase; // 1 = increase, 2 = fixed, 3 = decrease
+ float delay[3]; // time for 3 phases
+ float fix; // fixed time
+ Math::Vector pos; // position for marks
+ float radius; // radius of marks
+ float intensity; // color intensity
+ Math::Vector drawPos; // drawn in position marks
+ float drawRadius; // radius marks drawn
+ float drawIntensity; // current drawn
+ int dx, dy; // dimensions table
+ char* table; // pointer to the table
};
@@ -286,430 +286,430 @@ struct GroundMark
class CEngine
{
public:
- CEngine(CInstanceManager *iMan, CApplication *app);
- ~CEngine();
-
- void SetDevice(Gfx::CDevice *device);
- Gfx::CDevice* RetDevice();
-
- void SetTerrain(Gfx::CTerrain* terrain);
-
- bool WriteProfile();
-
- void SetPause(bool pause);
- bool RetPause();
-
- void SetMovieLock(bool lock);
- bool RetMovieLock();
-
- void SetShowStat(bool show);
- bool RetShowStat();
-
- void SetRenderEnable(bool enable);
-
- int OneTimeSceneInit();
- int InitDeviceObjects();
- int DeleteDeviceObjects();
- int RestoreSurfaces();
- int Render();
- int FrameMove(float rTime);
- void StepSimul(float rTime);
- int FinalCleanup();
- void AddStatisticTriangle(int nb);
- int RetStatisticTriangle();
- void SetHiliteRank(int *rankList);
- bool GetHilite(Math::Point &p1, Math::Point &p2);
- bool GetSpriteCoord(int &x, int &y);
- void SetInfoText(int line, char* text);
- char * RetInfoText(int line);
- //LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
- void FirstExecuteAdapt(bool first);
- //int GetVidMemTotal();
- //bool IsVideo8MB();
- //bool IsVideo32MB();
-
- bool EnumDevices(char *bufDevices, int lenDevices, char *bufModes, int lenModes, int &totalDevices, int &selectDevices, int &totalModes, int &selectModes);
- bool RetFullScreen();
- bool ChangeDevice(char *device, char *mode, bool full);
-
- Math::Matrix* RetMatView();
- Math::Matrix* RetMatLeftView();
- Math::Matrix* RetMatRightView();
-
- void TimeInit();
- void TimeEnterGel();
- void TimeExitGel();
- float TimeGet();
-
- int RetRestCreate();
- int CreateObject();
- void FlushObject();
- bool DeleteObject(int objRank);
- bool SetDrawWorld(int objRank, bool draw);
- bool SetDrawFront(int objRank, bool draw);
- bool AddTriangle(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material &mat, int state, char* texName1, char* texName2, float min, float max, bool globalUpdate);
- bool AddSurface(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material &mat, int state, char* texName1, char* texName2, float min, float max, bool globalUpdate);
- bool AddQuick(int objRank, Gfx::ObjLevel6* buffer, char* texName1, char* texName2, float min, float max, bool globalUpdate);
- Gfx::ObjLevel6* SearchTriangle(int objRank, const Gfx::Material &mat, int state, char* texName1, char* texName2, float min, float max);
- void ChangeLOD();
- bool ChangeSecondTexture(int objRank, char* texName2);
- int RetTotalTriangles(int objRank);
- int GetTriangles(int objRank, float min, float max, Gfx::Triangle* buffer, int size, float percent);
- bool GetBBox(int objRank, Math::Vector &min, Math::Vector &max);
- bool ChangeTextureMapping(int objRank, const Gfx::Material &mat, int state, char* texName1, char* texName2, float min, float max, Gfx::Mapping mode, float au, float bu, float av, float bv);
- bool TrackTextureMapping(int objRank, const Gfx::Material &mat, int state, char* texName1, char* texName2, float min, float max, Gfx::Mapping mode, float pos, float factor, float tl, float ts, float tt);
- bool SetObjectTransform(int objRank, const Math::Matrix &transform);
- bool GetObjectTransform(int objRank, Math::Matrix &transform);
- bool SetObjectType(int objRank, Gfx::ObjectType type);
- Gfx::ObjectType RetObjectType(int objRank);
- bool SetObjectTransparency(int objRank, float value);
-
- bool ShadowCreate(int objRank);
- void ShadowDelete(int objRank);
- bool SetObjectShadowHide(int objRank, bool hide);
- bool SetObjectShadowType(int objRank, Gfx::ShadowType type);
- bool SetObjectShadowPos(int objRank, const Math::Vector &pos);
- bool SetObjectShadowNormal(int objRank, const Math::Vector &n);
- bool SetObjectShadowAngle(int objRank, float angle);
- bool SetObjectShadowRadius(int objRank, float radius);
- bool SetObjectShadowIntensity(int objRank, float intensity);
- bool SetObjectShadowHeight(int objRank, float h);
- float RetObjectShadowRadius(int objRank);
-
- void GroundSpotFlush();
- int GroundSpotCreate();
- void GroundSpotDelete(int rank);
- bool SetObjectGroundSpotPos(int rank, const Math::Vector &pos);
- bool SetObjectGroundSpotRadius(int rank, float radius);
- bool SetObjectGroundSpotColor(int rank, const Gfx::Color &color);
- bool SetObjectGroundSpotMinMax(int rank, float min, float max);
- bool SetObjectGroundSpotSmooth(int rank, float smooth);
-
- int GroundMarkCreate(Math::Vector pos, float radius, float delay1, float delay2, float delay3, int dx, int dy, char* table);
- bool GroundMarkDelete(int rank);
-
- void Update();
-
- void SetViewParams(const Math::Vector &vEyePt, const Math::Vector &vLookatPt, const Math::Vector &vUpVec, float fEyeDistance);
-
- bool FreeTexture(char* name);
- bool LoadTexture(char* name, int stage=0);
- bool LoadAllTexture();
-
- void SetLimitLOD(int rank, float limit);
- float RetLimitLOD(int rank, bool last=false);
-
- void SetTerrainVision(float vision);
-
- void SetGroundSpot(bool mode);
- bool RetGroundSpot();
- void SetShadow(bool mode);
- bool RetShadow();
- void SetDirty(bool mode);
- bool RetDirty();
- void SetFog(bool mode);
- bool RetFog();
- bool RetStateColor();
-
- void SetSecondTexture(int texNum);
- int RetSecondTexture();
-
- void SetRankView(int rank);
- int RetRankView();
-
- void SetDrawWorld(bool draw);
- void SetDrawFront(bool draw);
-
- void SetAmbiantColor(const Gfx::Color &color, int rank=0);
- Gfx::Color RetAmbiantColor(int rank=0);
-
- void SetWaterAddColor(const Gfx::Color &color);
- Gfx::Color RetWaterAddColor();
-
- void SetFogColor(const Gfx::Color &color, int rank=0);
- Gfx::Color RetFogColor(int rank=0);
-
- void SetDeepView(float length, int rank=0, bool ref=false);
- float RetDeepView(int rank=0);
-
- void SetFogStart(float start, int rank=0);
- float RetFogStart(int rank=0);
-
- void SetBackground(char *name, Gfx::Color up=Gfx::Color(), Gfx::Color down=Gfx::Color(), Gfx::Color cloudUp=Gfx::Color(), Gfx::Color cloudDown=Gfx::Color(), bool full=false, bool quarter=false);
- void RetBackground(char *name, Gfx::Color &up, Gfx::Color &down, Gfx::Color &cloudUp, Gfx::Color &cloudDown, bool &full, bool &quarter);
- void SetFrontsizeName(char *name);
- void SetOverFront(bool front);
- void SetOverColor(const Gfx::Color &color=Gfx::Color(), int mode=RSTATE_TCOLOR_BLACK);
-
- void SetParticuleDensity(float value);
- float RetParticuleDensity();
- float ParticuleAdapt(float factor);
-
- void SetClippingDistance(float value);
- float RetClippingDistance();
-
- void SetObjectDetail(float value);
- float RetObjectDetail();
-
- void SetGadgetQuantity(float value);
- float RetGadgetQuantity();
-
- void SetTextureQuality(int value);
- int RetTextureQuality();
-
- void SetTotoMode(bool present);
- bool RetTotoMode();
-
- void SetLensMode(bool present);
- bool RetLensMode();
+ CEngine(CInstanceManager *iMan, CApplication *app);
+ ~CEngine();
+
+ void SetDevice(Gfx::CDevice *device);
+ Gfx::CDevice* RetDevice();
+
+ void SetTerrain(Gfx::CTerrain* terrain);
+
+ bool WriteProfile();
+
+ void SetPause(bool pause);
+ bool RetPause();
+
+ void SetMovieLock(bool lock);
+ bool RetMovieLock();
+
+ void SetShowStat(bool show);
+ bool RetShowStat();
+
+ void SetRenderEnable(bool enable);
+
+ int OneTimeSceneInit();
+ int InitDeviceObjects();
+ int DeleteDeviceObjects();
+ int RestoreSurfaces();
+ int Render();
+ int FrameMove(float rTime);
+ void StepSimul(float rTime);
+ int FinalCleanup();
+ void AddStatisticTriangle(int nb);
+ int RetStatisticTriangle();
+ void SetHiliteRank(int *rankList);
+ bool GetHilite(Math::Point &p1, Math::Point &p2);
+ bool GetSpriteCoord(int &x, int &y);
+ void SetInfoText(int line, char* text);
+ char * RetInfoText(int line);
+ //LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ void FirstExecuteAdapt(bool first);
+ //int GetVidMemTotal();
+ //bool IsVideo8MB();
+ //bool IsVideo32MB();
+
+ bool EnumDevices(char *bufDevices, int lenDevices, char *bufModes, int lenModes, int &totalDevices, int &selectDevices, int &totalModes, int &selectModes);
+ bool RetFullScreen();
+ bool ChangeDevice(char *device, char *mode, bool full);
+
+ Math::Matrix* RetMatView();
+ Math::Matrix* RetMatLeftView();
+ Math::Matrix* RetMatRightView();
+
+ void TimeInit();
+ void TimeEnterGel();
+ void TimeExitGel();
+ float TimeGet();
+
+ int RetRestCreate();
+ int CreateObject();
+ void FlushObject();
+ bool DeleteObject(int objRank);
+ bool SetDrawWorld(int objRank, bool draw);
+ bool SetDrawFront(int objRank, bool draw);
+ bool AddTriangle(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material &mat, int state, char* texName1, char* texName2, float min, float max, bool globalUpdate);
+ bool AddSurface(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material &mat, int state, char* texName1, char* texName2, float min, float max, bool globalUpdate);
+ bool AddQuick(int objRank, Gfx::ObjLevel6* buffer, char* texName1, char* texName2, float min, float max, bool globalUpdate);
+ Gfx::ObjLevel6* SearchTriangle(int objRank, const Gfx::Material &mat, int state, char* texName1, char* texName2, float min, float max);
+ void ChangeLOD();
+ bool ChangeSecondTexture(int objRank, char* texName2);
+ int RetTotalTriangles(int objRank);
+ int GetTriangles(int objRank, float min, float max, Gfx::Triangle* buffer, int size, float percent);
+ bool GetBBox(int objRank, Math::Vector &min, Math::Vector &max);
+ bool ChangeTextureMapping(int objRank, const Gfx::Material &mat, int state, char* texName1, char* texName2, float min, float max, Gfx::Mapping mode, float au, float bu, float av, float bv);
+ bool TrackTextureMapping(int objRank, const Gfx::Material &mat, int state, char* texName1, char* texName2, float min, float max, Gfx::Mapping mode, float pos, float factor, float tl, float ts, float tt);
+ bool SetObjectTransform(int objRank, const Math::Matrix &transform);
+ bool GetObjectTransform(int objRank, Math::Matrix &transform);
+ bool SetObjectType(int objRank, Gfx::ObjectType type);
+ Gfx::ObjectType RetObjectType(int objRank);
+ bool SetObjectTransparency(int objRank, float value);
+
+ bool ShadowCreate(int objRank);
+ void ShadowDelete(int objRank);
+ bool SetObjectShadowHide(int objRank, bool hide);
+ bool SetObjectShadowType(int objRank, Gfx::ShadowType type);
+ bool SetObjectShadowPos(int objRank, const Math::Vector &pos);
+ bool SetObjectShadowNormal(int objRank, const Math::Vector &n);
+ bool SetObjectShadowAngle(int objRank, float angle);
+ bool SetObjectShadowRadius(int objRank, float radius);
+ bool SetObjectShadowIntensity(int objRank, float intensity);
+ bool SetObjectShadowHeight(int objRank, float h);
+ float RetObjectShadowRadius(int objRank);
+
+ void GroundSpotFlush();
+ int GroundSpotCreate();
+ void GroundSpotDelete(int rank);
+ bool SetObjectGroundSpotPos(int rank, const Math::Vector &pos);
+ bool SetObjectGroundSpotRadius(int rank, float radius);
+ bool SetObjectGroundSpotColor(int rank, const Gfx::Color &color);
+ bool SetObjectGroundSpotMinMax(int rank, float min, float max);
+ bool SetObjectGroundSpotSmooth(int rank, float smooth);
+
+ int GroundMarkCreate(Math::Vector pos, float radius, float delay1, float delay2, float delay3, int dx, int dy, char* table);
+ bool GroundMarkDelete(int rank);
+
+ void Update();
+
+ void SetViewParams(const Math::Vector &vEyePt, const Math::Vector &vLookatPt, const Math::Vector &vUpVec, float fEyeDistance);
+
+ bool FreeTexture(char* name);
+ bool LoadTexture(char* name, int stage=0);
+ bool LoadAllTexture();
+
+ void SetLimitLOD(int rank, float limit);
+ float RetLimitLOD(int rank, bool last=false);
+
+ void SetTerrainVision(float vision);
+
+ void SetGroundSpot(bool mode);
+ bool RetGroundSpot();
+ void SetShadow(bool mode);
+ bool RetShadow();
+ void SetDirty(bool mode);
+ bool RetDirty();
+ void SetFog(bool mode);
+ bool RetFog();
+ bool RetStateColor();
+
+ void SetSecondTexture(int texNum);
+ int RetSecondTexture();
+
+ void SetRankView(int rank);
+ int RetRankView();
+
+ void SetDrawWorld(bool draw);
+ void SetDrawFront(bool draw);
+
+ void SetAmbiantColor(const Gfx::Color &color, int rank=0);
+ Gfx::Color RetAmbiantColor(int rank=0);
+
+ void SetWaterAddColor(const Gfx::Color &color);
+ Gfx::Color RetWaterAddColor();
+
+ void SetFogColor(const Gfx::Color &color, int rank=0);
+ Gfx::Color RetFogColor(int rank=0);
+
+ void SetDeepView(float length, int rank=0, bool ref=false);
+ float RetDeepView(int rank=0);
+
+ void SetFogStart(float start, int rank=0);
+ float RetFogStart(int rank=0);
+
+ void SetBackground(char *name, Gfx::Color up=Gfx::Color(), Gfx::Color down=Gfx::Color(), Gfx::Color cloudUp=Gfx::Color(), Gfx::Color cloudDown=Gfx::Color(), bool full=false, bool quarter=false);
+ void RetBackground(char *name, Gfx::Color &up, Gfx::Color &down, Gfx::Color &cloudUp, Gfx::Color &cloudDown, bool &full, bool &quarter);
+ void SetFrontsizeName(char *name);
+ void SetOverFront(bool front);
+ void SetOverColor(const Gfx::Color &color=Gfx::Color(), int mode=RSTATE_TCOLOR_BLACK);
+
+ void SetParticuleDensity(float value);
+ float RetParticuleDensity();
+ float ParticuleAdapt(float factor);
+
+ void SetClippingDistance(float value);
+ float RetClippingDistance();
+
+ void SetObjectDetail(float value);
+ float RetObjectDetail();
+
+ void SetGadgetQuantity(float value);
+ float RetGadgetQuantity();
+
+ void SetTextureQuality(int value);
+ int RetTextureQuality();
+
+ void SetTotoMode(bool present);
+ bool RetTotoMode();
+
+ void SetLensMode(bool present);
+ bool RetLensMode();
- void SetWaterMode(bool present);
- bool RetWaterMode();
-
- void SetBlitzMode(bool present);
- bool RetBlitzMode();
+ void SetWaterMode(bool present);
+ bool RetWaterMode();
+
+ void SetBlitzMode(bool present);
+ bool RetBlitzMode();
- void SetSkyMode(bool present);
- bool RetSkyMode();
+ void SetSkyMode(bool present);
+ bool RetSkyMode();
- void SetBackForce(bool present);
- bool RetBackForce();
+ void SetBackForce(bool present);
+ bool RetBackForce();
- void SetPlanetMode(bool present);
- bool RetPlanetMode();
+ void SetPlanetMode(bool present);
+ bool RetPlanetMode();
- void SetLightMode(bool present);
- bool RetLightMode();
+ void SetLightMode(bool present);
+ bool RetLightMode();
- void SetEditIndentMode(bool auto);
- bool RetEditIndentMode();
+ void SetEditIndentMode(bool auto);
+ bool RetEditIndentMode();
- void SetEditIndentValue(int value);
- int RetEditIndentValue();
+ void SetEditIndentValue(int value);
+ int RetEditIndentValue();
- void SetSpeed(float speed);
- float RetSpeed();
+ void SetSpeed(float speed);
+ float RetSpeed();
- void SetTracePrecision(float factor);
- float RetTracePrecision();
+ void SetTracePrecision(float factor);
+ float RetTracePrecision();
- void SetFocus(float focus);
- float RetFocus();
- Math::Vector RetEyePt();
- Math::Vector RetLookatPt();
- float RetEyeDirH();
- float RetEyeDirV();
- Math::Point RetDim();
- void UpdateMatProj();
+ void SetFocus(float focus);
+ float RetFocus();
+ Math::Vector RetEyePt();
+ Math::Vector RetLookatPt();
+ float RetEyeDirH();
+ float RetEyeDirV();
+ Math::Point RetDim();
+ void UpdateMatProj();
- void ApplyChange();
+ void ApplyChange();
- void FlushPressKey();
- void ResetKey();
- void SetKey(int keyRank, int option, int key);
- int RetKey(int keyRank, int option);
+ void FlushPressKey();
+ void ResetKey();
+ void SetKey(int keyRank, int option, int key);
+ int RetKey(int keyRank, int option);
- void SetJoystick(bool enable);
- bool RetJoystick();
+ void SetJoystick(bool enable);
+ bool RetJoystick();
- void SetDebugMode(bool mode);
- bool RetDebugMode();
- bool RetSetupMode();
+ void SetDebugMode(bool mode);
+ bool RetDebugMode();
+ bool RetSetupMode();
- bool IsVisiblePoint(const Math::Vector &pos);
+ bool IsVisiblePoint(const Math::Vector &pos);
- int DetectObject(Math::Point mouse);
- void SetState(int state, Gfx::Color color=Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f));
- void SetTexture(char *name, int stage=0);
- void SetMaterial(const Gfx::Material &mat);
+ int DetectObject(Math::Point mouse);
+ void SetState(int state, Gfx::Color color=Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f));
+ void SetTexture(char *name, int stage=0);
+ void SetMaterial(const Gfx::Material &mat);
- void MoveMousePos(Math::Point pos);
- void SetMousePos(Math::Point pos);
- Math::Point RetMousePos();
- void SetMouseType(Gfx::MouseType type);
- Gfx::MouseType RetMouseType();
- void SetMouseHide(bool hide);
- bool RetMouseHide();
- void SetNiceMouse(bool nice);
- bool RetNiceMouse();
- bool RetNiceMouseCap();
+ void MoveMousePos(Math::Point pos);
+ void SetMousePos(Math::Point pos);
+ Math::Point RetMousePos();
+ void SetMouseType(Gfx::MouseType type);
+ Gfx::MouseType RetMouseType();
+ void SetMouseHide(bool hide);
+ bool RetMouseHide();
+ void SetNiceMouse(bool nice);
+ bool RetNiceMouse();
+ bool RetNiceMouseCap();
- CText* RetText();
+ CText* RetText();
- bool ChangeColor(char *name, Gfx::Color colorRef1, Gfx::Color colorNew1, Gfx::Color colorRef2, Gfx::Color colorNew2, float tolerance1, float tolerance2, Math::Point ts, Math::Point ti, Math::Point *pExclu=0, float shift=0.0f, bool hSV=false);
- bool OpenImage(char *name);
- bool CopyImage();
- bool LoadImage();
- bool ScrollImage(int dx, int dy);
- bool SetDot(int x, int y, Gfx::Color color);
- bool CloseImage();
- bool WriteScreenShot(char *filename, int width, int height);
- //bool GetRenderDC(HDC &hDC);
- //bool ReleaseRenderDC(HDC &hDC);
- //PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp);
- //bool CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC);
+ bool ChangeColor(char *name, Gfx::Color colorRef1, Gfx::Color colorNew1, Gfx::Color colorRef2, Gfx::Color colorNew2, float tolerance1, float tolerance2, Math::Point ts, Math::Point ti, Math::Point *pExclu=0, float shift=0.0f, bool hSV=false);
+ bool OpenImage(char *name);
+ bool CopyImage();
+ bool LoadImage();
+ bool ScrollImage(int dx, int dy);
+ bool SetDot(int x, int y, Gfx::Color color);
+ bool CloseImage();
+ bool WriteScreenShot(char *filename, int width, int height);
+ //bool GetRenderDC(HDC &hDC);
+ //bool ReleaseRenderDC(HDC &hDC);
+ //PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp);
+ //bool CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC);
protected:
- void MemSpace1(Gfx::ObjLevel1 *&p, int nb);
- void MemSpace2(Gfx::ObjLevel2 *&p, int nb);
- void MemSpace3(Gfx::ObjLevel3 *&p, int nb);
- void MemSpace4(Gfx::ObjLevel4 *&p, int nb);
- void MemSpace5(Gfx::ObjLevel5 *&p, int nb);
- void MemSpace6(Gfx::ObjLevel6 *&p, int nb);
-
- Gfx::ObjLevel2* AddLevel1(Gfx::ObjLevel1 *&p1, char* texName1, char* texName2);
- Gfx::ObjLevel3* AddLevel2(Gfx::ObjLevel2 *&p2, int objRank);
- Gfx::ObjLevel4* AddLevel3(Gfx::ObjLevel3 *&p3, float min, float max);
- Gfx::ObjLevel5* AddLevel4(Gfx::ObjLevel4 *&p4, int reserve);
- Gfx::ObjLevel6* AddLevel5(Gfx::ObjLevel5 *&p5, Gfx::TriangleType type, const Gfx::Material &mat, int state, int nb);
-
- bool IsVisible(int objRank);
- bool DetectBBox(int objRank, Math::Point mouse);
- bool DetectTriangle(Math::Point mouse, Gfx::VertexTex2 *triangle, int objRank, float &dist);
- bool TransformPoint(Math::Vector &p2D, int objRank, Math::Vector p3D);
- void ComputeDistance();
- void UpdateGeometry();
- void RenderGroundSpot();
- void DrawShadow();
- void DrawBackground();
- void DrawBackgroundGradient(Gfx::Color up, Gfx::Color down);
- void DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, char *name);
- void DrawBackgroundImage();
- void DrawPlanet();
- void DrawFrontsize();
- void DrawOverColor();
- bool GetBBox2D(int objRank, Math::Point &min, Math::Point &max);
- void DrawHilite();
- void DrawMouse();
- void DrawSprite(Math::Point pos, Math::Point dim, int icon);
+ void MemSpace1(Gfx::ObjLevel1 *&p, int nb);
+ void MemSpace2(Gfx::ObjLevel2 *&p, int nb);
+ void MemSpace3(Gfx::ObjLevel3 *&p, int nb);
+ void MemSpace4(Gfx::ObjLevel4 *&p, int nb);
+ void MemSpace5(Gfx::ObjLevel5 *&p, int nb);
+ void MemSpace6(Gfx::ObjLevel6 *&p, int nb);
+
+ Gfx::ObjLevel2* AddLevel1(Gfx::ObjLevel1 *&p1, char* texName1, char* texName2);
+ Gfx::ObjLevel3* AddLevel2(Gfx::ObjLevel2 *&p2, int objRank);
+ Gfx::ObjLevel4* AddLevel3(Gfx::ObjLevel3 *&p3, float min, float max);
+ Gfx::ObjLevel5* AddLevel4(Gfx::ObjLevel4 *&p4, int reserve);
+ Gfx::ObjLevel6* AddLevel5(Gfx::ObjLevel5 *&p5, Gfx::TriangleType type, const Gfx::Material &mat, int state, int nb);
+
+ bool IsVisible(int objRank);
+ bool DetectBBox(int objRank, Math::Point mouse);
+ bool DetectTriangle(Math::Point mouse, Gfx::VertexTex2 *triangle, int objRank, float &dist);
+ bool TransformPoint(Math::Vector &p2D, int objRank, Math::Vector p3D);
+ void ComputeDistance();
+ void UpdateGeometry();
+ void RenderGroundSpot();
+ void DrawShadow();
+ void DrawBackground();
+ void DrawBackgroundGradient(Gfx::Color up, Gfx::Color down);
+ void DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, char *name);
+ void DrawBackgroundImage();
+ void DrawPlanet();
+ void DrawFrontsize();
+ void DrawOverColor();
+ bool GetBBox2D(int objRank, Math::Point &min, Math::Point &max);
+ void DrawHilite();
+ void DrawMouse();
+ void DrawSprite(Math::Point pos, Math::Point dim, int icon);
protected:
- CInstanceManager* m_iMan;
- CApplication* m_app;
- Gfx::CDevice* m_device;
- Gfx::CText* m_text;
- Gfx::CLight* m_light;
- Gfx::CParticle* m_particule;
- Gfx::CWater* m_water;
- Gfx::CCloud* m_cloud;
- Gfx::CLightning* m_blitz;
- Gfx::CPlanet* m_planet;
- Gfx::CTerrain* m_terrain;
- CSound* m_sound;
-
- int m_blackSrcBlend[2];
- int m_blackDestBlend[2];
- int m_whiteSrcBlend[2];
- int m_whiteDestBlend[2];
- int m_diffuseSrcBlend[2];
- int m_diffuseDestBlend[2];
- int m_alphaSrcBlend[2];
- int m_alphaDestBlend[2];
-
- Math::Matrix m_matProj;
- Math::Matrix m_matLeftView;
- Math::Matrix m_matRightView;
- Math::Matrix m_matView;
- float m_focus;
-
- Math::Matrix m_matWorldInterface;
- Math::Matrix m_matProjInterface;
- Math::Matrix m_matViewInterface;
-
- long m_baseTime;
- long m_stopTime;
- float m_absTime;
- float m_lastTime;
- float m_speed;
- bool m_pause;
- bool m_render;
- bool m_movieLock;
-
- Math::IntPoint m_dim;
- Math::IntPoint m_lastDim;
- Gfx::ObjLevel1* m_objectPointer;
- int m_objectParamTotal;
- Gfx::Object* m_objectParam;
- int m_shadowTotal;
- Gfx::Shadow* m_shadow;
- Gfx::GroundSpot* m_groundSpot;
- Gfx::GroundMark m_groundMark;
- Math::Vector m_eyePt;
- Math::Vector m_lookatPt;
- float m_eyeDirH;
- float m_eyeDirV;
- int m_rankView;
- Gfx::Color m_ambiantColor[2];
- Gfx::Color m_backColor[2];
- Gfx::Color m_fogColor[2];
- float m_deepView[2];
- float m_fogStart[2];
- Gfx::Color m_waterAddColor;
- int m_statisticTriangle;
- bool m_updateGeometry;
- char m_infoText[10][200];
- int m_alphaMode;
- bool m_stateColor;
- bool m_forceStateColor;
- bool m_groundSpotVisible;
- bool m_shadowVisible;
- bool m_dirty;
- bool m_fog;
- bool m_firstGroundSpot;
- int m_secondTexNum;
- char m_backgroundName[50];
- Gfx::Color m_backgroundColorUp;
- Gfx::Color m_backgroundColorDown;
- Gfx::Color m_backgroundCloudUp;
- Gfx::Color m_backgroundCloudDown;
- bool m_backgroundFull;
- bool m_backgroundQuarter;
- bool m_overFront;
- Gfx::Color m_overColor;
- int m_overMode;
- char m_frontsizeName[50];
- bool m_drawWorld;
- bool m_drawFront;
- float m_limitLOD[2];
- float m_particuleDensity;
- float m_clippingDistance;
- float m_lastClippingDistance;
- float m_objectDetail;
- float m_lastObjectDetail;
- float m_terrainVision;
- float m_gadgetQuantity;
- int m_textureQuality;
- bool m_totoMode;
- bool m_lensMode;
- bool m_waterMode;
- bool m_skyMode;
- bool m_backForce;
- bool m_planetMode;
- bool m_lightMode;
- bool m_editIndentMode;
- int m_editIndentValue;
- float m_tracePrecision;
-
- int m_hiliteRank[100];
- bool m_hilite;
- Math::Point m_hiliteP1;
- Math::Point m_hiliteP2;
-
- int m_lastState;
- Gfx::Color m_lastColor;
- char m_lastTexture[2][50];
- Gfx::Material m_lastMaterial;
-
- Math::Point m_mousePos;
- Gfx::MouseType m_mouseType;
- bool m_mouseHide;
- bool m_niceMouse;
-
- //LPDIRECTDRAWSURFACE7 m_imageSurface;
- //DDSURFACEDESC2 m_imageDDSD;
- //WORD* m_imageCopy;
- //int m_imageDX;
- //int m_imageDY;
+ CInstanceManager* m_iMan;
+ CApplication* m_app;
+ Gfx::CDevice* m_device;
+ Gfx::CText* m_text;
+ Gfx::CLight* m_light;
+ Gfx::CParticle* m_particule;
+ Gfx::CWater* m_water;
+ Gfx::CCloud* m_cloud;
+ Gfx::CLightning* m_blitz;
+ Gfx::CPlanet* m_planet;
+ Gfx::CTerrain* m_terrain;
+ CSound* m_sound;
+
+ int m_blackSrcBlend[2];
+ int m_blackDestBlend[2];
+ int m_whiteSrcBlend[2];
+ int m_whiteDestBlend[2];
+ int m_diffuseSrcBlend[2];
+ int m_diffuseDestBlend[2];
+ int m_alphaSrcBlend[2];
+ int m_alphaDestBlend[2];
+
+ Math::Matrix m_matProj;
+ Math::Matrix m_matLeftView;
+ Math::Matrix m_matRightView;
+ Math::Matrix m_matView;
+ float m_focus;
+
+ Math::Matrix m_matWorldInterface;
+ Math::Matrix m_matProjInterface;
+ Math::Matrix m_matViewInterface;
+
+ long m_baseTime;
+ long m_stopTime;
+ float m_absTime;
+ float m_lastTime;
+ float m_speed;
+ bool m_pause;
+ bool m_render;
+ bool m_movieLock;
+
+ Math::IntPoint m_dim;
+ Math::IntPoint m_lastDim;
+ Gfx::ObjLevel1* m_objectPointer;
+ int m_objectParamTotal;
+ Gfx::Object* m_objectParam;
+ int m_shadowTotal;
+ Gfx::Shadow* m_shadow;
+ Gfx::GroundSpot* m_groundSpot;
+ Gfx::GroundMark m_groundMark;
+ Math::Vector m_eyePt;
+ Math::Vector m_lookatPt;
+ float m_eyeDirH;
+ float m_eyeDirV;
+ int m_rankView;
+ Gfx::Color m_ambiantColor[2];
+ Gfx::Color m_backColor[2];
+ Gfx::Color m_fogColor[2];
+ float m_deepView[2];
+ float m_fogStart[2];
+ Gfx::Color m_waterAddColor;
+ int m_statisticTriangle;
+ bool m_updateGeometry;
+ char m_infoText[10][200];
+ int m_alphaMode;
+ bool m_stateColor;
+ bool m_forceStateColor;
+ bool m_groundSpotVisible;
+ bool m_shadowVisible;
+ bool m_dirty;
+ bool m_fog;
+ bool m_firstGroundSpot;
+ int m_secondTexNum;
+ char m_backgroundName[50];
+ Gfx::Color m_backgroundColorUp;
+ Gfx::Color m_backgroundColorDown;
+ Gfx::Color m_backgroundCloudUp;
+ Gfx::Color m_backgroundCloudDown;
+ bool m_backgroundFull;
+ bool m_backgroundQuarter;
+ bool m_overFront;
+ Gfx::Color m_overColor;
+ int m_overMode;
+ char m_frontsizeName[50];
+ bool m_drawWorld;
+ bool m_drawFront;
+ float m_limitLOD[2];
+ float m_particuleDensity;
+ float m_clippingDistance;
+ float m_lastClippingDistance;
+ float m_objectDetail;
+ float m_lastObjectDetail;
+ float m_terrainVision;
+ float m_gadgetQuantity;
+ int m_textureQuality;
+ bool m_totoMode;
+ bool m_lensMode;
+ bool m_waterMode;
+ bool m_skyMode;
+ bool m_backForce;
+ bool m_planetMode;
+ bool m_lightMode;
+ bool m_editIndentMode;
+ int m_editIndentValue;
+ float m_tracePrecision;
+
+ int m_hiliteRank[100];
+ bool m_hilite;
+ Math::Point m_hiliteP1;
+ Math::Point m_hiliteP2;
+
+ int m_lastState;
+ Gfx::Color m_lastColor;
+ char m_lastTexture[2][50];
+ Gfx::Material m_lastMaterial;
+
+ Math::Point m_mousePos;
+ Gfx::MouseType m_mouseType;
+ bool m_mouseHide;
+ bool m_niceMouse;
+
+ //LPDIRECTDRAWSURFACE7 m_imageSurface;
+ //DDSURFACEDESC2 m_imageDDSD;
+ //WORD* m_imageCopy;
+ //int m_imageDX;
+ //int m_imageDY;
};
}; // namespace Gfx
diff --git a/src/graphics/common/light.h b/src/graphics/common/light.h
index 0ad32a8..1d14c5b 100644
--- a/src/graphics/common/light.h
+++ b/src/graphics/common/light.h
@@ -29,9 +29,9 @@ namespace Gfx {
/** \enum LightType Type of light */
enum LightType
{
- LT_Point,
- LT_Spot,
- LT_Directional
+ LT_Point,
+ LT_Spot,
+ LT_Directional
};
/**
@@ -43,41 +43,41 @@ enum LightType
*/
struct Light
{
- //! Type of light source
- Gfx::LightType type;
- //! Color of light
- Gfx::Color color;
- //! Position in world space
- Math::Vector position;
- //! Direction in world space
- Math::Vector direction;
- //! Cutoff range
- float range;
- //! Falloff
- float falloff;
- //! Constant attenuation
- float attenuation0;
- //! Linear attenuation
- float attenuation1;
- //! Quadratic attenuation
- float attenuation2;
- //! Inner angle of spotlight cone
- float theta;
- //! Outer angle of spotlight cone
- float phi;
-
- Light() : type(LT_Point), range(0.0f), falloff(0.0f),
- attenuation0(0.0f), attenuation1(0.0f), attenuation2(0.0f),
- theta(0.0f), phi(0.0f) {}
+ //! Type of light source
+ Gfx::LightType type;
+ //! Color of light
+ Gfx::Color color;
+ //! Position in world space
+ Math::Vector position;
+ //! Direction in world space
+ Math::Vector direction;
+ //! Cutoff range
+ float range;
+ //! Falloff
+ float falloff;
+ //! Constant attenuation
+ float attenuation0;
+ //! Linear attenuation
+ float attenuation1;
+ //! Quadratic attenuation
+ float attenuation2;
+ //! Inner angle of spotlight cone
+ float theta;
+ //! Outer angle of spotlight cone
+ float phi;
+
+ Light() : type(LT_Point), range(0.0f), falloff(0.0f),
+ attenuation0(0.0f), attenuation1(0.0f), attenuation2(0.0f),
+ theta(0.0f), phi(0.0f) {}
};
struct LightProg
{
- float starting;
- float ending;
- float current;
- float progress;
- float speed;
+ float starting;
+ float ending;
+ float current;
+ float progress;
+ float speed;
};
/**
@@ -87,24 +87,24 @@ struct LightProg
*/
struct SceneLight
{
- //! true -> light exists
- bool used;
- //! true -> light turned on
- bool enable;
-
- //! Type of all objects included
- //D3DTypeObj incluType;
- //! Type of all objects excluded
- //D3DTypeObj excluType;
-
- //! Configuration of the light
- Gfx::Light light;
-
- //! intensity (0 .. 1)
- Gfx::LightProg intensity;
- Gfx::LightProg colorRed;
- Gfx::LightProg colorGreen;
- Gfx::LightProg colorBlue;
+ //! true -> light exists
+ bool used;
+ //! true -> light turned on
+ bool enable;
+
+ //! Type of all objects included
+ //D3DTypeObj incluType;
+ //! Type of all objects excluded
+ //D3DTypeObj excluType;
+
+ //! Configuration of the light
+ Gfx::Light light;
+
+ //! intensity (0 .. 1)
+ Gfx::LightProg intensity;
+ Gfx::LightProg colorRed;
+ Gfx::LightProg colorGreen;
+ Gfx::LightProg colorBlue;
};
// TODO CLight
diff --git a/src/graphics/common/lightning.h b/src/graphics/common/lightning.h
index 8edf9e5..957344c 100644
--- a/src/graphics/common/lightning.h
+++ b/src/graphics/common/lightning.h
@@ -35,51 +35,51 @@ class CTerrain;
class CCamera;
-const float BLITZPARA = 200.0f; // radius of lightning protection
+const float BLITZPARA = 200.0f; // radius of lightning protection
const short BLITZMAX = 50;
enum BlitzPhase
{
- BPH_WAIT,
- BPH_BLITZ,
+ BPH_WAIT,
+ BPH_BLITZ,
};
class CLightning
{
public:
- CLightning(CInstanceManager* iMan, CEngine* engine);
- ~CLightning();
+ CLightning(CInstanceManager* iMan, CEngine* engine);
+ ~CLightning();
- void Flush();
- bool EventProcess(const Event &event);
- bool Create(float sleep, float delay, float magnetic);
- bool GetStatus(float &sleep, float &delay, float &magnetic, float &progress);
- bool SetStatus(float sleep, float delay, float magnetic, float progress);
- void Draw();
+ void Flush();
+ bool EventProcess(const Event &event);
+ bool Create(float sleep, float delay, float magnetic);
+ bool GetStatus(float &sleep, float &delay, float &magnetic, float &progress);
+ bool SetStatus(float sleep, float delay, float magnetic, float progress);
+ void Draw();
protected:
- bool EventFrame(const Event &event);
- CObject* SearchObject(Math::Vector pos);
+ bool EventFrame(const Event &event);
+ CObject* SearchObject(Math::Vector pos);
protected:
- CInstanceManager* m_iMan;
- CEngine* m_engine;
- CTerrain* m_terrain;
- CCamera* m_camera;
- CSound* m_sound;
-
- bool m_bBlitzExist;
- 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];
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
+ CTerrain* m_terrain;
+ CCamera* m_camera;
+ CSound* m_sound;
+
+ bool m_bBlitzExist;
+ 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];
};
}; // namespace Gfx
diff --git a/src/graphics/common/material.h b/src/graphics/common/material.h
index 47f1a0d..2ec2e1b 100644
--- a/src/graphics/common/material.h
+++ b/src/graphics/common/material.h
@@ -32,12 +32,12 @@ namespace Gfx {
*/
struct Material
{
- //! Diffuse color
- Gfx::Color diffuse;
- //! Ambient color
- Gfx::Color ambient;
- //! Specular color
- Gfx::Color specular;
+ //! Diffuse color
+ Gfx::Color diffuse;
+ //! Ambient color
+ Gfx::Color ambient;
+ //! Specular color
+ Gfx::Color specular;
};
}; // namespace Gfx
diff --git a/src/graphics/common/model.h b/src/graphics/common/model.h
index 349c15c..e8a5f19 100644
--- a/src/graphics/common/model.h
+++ b/src/graphics/common/model.h
@@ -37,105 +37,105 @@ class CEngine;
class CModel {
- public:
- CModel(CInstanceManager* iMan);
- ~CModel();
-
- void StartUserAction();
- void StopUserAction();
-
- bool EventProcess(const Event &event);
-
- void InitView();
- void InitViewFromSelect();
- void UpdateView();
- void ViewMove(const Event &event, float speed);
-
- protected:
- bool EventFrame(const Event &event);
- bool GetVertex(int rank, Gfx::VertexTex2 &vertex);
- bool SetVertex(int rank, Gfx::VertexTex2 &vertex);
- Math::Vector RetSelectCDG();
- Math::Vector RetSelectNormal();
- void SmoothSelect();
- void PlaneSelect();
- void ColorSelect();
- void StateSelect();
- void MoveSelect(Math::Vector move);
- void OperSelect(Math::Vector move, char oper);
- void ReadScript(char *filename);
- void BBoxCompute(Math::Vector &min, Math::Vector &max);
- bool IsMappingSelectPlausible(Gfx::Mapping D3Dmode);
- void MappingSelect(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
- void MappingSelectSpherical(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
- Math::Vector RetMappingCenter(Math::Vector pos, Math::Vector min);
- void MappingSelectCylindrical(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
- void MappingSelectFace(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
- void MappingSelect2(int texNum2, int subdiv, int offsetU, int offsetV, bool bMirrorX, bool bMirrorY);
- void MappingSelectPlane2(int mode, bool bMirrorX, bool bMirrorY);
- void MappingSelectSpherical2(bool bMirrorX, bool bMirrorY);
- void MappingSelectMagic2(bool bMirrorX, bool bMirrorY);
- int SearchNext(int rank, int step);
- int SearchSamePlane(int first, int step);
- void CurrentSearchNext(int step, bool bControl);
- void CurrentInit();
- void CurrentSelect(bool bSelect);
- void DeselectAll();
- void SelectAll();
- void SelectZone(int first, int last);
- void SelectTerm();
- void DefaultSelect();
- void SelectDelete();
- void Compress();
- void MinMaxSelect();
- void MinMaxChange();
- void UpdateInfoText();
- int* RetTextureTable();
- void TexturePartUpdate();
- void TextureRankChange(int step);
- void TexturePartChange(int step);
- void PutTextureValues();
- void GetTextureValues();
- void GetModelName(char *buffer);
- void GetDXFName(char *buffer);
- void GetScriptName(char *buffer);
- bool IsEditFocus();
-
- protected:
- CInstanceManager* m_iMan;
- Gfx::CEngine* m_engine;
- CModFile* m_modFile;
- CInterface* m_interface;
-
- float m_time;
- ModelTriangle* m_triangleTable;
- int m_triangleSel1;
- int m_triangleSel2;
- int m_mode;
- int m_textureMode;
- int m_textureRotate;
- bool m_bTextureMirrorX;
- bool m_bTextureMirrorY;
- Math::Point m_textureInf;
- Math::Point m_textureSup;
- int m_texturePart;
- int m_textureRank;
- char m_textureName[20];
- bool m_bDisplayTransparent;
- bool m_bDisplayOnlySelection;
- float m_viewHeight;
- float m_viewDist;
- float m_viewAngleH;
- float m_viewAngleV;
- int m_color;
- int m_state;
- int m_secondTexNum;
- int m_secondSubdiv;
- int m_secondOffsetU;
- int m_secondOffsetV;
- char m_oper;
- float m_min;
- float m_max;
+ public:
+ CModel(CInstanceManager* iMan);
+ ~CModel();
+
+ void StartUserAction();
+ void StopUserAction();
+
+ bool EventProcess(const Event &event);
+
+ void InitView();
+ void InitViewFromSelect();
+ void UpdateView();
+ void ViewMove(const Event &event, float speed);
+
+ protected:
+ bool EventFrame(const Event &event);
+ bool GetVertex(int rank, Gfx::VertexTex2 &vertex);
+ bool SetVertex(int rank, Gfx::VertexTex2 &vertex);
+ Math::Vector RetSelectCDG();
+ Math::Vector RetSelectNormal();
+ void SmoothSelect();
+ void PlaneSelect();
+ void ColorSelect();
+ void StateSelect();
+ void MoveSelect(Math::Vector move);
+ void OperSelect(Math::Vector move, char oper);
+ void ReadScript(char *filename);
+ void BBoxCompute(Math::Vector &min, Math::Vector &max);
+ bool IsMappingSelectPlausible(Gfx::Mapping D3Dmode);
+ void MappingSelect(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
+ void MappingSelectSpherical(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
+ Math::Vector RetMappingCenter(Math::Vector pos, Math::Vector min);
+ void MappingSelectCylindrical(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
+ void MappingSelectFace(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
+ void MappingSelect2(int texNum2, int subdiv, int offsetU, int offsetV, bool bMirrorX, bool bMirrorY);
+ void MappingSelectPlane2(int mode, bool bMirrorX, bool bMirrorY);
+ void MappingSelectSpherical2(bool bMirrorX, bool bMirrorY);
+ void MappingSelectMagic2(bool bMirrorX, bool bMirrorY);
+ int SearchNext(int rank, int step);
+ int SearchSamePlane(int first, int step);
+ void CurrentSearchNext(int step, bool bControl);
+ void CurrentInit();
+ void CurrentSelect(bool bSelect);
+ void DeselectAll();
+ void SelectAll();
+ void SelectZone(int first, int last);
+ void SelectTerm();
+ void DefaultSelect();
+ void SelectDelete();
+ void Compress();
+ void MinMaxSelect();
+ void MinMaxChange();
+ void UpdateInfoText();
+ int* RetTextureTable();
+ void TexturePartUpdate();
+ void TextureRankChange(int step);
+ void TexturePartChange(int step);
+ void PutTextureValues();
+ void GetTextureValues();
+ void GetModelName(char *buffer);
+ void GetDXFName(char *buffer);
+ void GetScriptName(char *buffer);
+ bool IsEditFocus();
+
+ protected:
+ CInstanceManager* m_iMan;
+ Gfx::CEngine* m_engine;
+ CModFile* m_modFile;
+ CInterface* m_interface;
+
+ float m_time;
+ ModelTriangle* m_triangleTable;
+ int m_triangleSel1;
+ int m_triangleSel2;
+ int m_mode;
+ int m_textureMode;
+ int m_textureRotate;
+ bool m_bTextureMirrorX;
+ bool m_bTextureMirrorY;
+ Math::Point m_textureInf;
+ Math::Point m_textureSup;
+ int m_texturePart;
+ int m_textureRank;
+ char m_textureName[20];
+ bool m_bDisplayTransparent;
+ bool m_bDisplayOnlySelection;
+ float m_viewHeight;
+ float m_viewDist;
+ float m_viewAngleH;
+ float m_viewAngleV;
+ int m_color;
+ int m_state;
+ int m_secondTexNum;
+ int m_secondSubdiv;
+ int m_secondOffsetU;
+ int m_secondOffsetV;
+ char m_oper;
+ float m_min;
+ float m_max;
};
}; // namespace Gfx
diff --git a/src/graphics/common/modfile.h b/src/graphics/common/modfile.h
index 84b5456..c81739b 100644
--- a/src/graphics/common/modfile.h
+++ b/src/graphics/common/modfile.h
@@ -30,85 +30,85 @@ namespace Gfx {
struct OldModelTriangle1
{
- char bUsed; // TRUE -> using
- char bSelect; // TRUE -> selected
- Vertex p1;
- Vertex p2;
- Vertex p3;
- Material material;
- char texName[20];
- float min;
- float max;
-}; // length = 196 bytes
+ char bUsed; // TRUE -> using
+ char bSelect; // TRUE -> selected
+ Vertex p1;
+ Vertex p2;
+ Vertex p3;
+ Material material;
+ char texName[20];
+ float min;
+ float max;
+}; // length = 196 bytes
struct OldModelTriangle2
{
- char bUsed; // TRUE -> used
- char bSelect; // TRUE -> selected
- Vertex p1;
- Vertex p2;
- Vertex p3;
- Material material;
- char texName[20];
- float min;
- float max;
- long state;
- short reserve1;
- short reserve2;
- short reserve3;
- short reserve4;
+ char bUsed; // TRUE -> used
+ char bSelect; // TRUE -> selected
+ Vertex p1;
+ Vertex p2;
+ Vertex p3;
+ Material material;
+ char texName[20];
+ float min;
+ float max;
+ long state;
+ short reserve1;
+ short reserve2;
+ short reserve3;
+ short reserve4;
};
struct ModelTriangle
{
- char bUsed; // TRUE -> used
- char bSelect; // TRUE -> selected
- VertexTex2 p1;
- VertexTex2 p2;
- VertexTex2 p3;
- Material material;
- char texName[20];
- float min;
- float max;
- long state;
- short texNum2;
- short reserve2;
- short reserve3;
- short reserve4;
-}; // length = 208 bytes
+ char bUsed; // TRUE -> used
+ char bSelect; // TRUE -> selected
+ VertexTex2 p1;
+ VertexTex2 p2;
+ VertexTex2 p3;
+ Material material;
+ char texName[20];
+ float min;
+ float max;
+ long state;
+ short texNum2;
+ short reserve2;
+ short reserve3;
+ short reserve4;
+}; // length = 208 bytes
class CModFile {
public:
- CModFile(CInstanceManager* iMan);
- ~CModFile();
+ CModFile(CInstanceManager* iMan);
+ ~CModFile();
- bool ReadDXF(char *filename, float min, float max);
- bool AddModel(char *filename, int first, bool bEdit=false, bool bMeta=true);
- bool ReadModel(char *filename, bool bEdit=false, bool bMeta=true);
- bool WriteModel(char *filename);
+ bool ReadDXF(char *filename, float min, float max);
+ bool AddModel(char *filename, int first, bool bEdit=false, bool bMeta=true);
+ bool ReadModel(char *filename, bool bEdit=false, bool bMeta=true);
+ bool WriteModel(char *filename);
- bool CreateEngineObject(int objRank, int addState=0);
- void Mirror();
+ bool CreateEngineObject(int objRank, int addState=0);
+ void Mirror();
- void SetTriangleUsed(int total);
- int RetTriangleUsed();
- int RetTriangleMax();
- ModelTriangle* RetTriangleList();
+ void SetTriangleUsed(int total);
+ int RetTriangleUsed();
+ int RetTriangleMax();
+ ModelTriangle* RetTriangleList();
- float RetHeight(Math::Vector pos);
+ float RetHeight(Math::Vector pos);
protected:
- bool CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, float min, float max);
+ bool CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, float min, float max);
protected:
- CInstanceManager* m_iMan;
- CEngine* m_engine;
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
- ModelTriangle* m_triangleTable;
- int m_triangleUsed;
+ ModelTriangle* m_triangleTable;
+ int m_triangleUsed;
};
};
diff --git a/src/graphics/common/particle.h b/src/graphics/common/particle.h
index 4047cb5..e430e2a 100644
--- a/src/graphics/common/particle.h
+++ b/src/graphics/common/particle.h
@@ -40,217 +40,217 @@ const short MAXTRACKLEN = 10;
const short MAXPARTIFOG = 100;
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_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_MAX = 3;
-// type == 0 -> triangles
-// type == 1 -> effect00 (black background)
-// type == 2 -> effect01 (black background)
-// type == 3 -> effect02 (black background)
-// type == 4 -> text (white background)
+// type == 0 -> triangles
+// type == 1 -> effect00 (black background)
+// type == 2 -> effect01 (black background)
+// type == 3 -> effect02 (black background)
+// type == 4 -> text (white background)
enum ParticuleType
{
- 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 ParticulePhase
{
- PARPHSTART = 0,
- PARPHEND = 1,
+ PARPHSTART = 0,
+ PARPHEND = 1,
};
struct Particule
{
- char bUsed; // TRUE -> particle used
- char bRay; // TRUE -> ray with goal
- unsigned short uniqueStamp; // unique mark
- short sheet; // sheet (0..n)
- ParticuleType type; // type PARTI*
- ParticulePhase phase; // phase PARPH*
- float mass; // mass of the particle (in rebounding)
- float weight; // weight of the particle (for noise)
- float duration; // length of life
- Math::Vector pos; // absolute position (relative if object links)
- Math::Vector goal; // goal position (if bRay)
- Math::Vector speed; // speed of displacement
- float windSensitivity;
- short bounce; // number of rebounds
- Math::Point dim; // dimensions of the rectangle
- float zoom; // zoom (0..1)
- float angle; // angle of rotation
- float intensity; // intensity
- Math::Point texSup; // coordinated upper texture
- Math::Point texInf; // coordinated lower texture
- float time; // age of the particle (0..n)
- float phaseTime; // age at the beginning of phase
- float testTime; // time since last test
- CObject* objLink; // father object (for example reactor)
- CObject* objFather; // father object (for example reactor)
- short objRank; // rank of the object, or -1
- short trackRank; // rank of the drag
+ char bUsed; // TRUE -> particle used
+ char bRay; // TRUE -> ray with goal
+ unsigned short uniqueStamp; // unique mark
+ short sheet; // sheet (0..n)
+ ParticuleType type; // type PARTI*
+ ParticulePhase phase; // phase PARPH*
+ float mass; // mass of the particle (in rebounding)
+ float weight; // weight of the particle (for noise)
+ float duration; // length of life
+ Math::Vector pos; // absolute position (relative if object links)
+ Math::Vector goal; // goal position (if bRay)
+ Math::Vector speed; // speed of displacement
+ float windSensitivity;
+ short bounce; // number of rebounds
+ Math::Point dim; // dimensions of the rectangle
+ float zoom; // zoom (0..1)
+ float angle; // angle of rotation
+ float intensity; // intensity
+ Math::Point texSup; // coordinated upper texture
+ Math::Point texInf; // coordinated lower texture
+ float time; // age of the particle (0..n)
+ float phaseTime; // age at the beginning of phase
+ float testTime; // time since last test
+ CObject* objLink; // father object (for example reactor)
+ CObject* objFather; // father object (for example reactor)
+ short objRank; // rank of the object, or -1
+ short trackRank; // rank of the drag
};
struct Track
{
- char bUsed; // TRUE -> drag used
- char bDrawParticule;
- float step; // duration of not
- float last; // increase last not memorized
- float intensity; // intensity at starting (0..1)
- float width; // tail width
- int used; // number of positions in "pos"
- int head; // head to write index
- Math::Vector pos[MAXTRACKLEN];
- float len[MAXTRACKLEN];
+ char bUsed; // TRUE -> drag used
+ char bDrawParticule;
+ float step; // duration of not
+ float last; // increase last not memorized
+ float intensity; // intensity at starting (0..1)
+ float width; // tail width
+ int used; // number of positions in "pos"
+ int head; // head to write index
+ Math::Vector pos[MAXTRACKLEN];
+ float len[MAXTRACKLEN];
};
struct WheelTrace
{
- ParticuleType type; // type PARTI*
- Math::Vector pos[4]; // rectangle positions
- float startTime; // beginning of life
+ ParticuleType type; // type PARTI*
+ Math::Vector pos[4]; // rectangle positions
+ float startTime; // beginning of life
};
@@ -258,80 +258,80 @@ struct WheelTrace
class CParticle
{
public:
- CParticle(CInstanceManager* iMan, CEngine* engine);
- ~CParticle();
+ CParticle(CInstanceManager* iMan, CEngine* engine);
+ ~CParticle();
- void SetGLDevice(CDevice device);
+ void SetGLDevice(CDevice device);
- void FlushParticule();
- void FlushParticule(int sheet);
- int CreateParticule(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticuleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0);
- int CreateFrag(Math::Vector pos, Math::Vector speed, Triangle *triangle, ParticuleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0);
- int CreatePart(Math::Vector pos, Math::Vector speed, ParticuleType type, float duration=1.0f, float mass=0.0f, float weight=0.0f, float windSensitivity=1.0f, int sheet=0);
- int CreateRay(Math::Vector pos, Math::Vector goal, ParticuleType type, Math::Point dim, float duration=1.0f, int sheet=0);
- int CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticuleType type, float duration=1.0f, float mass=0.0f, float length=10.0f, float width=1.0f);
- void CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3, const Math::Vector &p4, ParticuleType type);
- void DeleteParticule(ParticuleType type);
- void DeleteParticule(int channel);
- void SetObjectLink(int channel, CObject *object);
- void SetObjectFather(int channel, CObject *object);
- void SetPosition(int channel, Math::Vector pos);
- void SetDimension(int channel, Math::Point dim);
- void SetZoom(int channel, float zoom);
- void SetAngle(int channel, float angle);
- 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, ParticulePhase phase, float duration);
- bool GetPosition(int channel, Math::Vector &pos);
+ void FlushParticule();
+ void FlushParticule(int sheet);
+ int CreateParticule(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticuleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0);
+ int CreateFrag(Math::Vector pos, Math::Vector speed, Triangle *triangle, ParticuleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0);
+ int CreatePart(Math::Vector pos, Math::Vector speed, ParticuleType type, float duration=1.0f, float mass=0.0f, float weight=0.0f, float windSensitivity=1.0f, int sheet=0);
+ int CreateRay(Math::Vector pos, Math::Vector goal, ParticuleType type, Math::Point dim, float duration=1.0f, int sheet=0);
+ int CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticuleType type, float duration=1.0f, float mass=0.0f, float length=10.0f, float width=1.0f);
+ void CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3, const Math::Vector &p4, ParticuleType type);
+ void DeleteParticule(ParticuleType type);
+ void DeleteParticule(int channel);
+ void SetObjectLink(int channel, CObject *object);
+ void SetObjectFather(int channel, CObject *object);
+ void SetPosition(int channel, Math::Vector pos);
+ void SetDimension(int channel, Math::Point dim);
+ void SetZoom(int channel, float zoom);
+ void SetAngle(int channel, float angle);
+ 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, ParticulePhase phase, float duration);
+ bool GetPosition(int channel, Math::Vector &pos);
- Gfx::Color RetFogColor(Math::Vector pos);
+ Gfx::Color RetFogColor(Math::Vector pos);
- void SetFrameUpdate(int sheet, bool bUpdate);
- void FrameParticule(float rTime);
- void DrawParticule(int sheet);
+ void SetFrameUpdate(int sheet, bool bUpdate);
+ void FrameParticule(float rTime);
+ void DrawParticule(int sheet);
- bool WriteWheelTrace(char *filename, int width, int height, Math::Vector dl, Math::Vector ur);
+ bool WriteWheelTrace(char *filename, int width, int height, Math::Vector dl, Math::Vector ur);
protected:
- void DeleteRank(int rank);
- bool CheckChannel(int &channel);
- void DrawParticuleTriangle(int i);
- void DrawParticuleNorm(int i);
- void DrawParticuleFlat(int i);
- void DrawParticuleFog(int i);
- void DrawParticuleRay(int i);
- void DrawParticuleSphere(int i);
- void DrawParticuleCylinder(int i);
- void DrawParticuleWheel(int i);
- CObject* SearchObjectGun(Math::Vector old, Math::Vector pos, ParticuleType type, CObject *father);
- CObject* SearchObjectRay(Math::Vector pos, Math::Vector goal, ParticuleType type, CObject *father);
- void Play(Snd::Sound sound, Math::Vector pos, float amplitude);
- bool TrackMove(int i, Math::Vector pos, float progress);
- void TrackDraw(int i, ParticuleType type);
+ void DeleteRank(int rank);
+ bool CheckChannel(int &channel);
+ void DrawParticuleTriangle(int i);
+ void DrawParticuleNorm(int i);
+ void DrawParticuleFlat(int i);
+ void DrawParticuleFog(int i);
+ void DrawParticuleRay(int i);
+ void DrawParticuleSphere(int i);
+ void DrawParticuleCylinder(int i);
+ void DrawParticuleWheel(int i);
+ CObject* SearchObjectGun(Math::Vector old, Math::Vector pos, ParticuleType type, CObject *father);
+ CObject* SearchObjectRay(Math::Vector pos, Math::Vector goal, ParticuleType type, CObject *father);
+ void Play(Snd::Sound sound, Math::Vector pos, float amplitude);
+ bool TrackMove(int i, Math::Vector pos, float progress);
+ void TrackDraw(int i, ParticuleType type);
protected:
- CInstanceManager* m_iMan;
- CEngine* m_engine;
- CDevice* m_pDevice;
- CRobotMain* m_main;
- CTerrain* m_terrain;
- CWater* m_water;
- CSound* m_sound;
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
+ CDevice* m_pDevice;
+ CRobotMain* m_main;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CSound* m_sound;
- Particule m_particule[MAXPARTICULE*MAXPARTITYPE];
- Gfx::Triangle m_triangle[MAXPARTICULE]; // triangle if PartiType == 0
- Track m_track[MAXTRACK];
- int m_wheelTraceTotal;
- int m_wheelTraceIndex;
- WheelTrace m_wheelTrace[MAXWHEELTRACE];
- int m_totalInterface[MAXPARTITYPE][SH_MAX];
- bool m_bFrameUpdate[SH_MAX];
- int m_fogTotal;
- int m_fog[MAXPARTIFOG];
- int m_uniqueStamp;
- int m_exploGunCounter;
- float m_lastTimeGunDel;
- float m_absTime;
+ Particule m_particule[MAXPARTICULE*MAXPARTITYPE];
+ Gfx::Triangle m_triangle[MAXPARTICULE]; // triangle if PartiType == 0
+ Track m_track[MAXTRACK];
+ int m_wheelTraceTotal;
+ int m_wheelTraceIndex;
+ WheelTrace m_wheelTrace[MAXWHEELTRACE];
+ int m_totalInterface[MAXPARTITYPE][SH_MAX];
+ bool m_bFrameUpdate[SH_MAX];
+ int m_fogTotal;
+ int m_fog[MAXPARTIFOG];
+ int m_uniqueStamp;
+ int m_exploGunCounter;
+ float m_lastTimeGunDel;
+ float m_absTime;
};
diff --git a/src/graphics/common/planet.h b/src/graphics/common/planet.h
index 4ffccfc..264d05c 100644
--- a/src/graphics/common/planet.h
+++ b/src/graphics/common/planet.h
@@ -35,15 +35,15 @@ const short MAXPLANET = 10;
struct Planet
{
- char bUsed; // TRUE -> planet exists
- Math::Point start; // initial position in degrees
- Math::Point angle; // current position in degrees
- float dim; // dimensions (0..1)
- float speed; // speed
- float dir; // direction in the sky
- char name[20]; // name of the texture
- Math::Point uv1, uv2; // texture mapping
- char bTGA; // texture .TGA
+ char bUsed; // TRUE -> planet exists
+ Math::Point start; // initial position in degrees
+ Math::Point angle; // current position in degrees
+ float dim; // dimensions (0..1)
+ float speed; // speed
+ float dir; // direction in the sky
+ char name[20]; // name of the texture
+ Math::Point uv1, uv2; // texture mapping
+ char bTGA; // texture .TGA
};
@@ -51,29 +51,29 @@ struct Planet
class CPlanet {
public:
- CPlanet(CInstanceManager* iMan, CEngine* engine);
- ~CPlanet();
-
- void Flush();
- bool EventProcess(const Event &event);
- bool Create(int mode, Math::Point start, float dim, float speed, float dir, char *name, Math::Point uv1, Math::Point uv2);
- bool PlanetExist();
- void LoadTexture();
- void Draw();
- void SetMode(int mode);
- int RetMode();
+ CPlanet(CInstanceManager* iMan, CEngine* engine);
+ ~CPlanet();
+
+ void Flush();
+ bool EventProcess(const Event &event);
+ bool Create(int mode, Math::Point start, float dim, float speed, float dir, char *name, Math::Point uv1, Math::Point uv2);
+ bool PlanetExist();
+ void LoadTexture();
+ void Draw();
+ void SetMode(int mode);
+ int RetMode();
protected:
- bool EventFrame(const Event &event);
+ bool EventFrame(const Event &event);
protected:
- CInstanceManager* m_iMan;
- CEngine* m_engine;
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
- float m_time;
- int m_mode;
- Planet m_planet[2][MAXPLANET];
- bool m_bPlanetExist;
+ float m_time;
+ int m_mode;
+ Planet m_planet[2][MAXPLANET];
+ bool m_bPlanetExist;
};
diff --git a/src/graphics/common/pyro.h b/src/graphics/common/pyro.h
index e6b5844..fda74b3 100644
--- a/src/graphics/common/pyro.h
+++ b/src/graphics/common/pyro.h
@@ -44,132 +44,132 @@ class CLight;
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_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
};
struct PyroBurnPart
{
- int part;
- Math::Vector initialPos;
- Math::Vector finalPos;
- Math::Vector initialAngle;
- Math::Vector finalAngle;
+ int part;
+ Math::Vector initialPos;
+ Math::Vector finalPos;
+ Math::Vector initialAngle;
+ Math::Vector finalAngle;
};
struct PyroLightOper
{
- float progress;
- float intensity;
- Gfx::Color color;
+ float progress;
+ float intensity;
+ Gfx::Color color;
};
class CPyro {
public:
- CPyro(CInstanceManager* iMan);
- ~CPyro();
+ CPyro(CInstanceManager* iMan);
+ ~CPyro();
- void DeleteObject(bool bAll=false);
- bool Create(PyroType type, CObject* pObj, float force=1.0f);
- bool EventProcess(const Event &event);
- Error IsEnded();
- void CutObjectLink(CObject* pObj);
+ void DeleteObject(bool bAll=false);
+ bool Create(PyroType type, CObject* pObj, float force=1.0f);
+ bool EventProcess(const Event &event);
+ Error IsEnded();
+ void CutObjectLink(CObject* pObj);
protected:
- void DisplayError(PyroType type, CObject* pObj);
- bool CreateLight(Math::Vector pos, float height);
- void DeleteObject(bool bPrimary, bool bSecondary);
+ void DisplayError(PyroType type, CObject* pObj);
+ bool CreateLight(Math::Vector pos, float height);
+ void DeleteObject(bool bPrimary, bool bSecondary);
- void CreateTriangle(CObject* pObj, ObjectType oType, int part);
+ void CreateTriangle(CObject* pObj, ObjectType oType, int part);
- void ExploStart();
- void ExploTerminate();
+ void ExploStart();
+ void ExploTerminate();
- void BurnStart();
- void BurnAddPart(int part, Math::Vector pos, Math::Vector angle);
- void BurnProgress();
- bool BurnIsKeepPart(int part);
- void BurnTerminate();
+ void BurnStart();
+ void BurnAddPart(int part, Math::Vector pos, Math::Vector angle);
+ void BurnProgress();
+ bool BurnIsKeepPart(int part);
+ void BurnTerminate();
- void FallStart();
- CObject* FallSearchBeeExplo();
- void FallProgress(float rTime);
- Error FallIsEnded();
+ void FallStart();
+ CObject* FallSearchBeeExplo();
+ void FallProgress(float rTime);
+ Error FallIsEnded();
- void LightOperFlush();
- void LightOperAdd(float progress, float intensity, float r, float g, float b);
- void LightOperFrame(float rTime);
+ void LightOperFlush();
+ void LightOperAdd(float progress, float intensity, float r, float g, float b);
+ void LightOperFrame(float rTime);
protected:
- CInstanceManager* m_iMan;
- CEngine* m_engine;
- CTerrain* m_terrain;
- CCamera* m_camera;
- CParticle* m_particule;
- CLight* m_light;
- CObject* m_object;
- CDisplayText* m_displayText;
- CRobotMain* m_main;
- CSound* m_sound;
-
- Math::Vector m_pos; // center of the effect
- Math::Vector m_posPower; // center of the battery
- bool m_bPower; // battery exists?
- PyroType m_type;
- float m_force;
- float m_size;
- float m_progress;
- float m_speed;
- float m_time;
- float m_lastParticule;
- float m_lastParticuleSmoke;
- int m_soundChannel;
-
- int m_lightRank;
- int m_lightOperTotal;
- PyroLightOper m_lightOper[10];
- float m_lightHeight;
-
- ObjectType m_burnType;
- int m_burnPartTotal;
- PyroBurnPart m_burnPart[10];
- int m_burnKeepPart[10];
- float m_burnFall;
-
- float m_fallFloor;
- float m_fallSpeed;
- float m_fallBulletTime;
- bool m_bFallEnding;
-
- int m_crashSphereUsed; // number of spheres used
- Math::Vector m_crashSpherePos[50];
- float m_crashSphereRadius[50];
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
+ CTerrain* m_terrain;
+ CCamera* m_camera;
+ CParticle* m_particule;
+ CLight* m_light;
+ CObject* m_object;
+ CDisplayText* m_displayText;
+ CRobotMain* m_main;
+ CSound* m_sound;
+
+ Math::Vector m_pos; // center of the effect
+ Math::Vector m_posPower; // center of the battery
+ bool m_bPower; // battery exists?
+ PyroType m_type;
+ float m_force;
+ float m_size;
+ float m_progress;
+ float m_speed;
+ float m_time;
+ float m_lastParticule;
+ float m_lastParticuleSmoke;
+ int m_soundChannel;
+
+ int m_lightRank;
+ int m_lightOperTotal;
+ PyroLightOper m_lightOper[10];
+ float m_lightHeight;
+
+ ObjectType m_burnType;
+ int m_burnPartTotal;
+ PyroBurnPart m_burnPart[10];
+ int m_burnKeepPart[10];
+ float m_burnFall;
+
+ float m_fallFloor;
+ float m_fallSpeed;
+ float m_fallBulletTime;
+ bool m_bFallEnding;
+
+ int m_crashSphereUsed; // number of spheres used
+ Math::Vector m_crashSpherePos[50];
+ float m_crashSphereRadius[50];
};
}; // namespace Gfx
diff --git a/src/graphics/common/terrain.h b/src/graphics/common/terrain.h
index 5ccc992..fd9a1a6 100644
--- a/src/graphics/common/terrain.h
+++ b/src/graphics/common/terrain.h
@@ -31,19 +31,19 @@ class CEngine;
class CWater;
-const short FLATLIMIT = (5.0f*Math::PI/180.0f);
+const short FLATLIMIT = (5.0f*Math::PI/180.0f);
enum TerrainRes
{
- TR_NULL = 0,
- TR_STONE = 1,
- TR_URANIUM = 2,
- TR_POWER = 3,
- TR_KEYa = 4,
- TR_KEYb = 5,
- TR_KEYc = 6,
- TR_KEYd = 7,
+ TR_NULL = 0,
+ TR_STONE = 1,
+ TR_URANIUM = 2,
+ TR_POWER = 3,
+ TR_KEYa = 4,
+ TR_KEYb = 5,
+ TR_KEYc = 6,
+ TR_KEYd = 7,
};
@@ -51,16 +51,16 @@ const short MAXBUILDINGLEVEL = 100;
struct BuildingLevel
{
- Math::Vector center;
- float factor;
- float min;
- float max;
- float level;
- float height;
- float bboxMinX;
- float bboxMaxX;
- float bboxMinZ;
- float bboxMaxZ;
+ Math::Vector center;
+ float factor;
+ float min;
+ float max;
+ float level;
+ float height;
+ float bboxMinX;
+ float bboxMaxX;
+ float bboxMinZ;
+ float bboxMaxZ;
};
@@ -68,17 +68,17 @@ const short MAXMATTERRAIN = 100;
struct TerrainMaterial
{
- short id;
- char texName[20];
- float u,v;
- float hardness;
- char mat[4]; // up, right, down, left
+ short id;
+ char texName[20];
+ float u,v;
+ float hardness;
+ char mat[4]; // up, right, down, left
};
struct DotLevel
{
- short id;
- char mat[4]; // up, right, down, left
+ short id;
+ char mat[4]; // up, right, down, left
};
@@ -86,10 +86,10 @@ const short MAXFLYINGLIMIT = 10;
struct FlyingLimit
{
- Math::Vector center;
- float extRadius;
- float intRadius;
- float maxHeight;
+ Math::Vector center;
+ float extRadius;
+ float intRadius;
+ float maxHeight;
};
@@ -97,115 +97,115 @@ struct FlyingLimit
class CTerrain
{
public:
- CTerrain(CInstanceManager* iMan);
- ~CTerrain();
-
- bool Generate(int mosaic, int brickP2, float size, float vision, int depth, float hardness);
- bool InitTextures(char* baseName, int* table, int dx, int dy);
- void LevelFlush();
- bool LevelMaterial(int id, char* baseName, float u, float v, int up, int right, int down, int left, float hardness);
- bool LevelInit(int id);
- bool LevelGenerate(int *id, float min, float max, float slope, float freq, Math::Vector center, float radius);
- void FlushRelief();
- bool ReliefFromBMP(const char* filename, float scaleRelief, bool adjustBorder);
- bool ReliefFromDXF(const char* filename, float scaleRelief);
- bool ResFromBMP(const char* filename);
- bool CreateObjects(bool bMultiRes);
- bool Terraform(const Math::Vector &p1, const Math::Vector &p2, float height);
-
- void SetWind(Math::Vector speed);
- Math::Vector RetWind();
-
- float RetFineSlope(const Math::Vector &pos);
- float RetCoarseSlope(const Math::Vector &pos);
- bool GetNormal(Math::Vector &n, const Math::Vector &p);
- float RetFloorLevel(const Math::Vector &p, bool bBrut=false, bool bWater=false);
- float RetFloorHeight(const Math::Vector &p, bool bBrut=false, bool bWater=false);
- bool MoveOnFloor(Math::Vector &p, bool bBrut=false, bool bWater=false);
- bool ValidPosition(Math::Vector &p, float marging);
- TerrainRes RetResource(const Math::Vector &p);
- void LimitPos(Math::Vector &pos);
-
- void FlushBuildingLevel();
- bool AddBuildingLevel(Math::Vector center, float min, float max, float height, float factor);
- bool UpdateBuildingLevel(Math::Vector center);
- bool DeleteBuildingLevel(Math::Vector center);
- float RetBuildingFactor(const Math::Vector &p);
- float RetHardness(const Math::Vector &p);
-
- int RetMosaic();
- int RetBrick();
- float RetSize();
- float RetScaleRelief();
-
- void GroundFlat(Math::Vector pos);
- float RetFlatZoneRadius(Math::Vector center, float max);
-
- void SetFlyingMaxHeight(float height);
- float RetFlyingMaxHeight();
- void FlushFlyingLimit();
- bool AddFlyingLimit(Math::Vector center, float extRadius, float intRadius, float maxHeight);
- float RetFlyingLimit(Math::Vector pos, bool bNoLimit);
+ CTerrain(CInstanceManager* iMan);
+ ~CTerrain();
+
+ bool Generate(int mosaic, int brickP2, float size, float vision, int depth, float hardness);
+ bool InitTextures(char* baseName, int* table, int dx, int dy);
+ void LevelFlush();
+ bool LevelMaterial(int id, char* baseName, float u, float v, int up, int right, int down, int left, float hardness);
+ bool LevelInit(int id);
+ bool LevelGenerate(int *id, float min, float max, float slope, float freq, Math::Vector center, float radius);
+ void FlushRelief();
+ bool ReliefFromBMP(const char* filename, float scaleRelief, bool adjustBorder);
+ bool ReliefFromDXF(const char* filename, float scaleRelief);
+ bool ResFromBMP(const char* filename);
+ bool CreateObjects(bool bMultiRes);
+ bool Terraform(const Math::Vector &p1, const Math::Vector &p2, float height);
+
+ void SetWind(Math::Vector speed);
+ Math::Vector RetWind();
+
+ float RetFineSlope(const Math::Vector &pos);
+ float RetCoarseSlope(const Math::Vector &pos);
+ bool GetNormal(Math::Vector &n, const Math::Vector &p);
+ float RetFloorLevel(const Math::Vector &p, bool bBrut=false, bool bWater=false);
+ float RetFloorHeight(const Math::Vector &p, bool bBrut=false, bool bWater=false);
+ bool MoveOnFloor(Math::Vector &p, bool bBrut=false, bool bWater=false);
+ bool ValidPosition(Math::Vector &p, float marging);
+ TerrainRes RetResource(const Math::Vector &p);
+ void LimitPos(Math::Vector &pos);
+
+ void FlushBuildingLevel();
+ bool AddBuildingLevel(Math::Vector center, float min, float max, float height, float factor);
+ bool UpdateBuildingLevel(Math::Vector center);
+ bool DeleteBuildingLevel(Math::Vector center);
+ float RetBuildingFactor(const Math::Vector &p);
+ float RetHardness(const Math::Vector &p);
+
+ int RetMosaic();
+ int RetBrick();
+ float RetSize();
+ float RetScaleRelief();
+
+ void GroundFlat(Math::Vector pos);
+ float RetFlatZoneRadius(Math::Vector center, float max);
+
+ void SetFlyingMaxHeight(float height);
+ float RetFlyingMaxHeight();
+ void FlushFlyingLimit();
+ bool AddFlyingLimit(Math::Vector center, float extRadius, float intRadius, float maxHeight);
+ float RetFlyingLimit(Math::Vector pos, bool bNoLimit);
protected:
- bool ReliefAddDot(Math::Vector pos, float scaleRelief);
- void AdjustRelief();
- Math::Vector RetVector(int x, int y);
- Gfx::VertexTex2 RetVertex(int x, int y, int step);
- bool CreateMosaic(int ox, int oy, int step, int objRank, const Gfx::Material &mat, float min, float max);
- bool CreateSquare(bool bMultiRes, int x, int y);
-
- TerrainMaterial* LevelSearchMat(int id);
- void LevelTextureName(int x, int y, char *name, Math::Point &uv);
- float LevelRetHeight(int x, int y);
- bool LevelGetDot(int x, int y, float min, float max, float slope);
- int LevelTestMat(char *mat);
- void LevelSetDot(int x, int y, int id, char *mat);
- bool LevelIfDot(int x, int y, int id, char *mat);
- bool LevelPutDot(int x, int y, int id);
- void LevelOpenTable();
- void LevelCloseTable();
-
- void AdjustBuildingLevel(Math::Vector &p);
+ bool ReliefAddDot(Math::Vector pos, float scaleRelief);
+ void AdjustRelief();
+ Math::Vector RetVector(int x, int y);
+ Gfx::VertexTex2 RetVertex(int x, int y, int step);
+ bool CreateMosaic(int ox, int oy, int step, int objRank, const Gfx::Material &mat, float min, float max);
+ bool CreateSquare(bool bMultiRes, int x, int y);
+
+ TerrainMaterial* LevelSearchMat(int id);
+ void LevelTextureName(int x, int y, char *name, Math::Point &uv);
+ float LevelRetHeight(int x, int y);
+ bool LevelGetDot(int x, int y, float min, float max, float slope);
+ int LevelTestMat(char *mat);
+ void LevelSetDot(int x, int y, int id, char *mat);
+ bool LevelIfDot(int x, int y, int id, char *mat);
+ bool LevelPutDot(int x, int y, int id);
+ void LevelOpenTable();
+ void LevelCloseTable();
+
+ void AdjustBuildingLevel(Math::Vector &p);
protected:
- CInstanceManager* m_iMan;
- CEngine* m_engine;
- CWater* m_water;
-
- int m_mosaic; // number of mosaics
- int m_brick; // number of bricks per mosaics
- float m_size; // size of an item in an brick
- float m_vision; // vision before a change of resolution
- float* m_relief; // table of the relief
- int* m_texture; // table of textures
- int* m_objRank; // table of rows of objects
- bool m_bMultiText;
- bool m_bLevelText;
- float m_scaleMapping; // scale of the mapping
- float m_scaleRelief;
- int m_subdivMapping;
- int m_depth; // number of different resolutions (1,2,3,4)
- char m_texBaseName[20];
- char m_texBaseExt[10];
- float m_defHardness;
-
- TerrainMaterial m_levelMat[MAXMATTERRAIN+1];
- int m_levelMatTotal;
- int m_levelMatMax;
- int m_levelDotSize;
- DotLevel* m_levelDot;
- int m_levelID;
-
- int m_buildingUsed;
- BuildingLevel m_buildingTable[MAXBUILDINGLEVEL];
-
- unsigned char* m_resources;
- Math::Vector m_wind; // wind speed
-
- float m_flyingMaxHeight;
- int m_flyingLimitTotal;
- FlyingLimit m_flyingLimit[MAXFLYINGLIMIT];
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
+ CWater* m_water;
+
+ int m_mosaic; // number of mosaics
+ int m_brick; // number of bricks per mosaics
+ float m_size; // size of an item in an brick
+ float m_vision; // vision before a change of resolution
+ float* m_relief; // table of the relief
+ int* m_texture; // table of textures
+ int* m_objRank; // table of rows of objects
+ bool m_bMultiText;
+ bool m_bLevelText;
+ float m_scaleMapping; // scale of the mapping
+ float m_scaleRelief;
+ int m_subdivMapping;
+ int m_depth; // number of different resolutions (1,2,3,4)
+ char m_texBaseName[20];
+ char m_texBaseExt[10];
+ float m_defHardness;
+
+ TerrainMaterial m_levelMat[MAXMATTERRAIN+1];
+ int m_levelMatTotal;
+ int m_levelMatMax;
+ int m_levelDotSize;
+ DotLevel* m_levelDot;
+ int m_levelID;
+
+ int m_buildingUsed;
+ BuildingLevel m_buildingTable[MAXBUILDINGLEVEL];
+
+ unsigned char* m_resources;
+ Math::Vector m_wind; // wind speed
+
+ float m_flyingMaxHeight;
+ int m_flyingLimitTotal;
+ FlyingLimit m_flyingLimit[MAXFLYINGLIMIT];
};
}; // namespace Gfx
diff --git a/src/graphics/common/text.h b/src/graphics/common/text.h
index 65b6772..00b73f2 100644
--- a/src/graphics/common/text.h
+++ b/src/graphics/common/text.h
@@ -38,27 +38,27 @@ const float NORMSTRETCH = 0.8f;
enum FontType
{
- FONT_COLOBOT = 0,
- FONT_COURIER = 1,
- FONT_BUTTON = 2,
+ FONT_COLOBOT = 0,
+ FONT_COURIER = 1,
+ FONT_BUTTON = 2,
};
enum FontTitle
{
- TITLE_BIG = 0x04,
- TITLE_NORM = 0x08,
- TITLE_LITTLE = 0x0c,
+ TITLE_BIG = 0x04,
+ TITLE_NORM = 0x08,
+ TITLE_LITTLE = 0x0c,
};
enum FontColor
{
- COLOR_LINK = 0x10,
- COLOR_TOKEN = 0x20,
- COLOR_TYPE = 0x30,
- COLOR_CONST = 0x40,
- COLOR_REM = 0x50,
- COLOR_KEY = 0x60,
- COLOR_TABLE = 0x70,
+ COLOR_LINK = 0x10,
+ COLOR_TOKEN = 0x20,
+ COLOR_TYPE = 0x30,
+ COLOR_CONST = 0x40,
+ COLOR_REM = 0x50,
+ COLOR_KEY = 0x60,
+ COLOR_TABLE = 0x70,
};
const short FONT_MASK = 0x03;
@@ -70,43 +70,43 @@ const short IMAGE_MASK = 0x80;
class CText {
public:
- CText(CInstanceManager *iMan, Gfx::CEngine* engine);
- ~CText();
+ CText(CInstanceManager *iMan, Gfx::CEngine* engine);
+ ~CText();
- void SetGLDevice(Gfx::CDevice device);
+ void SetGLDevice(Gfx::CDevice device);
- void DrawText(char *string, char *format, int len, Math::Point pos, float width, int justif, float size, float stretch, int eol);
- void DrawText(char *string, char *format, Math::Point pos, float width, int justif, float size, float stretch, int eol);
- void DrawText(char *string, int len, Math::Point pos, float width, int justif, float size, float stretch, FontType font, int eol);
- void DrawText(char *string, Math::Point pos, float width, int justif, float size, float stretch, FontType font, int eol);
- void DimText(char *string, char *format, int len, Math::Point pos, int justif, float size, float stretch, Math::Point &start, Math::Point &end);
- void DimText(char *string, char *format, Math::Point pos, int justif, float size, float stretch, Math::Point &start, Math::Point &end);
- void DimText(char *string, int len, Math::Point pos, int justif, float size, float stretch, FontType font, Math::Point &start, Math::Point &end);
- void DimText(char *string, Math::Point pos, int justif, float size, float stretch, FontType font, Math::Point &start, Math::Point &end);
+ void DrawText(char *string, char *format, int len, Math::Point pos, float width, int justif, float size, float stretch, int eol);
+ void DrawText(char *string, char *format, Math::Point pos, float width, int justif, float size, float stretch, int eol);
+ void DrawText(char *string, int len, Math::Point pos, float width, int justif, float size, float stretch, FontType font, int eol);
+ void DrawText(char *string, Math::Point pos, float width, int justif, float size, float stretch, FontType font, int eol);
+ void DimText(char *string, char *format, int len, Math::Point pos, int justif, float size, float stretch, Math::Point &start, Math::Point &end);
+ void DimText(char *string, char *format, Math::Point pos, int justif, float size, float stretch, Math::Point &start, Math::Point &end);
+ void DimText(char *string, int len, Math::Point pos, int justif, float size, float stretch, FontType font, Math::Point &start, Math::Point &end);
+ void DimText(char *string, Math::Point pos, int justif, float size, float stretch, FontType font, Math::Point &start, Math::Point &end);
- float RetAscent(float size, FontType font);
- float RetDescent(float size, FontType font);
- float RetHeight(float size, FontType font);
+ float RetAscent(float size, FontType font);
+ float RetDescent(float size, FontType font);
+ float RetHeight(float size, FontType font);
- float RetStringWidth(char *string, char *format, int len, float size, float stretch);
- float RetStringWidth(char *string, int len, float size, float stretch, FontType font);
- float RetCharWidth(int character, float offset, float size, float stretch, FontType font);
+ float RetStringWidth(char *string, char *format, int len, float size, float stretch);
+ float RetStringWidth(char *string, int len, float size, float stretch, FontType font);
+ float RetCharWidth(int character, float offset, float size, float stretch, FontType font);
- int Justif(char *string, char *format, int len, float width, float size, float stretch);
- int Justif(char *string, int len, float width, float size, float stretch, FontType font);
- int Detect(char *string, char *format, int len, float offset, float size, float stretch);
- int Detect(char *string, int len, float offset, float size, float stretch, FontType font);
+ int Justif(char *string, char *format, int len, float width, float size, float stretch);
+ int Justif(char *string, int len, float width, float size, float stretch, FontType font);
+ int Detect(char *string, char *format, int len, float offset, float size, float stretch);
+ int Detect(char *string, int len, float offset, float size, float stretch, FontType font);
protected:
- void DrawString(char *string, char *format, int len, Math::Point pos, float width, float size, float stretch, int eol);
- void DrawString(char *string, int len, Math::Point pos, float width, float size, float stretch, FontType font, int eol);
- void DrawColor(Math::Point pos, float size, float width, int color);
- void DrawChar(int character, Math::Point pos, float size, float stretch, FontType font);
+ void DrawString(char *string, char *format, int len, Math::Point pos, float width, float size, float stretch, int eol);
+ void DrawString(char *string, int len, Math::Point pos, float width, float size, float stretch, FontType font, int eol);
+ void DrawColor(Math::Point pos, float size, float width, int color);
+ void DrawChar(int character, Math::Point pos, float size, float stretch, FontType font);
protected:
- CInstanceManager* m_iMan;
- Gfx::CEngine* m_engine;
- Gfx::CDevice m_pDevice;
+ CInstanceManager* m_iMan;
+ Gfx::CEngine* m_engine;
+ Gfx::CDevice m_pDevice;
};
diff --git a/src/graphics/common/vertex.h b/src/graphics/common/vertex.h
index 9368b4b..b620413 100644
--- a/src/graphics/common/vertex.h
+++ b/src/graphics/common/vertex.h
@@ -36,14 +36,14 @@ namespace Gfx {
*/
struct Vertex
{
- Math::Vector coord;
- Math::Vector normal;
- Math::Point texCoord;
+ Math::Vector coord;
+ Math::Vector normal;
+ Math::Point texCoord;
- Vertex(Math::Vector aCoord = Math::Vector(),
- Math::Vector aNormal = Math::Vector(),
- Math::Point aTexCoord = Math::Point())
- : coord(aCoord), normal(aNormal), texCoord(aTexCoord) {}
+ Vertex(Math::Vector aCoord = Math::Vector(),
+ Math::Vector aNormal = Math::Vector(),
+ Math::Point aTexCoord = Math::Point())
+ : coord(aCoord), normal(aNormal), texCoord(aTexCoord) {}
};
/**
@@ -54,13 +54,13 @@ struct Vertex
*/
struct VertexTex2 : public Gfx::Vertex
{
- Math::Point texCoord2;
+ Math::Point texCoord2;
- VertexTex2(Math::Vector aCoord = Math::Vector(),
- Math::Vector aNormal = Math::Vector(),
- Math::Point aTexCoord = Math::Point(),
- Math::Point aTexCoord2 = Math::Point())
- : Vertex(aCoord, aNormal, aTexCoord), texCoord2(aTexCoord2) {}
+ VertexTex2(Math::Vector aCoord = Math::Vector(),
+ Math::Vector aNormal = Math::Vector(),
+ Math::Point aTexCoord = Math::Point(),
+ Math::Point aTexCoord2 = Math::Point())
+ : Vertex(aCoord, aNormal, aTexCoord), texCoord2(aTexCoord2) {}
};
}; // namespace Gfx
diff --git a/src/graphics/common/water.h b/src/graphics/common/water.h
index aaf5ec9..5999eac 100644
--- a/src/graphics/common/water.h
+++ b/src/graphics/common/water.h
@@ -37,9 +37,9 @@ const short MAXWATERLINE = 500;
struct WaterLine
{
- short x, y; // beginning
- short len; // length by x
- float px1, px2, pz;
+ short x, y; // beginning
+ short len; // length by x
+ float px1, px2, pz;
};
@@ -47,88 +47,88 @@ const short MAXWATVAPOR = 10;
struct WaterVapor
{
- bool bUsed;
- ParticuleType type;
- Math::Vector pos;
- float delay;
- float time;
- float last;
+ bool bUsed;
+ ParticuleType type;
+ Math::Vector pos;
+ float delay;
+ float time;
+ float last;
};
enum WaterType
{
- WATER_NULL = 0, // no water
- WATER_TT = 1, // transparent texture
- WATER_TO = 2, // opaque texture
- WATER_CT = 3, // transparent color
- WATER_CO = 4, // opaque color
+ WATER_NULL = 0, // no water
+ WATER_TT = 1, // transparent texture
+ WATER_TO = 2, // opaque texture
+ WATER_CT = 3, // transparent color
+ WATER_CO = 4, // opaque color
};
class CWater
{
public:
- CWater(CInstanceManager* iMan, Gfx::CEngine* engine);
- ~CWater();
+ CWater(CInstanceManager* iMan, Gfx::CEngine* engine);
+ ~CWater();
- void SetGLDevice(Gfx::CDevice device);
- bool EventProcess(const Event &event);
- void Flush();
- bool Create(WaterType type1, WaterType type2, const char *filename, Gfx::Color diffuse, Gfx::Color ambient, float level, float glint, Math::Vector eddy);
- void DrawBack();
- void DrawSurf();
+ void SetGLDevice(Gfx::CDevice device);
+ bool EventProcess(const Event &event);
+ void Flush();
+ bool Create(WaterType type1, WaterType type2, const char *filename, Gfx::Color diffuse, Gfx::Color ambient, float level, float glint, Math::Vector eddy);
+ void DrawBack();
+ void DrawSurf();
- bool SetLevel(float level);
- float RetLevel();
- float RetLevel(CObject* object);
+ bool SetLevel(float level);
+ float RetLevel();
+ float RetLevel(CObject* object);
- void SetLava(bool bLava);
- bool RetLava();
+ void SetLava(bool bLava);
+ bool RetLava();
- void AdjustEye(Math::Vector &eye);
+ void AdjustEye(Math::Vector &eye);
protected:
- bool EventFrame(const Event &event);
- void LavaFrame(float rTime);
- void AdjustLevel(Math::Vector &pos, Math::Vector &norm, Math::Point &uv1, Math::Point &uv2);
- bool RetWater(int x, int y);
- bool CreateLine(int x, int y, int len);
+ bool EventFrame(const Event &event);
+ void LavaFrame(float rTime);
+ void AdjustLevel(Math::Vector &pos, Math::Vector &norm, Math::Point &uv1, Math::Point &uv2);
+ bool RetWater(int x, int y);
+ bool CreateLine(int x, int y, int len);
- void VaporFlush();
- bool VaporCreate(ParticuleType type, Math::Vector pos, float delay);
- void VaporFrame(int i, float rTime);
+ void VaporFlush();
+ bool VaporCreate(ParticuleType type, Math::Vector pos, float delay);
+ void VaporFrame(int i, float rTime);
protected:
- CInstanceManager* m_iMan;
- CEngine* m_engine;
- CDevice* m_pDevice;
- CTerrain* m_terrain;
- CParticle* m_particule;
- CSound* m_sound;
-
- WaterType m_type[2];
- char m_filename[100];
- float m_level; // overall level
- float m_glint; // amplitude of reflections
- Math::Vector m_eddy; // amplitude of swirls
- Gfx::Color m_diffuse; // diffuse color
- Gfx::Color m_ambient; // ambient color
- float m_time;
- float m_lastLava;
- int m_subdiv;
-
- int m_brick; // number of brick*mosaics
- float m_size; // size of a item in an brick
-
- int m_lineUsed;
- WaterLine m_line[MAXWATERLINE];
-
- WaterVapor m_vapor[MAXWATVAPOR];
-
- bool m_bDraw;
- bool m_bLava;
- long m_color;
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
+ CDevice* m_pDevice;
+ CTerrain* m_terrain;
+ CParticle* m_particule;
+ CSound* m_sound;
+
+ WaterType m_type[2];
+ char m_filename[100];
+ float m_level; // overall level
+ float m_glint; // amplitude of reflections
+ Math::Vector m_eddy; // amplitude of swirls
+ Gfx::Color m_diffuse; // diffuse color
+ Gfx::Color m_ambient; // ambient color
+ float m_time;
+ float m_lastLava;
+ int m_subdiv;
+
+ int m_brick; // number of brick*mosaics
+ float m_size; // size of a item in an brick
+
+ int m_lineUsed;
+ WaterLine m_line[MAXWATERLINE];
+
+ WaterVapor m_vapor[MAXWATVAPOR];
+
+ bool m_bDraw;
+ bool m_bLava;
+ long m_color;
};
}; // namespace Gfx
diff --git a/src/math/const.h b/src/math/const.h
index 6721284..dd7ab0f 100644
--- a/src/math/const.h
+++ b/src/math/const.h
@@ -24,27 +24,27 @@
// Math module namespace
namespace Math
{
- /* @{ */ // start of group
+/* @{ */ // start of group
- //! Tolerance level -- minimum accepted float value
- const float TOLERANCE = 1e-6f;
+//! Tolerance level -- minimum accepted float value
+const float TOLERANCE = 1e-6f;
- //! Very small number (used in testing/returning some values)
- const float VERY_SMALL = 1e-6f;
- //! Very big number (used in testing/returning some values)
- const float VERY_BIG = 1e6f;
+//! Very small number (used in testing/returning some values)
+const float VERY_SMALL = 1e-6f;
+//! Very big number (used in testing/returning some values)
+const float VERY_BIG = 1e6f;
- //! Huge number
- const float HUGE = 1.0e+38f;
+//! Huge number
+const float HUGE = 1.0e+38f;
- //! PI
- const float PI = 3.14159265358979323846f;
+//! PI
+const float PI = 3.14159265358979323846f;
- //! Degrees to radians multiplier
- const float DEG_TO_RAD = 0.01745329251994329547f;
- //! Radians to degrees multiplier
- const float RAD_TO_DEG = 57.29577951308232286465f;
+//! Degrees to radians multiplier
+const float DEG_TO_RAD = 0.01745329251994329547f;
+//! Radians to degrees multiplier
+const float RAD_TO_DEG = 57.29577951308232286465f;
- /* @} */ // end of group
+/* @} */ // end of group
}; // namespace Math
diff --git a/src/math/conv.h b/src/math/conv.h
index bb6700b..43e6fbd 100644
--- a/src/math/conv.h
+++ b/src/math/conv.h
@@ -11,29 +11,29 @@
inline D3DVECTOR VEC_TO_D3DVEC(Math::Vector vec)
{
- return D3DVECTOR(vec.x, vec.y, vec.z);
+ return D3DVECTOR(vec.x, vec.y, vec.z);
}
inline Math::Vector D3DVEC_TO_VEC(D3DVECTOR vec)
{
- return Math::Vector(vec.x, vec.y, vec.z);
+ return Math::Vector(vec.x, vec.y, vec.z);
}
inline D3DMATRIX MAT_TO_D3DMAT(Math::Matrix mat)
{
- D3DMATRIX result;
- mat.Transpose();
- for (int r = 0; r < 4; ++r)
- {
- for (int c = 0; c < 16; ++c)
- result.m[r][c] = mat.m[4*c+r];
- }
- return result;
+ D3DMATRIX result;
+ mat.Transpose();
+ for (int r = 0; r < 4; ++r)
+ {
+ for (int c = 0; c < 16; ++c)
+ result.m[r][c] = mat.m[4*c+r];
+ }
+ return result;
}
inline Math::Matrix D3DMAT_TO_MAT(D3DMATRIX mat)
{
- Math::Matrix result(mat.m);
- result.Transpose();
- return result;
+ Math::Matrix result(mat.m);
+ result.Transpose();
+ return result;
}
diff --git a/src/math/func.h b/src/math/func.h
index 212f7c1..8f0e4ab 100644
--- a/src/math/func.h
+++ b/src/math/func.h
@@ -16,7 +16,7 @@
// * along with this program. If not, see http://www.gnu.org/licenses/.
/** @defgroup MathFuncModule math/func.h
- Contains common math functions.
+ Contains common math functions.
*/
#pragma once
@@ -36,146 +36,146 @@ namespace Math
//! Compares \a a and \a b within \a tolerance
inline bool IsEqual(float a, float b, float tolerance = TOLERANCE)
{
- return fabs(a - b) < tolerance;
+ return fabs(a - b) < tolerance;
}
//! Compares \a a to zero within \a tolerance
inline bool IsZero(float a, float tolerance = TOLERANCE)
{
- return IsEqual(a, 0.0f, tolerance);
+ return IsEqual(a, 0.0f, tolerance);
}
//! Minimum
inline float Min(float a, float b)
{
- if ( a <= b ) return a;
- else return b;
+ if ( a <= b ) return a;
+ else return b;
}
inline float Min(float a, float b, float c)
{
- return Min( Min(a, b), c );
+ return Min( Min(a, b), c );
}
inline float Min(float a, float b, float c, float d)
{
- return Min( Min(a, b), Min(c, d) );
+ return Min( Min(a, b), Min(c, d) );
}
inline float Min(float a, float b, float c, float d, float e)
{
- return Min( Min(a, b), Min(c, d), e );
+ return Min( Min(a, b), Min(c, d), e );
}
//! Maximum
inline float Max(float a, float b)
{
- if ( a >= b ) return a;
- else return b;
+ if ( a >= b ) return a;
+ else return b;
}
inline float Max(float a, float b, float c)
{
- return Max( Max(a, b), c );
+ return Max( Max(a, b), c );
}
inline float Max(float a, float b, float c, float d)
{
- return Max( Max(a, b), Max(c, d) );
+ return Max( Max(a, b), Max(c, d) );
}
inline float Max(float a, float b, float c, float d, float e)
{
- return Max( Max(a, b), Max(c, d), e );
+ return Max( Max(a, b), Max(c, d), e );
}
//! Returns the normalized value (0 .. 1)
inline float Norm(float a)
{
- if ( a < 0.0f ) return 0.0f;
- if ( a > 1.0f ) return 1.0f;
- return a;
+ if ( a < 0.0f ) return 0.0f;
+ if ( a > 1.0f ) return 1.0f;
+ return a;
}
//! Swaps two integers
inline void Swap(int &a, int &b)
{
- int c = a;
- a = b;
- b = c;
+ int c = a;
+ a = b;
+ b = c;
}
//! Swaps two real numbers
inline void Swap(float &a, float &b)
{
- float c = a;
- a = b;
- b = c;
+ float c = a;
+ a = b;
+ b = c;
}
//! Returns the modulo of a floating point number
/** Mod(8.1, 4) = 0.1
- Mod(n, 1) = fractional part of n */
+ Mod(n, 1) = fractional part of n */
inline float Mod(float a, float m)
{
- return a - ((int)(a/m))*m;
+ return a - ((int)(a/m))*m;
}
//! Returns a random value between 0 and 1.
inline float Rand()
{
- return (float)rand()/RAND_MAX;
+ return (float)rand()/RAND_MAX;
}
//! Returns a normalized angle, that is in other words between 0 and 2 * PI
inline float NormAngle(float angle)
{
- angle = Mod(angle, PI*2.0f);
- if ( angle < 0.0f )
- return PI*2.0f + angle;
+ angle = Mod(angle, PI*2.0f);
+ if ( angle < 0.0f )
+ return PI*2.0f + angle;
- return angle;
+ return angle;
}
//! Test if a angle is between two terminals
inline bool TestAngle(float angle, float min, float max)
{
- angle = NormAngle(angle);
- min = NormAngle(min);
- max = NormAngle(max);
+ angle = NormAngle(angle);
+ min = NormAngle(min);
+ max = NormAngle(max);
- if ( min > max )
- return ( angle <= max || angle >= min );
+ if ( min > max )
+ return ( angle <= max || angle >= min );
- return ( angle >= min && angle <= max );
+ return ( angle >= min && angle <= max );
}
//! Calculates a value (radians) proportional between a and b (degrees)
inline float PropAngle(int a, int b, float p)
{
- float aa = (float)a * DEG_TO_RAD;
- float bb = (float)b * DEG_TO_RAD;
+ float aa = (float)a * DEG_TO_RAD;
+ float bb = (float)b * DEG_TO_RAD;
- return aa+p*(bb-aa);
+ return aa+p*(bb-aa);
}
//! Calculates the angle to rotate the angle \a a to the angle \a g
/** A positive angle is counterclockwise (CCW). */
inline float Direction(float a, float g)
{
- a = NormAngle(a);
- g = NormAngle(g);
+ a = NormAngle(a);
+ g = NormAngle(g);
- if ( a < g )
- {
- if ( a+PI*2.0f-g < g-a ) a += PI*2.0f;
- }
- else
- {
- if ( g+PI*2.0f-a < a-g ) g += PI*2.0f;
- }
+ if ( a < g )
+ {
+ if ( a+PI*2.0f-g < g-a ) a += PI*2.0f;
+ }
+ else
+ {
+ if ( g+PI*2.0f-a < a-g ) g += PI*2.0f;
+ }
- return g-a;
+ return g-a;
}
//! Managing the dead zone of a joystick.
@@ -187,33 +187,33 @@ inline float Direction(float a, float g)
out: -1 0 0 1\endverbatim */
inline float Neutral(float value, float dead)
{
- if ( fabs(value) <= dead )
- {
- return 0.0f;
- }
- else
- {
- if ( value > 0.0f ) return (value-dead)/(1.0f-dead);
- else return (value+dead)/(1.0f-dead);
- }
+ if ( fabs(value) <= dead )
+ {
+ return 0.0f;
+ }
+ else
+ {
+ if ( value > 0.0f ) return (value-dead)/(1.0f-dead);
+ else return (value+dead)/(1.0f-dead);
+ }
}
//! Gently advances a desired value from its current value
/** Over time, the progression is more rapid. */
inline float Smooth(float actual, float hope, float time)
{
- float future = actual + (hope-actual)*time;
+ float future = actual + (hope-actual)*time;
- if ( hope > actual )
- {
- if ( future > hope ) future = hope;
- }
- if ( hope < actual )
- {
- if ( future < hope ) future = hope;
- }
+ if ( hope > actual )
+ {
+ if ( future > hope ) future = hope;
+ }
+ if ( hope < actual )
+ {
+ if ( future < hope ) future = hope;
+ }
- return future;
+ return future;
}
//! Bounces any movement
@@ -230,16 +230,16 @@ inline float Smooth(float actual, float hope, float time)
|<---->|middle\endverbatim */
inline float Bounce(float progress, float middle = 0.3f, float bounce = 0.4f)
{
- if ( progress < middle )
- {
- progress = progress/middle; // 0..1
- return 0.5f+sinf(progress*PI-PI/2.0f)/2.0f;
- }
- else
- {
- progress = (progress-middle)/(1.0f-middle); // 0..1
- return (1.0f-bounce/2.0f)+sinf((0.5f+progress*2.0f)*PI)*(bounce/2.0f);
- }
+ if ( progress < middle )
+ {
+ progress = progress/middle; // 0..1
+ return 0.5f+sinf(progress*PI-PI/2.0f)/2.0f;
+ }
+ else
+ {
+ progress = (progress-middle)/(1.0f-middle); // 0..1
+ return (1.0f-bounce/2.0f)+sinf((0.5f+progress*2.0f)*PI)*(bounce/2.0f);
+ }
}
/* @} */ // end of group
diff --git a/src/math/geometry.h b/src/math/geometry.h
index 5654dad..2f937e5 100644
--- a/src/math/geometry.h
+++ b/src/math/geometry.h
@@ -42,40 +42,40 @@ namespace Math
//! Returns py up on the line \a a - \a b
inline float MidPoint(const Point &a, const Point &b, float px)
{
- if (IsEqual(a.x, b.x))
- {
- if (a.y < b.y)
- return HUGE;
- else
- return -HUGE;
- }
- return (b.y-a.y) * (px-a.x) / (b.x-a.x) + a.y;
+ if (IsEqual(a.x, b.x))
+ {
+ if (a.y < b.y)
+ return HUGE;
+ else
+ return -HUGE;
+ }
+ return (b.y-a.y) * (px-a.x) / (b.x-a.x) + a.y;
}
//! Tests whether the point \a p is inside the triangle (\a a,\a b,\a c)
inline bool IsInsideTriangle(Point a, Point b, Point c, Point p)
{
- float n, m;
+ float n, m;
- if ( p.x < a.x && p.x < b.x && p.x < c.x ) return false;
- if ( p.x > a.x && p.x > b.x && p.x > c.x ) return false;
- if ( p.y < a.y && p.y < b.y && p.y < c.y ) return false;
- if ( p.y > a.y && p.y > b.y && p.y > c.y ) return false;
+ if ( p.x < a.x && p.x < b.x && p.x < c.x ) return false;
+ if ( p.x > a.x && p.x > b.x && p.x > c.x ) return false;
+ if ( p.y < a.y && p.y < b.y && p.y < c.y ) return false;
+ if ( p.y > a.y && p.y > b.y && p.y > c.y ) return false;
- if ( a.x > b.x ) Swap(a,b);
- if ( a.x > c.x ) Swap(a,c);
- if ( c.x < a.x ) Swap(c,a);
- if ( c.x < b.x ) Swap(c,b);
+ if ( a.x > b.x ) Swap(a,b);
+ if ( a.x > c.x ) Swap(a,c);
+ if ( c.x < a.x ) Swap(c,a);
+ if ( c.x < b.x ) Swap(c,b);
- n = MidPoint(a, b, p.x);
- m = MidPoint(a, c, p.x);
- if ( (n>p.y||p.y>m) && (n<p.y||p.y<m) ) return false;
+ n = MidPoint(a, b, p.x);
+ m = MidPoint(a, c, p.x);
+ if ( (n>p.y||p.y>m) && (n<p.y||p.y<m) ) return false;
- n = MidPoint(c, b, p.x);
- m = MidPoint(c, a, p.x);
- if ( (n>p.y||p.y>m) && (n<p.y||p.y<m) ) return false;
+ n = MidPoint(c, b, p.x);
+ m = MidPoint(c, a, p.x);
+ if ( (n>p.y||p.y>m) && (n<p.y||p.y<m) ) return false;
- return true;
+ return true;
}
//! Rotates a point around a center
@@ -84,18 +84,18 @@ inline bool IsInsideTriangle(Point a, Point b, Point c, Point p)
\a p the point */
inline Point RotatePoint(const Point &center, float angle, const Point &p)
{
- Point a;
- a.x = p.x-center.x;
- a.y = p.y-center.y;
+ Point a;
+ a.x = p.x-center.x;
+ a.y = p.y-center.y;
- Point b;
- b.x = a.x*cosf(angle) - a.y*sinf(angle);
- b.y = a.x*sinf(angle) + a.y*cosf(angle);
+ Point b;
+ b.x = a.x*cosf(angle) - a.y*sinf(angle);
+ b.y = a.x*sinf(angle) + a.y*cosf(angle);
- b.x += center.x;
- b.y += center.y;
+ b.x += center.x;
+ b.y += center.y;
- return b;
+ return b;
}
//! Rotates a point around the origin (0,0)
@@ -103,10 +103,10 @@ inline Point RotatePoint(const Point &center, float angle, const Point &p)
\a p the point */
inline Point RotatePoint(float angle, const Point &p)
{
- float x = p.x*cosf(angle) - p.y*sinf(angle);
- float y = p.x*sinf(angle) + p.y*cosf(angle);
+ float x = p.x*cosf(angle) - p.y*sinf(angle);
+ float y = p.x*sinf(angle) + p.y*cosf(angle);
- return Point(x, y);
+ return Point(x, y);
}
//! Rotates a vector (dist, 0).
@@ -114,25 +114,25 @@ inline Point RotatePoint(float angle, const Point &p)
\a dist distance to origin */
inline Point RotatePoint(float angle, float dist)
{
- float x = dist*cosf(angle);
- float y = dist*sinf(angle);
+ float x = dist*cosf(angle);
+ float y = dist*sinf(angle);
- return Point(x, y);
+ return Point(x, y);
}
//! TODO documentation
inline void RotatePoint(float cx, float cy, float angle, float &px, float &py)
{
- float ax, ay;
+ float ax, ay;
- px -= cx;
- py -= cy;
+ px -= cx;
+ py -= cy;
- ax = px*cosf(angle) - py*sinf(angle);
- ay = px*sinf(angle) + py*cosf(angle);
+ ax = px*cosf(angle) - py*sinf(angle);
+ ay = px*sinf(angle) + py*cosf(angle);
- px = cx+ax;
- py = cy+ay;
+ px = cx+ax;
+ py = cy+ay;
}
//! Rotates a point around a center in space.
@@ -142,16 +142,16 @@ inline void RotatePoint(float cx, float cy, float angle, float &px, float &py)
\returns the rotated point */
inline void RotatePoint(const Vector &center, float angleH, float angleV, Vector &p)
{
- p.x -= center.x;
- p.y -= center.y;
- p.z -= center.z;
+ p.x -= center.x;
+ p.y -= center.y;
+ p.z -= center.z;
- Vector b;
- b.x = p.x*cosf(angleH) - p.z*sinf(angleH);
- b.y = p.z*sinf(angleV) + p.y*cosf(angleV);
- b.z = p.x*sinf(angleH) + p.z*cosf(angleH);
+ Vector b;
+ b.x = p.x*cosf(angleH) - p.z*sinf(angleH);
+ b.y = p.z*sinf(angleV) + p.y*cosf(angleV);
+ b.z = p.x*sinf(angleH) + p.z*cosf(angleH);
- p = center + b;
+ p = center + b;
}
//! Rotates a point around a center in space.
@@ -161,60 +161,60 @@ inline void RotatePoint(const Vector &center, float angleH, float angleV, Vector
\returns the rotated point */
inline void RotatePoint2(const Vector center, float angleH, float angleV, Vector &p)
{
- p.x -= center.x;
- p.y -= center.y;
- p.z -= center.z;
+ p.x -= center.x;
+ p.y -= center.y;
+ p.z -= center.z;
- Vector a;
- a.x = p.x*cosf(angleH) - p.z*sinf(angleH);
- a.y = p.y;
- a.z = p.x*sinf(angleH) + p.z*cosf(angleH);
+ Vector a;
+ a.x = p.x*cosf(angleH) - p.z*sinf(angleH);
+ a.y = p.y;
+ a.z = p.x*sinf(angleH) + p.z*cosf(angleH);
- Vector b;
- b.x = a.x;
- b.y = a.z*sinf(angleV) + a.y*cosf(angleV);
- b.z = a.z*cosf(angleV) - a.y*sinf(angleV);
+ Vector b;
+ b.x = a.x;
+ b.y = a.z*sinf(angleV) + a.y*cosf(angleV);
+ b.z = a.z*cosf(angleV) - a.y*sinf(angleV);
- p = center + b;
+ p = center + b;
}
//! Returns the angle between point (x,y) and (0,0)
inline float RotateAngle(float x, float y)
{
- if ( (x == 0.0f) && (y == 0.0f) )
- return 0.0f;
+ if ( (x == 0.0f) && (y == 0.0f) )
+ return 0.0f;
- float atan = atan2(x, y);
+ float atan = atan2(x, y);
- if ((y < 0.0f) && (x >= 0.0f))
- return -atan + 2.5f*PI;
- else
- return -atan + 0.5f*PI;
+ if ((y < 0.0f) && (x >= 0.0f))
+ return -atan + 2.5f*PI;
+ else
+ return -atan + 0.5f*PI;
}
//! Calculates the angle between two points and one center
/** \a center the center point
\a p1,p2 the two points
- \returns The angle in radians (positive is counterclockwise (CCW) ) */
+ \returns The angle in radians (positive is counterclockwise (CCW) ) */
inline float RotateAngle(const Point &center, const Point &p1, const Point &p2)
{
- if (PointsEqual(p1, center))
- return 0;
+ if (PointsEqual(p1, center))
+ return 0;
- if (PointsEqual(p2, center))
- return 0;
+ if (PointsEqual(p2, center))
+ return 0;
- float a1 = asinf((p1.y - center.y) / Distance(p1, center));
- float a2 = asinf((p2.y - center.y) / Distance(p2, center));
+ float a1 = asinf((p1.y - center.y) / Distance(p1, center));
+ float a2 = asinf((p2.y - center.y) / Distance(p2, center));
- if (p1.x < center.x) a1 = PI - a1;
- if (p2.x < center.x) a2 = PI - a2;
+ if (p1.x < center.x) a1 = PI - a1;
+ if (p2.x < center.x) a2 = PI - a2;
- float a = a2 - a1;
- if (a < 0)
- a += 2.0f*PI;
+ float a = a2 - a1;
+ if (a < 0)
+ a += 2.0f*PI;
- return a;
+ return a;
}
//! Loads view matrix from the given vectors
@@ -223,62 +223,62 @@ inline float RotateAngle(const Point &center, const Point &p1, const Point &p2)
\a worldUp up vector */
inline void LoadViewMatrix(Matrix &mat, const Vector &from, const Vector &at, const Vector &worldUp)
{
- // Get the z basis vector, which points straight ahead. This is the
- // difference from the eyepoint to the lookat point.
- Vector view = at - from;
+ // Get the z basis vector, which points straight ahead. This is the
+ // difference from the eyepoint to the lookat point.
+ Vector view = at - from;
- float length = view.Length();
- assert(! IsZero(length) );
+ float length = view.Length();
+ assert(! IsZero(length) );
- // Normalize the z basis vector
- view /= length;
+ // Normalize the z basis vector
+ view /= length;
- // Get the dot product, and calculate the projection of the z basis
- // vector onto the up vector. The projection is the y basis vector.
- float dotProduct = DotProduct(worldUp, view);
+ // Get the dot product, and calculate the projection of the z basis
+ // vector onto the up vector. The projection is the y basis vector.
+ float dotProduct = DotProduct(worldUp, view);
- Vector up = worldUp - dotProduct * view;
+ Vector up = worldUp - dotProduct * view;
- // If this vector has near-zero length because the input specified a
- // bogus up vector, let's try a default up vector
- if ( IsZero(length = up.Length()) )
- {
- up = Vector(0.0f, 1.0f, 0.0f) - view.y * view;
-
- // If we still have near-zero length, resort to a different axis.
+ // If this vector has near-zero length because the input specified a
+ // bogus up vector, let's try a default up vector
if ( IsZero(length = up.Length()) )
{
- up = Vector(0.0f, 0.0f, 1.0f) - view.z * view;
+ up = Vector(0.0f, 1.0f, 0.0f) - view.y * view;
+
+ // If we still have near-zero length, resort to a different axis.
+ if ( IsZero(length = up.Length()) )
+ {
+ up = Vector(0.0f, 0.0f, 1.0f) - view.z * view;
- assert(! IsZero(up.Length()) );
+ assert(! IsZero(up.Length()) );
+ }
}
- }
-
- // Normalize the y basis vector
- up /= length;
-
- // The x basis vector is found simply with the cross product of the y
- // and z basis vectors
- Vector right = CrossProduct(up, view);
-
- // Start building the matrix. The first three rows contains the basis
- // vectors used to rotate the view to point at the lookat point
- mat.LoadIdentity();
-
- /* (1,1) */ mat.m[0 ] = right.x;
- /* (2,1) */ mat.m[1 ] = up.x;
- /* (3,1) */ mat.m[2 ] = view.x;
- /* (1,2) */ mat.m[4 ] = right.y;
- /* (2,2) */ mat.m[5 ] = up.y;
- /* (3,2) */ mat.m[6 ] = view.y;
- /* (1,3) */ mat.m[8 ] = right.z;
- /* (2,3) */ mat.m[9 ] = up.z;
- /* (3,3) */ mat.m[10] = view.z;
-
- // Do the translation values (rotations are still about the eyepoint)
- /* (1,4) */ mat.m[12] = -DotProduct(from, right);
- /* (2,4) */ mat.m[13] = -DotProduct(from, up);
- /* (3,4) */ mat.m[14] = -DotProduct(from, view);
+
+ // Normalize the y basis vector
+ up /= length;
+
+ // The x basis vector is found simply with the cross product of the y
+ // and z basis vectors
+ Vector right = CrossProduct(up, view);
+
+ // Start building the matrix. The first three rows contains the basis
+ // vectors used to rotate the view to point at the lookat point
+ mat.LoadIdentity();
+
+ /* (1,1) */ mat.m[0 ] = right.x;
+ /* (2,1) */ mat.m[1 ] = up.x;
+ /* (3,1) */ mat.m[2 ] = view.x;
+ /* (1,2) */ mat.m[4 ] = right.y;
+ /* (2,2) */ mat.m[5 ] = up.y;
+ /* (3,2) */ mat.m[6 ] = view.y;
+ /* (1,3) */ mat.m[8 ] = right.z;
+ /* (2,3) */ mat.m[9 ] = up.z;
+ /* (3,3) */ mat.m[10] = view.z;
+
+ // Do the translation values (rotations are still about the eyepoint)
+ /* (1,4) */ mat.m[12] = -DotProduct(from, right);
+ /* (2,4) */ mat.m[13] = -DotProduct(from, up);
+ /* (3,4) */ mat.m[14] = -DotProduct(from, view);
}
//! Loads a perspective projection matrix
@@ -289,73 +289,73 @@ inline void LoadViewMatrix(Matrix &mat, const Vector &from, const Vector &at, co
inline void LoadProjectionMatrix(Matrix &mat, float fov = 1.570795f, float aspect = 1.0f,
float nearPlane = 1.0f, float farPlane = 1000.0f)
{
- assert(fabs(farPlane - nearPlane) >= 0.01f);
- assert(fabs(sin(fov / 2)) >= 0.01f);
+ assert(fabs(farPlane - nearPlane) >= 0.01f);
+ assert(fabs(sin(fov / 2)) >= 0.01f);
- float w = aspect * (cosf(fov / 2) / sinf(fov / 2));
- float h = 1.0f * (cosf(fov / 2) / sinf(fov / 2));
- float q = farPlane / (farPlane - nearPlane);
+ float w = aspect * (cosf(fov / 2) / sinf(fov / 2));
+ float h = 1.0f * (cosf(fov / 2) / sinf(fov / 2));
+ float q = farPlane / (farPlane - nearPlane);
- mat.LoadZero();
+ mat.LoadZero();
- /* (1,1) */ mat.m[0 ] = w;
- /* (2,2) */ mat.m[5 ] = h;
- /* (3,3) */ mat.m[10] = q;
- /* (4,3) */ mat.m[11] = 1.0f;
- /* (3,4) */ mat.m[14] = -q * nearPlane;
+ /* (1,1) */ mat.m[0 ] = w;
+ /* (2,2) */ mat.m[5 ] = h;
+ /* (3,3) */ mat.m[10] = q;
+ /* (4,3) */ mat.m[11] = 1.0f;
+ /* (3,4) */ mat.m[14] = -q * nearPlane;
}
//! Loads a translation matrix from given vector
/** \a trans vector of translation*/
inline void LoadTranslationMatrix(Matrix &mat, const Vector &trans)
{
- mat.LoadIdentity();
- /* (1,4) */ mat.m[12] = trans.x;
- /* (2,4) */ mat.m[13] = trans.y;
- /* (3,4) */ mat.m[14] = trans.z;
+ mat.LoadIdentity();
+ /* (1,4) */ mat.m[12] = trans.x;
+ /* (2,4) */ mat.m[13] = trans.y;
+ /* (3,4) */ mat.m[14] = trans.z;
}
//! Loads a scaling matrix fom given vector
/** \a scale vector with scaling factors for X, Y, Z */
inline void LoadScaleMatrix(Matrix &mat, const Vector &scale)
{
- mat.LoadIdentity();
- /* (1,1) */ mat.m[0 ] = scale.x;
- /* (2,2) */ mat.m[5 ] = scale.y;
- /* (3,3) */ mat.m[10] = scale.z;
+ mat.LoadIdentity();
+ /* (1,1) */ mat.m[0 ] = scale.x;
+ /* (2,2) */ mat.m[5 ] = scale.y;
+ /* (3,3) */ mat.m[10] = scale.z;
}
//! Loads a rotation matrix along the X axis
/** \a angle angle in radians */
inline void LoadRotationXMatrix(Matrix &mat, float angle)
{
- mat.LoadIdentity();
- /* (2,2) */ mat.m[5 ] = cosf(angle);
- /* (3,2) */ mat.m[6 ] = sinf(angle);
- /* (2,3) */ mat.m[9 ] = -sinf(angle);
- /* (3,3) */ mat.m[10] = cosf(angle);
+ mat.LoadIdentity();
+ /* (2,2) */ mat.m[5 ] = cosf(angle);
+ /* (3,2) */ mat.m[6 ] = sinf(angle);
+ /* (2,3) */ mat.m[9 ] = -sinf(angle);
+ /* (3,3) */ mat.m[10] = cosf(angle);
}
//! Loads a rotation matrix along the Y axis
/** \a angle angle in radians */
inline void LoadRotationYMatrix(Matrix &mat, float angle)
{
- mat.LoadIdentity();
- /* (1,1) */ mat.m[0 ] = cosf(angle);
- /* (3,1) */ mat.m[2 ] = -sinf(angle);
- /* (1,3) */ mat.m[8 ] = sinf(angle);
- /* (3,3) */ mat.m[10] = cosf(angle);
+ mat.LoadIdentity();
+ /* (1,1) */ mat.m[0 ] = cosf(angle);
+ /* (3,1) */ mat.m[2 ] = -sinf(angle);
+ /* (1,3) */ mat.m[8 ] = sinf(angle);
+ /* (3,3) */ mat.m[10] = cosf(angle);
}
//! Loads a rotation matrix along the Z axis
/** \a angle angle in radians */
inline void LoadRotationZMatrix(Matrix &mat, float angle)
{
- mat.LoadIdentity();
- /* (1,1) */ mat.m[0 ] = cosf(angle);
- /* (2,1) */ mat.m[1 ] = sinf(angle);
- /* (1,2) */ mat.m[4 ] = -sinf(angle);
- /* (2,2) */ mat.m[5 ] = cosf(angle);
+ mat.LoadIdentity();
+ /* (1,1) */ mat.m[0 ] = cosf(angle);
+ /* (2,1) */ mat.m[1 ] = sinf(angle);
+ /* (1,2) */ mat.m[4 ] = -sinf(angle);
+ /* (2,2) */ mat.m[5 ] = cosf(angle);
}
//! Loads a rotation matrix along the given axis
@@ -363,66 +363,66 @@ inline void LoadRotationZMatrix(Matrix &mat, float angle)
\a angle angle in radians */
inline void LoadRotationMatrix(Matrix &mat, const Vector &dir, float angle)
{
- float cos = cosf(angle);
- float sin = sinf(angle);
- Vector v = Normalize(dir);
+ float cos = cosf(angle);
+ float sin = sinf(angle);
+ Vector v = Normalize(dir);
- mat.LoadIdentity();
+ mat.LoadIdentity();
- /* (1,1) */ mat.m[0 ] = (v.x * v.x) * (1.0f - cos) + cos;
- /* (2,1) */ mat.m[1 ] = (v.x * v.y) * (1.0f - cos) - (v.z * sin);
- /* (3,1) */ mat.m[2 ] = (v.x * v.z) * (1.0f - cos) + (v.y * sin);
+ /* (1,1) */ mat.m[0 ] = (v.x * v.x) * (1.0f - cos) + cos;
+ /* (2,1) */ mat.m[1 ] = (v.x * v.y) * (1.0f - cos) - (v.z * sin);
+ /* (3,1) */ mat.m[2 ] = (v.x * v.z) * (1.0f - cos) + (v.y * sin);
- /* (1,2) */ mat.m[4 ] = (v.y * v.x) * (1.0f - cos) + (v.z * sin);
- /* (2,2) */ mat.m[5 ] = (v.y * v.y) * (1.0f - cos) + cos ;
- /* (3,2) */ mat.m[6 ] = (v.y * v.z) * (1.0f - cos) - (v.x * sin);
+ /* (1,2) */ mat.m[4 ] = (v.y * v.x) * (1.0f - cos) + (v.z * sin);
+ /* (2,2) */ mat.m[5 ] = (v.y * v.y) * (1.0f - cos) + cos ;
+ /* (3,2) */ mat.m[6 ] = (v.y * v.z) * (1.0f - cos) - (v.x * sin);
- /* (1,3) */ mat.m[8 ] = (v.z * v.x) * (1.0f - cos) - (v.y * sin);
- /* (2,3) */ mat.m[9 ] = (v.z * v.y) * (1.0f - cos) + (v.x * sin);
- /* (3,3) */ mat.m[10] = (v.z * v.z) * (1.0f - cos) + cos;
+ /* (1,3) */ mat.m[8 ] = (v.z * v.x) * (1.0f - cos) - (v.y * sin);
+ /* (2,3) */ mat.m[9 ] = (v.z * v.y) * (1.0f - cos) + (v.x * sin);
+ /* (3,3) */ mat.m[10] = (v.z * v.z) * (1.0f - cos) + cos;
}
//! Calculates the matrix to make three rotations in the order X, Z and Y
inline void LoadRotationXZYMatrix(Matrix &mat, const Vector &angle)
{
- Matrix temp;
- LoadRotationXMatrix(temp, angle.x);
+ Matrix temp;
+ LoadRotationXMatrix(temp, angle.x);
- LoadRotationZMatrix(mat, angle.z);
- mat = Math::MultiplyMatrices(temp, mat);
+ LoadRotationZMatrix(mat, angle.z);
+ mat = Math::MultiplyMatrices(temp, mat);
- LoadRotationYMatrix(temp, angle.y);
- mat = Math::MultiplyMatrices(temp, mat);
+ LoadRotationYMatrix(temp, angle.y);
+ mat = Math::MultiplyMatrices(temp, mat);
}
//! Calculates the matrix to make three rotations in the order Z, X and Y
inline void LoadRotationZXYMatrix(Matrix &mat, const Vector &angle)
{
- Matrix temp;
- LoadRotationZMatrix(temp, angle.z);
+ Matrix temp;
+ LoadRotationZMatrix(temp, angle.z);
- LoadRotationXMatrix(mat, angle.x);
- mat = Math::MultiplyMatrices(temp, mat);
+ LoadRotationXMatrix(mat, angle.x);
+ mat = Math::MultiplyMatrices(temp, mat);
- LoadRotationYMatrix(temp, angle.y);
- mat = Math::MultiplyMatrices(temp, mat);
+ LoadRotationYMatrix(temp, angle.y);
+ mat = Math::MultiplyMatrices(temp, mat);
}
//! Returns the distance between projections on XZ plane of two vectors
inline float DistanceProjected(const Vector &a, const Vector &b)
{
- return sqrtf( (a.x-b.x)*(a.x-b.x) +
- (a.z-b.z)*(a.z-b.z) );
+ return sqrtf( (a.x-b.x)*(a.x-b.x) +
+ (a.z-b.z)*(a.z-b.z) );
}
//! Returns the normal vector to a plane
/** \param p1,p2,p3 points defining the plane */
inline Vector NormalToPlane(const Vector &p1, const Vector &p2, const Vector &p3)
{
- Vector u = p3 - p1;
- Vector v = p2 - p1;
+ Vector u = p3 - p1;
+ Vector v = p2 - p1;
- return Normalize(CrossProduct(u, v));
+ return Normalize(CrossProduct(u, v));
}
//! Returns a point on the line \a p1 - \a p2, in \a dist distance from \a p1
@@ -430,7 +430,7 @@ inline Vector NormalToPlane(const Vector &p1, const Vector &p2, const Vector &p3
\a dist scaling factor from \a p1, relative to distance between \a p1 and \a p2 */
inline Vector SegmentPoint(const Vector &p1, const Vector &p2, float dist)
{
- return p1 + (p2 - p1) * dist;
+ return p1 + (p2 - p1) * dist;
}
//! Returns the distance between given point and a plane
@@ -438,10 +438,10 @@ inline Vector SegmentPoint(const Vector &p1, const Vector &p2, float dist)
\param a,b,c points defining the plane */
inline float DistanceToPlane(const Vector &a, const Vector &b, const Vector &c, const Vector &p)
{
- Vector n = NormalToPlane(a, b, c);
- float d = -(n.x*a.x + n.y*a.y + n.z*a.z);
+ Vector n = NormalToPlane(a, b, c);
+ float d = -(n.x*a.x + n.y*a.y + n.z*a.z);
- return fabs(n.x*p.x + n.y*p.y + n.z*p.z + d);
+ return fabs(n.x*p.x + n.y*p.y + n.z*p.z + d);
}
//! Checks if two planes defined by three points are the same
@@ -449,73 +449,73 @@ inline float DistanceToPlane(const Vector &a, const Vector &b, const Vector &c,
\a plane2 array of three vectors defining the second plane */
inline bool IsSamePlane(const Vector (&plane1)[3], const Vector (&plane2)[3])
{
- Vector n1 = NormalToPlane(plane1[0], plane1[1], plane1[2]);
- Vector n2 = NormalToPlane(plane2[0], plane2[1], plane2[2]);
+ Vector n1 = NormalToPlane(plane1[0], plane1[1], plane1[2]);
+ Vector n2 = NormalToPlane(plane2[0], plane2[1], plane2[2]);
- if ( fabs(n1.x-n2.x) > 0.1f ||
- fabs(n1.y-n2.y) > 0.1f ||
- fabs(n1.z-n2.z) > 0.1f )
- return false;
+ if ( fabs(n1.x-n2.x) > 0.1f ||
+ fabs(n1.y-n2.y) > 0.1f ||
+ fabs(n1.z-n2.z) > 0.1f )
+ return false;
- float dist = DistanceToPlane(plane1[0], plane1[1], plane1[2], plane2[0]);
- if ( dist > 0.1f )
- return false;
+ float dist = DistanceToPlane(plane1[0], plane1[1], plane1[2], plane2[0]);
+ if ( dist > 0.1f )
+ return false;
- return true;
+ return true;
}
//! Calculates the intersection "i" right "of" the plane "abc".
inline bool Intersect(const Vector &a, const Vector &b, const Vector &c, const Vector &d, const Vector &e, Vector &i)
{
- float d1 = (d.x-a.x)*((b.y-a.y)*(c.z-a.z)-(c.y-a.y)*(b.z-a.z)) -
- (d.y-a.y)*((b.x-a.x)*(c.z-a.z)-(c.x-a.x)*(b.z-a.z)) +
- (d.z-a.z)*((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y));
+ float d1 = (d.x-a.x)*((b.y-a.y)*(c.z-a.z)-(c.y-a.y)*(b.z-a.z)) -
+ (d.y-a.y)*((b.x-a.x)*(c.z-a.z)-(c.x-a.x)*(b.z-a.z)) +
+ (d.z-a.z)*((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y));
- float d2 = (d.x-e.x)*((b.y-a.y)*(c.z-a.z)-(c.y-a.y)*(b.z-a.z)) -
- (d.y-e.y)*((b.x-a.x)*(c.z-a.z)-(c.x-a.x)*(b.z-a.z)) +
- (d.z-e.z)*((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y));
+ float d2 = (d.x-e.x)*((b.y-a.y)*(c.z-a.z)-(c.y-a.y)*(b.z-a.z)) -
+ (d.y-e.y)*((b.x-a.x)*(c.z-a.z)-(c.x-a.x)*(b.z-a.z)) +
+ (d.z-e.z)*((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y));
- if (d2 == 0)
- return false;
+ if (d2 == 0)
+ return false;
- i.x = d.x + d1/d2*(e.x-d.x);
- i.y = d.y + d1/d2*(e.y-d.y);
- i.z = d.z + d1/d2*(e.z-d.z);
+ i.x = d.x + d1/d2*(e.x-d.x);
+ i.y = d.y + d1/d2*(e.y-d.y);
+ i.z = d.z + d1/d2*(e.z-d.z);
- return true;
+ return true;
}
//! Calculates the intersection of the straight line passing through p (x, z)
/** Line is parallel to the y axis, with the plane abc. Returns p.y. */
inline bool IntersectY(const Vector &a, const Vector &b, const Vector &c, Vector &p)
{
- float d = (b.x-a.x)*(c.z-a.z) - (c.x-a.x)*(b.z-a.z);
- float d1 = (p.x-a.x)*(c.z-a.z) - (c.x-a.x)*(p.z-a.z);
- float d2 = (b.x-a.x)*(p.z-a.z) - (p.x-a.x)*(b.z-a.z);
+ float d = (b.x-a.x)*(c.z-a.z) - (c.x-a.x)*(b.z-a.z);
+ float d1 = (p.x-a.x)*(c.z-a.z) - (c.x-a.x)*(p.z-a.z);
+ float d2 = (b.x-a.x)*(p.z-a.z) - (p.x-a.x)*(b.z-a.z);
- if (d == 0.0f)
- return false;
+ if (d == 0.0f)
+ return false;
- p.y = a.y + d1/d*(b.y-a.y) + d2/d*(c.y-a.y);
+ p.y = a.y + d1/d*(b.y-a.y) + d2/d*(c.y-a.y);
- return true;
+ return true;
}
//! Calculates the end point
inline Vector LookatPoint(const Vector &eye, float angleH, float angleV, float length)
{
- Vector lookat = eye;
- lookat.z += length;
+ Vector lookat = eye;
+ lookat.z += length;
- RotatePoint(eye, angleH, angleV, lookat);
+ RotatePoint(eye, angleH, angleV, lookat);
- return lookat;
+ return lookat;
}
//! TODO documentation
inline Vector Transform(const Matrix &m, const Vector &p)
{
- return MatrixVectorMultiply(m, p);
+ return MatrixVectorMultiply(m, p);
}
//! Calculates the projection of the point \a p on a straight line \a a to \a b.
@@ -523,28 +523,28 @@ inline Vector Transform(const Matrix &m, const Vector &p)
\a a,b two ends of the line */
inline Vector Projection(const Vector &a, const Vector &b, const Vector &p)
{
- float k = DotProduct(b - a, p - a);
- k /= DotProduct(b - a, b - a);
+ float k = DotProduct(b - a, p - a);
+ k /= DotProduct(b - a, b - a);
- return a + k*(b-a);
+ return a + k*(b-a);
}
//! Calculates point of view to look at a center two angles and a distance
inline Vector RotateView(Vector center, float angleH, float angleV, float dist)
{
- Matrix mat1, mat2;
- LoadRotationZMatrix(mat1, -angleV);
- LoadRotationYMatrix(mat2, -angleH);
+ Matrix mat1, mat2;
+ LoadRotationZMatrix(mat1, -angleV);
+ LoadRotationYMatrix(mat2, -angleH);
- Matrix mat = MultiplyMatrices(mat2, mat1);
+ Matrix mat = MultiplyMatrices(mat2, mat1);
- Vector eye;
- eye.x = 0.0f+dist;
- eye.y = 0.0f;
- eye.z = 0.0f;
- eye = Transform(mat, eye);
+ Vector eye;
+ eye.x = 0.0f+dist;
+ eye.y = 0.0f;
+ eye.z = 0.0f;
+ eye = Transform(mat, eye);
- return eye+center;
+ return eye+center;
}
/* @} */ // end of group
diff --git a/src/math/intpoint.h b/src/math/intpoint.h
index cbfee2d..a760bc2 100644
--- a/src/math/intpoint.h
+++ b/src/math/intpoint.h
@@ -31,12 +31,12 @@ namespace Math {
*/
struct IntPoint
{
- //! X coord
- long x;
- //! Y coord
- long y;
+ //! X coord
+ long x;
+ //! Y coord
+ long y;
- IntPoint(long aX = 0, long aY = 0) : x(aX), y(aY) {}
+ IntPoint(long aX = 0, long aY = 0) : x(aX), y(aY) {}
};
/* @} */ // end of group
diff --git a/src/math/matrix.h b/src/math/matrix.h
index 35871cf..9b29f46 100644
--- a/src/math/matrix.h
+++ b/src/math/matrix.h
@@ -37,356 +37,356 @@ namespace Math
/** \struct Matrix math/matrix.h
\brief 4x4 matrix
- Represents an universal 4x4 matrix that can be used in OpenGL and DirectX engines.
- Contains the required methods for operating on matrices (inverting, multiplying, etc.).
+ Represents an universal 4x4 matrix that can be used in OpenGL and DirectX engines.
+ Contains the required methods for operating on matrices (inverting, multiplying, etc.).
- The internal representation is a 16-value table in column-major order, thus:
+ The internal representation is a 16-value table in column-major order, thus:
- \verbatim
+ \verbatim
m[0 ] m[4 ] m[8 ] m[12]
m[1 ] m[5 ] m[9 ] m[13]
m[2 ] m[6 ] m[10] m[14]
m[3 ] m[7 ] m[11] m[15] \endverbatim
- This representation is native to OpenGL; DirectX requires transposing the matrix.
+ This representation is native to OpenGL; DirectX requires transposing the matrix.
- The order of multiplication of matrix and vector is also OpenGL-native
- (see the function MatrixVectorMultiply).
+ The order of multiplication of matrix and vector is also OpenGL-native
+ (see the function MatrixVectorMultiply).
- All methods are made inline to maximize optimization.
+ All methods are made inline to maximize optimization.
- Unit tests for the structure and related functions are in module: math/test/matrix_test.cpp.
+ Unit tests for the structure and related functions are in module: math/test/matrix_test.cpp.
**/
struct Matrix
{
- //! Matrix values in column-major order
- float m[16];
-
- //! Creates the indentity matrix
- inline Matrix()
- {
- LoadIdentity();
- }
-
- //! Creates the matrix from 1D array
- /** \a m matrix values in column-major order */
- inline explicit Matrix(const float (&m)[16])
- {
- for (int i = 0; i < 16; ++i)
- this->m[i] = m[i];
- }
-
- //! Creates the matrix from 2D array
- /** The array's first index is row, second is column.
- \a m array with values */
- inline explicit Matrix(const float (&m)[4][4])
- {
- for (int c = 0; c < 4; ++c)
+ //! Matrix values in column-major order
+ float m[16];
+
+ //! Creates the indentity matrix
+ inline Matrix()
{
- for (int r = 0; r < 4; ++r)
- {
- this->m[4*c+r] = m[r][c];
- }
+ LoadIdentity();
}
- }
- inline void Set(int row, int col, float value)
- {
- m[(col-1)*4+(row-1)] = value;
- }
+ //! Creates the matrix from 1D array
+ /** \a m matrix values in column-major order */
+ inline explicit Matrix(const float (&m)[16])
+ {
+ for (int i = 0; i < 16; ++i)
+ this->m[i] = m[i];
+ }
- inline float Get(int row, int col)
- {
- return m[(col-1)*4+(row-1)];
- }
+ //! Creates the matrix from 2D array
+ /** The array's first index is row, second is column.
+ \a m array with values */
+ inline explicit Matrix(const float (&m)[4][4])
+ {
+ for (int c = 0; c < 4; ++c)
+ {
+ for (int r = 0; r < 4; ++r)
+ {
+ this->m[4*c+r] = m[r][c];
+ }
+ }
+ }
- //! Loads the zero matrix
- inline void LoadZero()
- {
- for (int i = 0; i < 16; ++i)
- m[i] = 0.0f;
- }
-
- //! Loads the identity matrix
- inline void LoadIdentity()
- {
- LoadZero();
- /* (1,1) */ m[0 ] = 1.0f;
- /* (2,2) */ m[5 ] = 1.0f;
- /* (3,3) */ m[10] = 1.0f;
- /* (4,4) */ m[15] = 1.0f;
- }
-
- //! Transposes the matrix
- inline void Transpose()
- {
- /* (2,1) <-> (1,2) */ Swap(m[1 ], m[4 ]);
- /* (3,1) <-> (1,3) */ Swap(m[2 ], m[8 ]);
- /* (4,1) <-> (1,4) */ Swap(m[3 ], m[12]);
- /* (3,2) <-> (2,3) */ Swap(m[6 ], m[9 ]);
- /* (4,2) <-> (2,4) */ Swap(m[7 ], m[13]);
- /* (4,3) <-> (3,4) */ Swap(m[11], m[14]);
- }
-
- //! Calculates the determinant of the matrix
- /** \returns the determinant */
- inline float Det() const
- {
- float result = 0.0f;
- for (int i = 0; i < 4; ++i)
+ inline void Set(int row, int col, float value)
{
- result += m[i] * Cofactor(i, 0);
+ m[(col-1)*4+(row-1)] = value;
}
- return result;
- }
- //! Calculates the cofactor of the matrix
- /** \a r row (0 to 3)
- \a c column (0 to 3)
- \returns the cofactor */
- inline float Cofactor(int r, int c) const
- {
- assert(r >= 0 && r <= 3);
- assert(c >= 0 && c <= 3);
+ inline float Get(int row, int col)
+ {
+ return m[(col-1)*4+(row-1)];
+ }
- float result = 0.0f;
+ //! Loads the zero matrix
+ inline void LoadZero()
+ {
+ for (int i = 0; i < 16; ++i)
+ m[i] = 0.0f;
+ }
- /* That looks horrible, I know. But it's fast :) */
+ //! Loads the identity matrix
+ inline void LoadIdentity()
+ {
+ LoadZero();
+ /* (1,1) */ m[0 ] = 1.0f;
+ /* (2,2) */ m[5 ] = 1.0f;
+ /* (3,3) */ m[10] = 1.0f;
+ /* (4,4) */ m[15] = 1.0f;
+ }
- switch (4*r + c)
+ //! Transposes the matrix
+ inline void Transpose()
{
- // r=0, c=0
- /* 05 09 13
- 06 10 14
- 07 11 15 */
- case 0:
- result = + m[5 ] * (m[10] * m[15] - m[14] * m[11])
- - m[9 ] * (m[6 ] * m[15] - m[14] * m[7 ])
- + m[13] * (m[6 ] * m[11] - m[10] * m[7 ]);
- break;
-
- // r=0, c=1
- /* 01 09 13
- 02 10 14
- 03 11 15 */
- case 1:
- result = - m[1 ] * (m[10] * m[15] - m[14] * m[11])
- + m[9 ] * (m[2 ] * m[15] - m[14] * m[3 ])
- - m[13] * (m[2 ] * m[11] - m[10] * m[3 ]);
- break;
-
- // r=0, c=2
- /* 01 05 13
- 02 06 14
- 03 07 15 */
- case 2:
- result = + m[1 ] * (m[6 ] * m[15] - m[14] * m[7 ])
- - m[5 ] * (m[2 ] * m[15] - m[14] * m[3 ])
- + m[13] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]);
- break;
-
- // r=0, c=3
- /* 01 05 09
- 02 06 10
- 03 07 11 */
- case 3:
- result = - m[1 ] * (m[6 ] * m[11] - m[10] * m[7 ])
- + m[5 ] * (m[2 ] * m[11] - m[10] * m[3 ])
- - m[9 ] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]);
- break;
-
- // r=1, c=0
- /* 04 08 12
- 06 10 14
- 07 11 15 */
- case 4:
- result = - m[4 ] * (m[10] * m[15] - m[14] * m[11])
- + m[8 ] * (m[6 ] * m[15] - m[14] * m[7 ])
- - m[12] * (m[6 ] * m[11] - m[10] * m[7 ]);
- break;
-
- // r=1, c=1
- /* 00 08 12
- 02 10 14
- 03 11 15 */
- case 5:
- result = + m[0 ] * (m[10] * m[15] - m[14] * m[11])
- - m[8 ] * (m[2 ] * m[15] - m[14] * m[3 ])
- + m[12] * (m[2 ] * m[11] - m[10] * m[3 ]);
- break;
-
- // r=1, c=2
- /* 00 04 12
- 02 06 14
- 03 07 15 */
- case 6:
- result = - m[0 ] * (m[6 ] * m[15] - m[14] * m[7 ])
- + m[4 ] * (m[2 ] * m[15] - m[14] * m[3 ])
- - m[12] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]);
- break;
-
- // r=1, c=3
- /* 00 04 08
- 02 06 10
- 03 07 11 */
- case 7:
- result = + m[0 ] * (m[6 ] * m[11] - m[10] * m[7 ])
- - m[4 ] * (m[2 ] * m[11] - m[10] * m[3 ])
- + m[8 ] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]);
- break;
-
- // r=2, c=0
- /* 04 08 12
- 05 09 13
- 07 11 15 */
- case 8:
- result = + m[4 ] * (m[9 ] * m[15] - m[13] * m[11])
- - m[8 ] * (m[5 ] * m[15] - m[13] * m[7 ])
- + m[12] * (m[5 ] * m[11] - m[9 ] * m[7 ]);
- break;
-
- // r=2, c=1
- /* 00 08 12
- 01 09 13
- 03 11 15 */
- case 9:
- result = - m[0 ] * (m[9 ] * m[15] - m[13] * m[11])
- + m[8 ] * (m[1 ] * m[15] - m[13] * m[3 ])
- - m[12] * (m[1 ] * m[11] - m[9 ] * m[3 ]);
- break;
-
- // r=2, c=2
- /* 00 04 12
- 01 05 13
- 03 07 15 */
- case 10:
- result = + m[0 ] * (m[5 ] * m[15] - m[13] * m[7 ])
- - m[4 ] * (m[1 ] * m[15] - m[13] * m[3 ])
- + m[12] * (m[1 ] * m[7 ] - m[5 ] * m[3 ]);
- break;
-
- // r=2, c=3
- /* 00 04 08
- 01 05 09
- 03 07 11 */
- case 11:
- result = - m[0 ] * (m[5 ] * m[11] - m[9 ] * m[7 ])
- + m[4 ] * (m[1 ] * m[11] - m[9 ] * m[3 ])
- - m[8 ] * (m[1 ] * m[7 ] - m[5 ] * m[3 ]);
- break;
-
- // r=3, c=0
- /* 04 08 12
- 05 09 13
- 06 10 14 */
- case 12:
- result = - m[4 ] * (m[9 ] * m[14] - m[13] * m[10])
- + m[8 ] * (m[5 ] * m[14] - m[13] * m[6 ])
- - m[12] * (m[5 ] * m[10] - m[9 ] * m[6 ]);
- break;
-
- // r=3, c=1
- /* 00 08 12
- 01 09 13
- 02 10 14 */
- case 13:
- result = + m[0 ] * (m[9 ] * m[14] - m[13] * m[10])
- - m[8 ] * (m[1 ] * m[14] - m[13] * m[2 ])
- + m[12] * (m[1 ] * m[10] - m[9 ] * m[2 ]);
- break;
-
- // r=3, c=2
- /* 00 04 12
- 01 05 13
- 02 06 14 */
- case 14:
- result = - m[0 ] * (m[5 ] * m[14] - m[13] * m[6 ])
- + m[4 ] * (m[1 ] * m[14] - m[13] * m[2 ])
- - m[12] * (m[1 ] * m[6 ] - m[5 ] * m[2 ]);
- break;
-
- // r=3, c=3
- /* 00 04 08
- 01 05 09
- 02 06 10 */
- case 15:
- result = + m[0 ] * (m[5 ] * m[10] - m[9 ] * m[6 ])
- - m[4 ] * (m[1 ] * m[10] - m[9 ] * m[2 ])
- + m[8 ] * (m[1 ] * m[6 ] - m[5 ] * m[2 ]);
- break;
-
- default:
- break;
+ /* (2,1) <-> (1,2) */ Swap(m[1 ], m[4 ]);
+ /* (3,1) <-> (1,3) */ Swap(m[2 ], m[8 ]);
+ /* (4,1) <-> (1,4) */ Swap(m[3 ], m[12]);
+ /* (3,2) <-> (2,3) */ Swap(m[6 ], m[9 ]);
+ /* (4,2) <-> (2,4) */ Swap(m[7 ], m[13]);
+ /* (4,3) <-> (3,4) */ Swap(m[11], m[14]);
}
- return result;
- }
+ //! Calculates the determinant of the matrix
+ /** \returns the determinant */
+ inline float Det() const
+ {
+ float result = 0.0f;
+ for (int i = 0; i < 4; ++i)
+ {
+ result += m[i] * Cofactor(i, 0);
+ }
+ return result;
+ }
- //! Calculates the inverse matrix
- /** The determinant of the matrix must not be zero.
- \returns the inverted matrix */
- inline Matrix Inverse() const
- {
- float d = Det();
- assert(! IsZero(d));
+ //! Calculates the cofactor of the matrix
+ /** \a r row (0 to 3)
+ \a c column (0 to 3)
+ \returns the cofactor */
+ inline float Cofactor(int r, int c) const
+ {
+ assert(r >= 0 && r <= 3);
+ assert(c >= 0 && c <= 3);
- float result[16] = { 0.0f };
+ float result = 0.0f;
- for (int r = 0; r < 4; ++r)
- {
- for (int c = 0; c < 4; ++c)
- {
- // Already transposed!
- result[4*r+c] = (1.0f / d) * Cofactor(r, c);
- }
- }
+ /* That looks horrible, I know. But it's fast :) */
- return Matrix(result);
- }
+ switch (4*r + c)
+ {
+ // r=0, c=0
+ /* 05 09 13
+ 06 10 14
+ 07 11 15 */
+ case 0:
+ result = + m[5 ] * (m[10] * m[15] - m[14] * m[11])
+ - m[9 ] * (m[6 ] * m[15] - m[14] * m[7 ])
+ + m[13] * (m[6 ] * m[11] - m[10] * m[7 ]);
+ break;
+
+ // r=0, c=1
+ /* 01 09 13
+ 02 10 14
+ 03 11 15 */
+ case 1:
+ result = - m[1 ] * (m[10] * m[15] - m[14] * m[11])
+ + m[9 ] * (m[2 ] * m[15] - m[14] * m[3 ])
+ - m[13] * (m[2 ] * m[11] - m[10] * m[3 ]);
+ break;
+
+ // r=0, c=2
+ /* 01 05 13
+ 02 06 14
+ 03 07 15 */
+ case 2:
+ result = + m[1 ] * (m[6 ] * m[15] - m[14] * m[7 ])
+ - m[5 ] * (m[2 ] * m[15] - m[14] * m[3 ])
+ + m[13] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]);
+ break;
+
+ // r=0, c=3
+ /* 01 05 09
+ 02 06 10
+ 03 07 11 */
+ case 3:
+ result = - m[1 ] * (m[6 ] * m[11] - m[10] * m[7 ])
+ + m[5 ] * (m[2 ] * m[11] - m[10] * m[3 ])
+ - m[9 ] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]);
+ break;
+
+ // r=1, c=0
+ /* 04 08 12
+ 06 10 14
+ 07 11 15 */
+ case 4:
+ result = - m[4 ] * (m[10] * m[15] - m[14] * m[11])
+ + m[8 ] * (m[6 ] * m[15] - m[14] * m[7 ])
+ - m[12] * (m[6 ] * m[11] - m[10] * m[7 ]);
+ break;
+
+ // r=1, c=1
+ /* 00 08 12
+ 02 10 14
+ 03 11 15 */
+ case 5:
+ result = + m[0 ] * (m[10] * m[15] - m[14] * m[11])
+ - m[8 ] * (m[2 ] * m[15] - m[14] * m[3 ])
+ + m[12] * (m[2 ] * m[11] - m[10] * m[3 ]);
+ break;
+
+ // r=1, c=2
+ /* 00 04 12
+ 02 06 14
+ 03 07 15 */
+ case 6:
+ result = - m[0 ] * (m[6 ] * m[15] - m[14] * m[7 ])
+ + m[4 ] * (m[2 ] * m[15] - m[14] * m[3 ])
+ - m[12] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]);
+ break;
+
+ // r=1, c=3
+ /* 00 04 08
+ 02 06 10
+ 03 07 11 */
+ case 7:
+ result = + m[0 ] * (m[6 ] * m[11] - m[10] * m[7 ])
+ - m[4 ] * (m[2 ] * m[11] - m[10] * m[3 ])
+ + m[8 ] * (m[2 ] * m[7 ] - m[6 ] * m[3 ]);
+ break;
+
+ // r=2, c=0
+ /* 04 08 12
+ 05 09 13
+ 07 11 15 */
+ case 8:
+ result = + m[4 ] * (m[9 ] * m[15] - m[13] * m[11])
+ - m[8 ] * (m[5 ] * m[15] - m[13] * m[7 ])
+ + m[12] * (m[5 ] * m[11] - m[9 ] * m[7 ]);
+ break;
+
+ // r=2, c=1
+ /* 00 08 12
+ 01 09 13
+ 03 11 15 */
+ case 9:
+ result = - m[0 ] * (m[9 ] * m[15] - m[13] * m[11])
+ + m[8 ] * (m[1 ] * m[15] - m[13] * m[3 ])
+ - m[12] * (m[1 ] * m[11] - m[9 ] * m[3 ]);
+ break;
+
+ // r=2, c=2
+ /* 00 04 12
+ 01 05 13
+ 03 07 15 */
+ case 10:
+ result = + m[0 ] * (m[5 ] * m[15] - m[13] * m[7 ])
+ - m[4 ] * (m[1 ] * m[15] - m[13] * m[3 ])
+ + m[12] * (m[1 ] * m[7 ] - m[5 ] * m[3 ]);
+ break;
+
+ // r=2, c=3
+ /* 00 04 08
+ 01 05 09
+ 03 07 11 */
+ case 11:
+ result = - m[0 ] * (m[5 ] * m[11] - m[9 ] * m[7 ])
+ + m[4 ] * (m[1 ] * m[11] - m[9 ] * m[3 ])
+ - m[8 ] * (m[1 ] * m[7 ] - m[5 ] * m[3 ]);
+ break;
+
+ // r=3, c=0
+ /* 04 08 12
+ 05 09 13
+ 06 10 14 */
+ case 12:
+ result = - m[4 ] * (m[9 ] * m[14] - m[13] * m[10])
+ + m[8 ] * (m[5 ] * m[14] - m[13] * m[6 ])
+ - m[12] * (m[5 ] * m[10] - m[9 ] * m[6 ]);
+ break;
+
+ // r=3, c=1
+ /* 00 08 12
+ 01 09 13
+ 02 10 14 */
+ case 13:
+ result = + m[0 ] * (m[9 ] * m[14] - m[13] * m[10])
+ - m[8 ] * (m[1 ] * m[14] - m[13] * m[2 ])
+ + m[12] * (m[1 ] * m[10] - m[9 ] * m[2 ]);
+ break;
+
+ // r=3, c=2
+ /* 00 04 12
+ 01 05 13
+ 02 06 14 */
+ case 14:
+ result = - m[0 ] * (m[5 ] * m[14] - m[13] * m[6 ])
+ + m[4 ] * (m[1 ] * m[14] - m[13] * m[2 ])
+ - m[12] * (m[1 ] * m[6 ] - m[5 ] * m[2 ]);
+ break;
+
+ // r=3, c=3
+ /* 00 04 08
+ 01 05 09
+ 02 06 10 */
+ case 15:
+ result = + m[0 ] * (m[5 ] * m[10] - m[9 ] * m[6 ])
+ - m[4 ] * (m[1 ] * m[10] - m[9 ] * m[2 ])
+ + m[8 ] * (m[1 ] * m[6 ] - m[5 ] * m[2 ]);
+ break;
+
+ default:
+ break;
+ }
- //! Calculates the multiplication of this matrix * given matrix
- /** \a right right-hand matrix
- \returns multiplication result */
- inline Matrix Multiply(const Matrix &right) const
- {
- float result[16] = { 0.0f };
+ return result;
+ }
- for (int c = 0; c < 4; ++c)
+ //! Calculates the inverse matrix
+ /** The determinant of the matrix must not be zero.
+ \returns the inverted matrix */
+ inline Matrix Inverse() const
{
- for (int r = 0; r < 4; ++r)
- {
- result[4*c+r] = 0.0f;
- for (int i = 0; i < 4; ++i)
+ float d = Det();
+ assert(! IsZero(d));
+
+ float result[16] = { 0.0f };
+
+ for (int r = 0; r < 4; ++r)
{
- result[4*c+r] += m[4*i+r] * right.m[4*c+i];
+ for (int c = 0; c < 4; ++c)
+ {
+ // Already transposed!
+ result[4*r+c] = (1.0f / d) * Cofactor(r, c);
+ }
}
- }
+
+ return Matrix(result);
}
- return Matrix(result);
- }
+ //! Calculates the multiplication of this matrix * given matrix
+ /** \a right right-hand matrix
+ \returns multiplication result */
+ inline Matrix Multiply(const Matrix &right) const
+ {
+ float result[16] = { 0.0f };
+
+ for (int c = 0; c < 4; ++c)
+ {
+ for (int r = 0; r < 4; ++r)
+ {
+ result[4*c+r] = 0.0f;
+ for (int i = 0; i < 4; ++i)
+ {
+ result[4*c+r] += m[4*i+r] * right.m[4*c+i];
+ }
+ }
+ }
+
+ return Matrix(result);
+ }
}; // struct Matrix
//! Checks if two matrices are equal within given \a tolerance
inline bool MatricesEqual(const Matrix &m1, const Matrix &m2,
- float tolerance = TOLERANCE)
+ float tolerance = TOLERANCE)
{
- for (int i = 0; i < 16; ++i)
- {
- if (! IsEqual(m1.m[i], m2.m[i], tolerance))
- return false;
- }
+ for (int i = 0; i < 16; ++i)
+ {
+ if (! IsEqual(m1.m[i], m2.m[i], tolerance))
+ return false;
+ }
- return true;
+ return true;
}
//! Convenience function for getting transposed matrix
inline Matrix Transpose(const Matrix &m)
{
- Matrix result = m;
- result.Transpose();
- return result;
+ Matrix result = m;
+ result.Transpose();
+ return result;
}
//! Convenience function for multiplying a matrix
@@ -395,7 +395,7 @@ inline Matrix Transpose(const Matrix &m)
\returns multiplied matrices */
inline Matrix MultiplyMatrices(const Matrix &left, const Matrix &right)
{
- return left.Multiply(right);
+ return left.Multiply(right);
}
//! Calculates the result of multiplying m * v
@@ -405,27 +405,27 @@ inline Matrix MultiplyMatrices(const Matrix &left, const Matrix &right)
[ m.m[2 ] m.m[6 ] m.m[10] m.m[14] ] * [ v.z ]
[ m.m[3 ] m.m[7 ] m.m[11] m.m[15] ] [ 1 ] \endverbatim
- The result, a 4x1 vector is then converted to 3x1 by dividing
- x,y,z coords by the fourth coord (w). */
+ The result, a 4x1 vector is then converted to 3x1 by dividing
+ x,y,z coords by the fourth coord (w). */
inline Vector MatrixVectorMultiply(const Matrix &m, const Vector &v, bool wDivide = false)
{
- float x = v.x * m.m[0 ] + v.y * m.m[4 ] + v.z * m.m[8 ] + m.m[12];
- float y = v.x * m.m[1 ] + v.y * m.m[5 ] + v.z * m.m[9 ] + m.m[13];
- float z = v.x * m.m[2 ] + v.y * m.m[6 ] + v.z * m.m[10] + m.m[14];
+ float x = v.x * m.m[0 ] + v.y * m.m[4 ] + v.z * m.m[8 ] + m.m[12];
+ float y = v.x * m.m[1 ] + v.y * m.m[5 ] + v.z * m.m[9 ] + m.m[13];
+ float z = v.x * m.m[2 ] + v.y * m.m[6 ] + v.z * m.m[10] + m.m[14];
- if (!wDivide)
- return Vector(x, y, z);
+ if (!wDivide)
+ return Vector(x, y, z);
- float w = v.x * m.m[3 ] + v.y * m.m[7 ] + v.z * m.m[11] + m.m[15];
+ float w = v.x * m.m[3 ] + v.y * m.m[7 ] + v.z * m.m[11] + m.m[15];
- if (IsZero(w))
- return Vector(x, y, z);
+ if (IsZero(w))
+ return Vector(x, y, z);
- x /= w;
- y /= w;
- z /= w;
+ x /= w;
+ y /= w;
+ z /= w;
- return Vector(x, y, z);
+ return Vector(x, y, z);
}
/* @} */ // end of group
diff --git a/src/math/point.h b/src/math/point.h
index fdb3051..84be190 100644
--- a/src/math/point.h
+++ b/src/math/point.h
@@ -12,10 +12,10 @@
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
+// * along with this program. If not, see http://www.gnu.org/licenses/.
/** @defgroup MathPointModule math/point.h
- Contains the Point struct and related functions.
+ Contains the Point struct and related functions.
*/
#pragma once
@@ -35,111 +35,111 @@ namespace Math
/** \struct Point math/point.h
\brief 2D point
- Represents a 2D point (x, y).
- Contains the required methods for operating on points.
+ Represents a 2D point (x, y).
+ Contains the required methods for operating on points.
- All methods are made inline to maximize optimization.
+ All methods are made inline to maximize optimization.
*/
struct Point
{
- //! X coord
- float x;
- //! Y coord
- float y;
-
- //! Constructs a zero point: (0,0)
- inline Point()
- {
- LoadZero();
- }
-
- //! Constructs a point from given coords: (x,y)
- inline explicit Point(float x, float y)
- {
- this->x = x;
- this->y = y;
- }
-
- //! Sets the zero point: (0,0)
- inline void LoadZero()
- {
- x = y = 0.0f;
- }
-
- //! Returns the distance from (0,0) to the point (x,y)
- inline float Length()
- {
- return sqrtf(x*x + y*y);
- }
-
- //! Returns the inverted point
- inline Point operator-() const
- {
- return Point(-x, -y);
- }
-
- //! Adds the given point
- inline const Point& operator+=(const Point &right)
- {
- x += right.x;
- y += right.y;
- return *this;
- }
-
- //! Adds two points
- inline friend const Point operator+(const Point &left, const Point &right)
- {
- return Point(left.x + right.x, left.y + right.y);
- }
-
- //! Subtracts the given vector
- inline const Point& operator-=(const Point &right)
- {
- x -= right.x;
- y -= right.y;
- return *this;
- }
-
- //! Subtracts two points
- inline friend const Point operator-(const Point &left, const Point &right)
- {
- return Point(left.x - right.x, left.y - right.y);
- }
-
- //! Multiplies by given scalar
- inline const Point& operator*=(const float &right)
- {
- x *= right;
- y *= right;
- return *this;
- }
-
- //! Multiplies point by scalar
- inline friend const Point operator*(const float &left, const Point &right)
- {
- return Point(left * right.x, left * right.y);
- }
-
- //! Multiplies point by scalar
- inline friend const Point operator*(const Point &left, const float &right)
- {
- return Point(left.x * right, left.y * right);
- }
-
- //! Divides by given scalar
- inline const Point& operator/=(const float &right)
- {
- x /= right;
- y /= right;
- return *this;
- }
-
- //! Divides point by scalar
- inline friend const Point operator/(const Point &left, const float &right)
- {
- return Point(left.x / right, left.y / right);
- }
+ //! X coord
+ float x;
+ //! Y coord
+ float y;
+
+ //! Constructs a zero point: (0,0)
+ inline Point()
+ {
+ LoadZero();
+ }
+
+ //! Constructs a point from given coords: (x,y)
+ inline explicit Point(float x, float y)
+ {
+ this->x = x;
+ this->y = y;
+ }
+
+ //! Sets the zero point: (0,0)
+ inline void LoadZero()
+ {
+ x = y = 0.0f;
+ }
+
+ //! Returns the distance from (0,0) to the point (x,y)
+ inline float Length()
+ {
+ return sqrtf(x*x + y*y);
+ }
+
+ //! Returns the inverted point
+ inline Point operator-() const
+ {
+ return Point(-x, -y);
+ }
+
+ //! Adds the given point
+ inline const Point& operator+=(const Point &right)
+ {
+ x += right.x;
+ y += right.y;
+ return *this;
+ }
+
+ //! Adds two points
+ inline friend const Point operator+(const Point &left, const Point &right)
+ {
+ return Point(left.x + right.x, left.y + right.y);
+ }
+
+ //! Subtracts the given vector
+ inline const Point& operator-=(const Point &right)
+ {
+ x -= right.x;
+ y -= right.y;
+ return *this;
+ }
+
+ //! Subtracts two points
+ inline friend const Point operator-(const Point &left, const Point &right)
+ {
+ return Point(left.x - right.x, left.y - right.y);
+ }
+
+ //! Multiplies by given scalar
+ inline const Point& operator*=(const float &right)
+ {
+ x *= right;
+ y *= right;
+ return *this;
+ }
+
+ //! Multiplies point by scalar
+ inline friend const Point operator*(const float &left, const Point &right)
+ {
+ return Point(left * right.x, left * right.y);
+ }
+
+ //! Multiplies point by scalar
+ inline friend const Point operator*(const Point &left, const float &right)
+ {
+ return Point(left.x * right, left.y * right);
+ }
+
+ //! Divides by given scalar
+ inline const Point& operator/=(const float &right)
+ {
+ x /= right;
+ y /= right;
+ return *this;
+ }
+
+ //! Divides point by scalar
+ inline friend const Point operator/(const Point &left, const float &right)
+ {
+ return Point(left.x / right, left.y / right);
+ }
}; // struct Point
@@ -147,23 +147,23 @@ struct Point
//! Checks if two vectors are equal within given \a tolerance
inline bool PointsEqual(const Point &a, const Point &b, float tolerance = TOLERANCE)
{
- return IsEqual(a.x, b.x, tolerance) && IsEqual(a.y, b.y, tolerance);
+ return IsEqual(a.x, b.x, tolerance) && IsEqual(a.y, b.y, tolerance);
}
//! Permutes two points
inline void Swap(Point &a, Point &b)
{
- Point c;
+ Point c;
- c = a;
- a = b;
- b = c;
+ c = a;
+ a = b;
+ b = c;
}
//! Returns the distance between two points
inline float Distance(const Point &a, const Point &b)
{
- return sqrtf((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
+ return sqrtf((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
}
/* @} */ // end of group
diff --git a/src/math/test/geometry_test.cpp b/src/math/test/geometry_test.cpp
index d6dbd9b..07fa2cf 100644
--- a/src/math/test/geometry_test.cpp
+++ b/src/math/test/geometry_test.cpp
@@ -35,367 +35,367 @@ const float TEST_TOLERANCE = 1e-5;
// Test for rewritten function RotateAngle()
int TestRotateAngle()
{
- if (! Math::IsEqual(Math::RotateAngle(0.0f, 0.0f), 0.0f, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::IsEqual(Math::RotateAngle(0.0f, 0.0f), 0.0f, TEST_TOLERANCE))
+ return __LINE__;
- if (! Math::IsEqual(Math::RotateAngle(1.0f, 0.0f), 0.0f, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::IsEqual(Math::RotateAngle(1.0f, 0.0f), 0.0f, TEST_TOLERANCE))
+ return __LINE__;
- if (! Math::IsEqual(Math::RotateAngle(1.0f, 1.0f), 0.25f * Math::PI, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::IsEqual(Math::RotateAngle(1.0f, 1.0f), 0.25f * Math::PI, TEST_TOLERANCE))
+ return __LINE__;
- if (! Math::IsEqual(Math::RotateAngle(0.0f, 2.0f), 0.5f * Math::PI, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::IsEqual(Math::RotateAngle(0.0f, 2.0f), 0.5f * Math::PI, TEST_TOLERANCE))
+ return __LINE__;
- if (! Math::IsEqual(Math::RotateAngle(-0.5f, 0.5f), 0.75f * Math::PI, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::IsEqual(Math::RotateAngle(-0.5f, 0.5f), 0.75f * Math::PI, TEST_TOLERANCE))
+ return __LINE__;
- if (! Math::IsEqual(Math::RotateAngle(-1.0f, 0.0f), Math::PI, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::IsEqual(Math::RotateAngle(-1.0f, 0.0f), Math::PI, TEST_TOLERANCE))
+ return __LINE__;
- if (! Math::IsEqual(Math::RotateAngle(-1.0f, -1.0f), 1.25f * Math::PI, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::IsEqual(Math::RotateAngle(-1.0f, -1.0f), 1.25f * Math::PI, TEST_TOLERANCE))
+ return __LINE__;
- if (! Math::IsEqual(Math::RotateAngle(0.0f, -2.0f), 1.5f * Math::PI, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::IsEqual(Math::RotateAngle(0.0f, -2.0f), 1.5f * Math::PI, TEST_TOLERANCE))
+ return __LINE__;
- if (! Math::IsEqual(Math::RotateAngle(1.0f, -1.0f), 1.75f * Math::PI, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::IsEqual(Math::RotateAngle(1.0f, -1.0f), 1.75f * Math::PI, TEST_TOLERANCE))
+ return __LINE__;
- return 0;
+ return 0;
}
// Tests for other altered, complex or uncertain functions
int TestAngle()
{
- const Math::Vector u(-0.0786076246943884, 0.2231249091714256, -1.1601361718477805);
- const Math::Vector v(-1.231228742001907, -1.720549809950561, -0.690468438834111);
+ const Math::Vector u(-0.0786076246943884, 0.2231249091714256, -1.1601361718477805);
+ const Math::Vector v(-1.231228742001907, -1.720549809950561, -0.690468438834111);
- float mathResult = Math::Angle(u, v);
- float oldMathResult = Angle(VEC_TO_D3DVEC(u), VEC_TO_D3DVEC(v));
+ float mathResult = Math::Angle(u, v);
+ float oldMathResult = Angle(VEC_TO_D3DVEC(u), VEC_TO_D3DVEC(v));
- if (! Math::IsEqual(mathResult, oldMathResult, TEST_TOLERANCE) )
- return __LINE__;
+ if (! Math::IsEqual(mathResult, oldMathResult, TEST_TOLERANCE) )
+ return __LINE__;
- return 0;
+ return 0;
}
int TestRotateView()
{
- const Math::Vector center(0.617909142705555, 0.896939729454538, -0.615041943652284);
- const float angleH = 44.5;
- const float angleV = 12.3;
- const float dist = 34.76;
+ const Math::Vector center(0.617909142705555, 0.896939729454538, -0.615041943652284);
+ const float angleH = 44.5;
+ const float angleV = 12.3;
+ const float dist = 34.76;
- Math::Vector mathResult = Math::RotateView(center, angleH, angleV, dist);
- Math::Vector oldMathResult = D3DVEC_TO_VEC(RotateView(VEC_TO_D3DVEC(center), angleH, angleV, dist));
+ Math::Vector mathResult = Math::RotateView(center, angleH, angleV, dist);
+ Math::Vector oldMathResult = D3DVEC_TO_VEC(RotateView(VEC_TO_D3DVEC(center), angleH, angleV, dist));
- if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE))
+ return __LINE__;
- return 0;
+ return 0;
}
int TestLookatPoint()
{
- const Math::Vector eye(-2.451183170579471, 0.241270270546559, -0.490677411454893);
- const float angleH = 48.4;
- const float angleV = 32.4;
- const float length = 74.44;
+ const Math::Vector eye(-2.451183170579471, 0.241270270546559, -0.490677411454893);
+ const float angleH = 48.4;
+ const float angleV = 32.4;
+ const float length = 74.44;
- Math::Vector mathResult = Math::LookatPoint(eye, angleH, angleV, length);
- Math::Vector oldMathResult = D3DVEC_TO_VEC(LookatPoint(VEC_TO_D3DVEC(eye), angleH, angleV, length));
+ Math::Vector mathResult = Math::LookatPoint(eye, angleH, angleV, length);
+ Math::Vector oldMathResult = D3DVEC_TO_VEC(LookatPoint(VEC_TO_D3DVEC(eye), angleH, angleV, length));
- if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE))
+ return __LINE__;
- return 0;
+ return 0;
}
int TestProjection()
{
- const Math::Vector a(0.852064846846319, -0.794279497087496, -0.655779805476688);
- const Math::Vector b(-0.245838834102304, -0.841115596038861, 0.470457161487799);
- const Math::Vector p(2.289326061164255, -0.505511362271196, 0.660204551169491);
+ const Math::Vector a(0.852064846846319, -0.794279497087496, -0.655779805476688);
+ const Math::Vector b(-0.245838834102304, -0.841115596038861, 0.470457161487799);
+ const Math::Vector p(2.289326061164255, -0.505511362271196, 0.660204551169491);
- Math::Vector mathResult = Math::Projection(a, b, p);
- Math::Vector oldMathResult = D3DVEC_TO_VEC(Projection(VEC_TO_D3DVEC(a), VEC_TO_D3DVEC(b), VEC_TO_D3DVEC(p)));
+ Math::Vector mathResult = Math::Projection(a, b, p);
+ Math::Vector oldMathResult = D3DVEC_TO_VEC(Projection(VEC_TO_D3DVEC(a), VEC_TO_D3DVEC(b), VEC_TO_D3DVEC(p)));
- if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE))
+ return __LINE__;
- return 0;
+ return 0;
}
int TestLoadViewMatrix()
{
- const Math::Vector from(2.5646013154868874, -0.6058794133917031, -0.0441195127419744);
- const Math::Vector at(0.728044925765569, -0.206343977871841, 2.543158236935463);
- const Math::Vector worldUp(-1.893738133660711, -1.009584441407070, 0.521745988225582);
-
- Math::Matrix mathResult;
- Math::LoadViewMatrix(mathResult, from, at, worldUp);
-
- Math::Matrix oldMathResult;
- {
- D3DMATRIX mat;
- D3DVECTOR fromD3D = VEC_TO_D3DVEC(from);
- D3DVECTOR atD3D = VEC_TO_D3DVEC(at);
- D3DVECTOR worldUpD3D = VEC_TO_D3DVEC(worldUp);
- D3DUtil_SetViewMatrix(mat, fromD3D, atD3D, worldUpD3D);
- oldMathResult = D3DMAT_TO_MAT(mat);
- }
-
- if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
- return __LINE__;
-
- return 0;
+ const Math::Vector from(2.5646013154868874, -0.6058794133917031, -0.0441195127419744);
+ const Math::Vector at(0.728044925765569, -0.206343977871841, 2.543158236935463);
+ const Math::Vector worldUp(-1.893738133660711, -1.009584441407070, 0.521745988225582);
+
+ Math::Matrix mathResult;
+ Math::LoadViewMatrix(mathResult, from, at, worldUp);
+
+ Math::Matrix oldMathResult;
+ {
+ D3DMATRIX mat;
+ D3DVECTOR fromD3D = VEC_TO_D3DVEC(from);
+ D3DVECTOR atD3D = VEC_TO_D3DVEC(at);
+ D3DVECTOR worldUpD3D = VEC_TO_D3DVEC(worldUp);
+ D3DUtil_SetViewMatrix(mat, fromD3D, atD3D, worldUpD3D);
+ oldMathResult = D3DMAT_TO_MAT(mat);
+ }
+
+ if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
+ return __LINE__;
+
+ return 0;
}
int TestLoadProjectionMatrix()
{
- const float fov = 76.3f;
- const float aspect = 0.891f;
- const float nearPlane = 12.3f;
- const float farPlane = 1238.9f;
+ const float fov = 76.3f;
+ const float aspect = 0.891f;
+ const float nearPlane = 12.3f;
+ const float farPlane = 1238.9f;
- Math::Matrix mathResult;
- Math::LoadProjectionMatrix(mathResult, fov, aspect, nearPlane, farPlane);
+ Math::Matrix mathResult;
+ Math::LoadProjectionMatrix(mathResult, fov, aspect, nearPlane, farPlane);
- Math::Matrix oldMathResult;
- {
- D3DMATRIX mat;
- D3DUtil_SetProjectionMatrix(mat, fov, aspect, nearPlane, farPlane);
- oldMathResult = D3DMAT_TO_MAT(mat);
- }
+ Math::Matrix oldMathResult;
+ {
+ D3DMATRIX mat;
+ D3DUtil_SetProjectionMatrix(mat, fov, aspect, nearPlane, farPlane);
+ oldMathResult = D3DMAT_TO_MAT(mat);
+ }
- if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
+ return __LINE__;
- return 0;
+ return 0;
}
int TestLoadTranslationMatrix()
{
- const Math::Vector translation(-0.3631590720995237, 1.6976327614875211, 0.0148815191502145);
+ const Math::Vector translation(-0.3631590720995237, 1.6976327614875211, 0.0148815191502145);
- Math::Matrix mathResult;
- Math::LoadTranslationMatrix(mathResult, translation);
+ Math::Matrix mathResult;
+ Math::LoadTranslationMatrix(mathResult, translation);
- Math::Matrix oldMathResult;
- {
- D3DMATRIX mat;
- D3DUtil_SetTranslateMatrix(mat, translation.x, translation.y, translation.z);
- oldMathResult = D3DMAT_TO_MAT(mat);
- }
+ Math::Matrix oldMathResult;
+ {
+ D3DMATRIX mat;
+ D3DUtil_SetTranslateMatrix(mat, translation.x, translation.y, translation.z);
+ oldMathResult = D3DMAT_TO_MAT(mat);
+ }
- if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
+ return __LINE__;
- return 0;
+ return 0;
}
int TestLoadScaleMatrix()
{
- const Math::Vector scale(0.612236460285503, -0.635566935025364, -0.254321375332065);
+ const Math::Vector scale(0.612236460285503, -0.635566935025364, -0.254321375332065);
- Math::Matrix mathResult;
- Math::LoadScaleMatrix(mathResult, scale);
+ Math::Matrix mathResult;
+ Math::LoadScaleMatrix(mathResult, scale);
- Math::Matrix oldMathResult;
- {
- D3DMATRIX mat;
- D3DUtil_SetScaleMatrix(mat, scale.x, scale.y, scale.z);
- oldMathResult = D3DMAT_TO_MAT(mat);
- }
+ Math::Matrix oldMathResult;
+ {
+ D3DMATRIX mat;
+ D3DUtil_SetScaleMatrix(mat, scale.x, scale.y, scale.z);
+ oldMathResult = D3DMAT_TO_MAT(mat);
+ }
- if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
+ return __LINE__;
- return 0;
+ return 0;
}
int TestLoadRotationXMatrix()
{
- const float angle = 0.513790685774275;
+ const float angle = 0.513790685774275;
- Math::Matrix mathResult;
- Math::LoadRotationXMatrix(mathResult, angle);
+ Math::Matrix mathResult;
+ Math::LoadRotationXMatrix(mathResult, angle);
- Math::Matrix oldMathResult;
- {
- D3DMATRIX mat;
- D3DUtil_SetRotateXMatrix(mat, angle);
- oldMathResult = D3DMAT_TO_MAT(mat);
- }
+ Math::Matrix oldMathResult;
+ {
+ D3DMATRIX mat;
+ D3DUtil_SetRotateXMatrix(mat, angle);
+ oldMathResult = D3DMAT_TO_MAT(mat);
+ }
- if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
+ return __LINE__;
- return 0;
+ return 0;
}
int TestLoadRotationYMatrix()
{
- const float angle = -0.569166650127303;
+ const float angle = -0.569166650127303;
- Math::Matrix mathResult;
- Math::LoadRotationYMatrix(mathResult, angle);
+ Math::Matrix mathResult;
+ Math::LoadRotationYMatrix(mathResult, angle);
- Math::Matrix oldMathResult;
- {
- D3DMATRIX mat;
- D3DUtil_SetRotateYMatrix(mat, angle);
- oldMathResult = D3DMAT_TO_MAT(mat);
- }
+ Math::Matrix oldMathResult;
+ {
+ D3DMATRIX mat;
+ D3DUtil_SetRotateYMatrix(mat, angle);
+ oldMathResult = D3DMAT_TO_MAT(mat);
+ }
- if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
+ return __LINE__;
- return 0;
+ return 0;
}
int TestLoadRotationZMatrix()
{
- const float angle = 0.380448034347452;
+ const float angle = 0.380448034347452;
- Math::Matrix mathResult;
- Math::LoadRotationZMatrix(mathResult, angle);
+ Math::Matrix mathResult;
+ Math::LoadRotationZMatrix(mathResult, angle);
- Math::Matrix oldMathResult;
- {
- D3DMATRIX mat;
- D3DUtil_SetRotateZMatrix(mat, angle);
- oldMathResult = D3DMAT_TO_MAT(mat);
- }
+ Math::Matrix oldMathResult;
+ {
+ D3DMATRIX mat;
+ D3DUtil_SetRotateZMatrix(mat, angle);
+ oldMathResult = D3DMAT_TO_MAT(mat);
+ }
- if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
+ return __LINE__;
- return 0;
+ return 0;
}
int TestLoadRotationMatrix()
{
- const float angle = -0.987747190637790;
- const Math::Vector dir(-0.113024727688331, -0.781265998072571, 1.838972397076884);
+ const float angle = -0.987747190637790;
+ const Math::Vector dir(-0.113024727688331, -0.781265998072571, 1.838972397076884);
- Math::Matrix mathResult;
- Math::LoadRotationMatrix(mathResult, dir, angle);
+ Math::Matrix mathResult;
+ Math::LoadRotationMatrix(mathResult, dir, angle);
- Math::Matrix oldMathResult;
- {
- D3DMATRIX mat;
- D3DVECTOR dirD3D = VEC_TO_D3DVEC(dir);
- D3DUtil_SetRotationMatrix(mat, dirD3D, angle);
- oldMathResult = D3DMAT_TO_MAT(mat);
- }
+ Math::Matrix oldMathResult;
+ {
+ D3DMATRIX mat;
+ D3DVECTOR dirD3D = VEC_TO_D3DVEC(dir);
+ D3DUtil_SetRotationMatrix(mat, dirD3D, angle);
+ oldMathResult = D3DMAT_TO_MAT(mat);
+ }
- if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
+ return __LINE__;
- return 0;
+ return 0;
}
int TestLoadRotationXZYMatrix()
{
- const Math::Vector angles(-0.841366567984597, -0.100543315396357, 1.610647811559988);
+ const Math::Vector angles(-0.841366567984597, -0.100543315396357, 1.610647811559988);
- Math::Matrix mathResult;
- Math::LoadRotationXZYMatrix(mathResult, angles);
+ Math::Matrix mathResult;
+ Math::LoadRotationXZYMatrix(mathResult, angles);
- Math::Matrix oldMathResult;
- {
- D3DMATRIX mat;
- MatRotateXZY(mat, VEC_TO_D3DVEC(angles));
- oldMathResult = D3DMAT_TO_MAT(mat);
- }
+ Math::Matrix oldMathResult;
+ {
+ D3DMATRIX mat;
+ MatRotateXZY(mat, VEC_TO_D3DVEC(angles));
+ oldMathResult = D3DMAT_TO_MAT(mat);
+ }
- if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
+ return __LINE__;
- return 0;
+ return 0;
}
int TestLoadRotationZXYMatrix()
{
- const Math::Vector angles(0.275558495480206, -0.224328265970090, 0.943077216574253);
+ const Math::Vector angles(0.275558495480206, -0.224328265970090, 0.943077216574253);
- Math::Matrix mathResult;
- Math::LoadRotationZXYMatrix(mathResult, angles);
+ Math::Matrix mathResult;
+ Math::LoadRotationZXYMatrix(mathResult, angles);
- Math::Matrix oldMathResult;
- {
- D3DMATRIX mat;
- MatRotateZXY(mat, VEC_TO_D3DVEC(angles));
- oldMathResult = D3DMAT_TO_MAT(mat);
- }
+ Math::Matrix oldMathResult;
+ {
+ D3DMATRIX mat;
+ MatRotateZXY(mat, VEC_TO_D3DVEC(angles));
+ oldMathResult = D3DMAT_TO_MAT(mat);
+ }
- if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
- return __LINE__;
+ if (! Math::MatricesEqual(mathResult, oldMathResult, TEST_TOLERANCE))
+ return __LINE__;
- return 0;
+ return 0;
}
int TestTransform()
{
- Math::Matrix transformMatrix(
- (float[4][4])
- {
- { -0.9282074720977896, 0.6794734970319730, -1.3234304946882685, 0.0925294727863890 },
- { -0.0395527963683484, 0.2897634352353881, 1.9144398570315440, -1.4062267508968478 },
- { 0.9133323625282361, -0.6741836434774530, -0.2188812951424338, -1.0089184339952666 },
- { 0.0f, 0.0f, 0.0f, 1.0f }
- }
- );
- Math::Vector vector(-0.314596433318370, -0.622681232583150, -0.371307535743574);
-
- Math::Vector mathResult = Math::Transform(transformMatrix, vector);
- Math::Vector oldMathResult = Transform(transformMatrix, vector);
-
- if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE))
- return __LINE__;
-
- return 0;
+ Math::Matrix transformMatrix(
+ (float[4][4])
+ {
+ { -0.9282074720977896, 0.6794734970319730, -1.3234304946882685, 0.0925294727863890 },
+ { -0.0395527963683484, 0.2897634352353881, 1.9144398570315440, -1.4062267508968478 },
+ { 0.9133323625282361, -0.6741836434774530, -0.2188812951424338, -1.0089184339952666 },
+ { 0.0f, 0.0f, 0.0f, 1.0f }
+ }
+ );
+ Math::Vector vector(-0.314596433318370, -0.622681232583150, -0.371307535743574);
+
+ Math::Vector mathResult = Math::Transform(transformMatrix, vector);
+ Math::Vector oldMathResult = Transform(transformMatrix, vector);
+
+ if (! Math::VectorsEqual(mathResult, oldMathResult, TEST_TOLERANCE))
+ return __LINE__;
+
+ return 0;
}
int main()
{
- // Functions to test
- int (*TESTS[])() =
- {
- TestRotateAngle,
- TestAngle,
- TestRotateView,
- TestLookatPoint,
- TestProjection,
- TestLoadViewMatrix,
- TestLoadProjectionMatrix,
- TestLoadTranslationMatrix,
- TestLoadScaleMatrix,
- TestLoadRotationXMatrix,
- TestLoadRotationYMatrix,
- TestLoadRotationZMatrix,
- TestLoadRotationMatrix,
- TestLoadRotationXZYMatrix,
- TestLoadRotationZXYMatrix,
- TestTransform
- };
- const int TESTS_SIZE = sizeof(TESTS) / sizeof(*TESTS);
-
- int result = 0;
- for (int i = 0; i < TESTS_SIZE; ++i)
- {
- result = TESTS[i]();
- if (result != 0)
+ // Functions to test
+ int (*TESTS[])() =
+ {
+ TestRotateAngle,
+ TestAngle,
+ TestRotateView,
+ TestLookatPoint,
+ TestProjection,
+ TestLoadViewMatrix,
+ TestLoadProjectionMatrix,
+ TestLoadTranslationMatrix,
+ TestLoadScaleMatrix,
+ TestLoadRotationXMatrix,
+ TestLoadRotationYMatrix,
+ TestLoadRotationZMatrix,
+ TestLoadRotationMatrix,
+ TestLoadRotationXZYMatrix,
+ TestLoadRotationZXYMatrix,
+ TestTransform
+ };
+ const int TESTS_SIZE = sizeof(TESTS) / sizeof(*TESTS);
+
+ int result = 0;
+ for (int i = 0; i < TESTS_SIZE; ++i)
{
- fprintf(stderr, "Test function %d failed at line %d\n", i+1, result);
- return result;
+ result = TESTS[i]();
+ if (result != 0)
+ {
+ fprintf(stderr, "Test function %d failed at line %d\n", i+1, result);
+ return result;
+ }
}
- }
- fprintf(stderr, "All tests successful\n");
+ fprintf(stderr, "All tests successful\n");
- return 0;
+ return 0;
}
diff --git a/src/math/test/matrix_test.cpp b/src/math/test/matrix_test.cpp
index 95f1ed7..663234c 100644
--- a/src/math/test/matrix_test.cpp
+++ b/src/math/test/matrix_test.cpp
@@ -16,11 +16,11 @@
// math/test/matrix_test.cpp
-/* Unit tests for Matrix struct
-
- Test data was randomly generated and the expected results
- calculated using GNU Octave.
+/*
+ Unit tests for Matrix struct
+ Test data was randomly generated and the expected results
+ calculated using GNU Octave.
*/
#include "../func.h"
@@ -34,369 +34,369 @@ const float TEST_TOLERANCE = 1e-6;
int TestTranspose()
{
- const Math::Matrix mat(
- (float[4][4])
- {
- { -0.07011674491203920, 1.26145596067429810, 2.09476603598066902, 0.35560176915570696 },
- { -1.34075615966224704, 1.17988499016709314, 0.00601713429241016, -0.75213676977972566 },
- { 0.59186722295223981, 0.88089224074765293, 0.70994467464257294, 0.36730385425340212 },
- { -0.95649396555068111, 0.75912182022565566, 1.34883305778387186, -1.34957997578168754 }
- }
- );
-
- const Math::Matrix expectedTranspose(
- (float[4][4])
+ const Math::Matrix mat(
+ (float[4][4])
+ {
+ { -0.07011674491203920, 1.26145596067429810, 2.09476603598066902, 0.35560176915570696 },
+ { -1.34075615966224704, 1.17988499016709314, 0.00601713429241016, -0.75213676977972566 },
+ { 0.59186722295223981, 0.88089224074765293, 0.70994467464257294, 0.36730385425340212 },
+ { -0.95649396555068111, 0.75912182022565566, 1.34883305778387186, -1.34957997578168754 }
+ }
+ );
+
+ const Math::Matrix expectedTranspose(
+ (float[4][4])
+ {
+ { -0.07011674491203920, -1.34075615966224704, 0.59186722295223981, -0.95649396555068111 },
+ { 1.26145596067429810, 1.17988499016709314, 0.88089224074765293, 0.75912182022565566 },
+ { 2.09476603598066902, 0.00601713429241016, 0.70994467464257294, 1.34883305778387186 },
+ { 0.35560176915570696, -0.75213676977972566, 0.36730385425340212, -1.34957997578168754 }
+ }
+ );
+
+ Math::Matrix transpose = Math::Transpose(mat);
+
+ if (! Math::MatricesEqual(transpose, expectedTranspose, TEST_TOLERANCE))
{
- { -0.07011674491203920, -1.34075615966224704, 0.59186722295223981, -0.95649396555068111 },
- { 1.26145596067429810, 1.17988499016709314, 0.88089224074765293, 0.75912182022565566 },
- { 2.09476603598066902, 0.00601713429241016, 0.70994467464257294, 1.34883305778387186 },
- { 0.35560176915570696, -0.75213676977972566, 0.36730385425340212, -1.34957997578168754 }
+ fprintf(stderr, "Transpose mismatch!\n");
+ return __LINE__;
}
- );
-
- Math::Matrix transpose = Math::Transpose(mat);
- if (! Math::MatricesEqual(transpose, expectedTranspose, TEST_TOLERANCE))
- {
- fprintf(stderr, "Transpose mismatch!\n");
- return __LINE__;
- }
-
- return 0;
+ return 0;
}
int TestCofactor()
{
- const Math::Matrix mat1(
- (float[4][4])
- {
- { 0.610630320796245, 1.059932357918312, -1.581674311378210, 1.782214448453331 },
- { 0.191028848211526, -0.813898708757524, 1.516114203870644, 0.395202639476002 },
- { 0.335142750345279, -0.346586619596529, 0.545382042472336, -0.879268918923072 },
- { 1.417588151657198, 1.450841789070141, 0.219080104196171, 0.378724047481655 }
- }
- );
-
- const Math::Matrix expectedCofactors1(
- (float[4][4])
- {
- { -2.402679369186782, 2.282452509293019, 1.722732204057644, -0.746939701104385 },
- { -0.687677756877654, 1.168949180331164, -0.985354966837796, -1.334071111592705 },
- { -5.115621958424845, 4.229724770159009, 2.529000630782808, 1.481632618355891 },
- { 0.147480897398694, -2.140677680337111, -1.207189492265546, 0.151236920408051 }
- }
- );
-
- for (int r = 0; r < 4; ++r)
- {
- for (int c = 0; c < 4; ++c)
- {
- float ret = mat1.Cofactor(r, c);
- float exp = expectedCofactors1.m[4*c+r];
- if (! Math::IsEqual(ret, exp, TEST_TOLERANCE))
- {
- fprintf(stderr, "Cofactors 1 mismatch!\n");
- fprintf(stderr, "r=%d, c=%d, %f (returned) != %f (expected)\n", r, c, ret, exp);
- return __LINE__;
- }
- }
- }
-
- const Math::Matrix mat2(
- (float[4][4])
- {
- { 0.9845099464982393, -0.9091233416532389, -0.6272243714245945, 0.4645001858944354 },
- { -0.1333308471483736, 0.9128181433725897, -1.0937461393836190, 0.3180936795928376 },
- { -0.0654324396846289, 0.1014641705415945, 1.5107709042683430, -0.0240560430414690 },
- { 0.0179638644093347, -1.0695585982782767, -0.1741250853101032, 1.0803106709464336 }
- }
- );
-
- const Math::Matrix expectedCofactors2(
- (float[4][4])
+ const Math::Matrix mat1(
+ (float[4][4])
+ {
+ { 0.610630320796245, 1.059932357918312, -1.581674311378210, 1.782214448453331 },
+ { 0.191028848211526, -0.813898708757524, 1.516114203870644, 0.395202639476002 },
+ { 0.335142750345279, -0.346586619596529, 0.545382042472336, -0.879268918923072 },
+ { 1.417588151657198, 1.450841789070141, 0.219080104196171, 0.378724047481655 }
+ }
+ );
+
+ const Math::Matrix expectedCofactors1(
+ (float[4][4])
+ {
+ { -2.402679369186782, 2.282452509293019, 1.722732204057644, -0.746939701104385 },
+ { -0.687677756877654, 1.168949180331164, -0.985354966837796, -1.334071111592705 },
+ { -5.115621958424845, 4.229724770159009, 2.529000630782808, 1.481632618355891 },
+ { 0.147480897398694, -2.140677680337111, -1.207189492265546, 0.151236920408051 }
+ }
+ );
+
+ for (int r = 0; r < 4; ++r)
{
- { 2.0861102207614466, 0.2989010779528912, 0.0746276150537432, 0.2732659822656097 },
- { 0.6850002886584565, 1.5513169659641379, -0.0503743176545917, 1.5163672441575642 },
- { 1.2385556680997216, 1.1827709562505695, 1.2282813085138962, 1.3483789679871401 },
- { -1.0710790241539783, -0.5589604503588883, 0.0100959837872308, 1.1897872684455839 }
+ for (int c = 0; c < 4; ++c)
+ {
+ float ret = mat1.Cofactor(r, c);
+ float exp = expectedCofactors1.m[4*c+r];
+ if (! Math::IsEqual(ret, exp, TEST_TOLERANCE))
+ {
+ fprintf(stderr, "Cofactors 1 mismatch!\n");
+ fprintf(stderr, "r=%d, c=%d, %f (returned) != %f (expected)\n", r, c, ret, exp);
+ return __LINE__;
+ }
+ }
}
- );
-
- for (int r = 0; r < 4; ++r)
- {
- for (int c = 0; c < 4; ++c)
+ const Math::Matrix mat2(
+ (float[4][4])
+ {
+ { 0.9845099464982393, -0.9091233416532389, -0.6272243714245945, 0.4645001858944354 },
+ { -0.1333308471483736, 0.9128181433725897, -1.0937461393836190, 0.3180936795928376 },
+ { -0.0654324396846289, 0.1014641705415945, 1.5107709042683430, -0.0240560430414690 },
+ { 0.0179638644093347, -1.0695585982782767, -0.1741250853101032, 1.0803106709464336 }
+ }
+ );
+
+ const Math::Matrix expectedCofactors2(
+ (float[4][4])
+ {
+ { 2.0861102207614466, 0.2989010779528912, 0.0746276150537432, 0.2732659822656097 },
+ { 0.6850002886584565, 1.5513169659641379, -0.0503743176545917, 1.5163672441575642 },
+ { 1.2385556680997216, 1.1827709562505695, 1.2282813085138962, 1.3483789679871401 },
+ { -1.0710790241539783, -0.5589604503588883, 0.0100959837872308, 1.1897872684455839 }
+ }
+ );
+
+
+ for (int r = 0; r < 4; ++r)
{
- float ret = mat2.Cofactor(r, c);
- float exp = expectedCofactors2.m[4*c+r];
- if (! Math::IsEqual(ret, exp, TEST_TOLERANCE))
- {
- fprintf(stderr, "Cofactors 2 mismatch!\n");
- fprintf(stderr, "r=%d, c=%d, %f (returned) != %f (expected)\n", r, c, ret, exp);
- return __LINE__;
- }
+ for (int c = 0; c < 4; ++c)
+ {
+ float ret = mat2.Cofactor(r, c);
+ float exp = expectedCofactors2.m[4*c+r];
+ if (! Math::IsEqual(ret, exp, TEST_TOLERANCE))
+ {
+ fprintf(stderr, "Cofactors 2 mismatch!\n");
+ fprintf(stderr, "r=%d, c=%d, %f (returned) != %f (expected)\n", r, c, ret, exp);
+ return __LINE__;
+ }
+ }
}
- }
- return 0;
+ return 0;
}
int TestDet()
{
- const Math::Matrix mat1(
- (float[4][4])
+ const Math::Matrix mat1(
+ (float[4][4])
+ {
+ { -0.95880162984708284, 0.24004047608997131, -0.78172309932665407, -0.11604124457222834 },
+ { -0.36230592086261376, -0.75778166876017261, 0.33041059404631740, -1.06001391941094836 },
+ { 0.00260215210936187, 1.27485610196385113, -0.26149859846418033, -0.59669701186364876 },
+ { 0.36899429848485432, 3.01720896813933104, 2.10311476609438719, -1.68627076626448269 }
+ }
+ );
+
+ const float expectedDet1 = 4.07415413729671;
+
+ float ret1 = mat1.Det();
+ if (! Math::IsEqual(ret1, expectedDet1, TEST_TOLERANCE))
{
- { -0.95880162984708284, 0.24004047608997131, -0.78172309932665407, -0.11604124457222834 },
- { -0.36230592086261376, -0.75778166876017261, 0.33041059404631740, -1.06001391941094836 },
- { 0.00260215210936187, 1.27485610196385113, -0.26149859846418033, -0.59669701186364876 },
- { 0.36899429848485432, 3.01720896813933104, 2.10311476609438719, -1.68627076626448269 }
+ fprintf(stderr, "Det mismatch!\n");
+ fprintf(stderr, "%f (returned) != %f (expected)\n", ret1, expectedDet1);
+ return __LINE__;
}
- );
- const float expectedDet1 = 4.07415413729671;
+ const Math::Matrix mat2(
+ (float[4][4])
+ {
+ { -1.0860073221346871, 0.9150354098189495, -0.2723201933559999, 0.2922832160271507 },
+ { -1.0248331304801788, -2.5081237461125205, -1.0277123574586633, -0.2254690663329798 },
+ { -1.4227635282899367, -0.0403846809122684, 0.9216148477171653, 1.2517067488015878 },
+ { -0.1160254467152022, 0.8270675274393656, 1.0327218739781614, -0.3674886870220400 }
+ }
+ );
- float ret1 = mat1.Det();
- if (! Math::IsEqual(ret1, expectedDet1, TEST_TOLERANCE))
- {
- fprintf(stderr, "Det mismatch!\n");
- fprintf(stderr, "%f (returned) != %f (expected)\n", ret1, expectedDet1);
- return __LINE__;
- }
+ const float expectedDet2 = -6.35122307880942;
- const Math::Matrix mat2(
- (float[4][4])
+ float ret2 = mat2.Det();
+ if (! Math::IsEqual(ret2, expectedDet2, TEST_TOLERANCE))
{
- { -1.0860073221346871, 0.9150354098189495, -0.2723201933559999, 0.2922832160271507 },
- { -1.0248331304801788, -2.5081237461125205, -1.0277123574586633, -0.2254690663329798 },
- { -1.4227635282899367, -0.0403846809122684, 0.9216148477171653, 1.2517067488015878 },
- { -0.1160254467152022, 0.8270675274393656, 1.0327218739781614, -0.3674886870220400 }
+ fprintf(stderr, "Det mismatch!\n");
+ fprintf(stderr, "%f (returned) != %f (expected)\n", ret2, expectedDet2);
+ return __LINE__;
}
- );
- const float expectedDet2 = -6.35122307880942;
-
- float ret2 = mat2.Det();
- if (! Math::IsEqual(ret2, expectedDet2, TEST_TOLERANCE))
- {
- fprintf(stderr, "Det mismatch!\n");
- fprintf(stderr, "%f (returned) != %f (expected)\n", ret2, expectedDet2);
- return __LINE__;
- }
-
- return 0;
+ return 0;
}
int TestInverse()
{
- const Math::Matrix mat1(
- (float[4][4])
- {
- { -2.2829352811514658, -0.9103222363187888, 0.2792976509411680, -0.7984393573193174 },
- { 2.4823665798689589, -0.0599056759070980, 0.3832364352926366, -1.6404257204372739 },
- { -0.3841952272526398, -0.8377700696457873, -0.3416328338427138, 1.1746577275723329 },
- { 0.1746031241954947, -0.4952532117949962, 0.2155084379835037, -1.6586460437329220 }
- }
- );
-
- const Math::Matrix expectedInverse1(
- (float[4][4])
- {
- { -0.119472603171041, 0.331675963276297, 0.187516809009720, -0.137720814290806 },
- { -0.387591686166085, -0.487284946727583, -0.798527541290274, 0.102991635972060 },
- { 2.601905603425902, 2.606899016264679, -0.528006148839176, -4.204703326522837 },
- { 0.441220327151392, 0.519128136207318, 0.189567009205522, -1.194469716136194 }
- }
- );
-
- Math::Matrix inverse1 = mat1.Inverse();
-
- if (! Math::MatricesEqual(inverse1, expectedInverse1, TEST_TOLERANCE))
- {
- fprintf(stderr, "Inverse 1 mismatch!\n");
- return __LINE__;
- }
-
- const Math::Matrix mat2(
- (float[4][4])
+ const Math::Matrix mat1(
+ (float[4][4])
+ {
+ { -2.2829352811514658, -0.9103222363187888, 0.2792976509411680, -0.7984393573193174 },
+ { 2.4823665798689589, -0.0599056759070980, 0.3832364352926366, -1.6404257204372739 },
+ { -0.3841952272526398, -0.8377700696457873, -0.3416328338427138, 1.1746577275723329 },
+ { 0.1746031241954947, -0.4952532117949962, 0.2155084379835037, -1.6586460437329220 }
+ }
+ );
+
+ const Math::Matrix expectedInverse1(
+ (float[4][4])
+ {
+ { -0.119472603171041, 0.331675963276297, 0.187516809009720, -0.137720814290806 },
+ { -0.387591686166085, -0.487284946727583, -0.798527541290274, 0.102991635972060 },
+ { 2.601905603425902, 2.606899016264679, -0.528006148839176, -4.204703326522837 },
+ { 0.441220327151392, 0.519128136207318, 0.189567009205522, -1.194469716136194 }
+ }
+ );
+
+ Math::Matrix inverse1 = mat1.Inverse();
+
+ if (! Math::MatricesEqual(inverse1, expectedInverse1, TEST_TOLERANCE))
{
- { -0.05464332404298505, -0.64357755258235749, -0.13017671677619302, -0.56742332785888006 },
- { 0.29048383600458222, -0.91517047043724875, 0.84517524415561684, 0.51628195547960565 },
- { 0.00946488004480186, -0.89077382212689293, 0.73565573766341397, -0.15932513521840930 },
- { -1.01244718912499132, -0.27840911963972276, -0.39189681211309862, 1.18315064340192055 }
+ fprintf(stderr, "Inverse 1 mismatch!\n");
+ return __LINE__;
}
- );
- const Math::Matrix expectedInverse2(
- (float[4][4])
+ const Math::Matrix mat2(
+ (float[4][4])
+ {
+ { -0.05464332404298505, -0.64357755258235749, -0.13017671677619302, -0.56742332785888006 },
+ { 0.29048383600458222, -0.91517047043724875, 0.84517524415561684, 0.51628195547960565 },
+ { 0.00946488004480186, -0.89077382212689293, 0.73565573766341397, -0.15932513521840930 },
+ { -1.01244718912499132, -0.27840911963972276, -0.39189681211309862, 1.18315064340192055 }
+ }
+ );
+
+ const Math::Matrix expectedInverse2(
+ (float[4][4])
+ {
+ { 0.771302711132012, 1.587542278361995, -2.003075114445104, -0.592574156227379 },
+ { -1.208929259769431, -0.786598967848473, 0.607335305808052, -0.154759693303324 },
+ { -1.500037668208218, -0.774300278997914, 1.917800427261255, -0.123268572651291 },
+ { -0.121314770937944, 0.916925149209746, -0.935924950785014, 0.260875394250671 }
+ }
+ );
+
+ Math::Matrix inverse2 = mat2.Inverse();
+
+ if (! Math::MatricesEqual(inverse2, expectedInverse2, TEST_TOLERANCE))
{
- { 0.771302711132012, 1.587542278361995, -2.003075114445104, -0.592574156227379 },
- { -1.208929259769431, -0.786598967848473, 0.607335305808052, -0.154759693303324 },
- { -1.500037668208218, -0.774300278997914, 1.917800427261255, -0.123268572651291 },
- { -0.121314770937944, 0.916925149209746, -0.935924950785014, 0.260875394250671 }
+ fprintf(stderr, "Inverse 2 mismatch!\n");
+ return __LINE__;
}
- );
- Math::Matrix inverse2 = mat2.Inverse();
-
- if (! Math::MatricesEqual(inverse2, expectedInverse2, TEST_TOLERANCE))
- {
- fprintf(stderr, "Inverse 2 mismatch!\n");
- return __LINE__;
- }
-
- return 0;
+ return 0;
}
int TestMultiply()
{
- const Math::Matrix mat1A(
- (float[4][4])
- {
- { 0.6561727049162027, -1.4180263627131411, -0.8271026046117423, 2.3919331748512578 },
- { -0.6035665535146352, 0.0150827348790615, -0.7090794192822540, 0.9057604704594814 },
- { -0.9871045001223655, -0.4980646811455065, 0.3806177002298990, 0.1520583649240934 },
- { -0.2721911170792712, 0.7627928194552067, -0.1504091336784158, 0.9747545351840121 }
- }
- );
-
- const Math::Matrix mat1B(
- (float[4][4])
- {
- { -0.2643735892448818, -0.7542994492819621, 0.6082322350568750, 0.0581733424861419 },
- { 1.0293246070431237, 0.1979285388251341, -0.2932031385332818, 0.8838407179018929 },
- { 0.3448687251553114, 0.5031654871245456, 0.7554693012922442, -0.4845315903845708 },
- { -1.8662838497278593, -0.7843850624747805, 0.1389026096476257, -1.3686415408300689 }
- }
- );
-
- const Math::Matrix expectedMultiply1(
- (float[4][4])
- {
- { -6.382352236417988, -3.067984733682130, 0.522270304251466, -4.088079444498280 },
- { -1.759853366848825, -0.608994052024491, -0.781406179437379, -0.917870775786188 },
- { -0.404226802169062, 0.718232546720114, -0.145688356880835, -0.890167707987175 },
- { -1.013918490922430, -0.483971504099758, -0.367442194643757, -0.602858486133615 }
- }
- );
-
- Math::Matrix multiply1 = Math::MultiplyMatrices(mat1A, mat1B);
- if (! Math::MatricesEqual(multiply1, expectedMultiply1, TEST_TOLERANCE ) )
- {
- fprintf(stderr, "Multiply 1 mismath!\n");
- return __LINE__;
- }
-
- const Math::Matrix mat2A(
- (float[4][4])
+ const Math::Matrix mat1A(
+ (float[4][4])
+ {
+ { 0.6561727049162027, -1.4180263627131411, -0.8271026046117423, 2.3919331748512578 },
+ { -0.6035665535146352, 0.0150827348790615, -0.7090794192822540, 0.9057604704594814 },
+ { -0.9871045001223655, -0.4980646811455065, 0.3806177002298990, 0.1520583649240934 },
+ { -0.2721911170792712, 0.7627928194552067, -0.1504091336784158, 0.9747545351840121 }
+ }
+ );
+
+ const Math::Matrix mat1B(
+ (float[4][4])
+ {
+ { -0.2643735892448818, -0.7542994492819621, 0.6082322350568750, 0.0581733424861419 },
+ { 1.0293246070431237, 0.1979285388251341, -0.2932031385332818, 0.8838407179018929 },
+ { 0.3448687251553114, 0.5031654871245456, 0.7554693012922442, -0.4845315903845708 },
+ { -1.8662838497278593, -0.7843850624747805, 0.1389026096476257, -1.3686415408300689 }
+ }
+ );
+
+ const Math::Matrix expectedMultiply1(
+ (float[4][4])
+ {
+ { -6.382352236417988, -3.067984733682130, 0.522270304251466, -4.088079444498280 },
+ { -1.759853366848825, -0.608994052024491, -0.781406179437379, -0.917870775786188 },
+ { -0.404226802169062, 0.718232546720114, -0.145688356880835, -0.890167707987175 },
+ { -1.013918490922430, -0.483971504099758, -0.367442194643757, -0.602858486133615 }
+ }
+ );
+
+ Math::Matrix multiply1 = Math::MultiplyMatrices(mat1A, mat1B);
+ if (! Math::MatricesEqual(multiply1, expectedMultiply1, TEST_TOLERANCE ) )
{
- { 0.8697203025776754, 2.1259475710644935, 1.7856691009707812, -2.1563963348328126 },
- { 1.5888074489288735, -0.0794849733953615, 0.7307782768677457, 0.7943129159612630 },
- { 0.2859761537233830, -0.6231231890384962, -0.0496743172880377, -0.8137857518646087 },
- { 1.2670547229512983, -0.5305171374831831, -0.4987412674062375, -1.1257327113869595 }
- }
- );
-
- const Math::Matrix mat2B(
- (float[4][4])
- {
- { 1.1321105701165317, 0.1759563504574463, -2.0675778912000418, 1.4840339814245538 },
- { -1.5117280888829916, -0.0933013188828093, -0.2079262944351640, 0.9575727579539316 },
- { 0.3615378398970173, 1.2465163589027248, 1.1326150997082589, 0.9921208694352303 },
- { -0.7357104529373861, -0.4774022005969588, -0.2118739096676499, 1.1427567093270703 }
+ fprintf(stderr, "Multiply 1 mismath!\n");
+ return __LINE__;
}
- );
- const Math::Matrix expectedMultiply2(
- (float[4][4])
+ const Math::Matrix mat2A(
+ (float[4][4])
+ {
+ { 0.8697203025776754, 2.1259475710644935, 1.7856691009707812, -2.1563963348328126 },
+ { 1.5888074489288735, -0.0794849733953615, 0.7307782768677457, 0.7943129159612630 },
+ { 0.2859761537233830, -0.6231231890384962, -0.0496743172880377, -0.8137857518646087 },
+ { 1.2670547229512983, -0.5305171374831831, -0.4987412674062375, -1.1257327113869595 }
+ }
+ );
+
+ const Math::Matrix mat2B(
+ (float[4][4])
+ {
+ { 1.1321105701165317, 0.1759563504574463, -2.0675778912000418, 1.4840339814245538 },
+ { -1.5117280888829916, -0.0933013188828093, -0.2079262944351640, 0.9575727579539316 },
+ { 0.3615378398970173, 1.2465163589027248, 1.1326150997082589, 0.9921208694352303 },
+ { -0.7357104529373861, -0.4774022005969588, -0.2118739096676499, 1.1427567093270703 }
+ }
+ );
+
+ const Math::Matrix expectedMultiply2(
+ (float[4][4])
+ {
+ { 0.00283516267056338, 3.21001319965989307, 0.23910503934370686, 2.63380716363006107 },
+ { 1.59868505822469742, 0.81869715594617765, -2.60905981088293570, 3.91445839239110294 },
+ { 1.84650099286297942, 0.43504079532852930, -0.34555619012424243, -1.15152951542451487 },
+ { 2.88434318563174585, 0.18818239851585700, -2.83579436909308980, -0.40890672198610400 }
+ }
+ );
+
+ Math::Matrix multiply2 = Math::MultiplyMatrices(mat2A, mat2B);
+ if (! Math::MatricesEqual(multiply2, expectedMultiply2, TEST_TOLERANCE ) )
{
- { 0.00283516267056338, 3.21001319965989307, 0.23910503934370686, 2.63380716363006107 },
- { 1.59868505822469742, 0.81869715594617765, -2.60905981088293570, 3.91445839239110294 },
- { 1.84650099286297942, 0.43504079532852930, -0.34555619012424243, -1.15152951542451487 },
- { 2.88434318563174585, 0.18818239851585700, -2.83579436909308980, -0.40890672198610400 }
+ fprintf(stderr, "Multiply 2 mismath!\n");
+ return __LINE__;
}
- );
-
- Math::Matrix multiply2 = Math::MultiplyMatrices(mat2A, mat2B);
- if (! Math::MatricesEqual(multiply2, expectedMultiply2, TEST_TOLERANCE ) )
- {
- fprintf(stderr, "Multiply 2 mismath!\n");
- return __LINE__;
- }
- return 0;
+ return 0;
}
int TestMultiplyVector()
{
- const Math::Matrix mat1(
- (float[4][4])
+ const Math::Matrix mat1(
+ (float[4][4])
+ {
+ { 0.188562846910008, -0.015148651460679, 0.394512304108827, 0.906910631257135 },
+ { -0.297506779519667, 0.940119328178913, 0.970957796752517, 0.310559318965526 },
+ { -0.819770525290873, -2.316574438778879, 0.155756069319732, -0.855661405742964 },
+ { 0.000000000000000, 0.000000000000000, 0.000000000000000, 1.000000000000000 }
+ }
+ );
+
+ const Math::Vector vec1(-0.824708565156661, -1.598287748103842, -0.422498044734181);
+
+ const Math::Vector expectedMultiply1(0.608932463260470, -1.356893266403749, 3.457156276255142);
+
+ Math::Vector multiply1 = Math::MatrixVectorMultiply(mat1, vec1, false);
+ if (! Math::VectorsEqual(multiply1, expectedMultiply1, TEST_TOLERANCE ) )
{
- { 0.188562846910008, -0.015148651460679, 0.394512304108827, 0.906910631257135 },
- { -0.297506779519667, 0.940119328178913, 0.970957796752517, 0.310559318965526 },
- { -0.819770525290873, -2.316574438778879, 0.155756069319732, -0.855661405742964 },
- { 0.000000000000000, 0.000000000000000, 0.000000000000000, 1.000000000000000 }
+ fprintf(stderr, "Multiply vector 1 mismath!\n");
+ return __LINE__;
}
- );
- const Math::Vector vec1(-0.824708565156661, -1.598287748103842, -0.422498044734181);
+ const Math::Matrix mat2(
+ (float[4][4])
+ {
+ { -0.63287117038834284, 0.55148060401816856, -0.02042395559467368, -1.50367083897656850 },
+ { 0.69629042156335297, 0.12982747869796774, -1.16250029235919405, 1.19084447253756909 },
+ { 0.44164132914357224, -0.15169304045662041, -0.00880583574621390, -0.55817802940035310 },
+ { 0.95680476533530789, -1.51912346889253125, -0.74209769406615944, -0.20938988867903682 }
+ }
+ );
- const Math::Vector expectedMultiply1(0.608932463260470, -1.356893266403749, 3.457156276255142);
+ const Math::Vector vec2(0.330987381051962, 1.494375516393466, 1.483422335561857);
- Math::Vector multiply1 = Math::MatrixVectorMultiply(mat1, vec1, false);
- if (! Math::VectorsEqual(multiply1, expectedMultiply1, TEST_TOLERANCE ) )
- {
- fprintf(stderr, "Multiply vector 1 mismath!\n");
- return __LINE__;
- }
+ const Math::Vector expectedMultiply2(0.2816820577317669, 0.0334468811767428, 0.1996974284970455);
- const Math::Matrix mat2(
- (float[4][4])
+ Math::Vector multiply2 = Math::MatrixVectorMultiply(mat2, vec2, true);
+ if (! Math::VectorsEqual(multiply2, expectedMultiply2, TEST_TOLERANCE ) )
{
- { -0.63287117038834284, 0.55148060401816856, -0.02042395559467368, -1.50367083897656850 },
- { 0.69629042156335297, 0.12982747869796774, -1.16250029235919405, 1.19084447253756909 },
- { 0.44164132914357224, -0.15169304045662041, -0.00880583574621390, -0.55817802940035310 },
- { 0.95680476533530789, -1.51912346889253125, -0.74209769406615944, -0.20938988867903682 }
+ fprintf(stderr, "Multiply vector 2 mismath!\n");
+ return __LINE__;
}
- );
- const Math::Vector vec2(0.330987381051962, 1.494375516393466, 1.483422335561857);
-
- const Math::Vector expectedMultiply2(0.2816820577317669, 0.0334468811767428, 0.1996974284970455);
-
- Math::Vector multiply2 = Math::MatrixVectorMultiply(mat2, vec2, true);
- if (! Math::VectorsEqual(multiply2, expectedMultiply2, TEST_TOLERANCE ) )
- {
- fprintf(stderr, "Multiply vector 2 mismath!\n");
- return __LINE__;
- }
-
- return 0;
+ return 0;
}
int main()
{
- // Functions to test
- int (*TESTS[])() =
- {
- TestTranspose,
- TestCofactor,
- TestDet,
- TestInverse,
- TestMultiply,
- TestMultiplyVector
- };
- const int TESTS_SIZE = sizeof(TESTS) / sizeof(*TESTS);
-
- int result = 0;
- for (int i = 0; i < TESTS_SIZE; ++i)
- {
- result = TESTS[i]();
- if (result != 0)
- return result;
- }
-
- fprintf(stderr, "All tests successful\n");
-
- return 0;
+ // Functions to test
+ int (*TESTS[])() =
+ {
+ TestTranspose,
+ TestCofactor,
+ TestDet,
+ TestInverse,
+ TestMultiply,
+ TestMultiplyVector
+ };
+ const int TESTS_SIZE = sizeof(TESTS) / sizeof(*TESTS);
+
+ int result = 0;
+ for (int i = 0; i < TESTS_SIZE; ++i)
+ {
+ result = TESTS[i]();
+ if (result != 0)
+ return result;
+ }
+
+ fprintf(stderr, "All tests successful\n");
+
+ return 0;
}
diff --git a/src/math/test/vector_test.cpp b/src/math/test/vector_test.cpp
index d2bf231..899a580 100644
--- a/src/math/test/vector_test.cpp
+++ b/src/math/test/vector_test.cpp
@@ -16,11 +16,11 @@
// math/test/vector_test.cpp
-/* Unit tests for Vector struct
-
- Test data was randomly generated and the expected results
- calculated using GNU Octave.
+/*
+ Unit tests for Vector struct
+ Test data was randomly generated and the expected results
+ calculated using GNU Octave.
*/
#include "../func.h"
@@ -34,94 +34,94 @@ const float TEST_TOLERANCE = 1e-6;
int TestLength()
{
- Math::Vector vec(-1.288447945923275, 0.681452565308134, -0.633761098985957);
- const float expectedLength = 1.58938001708428;
+ Math::Vector vec(-1.288447945923275, 0.681452565308134, -0.633761098985957);
+ const float expectedLength = 1.58938001708428;
- if (! Math::IsEqual(vec.Length(), expectedLength, TEST_TOLERANCE) )
- {
- fprintf(stderr, "Length mismatch!\n");
- return __LINE__;
- }
+ if (! Math::IsEqual(vec.Length(), expectedLength, TEST_TOLERANCE) )
+ {
+ fprintf(stderr, "Length mismatch!\n");
+ return __LINE__;
+ }
- return 0;
+ return 0;
}
int TestNormalize()
{
- Math::Vector vec(1.848877241804398, -0.157262961268577, -1.963031403332377);
- const Math::Vector expectedNormalized(0.6844609421393856, -0.0582193085618106, -0.7267212194481797);
+ Math::Vector vec(1.848877241804398, -0.157262961268577, -1.963031403332377);
+ const Math::Vector expectedNormalized(0.6844609421393856, -0.0582193085618106, -0.7267212194481797);
- vec.Normalize();
+ vec.Normalize();
- if (! Math::VectorsEqual(vec, expectedNormalized, TEST_TOLERANCE))
- {
- fprintf(stderr, "Normalize mismatch!\n");
- return __LINE__;
- }
+ if (! Math::VectorsEqual(vec, expectedNormalized, TEST_TOLERANCE))
+ {
+ fprintf(stderr, "Normalize mismatch!\n");
+ return __LINE__;
+ }
- return 0;
+ return 0;
}
int TestDot()
{
- Math::Vector vecA(0.8202190530968309, 0.0130926060162780, 0.2411914183883510);
- Math::Vector vecB(-0.0524083951404069, 1.5564932716738220, -0.8971342631500536);
+ Math::Vector vecA(0.8202190530968309, 0.0130926060162780, 0.2411914183883510);
+ Math::Vector vecB(-0.0524083951404069, 1.5564932716738220, -0.8971342631500536);
- float expectedDot = -0.238988896477326;
+ float expectedDot = -0.238988896477326;
- if (! Math::IsEqual(Math::DotProduct(vecA, vecB), expectedDot, TEST_TOLERANCE) )
- {
- fprintf(stderr, "Dot product mismatch!\n");
- return __LINE__;
- }
+ if (! Math::IsEqual(Math::DotProduct(vecA, vecB), expectedDot, TEST_TOLERANCE) )
+ {
+ fprintf(stderr, "Dot product mismatch!\n");
+ return __LINE__;
+ }
- return 0;
+ return 0;
}
int TestCross()
{
- Math::Vector vecA(1.37380499798567, 1.18054518384682, 1.95166361293121);
- Math::Vector vecB(0.891657855926886, 0.447591335394532, -0.901604070087823);
+ Math::Vector vecA(1.37380499798567, 1.18054518384682, 1.95166361293121);
+ Math::Vector vecB(0.891657855926886, 0.447591335394532, -0.901604070087823);
- Math::Vector expectedCross(-1.937932065431669, 2.978844370287636, -0.437739173833581);
- Math::Vector expectedReverseCross = -expectedCross;
+ Math::Vector expectedCross(-1.937932065431669, 2.978844370287636, -0.437739173833581);
+ Math::Vector expectedReverseCross = -expectedCross;
- if (! Math::VectorsEqual(vecA.CrossMultiply(vecB), expectedCross, TEST_TOLERANCE) )
- {
- fprintf(stderr, "Cross product mismatch!\n");
- return __LINE__;
- }
+ if (! Math::VectorsEqual(vecA.CrossMultiply(vecB), expectedCross, TEST_TOLERANCE) )
+ {
+ fprintf(stderr, "Cross product mismatch!\n");
+ return __LINE__;
+ }
- if (! Math::VectorsEqual(vecB.CrossMultiply(vecA), expectedReverseCross, TEST_TOLERANCE) )
- {
- fprintf(stderr, "Reverse cross product mismatch!\n");
- return __LINE__;
- }
+ if (! Math::VectorsEqual(vecB.CrossMultiply(vecA), expectedReverseCross, TEST_TOLERANCE) )
+ {
+ fprintf(stderr, "Reverse cross product mismatch!\n");
+ return __LINE__;
+ }
- return 0;
+ return 0;
}
int main()
{
- // Functions to test
- int (*TESTS[])() =
- {
- TestLength,
- TestNormalize,
- TestDot,
- TestCross
- };
- const int TESTS_SIZE = sizeof(TESTS) / sizeof(*TESTS);
-
- int result = 0;
- for (int i = 0; i < TESTS_SIZE; ++i)
- {
- result = TESTS[i]();
- if (result != 0)
- return result;
- }
-
- fprintf(stderr, "All tests successful\n");
-
- return 0;
+ // Functions to test
+ int (*TESTS[])() =
+ {
+ TestLength,
+ TestNormalize,
+ TestDot,
+ TestCross
+ };
+ const int TESTS_SIZE = sizeof(TESTS) / sizeof(*TESTS);
+
+ int result = 0;
+ for (int i = 0; i < TESTS_SIZE; ++i)
+ {
+ result = TESTS[i]();
+ if (result != 0)
+ return result;
+ }
+
+ fprintf(stderr, "All tests successful\n");
+
+ return 0;
}
diff --git a/src/math/vector.h b/src/math/vector.h
index fd9aa52..3c756f2 100644
--- a/src/math/vector.h
+++ b/src/math/vector.h
@@ -35,209 +35,209 @@ namespace Math
/** \struct Vector math/vector.h
\brief 3D (3x1) vector
- Represents a universal 3x1 vector that can be used in OpenGL and DirectX engines.
- Contains the required methods for operating on vectors.
+ Represents a universal 3x1 vector that can be used in OpenGL and DirectX engines.
+ Contains the required methods for operating on vectors.
- All methods are made inline to maximize optimization.
+ All methods are made inline to maximize optimization.
- Unit tests for the structure and related functions are in module: math/test/vector_test.cpp.
+ Unit tests for the structure and related functions are in module: math/test/vector_test.cpp.
*/
struct Vector
{
- //! X - 1st coord
- float x;
- //! Y - 2nd coord
- float y;
- //! Z - 3rd coord
- float z;
-
- //! Creates a zero vector (0, 0, 0)
- inline Vector()
- {
- LoadZero();
- }
-
- //! Creates a vector from given values
- inline explicit Vector(float x, float y, float z)
- {
- this->x = x;
- this->y = y;
- this->z = z;
- }
-
- //! Loads the zero vector (0, 0, 0)
- inline void LoadZero()
- {
- x = y = z = 0.0f;
- }
-
- //! Returns the vector length
- inline float Length() const
- {
- return sqrtf(x*x + y*y + z*z);
- }
-
- //! Normalizes the vector
- inline void Normalize()
- {
- float l = Length();
- if (IsZero(l))
- return;
-
- x /= l;
- y /= l;
- z /= l;
- }
-
- //! Calculates the cross product with another vector
- /** \a right right-hand side vector
- \returns the cross product*/
- inline Vector CrossMultiply(const Vector &right) const
- {
- float px = y * right.z - z * right.y;
- float py = z * right.x - x * right.z;
- float pz = x * right.y - y * right.x;
- return Vector(px, py, pz);
- }
-
- //! Calculates the dot product with another vector
- /** \a right right-hand side vector
- \returns the dot product */
- inline float DotMultiply(const Vector &right) const
- {
- return x * right.x + y * right.y + z * right.z;
- }
-
- //! Returns the cosine of angle between this and another vector
- inline float CosAngle(const Vector &right) const
- {
- return DotMultiply(right) / (Length() * right.Length());
- }
-
- //! Returns angle (in radians) between this and another vector
- inline float Angle(const Vector &right) const
- {
- return acos(CosAngle(right));
- }
-
-
- /* Operators */
-
- //! Returns the inverted vector
- inline Vector operator-() const
- {
- return Vector(-x, -y, -z);
- }
-
- //! Adds the given vector
- inline const Vector& operator+=(const Vector &right)
- {
- x += right.x;
- y += right.y;
- z += right.z;
- return *this;
- }
-
- //! Adds two vectors
- inline friend const Vector operator+(const Vector &left, const Vector &right)
- {
- return Vector(left.x + right.x, left.y + right.y, left.z + right.z);
- }
-
- //! Subtracts the given vector
- inline const Vector& operator-=(const Vector &right)
- {
- x -= right.x;
- y -= right.y;
- z -= right.z;
- return *this;
- }
-
- //! Subtracts two vectors
- inline friend const Vector operator-(const Vector &left, const Vector &right)
- {
- return Vector(left.x - right.x, left.y - right.y, left.z - right.z);
- }
-
- //! Multiplies by given scalar
- inline const Vector& operator*=(const float &right)
- {
- x *= right;
- y *= right;
- z *= right;
- return *this;
- }
-
- //! Multiplies vector by scalar
- inline friend const Vector operator*(const float &left, const Vector &right)
- {
- return Vector(left * right.x, left * right.y, left * right.z);
- }
-
- //! Multiplies vector by scalar
- inline friend const Vector operator*(const Vector &left, const float &right)
- {
- return Vector(left.x * right, left.y * right, left.z * right);
- }
-
- //! Divides by given scalar
- inline const Vector& operator/=(const float &right)
- {
- x /= right;
- y /= right;
- z /= right;
- return *this;
- }
-
- //! Divides vector by scalar
- inline friend const Vector operator/(const Vector &left, const float &right)
- {
- return Vector(left.x / right, left.y / right, left.z / right);
- }
+ //! X - 1st coord
+ float x;
+ //! Y - 2nd coord
+ float y;
+ //! Z - 3rd coord
+ float z;
+
+ //! Creates a zero vector (0, 0, 0)
+ inline Vector()
+ {
+ LoadZero();
+ }
+
+ //! Creates a vector from given values
+ inline explicit Vector(float x, float y, float z)
+ {
+ this->x = x;
+ this->y = y;
+ this->z = z;
+ }
+
+ //! Loads the zero vector (0, 0, 0)
+ inline void LoadZero()
+ {
+ x = y = z = 0.0f;
+ }
+
+ //! Returns the vector length
+ inline float Length() const
+ {
+ return sqrtf(x*x + y*y + z*z);
+ }
+
+ //! Normalizes the vector
+ inline void Normalize()
+ {
+ float l = Length();
+ if (IsZero(l))
+ return;
+
+ x /= l;
+ y /= l;
+ z /= l;
+ }
+
+ //! Calculates the cross product with another vector
+ /** \a right right-hand side vector
+ \returns the cross product*/
+ inline Vector CrossMultiply(const Vector &right) const
+ {
+ float px = y * right.z - z * right.y;
+ float py = z * right.x - x * right.z;
+ float pz = x * right.y - y * right.x;
+ return Vector(px, py, pz);
+ }
+
+ //! Calculates the dot product with another vector
+ /** \a right right-hand side vector
+ \returns the dot product */
+ inline float DotMultiply(const Vector &right) const
+ {
+ return x * right.x + y * right.y + z * right.z;
+ }
+
+ //! Returns the cosine of angle between this and another vector
+ inline float CosAngle(const Vector &right) const
+ {
+ return DotMultiply(right) / (Length() * right.Length());
+ }
+
+ //! Returns angle (in radians) between this and another vector
+ inline float Angle(const Vector &right) const
+ {
+ return acos(CosAngle(right));
+ }
+
+
+ /* Operators */
+
+ //! Returns the inverted vector
+ inline Vector operator-() const
+ {
+ return Vector(-x, -y, -z);
+ }
+
+ //! Adds the given vector
+ inline const Vector& operator+=(const Vector &right)
+ {
+ x += right.x;
+ y += right.y;
+ z += right.z;
+ return *this;
+ }
+
+ //! Adds two vectors
+ inline friend const Vector operator+(const Vector &left, const Vector &right)
+ {
+ return Vector(left.x + right.x, left.y + right.y, left.z + right.z);
+ }
+
+ //! Subtracts the given vector
+ inline const Vector& operator-=(const Vector &right)
+ {
+ x -= right.x;
+ y -= right.y;
+ z -= right.z;
+ return *this;
+ }
+
+ //! Subtracts two vectors
+ inline friend const Vector operator-(const Vector &left, const Vector &right)
+ {
+ return Vector(left.x - right.x, left.y - right.y, left.z - right.z);
+ }
+
+ //! Multiplies by given scalar
+ inline const Vector& operator*=(const float &right)
+ {
+ x *= right;
+ y *= right;
+ z *= right;
+ return *this;
+ }
+
+ //! Multiplies vector by scalar
+ inline friend const Vector operator*(const float &left, const Vector &right)
+ {
+ return Vector(left * right.x, left * right.y, left * right.z);
+ }
+
+ //! Multiplies vector by scalar
+ inline friend const Vector operator*(const Vector &left, const float &right)
+ {
+ return Vector(left.x * right, left.y * right, left.z * right);
+ }
+
+ //! Divides by given scalar
+ inline const Vector& operator/=(const float &right)
+ {
+ x /= right;
+ y /= right;
+ z /= right;
+ return *this;
+ }
+
+ //! Divides vector by scalar
+ inline friend const Vector operator/(const Vector &left, const float &right)
+ {
+ return Vector(left.x / right, left.y / right, left.z / right);
+ }
}; // struct Point
//! Checks if two vectors are equal within given \a tolerance
inline bool VectorsEqual(const Vector &a, const Vector &b, float tolerance = TOLERANCE)
{
- return IsEqual(a.x, b.x, tolerance)
- && IsEqual(a.y, b.y, tolerance)
- && IsEqual(a.z, b.z, tolerance);
+ return IsEqual(a.x, b.x, tolerance)
+ && IsEqual(a.y, b.y, tolerance)
+ && IsEqual(a.z, b.z, tolerance);
}
//! Convenience function for getting normalized vector
inline Vector Normalize(const Vector &v)
{
- Vector result = v;
- result.Normalize();
- return result;
+ Vector result = v;
+ result.Normalize();
+ return result;
}
//! Convenience function for calculating dot product
inline float DotProduct(const Vector &left, const Vector &right)
{
- return left.DotMultiply(right);
+ return left.DotMultiply(right);
}
//! Convenience function for calculating cross product
inline Vector CrossProduct(const Vector &left, const Vector &right)
{
- return left.CrossMultiply(right);
+ return left.CrossMultiply(right);
}
//! Convenience function for calculating angle (in radians) between two vectors
inline float Angle(const Vector &a, const Vector &b)
{
- return a.Angle(b);
+ return a.Angle(b);
}
//! Returns the distance between the ends of two vectors
inline float Distance(const Vector &a, const Vector &b)
{
- return sqrtf( (a.x-b.x)*(a.x-b.x) +
- (a.y-b.y)*(a.y-b.y) +
- (a.z-b.z)*(a.z-b.z) );
+ return sqrtf( (a.x-b.x)*(a.x-b.x) +
+ (a.y-b.y)*(a.y-b.y) +
+ (a.z-b.z)*(a.z-b.z) );
}
/* @} */ // end of group
diff --git a/src/object/auto/auto.cpp b/src/object/auto/auto.cpp
index 9635265..f2764e2 100644
--- a/src/object/auto/auto.cpp
+++ b/src/object/auto/auto.cpp
@@ -1,437 +1,437 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/auto.h"
-
-
-#include "common/iman.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/gauge.h"
-#include "ui/window.h"
-
-
-
-
-// Object's constructor.
-
-CAuto::CAuto(CInstanceManager* iMan, CObject* object)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_AUTO, this, 100);
-
- m_object = object;
- m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
- m_cloud = (CCloud*)m_iMan->SearchInstance(CLASS_CLOUD);
- m_planet = (CPlanet*)m_iMan->SearchInstance(CLASS_PLANET);
- m_blitz = (CBlitz*)m_iMan->SearchInstance(CLASS_BLITZ);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
-
- m_type = m_object->RetType();
- m_time = 0.0f;
- m_lastUpdateTime = 0.0f;
- m_bMotor = false;
- m_progressTime = 0.0f;
- m_progressTotal = 1.0f;
-
- Init();
-}
-
-// Object's destructor.
-
-CAuto::~CAuto()
-{
- m_iMan->DeleteInstance(CLASS_AUTO, this);
-}
-
-
-// Destroys the object.
-
-void CAuto::DeleteObject(bool bAll)
-{
-}
-
-
-// Initialize the object.
-
-void CAuto::Init()
-{
- m_bBusy = false;
-}
-
-// Starts the object.
-
-void CAuto::Start(int param)
-{
-}
-
-
-// Give a type.
-
-bool CAuto::SetType(ObjectType type)
-{
- return false;
-}
-
-// Gives a value.
-
-bool CAuto::SetValue(int rank, float value)
-{
- return false;
-}
-
-// Gives the string.
-
-bool CAuto::SetString(char *string)
-{
- return false;
-}
-
-
-// Management of an event.
-
-bool CAuto::EventProcess(const Event &event)
-{
- if ( event.event == EVENT_FRAME &&
- !m_engine->RetPause() )
- {
- m_time += event.rTime;
- UpdateInterface(event.rTime);
- }
-
- if ( !m_object->RetSelect() ) // robot not selected?
- {
- return true;
- }
-
- return true;
-}
-
-// Indicates whether the controller has finished its activity.
-
-Error CAuto::IsEnded()
-{
- return ERR_CONTINUE;
-}
-
-// Stops the controller
-
-bool CAuto::Abort()
-{
- return false;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAuto::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, dim, ddim;
- float ox, oy, sx, sy;
- char name[100];
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw != 0 )
- {
- pw->Flush(); // destroys the window buttons
- m_interface->DeleteControl(EVENT_WINDOW0); // destroys the window
- }
-
- if ( !bSelect ) return true;
-
- pos.x = 0.0f;
- pos.y = 0.0f;
- dim.x = 540.0f/640.0f;
-//? dim.y = 70.0f/480.0f;
- dim.y = 86.0f/480.0f;
- m_interface->CreateWindows(pos, dim, 3, EVENT_WINDOW0);
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- m_object->GetTooltipName(name);
- pos.x = 0.0f;
- pos.y = 64.0f/480.0f;
- ddim.x = 540.0f/640.0f;
- ddim.y = 16.0f/480.0f;
- pw->CreateLabel(pos, ddim, 0, EVENT_LABEL0, name);
-
- dim.x = 33.0f/640.0f;
- dim.y = 33.0f/480.0f;
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*7.0f;
- pos.y = oy+sy*0.6f;
- ddim.x = 160.0f/640.0f;
- ddim.y = 26.0f/480.0f;
- pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GPROGRESS);
-
- if ( m_type != OBJECT_BASE &&
- m_type != OBJECT_SAFE &&
- m_type != OBJECT_HUSTON )
- {
- pos.x = ox+sx*2.1f;
- pos.y = oy+sy*0;
- ddim.x = dim.x*0.6f;
- ddim.y = dim.y*0.6f;
- pw->CreateButton(pos, ddim, 12, EVENT_OBJECT_DELETE);
- }
-
-#if 0
- pos.x = ox+sx*12.4f;
- pos.y = oy+sy*1;
- pw->CreateButton(pos, dim, 63, EVENT_OBJECT_BHELP);
-
- pos.x = ox+sx*12.4f;
- pos.y = oy+sy*0;
- pw->CreateButton(pos, dim, 19, EVENT_OBJECT_HELP);
-
- if ( m_main->RetSceneSoluce() )
- {
- pos.x = ox+sx*13.4f;
- pos.y = oy+sy*1;
- pw->CreateButton(pos, dim, 20, EVENT_OBJECT_SOLUCE);
- }
-
- pos.x = ox+sx*13.4f;
- pos.y = oy+sy*0;
- pw->CreateButton(pos, dim, 10, EVENT_OBJECT_DESELECT);
-#else
- pos.x = ox+sx*12.3f;
- pos.y = oy+sy*-0.1f;
- ddim.x = dim.x*1.0f;
- ddim.y = dim.y*2.1f;
- pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue background
-
- pos.x = ox+sx*12.3f;
- pos.y = oy+sy*1;
- pw->CreateGroup(pos, dim, 19, EVENT_NULL); // sign SatCom
-
- pos.x = ox+sx*12.4f;
- pos.y = oy+sy*0.5f;
- ddim.x = dim.x*0.8f;
- ddim.y = dim.y*0.5f;
- pw->CreateButton(pos, ddim, 18, EVENT_OBJECT_BHELP);
- pos.y = oy+sy*0.0f;
- pw->CreateButton(pos, ddim, 19, EVENT_OBJECT_HELP);
-
- pos.x = ox+sx*13.4f;
- pos.y = oy+sy*0;
- pw->CreateButton(pos, dim, 10, EVENT_OBJECT_DESELECT);
-#endif
-
- pos.x = ox+sx*14.9f;
- pos.y = oy+sy*0;
- ddim.x = 14.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGauge(pos, ddim, 3, EVENT_OBJECT_GSHIELD);
-
- UpdateInterface();
- m_lastUpdateTime = 0.0f;
- UpdateInterface(0.0f);
-
- return true;
-}
-
-// Change the state of a button interface.
-
-void CAuto::CheckInterface(CWindow *pw, EventMsg event, bool bState)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_CHECK, bState);
-}
-
-// Change the state of a button interface.
-
-void CAuto::EnableInterface(CWindow *pw, EventMsg event, bool bState)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_ENABLE, bState);
-}
-
-// Change the state of a button interface.
-
-void CAuto::VisibleInterface(CWindow *pw, EventMsg event, bool bState)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_VISIBLE, bState);
-}
-
-// Change the state of a button interface.
-
-void CAuto::DeadInterface(CWindow *pw, EventMsg event, bool bState)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_DEAD, !bState);
-}
-
-// Change the state of a button interface.
-
-void CAuto::UpdateInterface()
-{
- CWindow* pw;
-
- if ( !m_object->RetSelect() ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- VisibleInterface(pw, EVENT_OBJECT_GPROGRESS, m_bBusy);
-}
-
-// Updates the state of all buttons on the interface,
-// following the time that elapses ...
-
-void CAuto::UpdateInterface(float rTime)
-{
- CWindow* pw;
- CGauge* pg;
-
- if ( m_time < m_lastUpdateTime+0.1f ) return;
- m_lastUpdateTime = m_time;
-
- if ( !m_object->RetSelect() ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GSHIELD);
- if ( pg != 0 )
- {
- pg->SetLevel(m_object->RetShield());
- }
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GPROGRESS);
- if ( pg != 0 )
- {
- pg->SetLevel(m_progressTime);
- }
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAuto::RetError()
-{
- return ERR_OK;
-}
-
-
-// Management of the occupation.
-
-bool CAuto::RetBusy()
-{
- return m_bBusy;
-}
-
-void CAuto::SetBusy(bool bBusy)
-{
- m_bBusy = bBusy;
-}
-
-void CAuto::InitProgressTotal(float total)
-{
- m_progressTime = 0.0f;
- m_progressTotal = total;
-}
-
-void CAuto::EventProgress(float rTime)
-{
- m_progressTime += rTime/m_progressTotal;
-}
-
-
-// Engine management.
-
-bool CAuto::RetMotor()
-{
- return m_bMotor;
-}
-
-void CAuto::SetMotor(bool bMotor)
-{
- m_bMotor = bMotor;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAuto::Write(char *line)
-{
- char name[100];
-
- sprintf(name, " aType=%d", m_type);
- strcat(line, name);
-
- sprintf(name, " aBusy=%d", m_bBusy);
- strcat(line, name);
-
- sprintf(name, " aTime=%.2f", m_time);
- strcat(line, name);
-
- sprintf(name, " aProgressTime=%.2f", m_progressTime);
- strcat(line, name);
-
- sprintf(name, " aProgressTotal=%.2f", m_progressTotal);
- strcat(line, name);
-
- return false;
-}
-
-// Return all settings to the controller.
-
-bool CAuto::Read(char *line)
-{
- m_type = (ObjectType)OpInt(line, "aType", OBJECT_NULL);
- m_bBusy = OpInt(line, "aBusy", 0);
- m_time = OpFloat(line, "aTime", 0.0f);
- m_progressTime = OpFloat(line, "aProgressTime", 0.0f);
- m_progressTotal = OpFloat(line, "aProgressTotal", 0.0f);
-
- return false;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/auto.h"
+
+
+#include "common/iman.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/gauge.h"
+#include "ui/window.h"
+
+
+
+
+// Object's constructor.
+
+CAuto::CAuto(CInstanceManager* iMan, CObject* object)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_AUTO, this, 100);
+
+ m_object = object;
+ m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ m_cloud = (CCloud*)m_iMan->SearchInstance(CLASS_CLOUD);
+ m_planet = (CPlanet*)m_iMan->SearchInstance(CLASS_PLANET);
+ m_blitz = (CBlitz*)m_iMan->SearchInstance(CLASS_BLITZ);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+
+ m_type = m_object->RetType();
+ m_time = 0.0f;
+ m_lastUpdateTime = 0.0f;
+ m_bMotor = false;
+ m_progressTime = 0.0f;
+ m_progressTotal = 1.0f;
+
+ Init();
+}
+
+// Object's destructor.
+
+CAuto::~CAuto()
+{
+ m_iMan->DeleteInstance(CLASS_AUTO, this);
+}
+
+
+// Destroys the object.
+
+void CAuto::DeleteObject(bool bAll)
+{
+}
+
+
+// Initialize the object.
+
+void CAuto::Init()
+{
+ m_bBusy = false;
+}
+
+// Starts the object.
+
+void CAuto::Start(int param)
+{
+}
+
+
+// Give a type.
+
+bool CAuto::SetType(ObjectType type)
+{
+ return false;
+}
+
+// Gives a value.
+
+bool CAuto::SetValue(int rank, float value)
+{
+ return false;
+}
+
+// Gives the string.
+
+bool CAuto::SetString(char *string)
+{
+ return false;
+}
+
+
+// Management of an event.
+
+bool CAuto::EventProcess(const Event &event)
+{
+ if ( event.event == EVENT_FRAME &&
+ !m_engine->RetPause() )
+ {
+ m_time += event.rTime;
+ UpdateInterface(event.rTime);
+ }
+
+ if ( !m_object->RetSelect() ) // robot not selected?
+ {
+ return true;
+ }
+
+ return true;
+}
+
+// Indicates whether the controller has finished its activity.
+
+Error CAuto::IsEnded()
+{
+ return ERR_CONTINUE;
+}
+
+// Stops the controller
+
+bool CAuto::Abort()
+{
+ return false;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAuto::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, dim, ddim;
+ float ox, oy, sx, sy;
+ char name[100];
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw != 0 )
+ {
+ pw->Flush(); // destroys the window buttons
+ m_interface->DeleteControl(EVENT_WINDOW0); // destroys the window
+ }
+
+ if ( !bSelect ) return true;
+
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ dim.x = 540.0f/640.0f;
+//? dim.y = 70.0f/480.0f;
+ dim.y = 86.0f/480.0f;
+ m_interface->CreateWindows(pos, dim, 3, EVENT_WINDOW0);
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ m_object->GetTooltipName(name);
+ pos.x = 0.0f;
+ pos.y = 64.0f/480.0f;
+ ddim.x = 540.0f/640.0f;
+ ddim.y = 16.0f/480.0f;
+ pw->CreateLabel(pos, ddim, 0, EVENT_LABEL0, name);
+
+ dim.x = 33.0f/640.0f;
+ dim.y = 33.0f/480.0f;
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*7.0f;
+ pos.y = oy+sy*0.6f;
+ ddim.x = 160.0f/640.0f;
+ ddim.y = 26.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GPROGRESS);
+
+ if ( m_type != OBJECT_BASE &&
+ m_type != OBJECT_SAFE &&
+ m_type != OBJECT_HUSTON )
+ {
+ pos.x = ox+sx*2.1f;
+ pos.y = oy+sy*0;
+ ddim.x = dim.x*0.6f;
+ ddim.y = dim.y*0.6f;
+ pw->CreateButton(pos, ddim, 12, EVENT_OBJECT_DELETE);
+ }
+
+#if 0
+ pos.x = ox+sx*12.4f;
+ pos.y = oy+sy*1;
+ pw->CreateButton(pos, dim, 63, EVENT_OBJECT_BHELP);
+
+ pos.x = ox+sx*12.4f;
+ pos.y = oy+sy*0;
+ pw->CreateButton(pos, dim, 19, EVENT_OBJECT_HELP);
+
+ if ( m_main->RetSceneSoluce() )
+ {
+ pos.x = ox+sx*13.4f;
+ pos.y = oy+sy*1;
+ pw->CreateButton(pos, dim, 20, EVENT_OBJECT_SOLUCE);
+ }
+
+ pos.x = ox+sx*13.4f;
+ pos.y = oy+sy*0;
+ pw->CreateButton(pos, dim, 10, EVENT_OBJECT_DESELECT);
+#else
+ pos.x = ox+sx*12.3f;
+ pos.y = oy+sy*-0.1f;
+ ddim.x = dim.x*1.0f;
+ ddim.y = dim.y*2.1f;
+ pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue background
+
+ pos.x = ox+sx*12.3f;
+ pos.y = oy+sy*1;
+ pw->CreateGroup(pos, dim, 19, EVENT_NULL); // sign SatCom
+
+ pos.x = ox+sx*12.4f;
+ pos.y = oy+sy*0.5f;
+ ddim.x = dim.x*0.8f;
+ ddim.y = dim.y*0.5f;
+ pw->CreateButton(pos, ddim, 18, EVENT_OBJECT_BHELP);
+ pos.y = oy+sy*0.0f;
+ pw->CreateButton(pos, ddim, 19, EVENT_OBJECT_HELP);
+
+ pos.x = ox+sx*13.4f;
+ pos.y = oy+sy*0;
+ pw->CreateButton(pos, dim, 10, EVENT_OBJECT_DESELECT);
+#endif
+
+ pos.x = ox+sx*14.9f;
+ pos.y = oy+sy*0;
+ ddim.x = 14.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 3, EVENT_OBJECT_GSHIELD);
+
+ UpdateInterface();
+ m_lastUpdateTime = 0.0f;
+ UpdateInterface(0.0f);
+
+ return true;
+}
+
+// Change the state of a button interface.
+
+void CAuto::CheckInterface(CWindow *pw, EventMsg event, bool bState)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_CHECK, bState);
+}
+
+// Change the state of a button interface.
+
+void CAuto::EnableInterface(CWindow *pw, EventMsg event, bool bState)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_ENABLE, bState);
+}
+
+// Change the state of a button interface.
+
+void CAuto::VisibleInterface(CWindow *pw, EventMsg event, bool bState)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_VISIBLE, bState);
+}
+
+// Change the state of a button interface.
+
+void CAuto::DeadInterface(CWindow *pw, EventMsg event, bool bState)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_DEAD, !bState);
+}
+
+// Change the state of a button interface.
+
+void CAuto::UpdateInterface()
+{
+ CWindow* pw;
+
+ if ( !m_object->RetSelect() ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ VisibleInterface(pw, EVENT_OBJECT_GPROGRESS, m_bBusy);
+}
+
+// Updates the state of all buttons on the interface,
+// following the time that elapses ...
+
+void CAuto::UpdateInterface(float rTime)
+{
+ CWindow* pw;
+ CGauge* pg;
+
+ if ( m_time < m_lastUpdateTime+0.1f ) return;
+ m_lastUpdateTime = m_time;
+
+ if ( !m_object->RetSelect() ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GSHIELD);
+ if ( pg != 0 )
+ {
+ pg->SetLevel(m_object->RetShield());
+ }
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GPROGRESS);
+ if ( pg != 0 )
+ {
+ pg->SetLevel(m_progressTime);
+ }
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAuto::RetError()
+{
+ return ERR_OK;
+}
+
+
+// Management of the occupation.
+
+bool CAuto::RetBusy()
+{
+ return m_bBusy;
+}
+
+void CAuto::SetBusy(bool bBusy)
+{
+ m_bBusy = bBusy;
+}
+
+void CAuto::InitProgressTotal(float total)
+{
+ m_progressTime = 0.0f;
+ m_progressTotal = total;
+}
+
+void CAuto::EventProgress(float rTime)
+{
+ m_progressTime += rTime/m_progressTotal;
+}
+
+
+// Engine management.
+
+bool CAuto::RetMotor()
+{
+ return m_bMotor;
+}
+
+void CAuto::SetMotor(bool bMotor)
+{
+ m_bMotor = bMotor;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAuto::Write(char *line)
+{
+ char name[100];
+
+ sprintf(name, " aType=%d", m_type);
+ strcat(line, name);
+
+ sprintf(name, " aBusy=%d", m_bBusy);
+ strcat(line, name);
+
+ sprintf(name, " aTime=%.2f", m_time);
+ strcat(line, name);
+
+ sprintf(name, " aProgressTime=%.2f", m_progressTime);
+ strcat(line, name);
+
+ sprintf(name, " aProgressTotal=%.2f", m_progressTotal);
+ strcat(line, name);
+
+ return false;
+}
+
+// Return all settings to the controller.
+
+bool CAuto::Read(char *line)
+{
+ m_type = (ObjectType)OpInt(line, "aType", OBJECT_NULL);
+ m_bBusy = OpInt(line, "aBusy", 0);
+ m_time = OpFloat(line, "aTime", 0.0f);
+ m_progressTime = OpFloat(line, "aProgressTime", 0.0f);
+ m_progressTotal = OpFloat(line, "aProgressTotal", 0.0f);
+
+ return false;
+}
+
diff --git a/src/object/auto/auto.h b/src/object/auto/auto.h
index 3928d28..09efdd9 100644
--- a/src/object/auto/auto.h
+++ b/src/object/auto/auto.h
@@ -1,111 +1,111 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// auto.h
-
-#pragma once
-
-
-#include "common/misc.h"
-#include "object/object.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CParticule;
-class CLight;
-class CTerrain;
-class CWater;
-class CCloud;
-class CPlanet;
-class CBlitz;
-class CCamera;
-class CInterface;
-class CRobotMain;
-class CDisplayText;
-class CWindow;
-class CSound;
-
-
-
-
-class CAuto
-{
-public:
- CAuto(CInstanceManager* iMan, CObject* object);
- virtual ~CAuto();
-
- virtual void DeleteObject(bool bAll=false);
-
- virtual void Init();
- virtual void Start(int param);
- virtual bool EventProcess(const Event &event);
- virtual Error IsEnded();
- virtual bool Abort();
-
- virtual bool SetType(ObjectType type);
- virtual bool SetValue(int rank, float value);
- virtual bool SetString(char *string);
-
- virtual bool CreateInterface(bool bSelect);
- virtual Error RetError();
-
- virtual bool RetBusy();
- virtual void SetBusy(bool bBuse);
- virtual void InitProgressTotal(float total);
- virtual void EventProgress(float rTime);
-
- virtual bool RetMotor();
- virtual void SetMotor(bool bMotor);
-
- virtual bool Write(char *line);
- virtual bool Read(char *line);
-
-protected:
- void CheckInterface(CWindow *pw, EventMsg event, bool bState);
- void EnableInterface(CWindow *pw, EventMsg event, bool bState);
- void VisibleInterface(CWindow *pw, EventMsg event, bool bState);
- void DeadInterface(CWindow *pw, EventMsg event, bool bState);
- void UpdateInterface();
- void UpdateInterface(float rTime);
-
-protected:
- CInstanceManager* m_iMan;
- CEvent* m_event;
- CD3DEngine* m_engine;
- CParticule* m_particule;
- CLight* m_light;
- CTerrain* m_terrain;
- CWater* m_water;
- CCloud * m_cloud;
- CPlanet * m_planet;
- CBlitz* m_blitz;
- CCamera* m_camera;
- CInterface* m_interface;
- CRobotMain* m_main;
- CDisplayText* m_displayText;
- CObject* m_object;
- CSound* m_sound;
-
- ObjectType m_type;
- bool m_bBusy;
- bool m_bMotor;
- float m_time;
- float m_lastUpdateTime;
- float m_progressTime;
- float m_progressTotal;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// auto.h
+
+#pragma once
+
+
+#include "common/misc.h"
+#include "object/object.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CParticule;
+class CLight;
+class CTerrain;
+class CWater;
+class CCloud;
+class CPlanet;
+class CBlitz;
+class CCamera;
+class CInterface;
+class CRobotMain;
+class CDisplayText;
+class CWindow;
+class CSound;
+
+
+
+
+class CAuto
+{
+public:
+ CAuto(CInstanceManager* iMan, CObject* object);
+ virtual ~CAuto();
+
+ virtual void DeleteObject(bool bAll=false);
+
+ virtual void Init();
+ virtual void Start(int param);
+ virtual bool EventProcess(const Event &event);
+ virtual Error IsEnded();
+ virtual bool Abort();
+
+ virtual bool SetType(ObjectType type);
+ virtual bool SetValue(int rank, float value);
+ virtual bool SetString(char *string);
+
+ virtual bool CreateInterface(bool bSelect);
+ virtual Error RetError();
+
+ virtual bool RetBusy();
+ virtual void SetBusy(bool bBuse);
+ virtual void InitProgressTotal(float total);
+ virtual void EventProgress(float rTime);
+
+ virtual bool RetMotor();
+ virtual void SetMotor(bool bMotor);
+
+ virtual bool Write(char *line);
+ virtual bool Read(char *line);
+
+protected:
+ void CheckInterface(CWindow *pw, EventMsg event, bool bState);
+ void EnableInterface(CWindow *pw, EventMsg event, bool bState);
+ void VisibleInterface(CWindow *pw, EventMsg event, bool bState);
+ void DeadInterface(CWindow *pw, EventMsg event, bool bState);
+ void UpdateInterface();
+ void UpdateInterface(float rTime);
+
+protected:
+ CInstanceManager* m_iMan;
+ CEvent* m_event;
+ CD3DEngine* m_engine;
+ CParticule* m_particule;
+ CLight* m_light;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CCloud * m_cloud;
+ CPlanet * m_planet;
+ CBlitz* m_blitz;
+ CCamera* m_camera;
+ CInterface* m_interface;
+ CRobotMain* m_main;
+ CDisplayText* m_displayText;
+ CObject* m_object;
+ CSound* m_sound;
+
+ ObjectType m_type;
+ bool m_bBusy;
+ bool m_bMotor;
+ float m_time;
+ float m_lastUpdateTime;
+ float m_progressTime;
+ float m_progressTotal;
+};
+
diff --git a/src/object/auto/autobase.cpp b/src/object/auto/autobase.cpp
index a13232f..19382b7 100644
--- a/src/object/auto/autobase.cpp
+++ b/src/object/auto/autobase.cpp
@@ -1,1441 +1,1441 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autobase.h"
-
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "old/cloud.h"
-#include "old/planet.h"
-#include "old/blitz.h"
-#include "math/geometry.h"
-#include "object/robotmain.h"
-#include "physics/physics.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-
-
-
-const float BASE_LAND_TIME = 7.5f; // hard landing
-const float BASE_TAKO_TIME = 10.0f; // hard landing
-const float BASE_DOOR_TIME = 6.0f; // time opening / closing
-const float BASE_DOOR_TIME2 = 2.0f; // time opening / closing suppl.
-const float BASE_PORTICO_TIME_MOVE = 16.0f; // gate advance time
-const float BASE_PORTICO_TIME_DOWN = 4.0f; // gate length down
-const float BASE_PORTICO_TIME_OPEN = 4.0f; // gate opening duration
-const float BASE_TRANSIT_TIME = 15.0f; // transit duration
-
-
-
-
-// Object's constructor.
-
-CAutoBase::CAutoBase(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- m_fogStart = m_engine->RetFogStart();
- m_deepView = m_engine->RetDeepView();
- Init();
- m_phase = ABP_WAIT;
- m_soundChannel = -1;
-}
-
-// Object's destructor.
-
-CAutoBase::~CAutoBase()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoBase::DeleteObject(bool bAll)
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoBase::Init()
-{
- m_bOpen = false;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- m_lastMotorParticule = 0.0f;
-
- m_pos = m_object->RetPosition(0);
- m_lastPos = m_pos;
-
- m_phase = ABP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-}
-
-
-// Start the object.
-
-void CAutoBase::Start(int param)
-{
- m_phase = ABP_START;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- m_param = param;
-}
-
-
-// Management of an event.
-
-bool CAutoBase::EventProcess(const Event &event)
-{
- Math::Matrix* mat;
- Event newEvent;
- CObject* pObj;
- Math::Vector pos, speed, vibCir, iPos;
- Math::Point dim, p;
- Error err;
- float angle, dist, time, h, len, vSpeed;
- int i, max;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
-
-begin:
- iPos = m_object->RetPosition(0);
-
- if ( m_phase == ABP_START )
- {
- if ( m_param != PARAM_STOP && // not placed on the ground?
- m_param != PARAM_FIXSCENE )
- {
- FreezeCargo(true); // freeze whole cargo
- }
-
- if ( m_param == PARAM_STOP ) // raises the ground?
- {
- m_phase = ABP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
- m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
- m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
- m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
- m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
- }
-
- pObj = m_main->RetSelectObject();
- m_main->SelectObject(pObj);
- m_camera->SetObject(pObj);
- if ( pObj == 0 )
- {
- m_camera->SetType(CAMERA_BACK);
- }
- else
- {
- m_camera->SetType(pObj->RetCameraType());
- m_camera->SetDist(pObj->RetCameraDist());
- }
-
- m_main->StartMusic();
- }
-
- if ( m_param == PARAM_FIXSCENE ) // raises the ground?
- {
- m_phase = ABP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
- m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
- m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
- m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
- m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
- }
- }
-
- if ( m_param == PARAM_LANDING ) // Landing?
- {
- m_phase = ABP_LAND;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_LAND_TIME;
-
- m_main->SetMovieLock(true); // blocks everything until the end of the landing
- m_bMotor = true; // lights the jet engine
-
- m_camera->SetType(CAMERA_SCRIPT);
-
- pos = m_pos;
- pos.x -= 150.0f;
- m_terrain->MoveOnFloor(pos);
- pos.y += 10.0f;
- m_camera->SetScriptEye(pos);
- m_posSound = pos;
-
- pos = m_object->RetPosition(0);
- pos.y += 300.0f+50.0f;
- m_camera->SetScriptLookat(pos);
-
- m_camera->FixCamera();
- m_engine->SetFocus(2.0f);
-
- m_engine->SetFogStart(0.9f);
-
- if ( m_soundChannel == -1 )
- {
- m_soundChannel = m_sound->Play(SOUND_FLY, m_posSound, 0.3f, 2.0f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, BASE_LAND_TIME, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 2.0f, SOPER_STOP);
- }
-
- m_main->StartMusic();
- }
-
- if ( m_param == PARAM_PORTICO ) // gate on the porch?
- {
- pos = m_object->RetPosition(0);
- m_finalPos = pos;
- pos.z += BASE_PORTICO_TIME_MOVE*5.0f; // back
- pos.y += 10.0f; // rises (the gate)
- m_object->SetPosition(0, pos);
- MoveCargo(); // all cargo moves
-
- m_phase = ABP_PORTICO_MOVE;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_PORTICO_TIME_MOVE;
-
- m_main->StartMusic();
- }
-
- if ( m_param == PARAM_TRANSIT1 ||
- m_param == PARAM_TRANSIT2 ||
- m_param == PARAM_TRANSIT3 ) // transit in space?
- {
- m_phase = ABP_TRANSIT_MOVE;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_TRANSIT_TIME;
-
- m_object->SetAngleZ(0, -Math::PI/2.0f);
- pos = m_object->RetPosition(0);
- pos.y += 10000.0f; // in space
- m_finalPos = pos;
- m_object->SetPosition(0, pos);
-
- m_main->SetMovieLock(true); // blocks everything until the end of the landing
- m_bMotor = true; // lights the jet engine
-
- m_camera->SetType(CAMERA_SCRIPT);
- pos.x += 1000.0f;
- pos.z -= 60.0f;
- pos.y += 80.0f;
- m_camera->SetScriptEye(pos);
- m_posSound = pos;
- m_camera->FixCamera();
- m_engine->SetFocus(1.0f);
-
- BeginTransit();
-
- mat = m_object->RetWorldMatrix(0);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 10.0f;
- dim.y = dim.x;
- pos = Math::Vector(42.0f, -2.0f, 17.0f);
- pos = Transform(*mat, pos);
- m_partiChannel[0] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
- pos = Math::Vector(17.0f, -2.0f, 42.0f);
- pos = Transform(*mat, pos);
- m_partiChannel[1] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
- pos = Math::Vector(42.0f, -2.0f, -17.0f);
- pos = Transform(*mat, pos);
- m_partiChannel[2] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
- pos = Math::Vector(17.0f, -2.0f, -42.0f);
- pos = Transform(*mat, pos);
- m_partiChannel[3] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
- pos = Math::Vector(-42.0f, -2.0f, 17.0f);
- pos = Transform(*mat, pos);
- m_partiChannel[4] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
- pos = Math::Vector(-17.0f, -2.0f, 42.0f);
- pos = Transform(*mat, pos);
- m_partiChannel[5] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
- pos = Math::Vector(-42.0f, -2.0f, -17.0f);
- pos = Transform(*mat, pos);
- m_partiChannel[6] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
- pos = Math::Vector(-17.0f, -2.0f, -42.0f);
- pos = Transform(*mat, pos);
- m_partiChannel[7] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
-
- if ( m_soundChannel == -1 )
- {
- m_soundChannel = m_sound->Play(SOUND_FLY, m_posSound, 0.0f, 1.2f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, BASE_TRANSIT_TIME*0.55f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.8f, BASE_TRANSIT_TIME*0.45f, SOPER_STOP);
- }
- }
- }
-
- if ( event.event == EVENT_UPDINTERFACE )
- {
- if ( m_object->RetSelect() ) CreateInterface(true);
- }
-
- if ( event.event == EVENT_OBJECT_BTAKEOFF )
- {
- err = CheckCloseDoor();
- if ( err != ERR_OK )
- {
- m_displayText->DisplayError(err, m_object);
- return false;
- }
-
- err = m_main->CheckEndMission(false);
- if ( err != ERR_OK )
- {
- m_displayText->DisplayError(err, m_object);
- return false;
- }
-
- FreezeCargo(true); // freeze whole cargo
- m_main->SetMovieLock(true); // blocks everything until the end
- m_main->DeselectAll();
-
- m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
- m_event->AddEvent(newEvent);
-
- m_camera->SetType(CAMERA_SCRIPT);
-
- pos = m_pos;
- pos.x -= 110.0f;
- m_terrain->MoveOnFloor(pos);
- pos.y += 10.0f;
- m_camera->SetScriptEye(pos);
- m_posSound = pos;
-
- pos = m_object->RetPosition(0);
- pos.y += 50.0f;
- m_camera->SetScriptLookat(pos);
-
- m_engine->SetFocus(1.0f);
-
- m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.3f, 1.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.5f, BASE_DOOR_TIME2, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.5f, 0.5f, SOPER_STOP);
-
- m_phase = ABP_CLOSE2;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_DOOR_TIME2;
- return true;
- }
-
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_phase == ABP_WAIT ) return true;
-
- m_progress += event.rTime*m_speed;
-
- if ( m_phase == ABP_LAND )
- {
- if ( m_progress < 1.0f )
- {
- pos = m_pos;
- pos.y += powf(1.0f-m_progress, 2.0f)*300.0f;
- m_object->SetPosition(0, pos);
- MoveCargo(); // all cargo moves
-
- vibCir.z = sinf(m_time*Math::PI* 2.01f)*(Math::PI/150.0f)+
- sinf(m_time*Math::PI* 2.51f)*(Math::PI/200.0f)+
- sinf(m_time*Math::PI*19.01f)*(Math::PI/400.0f);
- vibCir.x = sinf(m_time*Math::PI* 2.03f)*(Math::PI/150.0f)+
- sinf(m_time*Math::PI* 2.52f)*(Math::PI/200.0f)+
- sinf(m_time*Math::PI*19.53f)*(Math::PI/400.0f);
- vibCir.y = 0.0f;
- vibCir *= Math::Min(1.0f, (1.0f-m_progress)*3.0f);
- m_object->SetCirVibration(vibCir);
-
- pos = m_pos;
- pos.x -= 150.0f;
- m_terrain->MoveOnFloor(pos);
- pos.y += 10.0f;
- m_camera->SetScriptEye(pos);
-
- pos = m_object->RetPosition(0);
- pos.y += 50.0f;
- m_camera->SetScriptLookat(pos);
-
- m_engine->SetFocus(1.0f+(1.0f-m_progress));
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- // Dust thrown to the ground.
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- angle = Math::Rand()*(Math::PI*2.0f);
- dist = m_progress*50.0f;
- p = Math::RotatePoint(angle, dist);
- speed.x = p.x;
- speed.z = p.y;
- speed.y = 0.0f;
- dim.x = (Math::Rand()*15.0f+15.0f)*m_progress;
- dim.y = dim.x;
- if ( dim.x >= 1.0f )
- {
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 2.0f);
- }
-
- // Particles are ejected from the jet engine.
- pos = m_object->RetPosition(0);
- pos.y += 6.0f;
- h = m_terrain->RetFloorHeight(pos)/300.0f;
- speed.x = (Math::Rand()-0.5f)*(80.0f-50.0f*h);
- speed.z = (Math::Rand()-0.5f)*(80.0f-50.0f*h);
- speed.y = -(Math::Rand()*(h+1.0f)*40.0f+(h+1.0f)*40.0f);
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 2.0f, 10.0f, 2.0f);
-
- // Black smoke from the jet engine.
- if ( m_progress > 0.8f )
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*8.0f;
- pos.z += (Math::Rand()-0.5f)*8.0f;
- pos.y += 3.0f;
- speed.x = (Math::Rand()-0.5f)*8.0f;
- speed.z = (Math::Rand()-0.5f)*8.0f;
- speed.y = 0.0f;
- dim.x = Math::Rand()*4.0f+4.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 2.0f);
- }
- }
- }
- else
- {
- m_bMotor = false; // put out the reactor
-
- m_object->SetPosition(0, m_pos); // setting down
- m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- MoveCargo(); // all cargo moves
-
- // Impact with the ground.
- max = (int)(50.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<max ; i++ )
- {
- angle = Math::Rand()*(Math::PI*2.0f);
- p = Math::RotatePoint(angle, 46.0f);
- pos = m_pos;
- pos.x += p.x;
- pos.z += p.y;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*10.0f+10.0f;
- dim.y = dim.x;
- time = Math::Rand()*2.0f+1.5f;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, time, 0.0f, 2.0f);
- }
-
-//? m_camera->StartEffect(CE_CRASH, m_pos, 1.0f);
- m_camera->StartEffect(CE_EXPLO, m_pos, 2.0f);
- m_engine->SetFocus(1.0f);
- m_sound->Play(SOUND_BOUM, m_posSound, 0.6f, 0.5f);
-
- m_phase = ABP_OPENWAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == ABP_OPENWAIT )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- // Black smoke from the reactor.
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*8.0f;
- pos.z += (Math::Rand()-0.5f)*8.0f;
- pos.y += 3.0f;
- speed.x = (Math::Rand()-0.5f)*8.0f;
- speed.z = (Math::Rand()-0.5f)*8.0f;
- speed.y = 0.0f;
- dim.x = Math::Rand()*4.0f+4.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 2.0f);
- }
- }
- else
- {
- m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.0f, 0.3f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.3f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.0f, BASE_DOOR_TIME-1.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 1.0f, SOPER_STOP);
-
- m_phase = ABP_OPEN;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_DOOR_TIME;
- }
- }
-
- if ( m_phase == ABP_OPEN )
- {
- if ( m_progress < 1.0f )
- {
- angle = -m_progress*124.0f*Math::PI/180.0f;
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetAngleZ(1+i, Math::PI/2.0f+angle);
- }
-
- if ( m_param != PARAM_PORTICO )
- {
- angle = m_progress*Math::PI*2.0f;
- p = Math::RotatePoint(angle, -150.0f);
- pos = m_pos;
- pos.x += p.x;
- pos.z += p.y;
- m_terrain->MoveOnFloor(pos);
- pos.y += 10.0f;
- pos.y += m_progress*40.0f;
- m_camera->SetScriptEye(pos);
-
- m_engine->SetFogStart(0.9f-(0.9f-m_fogStart)*m_progress);
- }
- }
- else
- {
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
- }
-
- // Clash the doors with the ground.
- max = (int)(20.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<max ; i++ )
- {
- angle = Math::Rand()*(20.0f*Math::PI/180.0f)-(10.0f*Math::PI/180.0f);
- angle += (Math::PI/4.0f)*(rand()%8);
- p = Math::RotatePoint(angle, 74.0f);
- pos = m_pos;
- pos.x += p.x;
- pos.z += p.y;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*8.0f+8.0f;
- dim.y = dim.x;
- time = Math::Rand()*2.0f+1.5f;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, time, 0.0f, 2.0f);
- }
-
- m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.3f, 1.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.5f, BASE_DOOR_TIME2, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.5f, 0.5f, SOPER_STOP);
-
- m_phase = ABP_OPEN2;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_DOOR_TIME2;
- }
- }
-
- if ( m_phase == ABP_OPEN2 )
- {
- if ( m_progress < 1.0f )
- {
- len = 7.0f-m_progress*(7.0f+11.5f);
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, len));
- m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, -len));
- m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f*m_progress);
- m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f*m_progress);
- }
-
- if ( m_param != PARAM_PORTICO )
- {
- angle = m_progress*Math::PI/2.0f;
- p = Math::RotatePoint(angle, -150.0f);
- pos = m_pos;
- pos.x += p.x;
- pos.z += p.y;
- m_terrain->MoveOnFloor(pos);
- pos.y += 10.0f;
- pos.y += m_progress*40.0f;
- m_camera->SetScriptEye(pos);
-
- m_engine->SetFogStart(0.9f-(0.9f-m_fogStart)*m_progress);
- }
- }
- else
- {
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
- m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
- m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
- m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
- }
-
- m_phase = ABP_LDWAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ABP_LDWAIT )
- {
- if ( m_progress >= 1.0f )
- {
- FreezeCargo(false); // frees all cargo
-
- if ( m_param != PARAM_PORTICO )
- {
- m_main->SetMovieLock(false); // you can play!
-
- pObj = m_main->RetSelectObject();
- m_main->SelectObject(pObj);
- m_camera->SetObject(pObj);
- if ( pObj == 0 )
- {
- m_camera->SetType(CAMERA_BACK);
- }
- else
- {
- m_camera->SetType(pObj->RetCameraType());
- m_camera->SetDist(pObj->RetCameraDist());
- }
- m_sound->Play(SOUND_BOUM, m_object->RetPosition(0));
- m_soundChannel = -1;
-
- m_engine->SetFogStart(m_fogStart);
- }
-
- m_bOpen = true;
- m_phase = ABP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ABP_CLOSE2 )
- {
- if ( m_progress < 1.0f )
- {
- len = 7.0f-(1.0f-m_progress)*(7.0f+11.5f);
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, len));
- m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, -len));
- m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f*(1.0f-m_progress));
- m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f*(1.0f-m_progress));
- }
- }
- else
- {
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, 7.0f));
- m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, -7.0f));
- m_object->SetAngleX(10+i, 0.0f);
- m_object->SetAngleX(18+i, 0.0f);
- }
-
- m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.0f, 0.3f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.3f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.0f, BASE_DOOR_TIME-1.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 1.0f, SOPER_STOP);
-
- m_phase = ABP_CLOSE;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_DOOR_TIME;
- }
- }
-
- if ( m_phase == ABP_CLOSE )
- {
- if ( m_progress < 1.0f )
- {
- angle = -(1.0f-m_progress)*124.0f*Math::PI/180.0f;
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetAngleZ(1+i, Math::PI/2.0f+angle);
- }
- }
- else
- {
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetAngleZ(1+i, Math::PI/2.0f);
- }
- m_bMotor = true; // lights the jet engine
-
- // Shock of the closing doors.
- max = (int)(20.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<max ; i++ )
- {
- angle = Math::Rand()*Math::PI*2.0f;
- p = Math::RotatePoint(angle, 32.0f);
- pos = m_pos;
- pos.x += p.x;
- pos.z += p.y;
- pos.y += 85.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*3.0f+3.0f;
- dim.y = dim.x;
- time = Math::Rand()*1.0f+1.0f;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, time);
- }
- m_sound->Play(SOUND_BOUM, m_object->RetPosition(0));
-
- m_soundChannel = -1;
- m_bOpen = false;
- m_phase = ABP_TOWAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == ABP_TOWAIT )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_soundChannel == -1 )
- {
- m_soundChannel = m_sound->Play(SOUND_FLY, m_posSound, 0.0f, 0.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 2.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 2.0f, BASE_TAKO_TIME, SOPER_STOP);
- }
-
- vibCir.z = sinf(m_time*Math::PI*19.01f)*(Math::PI/400.0f);
- vibCir.x = sinf(m_time*Math::PI*19.53f)*(Math::PI/400.0f);
- vibCir.y = 0.0f;
- vibCir *= m_progress*1.0f;
- m_object->SetCirVibration(vibCir);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- // Particles are ejected from the reactor.
- pos = m_object->RetPosition(0);
- pos.y += 6.0f;
- speed.x = (Math::Rand()-0.5f)*160.0f;
- speed.z = (Math::Rand()-0.5f)*160.0f;
- speed.y = -(Math::Rand()*10.0f+10.0f);
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 2.0f, 10.0f, 2.0f);
- }
-
- m_engine->SetFogStart(m_fogStart+(0.9f-m_fogStart)*m_progress);
- }
- else
- {
- m_engine->SetFogStart(0.9f);
-
- m_phase = ABP_TAKEOFF;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_TAKO_TIME;
- }
- }
-
- if ( m_phase == ABP_TAKEOFF )
- {
- if ( m_progress < 1.0f )
- {
- pos = m_pos;
- pos.y += powf(m_progress, 2.0f)*600.0f;
- m_object->SetPosition(0, pos);
- MoveCargo(); // all cargo moves
-
- vibCir.z = sinf(m_time*Math::PI*19.01f)*(Math::PI/400.0f);
- vibCir.x = sinf(m_time*Math::PI*19.53f)*(Math::PI/400.0f);
- vibCir.y = 0.0f;
- m_object->SetCirVibration(vibCir);
-
- pos = m_pos;
- pos.x -= 110.0f+m_progress*250.0f;
- m_terrain->MoveOnFloor(pos);
- pos.y += 10.0f;
- m_camera->SetScriptEye(pos);
-
- pos = m_object->RetPosition(0);
- pos.y += 50.0f;
- m_camera->SetScriptLookat(pos);
-
- m_engine->SetFocus(1.0f+m_progress);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- // Dust thrown to the ground.
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- angle = Math::Rand()*(Math::PI*2.0f);
- dist = (1.0f-m_progress)*50.0f;
- p = Math::RotatePoint(angle, dist);
- speed.x = p.x;
- speed.z = p.y;
- speed.y = 0.0f;
- dim.x = (Math::Rand()*10.0f+10.0f)*(1.0f-m_progress);
- dim.y = dim.x;
- if ( dim.x >= 1.0f )
- {
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 2.0f);
- }
-
- // Particles are ejected from the reactor.
- pos = m_object->RetPosition(0);
- pos.y += 6.0f;
- speed.x = (Math::Rand()-0.5f)*40.0f;
- speed.z = (Math::Rand()-0.5f)*40.0f;
- time = 5.0f+150.0f*m_progress;
- speed.y = -(Math::Rand()*time+time);
- time = 2.0f+m_progress*12.0f;
- dim.x = Math::Rand()*time+time;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 2.0f, 10.0f, 2.0f);
-
- // Black smoke from the reactor.
- pos = m_object->RetPosition(0);
- pos.y += 3.0f;
- speed.x = (Math::Rand()-0.5f)*10.0f*(4.0f-m_progress*3.0f);
- speed.z = (Math::Rand()-0.5f)*10.0f*(4.0f-m_progress*3.0f);
- speed.y = 0.0f;
- dim.x = Math::Rand()*20.0f+20.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 10.0f, 0.0f, 2.0f);
- }
- }
- else
- {
- m_soundChannel = -1;
- m_event->MakeEvent(newEvent, EVENT_WIN);
- m_event->AddEvent(newEvent);
-
- m_phase = ABP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == ABP_PORTICO_MOVE ) // advance of the gate?
- {
- if ( m_progress < 1.0f )
- {
- pos = m_object->RetPosition(0);
- pos.z -= event.rTime*5.0f;
- m_object->SetPosition(0, pos);
- MoveCargo(); // all cargo moves
- }
- else
- {
- m_phase = ABP_PORTICO_WAIT1;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ABP_PORTICO_WAIT1 ) // expectation the gate?
- {
- if ( m_progress >= 1.0f )
- {
- m_phase = ABP_PORTICO_DOWN;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_PORTICO_TIME_DOWN;
- }
- }
-
- if ( m_phase == ABP_PORTICO_DOWN ) // down the gate?
- {
- if ( m_progress < 1.0f )
- {
- pos = m_object->RetPosition(0);
- pos.y -= event.rTime*(10.0f/BASE_PORTICO_TIME_DOWN);
- m_object->SetPosition(0, pos);
- MoveCargo(); // all cargo moves
- }
- else
- {
- // Impact with the ground.
- max = (int)(50.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<max ; i++ )
- {
- angle = Math::Rand()*(Math::PI*2.0f);
- p = Math::RotatePoint(angle, 46.0f);
- pos = m_pos;
- pos.x += p.x;
- pos.z += p.y;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*10.0f+10.0f;
- dim.y = dim.x;
- time = Math::Rand()*2.0f+1.5f;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, time, 0.0f, 2.0f);
- }
-
- m_phase = ABP_PORTICO_WAIT2;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ABP_PORTICO_WAIT2 ) // expectation the gate?
- {
- if ( m_progress >= 1.0f )
- {
- m_phase = ABP_PORTICO_OPEN;
- m_progress = 0.0f;
- m_speed = 1.0f/BASE_PORTICO_TIME_OPEN;
- }
- }
-
- if ( m_phase == ABP_PORTICO_OPEN ) // opening the gate?
- {
- if ( m_progress < 1.0f )
- {
- }
- else
- {
- m_phase = ABP_OPEN;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == ABP_TRANSIT_MOVE ) // transit in space?
- {
- if ( m_progress < 1.0f )
- {
- pos = m_object->RetPosition(0);
- pos.x += event.rTime*(2000.0f/BASE_TRANSIT_TIME);
- m_object->SetPosition(0, pos);
- pos.x += 60.0f;
- m_camera->SetScriptLookat(pos);
- }
- else
- {
- m_object->SetAngleZ(0, 0.0f);
-
- m_param = PARAM_LANDING;
- m_phase = ABP_START;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- EndTransit();
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.8f, 0.01f, SOPER_STOP);
- m_soundChannel = -1;
- }
- goto begin;
- }
- }
-
- if ( m_bMotor )
- {
- if ( m_lastMotorParticule+m_engine->ParticuleAdapt(0.02f) <= m_time )
- {
- m_lastMotorParticule = m_time;
-
- mat = m_object->RetWorldMatrix(0);
-
- if ( event.rTime == 0.0f )
- {
- vSpeed = 0.0f;
- }
- else
- {
- pos = m_object->RetPosition(0);
- if ( m_phase == ABP_TRANSIT_MOVE )
- {
- vSpeed = (pos.x-iPos.x)/event.rTime;
- }
- else
- {
- vSpeed = (pos.y-iPos.y)/event.rTime;
- }
- if ( vSpeed < 0.0f ) vSpeed *= 1.5f;
- }
-
- pos = Math::Vector(0.0f, 6.0f, 0.0f);
- speed.x = (Math::Rand()-0.5f)*4.0f;
- speed.z = (Math::Rand()-0.5f)*4.0f;
- speed.y = vSpeed*0.8f-(8.0f+Math::Rand()*6.0f);
- speed += pos;
- pos = Transform(*mat, pos);
- speed = Transform(*mat, speed);
- speed -= pos;
-
- dim.x = 4.0f+Math::Rand()*4.0f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIBASE, 3.0f, 0.0f, 0.0f);
-
- if ( m_phase == ABP_TRANSIT_MOVE )
- {
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 12.0f;
- dim.y = dim.x;
- pos = Math::Vector(0.0f, 7.0f, 0.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 1.0f, 0.0f, 0.0f);
-
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 4.0f;
- dim.y = dim.x;
- pos = Math::Vector(42.0f, 0.0f, 17.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
- pos = Math::Vector(17.0f, 0.0f, 42.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
- pos = Math::Vector(42.0f, 0.0f, -17.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
- pos = Math::Vector(17.0f, 0.0f, -42.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
- pos = Math::Vector(-42.0f, 0.0f, 17.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
- pos = Math::Vector(-17.0f, 0.0f, 42.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
- pos = Math::Vector(-42.0f, 0.0f, -17.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
- pos = Math::Vector(-17.0f, 0.0f, -42.0f);
- pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
- pos = Transform(*mat, pos);
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
-
- pos = Math::Vector(42.0f, -2.0f, 17.0f);
- pos = Transform(*mat, pos);
- m_particule->SetPosition(m_partiChannel[0], pos);
- pos = Math::Vector(17.0f, -2.0f, 42.0f);
- pos = Transform(*mat, pos);
- m_particule->SetPosition(m_partiChannel[1], pos);
- pos = Math::Vector(42.0f, -2.0f, -17.0f);
- pos = Transform(*mat, pos);
- m_particule->SetPosition(m_partiChannel[2], pos);
- pos = Math::Vector(17.0f, -2.0f, -42.0f);
- pos = Transform(*mat, pos);
- m_particule->SetPosition(m_partiChannel[3], pos);
- pos = Math::Vector(-42.0f, -2.0f, 17.0f);
- pos = Transform(*mat, pos);
- m_particule->SetPosition(m_partiChannel[4], pos);
- pos = Math::Vector(-17.0f, -2.0f, 42.0f);
- pos = Transform(*mat, pos);
- m_particule->SetPosition(m_partiChannel[5], pos);
- pos = Math::Vector(-42.0f, -2.0f, -17.0f);
- pos = Transform(*mat, pos);
- m_particule->SetPosition(m_partiChannel[6], pos);
- pos = Math::Vector(-17.0f, -2.0f, -42.0f);
- pos = Transform(*mat, pos);
- m_particule->SetPosition(m_partiChannel[7], pos);
- }
- }
- }
-
- if ( m_soundChannel != -1 )
- {
- pos = m_engine->RetEyePt();
- m_sound->Position(m_soundChannel, pos);
- }
-
- return true;
-}
-
-// Stops the controller.
-
-bool CAutoBase::Abort()
-{
- Event newEvent;
- CObject* pObj;
- int i;
-
- if ( m_phase == ABP_TRANSIT_MOVE ) // transit ?
- {
- m_object->SetAngleZ(0, 0.0f);
-
- m_param = PARAM_LANDING;
- m_phase = ABP_START;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- EndTransit();
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.8f, 0.01f, SOPER_STOP);
- m_soundChannel = -1;
- }
- return true;
- }
-
- if ( m_param == PARAM_PORTICO ) // gate on the porch?
- {
- m_object->SetPosition(0, m_finalPos);
- MoveCargo(); // all cargo moves
-
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
- m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
- m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
- m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
- m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
- }
- }
- else
- {
- if ( m_phase == ABP_LAND ||
- m_phase == ABP_OPENWAIT ||
- m_phase == ABP_OPEN ||
- m_phase == ABP_OPEN2 ) // Landing?
- {
- m_bMotor = false; // put out the jet engine
- m_bOpen = true;
-
- m_object->SetPosition(0, m_pos); // setting down
- m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- MoveCargo(); // all cargo moves
- for ( i=0 ; i<8 ; i++ )
- {
- m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
- m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
- m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
- m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
- m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
- }
-
- m_main->SetMovieLock(false); // you can play!
-
- pObj = m_main->RetSelectObject();
- m_main->SelectObject(pObj);
- m_camera->SetObject(pObj);
- if ( pObj == 0 )
- {
- m_camera->SetType(CAMERA_BACK);
- }
- else
- {
- m_camera->SetType(pObj->RetCameraType());
- m_camera->SetDist(pObj->RetCameraDist());
- }
-
- m_engine->SetFogStart(m_fogStart);
- }
-
- if ( m_phase == ABP_CLOSE2 ||
- m_phase == ABP_CLOSE ||
- m_phase == ABP_TOWAIT ||
- m_phase == ABP_TAKEOFF ) // off?
- {
- m_event->MakeEvent(newEvent, EVENT_WIN);
- m_event->AddEvent(newEvent);
- }
- }
-
- m_object->SetAngleZ(0, 0.0f);
- FreezeCargo(false); // frees all cargo
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- m_phase = ABP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoBase::RetError()
-{
- return ERR_OK;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoBase::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, dim, ddim;
- float ox, oy, sx, sy;
- float sleep, delay, magnetic, progress;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- dim.x = 33.0f/640.0f;
- dim.y = 33.0f/480.0f;
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- ddim.x = dim.x*1.5f;
- ddim.y = dim.y*1.5f;
-
-//? pos.x = ox+sx*7.25f;
-//? pos.y = oy+sy*0.25f;
-//? pw->CreateButton(pos, ddim, 63, EVENT_OBJECT_BHELP);
-
- pos.x = ox+sx*8.00f;
- pos.y = oy+sy*0.25f;
- pw->CreateButton(pos, ddim, 28, EVENT_OBJECT_BTAKEOFF);
-
- if ( m_blitz->GetStatus(sleep, delay, magnetic, progress) )
- {
- pos.x = ox+sx*10.2f;
- pos.y = oy+sy*0.5f;
- ddim.x = dim.x*1.0f;
- ddim.y = dim.y*1.0f;
- pw->CreateButton(pos, ddim, 41, EVENT_OBJECT_LIMIT);
- }
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 100, EVENT_OBJECT_TYPE);
-
- UpdateInterface();
-
- return true;
-}
-
-// Updates the status of all interface buttons.
-
-void CAutoBase::UpdateInterface()
-{
- CWindow* pw;
-
- if ( !m_object->RetSelect() ) return;
-
- CAuto::UpdateInterface();
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
-}
-
-
-// Freeze or frees all cargo.
-
-void CAutoBase::FreezeCargo(bool bFreeze)
-{
- CObject* pObj;
- CPhysics* physics;
- Math::Vector oPos;
- float dist;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- pObj->SetCargo(false);
-
- if ( pObj == m_object ) continue; // yourself?
- if ( pObj->RetTruck() != 0 ) continue; // transport object?
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(m_pos, oPos);
- if ( dist < 32.0f )
- {
- if ( bFreeze )
- {
- pObj->SetCargo(true);
- }
-
- physics = pObj->RetPhysics();
- if ( physics != 0 )
- {
- physics->SetFreeze(bFreeze);
- }
- }
- }
-}
-
-// All cargo moves vertically with the ship.
-
-void CAutoBase::MoveCargo()
-{
- CObject* pObj;
- Math::Vector oPos, sPos;
- int i;
-
- sPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetCargo() ) continue;
-
- oPos = pObj->RetPosition(0);
- oPos.y = sPos.y+30.0f;
- oPos.y += pObj->RetCharacter()->height;
- oPos.x += sPos.x-m_lastPos.x;
- oPos.z += sPos.z-m_lastPos.z;
- pObj->SetPosition(0, oPos);
- }
-
- m_lastPos = sPos;
-}
-
-
-// Checks whether it is possible to close the doors.
-
-Error CAutoBase::CheckCloseDoor()
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- float oRad, dist;
- int i, j;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue; // yourself?
- if ( !pObj->RetActif() ) continue; // inactive?
-
- type = pObj->RetType();
- if ( type == OBJECT_PORTICO ) continue;
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRad) )
- {
- dist = Math::DistanceProjected(m_pos, oPos);
- if ( dist+oRad > 32.0f &&
- dist-oRad < 72.0f )
- {
- return ERR_BASE_DLOCK;
- }
-
- if ( type == OBJECT_HUMAN &&
- dist+oRad > 32.0f )
- {
- return ERR_BASE_DHUMAN;
- }
- }
- }
- return ERR_OK;
-}
-
-
-// Start a transit.
-
-void CAutoBase::BeginTransit()
-{
- bool bFull, bQuarter;
-
- if ( m_param == PARAM_TRANSIT2 )
- {
- strcpy(m_bgBack, "back01.tga"); // clouds orange / blue
- }
- else if ( m_param == PARAM_TRANSIT3 )
- {
- strcpy(m_bgBack, "back22.tga"); // blueberries clouds
- }
- else
- {
-#if _DEMO
- strcpy(m_bgBack, "back46b.tga"); // paintings
-#else
- strcpy(m_bgBack, "back46.tga"); // paintings
-#endif
- }
-
- m_engine->SetFogStart(0.9f); // hardly any fog
- m_engine->SetDeepView(2000.0f); // we see very far
- m_engine->ApplyChange();
-
- m_engine->RetBackground(m_bgName, m_bgUp, m_bgDown, m_bgCloudUp, m_bgCloudDown, bFull, bQuarter);
- m_engine->FreeTexture(m_bgName);
-
- m_engine->SetBackground(m_bgBack, 0x00000000, 0x00000000, 0x00000000, 0x00000000);
- m_engine->LoadTexture(m_bgBack);
-
- m_cloud->SetEnable(false); // cache clouds
- m_planet->SetMode(1);
-}
-
-// End of a transit.
-
-void CAutoBase::EndTransit()
-{
- m_engine->SetFogStart(m_fogStart); // gives initial fog
- m_engine->SetDeepView(m_deepView); // gives initial depth
- m_engine->ApplyChange();
-
- m_engine->FreeTexture(m_bgBack);
-
- m_engine->SetBackground(m_bgName, m_bgUp, m_bgDown, m_bgCloudUp, m_bgCloudDown);
- m_engine->LoadTexture(m_bgName);
-
- m_cloud->SetEnable(true); // gives the clouds
- m_planet->SetMode(0);
-
- m_main->StartMusic();
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autobase.h"
+
+#include "common/iman.h"
+#include "old/terrain.h"
+#include "old/cloud.h"
+#include "old/planet.h"
+#include "old/blitz.h"
+#include "math/geometry.h"
+#include "object/robotmain.h"
+#include "physics/physics.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+
+
+
+const float BASE_LAND_TIME = 7.5f; // hard landing
+const float BASE_TAKO_TIME = 10.0f; // hard landing
+const float BASE_DOOR_TIME = 6.0f; // time opening / closing
+const float BASE_DOOR_TIME2 = 2.0f; // time opening / closing suppl.
+const float BASE_PORTICO_TIME_MOVE = 16.0f; // gate advance time
+const float BASE_PORTICO_TIME_DOWN = 4.0f; // gate length down
+const float BASE_PORTICO_TIME_OPEN = 4.0f; // gate opening duration
+const float BASE_TRANSIT_TIME = 15.0f; // transit duration
+
+
+
+
+// Object's constructor.
+
+CAutoBase::CAutoBase(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ m_fogStart = m_engine->RetFogStart();
+ m_deepView = m_engine->RetDeepView();
+ Init();
+ m_phase = ABP_WAIT;
+ m_soundChannel = -1;
+}
+
+// Object's destructor.
+
+CAutoBase::~CAutoBase()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoBase::DeleteObject(bool bAll)
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoBase::Init()
+{
+ m_bOpen = false;
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+ m_lastMotorParticule = 0.0f;
+
+ m_pos = m_object->RetPosition(0);
+ m_lastPos = m_pos;
+
+ m_phase = ABP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+}
+
+
+// Start the object.
+
+void CAutoBase::Start(int param)
+{
+ m_phase = ABP_START;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ m_param = param;
+}
+
+
+// Management of an event.
+
+bool CAutoBase::EventProcess(const Event &event)
+{
+ Math::Matrix* mat;
+ Event newEvent;
+ CObject* pObj;
+ Math::Vector pos, speed, vibCir, iPos;
+ Math::Point dim, p;
+ Error err;
+ float angle, dist, time, h, len, vSpeed;
+ int i, max;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+
+begin:
+ iPos = m_object->RetPosition(0);
+
+ if ( m_phase == ABP_START )
+ {
+ if ( m_param != PARAM_STOP && // not placed on the ground?
+ m_param != PARAM_FIXSCENE )
+ {
+ FreezeCargo(true); // freeze whole cargo
+ }
+
+ if ( m_param == PARAM_STOP ) // raises the ground?
+ {
+ m_phase = ABP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
+ m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
+ m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
+ m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
+ m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
+ }
+
+ pObj = m_main->RetSelectObject();
+ m_main->SelectObject(pObj);
+ m_camera->SetObject(pObj);
+ if ( pObj == 0 )
+ {
+ m_camera->SetType(CAMERA_BACK);
+ }
+ else
+ {
+ m_camera->SetType(pObj->RetCameraType());
+ m_camera->SetDist(pObj->RetCameraDist());
+ }
+
+ m_main->StartMusic();
+ }
+
+ if ( m_param == PARAM_FIXSCENE ) // raises the ground?
+ {
+ m_phase = ABP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
+ m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
+ m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
+ m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
+ m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
+ }
+ }
+
+ if ( m_param == PARAM_LANDING ) // Landing?
+ {
+ m_phase = ABP_LAND;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_LAND_TIME;
+
+ m_main->SetMovieLock(true); // blocks everything until the end of the landing
+ m_bMotor = true; // lights the jet engine
+
+ m_camera->SetType(CAMERA_SCRIPT);
+
+ pos = m_pos;
+ pos.x -= 150.0f;
+ m_terrain->MoveOnFloor(pos);
+ pos.y += 10.0f;
+ m_camera->SetScriptEye(pos);
+ m_posSound = pos;
+
+ pos = m_object->RetPosition(0);
+ pos.y += 300.0f+50.0f;
+ m_camera->SetScriptLookat(pos);
+
+ m_camera->FixCamera();
+ m_engine->SetFocus(2.0f);
+
+ m_engine->SetFogStart(0.9f);
+
+ if ( m_soundChannel == -1 )
+ {
+ m_soundChannel = m_sound->Play(SOUND_FLY, m_posSound, 0.3f, 2.0f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, BASE_LAND_TIME, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 2.0f, SOPER_STOP);
+ }
+
+ m_main->StartMusic();
+ }
+
+ if ( m_param == PARAM_PORTICO ) // gate on the porch?
+ {
+ pos = m_object->RetPosition(0);
+ m_finalPos = pos;
+ pos.z += BASE_PORTICO_TIME_MOVE*5.0f; // back
+ pos.y += 10.0f; // rises (the gate)
+ m_object->SetPosition(0, pos);
+ MoveCargo(); // all cargo moves
+
+ m_phase = ABP_PORTICO_MOVE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_PORTICO_TIME_MOVE;
+
+ m_main->StartMusic();
+ }
+
+ if ( m_param == PARAM_TRANSIT1 ||
+ m_param == PARAM_TRANSIT2 ||
+ m_param == PARAM_TRANSIT3 ) // transit in space?
+ {
+ m_phase = ABP_TRANSIT_MOVE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_TRANSIT_TIME;
+
+ m_object->SetAngleZ(0, -Math::PI/2.0f);
+ pos = m_object->RetPosition(0);
+ pos.y += 10000.0f; // in space
+ m_finalPos = pos;
+ m_object->SetPosition(0, pos);
+
+ m_main->SetMovieLock(true); // blocks everything until the end of the landing
+ m_bMotor = true; // lights the jet engine
+
+ m_camera->SetType(CAMERA_SCRIPT);
+ pos.x += 1000.0f;
+ pos.z -= 60.0f;
+ pos.y += 80.0f;
+ m_camera->SetScriptEye(pos);
+ m_posSound = pos;
+ m_camera->FixCamera();
+ m_engine->SetFocus(1.0f);
+
+ BeginTransit();
+
+ mat = m_object->RetWorldMatrix(0);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 10.0f;
+ dim.y = dim.x;
+ pos = Math::Vector(42.0f, -2.0f, 17.0f);
+ pos = Transform(*mat, pos);
+ m_partiChannel[0] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
+ pos = Math::Vector(17.0f, -2.0f, 42.0f);
+ pos = Transform(*mat, pos);
+ m_partiChannel[1] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
+ pos = Math::Vector(42.0f, -2.0f, -17.0f);
+ pos = Transform(*mat, pos);
+ m_partiChannel[2] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
+ pos = Math::Vector(17.0f, -2.0f, -42.0f);
+ pos = Transform(*mat, pos);
+ m_partiChannel[3] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
+ pos = Math::Vector(-42.0f, -2.0f, 17.0f);
+ pos = Transform(*mat, pos);
+ m_partiChannel[4] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
+ pos = Math::Vector(-17.0f, -2.0f, 42.0f);
+ pos = Transform(*mat, pos);
+ m_partiChannel[5] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
+ pos = Math::Vector(-42.0f, -2.0f, -17.0f);
+ pos = Transform(*mat, pos);
+ m_partiChannel[6] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
+ pos = Math::Vector(-17.0f, -2.0f, -42.0f);
+ pos = Transform(*mat, pos);
+ m_partiChannel[7] = m_particule->CreateParticule(pos, speed, dim, PARTILENS1, BASE_TRANSIT_TIME+1.0f, 0.0f, 0.0f);
+
+ if ( m_soundChannel == -1 )
+ {
+ m_soundChannel = m_sound->Play(SOUND_FLY, m_posSound, 0.0f, 1.2f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, BASE_TRANSIT_TIME*0.55f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.8f, BASE_TRANSIT_TIME*0.45f, SOPER_STOP);
+ }
+ }
+ }
+
+ if ( event.event == EVENT_UPDINTERFACE )
+ {
+ if ( m_object->RetSelect() ) CreateInterface(true);
+ }
+
+ if ( event.event == EVENT_OBJECT_BTAKEOFF )
+ {
+ err = CheckCloseDoor();
+ if ( err != ERR_OK )
+ {
+ m_displayText->DisplayError(err, m_object);
+ return false;
+ }
+
+ err = m_main->CheckEndMission(false);
+ if ( err != ERR_OK )
+ {
+ m_displayText->DisplayError(err, m_object);
+ return false;
+ }
+
+ FreezeCargo(true); // freeze whole cargo
+ m_main->SetMovieLock(true); // blocks everything until the end
+ m_main->DeselectAll();
+
+ m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
+ m_event->AddEvent(newEvent);
+
+ m_camera->SetType(CAMERA_SCRIPT);
+
+ pos = m_pos;
+ pos.x -= 110.0f;
+ m_terrain->MoveOnFloor(pos);
+ pos.y += 10.0f;
+ m_camera->SetScriptEye(pos);
+ m_posSound = pos;
+
+ pos = m_object->RetPosition(0);
+ pos.y += 50.0f;
+ m_camera->SetScriptLookat(pos);
+
+ m_engine->SetFocus(1.0f);
+
+ m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.3f, 1.5f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.5f, BASE_DOOR_TIME2, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.5f, 0.5f, SOPER_STOP);
+
+ m_phase = ABP_CLOSE2;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_DOOR_TIME2;
+ return true;
+ }
+
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_phase == ABP_WAIT ) return true;
+
+ m_progress += event.rTime*m_speed;
+
+ if ( m_phase == ABP_LAND )
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos = m_pos;
+ pos.y += powf(1.0f-m_progress, 2.0f)*300.0f;
+ m_object->SetPosition(0, pos);
+ MoveCargo(); // all cargo moves
+
+ vibCir.z = sinf(m_time*Math::PI* 2.01f)*(Math::PI/150.0f)+
+ sinf(m_time*Math::PI* 2.51f)*(Math::PI/200.0f)+
+ sinf(m_time*Math::PI*19.01f)*(Math::PI/400.0f);
+ vibCir.x = sinf(m_time*Math::PI* 2.03f)*(Math::PI/150.0f)+
+ sinf(m_time*Math::PI* 2.52f)*(Math::PI/200.0f)+
+ sinf(m_time*Math::PI*19.53f)*(Math::PI/400.0f);
+ vibCir.y = 0.0f;
+ vibCir *= Math::Min(1.0f, (1.0f-m_progress)*3.0f);
+ m_object->SetCirVibration(vibCir);
+
+ pos = m_pos;
+ pos.x -= 150.0f;
+ m_terrain->MoveOnFloor(pos);
+ pos.y += 10.0f;
+ m_camera->SetScriptEye(pos);
+
+ pos = m_object->RetPosition(0);
+ pos.y += 50.0f;
+ m_camera->SetScriptLookat(pos);
+
+ m_engine->SetFocus(1.0f+(1.0f-m_progress));
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ // Dust thrown to the ground.
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ angle = Math::Rand()*(Math::PI*2.0f);
+ dist = m_progress*50.0f;
+ p = Math::RotatePoint(angle, dist);
+ speed.x = p.x;
+ speed.z = p.y;
+ speed.y = 0.0f;
+ dim.x = (Math::Rand()*15.0f+15.0f)*m_progress;
+ dim.y = dim.x;
+ if ( dim.x >= 1.0f )
+ {
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 2.0f);
+ }
+
+ // Particles are ejected from the jet engine.
+ pos = m_object->RetPosition(0);
+ pos.y += 6.0f;
+ h = m_terrain->RetFloorHeight(pos)/300.0f;
+ speed.x = (Math::Rand()-0.5f)*(80.0f-50.0f*h);
+ speed.z = (Math::Rand()-0.5f)*(80.0f-50.0f*h);
+ speed.y = -(Math::Rand()*(h+1.0f)*40.0f+(h+1.0f)*40.0f);
+ dim.x = Math::Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 2.0f, 10.0f, 2.0f);
+
+ // Black smoke from the jet engine.
+ if ( m_progress > 0.8f )
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*8.0f;
+ pos.z += (Math::Rand()-0.5f)*8.0f;
+ pos.y += 3.0f;
+ speed.x = (Math::Rand()-0.5f)*8.0f;
+ speed.z = (Math::Rand()-0.5f)*8.0f;
+ speed.y = 0.0f;
+ dim.x = Math::Rand()*4.0f+4.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 2.0f);
+ }
+ }
+ }
+ else
+ {
+ m_bMotor = false; // put out the reactor
+
+ m_object->SetPosition(0, m_pos); // setting down
+ m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ MoveCargo(); // all cargo moves
+
+ // Impact with the ground.
+ max = (int)(50.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<max ; i++ )
+ {
+ angle = Math::Rand()*(Math::PI*2.0f);
+ p = Math::RotatePoint(angle, 46.0f);
+ pos = m_pos;
+ pos.x += p.x;
+ pos.z += p.y;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*10.0f+10.0f;
+ dim.y = dim.x;
+ time = Math::Rand()*2.0f+1.5f;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, time, 0.0f, 2.0f);
+ }
+
+//? m_camera->StartEffect(CE_CRASH, m_pos, 1.0f);
+ m_camera->StartEffect(CE_EXPLO, m_pos, 2.0f);
+ m_engine->SetFocus(1.0f);
+ m_sound->Play(SOUND_BOUM, m_posSound, 0.6f, 0.5f);
+
+ m_phase = ABP_OPENWAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == ABP_OPENWAIT )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ // Black smoke from the reactor.
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*8.0f;
+ pos.z += (Math::Rand()-0.5f)*8.0f;
+ pos.y += 3.0f;
+ speed.x = (Math::Rand()-0.5f)*8.0f;
+ speed.z = (Math::Rand()-0.5f)*8.0f;
+ speed.y = 0.0f;
+ dim.x = Math::Rand()*4.0f+4.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 2.0f);
+ }
+ }
+ else
+ {
+ m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.0f, 0.3f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.3f, 1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.0f, BASE_DOOR_TIME-1.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 1.0f, SOPER_STOP);
+
+ m_phase = ABP_OPEN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_DOOR_TIME;
+ }
+ }
+
+ if ( m_phase == ABP_OPEN )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = -m_progress*124.0f*Math::PI/180.0f;
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, Math::PI/2.0f+angle);
+ }
+
+ if ( m_param != PARAM_PORTICO )
+ {
+ angle = m_progress*Math::PI*2.0f;
+ p = Math::RotatePoint(angle, -150.0f);
+ pos = m_pos;
+ pos.x += p.x;
+ pos.z += p.y;
+ m_terrain->MoveOnFloor(pos);
+ pos.y += 10.0f;
+ pos.y += m_progress*40.0f;
+ m_camera->SetScriptEye(pos);
+
+ m_engine->SetFogStart(0.9f-(0.9f-m_fogStart)*m_progress);
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
+ }
+
+ // Clash the doors with the ground.
+ max = (int)(20.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<max ; i++ )
+ {
+ angle = Math::Rand()*(20.0f*Math::PI/180.0f)-(10.0f*Math::PI/180.0f);
+ angle += (Math::PI/4.0f)*(rand()%8);
+ p = Math::RotatePoint(angle, 74.0f);
+ pos = m_pos;
+ pos.x += p.x;
+ pos.z += p.y;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*8.0f+8.0f;
+ dim.y = dim.x;
+ time = Math::Rand()*2.0f+1.5f;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, time, 0.0f, 2.0f);
+ }
+
+ m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.3f, 1.5f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.5f, BASE_DOOR_TIME2, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.5f, 0.5f, SOPER_STOP);
+
+ m_phase = ABP_OPEN2;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_DOOR_TIME2;
+ }
+ }
+
+ if ( m_phase == ABP_OPEN2 )
+ {
+ if ( m_progress < 1.0f )
+ {
+ len = 7.0f-m_progress*(7.0f+11.5f);
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, len));
+ m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, -len));
+ m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f*m_progress);
+ m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f*m_progress);
+ }
+
+ if ( m_param != PARAM_PORTICO )
+ {
+ angle = m_progress*Math::PI/2.0f;
+ p = Math::RotatePoint(angle, -150.0f);
+ pos = m_pos;
+ pos.x += p.x;
+ pos.z += p.y;
+ m_terrain->MoveOnFloor(pos);
+ pos.y += 10.0f;
+ pos.y += m_progress*40.0f;
+ m_camera->SetScriptEye(pos);
+
+ m_engine->SetFogStart(0.9f-(0.9f-m_fogStart)*m_progress);
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
+ m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
+ m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
+ m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
+ }
+
+ m_phase = ABP_LDWAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ABP_LDWAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ FreezeCargo(false); // frees all cargo
+
+ if ( m_param != PARAM_PORTICO )
+ {
+ m_main->SetMovieLock(false); // you can play!
+
+ pObj = m_main->RetSelectObject();
+ m_main->SelectObject(pObj);
+ m_camera->SetObject(pObj);
+ if ( pObj == 0 )
+ {
+ m_camera->SetType(CAMERA_BACK);
+ }
+ else
+ {
+ m_camera->SetType(pObj->RetCameraType());
+ m_camera->SetDist(pObj->RetCameraDist());
+ }
+ m_sound->Play(SOUND_BOUM, m_object->RetPosition(0));
+ m_soundChannel = -1;
+
+ m_engine->SetFogStart(m_fogStart);
+ }
+
+ m_bOpen = true;
+ m_phase = ABP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ABP_CLOSE2 )
+ {
+ if ( m_progress < 1.0f )
+ {
+ len = 7.0f-(1.0f-m_progress)*(7.0f+11.5f);
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, len));
+ m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, -len));
+ m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f*(1.0f-m_progress));
+ m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f*(1.0f-m_progress));
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, 7.0f));
+ m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, -7.0f));
+ m_object->SetAngleX(10+i, 0.0f);
+ m_object->SetAngleX(18+i, 0.0f);
+ }
+
+ m_soundChannel = m_sound->Play(SOUND_MANIP, m_posSound, 0.0f, 0.3f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.3f, 1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 1.0f, BASE_DOOR_TIME-1.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 1.0f, SOPER_STOP);
+
+ m_phase = ABP_CLOSE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_DOOR_TIME;
+ }
+ }
+
+ if ( m_phase == ABP_CLOSE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = -(1.0f-m_progress)*124.0f*Math::PI/180.0f;
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, Math::PI/2.0f+angle);
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, Math::PI/2.0f);
+ }
+ m_bMotor = true; // lights the jet engine
+
+ // Shock of the closing doors.
+ max = (int)(20.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<max ; i++ )
+ {
+ angle = Math::Rand()*Math::PI*2.0f;
+ p = Math::RotatePoint(angle, 32.0f);
+ pos = m_pos;
+ pos.x += p.x;
+ pos.z += p.y;
+ pos.y += 85.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*3.0f+3.0f;
+ dim.y = dim.x;
+ time = Math::Rand()*1.0f+1.0f;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, time);
+ }
+ m_sound->Play(SOUND_BOUM, m_object->RetPosition(0));
+
+ m_soundChannel = -1;
+ m_bOpen = false;
+ m_phase = ABP_TOWAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == ABP_TOWAIT )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_soundChannel == -1 )
+ {
+ m_soundChannel = m_sound->Play(SOUND_FLY, m_posSound, 0.0f, 0.5f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 2.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 2.0f, BASE_TAKO_TIME, SOPER_STOP);
+ }
+
+ vibCir.z = sinf(m_time*Math::PI*19.01f)*(Math::PI/400.0f);
+ vibCir.x = sinf(m_time*Math::PI*19.53f)*(Math::PI/400.0f);
+ vibCir.y = 0.0f;
+ vibCir *= m_progress*1.0f;
+ m_object->SetCirVibration(vibCir);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ // Particles are ejected from the reactor.
+ pos = m_object->RetPosition(0);
+ pos.y += 6.0f;
+ speed.x = (Math::Rand()-0.5f)*160.0f;
+ speed.z = (Math::Rand()-0.5f)*160.0f;
+ speed.y = -(Math::Rand()*10.0f+10.0f);
+ dim.x = Math::Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 2.0f, 10.0f, 2.0f);
+ }
+
+ m_engine->SetFogStart(m_fogStart+(0.9f-m_fogStart)*m_progress);
+ }
+ else
+ {
+ m_engine->SetFogStart(0.9f);
+
+ m_phase = ABP_TAKEOFF;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_TAKO_TIME;
+ }
+ }
+
+ if ( m_phase == ABP_TAKEOFF )
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos = m_pos;
+ pos.y += powf(m_progress, 2.0f)*600.0f;
+ m_object->SetPosition(0, pos);
+ MoveCargo(); // all cargo moves
+
+ vibCir.z = sinf(m_time*Math::PI*19.01f)*(Math::PI/400.0f);
+ vibCir.x = sinf(m_time*Math::PI*19.53f)*(Math::PI/400.0f);
+ vibCir.y = 0.0f;
+ m_object->SetCirVibration(vibCir);
+
+ pos = m_pos;
+ pos.x -= 110.0f+m_progress*250.0f;
+ m_terrain->MoveOnFloor(pos);
+ pos.y += 10.0f;
+ m_camera->SetScriptEye(pos);
+
+ pos = m_object->RetPosition(0);
+ pos.y += 50.0f;
+ m_camera->SetScriptLookat(pos);
+
+ m_engine->SetFocus(1.0f+m_progress);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ // Dust thrown to the ground.
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ angle = Math::Rand()*(Math::PI*2.0f);
+ dist = (1.0f-m_progress)*50.0f;
+ p = Math::RotatePoint(angle, dist);
+ speed.x = p.x;
+ speed.z = p.y;
+ speed.y = 0.0f;
+ dim.x = (Math::Rand()*10.0f+10.0f)*(1.0f-m_progress);
+ dim.y = dim.x;
+ if ( dim.x >= 1.0f )
+ {
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 2.0f);
+ }
+
+ // Particles are ejected from the reactor.
+ pos = m_object->RetPosition(0);
+ pos.y += 6.0f;
+ speed.x = (Math::Rand()-0.5f)*40.0f;
+ speed.z = (Math::Rand()-0.5f)*40.0f;
+ time = 5.0f+150.0f*m_progress;
+ speed.y = -(Math::Rand()*time+time);
+ time = 2.0f+m_progress*12.0f;
+ dim.x = Math::Rand()*time+time;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 2.0f, 10.0f, 2.0f);
+
+ // Black smoke from the reactor.
+ pos = m_object->RetPosition(0);
+ pos.y += 3.0f;
+ speed.x = (Math::Rand()-0.5f)*10.0f*(4.0f-m_progress*3.0f);
+ speed.z = (Math::Rand()-0.5f)*10.0f*(4.0f-m_progress*3.0f);
+ speed.y = 0.0f;
+ dim.x = Math::Rand()*20.0f+20.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 10.0f, 0.0f, 2.0f);
+ }
+ }
+ else
+ {
+ m_soundChannel = -1;
+ m_event->MakeEvent(newEvent, EVENT_WIN);
+ m_event->AddEvent(newEvent);
+
+ m_phase = ABP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == ABP_PORTICO_MOVE ) // advance of the gate?
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos = m_object->RetPosition(0);
+ pos.z -= event.rTime*5.0f;
+ m_object->SetPosition(0, pos);
+ MoveCargo(); // all cargo moves
+ }
+ else
+ {
+ m_phase = ABP_PORTICO_WAIT1;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ABP_PORTICO_WAIT1 ) // expectation the gate?
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_phase = ABP_PORTICO_DOWN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_PORTICO_TIME_DOWN;
+ }
+ }
+
+ if ( m_phase == ABP_PORTICO_DOWN ) // down the gate?
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos = m_object->RetPosition(0);
+ pos.y -= event.rTime*(10.0f/BASE_PORTICO_TIME_DOWN);
+ m_object->SetPosition(0, pos);
+ MoveCargo(); // all cargo moves
+ }
+ else
+ {
+ // Impact with the ground.
+ max = (int)(50.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<max ; i++ )
+ {
+ angle = Math::Rand()*(Math::PI*2.0f);
+ p = Math::RotatePoint(angle, 46.0f);
+ pos = m_pos;
+ pos.x += p.x;
+ pos.z += p.y;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*10.0f+10.0f;
+ dim.y = dim.x;
+ time = Math::Rand()*2.0f+1.5f;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, time, 0.0f, 2.0f);
+ }
+
+ m_phase = ABP_PORTICO_WAIT2;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ABP_PORTICO_WAIT2 ) // expectation the gate?
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_phase = ABP_PORTICO_OPEN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/BASE_PORTICO_TIME_OPEN;
+ }
+ }
+
+ if ( m_phase == ABP_PORTICO_OPEN ) // opening the gate?
+ {
+ if ( m_progress < 1.0f )
+ {
+ }
+ else
+ {
+ m_phase = ABP_OPEN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == ABP_TRANSIT_MOVE ) // transit in space?
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += event.rTime*(2000.0f/BASE_TRANSIT_TIME);
+ m_object->SetPosition(0, pos);
+ pos.x += 60.0f;
+ m_camera->SetScriptLookat(pos);
+ }
+ else
+ {
+ m_object->SetAngleZ(0, 0.0f);
+
+ m_param = PARAM_LANDING;
+ m_phase = ABP_START;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ EndTransit();
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.8f, 0.01f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+ goto begin;
+ }
+ }
+
+ if ( m_bMotor )
+ {
+ if ( m_lastMotorParticule+m_engine->ParticuleAdapt(0.02f) <= m_time )
+ {
+ m_lastMotorParticule = m_time;
+
+ mat = m_object->RetWorldMatrix(0);
+
+ if ( event.rTime == 0.0f )
+ {
+ vSpeed = 0.0f;
+ }
+ else
+ {
+ pos = m_object->RetPosition(0);
+ if ( m_phase == ABP_TRANSIT_MOVE )
+ {
+ vSpeed = (pos.x-iPos.x)/event.rTime;
+ }
+ else
+ {
+ vSpeed = (pos.y-iPos.y)/event.rTime;
+ }
+ if ( vSpeed < 0.0f ) vSpeed *= 1.5f;
+ }
+
+ pos = Math::Vector(0.0f, 6.0f, 0.0f);
+ speed.x = (Math::Rand()-0.5f)*4.0f;
+ speed.z = (Math::Rand()-0.5f)*4.0f;
+ speed.y = vSpeed*0.8f-(8.0f+Math::Rand()*6.0f);
+ speed += pos;
+ pos = Transform(*mat, pos);
+ speed = Transform(*mat, speed);
+ speed -= pos;
+
+ dim.x = 4.0f+Math::Rand()*4.0f;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTIBASE, 3.0f, 0.0f, 0.0f);
+
+ if ( m_phase == ABP_TRANSIT_MOVE )
+ {
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 12.0f;
+ dim.y = dim.x;
+ pos = Math::Vector(0.0f, 7.0f, 0.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 1.0f, 0.0f, 0.0f);
+
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 4.0f;
+ dim.y = dim.x;
+ pos = Math::Vector(42.0f, 0.0f, 17.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = Math::Vector(17.0f, 0.0f, 42.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = Math::Vector(42.0f, 0.0f, -17.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = Math::Vector(17.0f, 0.0f, -42.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = Math::Vector(-42.0f, 0.0f, 17.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = Math::Vector(-17.0f, 0.0f, 42.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = Math::Vector(-42.0f, 0.0f, -17.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+ pos = Math::Vector(-17.0f, 0.0f, -42.0f);
+ pos.x += (Math::Rand()-0.5f)*2.0f; pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos = Transform(*mat, pos);
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 0.5f, 0.0f, 0.0f);
+
+ pos = Math::Vector(42.0f, -2.0f, 17.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[0], pos);
+ pos = Math::Vector(17.0f, -2.0f, 42.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[1], pos);
+ pos = Math::Vector(42.0f, -2.0f, -17.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[2], pos);
+ pos = Math::Vector(17.0f, -2.0f, -42.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[3], pos);
+ pos = Math::Vector(-42.0f, -2.0f, 17.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[4], pos);
+ pos = Math::Vector(-17.0f, -2.0f, 42.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[5], pos);
+ pos = Math::Vector(-42.0f, -2.0f, -17.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[6], pos);
+ pos = Math::Vector(-17.0f, -2.0f, -42.0f);
+ pos = Transform(*mat, pos);
+ m_particule->SetPosition(m_partiChannel[7], pos);
+ }
+ }
+ }
+
+ if ( m_soundChannel != -1 )
+ {
+ pos = m_engine->RetEyePt();
+ m_sound->Position(m_soundChannel, pos);
+ }
+
+ return true;
+}
+
+// Stops the controller.
+
+bool CAutoBase::Abort()
+{
+ Event newEvent;
+ CObject* pObj;
+ int i;
+
+ if ( m_phase == ABP_TRANSIT_MOVE ) // transit ?
+ {
+ m_object->SetAngleZ(0, 0.0f);
+
+ m_param = PARAM_LANDING;
+ m_phase = ABP_START;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ EndTransit();
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.8f, 0.01f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+ return true;
+ }
+
+ if ( m_param == PARAM_PORTICO ) // gate on the porch?
+ {
+ m_object->SetPosition(0, m_finalPos);
+ MoveCargo(); // all cargo moves
+
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
+ m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
+ m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
+ m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
+ m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
+ }
+ }
+ else
+ {
+ if ( m_phase == ABP_LAND ||
+ m_phase == ABP_OPENWAIT ||
+ m_phase == ABP_OPEN ||
+ m_phase == ABP_OPEN2 ) // Landing?
+ {
+ m_bMotor = false; // put out the jet engine
+ m_bOpen = true;
+
+ m_object->SetPosition(0, m_pos); // setting down
+ m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ MoveCargo(); // all cargo moves
+ for ( i=0 ; i<8 ; i++ )
+ {
+ m_object->SetAngleZ(1+i, Math::PI/2.0f-124.0f*Math::PI/180.0f);
+ m_object->SetAngleX(10+i, -10.0f*Math::PI/180.0f);
+ m_object->SetAngleX(18+i, 10.0f*Math::PI/180.0f);
+ m_object->SetPosition(10+i, Math::Vector(23.5f, 0.0f, -11.5f));
+ m_object->SetPosition(18+i, Math::Vector(23.5f, 0.0f, 11.5f));
+ }
+
+ m_main->SetMovieLock(false); // you can play!
+
+ pObj = m_main->RetSelectObject();
+ m_main->SelectObject(pObj);
+ m_camera->SetObject(pObj);
+ if ( pObj == 0 )
+ {
+ m_camera->SetType(CAMERA_BACK);
+ }
+ else
+ {
+ m_camera->SetType(pObj->RetCameraType());
+ m_camera->SetDist(pObj->RetCameraDist());
+ }
+
+ m_engine->SetFogStart(m_fogStart);
+ }
+
+ if ( m_phase == ABP_CLOSE2 ||
+ m_phase == ABP_CLOSE ||
+ m_phase == ABP_TOWAIT ||
+ m_phase == ABP_TAKEOFF ) // off?
+ {
+ m_event->MakeEvent(newEvent, EVENT_WIN);
+ m_event->AddEvent(newEvent);
+ }
+ }
+
+ m_object->SetAngleZ(0, 0.0f);
+ FreezeCargo(false); // frees all cargo
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ m_phase = ABP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoBase::RetError()
+{
+ return ERR_OK;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoBase::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, dim, ddim;
+ float ox, oy, sx, sy;
+ float sleep, delay, magnetic, progress;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ dim.x = 33.0f/640.0f;
+ dim.y = 33.0f/480.0f;
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ ddim.x = dim.x*1.5f;
+ ddim.y = dim.y*1.5f;
+
+//? pos.x = ox+sx*7.25f;
+//? pos.y = oy+sy*0.25f;
+//? pw->CreateButton(pos, ddim, 63, EVENT_OBJECT_BHELP);
+
+ pos.x = ox+sx*8.00f;
+ pos.y = oy+sy*0.25f;
+ pw->CreateButton(pos, ddim, 28, EVENT_OBJECT_BTAKEOFF);
+
+ if ( m_blitz->GetStatus(sleep, delay, magnetic, progress) )
+ {
+ pos.x = ox+sx*10.2f;
+ pos.y = oy+sy*0.5f;
+ ddim.x = dim.x*1.0f;
+ ddim.y = dim.y*1.0f;
+ pw->CreateButton(pos, ddim, 41, EVENT_OBJECT_LIMIT);
+ }
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 100, EVENT_OBJECT_TYPE);
+
+ UpdateInterface();
+
+ return true;
+}
+
+// Updates the status of all interface buttons.
+
+void CAutoBase::UpdateInterface()
+{
+ CWindow* pw;
+
+ if ( !m_object->RetSelect() ) return;
+
+ CAuto::UpdateInterface();
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+}
+
+
+// Freeze or frees all cargo.
+
+void CAutoBase::FreezeCargo(bool bFreeze)
+{
+ CObject* pObj;
+ CPhysics* physics;
+ Math::Vector oPos;
+ float dist;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ pObj->SetCargo(false);
+
+ if ( pObj == m_object ) continue; // yourself?
+ if ( pObj->RetTruck() != 0 ) continue; // transport object?
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(m_pos, oPos);
+ if ( dist < 32.0f )
+ {
+ if ( bFreeze )
+ {
+ pObj->SetCargo(true);
+ }
+
+ physics = pObj->RetPhysics();
+ if ( physics != 0 )
+ {
+ physics->SetFreeze(bFreeze);
+ }
+ }
+ }
+}
+
+// All cargo moves vertically with the ship.
+
+void CAutoBase::MoveCargo()
+{
+ CObject* pObj;
+ Math::Vector oPos, sPos;
+ int i;
+
+ sPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetCargo() ) continue;
+
+ oPos = pObj->RetPosition(0);
+ oPos.y = sPos.y+30.0f;
+ oPos.y += pObj->RetCharacter()->height;
+ oPos.x += sPos.x-m_lastPos.x;
+ oPos.z += sPos.z-m_lastPos.z;
+ pObj->SetPosition(0, oPos);
+ }
+
+ m_lastPos = sPos;
+}
+
+
+// Checks whether it is possible to close the doors.
+
+Error CAutoBase::CheckCloseDoor()
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ ObjectType type;
+ float oRad, dist;
+ int i, j;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue; // yourself?
+ if ( !pObj->RetActif() ) continue; // inactive?
+
+ type = pObj->RetType();
+ if ( type == OBJECT_PORTICO ) continue;
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRad) )
+ {
+ dist = Math::DistanceProjected(m_pos, oPos);
+ if ( dist+oRad > 32.0f &&
+ dist-oRad < 72.0f )
+ {
+ return ERR_BASE_DLOCK;
+ }
+
+ if ( type == OBJECT_HUMAN &&
+ dist+oRad > 32.0f )
+ {
+ return ERR_BASE_DHUMAN;
+ }
+ }
+ }
+ return ERR_OK;
+}
+
+
+// Start a transit.
+
+void CAutoBase::BeginTransit()
+{
+ bool bFull, bQuarter;
+
+ if ( m_param == PARAM_TRANSIT2 )
+ {
+ strcpy(m_bgBack, "back01.tga"); // clouds orange / blue
+ }
+ else if ( m_param == PARAM_TRANSIT3 )
+ {
+ strcpy(m_bgBack, "back22.tga"); // blueberries clouds
+ }
+ else
+ {
+#if _DEMO
+ strcpy(m_bgBack, "back46b.tga"); // paintings
+#else
+ strcpy(m_bgBack, "back46.tga"); // paintings
+#endif
+ }
+
+ m_engine->SetFogStart(0.9f); // hardly any fog
+ m_engine->SetDeepView(2000.0f); // we see very far
+ m_engine->ApplyChange();
+
+ m_engine->RetBackground(m_bgName, m_bgUp, m_bgDown, m_bgCloudUp, m_bgCloudDown, bFull, bQuarter);
+ m_engine->FreeTexture(m_bgName);
+
+ m_engine->SetBackground(m_bgBack, 0x00000000, 0x00000000, 0x00000000, 0x00000000);
+ m_engine->LoadTexture(m_bgBack);
+
+ m_cloud->SetEnable(false); // cache clouds
+ m_planet->SetMode(1);
+}
+
+// End of a transit.
+
+void CAutoBase::EndTransit()
+{
+ m_engine->SetFogStart(m_fogStart); // gives initial fog
+ m_engine->SetDeepView(m_deepView); // gives initial depth
+ m_engine->ApplyChange();
+
+ m_engine->FreeTexture(m_bgBack);
+
+ m_engine->SetBackground(m_bgName, m_bgUp, m_bgDown, m_bgCloudUp, m_bgCloudDown);
+ m_engine->LoadTexture(m_bgName);
+
+ m_cloud->SetEnable(true); // gives the clouds
+ m_planet->SetMode(0);
+
+ m_main->StartMusic();
+}
+
diff --git a/src/object/auto/autobase.h b/src/object/auto/autobase.h
index 0f71ef6..eb47a93 100644
--- a/src/object/auto/autobase.h
+++ b/src/object/auto/autobase.h
@@ -1,112 +1,112 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autobase.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoBaseParam
-{
- PARAM_STOP = 0, // run=0 -> stops and open
- PARAM_LANDING = 1, // run=1 -> landing
- PARAM_PORTICO = 2, // run=2 -> gate on the ground
- PARAM_FIXSCENE = 3, // run=3 -> open and stops to win / lost
- PARAM_TRANSIT1 = 11, // run=11 -> transit in space
- PARAM_TRANSIT2 = 12, // run=12 -> transit in space
- PARAM_TRANSIT3 = 13 // run=13 -> transit in space
-};
-
-enum AutoBasePhase
-{
- ABP_WAIT = 1, // expected
- ABP_START = 2, // start-up
-
- ABP_LAND = 3, // landing
- ABP_OPENWAIT = 4, // wait before opening
- ABP_OPEN = 5, // opens the gate
- ABP_OPEN2 = 6, // opens supplements
- ABP_LDWAIT = 7, // expected
-
- ABP_CLOSE2 = 8, // closes supplements
- ABP_CLOSE = 9, // closes gate
- ABP_TOWAIT = 10, // wait before takeoff
- ABP_TAKEOFF = 11, // take-off
-
- ABP_PORTICO_MOVE = 12, // gate advance
- ABP_PORTICO_WAIT1= 13, // gate expected
- ABP_PORTICO_DOWN = 14, // gate down
- ABP_PORTICO_WAIT2= 15, // gate expected
- ABP_PORTICO_OPEN = 16, // gate opens
-
- ABP_TRANSIT_MOVE = 17, // transit - moving
-};
-
-
-
-class CAutoBase : public CAuto
-{
-public:
- CAutoBase(CInstanceManager* iMan, CObject* object);
- ~CAutoBase();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- void Start(int param);
- bool EventProcess(const Event &event);
- bool Abort();
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
-protected:
- void UpdateInterface();
- void FreezeCargo(bool bFreeze);
- void MoveCargo();
- Error CheckCloseDoor();
- void BeginTransit();
- void EndTransit();
-
-protected:
- AutoBasePhase m_phase;
- bool m_bOpen;
- float m_progress;
- float m_speed;
- float m_lastParticule;
- float m_lastMotorParticule;
- float m_fogStart;
- float m_deepView;
- Math::Vector m_pos;
- Math::Vector m_posSound;
- Math::Vector m_finalPos;
- Math::Vector m_lastPos;
- int m_param;
- int m_soundChannel;
- int m_partiChannel[8];
-
- char m_bgBack[100];
- char m_bgName[100];
- D3DCOLOR m_bgUp;
- D3DCOLOR m_bgDown;
- D3DCOLOR m_bgCloudUp;
- D3DCOLOR m_bgCloudDown;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autobase.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoBaseParam
+{
+ PARAM_STOP = 0, // run=0 -> stops and open
+ PARAM_LANDING = 1, // run=1 -> landing
+ PARAM_PORTICO = 2, // run=2 -> gate on the ground
+ PARAM_FIXSCENE = 3, // run=3 -> open and stops to win / lost
+ PARAM_TRANSIT1 = 11, // run=11 -> transit in space
+ PARAM_TRANSIT2 = 12, // run=12 -> transit in space
+ PARAM_TRANSIT3 = 13 // run=13 -> transit in space
+};
+
+enum AutoBasePhase
+{
+ ABP_WAIT = 1, // expected
+ ABP_START = 2, // start-up
+
+ ABP_LAND = 3, // landing
+ ABP_OPENWAIT = 4, // wait before opening
+ ABP_OPEN = 5, // opens the gate
+ ABP_OPEN2 = 6, // opens supplements
+ ABP_LDWAIT = 7, // expected
+
+ ABP_CLOSE2 = 8, // closes supplements
+ ABP_CLOSE = 9, // closes gate
+ ABP_TOWAIT = 10, // wait before takeoff
+ ABP_TAKEOFF = 11, // take-off
+
+ ABP_PORTICO_MOVE = 12, // gate advance
+ ABP_PORTICO_WAIT1= 13, // gate expected
+ ABP_PORTICO_DOWN = 14, // gate down
+ ABP_PORTICO_WAIT2= 15, // gate expected
+ ABP_PORTICO_OPEN = 16, // gate opens
+
+ ABP_TRANSIT_MOVE = 17, // transit - moving
+};
+
+
+
+class CAutoBase : public CAuto
+{
+public:
+ CAutoBase(CInstanceManager* iMan, CObject* object);
+ ~CAutoBase();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ void Start(int param);
+ bool EventProcess(const Event &event);
+ bool Abort();
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+protected:
+ void UpdateInterface();
+ void FreezeCargo(bool bFreeze);
+ void MoveCargo();
+ Error CheckCloseDoor();
+ void BeginTransit();
+ void EndTransit();
+
+protected:
+ AutoBasePhase m_phase;
+ bool m_bOpen;
+ float m_progress;
+ float m_speed;
+ float m_lastParticule;
+ float m_lastMotorParticule;
+ float m_fogStart;
+ float m_deepView;
+ Math::Vector m_pos;
+ Math::Vector m_posSound;
+ Math::Vector m_finalPos;
+ Math::Vector m_lastPos;
+ int m_param;
+ int m_soundChannel;
+ int m_partiChannel[8];
+
+ char m_bgBack[100];
+ char m_bgName[100];
+ D3DCOLOR m_bgUp;
+ D3DCOLOR m_bgDown;
+ D3DCOLOR m_bgCloudUp;
+ D3DCOLOR m_bgCloudDown;
+};
+
diff --git a/src/object/auto/autoconvert.cpp b/src/object/auto/autoconvert.cpp
index ffe7d59..b5ad43a 100644
--- a/src/object/auto/autoconvert.cpp
+++ b/src/object/auto/autoconvert.cpp
@@ -1,527 +1,527 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoconvert.h"
-
-#include "common/iman.h"
-#include "math/geometry.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-
-
-
-
-// Object's constructor.
-
-CAutoConvert::CAutoConvert(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
- m_phase = ACP_STOP;
- m_bResetDelete = false;
- m_soundChannel = -1;
-}
-
-// Object's destructor.
-
-CAutoConvert::~CAutoConvert()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoConvert::DeleteObject(bool bAll)
-{
- CObject* fret;
-
- if ( !bAll )
- {
- fret = SearchStone(OBJECT_STONE);
- if ( fret != 0 )
- {
- fret->DeleteObject(); // destroy the stone
- delete fret;
- }
- }
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoConvert::Init()
-{
- m_phase = ACP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastParticule = 0.0f;
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoConvert::EventProcess(const Event &event)
-{
- CObject* fret;
- Math::Vector pos, speed;
- Math::Point dim, c, p;
- float angle;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
-
- angle = (Math::Rand()-0.5f)*0.3f;
- m_object->SetAngleY(1, angle);
- m_object->SetAngleY(2, angle);
- m_object->SetAngleY(3, angle+Math::PI);
-
- m_object->SetAngleX(2, -Math::PI*0.35f*(0.8f+Math::Rand()*0.2f));
- m_object->SetAngleX(3, -Math::PI*0.35f*(0.8f+Math::Rand()*0.2f));
- }
- return true;
- }
-
- EventProgress(event.rTime);
-
- if ( m_phase == ACP_STOP ) return true;
-
- if ( m_phase == ACP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- fret = SearchStone(OBJECT_STONE); // Has stone transformed?
- if ( fret == 0 || SearchVehicle() )
- {
- m_phase = ACP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- else
- {
- fret->SetLock(true); // stone usable
-
- SetBusy(true);
- InitProgressTotal(3.0f+10.0f+1.5f);
- UpdateInterface();
-
- m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.0f);
- m_bSoundClose = false;
-
- m_phase = ACP_CLOSE;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- }
- }
- }
-
- if ( m_phase == ACP_CLOSE )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_progress >= 0.8f && !m_bSoundClose )
- {
- m_bSoundClose = true;
- m_sound->Play(SOUND_CLOSE, m_object->RetPosition(0), 1.0f, 0.8f);
- }
- angle = -Math::PI*0.35f*(1.0f-Math::Bounce(m_progress, 0.85f, 0.05f));
- m_object->SetAngleX(2, angle);
- m_object->SetAngleX(3, angle);
- }
- else
- {
- m_object->SetAngleX(2, 0.0f);
- m_object->SetAngleX(3, 0.0f);
-
- m_soundChannel = m_sound->Play(SOUND_CONVERT, m_object->RetPosition(0), 0.0f, 0.25f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.25f, 0.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.00f, 4.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.25f, 4.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.25f, 0.5f, SOPER_STOP);
-
- m_phase = ACP_ROTATE;
- m_progress = 0.0f;
- m_speed = 1.0f/10.0f;
- }
- }
-
- if ( m_phase == ACP_ROTATE )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_progress < 0.5f )
- {
- angle = powf((m_progress*2.0f)*5.0f, 2.0f); // accelerates
- }
- else
- {
- angle = -powf((2.0f-m_progress*2.0f)*5.0f, 2.0f); // slows
- }
- m_object->SetAngleY(1, angle);
- m_object->SetAngleY(2, angle);
- m_object->SetAngleY(3, angle+Math::PI);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- c.x = pos.x;
- c.y = pos.z;
- p.x = c.x;
- p.y = c.y+6.0f;
- p = Math::RotatePoint(c, Math::Rand()*Math::PI*2.0f, p);
- pos.x = p.x;
- pos.z = p.y;
- pos.y += 1.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*2.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 1.0f, 0.0f, 0.0f);
- }
- }
- else
- {
- m_object->SetAngleY(1, 0.0f);
- m_object->SetAngleY(2, 0.0f);
- m_object->SetAngleY(3, Math::PI);
-
- fret = SearchStone(OBJECT_STONE);
- if ( fret != 0 )
- {
- m_bResetDelete = ( fret->RetResetCap() != RESET_NONE );
- fret->DeleteObject(); // destroy the stone
- delete fret;
- }
-
- CreateMetal(); // Create the metal
- m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.5f);
-
- m_phase = ACP_OPEN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
-
- if ( m_phase == ACP_OPEN )
- {
- if ( m_progress < 1.0f )
- {
- angle = -Math::PI*0.35f*Math::Bounce(m_progress, 0.7f, 0.2f);
- m_object->SetAngleX(2, angle);
- m_object->SetAngleX(3, angle);
-
- if ( m_progress < 0.9f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*6.0f;
- pos.z += (Math::Rand()-0.5f)*6.0f;
- pos.y += Math::Rand()*4.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*4.0f+3.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
- }
- }
- else
- {
- m_soundChannel = -1;
- m_object->SetAngleX(2, -Math::PI*0.35f);
- m_object->SetAngleX(3, -Math::PI*0.35f);
-
- SetBusy(false);
- UpdateInterface();
-
- m_phase = ACP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- return true;
-}
-
-// Returns an error due the state of the automation.
-
-Error CAutoConvert::RetError()
-{
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- if ( m_phase == ACP_WAIT ) return ERR_CONVERT_EMPTY;
- return ERR_OK;
-}
-
-// Cancels the current transformation.
-
-bool CAutoConvert::Abort()
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- m_object->SetAngleY(1, 0.0f);
- m_object->SetAngleY(2, 0.0f);
- m_object->SetAngleY(3, Math::PI);
- m_object->SetAngleX(2, -Math::PI*0.35f);
- m_object->SetAngleX(3, -Math::PI*0.35f);
-
- m_phase = ACP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- SetBusy(false);
- UpdateInterface();
-
- return true;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoConvert::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 103, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoConvert::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == ACP_STOP ||
- m_phase == ACP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoConvert::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoConvertPhase)OpInt(line, "aPhase", ACP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
-// Searches for the object before or during processing.
-
-CObject* CAutoConvert::SearchStone(ObjectType type)
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType oType;
- float dist;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( oType != type ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, cPos);
-
- if ( dist <= 5.0f ) return pObj;
- }
-
- return 0;
-}
-
-// Search if a vehicle is too close.
-
-bool CAutoConvert::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType type;
- float oRadius, dist;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr &&
- type != OBJECT_METAL &&
- type != OBJECT_URANIUM &&
- type != OBJECT_POWER &&
- type != OBJECT_ATOMIC &&
- type != OBJECT_BULLET &&
- type != OBJECT_BBOX &&
- type != OBJECT_TNT &&
- type != OBJECT_MOTHER &&
- type != OBJECT_ANT &&
- type != OBJECT_SPIDER &&
- type != OBJECT_BEE &&
- type != OBJECT_WORM ) continue;
-
- if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
- dist = Math::Distance(oPos, cPos)-oRadius;
-
- if ( dist < 8.0f ) return true;
- }
-
- return false;
-}
-
-// Creates an object metal.
-
-void CAutoConvert::CreateMetal()
-{
- Math::Vector pos;
- float angle;
- CObject* fret;
-
- pos = m_object->RetPosition(0);
- angle = m_object->RetAngleY(0);
-
- fret = new CObject(m_iMan);
- if ( !fret->CreateResource(pos, angle, OBJECT_METAL) )
- {
- delete fret;
- m_displayText->DisplayError(ERR_TOOMANY, m_object);
- return;
- }
-
- if ( m_bResetDelete )
- {
- fret->SetResetCap(RESET_DELETE);
- }
-
- m_displayText->DisplayError(INFO_CONVERT, m_object);
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoconvert.h"
+
+#include "common/iman.h"
+#include "math/geometry.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+
+
+
+
+// Object's constructor.
+
+CAutoConvert::CAutoConvert(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+ m_phase = ACP_STOP;
+ m_bResetDelete = false;
+ m_soundChannel = -1;
+}
+
+// Object's destructor.
+
+CAutoConvert::~CAutoConvert()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoConvert::DeleteObject(bool bAll)
+{
+ CObject* fret;
+
+ if ( !bAll )
+ {
+ fret = SearchStone(OBJECT_STONE);
+ if ( fret != 0 )
+ {
+ fret->DeleteObject(); // destroy the stone
+ delete fret;
+ }
+ }
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoConvert::Init()
+{
+ m_phase = ACP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoConvert::EventProcess(const Event &event)
+{
+ CObject* fret;
+ Math::Vector pos, speed;
+ Math::Point dim, c, p;
+ float angle;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+
+ angle = (Math::Rand()-0.5f)*0.3f;
+ m_object->SetAngleY(1, angle);
+ m_object->SetAngleY(2, angle);
+ m_object->SetAngleY(3, angle+Math::PI);
+
+ m_object->SetAngleX(2, -Math::PI*0.35f*(0.8f+Math::Rand()*0.2f));
+ m_object->SetAngleX(3, -Math::PI*0.35f*(0.8f+Math::Rand()*0.2f));
+ }
+ return true;
+ }
+
+ EventProgress(event.rTime);
+
+ if ( m_phase == ACP_STOP ) return true;
+
+ if ( m_phase == ACP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ fret = SearchStone(OBJECT_STONE); // Has stone transformed?
+ if ( fret == 0 || SearchVehicle() )
+ {
+ m_phase = ACP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ else
+ {
+ fret->SetLock(true); // stone usable
+
+ SetBusy(true);
+ InitProgressTotal(3.0f+10.0f+1.5f);
+ UpdateInterface();
+
+ m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.0f);
+ m_bSoundClose = false;
+
+ m_phase = ACP_CLOSE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ }
+ }
+ }
+
+ if ( m_phase == ACP_CLOSE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_progress >= 0.8f && !m_bSoundClose )
+ {
+ m_bSoundClose = true;
+ m_sound->Play(SOUND_CLOSE, m_object->RetPosition(0), 1.0f, 0.8f);
+ }
+ angle = -Math::PI*0.35f*(1.0f-Math::Bounce(m_progress, 0.85f, 0.05f));
+ m_object->SetAngleX(2, angle);
+ m_object->SetAngleX(3, angle);
+ }
+ else
+ {
+ m_object->SetAngleX(2, 0.0f);
+ m_object->SetAngleX(3, 0.0f);
+
+ m_soundChannel = m_sound->Play(SOUND_CONVERT, m_object->RetPosition(0), 0.0f, 0.25f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.25f, 0.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.00f, 4.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.25f, 4.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.25f, 0.5f, SOPER_STOP);
+
+ m_phase = ACP_ROTATE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/10.0f;
+ }
+ }
+
+ if ( m_phase == ACP_ROTATE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_progress < 0.5f )
+ {
+ angle = powf((m_progress*2.0f)*5.0f, 2.0f); // accelerates
+ }
+ else
+ {
+ angle = -powf((2.0f-m_progress*2.0f)*5.0f, 2.0f); // slows
+ }
+ m_object->SetAngleY(1, angle);
+ m_object->SetAngleY(2, angle);
+ m_object->SetAngleY(3, angle+Math::PI);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ c.x = pos.x;
+ c.y = pos.z;
+ p.x = c.x;
+ p.y = c.y+6.0f;
+ p = Math::RotatePoint(c, Math::Rand()*Math::PI*2.0f, p);
+ pos.x = p.x;
+ pos.z = p.y;
+ pos.y += 1.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*2.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS, 1.0f, 0.0f, 0.0f);
+ }
+ }
+ else
+ {
+ m_object->SetAngleY(1, 0.0f);
+ m_object->SetAngleY(2, 0.0f);
+ m_object->SetAngleY(3, Math::PI);
+
+ fret = SearchStone(OBJECT_STONE);
+ if ( fret != 0 )
+ {
+ m_bResetDelete = ( fret->RetResetCap() != RESET_NONE );
+ fret->DeleteObject(); // destroy the stone
+ delete fret;
+ }
+
+ CreateMetal(); // Create the metal
+ m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.5f);
+
+ m_phase = ACP_OPEN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+
+ if ( m_phase == ACP_OPEN )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = -Math::PI*0.35f*Math::Bounce(m_progress, 0.7f, 0.2f);
+ m_object->SetAngleX(2, angle);
+ m_object->SetAngleX(3, angle);
+
+ if ( m_progress < 0.9f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*6.0f;
+ pos.z += (Math::Rand()-0.5f)*6.0f;
+ pos.y += Math::Rand()*4.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*4.0f+3.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
+ }
+ }
+ else
+ {
+ m_soundChannel = -1;
+ m_object->SetAngleX(2, -Math::PI*0.35f);
+ m_object->SetAngleX(3, -Math::PI*0.35f);
+
+ SetBusy(false);
+ UpdateInterface();
+
+ m_phase = ACP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ return true;
+}
+
+// Returns an error due the state of the automation.
+
+Error CAutoConvert::RetError()
+{
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ if ( m_phase == ACP_WAIT ) return ERR_CONVERT_EMPTY;
+ return ERR_OK;
+}
+
+// Cancels the current transformation.
+
+bool CAutoConvert::Abort()
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ m_object->SetAngleY(1, 0.0f);
+ m_object->SetAngleY(2, 0.0f);
+ m_object->SetAngleY(3, Math::PI);
+ m_object->SetAngleX(2, -Math::PI*0.35f);
+ m_object->SetAngleX(3, -Math::PI*0.35f);
+
+ m_phase = ACP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ SetBusy(false);
+ UpdateInterface();
+
+ return true;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoConvert::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 103, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoConvert::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == ACP_STOP ||
+ m_phase == ACP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoConvert::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoConvertPhase)OpInt(line, "aPhase", ACP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
+// Searches for the object before or during processing.
+
+CObject* CAutoConvert::SearchStone(ObjectType type)
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType oType;
+ float dist;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( oType != type ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, cPos);
+
+ if ( dist <= 5.0f ) return pObj;
+ }
+
+ return 0;
+}
+
+// Search if a vehicle is too close.
+
+bool CAutoConvert::SearchVehicle()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType type;
+ float oRadius, dist;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_HUMAN &&
+ type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis &&
+ type != OBJECT_MOBILErt &&
+ type != OBJECT_MOBILErc &&
+ type != OBJECT_MOBILErr &&
+ type != OBJECT_MOBILErs &&
+ type != OBJECT_MOBILEsa &&
+ type != OBJECT_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_MOBILEdr &&
+ type != OBJECT_METAL &&
+ type != OBJECT_URANIUM &&
+ type != OBJECT_POWER &&
+ type != OBJECT_ATOMIC &&
+ type != OBJECT_BULLET &&
+ type != OBJECT_BBOX &&
+ type != OBJECT_TNT &&
+ type != OBJECT_MOTHER &&
+ type != OBJECT_ANT &&
+ type != OBJECT_SPIDER &&
+ type != OBJECT_BEE &&
+ type != OBJECT_WORM ) continue;
+
+ if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
+ dist = Math::Distance(oPos, cPos)-oRadius;
+
+ if ( dist < 8.0f ) return true;
+ }
+
+ return false;
+}
+
+// Creates an object metal.
+
+void CAutoConvert::CreateMetal()
+{
+ Math::Vector pos;
+ float angle;
+ CObject* fret;
+
+ pos = m_object->RetPosition(0);
+ angle = m_object->RetAngleY(0);
+
+ fret = new CObject(m_iMan);
+ if ( !fret->CreateResource(pos, angle, OBJECT_METAL) )
+ {
+ delete fret;
+ m_displayText->DisplayError(ERR_TOOMANY, m_object);
+ return;
+ }
+
+ if ( m_bResetDelete )
+ {
+ fret->SetResetCap(RESET_DELETE);
+ }
+
+ m_displayText->DisplayError(INFO_CONVERT, m_object);
+}
+
diff --git a/src/object/auto/autoconvert.h b/src/object/auto/autoconvert.h
index b907c3a..c2042cf 100644
--- a/src/object/auto/autoconvert.h
+++ b/src/object/auto/autoconvert.h
@@ -1,70 +1,70 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoconvert.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoConvertPhase
-{
- ACP_STOP = 1,
- ACP_WAIT = 2,
- ACP_CLOSE = 3, // close the cover
- ACP_ROTATE = 4, // turn the cover
- ACP_OPEN = 5, // opens the cover
-};
-
-
-
-class CAutoConvert : public CAuto
-{
-public:
- CAutoConvert(CInstanceManager* iMan, CObject* object);
- ~CAutoConvert();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
- bool Abort();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- CObject* SearchStone(ObjectType type);
- bool SearchVehicle();
- void CreateMetal();
-
-protected:
- AutoConvertPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
- bool m_bResetDelete;
- bool m_bSoundClose;
- int m_soundChannel;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoconvert.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoConvertPhase
+{
+ ACP_STOP = 1,
+ ACP_WAIT = 2,
+ ACP_CLOSE = 3, // close the cover
+ ACP_ROTATE = 4, // turn the cover
+ ACP_OPEN = 5, // opens the cover
+};
+
+
+
+class CAutoConvert : public CAuto
+{
+public:
+ CAutoConvert(CInstanceManager* iMan, CObject* object);
+ ~CAutoConvert();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+ bool Abort();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ CObject* SearchStone(ObjectType type);
+ bool SearchVehicle();
+ void CreateMetal();
+
+protected:
+ AutoConvertPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+ bool m_bResetDelete;
+ bool m_bSoundClose;
+ int m_soundChannel;
+};
+
diff --git a/src/object/auto/autoderrick.cpp b/src/object/auto/autoderrick.cpp
index fa7cff9..3f1cda5 100644
--- a/src/object/auto/autoderrick.cpp
+++ b/src/object/auto/autoderrick.cpp
@@ -1,589 +1,589 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoderrick.h"
-
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "math/geometry.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-
-
-
-
-const float DERRICK_DELAY = 10.0f; // duration of the extraction
-const float DERRICK_DELAYu = 30.0f; // same, but for uranium
-
-
-
-
-// Object's constructor.
-
-CAutoDerrick::CAutoDerrick(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
- m_phase = ADP_WAIT; // paused until the first Init ()
- m_soundChannel = -1;
-}
-
-// Object's destructor.
-
-CAutoDerrick::~CAutoDerrick()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoDerrick::DeleteObject(bool bAll)
-{
- CObject* fret;
-
- if ( !bAll )
- {
- fret = SearchFret();
- if ( fret != 0 && fret->RetLock() )
- {
- fret->DeleteObject();
- delete fret;
- }
- }
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoDerrick::Init()
-{
- Math::Matrix* mat;
- Math::Vector pos;
- TerrainRes res;
-
- pos = m_object->RetPosition(0);
- res = m_terrain->RetResource(pos);
-
- if ( res == TR_STONE ||
- res == TR_URANIUM ||
- res == TR_KEYa ||
- res == TR_KEYb ||
- res == TR_KEYc ||
- res == TR_KEYd )
- {
- m_type = OBJECT_FRET;
- if ( res == TR_STONE ) m_type = OBJECT_STONE;
- if ( res == TR_URANIUM ) m_type = OBJECT_URANIUM;
- if ( res == TR_KEYa ) m_type = OBJECT_KEYa;
- if ( res == TR_KEYb ) m_type = OBJECT_KEYb;
- if ( res == TR_KEYc ) m_type = OBJECT_KEYc;
- if ( res == TR_KEYd ) m_type = OBJECT_KEYd;
-
- m_phase = ADP_EXCAVATE;
- m_progress = 0.0f;
- m_speed = 1.0f/(m_type==OBJECT_URANIUM?DERRICK_DELAYu:DERRICK_DELAY);
- }
- else
- {
- m_phase = ADP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f;
- }
-
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastParticule = 0.0f;
- m_lastTrack = 0.0f;
-
- pos = Math::Vector(7.0f, 0.0f, 0.0f);
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Transform(*mat, pos);
- m_terrain->MoveOnFloor(pos);
- m_fretPos = pos;
-}
-
-
-// Management of an event.
-
-bool CAutoDerrick::EventProcess(const Event &event)
-{
- CObject* fret;
- Math::Vector pos, speed;
- Math::Point dim;
- float angle, duration, factor;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_phase == ADP_WAIT ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
-
- pos.x = 0.0f;
- pos.z = 0.0f;
- pos.y = -2.0f*Math::Rand();
- m_object->SetPosition(1, pos); // up / down the drill
-
- m_object->SetAngleY(1, Math::Rand()*0.5f); // rotates the drill
- }
- return true;
- }
-
- if ( m_phase == ADP_EXCAVATE )
- {
- if ( m_soundChannel == -1 )
- {
- if ( m_type == OBJECT_URANIUM )
- {
- factor = DERRICK_DELAYu/DERRICK_DELAY;
- }
- else
- {
- factor = 1.0f;
- }
- m_soundChannel = m_sound->Play(SOUND_DERRICK, m_object->RetPosition(0), 1.0f, 0.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 4.0f*factor, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.3f, 6.0f*factor, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 4.0f, SOPER_STOP);
- }
-
- if ( m_progress >= 6.0f/16.0f && // penetrates into the ground?
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = Math::Rand()*5.0f;
- dim.x = Math::Rand()*3.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
-
- if ( m_progress >= 6.0f/16.0f && // penetrates into the ground?
- m_lastTrack+m_engine->ParticuleAdapt(0.5f) <= m_time )
- {
- m_lastTrack = m_time;
-
- pos = m_object->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*12.0f;
- speed.z = (Math::Rand()-0.5f)*12.0f;
- speed.y = Math::Rand()*10.0f+10.0f;
- dim.x = 0.6f;
- dim.y = dim.x;
- pos.y += dim.y;
- duration = Math::Rand()*2.0f+2.0f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK5,
- duration, Math::Rand()*10.0f+15.0f,
- duration*0.2f, 1.0f);
- }
-
- if ( m_progress < 1.0f )
- {
- pos.x = 0.0f;
- pos.z = 0.0f;
- pos.y = -m_progress*16.0f;
- m_object->SetPosition(1, pos); // down the drill
-
- angle = m_object->RetAngleY(1);
- angle += event.rTime*8.0f;
- m_object->SetAngleY(1, angle); // rotates the drill
- }
- else
- {
- m_phase = ADP_ASCEND;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- }
- }
-
- if ( m_phase == ADP_ASCEND )
- {
- if ( m_progress <= 7.0f/16.0f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = Math::Rand()*5.0f;
- dim.x = Math::Rand()*3.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
-
- if ( m_progress <= 4.0f/16.0f &&
- m_lastTrack+m_engine->ParticuleAdapt(1.0f) <= m_time )
- {
- m_lastTrack = m_time;
-
- pos = m_object->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*12.0f;
- speed.z = (Math::Rand()-0.5f)*12.0f;
- speed.y = Math::Rand()*10.0f+10.0f;
- dim.x = 0.6f;
- dim.y = dim.x;
- pos.y += dim.y;
- duration = Math::Rand()*2.0f+2.0f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK5,
- duration, Math::Rand()*10.0f+15.0f,
- duration*0.2f, 1.0f);
- }
-
- if ( m_progress < 1.0f )
- {
- pos.x = 0.0f;
- pos.z = 0.0f;
- pos.y = -(1.0f-m_progress)*16.0f;
- m_object->SetPosition(1, pos); // back the drill
-
- angle = m_object->RetAngleY(1);
- angle -= event.rTime*2.0f;
- m_object->SetAngleY(1, angle); // rotates the drill
- }
- else
- {
- m_soundChannel = -1;
- m_bSoundFall = false;
-
- m_phase = ADP_EXPORT;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- }
- }
-
- if ( m_phase == ADP_ISFREE )
- {
- if ( m_progress >= 1.0f )
- {
- m_bSoundFall = false;
-
- m_phase = ADP_EXPORT;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- }
- }
-
- if ( m_phase == ADP_EXPORT )
- {
- if ( m_progress == 0.0f )
- {
- if ( SearchFree(m_fretPos) )
- {
- angle = m_object->RetAngleY(0);
- CreateFret(m_fretPos, angle, m_type, 16.0f);
- }
- else
- {
- m_phase = ADP_ISFREE;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- return true;
- }
- }
-
- fret = SearchFret();
-
- if ( fret != 0 &&
- m_progress <= 0.5f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
- {
- m_lastParticule = m_time;
-
- if ( m_progress < 0.3f )
- {
- pos = fret->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- pos.y += (Math::Rand()-0.5f)*5.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 3.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFIRE, 1.0f, 0.0f, 0.0f);
- }
- else
- {
- pos = fret->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- pos.y += Math::Rand()*2.5f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
- }
- }
-
- if ( m_progress < 1.0f )
- {
- if ( fret != 0 )
- {
- pos = fret->RetPosition(0);
- pos.y -= event.rTime*20.0f; // grave
- if ( !m_bSoundFall && pos.y < m_fretPos.y )
- {
- m_sound->Play(SOUND_BOUM, m_fretPos);
- m_bSoundFall = true;
- }
- if ( pos.y < m_fretPos.y )
- {
- pos.y = m_fretPos.y;
- fret->SetLock(false); // object usable
- }
- fret->SetPosition(0, pos);
- }
- }
- else
- {
- if ( ExistKey() ) // key already exists?
- {
- m_phase = ADP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/10.0f;
- }
- else
- {
- m_phase = ADP_EXCAVATE;
- m_progress = 0.0f;
- m_speed = 1.0f/(m_type==OBJECT_URANIUM?DERRICK_DELAYu:DERRICK_DELAY);
- }
- }
- }
-
- return true;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoDerrick::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 109, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoDerrick::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == ADP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoDerrick::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoDerrickPhase)OpInt(line, "aPhase", ADP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
-// Seeks the subject cargo.
-
-CObject* CAutoDerrick::SearchFret()
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_DERRICK ) continue;
-
- oPos = pObj->RetPosition(0);
-
- if ( oPos.x == m_fretPos.x &&
- oPos.z == m_fretPos.z ) return pObj;
- }
-
- return 0;
-}
-
-// Seeks if a site is free.
-
-bool CAutoDerrick::SearchFree(Math::Vector pos)
-{
- CObject* pObj;
- Math::Vector sPos;
- ObjectType type;
- float sRadius, distance;
- int i, j;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_DERRICK ) continue;
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, sPos, sRadius) )
- {
- distance = Math::Distance(sPos, pos);
- distance -= sRadius;
- if ( distance < 2.0f ) return false; // location occupied
- }
- }
-
- return true; // location free
-}
-
-// Create a transportable object.
-
-void CAutoDerrick::CreateFret(Math::Vector pos, float angle, ObjectType type,
- float height)
-{
- CObject* fret;
-
- fret = new CObject(m_iMan);
- if ( !fret->CreateResource(pos, angle, type) )
- {
- delete fret;
- m_displayText->DisplayError(ERR_TOOMANY, m_object);
- return;
- }
- fret->SetLock(true); // object not yet usable
-
- if ( m_object->RetResetCap() == RESET_MOVE )
- {
- fret->SetResetCap(RESET_DELETE);
- }
-
- pos = fret->RetPosition(0);
- pos.y += height;
- fret->SetPosition(0, pos);
-}
-
-// Look if there is already a key.
-
-bool CAutoDerrick::ExistKey()
-{
- CObject* pObj;
- ObjectType type;
- int i;
-
- if ( m_type != OBJECT_KEYa &&
- m_type != OBJECT_KEYb &&
- m_type != OBJECT_KEYc &&
- m_type != OBJECT_KEYd ) return false;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == m_type ) return true;
- }
-
- return false;
-}
-
-
-// Returns an error due the state of the automaton.
-
-Error CAutoDerrick::RetError()
-{
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- if ( m_phase == ADP_WAIT ) return ERR_DERRICK_NULL;
- return ERR_OK;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoderrick.h"
+
+#include "common/iman.h"
+#include "old/terrain.h"
+#include "math/geometry.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+
+
+
+
+const float DERRICK_DELAY = 10.0f; // duration of the extraction
+const float DERRICK_DELAYu = 30.0f; // same, but for uranium
+
+
+
+
+// Object's constructor.
+
+CAutoDerrick::CAutoDerrick(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+ m_phase = ADP_WAIT; // paused until the first Init ()
+ m_soundChannel = -1;
+}
+
+// Object's destructor.
+
+CAutoDerrick::~CAutoDerrick()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoDerrick::DeleteObject(bool bAll)
+{
+ CObject* fret;
+
+ if ( !bAll )
+ {
+ fret = SearchFret();
+ if ( fret != 0 && fret->RetLock() )
+ {
+ fret->DeleteObject();
+ delete fret;
+ }
+ }
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoDerrick::Init()
+{
+ Math::Matrix* mat;
+ Math::Vector pos;
+ TerrainRes res;
+
+ pos = m_object->RetPosition(0);
+ res = m_terrain->RetResource(pos);
+
+ if ( res == TR_STONE ||
+ res == TR_URANIUM ||
+ res == TR_KEYa ||
+ res == TR_KEYb ||
+ res == TR_KEYc ||
+ res == TR_KEYd )
+ {
+ m_type = OBJECT_FRET;
+ if ( res == TR_STONE ) m_type = OBJECT_STONE;
+ if ( res == TR_URANIUM ) m_type = OBJECT_URANIUM;
+ if ( res == TR_KEYa ) m_type = OBJECT_KEYa;
+ if ( res == TR_KEYb ) m_type = OBJECT_KEYb;
+ if ( res == TR_KEYc ) m_type = OBJECT_KEYc;
+ if ( res == TR_KEYd ) m_type = OBJECT_KEYd;
+
+ m_phase = ADP_EXCAVATE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/(m_type==OBJECT_URANIUM?DERRICK_DELAYu:DERRICK_DELAY);
+ }
+ else
+ {
+ m_phase = ADP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f;
+ }
+
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+ m_lastTrack = 0.0f;
+
+ pos = Math::Vector(7.0f, 0.0f, 0.0f);
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Transform(*mat, pos);
+ m_terrain->MoveOnFloor(pos);
+ m_fretPos = pos;
+}
+
+
+// Management of an event.
+
+bool CAutoDerrick::EventProcess(const Event &event)
+{
+ CObject* fret;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float angle, duration, factor;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_phase == ADP_WAIT ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+
+ pos.x = 0.0f;
+ pos.z = 0.0f;
+ pos.y = -2.0f*Math::Rand();
+ m_object->SetPosition(1, pos); // up / down the drill
+
+ m_object->SetAngleY(1, Math::Rand()*0.5f); // rotates the drill
+ }
+ return true;
+ }
+
+ if ( m_phase == ADP_EXCAVATE )
+ {
+ if ( m_soundChannel == -1 )
+ {
+ if ( m_type == OBJECT_URANIUM )
+ {
+ factor = DERRICK_DELAYu/DERRICK_DELAY;
+ }
+ else
+ {
+ factor = 1.0f;
+ }
+ m_soundChannel = m_sound->Play(SOUND_DERRICK, m_object->RetPosition(0), 1.0f, 0.5f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 4.0f*factor, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.3f, 6.0f*factor, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 4.0f, SOPER_STOP);
+ }
+
+ if ( m_progress >= 6.0f/16.0f && // penetrates into the ground?
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = Math::Rand()*5.0f;
+ dim.x = Math::Rand()*3.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+
+ if ( m_progress >= 6.0f/16.0f && // penetrates into the ground?
+ m_lastTrack+m_engine->ParticuleAdapt(0.5f) <= m_time )
+ {
+ m_lastTrack = m_time;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*12.0f;
+ speed.z = (Math::Rand()-0.5f)*12.0f;
+ speed.y = Math::Rand()*10.0f+10.0f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ pos.y += dim.y;
+ duration = Math::Rand()*2.0f+2.0f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK5,
+ duration, Math::Rand()*10.0f+15.0f,
+ duration*0.2f, 1.0f);
+ }
+
+ if ( m_progress < 1.0f )
+ {
+ pos.x = 0.0f;
+ pos.z = 0.0f;
+ pos.y = -m_progress*16.0f;
+ m_object->SetPosition(1, pos); // down the drill
+
+ angle = m_object->RetAngleY(1);
+ angle += event.rTime*8.0f;
+ m_object->SetAngleY(1, angle); // rotates the drill
+ }
+ else
+ {
+ m_phase = ADP_ASCEND;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ }
+ }
+
+ if ( m_phase == ADP_ASCEND )
+ {
+ if ( m_progress <= 7.0f/16.0f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = Math::Rand()*5.0f;
+ dim.x = Math::Rand()*3.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+
+ if ( m_progress <= 4.0f/16.0f &&
+ m_lastTrack+m_engine->ParticuleAdapt(1.0f) <= m_time )
+ {
+ m_lastTrack = m_time;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*12.0f;
+ speed.z = (Math::Rand()-0.5f)*12.0f;
+ speed.y = Math::Rand()*10.0f+10.0f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ pos.y += dim.y;
+ duration = Math::Rand()*2.0f+2.0f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK5,
+ duration, Math::Rand()*10.0f+15.0f,
+ duration*0.2f, 1.0f);
+ }
+
+ if ( m_progress < 1.0f )
+ {
+ pos.x = 0.0f;
+ pos.z = 0.0f;
+ pos.y = -(1.0f-m_progress)*16.0f;
+ m_object->SetPosition(1, pos); // back the drill
+
+ angle = m_object->RetAngleY(1);
+ angle -= event.rTime*2.0f;
+ m_object->SetAngleY(1, angle); // rotates the drill
+ }
+ else
+ {
+ m_soundChannel = -1;
+ m_bSoundFall = false;
+
+ m_phase = ADP_EXPORT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ }
+ }
+
+ if ( m_phase == ADP_ISFREE )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_bSoundFall = false;
+
+ m_phase = ADP_EXPORT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ }
+ }
+
+ if ( m_phase == ADP_EXPORT )
+ {
+ if ( m_progress == 0.0f )
+ {
+ if ( SearchFree(m_fretPos) )
+ {
+ angle = m_object->RetAngleY(0);
+ CreateFret(m_fretPos, angle, m_type, 16.0f);
+ }
+ else
+ {
+ m_phase = ADP_ISFREE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ return true;
+ }
+ }
+
+ fret = SearchFret();
+
+ if ( fret != 0 &&
+ m_progress <= 0.5f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ if ( m_progress < 0.3f )
+ {
+ pos = fret->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ pos.y += (Math::Rand()-0.5f)*5.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 3.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFIRE, 1.0f, 0.0f, 0.0f);
+ }
+ else
+ {
+ pos = fret->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ pos.y += Math::Rand()*2.5f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
+ }
+ }
+
+ if ( m_progress < 1.0f )
+ {
+ if ( fret != 0 )
+ {
+ pos = fret->RetPosition(0);
+ pos.y -= event.rTime*20.0f; // grave
+ if ( !m_bSoundFall && pos.y < m_fretPos.y )
+ {
+ m_sound->Play(SOUND_BOUM, m_fretPos);
+ m_bSoundFall = true;
+ }
+ if ( pos.y < m_fretPos.y )
+ {
+ pos.y = m_fretPos.y;
+ fret->SetLock(false); // object usable
+ }
+ fret->SetPosition(0, pos);
+ }
+ }
+ else
+ {
+ if ( ExistKey() ) // key already exists?
+ {
+ m_phase = ADP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/10.0f;
+ }
+ else
+ {
+ m_phase = ADP_EXCAVATE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/(m_type==OBJECT_URANIUM?DERRICK_DELAYu:DERRICK_DELAY);
+ }
+ }
+ }
+
+ return true;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoDerrick::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 109, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoDerrick::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == ADP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoDerrick::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoDerrickPhase)OpInt(line, "aPhase", ADP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
+// Seeks the subject cargo.
+
+CObject* CAutoDerrick::SearchFret()
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ ObjectType type;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_DERRICK ) continue;
+
+ oPos = pObj->RetPosition(0);
+
+ if ( oPos.x == m_fretPos.x &&
+ oPos.z == m_fretPos.z ) return pObj;
+ }
+
+ return 0;
+}
+
+// Seeks if a site is free.
+
+bool CAutoDerrick::SearchFree(Math::Vector pos)
+{
+ CObject* pObj;
+ Math::Vector sPos;
+ ObjectType type;
+ float sRadius, distance;
+ int i, j;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_DERRICK ) continue;
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, sPos, sRadius) )
+ {
+ distance = Math::Distance(sPos, pos);
+ distance -= sRadius;
+ if ( distance < 2.0f ) return false; // location occupied
+ }
+ }
+
+ return true; // location free
+}
+
+// Create a transportable object.
+
+void CAutoDerrick::CreateFret(Math::Vector pos, float angle, ObjectType type,
+ float height)
+{
+ CObject* fret;
+
+ fret = new CObject(m_iMan);
+ if ( !fret->CreateResource(pos, angle, type) )
+ {
+ delete fret;
+ m_displayText->DisplayError(ERR_TOOMANY, m_object);
+ return;
+ }
+ fret->SetLock(true); // object not yet usable
+
+ if ( m_object->RetResetCap() == RESET_MOVE )
+ {
+ fret->SetResetCap(RESET_DELETE);
+ }
+
+ pos = fret->RetPosition(0);
+ pos.y += height;
+ fret->SetPosition(0, pos);
+}
+
+// Look if there is already a key.
+
+bool CAutoDerrick::ExistKey()
+{
+ CObject* pObj;
+ ObjectType type;
+ int i;
+
+ if ( m_type != OBJECT_KEYa &&
+ m_type != OBJECT_KEYb &&
+ m_type != OBJECT_KEYc &&
+ m_type != OBJECT_KEYd ) return false;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == m_type ) return true;
+ }
+
+ return false;
+}
+
+
+// Returns an error due the state of the automaton.
+
+Error CAutoDerrick::RetError()
+{
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ if ( m_phase == ADP_WAIT ) return ERR_DERRICK_NULL;
+ return ERR_OK;
+}
+
+
diff --git a/src/object/auto/autoderrick.h b/src/object/auto/autoderrick.h
index e211c0f..61a1ff1 100644
--- a/src/object/auto/autoderrick.h
+++ b/src/object/auto/autoderrick.h
@@ -1,71 +1,71 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoderrick.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoDerrickPhase
-{
- ADP_WAIT = 1,
- ADP_EXCAVATE = 2, // down the drill
- ADP_ASCEND = 3, // up the drill
- ADP_EXPORT = 4, // exports matter
- ADP_ISFREE = 5, // expected material loss
-};
-
-
-
-class CAutoDerrick : public CAuto
-{
-public:
- CAutoDerrick(CInstanceManager* iMan, CObject* object);
- ~CAutoDerrick();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- CObject* SearchFret();
- bool SearchFree(Math::Vector pos);
- void CreateFret(Math::Vector pos, float angle, ObjectType type, float height);
- bool ExistKey();
-
-protected:
- AutoDerrickPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
- float m_lastTrack;
- Math::Vector m_fretPos;
- int m_soundChannel;
- bool m_bSoundFall;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoderrick.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoDerrickPhase
+{
+ ADP_WAIT = 1,
+ ADP_EXCAVATE = 2, // down the drill
+ ADP_ASCEND = 3, // up the drill
+ ADP_EXPORT = 4, // exports matter
+ ADP_ISFREE = 5, // expected material loss
+};
+
+
+
+class CAutoDerrick : public CAuto
+{
+public:
+ CAutoDerrick(CInstanceManager* iMan, CObject* object);
+ ~CAutoDerrick();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ CObject* SearchFret();
+ bool SearchFree(Math::Vector pos);
+ void CreateFret(Math::Vector pos, float angle, ObjectType type, float height);
+ bool ExistKey();
+
+protected:
+ AutoDerrickPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+ float m_lastTrack;
+ Math::Vector m_fretPos;
+ int m_soundChannel;
+ bool m_bSoundFall;
+};
+
diff --git a/src/object/auto/autodestroyer.cpp b/src/object/auto/autodestroyer.cpp
index f1f018c..b40c374 100644
--- a/src/object/auto/autodestroyer.cpp
+++ b/src/object/auto/autodestroyer.cpp
@@ -1,374 +1,374 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autodestroyer.h"
-
-#include "common/iman.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-
-
-
-
-// Object's constructor.
-
-CAutoDestroyer::CAutoDestroyer(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
- m_phase = ADEP_WAIT; // paused until the first Init ()
-}
-
-// Destructive of the object.
-
-CAutoDestroyer::~CAutoDestroyer()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoDestroyer::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoDestroyer::Init()
-{
- m_phase = ADEP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/0.5f;
-
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastParticule = 0.0f;
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoDestroyer::EventProcess(const Event &event)
-{
- CObject* scrap;
- CPyro* pyro;
- Math::Vector pos, speed;
- Math::Point dim;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
- }
- return true;
- }
-
- if ( m_phase == ADEP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- scrap = SearchPlastic();
- if ( scrap == 0 )
- {
- m_phase = ADEP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/0.5f;
- }
- else
- {
- scrap->SetLock(true); // usable waste
-//? scrap->SetTruck(m_object); // usable waste
-
- if ( SearchVehicle() )
- {
- m_phase = ADEP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/0.5f;
- }
- else
- {
- m_sound->Play(SOUND_PSHHH2, m_object->RetPosition(0), 1.0f, 1.0f);
-
- m_phase = ADEP_DOWN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- m_bExplo = false;
- }
- }
- }
- }
-
- if ( m_phase == ADEP_DOWN )
- {
- if ( m_progress >= 0.3f-0.05f && !m_bExplo )
- {
- scrap = SearchPlastic();
- if ( scrap != 0 )
- {
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FRAGT, scrap);
- }
- m_bExplo = true;
- }
-
- if ( m_progress < 1.0f )
- {
- pos = Math::Vector(0.0f, -10.0f, 0.0f);
- pos.y = -Math::Bounce(m_progress, 0.3f)*10.0f;
- m_object->SetPosition(1, pos);
- }
- else
- {
- m_object->SetPosition(1, Math::Vector(0.0f, -10.0f, 0.0f));
- m_sound->Play(SOUND_REPAIR, m_object->RetPosition(0));
-
- m_phase = ADEP_REPAIR;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ADEP_REPAIR )
- {
- if ( m_progress < 1.0f )
- {
- }
- else
- {
- m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 0.8f);
-
- m_phase = ADEP_UP;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- }
- }
-
- if ( m_phase == ADEP_UP )
- {
- if ( m_progress < 1.0f )
- {
- pos = Math::Vector(0.0f, -10.0f, 0.0f);
- pos.y = -(1.0f-m_progress)*10.0f;
- m_object->SetPosition(1, pos);
- }
- else
- {
- m_object->SetPosition(1, Math::Vector(0.0f, 0.0f, 0.0f));
-
- m_phase = ADEP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/0.5f;
- }
- }
-
- return true;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoDestroyer::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 106, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-
-// Seeks plate waste in the destroyer.
-
-CObject* CAutoDestroyer::SearchPlastic()
-{
- CObject* pObj;
- Math::Vector sPos, oPos;
- ObjectType type;
- float dist;
- int i;
-
- sPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_SCRAP4 &&
- type != OBJECT_SCRAP5 ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, sPos);
- if ( dist <= 5.0f ) return pObj;
- }
-
- return 0;
-}
-
-// Seeks if one vehicle is too close.
-
-bool CAutoDestroyer::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType type;
- float oRadius, dist;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr &&
- type != OBJECT_MOTHER &&
- type != OBJECT_ANT &&
- type != OBJECT_SPIDER &&
- type != OBJECT_BEE &&
- type != OBJECT_WORM ) continue;
-
- if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
- dist = Math::Distance(oPos, cPos)-oRadius;
-
- if ( dist < 20.0f ) return true;
- }
-
- return false;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoDestroyer::RetError()
-{
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- return ERR_OK;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoDestroyer::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == ADEP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoDestroyer::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoDestroyerPhase)OpInt(line, "aPhase", ADEP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autodestroyer.h"
+
+#include "common/iman.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+
+
+
+
+// Object's constructor.
+
+CAutoDestroyer::CAutoDestroyer(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+ m_phase = ADEP_WAIT; // paused until the first Init ()
+}
+
+// Destructive of the object.
+
+CAutoDestroyer::~CAutoDestroyer()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoDestroyer::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoDestroyer::Init()
+{
+ m_phase = ADEP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/0.5f;
+
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoDestroyer::EventProcess(const Event &event)
+{
+ CObject* scrap;
+ CPyro* pyro;
+ Math::Vector pos, speed;
+ Math::Point dim;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+ }
+ return true;
+ }
+
+ if ( m_phase == ADEP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ scrap = SearchPlastic();
+ if ( scrap == 0 )
+ {
+ m_phase = ADEP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/0.5f;
+ }
+ else
+ {
+ scrap->SetLock(true); // usable waste
+//? scrap->SetTruck(m_object); // usable waste
+
+ if ( SearchVehicle() )
+ {
+ m_phase = ADEP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/0.5f;
+ }
+ else
+ {
+ m_sound->Play(SOUND_PSHHH2, m_object->RetPosition(0), 1.0f, 1.0f);
+
+ m_phase = ADEP_DOWN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ m_bExplo = false;
+ }
+ }
+ }
+ }
+
+ if ( m_phase == ADEP_DOWN )
+ {
+ if ( m_progress >= 0.3f-0.05f && !m_bExplo )
+ {
+ scrap = SearchPlastic();
+ if ( scrap != 0 )
+ {
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FRAGT, scrap);
+ }
+ m_bExplo = true;
+ }
+
+ if ( m_progress < 1.0f )
+ {
+ pos = Math::Vector(0.0f, -10.0f, 0.0f);
+ pos.y = -Math::Bounce(m_progress, 0.3f)*10.0f;
+ m_object->SetPosition(1, pos);
+ }
+ else
+ {
+ m_object->SetPosition(1, Math::Vector(0.0f, -10.0f, 0.0f));
+ m_sound->Play(SOUND_REPAIR, m_object->RetPosition(0));
+
+ m_phase = ADEP_REPAIR;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ADEP_REPAIR )
+ {
+ if ( m_progress < 1.0f )
+ {
+ }
+ else
+ {
+ m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 0.8f);
+
+ m_phase = ADEP_UP;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ }
+ }
+
+ if ( m_phase == ADEP_UP )
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos = Math::Vector(0.0f, -10.0f, 0.0f);
+ pos.y = -(1.0f-m_progress)*10.0f;
+ m_object->SetPosition(1, pos);
+ }
+ else
+ {
+ m_object->SetPosition(1, Math::Vector(0.0f, 0.0f, 0.0f));
+
+ m_phase = ADEP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/0.5f;
+ }
+ }
+
+ return true;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoDestroyer::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 106, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+
+// Seeks plate waste in the destroyer.
+
+CObject* CAutoDestroyer::SearchPlastic()
+{
+ CObject* pObj;
+ Math::Vector sPos, oPos;
+ ObjectType type;
+ float dist;
+ int i;
+
+ sPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_SCRAP4 &&
+ type != OBJECT_SCRAP5 ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, sPos);
+ if ( dist <= 5.0f ) return pObj;
+ }
+
+ return 0;
+}
+
+// Seeks if one vehicle is too close.
+
+bool CAutoDestroyer::SearchVehicle()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType type;
+ float oRadius, dist;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_HUMAN &&
+ type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis &&
+ type != OBJECT_MOBILErt &&
+ type != OBJECT_MOBILErc &&
+ type != OBJECT_MOBILErr &&
+ type != OBJECT_MOBILErs &&
+ type != OBJECT_MOBILEsa &&
+ type != OBJECT_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_MOBILEdr &&
+ type != OBJECT_MOTHER &&
+ type != OBJECT_ANT &&
+ type != OBJECT_SPIDER &&
+ type != OBJECT_BEE &&
+ type != OBJECT_WORM ) continue;
+
+ if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
+ dist = Math::Distance(oPos, cPos)-oRadius;
+
+ if ( dist < 20.0f ) return true;
+ }
+
+ return false;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoDestroyer::RetError()
+{
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ return ERR_OK;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoDestroyer::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == ADEP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoDestroyer::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoDestroyerPhase)OpInt(line, "aPhase", ADEP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autodestroyer.h b/src/object/auto/autodestroyer.h
index a233b88..88c93ea 100644
--- a/src/object/auto/autodestroyer.h
+++ b/src/object/auto/autodestroyer.h
@@ -1,65 +1,65 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autodestroyer.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoDestroyerPhase
-{
- ADEP_WAIT = 1, // expected metal
- ADEP_DOWN = 2, // down the cover
- ADEP_REPAIR = 3, // built the vehicle
- ADEP_UP = 4, // up the cover
-};
-
-
-
-class CAutoDestroyer : public CAuto
-{
-public:
- CAutoDestroyer(CInstanceManager* iMan, CObject* object);
- ~CAutoDestroyer();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- CObject* SearchPlastic();
- bool SearchVehicle();
-
-protected:
- AutoDestroyerPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
- bool m_bExplo;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autodestroyer.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoDestroyerPhase
+{
+ ADEP_WAIT = 1, // expected metal
+ ADEP_DOWN = 2, // down the cover
+ ADEP_REPAIR = 3, // built the vehicle
+ ADEP_UP = 4, // up the cover
+};
+
+
+
+class CAutoDestroyer : public CAuto
+{
+public:
+ CAutoDestroyer(CInstanceManager* iMan, CObject* object);
+ ~CAutoDestroyer();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ CObject* SearchPlastic();
+ bool SearchVehicle();
+
+protected:
+ AutoDestroyerPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+ bool m_bExplo;
+};
+
diff --git a/src/object/auto/autoegg.cpp b/src/object/auto/autoegg.cpp
index 773718c..b1e1c03 100644
--- a/src/object/auto/autoegg.cpp
+++ b/src/object/auto/autoegg.cpp
@@ -1,359 +1,359 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoegg.h"
-
-#include "math/geometry.h"
-#include "common/iman.h"
-#include "script/cmdtoken.h"
-
-
-
-
-// Object's constructor.
-
-CAutoEgg::CAutoEgg(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- m_type = OBJECT_NULL;
- m_value = 0.0f;
- m_string[0] = 0;
-
- m_param = 0;
- m_phase = AEP_NULL;
- Init();
-}
-
-// Object's destructor.
-
-CAutoEgg::~CAutoEgg()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoEgg::DeleteObject(bool bAll)
-{
- CObject* alien;
-
- CAuto::DeleteObject(bAll);
-
- if ( !bAll )
- {
- alien = SearchAlien();
- if ( alien != 0 )
- {
- // Probably the intended action
- // Original code: ( alien->RetZoom(0) == 1.0f )
- if ( alien->RetZoomY(0) == 1.0f )
- {
- alien->SetLock(false);
- alien->SetActivity(true); // the insect is active
- }
- else
- {
- alien->DeleteObject();
- delete alien;
- }
- }
- }
-}
-
-
-// Initialize the object.
-
-void CAutoEgg::Init()
-{
- CObject* alien;
-
- alien = SearchAlien();
- if ( alien == 0 )
- {
- m_phase = AEP_NULL;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- m_time = 0.0f;
- return;
- }
-
- m_phase = AEP_INCUB;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- m_time = 0.0f;
-
- m_type = alien->RetType();
-
- if ( m_type == OBJECT_ANT ||
- m_type == OBJECT_SPIDER ||
- m_type == OBJECT_BEE )
- {
- alien->SetZoom(0, 0.2f);
- }
- if ( m_type == OBJECT_WORM )
- {
- alien->SetZoom(0, 0.01f); // invisible !
- }
- alien->SetLock(true);
- alien->SetActivity(false);
-}
-
-
-// Gives a value.
-
-bool CAutoEgg::SetType(ObjectType type)
-{
- m_type = type;
- return true;
-}
-
-// Gives a value.
-
-bool CAutoEgg::SetValue(int rank, float value)
-{
- if ( rank != 0 ) return false;
- m_value = value;
- return true;
-}
-
-// Gives the string.
-
-bool CAutoEgg::SetString(char *string)
-{
- strcpy(m_string, string);
- return true;
-}
-
-
-// Start object.
-
-void CAutoEgg::Start(int param)
-{
- if ( m_type == OBJECT_NULL ) return;
- if ( m_value == 0.0f ) return;
-
- m_phase = AEP_DELAY;
- m_progress = 0.0f;
- m_speed = 1.0f/m_value;
-
- m_param = param;
-}
-
-
-// Management of an event.
-
-bool CAutoEgg::EventProcess(const Event &event)
-{
- CObject* alien;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
-
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_phase == AEP_NULL ) return true;
-
- if ( m_phase == AEP_DELAY )
- {
- m_progress += event.rTime*m_speed;
- if ( m_progress < 1.0f ) return true;
-
- alien = new CObject(m_iMan);
- if ( !alien->CreateInsect(m_object->RetPosition(0), m_object->RetAngleY(0), m_type) )
- {
- delete alien;
- m_phase = AEP_DELAY;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- return true;
- }
- alien->SetActivity(false);
- alien->ReadProgram(0, m_string);
- alien->RunProgram(0);
- Init();
- }
-
- alien = SearchAlien();
- if ( alien == 0 ) return true;
- alien->SetActivity(false);
-
- m_progress += event.rTime*m_speed;
-
- if ( m_phase == AEP_ZOOM )
- {
- if ( m_type == OBJECT_ANT ||
- m_type == OBJECT_SPIDER ||
- m_type == OBJECT_BEE )
- {
- alien->SetZoom(0, 0.2f+m_progress*0.8f); // Others push
- }
- }
-
- return true;
-}
-
-// Indicates whether the controller has completed its activity.
-
-Error CAutoEgg::IsEnded()
-{
- CObject* alien;
- CPyro* pyro;
-
- if ( m_phase == AEP_DELAY )
- {
- return ERR_CONTINUE;
- }
-
- alien = SearchAlien();
- if ( alien == 0 ) return ERR_STOP;
-
- if ( m_phase == AEP_INCUB )
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_phase = AEP_ZOOM;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- }
-
- if ( m_phase == AEP_ZOOM )
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_EGG, m_object); // exploding egg
-
- alien->SetZoom(0, 1.0f); // this is a big boy now
-
- m_phase = AEP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- }
-
- if ( m_phase == AEP_WAIT )
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- alien->SetLock(false);
- alien->SetActivity(true); // the insect is active
- }
-
- return ERR_STOP;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoEgg::RetError()
-{
- return ERR_OK;
-}
-
-
-// Seeking the insect that starts in the egg.
-
-CObject* CAutoEgg::SearchAlien()
-{
- CObject* pObj;
- CObject* pBest;
- Math::Vector cPos, oPos;
- ObjectType type;
- float dist, min;
- int i;
-
- cPos = m_object->RetPosition(0);
- min = 100000.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetTruck() != 0 ) continue;
-
- type = pObj->RetType();
- if ( type != OBJECT_ANT &&
- type != OBJECT_BEE &&
- type != OBJECT_SPIDER &&
- type != OBJECT_WORM ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, cPos);
- if ( dist < 8.0f && dist < min )
- {
- min = dist;
- pBest = pObj;
- }
- }
- return pBest;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoEgg::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == AEP_NULL ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.5f", m_speed);
- strcat(line, name);
-
- sprintf(name, " aParamType=%s", GetTypeObject(m_type));
- strcat(line, name);
-
- sprintf(name, " aParamValue1=%.2f", m_value);
- strcat(line, name);
-
- sprintf(name, " aParamString=\"%s\"", m_string);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoEgg::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoEggPhase)OpInt(line, "aPhase", AEP_NULL);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
- m_type = OpTypeObject(line, "aParamType", OBJECT_NULL);
- m_value = OpFloat(line, "aParamValue1", 0.0f);
- OpString(line, "aParamString", m_string);
-
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoegg.h"
+
+#include "math/geometry.h"
+#include "common/iman.h"
+#include "script/cmdtoken.h"
+
+
+
+
+// Object's constructor.
+
+CAutoEgg::CAutoEgg(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ m_type = OBJECT_NULL;
+ m_value = 0.0f;
+ m_string[0] = 0;
+
+ m_param = 0;
+ m_phase = AEP_NULL;
+ Init();
+}
+
+// Object's destructor.
+
+CAutoEgg::~CAutoEgg()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoEgg::DeleteObject(bool bAll)
+{
+ CObject* alien;
+
+ CAuto::DeleteObject(bAll);
+
+ if ( !bAll )
+ {
+ alien = SearchAlien();
+ if ( alien != 0 )
+ {
+ // Probably the intended action
+ // Original code: ( alien->RetZoom(0) == 1.0f )
+ if ( alien->RetZoomY(0) == 1.0f )
+ {
+ alien->SetLock(false);
+ alien->SetActivity(true); // the insect is active
+ }
+ else
+ {
+ alien->DeleteObject();
+ delete alien;
+ }
+ }
+ }
+}
+
+
+// Initialize the object.
+
+void CAutoEgg::Init()
+{
+ CObject* alien;
+
+ alien = SearchAlien();
+ if ( alien == 0 )
+ {
+ m_phase = AEP_NULL;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ m_time = 0.0f;
+ return;
+ }
+
+ m_phase = AEP_INCUB;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ m_time = 0.0f;
+
+ m_type = alien->RetType();
+
+ if ( m_type == OBJECT_ANT ||
+ m_type == OBJECT_SPIDER ||
+ m_type == OBJECT_BEE )
+ {
+ alien->SetZoom(0, 0.2f);
+ }
+ if ( m_type == OBJECT_WORM )
+ {
+ alien->SetZoom(0, 0.01f); // invisible !
+ }
+ alien->SetLock(true);
+ alien->SetActivity(false);
+}
+
+
+// Gives a value.
+
+bool CAutoEgg::SetType(ObjectType type)
+{
+ m_type = type;
+ return true;
+}
+
+// Gives a value.
+
+bool CAutoEgg::SetValue(int rank, float value)
+{
+ if ( rank != 0 ) return false;
+ m_value = value;
+ return true;
+}
+
+// Gives the string.
+
+bool CAutoEgg::SetString(char *string)
+{
+ strcpy(m_string, string);
+ return true;
+}
+
+
+// Start object.
+
+void CAutoEgg::Start(int param)
+{
+ if ( m_type == OBJECT_NULL ) return;
+ if ( m_value == 0.0f ) return;
+
+ m_phase = AEP_DELAY;
+ m_progress = 0.0f;
+ m_speed = 1.0f/m_value;
+
+ m_param = param;
+}
+
+
+// Management of an event.
+
+bool CAutoEgg::EventProcess(const Event &event)
+{
+ CObject* alien;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_phase == AEP_NULL ) return true;
+
+ if ( m_phase == AEP_DELAY )
+ {
+ m_progress += event.rTime*m_speed;
+ if ( m_progress < 1.0f ) return true;
+
+ alien = new CObject(m_iMan);
+ if ( !alien->CreateInsect(m_object->RetPosition(0), m_object->RetAngleY(0), m_type) )
+ {
+ delete alien;
+ m_phase = AEP_DELAY;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ return true;
+ }
+ alien->SetActivity(false);
+ alien->ReadProgram(0, m_string);
+ alien->RunProgram(0);
+ Init();
+ }
+
+ alien = SearchAlien();
+ if ( alien == 0 ) return true;
+ alien->SetActivity(false);
+
+ m_progress += event.rTime*m_speed;
+
+ if ( m_phase == AEP_ZOOM )
+ {
+ if ( m_type == OBJECT_ANT ||
+ m_type == OBJECT_SPIDER ||
+ m_type == OBJECT_BEE )
+ {
+ alien->SetZoom(0, 0.2f+m_progress*0.8f); // Others push
+ }
+ }
+
+ return true;
+}
+
+// Indicates whether the controller has completed its activity.
+
+Error CAutoEgg::IsEnded()
+{
+ CObject* alien;
+ CPyro* pyro;
+
+ if ( m_phase == AEP_DELAY )
+ {
+ return ERR_CONTINUE;
+ }
+
+ alien = SearchAlien();
+ if ( alien == 0 ) return ERR_STOP;
+
+ if ( m_phase == AEP_INCUB )
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_phase = AEP_ZOOM;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ }
+
+ if ( m_phase == AEP_ZOOM )
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_EGG, m_object); // exploding egg
+
+ alien->SetZoom(0, 1.0f); // this is a big boy now
+
+ m_phase = AEP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ }
+
+ if ( m_phase == AEP_WAIT )
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ alien->SetLock(false);
+ alien->SetActivity(true); // the insect is active
+ }
+
+ return ERR_STOP;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoEgg::RetError()
+{
+ return ERR_OK;
+}
+
+
+// Seeking the insect that starts in the egg.
+
+CObject* CAutoEgg::SearchAlien()
+{
+ CObject* pObj;
+ CObject* pBest;
+ Math::Vector cPos, oPos;
+ ObjectType type;
+ float dist, min;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+ min = 100000.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_ANT &&
+ type != OBJECT_BEE &&
+ type != OBJECT_SPIDER &&
+ type != OBJECT_WORM ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, cPos);
+ if ( dist < 8.0f && dist < min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+ return pBest;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoEgg::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == AEP_NULL ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.5f", m_speed);
+ strcat(line, name);
+
+ sprintf(name, " aParamType=%s", GetTypeObject(m_type));
+ strcat(line, name);
+
+ sprintf(name, " aParamValue1=%.2f", m_value);
+ strcat(line, name);
+
+ sprintf(name, " aParamString=\"%s\"", m_string);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoEgg::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoEggPhase)OpInt(line, "aPhase", AEP_NULL);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+ m_type = OpTypeObject(line, "aParamType", OBJECT_NULL);
+ m_value = OpFloat(line, "aParamValue1", 0.0f);
+ OpString(line, "aParamString", m_string);
+
+ return true;
+}
+
diff --git a/src/object/auto/autoegg.h b/src/object/auto/autoegg.h
index fcdf760..443dff6 100644
--- a/src/object/auto/autoegg.h
+++ b/src/object/auto/autoegg.h
@@ -1,69 +1,69 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoegg.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-enum AutoEggPhase
-{
- AEP_NULL = 0,
- AEP_DELAY = 1,
- AEP_INCUB = 3,
- AEP_ZOOM = 4,
- AEP_WAIT = 5,
-};
-
-
-
-class CAutoEgg : public CAuto
-{
-public:
- CAutoEgg(CInstanceManager* iMan, CObject* object);
- ~CAutoEgg();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- void Start(int param);
- bool EventProcess(const Event &event);
- Error IsEnded();
- Error RetError();
-
- bool SetType(ObjectType type);
- bool SetValue(int rank, float value);
- bool SetString(char *string);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- CObject* SearchAlien();
-
-protected:
- ObjectType m_type;
- float m_value;
- char m_string[100];
- int m_param;
- AutoEggPhase m_phase;
- float m_progress;
- float m_speed;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoegg.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+enum AutoEggPhase
+{
+ AEP_NULL = 0,
+ AEP_DELAY = 1,
+ AEP_INCUB = 3,
+ AEP_ZOOM = 4,
+ AEP_WAIT = 5,
+};
+
+
+
+class CAutoEgg : public CAuto
+{
+public:
+ CAutoEgg(CInstanceManager* iMan, CObject* object);
+ ~CAutoEgg();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ void Start(int param);
+ bool EventProcess(const Event &event);
+ Error IsEnded();
+ Error RetError();
+
+ bool SetType(ObjectType type);
+ bool SetValue(int rank, float value);
+ bool SetString(char *string);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ CObject* SearchAlien();
+
+protected:
+ ObjectType m_type;
+ float m_value;
+ char m_string[100];
+ int m_param;
+ AutoEggPhase m_phase;
+ float m_progress;
+ float m_speed;
+};
+
diff --git a/src/object/auto/autoenergy.cpp b/src/object/auto/autoenergy.cpp
index 74db234..37c2f29 100644
--- a/src/object/auto/autoenergy.cpp
+++ b/src/object/auto/autoenergy.cpp
@@ -1,647 +1,647 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoenergy.h"
-
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "math/geometry.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/gauge.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-
-
-
-const float ENERGY_POWER = 0.4f; // Necessary energy for a battery
-const float ENERGY_DELAY = 12.0f; // processing time
-
-
-
-
-// Object's constructor.
-
-CAutoEnergy::CAutoEnergy(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- m_partiSphere = -1;
- Init();
-}
-
-// Object's destructor.
-
-CAutoEnergy::~CAutoEnergy()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoEnergy::DeleteObject(bool bAll)
-{
- CObject* fret;
-
- if ( m_partiSphere != -1 )
- {
- m_particule->DeleteParticule(m_partiSphere);
- m_partiSphere = -1;
- }
-
- if ( !bAll )
- {
- fret = SearchMetal();
- if ( fret != 0 )
- {
- fret->DeleteObject(); // destroys the metal
- delete fret;
- }
-
- fret = SearchPower();
- if ( fret != 0 )
- {
- fret->DeleteObject(); // destroys the cell
- delete fret;
- }
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoEnergy::Init()
-{
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastUpdateTime = 0.0f;
- m_lastParticule = 0.0f;
-
- m_phase = AENP_WAIT; // waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoEnergy::EventProcess(const Event &event)
-{
- CObject* fret;
- Math::Vector pos, ppos, speed;
- Math::Point dim, c, p;
- TerrainRes res;
- float big;
- bool bGO;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
- pos = m_object->RetPosition(0);
- pos.y += 10.0f;
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = -7.0f;
- dim.x = Math::Rand()*0.5f+0.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ, 1.0f, 0.0f, 0.0f);
- }
- }
- return true;
- }
-
- UpdateInterface(event.rTime);
- EventProgress(event.rTime);
-
- big = m_object->RetEnergy();
-
- res = m_terrain->RetResource(m_object->RetPosition(0));
- if ( res == TR_POWER )
- {
- big += event.rTime*0.01f; // recharges the big pile
- }
-
- if ( m_phase == AENP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- bGO = false;
- fret = SearchMetal(); // transform metal?
- if ( fret != 0 )
- {
- if ( fret->RetType() == OBJECT_METAL )
- {
- if ( big > ENERGY_POWER ) bGO = true;
- }
- else
- {
- if ( !SearchVehicle() ) bGO = true;
- }
- }
-
- if ( bGO )
- {
- if ( fret->RetType() == OBJECT_METAL )
- {
- fret->SetLock(true); // usable metal
- CreatePower(); // creates the battery
- }
-
- SetBusy(true);
- InitProgressTotal(ENERGY_DELAY);
- CAuto::UpdateInterface();
-
- pos = m_object->RetPosition(0);
- pos.y += 4.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 3.0f;
- dim.y = dim.x;
- m_partiSphere = m_particule->CreateParticule(pos, speed, dim, PARTISPHERE1, ENERGY_DELAY, 0.0f, 0.0f);
-
- m_phase = AENP_CREATE;
- m_progress = 0.0f;
- m_speed = 1.0f/ENERGY_DELAY;
- }
- else
- {
- if ( rand()%3 == 0 && big > 0.01f )
- {
- m_phase = AENP_BLITZ;
- m_progress = 0.0f;
- m_speed = 1.0f/Math::Rand()*1.0f+1.0f;
- }
- else
- {
- m_phase = AENP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
- }
- }
-
- if ( m_phase == AENP_BLITZ )
- {
- if ( m_progress < 1.0f && big > 0.01f )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
- pos = m_object->RetPosition(0);
- pos.y += 10.0f;
- speed.x = (Math::Rand()-0.5f)*1.0f;
- speed.z = (Math::Rand()-0.5f)*1.0f;
- speed.y = -7.0f;
- dim.x = Math::Rand()*0.5f+0.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ, 1.0f, 0.0f, 0.0f);
- }
- }
- else
- {
- m_phase = AENP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == AENP_CREATE )
- {
- if ( m_progress < 1.0f )
- {
- fret = SearchMetal();
- if ( fret != 0 )
- {
- if ( fret->RetType() == OBJECT_METAL )
- {
- big -= event.rTime/ENERGY_DELAY*ENERGY_POWER;
- }
- else
- {
- big += event.rTime/ENERGY_DELAY*0.25f;
- }
- fret->SetZoom(0, 1.0f-m_progress);
- }
-
- fret = SearchPower();
- if ( fret != 0 )
- {
- fret->SetZoom(0, m_progress);
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- c.x = pos.x;
- c.y = pos.z;
- p.x = c.x;
- p.y = c.y+2.0f;
- p = Math::RotatePoint(c, Math::Rand()*Math::PI*2.0f, p);
- pos.x = p.x;
- pos.z = p.y;
- pos.y += 2.5f+Math::Rand()*3.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*2.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 1.0f, 0.0f, 0.0f);
-
- pos = m_object->RetPosition(0);
- pos.y += 3.0f;
- speed.x = (Math::Rand()-0.5f)*30.0f;
- speed.z = (Math::Rand()-0.5f)*30.0f;
- speed.y = Math::Rand()*20.0f+10.0f;
- dim.x = Math::Rand()*0.4f+0.4f;
- dim.y = dim.x;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK2, 2.0f, 50.0f, 1.2f, 1.2f);
-
- pos = m_object->RetPosition(0);
- pos.y += 10.0f;
- speed.x = (Math::Rand()-0.5f)*1.5f;
- speed.z = (Math::Rand()-0.5f)*1.5f;
- speed.y = -6.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ, 1.0f, 0.0f, 0.0f);
-
- m_sound->Play(SOUND_ENERGY, m_object->RetPosition(0),
- 1.0f, 1.0f+Math::Rand()*1.5f);
- }
- }
- else
- {
- fret = SearchMetal();
- if ( fret != 0 )
- {
- m_object->SetPower(0);
- fret->DeleteObject(); // destroys the metal
- delete fret;
- }
-
- fret = SearchPower();
- if ( fret != 0 )
- {
- fret->SetZoom(0, 1.0f);
- fret->SetLock(false); // usable battery
- fret->SetTruck(m_object);
- fret->SetPosition(0, Math::Vector(0.0f, 3.0f, 0.0f));
- m_object->SetPower(fret);
-
- m_displayText->DisplayError(INFO_ENERGY, m_object);
- }
-
- SetBusy(false);
- CAuto::UpdateInterface();
-
- m_phase = AENP_SMOKE;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- }
- }
-
- if ( m_phase == AENP_SMOKE )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.y += 17.0f;
- pos.x += (Math::Rand()-0.5f)*3.0f;
- pos.z += (Math::Rand()-0.5f)*3.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 6.0f+Math::Rand()*6.0f;
- dim.x = Math::Rand()*1.5f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
- }
- }
- else
- {
- m_phase = AENP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( big < 0.0f ) big = 0.0f;
- if ( big > 1.0f ) big = 1.0f;
- m_object->SetEnergy(big); // shift the big pile
-
- return true;
-}
-
-
-// Seeking the metal object.
-
-CObject* CAutoEnergy::SearchMetal()
-{
- CObject* pObj;
- ObjectType type;
-
- pObj = m_object->RetPower();
- if ( pObj == 0 ) return 0;
-
- type = pObj->RetType();
- if ( type == OBJECT_METAL ||
- type == OBJECT_SCRAP1 ||
- type == OBJECT_SCRAP2 ||
- type == OBJECT_SCRAP3 ) return pObj;
-
- return 0;
-}
-
-// Search if a vehicle is too close.
-
-bool CAutoEnergy::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType type;
- float oRadius, dist;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr &&
- type != OBJECT_MOTHER &&
- type != OBJECT_ANT &&
- type != OBJECT_SPIDER &&
- type != OBJECT_BEE &&
- type != OBJECT_WORM ) continue;
-
- if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
- dist = Math::Distance(oPos, cPos)-oRadius;
-
- if ( dist < 10.0f ) return true;
- }
-
- return false;
-}
-
-// Create a cell.
-
-void CAutoEnergy::CreatePower()
-{
- CObject* power;
- Math::Vector pos;
- float angle;
-
- pos = m_object->RetPosition(0);
- angle = m_object->RetAngleY(0);
-
- power = new CObject(m_iMan);
- if ( !power->CreateResource(pos, angle, OBJECT_POWER) )
- {
- delete power;
- m_displayText->DisplayError(ERR_TOOMANY, m_object);
- return;
- }
- power->SetLock(true); // battery not yet usable
-
- pos = power->RetPosition(0);
- pos.y += 3.0f;
- power->SetPosition(0, pos);
-}
-
-// Seeking the battery during manufacture.
-
-CObject* CAutoEnergy::SearchPower()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType type;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetLock() ) continue;
-
- type = pObj->RetType();
- if ( type != OBJECT_POWER ) continue;
-
- oPos = pObj->RetPosition(0);
- if ( oPos.x == cPos.x &&
- oPos.z == cPos.z )
- {
- return pObj;
- }
- }
-
- return 0;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoEnergy::RetError()
-{
- CObject* pObj;
- ObjectType type;
- TerrainRes res;
-
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- if ( m_phase != AENP_WAIT &&
- m_phase != AENP_BLITZ ) return ERR_OK;
-
- res = m_terrain->RetResource(m_object->RetPosition(0));
- if ( res != TR_POWER ) return ERR_ENERGY_NULL;
-
- if ( m_object->RetEnergy() < ENERGY_POWER ) return ERR_ENERGY_LOW;
-
- pObj = m_object->RetPower();
- if ( pObj == 0 ) return ERR_ENERGY_EMPTY;
- type = pObj->RetType();
- if ( type == OBJECT_POWER ) return ERR_OK;
- if ( type != OBJECT_METAL &&
- type != OBJECT_SCRAP1 &&
- type != OBJECT_SCRAP2 &&
- type != OBJECT_SCRAP3 ) return ERR_ENERGY_BAD;
-
- return ERR_OK;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoEnergy::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*14.5f;
- pos.y = oy+sy*0;
- ddim.x = 14.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 108, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-// Updates the state of all buttons on the interface,
-// following the time that elapses ...
-
-void CAutoEnergy::UpdateInterface(float rTime)
-{
- CWindow* pw;
- CGauge* pg;
-
- CAuto::UpdateInterface(rTime);
-
- if ( m_time < m_lastUpdateTime+0.1f ) return;
- m_lastUpdateTime = m_time;
-
- if ( !m_object->RetSelect() ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
- if ( pg != 0 )
- {
- pg->SetLevel(m_object->RetEnergy());
- }
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoEnergy::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == AENP_STOP ||
- m_phase == AENP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoEnergy::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoEnergyPhase)OpInt(line, "aPhase", AENP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastUpdateTime = 0.0f;
- m_lastParticule = 0.0f;
-
- return true;
-}
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoenergy.h"
+
+#include "common/iman.h"
+#include "old/terrain.h"
+#include "math/geometry.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/gauge.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+
+
+
+const float ENERGY_POWER = 0.4f; // Necessary energy for a battery
+const float ENERGY_DELAY = 12.0f; // processing time
+
+
+
+
+// Object's constructor.
+
+CAutoEnergy::CAutoEnergy(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ m_partiSphere = -1;
+ Init();
+}
+
+// Object's destructor.
+
+CAutoEnergy::~CAutoEnergy()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoEnergy::DeleteObject(bool bAll)
+{
+ CObject* fret;
+
+ if ( m_partiSphere != -1 )
+ {
+ m_particule->DeleteParticule(m_partiSphere);
+ m_partiSphere = -1;
+ }
+
+ if ( !bAll )
+ {
+ fret = SearchMetal();
+ if ( fret != 0 )
+ {
+ fret->DeleteObject(); // destroys the metal
+ delete fret;
+ }
+
+ fret = SearchPower();
+ if ( fret != 0 )
+ {
+ fret->DeleteObject(); // destroys the cell
+ delete fret;
+ }
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoEnergy::Init()
+{
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastUpdateTime = 0.0f;
+ m_lastParticule = 0.0f;
+
+ m_phase = AENP_WAIT; // waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoEnergy::EventProcess(const Event &event)
+{
+ CObject* fret;
+ Math::Vector pos, ppos, speed;
+ Math::Point dim, c, p;
+ TerrainRes res;
+ float big;
+ bool bGO;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+ pos = m_object->RetPosition(0);
+ pos.y += 10.0f;
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = -7.0f;
+ dim.x = Math::Rand()*0.5f+0.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ, 1.0f, 0.0f, 0.0f);
+ }
+ }
+ return true;
+ }
+
+ UpdateInterface(event.rTime);
+ EventProgress(event.rTime);
+
+ big = m_object->RetEnergy();
+
+ res = m_terrain->RetResource(m_object->RetPosition(0));
+ if ( res == TR_POWER )
+ {
+ big += event.rTime*0.01f; // recharges the big pile
+ }
+
+ if ( m_phase == AENP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ bGO = false;
+ fret = SearchMetal(); // transform metal?
+ if ( fret != 0 )
+ {
+ if ( fret->RetType() == OBJECT_METAL )
+ {
+ if ( big > ENERGY_POWER ) bGO = true;
+ }
+ else
+ {
+ if ( !SearchVehicle() ) bGO = true;
+ }
+ }
+
+ if ( bGO )
+ {
+ if ( fret->RetType() == OBJECT_METAL )
+ {
+ fret->SetLock(true); // usable metal
+ CreatePower(); // creates the battery
+ }
+
+ SetBusy(true);
+ InitProgressTotal(ENERGY_DELAY);
+ CAuto::UpdateInterface();
+
+ pos = m_object->RetPosition(0);
+ pos.y += 4.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 3.0f;
+ dim.y = dim.x;
+ m_partiSphere = m_particule->CreateParticule(pos, speed, dim, PARTISPHERE1, ENERGY_DELAY, 0.0f, 0.0f);
+
+ m_phase = AENP_CREATE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/ENERGY_DELAY;
+ }
+ else
+ {
+ if ( rand()%3 == 0 && big > 0.01f )
+ {
+ m_phase = AENP_BLITZ;
+ m_progress = 0.0f;
+ m_speed = 1.0f/Math::Rand()*1.0f+1.0f;
+ }
+ else
+ {
+ m_phase = AENP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+ }
+ }
+
+ if ( m_phase == AENP_BLITZ )
+ {
+ if ( m_progress < 1.0f && big > 0.01f )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+ pos = m_object->RetPosition(0);
+ pos.y += 10.0f;
+ speed.x = (Math::Rand()-0.5f)*1.0f;
+ speed.z = (Math::Rand()-0.5f)*1.0f;
+ speed.y = -7.0f;
+ dim.x = Math::Rand()*0.5f+0.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ, 1.0f, 0.0f, 0.0f);
+ }
+ }
+ else
+ {
+ m_phase = AENP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == AENP_CREATE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ fret = SearchMetal();
+ if ( fret != 0 )
+ {
+ if ( fret->RetType() == OBJECT_METAL )
+ {
+ big -= event.rTime/ENERGY_DELAY*ENERGY_POWER;
+ }
+ else
+ {
+ big += event.rTime/ENERGY_DELAY*0.25f;
+ }
+ fret->SetZoom(0, 1.0f-m_progress);
+ }
+
+ fret = SearchPower();
+ if ( fret != 0 )
+ {
+ fret->SetZoom(0, m_progress);
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ c.x = pos.x;
+ c.y = pos.z;
+ p.x = c.x;
+ p.y = c.y+2.0f;
+ p = Math::RotatePoint(c, Math::Rand()*Math::PI*2.0f, p);
+ pos.x = p.x;
+ pos.z = p.y;
+ pos.y += 2.5f+Math::Rand()*3.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*2.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 1.0f, 0.0f, 0.0f);
+
+ pos = m_object->RetPosition(0);
+ pos.y += 3.0f;
+ speed.x = (Math::Rand()-0.5f)*30.0f;
+ speed.z = (Math::Rand()-0.5f)*30.0f;
+ speed.y = Math::Rand()*20.0f+10.0f;
+ dim.x = Math::Rand()*0.4f+0.4f;
+ dim.y = dim.x;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK2, 2.0f, 50.0f, 1.2f, 1.2f);
+
+ pos = m_object->RetPosition(0);
+ pos.y += 10.0f;
+ speed.x = (Math::Rand()-0.5f)*1.5f;
+ speed.z = (Math::Rand()-0.5f)*1.5f;
+ speed.y = -6.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ, 1.0f, 0.0f, 0.0f);
+
+ m_sound->Play(SOUND_ENERGY, m_object->RetPosition(0),
+ 1.0f, 1.0f+Math::Rand()*1.5f);
+ }
+ }
+ else
+ {
+ fret = SearchMetal();
+ if ( fret != 0 )
+ {
+ m_object->SetPower(0);
+ fret->DeleteObject(); // destroys the metal
+ delete fret;
+ }
+
+ fret = SearchPower();
+ if ( fret != 0 )
+ {
+ fret->SetZoom(0, 1.0f);
+ fret->SetLock(false); // usable battery
+ fret->SetTruck(m_object);
+ fret->SetPosition(0, Math::Vector(0.0f, 3.0f, 0.0f));
+ m_object->SetPower(fret);
+
+ m_displayText->DisplayError(INFO_ENERGY, m_object);
+ }
+
+ SetBusy(false);
+ CAuto::UpdateInterface();
+
+ m_phase = AENP_SMOKE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ }
+ }
+
+ if ( m_phase == AENP_SMOKE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.y += 17.0f;
+ pos.x += (Math::Rand()-0.5f)*3.0f;
+ pos.z += (Math::Rand()-0.5f)*3.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 6.0f+Math::Rand()*6.0f;
+ dim.x = Math::Rand()*1.5f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
+ }
+ }
+ else
+ {
+ m_phase = AENP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( big < 0.0f ) big = 0.0f;
+ if ( big > 1.0f ) big = 1.0f;
+ m_object->SetEnergy(big); // shift the big pile
+
+ return true;
+}
+
+
+// Seeking the metal object.
+
+CObject* CAutoEnergy::SearchMetal()
+{
+ CObject* pObj;
+ ObjectType type;
+
+ pObj = m_object->RetPower();
+ if ( pObj == 0 ) return 0;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_METAL ||
+ type == OBJECT_SCRAP1 ||
+ type == OBJECT_SCRAP2 ||
+ type == OBJECT_SCRAP3 ) return pObj;
+
+ return 0;
+}
+
+// Search if a vehicle is too close.
+
+bool CAutoEnergy::SearchVehicle()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType type;
+ float oRadius, dist;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_HUMAN &&
+ type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis &&
+ type != OBJECT_MOBILErt &&
+ type != OBJECT_MOBILErc &&
+ type != OBJECT_MOBILErr &&
+ type != OBJECT_MOBILErs &&
+ type != OBJECT_MOBILEsa &&
+ type != OBJECT_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_MOBILEdr &&
+ type != OBJECT_MOTHER &&
+ type != OBJECT_ANT &&
+ type != OBJECT_SPIDER &&
+ type != OBJECT_BEE &&
+ type != OBJECT_WORM ) continue;
+
+ if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
+ dist = Math::Distance(oPos, cPos)-oRadius;
+
+ if ( dist < 10.0f ) return true;
+ }
+
+ return false;
+}
+
+// Create a cell.
+
+void CAutoEnergy::CreatePower()
+{
+ CObject* power;
+ Math::Vector pos;
+ float angle;
+
+ pos = m_object->RetPosition(0);
+ angle = m_object->RetAngleY(0);
+
+ power = new CObject(m_iMan);
+ if ( !power->CreateResource(pos, angle, OBJECT_POWER) )
+ {
+ delete power;
+ m_displayText->DisplayError(ERR_TOOMANY, m_object);
+ return;
+ }
+ power->SetLock(true); // battery not yet usable
+
+ pos = power->RetPosition(0);
+ pos.y += 3.0f;
+ power->SetPosition(0, pos);
+}
+
+// Seeking the battery during manufacture.
+
+CObject* CAutoEnergy::SearchPower()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType type;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetLock() ) continue;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_POWER ) continue;
+
+ oPos = pObj->RetPosition(0);
+ if ( oPos.x == cPos.x &&
+ oPos.z == cPos.z )
+ {
+ return pObj;
+ }
+ }
+
+ return 0;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoEnergy::RetError()
+{
+ CObject* pObj;
+ ObjectType type;
+ TerrainRes res;
+
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ if ( m_phase != AENP_WAIT &&
+ m_phase != AENP_BLITZ ) return ERR_OK;
+
+ res = m_terrain->RetResource(m_object->RetPosition(0));
+ if ( res != TR_POWER ) return ERR_ENERGY_NULL;
+
+ if ( m_object->RetEnergy() < ENERGY_POWER ) return ERR_ENERGY_LOW;
+
+ pObj = m_object->RetPower();
+ if ( pObj == 0 ) return ERR_ENERGY_EMPTY;
+ type = pObj->RetType();
+ if ( type == OBJECT_POWER ) return ERR_OK;
+ if ( type != OBJECT_METAL &&
+ type != OBJECT_SCRAP1 &&
+ type != OBJECT_SCRAP2 &&
+ type != OBJECT_SCRAP3 ) return ERR_ENERGY_BAD;
+
+ return ERR_OK;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoEnergy::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*14.5f;
+ pos.y = oy+sy*0;
+ ddim.x = 14.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 108, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+// Updates the state of all buttons on the interface,
+// following the time that elapses ...
+
+void CAutoEnergy::UpdateInterface(float rTime)
+{
+ CWindow* pw;
+ CGauge* pg;
+
+ CAuto::UpdateInterface(rTime);
+
+ if ( m_time < m_lastUpdateTime+0.1f ) return;
+ m_lastUpdateTime = m_time;
+
+ if ( !m_object->RetSelect() ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
+ if ( pg != 0 )
+ {
+ pg->SetLevel(m_object->RetEnergy());
+ }
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoEnergy::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == AENP_STOP ||
+ m_phase == AENP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoEnergy::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoEnergyPhase)OpInt(line, "aPhase", AENP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastUpdateTime = 0.0f;
+ m_lastParticule = 0.0f;
+
+ return true;
+}
diff --git a/src/object/auto/autoenergy.h b/src/object/auto/autoenergy.h
index 300ee45..727f2c3 100644
--- a/src/object/auto/autoenergy.h
+++ b/src/object/auto/autoenergy.h
@@ -1,71 +1,71 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoenergy.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoEnergyPhase
-{
- AENP_STOP = 1,
- AENP_WAIT = 2,
- AENP_BLITZ = 3,
- AENP_CREATE = 4,
- AENP_SMOKE = 5,
-};
-
-
-
-class CAutoEnergy : public CAuto
-{
-public:
- CAutoEnergy(CInstanceManager* iMan, CObject* object);
- ~CAutoEnergy();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- void UpdateInterface(float rTime);
-
- CObject* SearchMetal();
- bool SearchVehicle();
- void CreatePower();
- CObject* SearchPower();
-
-protected:
- AutoEnergyPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastUpdateTime;
- float m_lastParticule;
- int m_partiSphere;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoenergy.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoEnergyPhase
+{
+ AENP_STOP = 1,
+ AENP_WAIT = 2,
+ AENP_BLITZ = 3,
+ AENP_CREATE = 4,
+ AENP_SMOKE = 5,
+};
+
+
+
+class CAutoEnergy : public CAuto
+{
+public:
+ CAutoEnergy(CInstanceManager* iMan, CObject* object);
+ ~CAutoEnergy();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ void UpdateInterface(float rTime);
+
+ CObject* SearchMetal();
+ bool SearchVehicle();
+ void CreatePower();
+ CObject* SearchPower();
+
+protected:
+ AutoEnergyPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastUpdateTime;
+ float m_lastParticule;
+ int m_partiSphere;
+};
+
diff --git a/src/object/auto/autofactory.cpp b/src/object/auto/autofactory.cpp
index be5a189..f02195c 100644
--- a/src/object/auto/autofactory.cpp
+++ b/src/object/auto/autofactory.cpp
@@ -1,941 +1,941 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autofactory.h"
-
-#include "common/global.h"
-#include "common/iman.h"
-#include "math/geometry.h"
-#include "object/robotmain.h"
-#include "physics/physics.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-
-
-
-
-
-// Object's constructor.
-
-CAutoFactory::CAutoFactory(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
- m_type = OBJECT_MOBILEws;
- m_phase = AFP_WAIT; // paused until the first Init ()
- m_channelSound = -1;
-}
-
-// Object's destructor.
-
-CAutoFactory::~CAutoFactory()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoFactory::DeleteObject(bool bAll)
-{
- CObject* fret;
- CObject* vehicle;
-
- if ( !bAll )
- {
- fret = SearchFret(); // transform metal?
- if ( fret != 0 )
- {
- fret->DeleteObject(); // destroys the metal
- delete fret;
- }
-
- vehicle = SearchVehicle();
- if ( vehicle != 0 )
- {
- vehicle->DeleteObject(); // destroys the vehicle
- delete vehicle;
- }
- }
-
- if ( m_channelSound != -1 )
- {
- m_sound->FlushEnvelope(m_channelSound);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_channelSound = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoFactory::Init()
-{
- m_phase = AFP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- m_time = 0.0f;
- m_lastParticule = 0.0f;
-
- m_fretPos = m_object->RetPosition(0);
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoFactory::EventProcess(const Event &event)
-{
- CObject* fret;
- CObject* vehicle;
- Math::Matrix* mat;
- CPhysics* physics;
- Math::Vector pos, speed;
- Math::Point dim;
- ObjectType type;
- float zoom, angle, prog;
- int i;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
-
- if ( m_object->RetSelect() ) // factory selected?
- {
- if ( event.event == EVENT_UPDINTERFACE )
- {
- CreateInterface(true);
- }
-
- type = OBJECT_NULL;
- if ( event.event == EVENT_OBJECT_FACTORYwa ) type = OBJECT_MOBILEwa;
- if ( event.event == EVENT_OBJECT_FACTORYta ) type = OBJECT_MOBILEta;
- if ( event.event == EVENT_OBJECT_FACTORYfa ) type = OBJECT_MOBILEfa;
- if ( event.event == EVENT_OBJECT_FACTORYia ) type = OBJECT_MOBILEia;
- if ( event.event == EVENT_OBJECT_FACTORYws ) type = OBJECT_MOBILEws;
- if ( event.event == EVENT_OBJECT_FACTORYts ) type = OBJECT_MOBILEts;
- if ( event.event == EVENT_OBJECT_FACTORYfs ) type = OBJECT_MOBILEfs;
- if ( event.event == EVENT_OBJECT_FACTORYis ) type = OBJECT_MOBILEis;
- if ( event.event == EVENT_OBJECT_FACTORYwc ) type = OBJECT_MOBILEwc;
- if ( event.event == EVENT_OBJECT_FACTORYtc ) type = OBJECT_MOBILEtc;
- if ( event.event == EVENT_OBJECT_FACTORYfc ) type = OBJECT_MOBILEfc;
- if ( event.event == EVENT_OBJECT_FACTORYic ) type = OBJECT_MOBILEic;
- if ( event.event == EVENT_OBJECT_FACTORYwi ) type = OBJECT_MOBILEwi;
- if ( event.event == EVENT_OBJECT_FACTORYti ) type = OBJECT_MOBILEti;
- if ( event.event == EVENT_OBJECT_FACTORYfi ) type = OBJECT_MOBILEfi;
- if ( event.event == EVENT_OBJECT_FACTORYii ) type = OBJECT_MOBILEii;
- if ( event.event == EVENT_OBJECT_FACTORYrt ) type = OBJECT_MOBILErt;
- if ( event.event == EVENT_OBJECT_FACTORYrc ) type = OBJECT_MOBILErc;
- if ( event.event == EVENT_OBJECT_FACTORYrr ) type = OBJECT_MOBILErr;
- if ( event.event == EVENT_OBJECT_FACTORYrs ) type = OBJECT_MOBILErs;
- if ( event.event == EVENT_OBJECT_FACTORYsa ) type = OBJECT_MOBILEsa;
-
- if ( type != OBJECT_NULL )
- {
- m_type = type;
-
- if ( m_phase != AFP_WAIT )
- {
- return false;
- }
-
- fret = SearchFret(); // transform metal?
- if ( fret == 0 )
- {
- m_displayText->DisplayError(ERR_FACTORY_NULL, m_object);
- return false;
- }
- if ( NearestVehicle() )
- {
- m_displayText->DisplayError(ERR_FACTORY_NEAR, m_object);
- return false;
- }
-
- SetBusy(true);
- InitProgressTotal(3.0f+2.0f+15.0f+2.0f+3.0f);
- UpdateInterface();
-
- fret->SetLock(true); // usable metal
- SoundManip(3.0f, 1.0f, 0.5f);
-
- m_phase = AFP_CLOSE_S;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- return true;
- }
- }
-
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- EventProgress(event.rTime);
-
- if ( m_phase == AFP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- m_phase = AFP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == AFP_CLOSE_S )
- {
- if ( m_progress < 1.0f )
- {
- for ( i=0 ; i<9 ; i++ )
- {
- zoom = 0.30f+(m_progress-0.5f+i/16.0f)*2.0f*0.70f;
- if ( zoom < 0.30f ) zoom = 0.30f;
- if ( zoom > 1.00f ) zoom = 1.00f;
- m_object->SetZoomZ( 1+i, zoom);
- m_object->SetZoomZ(10+i, zoom);
- }
- }
- else
- {
- for ( i=0 ; i<9 ; i++ )
- {
- m_object->SetZoomZ( 1+i, 1.0f);
- m_object->SetZoomZ(10+i, 1.0f);
- }
-
- SoundManip(2.0f, 1.0f, 1.2f);
-
- m_phase = AFP_CLOSE_T;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == AFP_CLOSE_T )
- {
- if ( m_progress < 1.0f )
- {
- for ( i=0 ; i<9 ; i++ )
- {
- angle = -m_progress*(Math::PI/2.0f)+Math::PI/2.0f;
- m_object->SetAngleZ( 1+i, angle);
- m_object->SetAngleZ(10+i, -angle);
- }
- }
- else
- {
- for ( i=0 ; i<9 ; i++ )
- {
- m_object->SetAngleZ( 1+i, 0.0f);
- m_object->SetAngleZ(10+i, 0.0f);
- }
-
- m_channelSound = m_sound->Play(SOUND_FACTORY, m_object->RetPosition(0), 0.0f, 1.0f, true);
- m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 11.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP);
-
- m_phase = AFP_BUILD;
- m_progress = 0.0f;
- m_speed = 1.0f/15.0f;
- }
- }
-
- if ( m_phase == AFP_BUILD )
- {
- if ( m_progress == 0.0f )
- {
- if ( !CreateVehicle() )
- {
- fret = SearchFret(); // transform metal?
- if ( fret != 0 )
- {
- fret->SetLock(false); // metal usable again
- }
-
- if ( m_channelSound != -1 )
- {
- m_sound->FlushEnvelope(m_channelSound);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_channelSound = -1;
- }
-
- m_phase = AFP_OPEN_T;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- return true;
- }
- }
-
- if ( m_progress < 1.0f )
- {
- if ( m_type == OBJECT_MOBILErt ||
- m_type == OBJECT_MOBILErc ||
- m_type == OBJECT_MOBILErr ||
- m_type == OBJECT_MOBILErs )
- {
- prog = 1.0f-m_progress*1.5f;
- if ( prog < 0.0f ) prog = 0.0f;
- }
- else
- {
- prog = 1.0f-m_progress;
- }
- angle = powf(prog*10.0f, 2.0f)+m_object->RetAngleY(0);
-
- vehicle = SearchVehicle();
- if ( vehicle != 0 )
- {
- vehicle->SetAngleY(0, angle+Math::PI);
- vehicle->SetZoom(0, m_progress);
- }
-
- fret = SearchFret(); // transform metal?
- if ( fret != 0 )
- {
- fret->SetZoom(0, 1.0f-m_progress);
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
-#if 0
- pos = m_fretPos;
- pos.x += (Math::Rand()-0.5f)*20.0f;
- pos.z += (Math::Rand()-0.5f)*20.0f;
- pos.y += 1.0f;
- speed.x = (Math::Rand()-0.5f)*12.0f;
- speed.z = (Math::Rand()-0.5f)*12.0f;
- speed.y = Math::Rand()*12.0f;
- dim.x = Math::Rand()*12.0f+10.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
-#else
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(-12.0f, 20.0f, -4.0f); // position of chimney
- pos = Math::Transform(*mat, pos);
- pos.y += 2.0f;
- pos.x += (Math::Rand()-0.5f)*2.0f;
- pos.z += (Math::Rand()-0.5f)*2.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 6.0f+Math::Rand()*6.0f;
- dim.x = Math::Rand()*1.5f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
-#endif
- }
- }
- else
- {
- m_displayText->DisplayError(INFO_FACTORY, m_object);
- SoundManip(2.0f, 1.0f, 1.2f);
-
- fret = SearchFret(); // transform metal?
- if ( fret != 0 )
- {
- fret->DeleteObject(); // removes the metal
- delete fret;
- }
-
- vehicle = SearchVehicle();
- if ( vehicle != 0 )
- {
- physics = vehicle->RetPhysics();
- if ( physics != 0 )
- {
- physics->SetFreeze(false); // can move
- }
-
- vehicle->SetLock(false); // vehicle useable
-//? vehicle->RetPhysics()->RetBrain()->StartTaskAdvance(16.0f);
- vehicle->SetAngleY(0, m_object->RetAngleY(0)+Math::PI);
- vehicle->SetZoom(0, 1.0f);
- }
-
- m_main->CreateShortcuts();
-
- m_phase = AFP_OPEN_T;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == AFP_OPEN_T )
- {
- if ( m_progress < 1.0f )
- {
- for ( i=0 ; i<9 ; i++ )
- {
- angle = -(1.0f-m_progress)*(Math::PI/2.0f)+Math::PI/2.0f;
- m_object->SetAngleZ( 1+i, angle);
- m_object->SetAngleZ(10+i, -angle);
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_fretPos;
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- pos.y += Math::Rand()*10.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
- }
- }
- else
- {
- for ( i=0 ; i<9 ; i++ )
- {
- m_object->SetAngleZ( 1+i, Math::PI/2.0f);
- m_object->SetAngleZ(10+i, -Math::PI/2.0f);
- }
-
- SoundManip(3.0f, 1.0f, 0.5f);
-
- m_phase = AFP_OPEN_S;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- }
- }
-
- if ( m_phase == AFP_OPEN_S )
- {
- if ( m_progress < 1.0f )
- {
- for ( i=0 ; i<9 ; i++ )
- {
- zoom = 0.30f+((1.0f-m_progress)-0.5f+i/16.0f)*2.0f*0.70f;
- if ( zoom < 0.30f ) zoom = 0.30f;
- if ( zoom > 1.00f ) zoom = 1.00f;
- m_object->SetZoomZ( 1+i, zoom);
- m_object->SetZoomZ(10+i, zoom);
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_fretPos;
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- pos.y += Math::Rand()*10.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
- }
- }
- else
- {
- for ( i=0 ; i<9 ; i++ )
- {
- m_object->SetZoomZ( 1+i, 0.30f);
- m_object->SetZoomZ(10+i, 0.30f);
- }
-
- SetBusy(false);
- UpdateInterface();
-
- m_phase = AFP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- return true;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoFactory::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == AFP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller
-
-bool CAutoFactory::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoFactoryPhase)OpInt(line, "aPhase", AFP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
- m_fretPos = m_object->RetPosition(0);
-
- return true;
-}
-
-
-//Seeks the cargo.
-
-CObject* CAutoFactory::SearchFret()
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- float dist;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_METAL ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, m_fretPos);
-
- if ( dist < 8.0f ) return pObj;
- }
-
- return 0;
-}
-
-// Search if a vehicle is too close.
-
-bool CAutoFactory::NearestVehicle()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType type;
- float oRadius, dist;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr &&
- type != OBJECT_MOTHER &&
- type != OBJECT_ANT &&
- type != OBJECT_SPIDER &&
- type != OBJECT_BEE &&
- type != OBJECT_WORM ) continue;
-
- if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
- dist = Math::Distance(oPos, cPos)-oRadius;
-
- if ( dist < 10.0f ) return true;
- }
-
- return false;
-}
-
-
-// Creates a vehicle.
-
-bool CAutoFactory::CreateVehicle()
-{
- CObject* vehicle;
- Math::Matrix* mat;
- CPhysics* physics;
- Math::Vector pos;
- float angle;
- char* name;
- int i;
-
- angle = m_object->RetAngleY(0);
-
- mat = m_object->RetWorldMatrix(0);
- if ( m_type == OBJECT_MOBILErt ||
- m_type == OBJECT_MOBILErc ||
- m_type == OBJECT_MOBILErr ||
- m_type == OBJECT_MOBILErs )
- {
- pos = Math::Vector(2.0f, 0.0f, 0.0f);
- }
- else
- {
- pos = Math::Vector(4.0f, 0.0f, 0.0f);
- }
- pos = Transform(*mat, pos);
-
- vehicle = new CObject(m_iMan);
- if ( !vehicle->CreateVehicle(pos, angle, m_type, -1.0f, false, false) )
- {
- delete vehicle;
- m_displayText->DisplayError(ERR_TOOMANY, m_object);
- return false;
- }
- vehicle->UpdateMapping();
- vehicle->SetLock(true); // not usable
- vehicle->SetRange(30.0f);
-
- physics = vehicle->RetPhysics();
- if ( physics != 0 )
- {
- physics->SetFreeze(true); // it doesn't move
- }
-
- for ( i=0 ; i<10 ; i++ )
- {
- name = m_main->RetNewScriptName(m_type, i);
- if ( name == 0 ) break;
- vehicle->ReadProgram(i, name);
- }
-
- return true;
-}
-
-// Seeking the vehicle during manufacture.
-
-CObject* CAutoFactory::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- float dist;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetLock() ) continue;
-
- type = pObj->RetType();
- if ( type != m_type ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, m_fretPos);
-
- if ( dist < 8.0f ) return pObj;
- }
-
- return 0;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoFactory::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, dim, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- dim.x = 33.0f/640.0f;
- dim.y = 33.0f/480.0f;
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = 0.0f;
- pos.y = oy+sy*2.6f;
- ddim.x = 138.0f/640.0f;
- ddim.y = 222.0f/480.0f;
- pw->CreateGroup(pos, ddim, 6, EVENT_WINDOW3);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*8.2f;
- pw->CreateButton(pos, dim, 128+9, EVENT_OBJECT_FACTORYwa);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+10, EVENT_OBJECT_FACTORYta);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+11, EVENT_OBJECT_FACTORYfa);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+22, EVENT_OBJECT_FACTORYia);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*7.1f;
- pw->CreateButton(pos, dim, 128+12, EVENT_OBJECT_FACTORYws);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+13, EVENT_OBJECT_FACTORYts);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+14, EVENT_OBJECT_FACTORYfs);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+24, EVENT_OBJECT_FACTORYis);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*6.0f;
- pw->CreateButton(pos, dim, 128+15, EVENT_OBJECT_FACTORYwc);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+16, EVENT_OBJECT_FACTORYtc);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+17, EVENT_OBJECT_FACTORYfc);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+23, EVENT_OBJECT_FACTORYic);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*4.9f;
- pw->CreateButton(pos, dim, 128+25, EVENT_OBJECT_FACTORYwi);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+26, EVENT_OBJECT_FACTORYti);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+27, EVENT_OBJECT_FACTORYfi);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+28, EVENT_OBJECT_FACTORYii);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*3.8f;
- pw->CreateButton(pos, dim, 128+18, EVENT_OBJECT_FACTORYrt);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+19, EVENT_OBJECT_FACTORYrc);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+20, EVENT_OBJECT_FACTORYrr);
- pos.x += dim.x;
- pw->CreateButton(pos, dim, 128+29, EVENT_OBJECT_FACTORYrs);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*2.7f;
- pw->CreateButton(pos, dim, 128+21, EVENT_OBJECT_FACTORYsa);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 101, EVENT_OBJECT_TYPE);
-
- UpdateInterface();
- return true;
-}
-
-// Updates the status of all interface buttons.
-
-void CAutoFactory::UpdateInterface()
-{
- CWindow* pw;
-
- if ( !m_object->RetSelect() ) return;
-
- CAuto::UpdateInterface();
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
-
- UpdateButton(pw, EVENT_OBJECT_FACTORYwa, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYta, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYfa, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYia, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYws, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYts, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYfs, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYis, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYwc, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYtc, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYfc, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYic, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYwi, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYti, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYfi, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYii, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYrt, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYrc, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYrr, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYrs, m_bBusy);
- UpdateButton(pw, EVENT_OBJECT_FACTORYsa, m_bBusy);
-}
-
-// Updates the status of one interface button.
-
-void CAutoFactory::UpdateButton(CWindow *pw, EventMsg event, bool bBusy)
-{
- bool bEnable = true;
-
- EnableInterface(pw, event, !bBusy);
-
- if ( event == EVENT_OBJECT_FACTORYta )
- {
- bEnable = g_researchDone&RESEARCH_TANK;
- }
- if ( event == EVENT_OBJECT_FACTORYfa )
- {
- bEnable = g_researchDone&RESEARCH_FLY;
- }
- if ( event == EVENT_OBJECT_FACTORYia )
- {
- bEnable = g_researchDone&RESEARCH_iPAW;
- }
-
- if ( event == EVENT_OBJECT_FACTORYws )
- {
- bEnable = g_researchDone&RESEARCH_SNIFFER;
- }
- if ( event == EVENT_OBJECT_FACTORYts )
- {
- bEnable = ( (g_researchDone&RESEARCH_SNIFFER) &&
- (g_researchDone&RESEARCH_TANK) );
- }
- if ( event == EVENT_OBJECT_FACTORYfs )
- {
- bEnable = ( (g_researchDone&RESEARCH_SNIFFER) &&
- (g_researchDone&RESEARCH_FLY) );
- }
- if ( event == EVENT_OBJECT_FACTORYis )
- {
- bEnable = ( (g_researchDone&RESEARCH_SNIFFER) &&
- (g_researchDone&RESEARCH_iPAW) );
- }
-
- if ( event == EVENT_OBJECT_FACTORYwc )
- {
- bEnable = g_researchDone&RESEARCH_CANON;
- }
- if ( event == EVENT_OBJECT_FACTORYtc )
- {
- bEnable = ( (g_researchDone&RESEARCH_CANON) &&
- (g_researchDone&RESEARCH_TANK) );
- }
- if ( event == EVENT_OBJECT_FACTORYfc )
- {
- bEnable = ( (g_researchDone&RESEARCH_CANON) &&
- (g_researchDone&RESEARCH_FLY) );
- }
- if ( event == EVENT_OBJECT_FACTORYic )
- {
- bEnable = ( (g_researchDone&RESEARCH_CANON) &&
- (g_researchDone&RESEARCH_iPAW) );
- }
-
- if ( event == EVENT_OBJECT_FACTORYwi )
- {
- bEnable = g_researchDone&RESEARCH_iGUN;
- }
- if ( event == EVENT_OBJECT_FACTORYti )
- {
- bEnable = ( (g_researchDone&RESEARCH_iGUN) &&
- (g_researchDone&RESEARCH_TANK) );
- }
- if ( event == EVENT_OBJECT_FACTORYfi )
- {
- bEnable = ( (g_researchDone&RESEARCH_iGUN) &&
- (g_researchDone&RESEARCH_FLY) );
- }
- if ( event == EVENT_OBJECT_FACTORYii )
- {
- bEnable = ( (g_researchDone&RESEARCH_iGUN) &&
- (g_researchDone&RESEARCH_iPAW) );
- }
-
- if ( event == EVENT_OBJECT_FACTORYrt )
- {
- bEnable = ( (g_researchDone&RESEARCH_THUMP) &&
- (g_researchDone&RESEARCH_TANK) );
- }
- if ( event == EVENT_OBJECT_FACTORYrc )
- {
- bEnable = ( (g_researchDone&RESEARCH_PHAZER) &&
- (g_researchDone&RESEARCH_TANK) );
- }
- if ( event == EVENT_OBJECT_FACTORYrr )
- {
- bEnable = ( (g_researchDone&RESEARCH_RECYCLER) &&
- (g_researchDone&RESEARCH_TANK) );
- }
- if ( event == EVENT_OBJECT_FACTORYrs )
- {
- bEnable = ( (g_researchDone&RESEARCH_SHIELD) &&
- (g_researchDone&RESEARCH_TANK) );
- }
-
- if ( event == EVENT_OBJECT_FACTORYsa )
- {
- bEnable = g_researchDone&RESEARCH_SUBM;
- }
-
- DeadInterface(pw, event, bEnable);
-}
-
-// Plays the sound of the manipulator arm.
-
-void CAutoFactory::SoundManip(float time, float amplitude, float frequency)
-{
- int i;
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autofactory.h"
+
+#include "common/global.h"
+#include "common/iman.h"
+#include "math/geometry.h"
+#include "object/robotmain.h"
+#include "physics/physics.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+
+
+
+
+
+// Object's constructor.
+
+CAutoFactory::CAutoFactory(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+ m_type = OBJECT_MOBILEws;
+ m_phase = AFP_WAIT; // paused until the first Init ()
+ m_channelSound = -1;
+}
+
+// Object's destructor.
+
+CAutoFactory::~CAutoFactory()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoFactory::DeleteObject(bool bAll)
+{
+ CObject* fret;
+ CObject* vehicle;
+
+ if ( !bAll )
+ {
+ fret = SearchFret(); // transform metal?
+ if ( fret != 0 )
+ {
+ fret->DeleteObject(); // destroys the metal
+ delete fret;
+ }
+
+ vehicle = SearchVehicle();
+ if ( vehicle != 0 )
+ {
+ vehicle->DeleteObject(); // destroys the vehicle
+ delete vehicle;
+ }
+ }
+
+ if ( m_channelSound != -1 )
+ {
+ m_sound->FlushEnvelope(m_channelSound);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_channelSound = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoFactory::Init()
+{
+ m_phase = AFP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+
+ m_fretPos = m_object->RetPosition(0);
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoFactory::EventProcess(const Event &event)
+{
+ CObject* fret;
+ CObject* vehicle;
+ Math::Matrix* mat;
+ CPhysics* physics;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ ObjectType type;
+ float zoom, angle, prog;
+ int i;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+
+ if ( m_object->RetSelect() ) // factory selected?
+ {
+ if ( event.event == EVENT_UPDINTERFACE )
+ {
+ CreateInterface(true);
+ }
+
+ type = OBJECT_NULL;
+ if ( event.event == EVENT_OBJECT_FACTORYwa ) type = OBJECT_MOBILEwa;
+ if ( event.event == EVENT_OBJECT_FACTORYta ) type = OBJECT_MOBILEta;
+ if ( event.event == EVENT_OBJECT_FACTORYfa ) type = OBJECT_MOBILEfa;
+ if ( event.event == EVENT_OBJECT_FACTORYia ) type = OBJECT_MOBILEia;
+ if ( event.event == EVENT_OBJECT_FACTORYws ) type = OBJECT_MOBILEws;
+ if ( event.event == EVENT_OBJECT_FACTORYts ) type = OBJECT_MOBILEts;
+ if ( event.event == EVENT_OBJECT_FACTORYfs ) type = OBJECT_MOBILEfs;
+ if ( event.event == EVENT_OBJECT_FACTORYis ) type = OBJECT_MOBILEis;
+ if ( event.event == EVENT_OBJECT_FACTORYwc ) type = OBJECT_MOBILEwc;
+ if ( event.event == EVENT_OBJECT_FACTORYtc ) type = OBJECT_MOBILEtc;
+ if ( event.event == EVENT_OBJECT_FACTORYfc ) type = OBJECT_MOBILEfc;
+ if ( event.event == EVENT_OBJECT_FACTORYic ) type = OBJECT_MOBILEic;
+ if ( event.event == EVENT_OBJECT_FACTORYwi ) type = OBJECT_MOBILEwi;
+ if ( event.event == EVENT_OBJECT_FACTORYti ) type = OBJECT_MOBILEti;
+ if ( event.event == EVENT_OBJECT_FACTORYfi ) type = OBJECT_MOBILEfi;
+ if ( event.event == EVENT_OBJECT_FACTORYii ) type = OBJECT_MOBILEii;
+ if ( event.event == EVENT_OBJECT_FACTORYrt ) type = OBJECT_MOBILErt;
+ if ( event.event == EVENT_OBJECT_FACTORYrc ) type = OBJECT_MOBILErc;
+ if ( event.event == EVENT_OBJECT_FACTORYrr ) type = OBJECT_MOBILErr;
+ if ( event.event == EVENT_OBJECT_FACTORYrs ) type = OBJECT_MOBILErs;
+ if ( event.event == EVENT_OBJECT_FACTORYsa ) type = OBJECT_MOBILEsa;
+
+ if ( type != OBJECT_NULL )
+ {
+ m_type = type;
+
+ if ( m_phase != AFP_WAIT )
+ {
+ return false;
+ }
+
+ fret = SearchFret(); // transform metal?
+ if ( fret == 0 )
+ {
+ m_displayText->DisplayError(ERR_FACTORY_NULL, m_object);
+ return false;
+ }
+ if ( NearestVehicle() )
+ {
+ m_displayText->DisplayError(ERR_FACTORY_NEAR, m_object);
+ return false;
+ }
+
+ SetBusy(true);
+ InitProgressTotal(3.0f+2.0f+15.0f+2.0f+3.0f);
+ UpdateInterface();
+
+ fret->SetLock(true); // usable metal
+ SoundManip(3.0f, 1.0f, 0.5f);
+
+ m_phase = AFP_CLOSE_S;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ return true;
+ }
+ }
+
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ EventProgress(event.rTime);
+
+ if ( m_phase == AFP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_phase = AFP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == AFP_CLOSE_S )
+ {
+ if ( m_progress < 1.0f )
+ {
+ for ( i=0 ; i<9 ; i++ )
+ {
+ zoom = 0.30f+(m_progress-0.5f+i/16.0f)*2.0f*0.70f;
+ if ( zoom < 0.30f ) zoom = 0.30f;
+ if ( zoom > 1.00f ) zoom = 1.00f;
+ m_object->SetZoomZ( 1+i, zoom);
+ m_object->SetZoomZ(10+i, zoom);
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<9 ; i++ )
+ {
+ m_object->SetZoomZ( 1+i, 1.0f);
+ m_object->SetZoomZ(10+i, 1.0f);
+ }
+
+ SoundManip(2.0f, 1.0f, 1.2f);
+
+ m_phase = AFP_CLOSE_T;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == AFP_CLOSE_T )
+ {
+ if ( m_progress < 1.0f )
+ {
+ for ( i=0 ; i<9 ; i++ )
+ {
+ angle = -m_progress*(Math::PI/2.0f)+Math::PI/2.0f;
+ m_object->SetAngleZ( 1+i, angle);
+ m_object->SetAngleZ(10+i, -angle);
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<9 ; i++ )
+ {
+ m_object->SetAngleZ( 1+i, 0.0f);
+ m_object->SetAngleZ(10+i, 0.0f);
+ }
+
+ m_channelSound = m_sound->Play(SOUND_FACTORY, m_object->RetPosition(0), 0.0f, 1.0f, true);
+ m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 11.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP);
+
+ m_phase = AFP_BUILD;
+ m_progress = 0.0f;
+ m_speed = 1.0f/15.0f;
+ }
+ }
+
+ if ( m_phase == AFP_BUILD )
+ {
+ if ( m_progress == 0.0f )
+ {
+ if ( !CreateVehicle() )
+ {
+ fret = SearchFret(); // transform metal?
+ if ( fret != 0 )
+ {
+ fret->SetLock(false); // metal usable again
+ }
+
+ if ( m_channelSound != -1 )
+ {
+ m_sound->FlushEnvelope(m_channelSound);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_channelSound = -1;
+ }
+
+ m_phase = AFP_OPEN_T;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ return true;
+ }
+ }
+
+ if ( m_progress < 1.0f )
+ {
+ if ( m_type == OBJECT_MOBILErt ||
+ m_type == OBJECT_MOBILErc ||
+ m_type == OBJECT_MOBILErr ||
+ m_type == OBJECT_MOBILErs )
+ {
+ prog = 1.0f-m_progress*1.5f;
+ if ( prog < 0.0f ) prog = 0.0f;
+ }
+ else
+ {
+ prog = 1.0f-m_progress;
+ }
+ angle = powf(prog*10.0f, 2.0f)+m_object->RetAngleY(0);
+
+ vehicle = SearchVehicle();
+ if ( vehicle != 0 )
+ {
+ vehicle->SetAngleY(0, angle+Math::PI);
+ vehicle->SetZoom(0, m_progress);
+ }
+
+ fret = SearchFret(); // transform metal?
+ if ( fret != 0 )
+ {
+ fret->SetZoom(0, 1.0f-m_progress);
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+#if 0
+ pos = m_fretPos;
+ pos.x += (Math::Rand()-0.5f)*20.0f;
+ pos.z += (Math::Rand()-0.5f)*20.0f;
+ pos.y += 1.0f;
+ speed.x = (Math::Rand()-0.5f)*12.0f;
+ speed.z = (Math::Rand()-0.5f)*12.0f;
+ speed.y = Math::Rand()*12.0f;
+ dim.x = Math::Rand()*12.0f+10.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
+#else
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(-12.0f, 20.0f, -4.0f); // position of chimney
+ pos = Math::Transform(*mat, pos);
+ pos.y += 2.0f;
+ pos.x += (Math::Rand()-0.5f)*2.0f;
+ pos.z += (Math::Rand()-0.5f)*2.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 6.0f+Math::Rand()*6.0f;
+ dim.x = Math::Rand()*1.5f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
+#endif
+ }
+ }
+ else
+ {
+ m_displayText->DisplayError(INFO_FACTORY, m_object);
+ SoundManip(2.0f, 1.0f, 1.2f);
+
+ fret = SearchFret(); // transform metal?
+ if ( fret != 0 )
+ {
+ fret->DeleteObject(); // removes the metal
+ delete fret;
+ }
+
+ vehicle = SearchVehicle();
+ if ( vehicle != 0 )
+ {
+ physics = vehicle->RetPhysics();
+ if ( physics != 0 )
+ {
+ physics->SetFreeze(false); // can move
+ }
+
+ vehicle->SetLock(false); // vehicle useable
+//? vehicle->RetPhysics()->RetBrain()->StartTaskAdvance(16.0f);
+ vehicle->SetAngleY(0, m_object->RetAngleY(0)+Math::PI);
+ vehicle->SetZoom(0, 1.0f);
+ }
+
+ m_main->CreateShortcuts();
+
+ m_phase = AFP_OPEN_T;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == AFP_OPEN_T )
+ {
+ if ( m_progress < 1.0f )
+ {
+ for ( i=0 ; i<9 ; i++ )
+ {
+ angle = -(1.0f-m_progress)*(Math::PI/2.0f)+Math::PI/2.0f;
+ m_object->SetAngleZ( 1+i, angle);
+ m_object->SetAngleZ(10+i, -angle);
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_fretPos;
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ pos.y += Math::Rand()*10.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<9 ; i++ )
+ {
+ m_object->SetAngleZ( 1+i, Math::PI/2.0f);
+ m_object->SetAngleZ(10+i, -Math::PI/2.0f);
+ }
+
+ SoundManip(3.0f, 1.0f, 0.5f);
+
+ m_phase = AFP_OPEN_S;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ }
+ }
+
+ if ( m_phase == AFP_OPEN_S )
+ {
+ if ( m_progress < 1.0f )
+ {
+ for ( i=0 ; i<9 ; i++ )
+ {
+ zoom = 0.30f+((1.0f-m_progress)-0.5f+i/16.0f)*2.0f*0.70f;
+ if ( zoom < 0.30f ) zoom = 0.30f;
+ if ( zoom > 1.00f ) zoom = 1.00f;
+ m_object->SetZoomZ( 1+i, zoom);
+ m_object->SetZoomZ(10+i, zoom);
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_fretPos;
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ pos.y += Math::Rand()*10.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<9 ; i++ )
+ {
+ m_object->SetZoomZ( 1+i, 0.30f);
+ m_object->SetZoomZ(10+i, 0.30f);
+ }
+
+ SetBusy(false);
+ UpdateInterface();
+
+ m_phase = AFP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ return true;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoFactory::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == AFP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller
+
+bool CAutoFactory::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoFactoryPhase)OpInt(line, "aPhase", AFP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+ m_fretPos = m_object->RetPosition(0);
+
+ return true;
+}
+
+
+//Seeks the cargo.
+
+CObject* CAutoFactory::SearchFret()
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ ObjectType type;
+ float dist;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_METAL ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, m_fretPos);
+
+ if ( dist < 8.0f ) return pObj;
+ }
+
+ return 0;
+}
+
+// Search if a vehicle is too close.
+
+bool CAutoFactory::NearestVehicle()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType type;
+ float oRadius, dist;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_HUMAN &&
+ type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis &&
+ type != OBJECT_MOBILErt &&
+ type != OBJECT_MOBILErc &&
+ type != OBJECT_MOBILErr &&
+ type != OBJECT_MOBILErs &&
+ type != OBJECT_MOBILEsa &&
+ type != OBJECT_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_MOBILEdr &&
+ type != OBJECT_MOTHER &&
+ type != OBJECT_ANT &&
+ type != OBJECT_SPIDER &&
+ type != OBJECT_BEE &&
+ type != OBJECT_WORM ) continue;
+
+ if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
+ dist = Math::Distance(oPos, cPos)-oRadius;
+
+ if ( dist < 10.0f ) return true;
+ }
+
+ return false;
+}
+
+
+// Creates a vehicle.
+
+bool CAutoFactory::CreateVehicle()
+{
+ CObject* vehicle;
+ Math::Matrix* mat;
+ CPhysics* physics;
+ Math::Vector pos;
+ float angle;
+ char* name;
+ int i;
+
+ angle = m_object->RetAngleY(0);
+
+ mat = m_object->RetWorldMatrix(0);
+ if ( m_type == OBJECT_MOBILErt ||
+ m_type == OBJECT_MOBILErc ||
+ m_type == OBJECT_MOBILErr ||
+ m_type == OBJECT_MOBILErs )
+ {
+ pos = Math::Vector(2.0f, 0.0f, 0.0f);
+ }
+ else
+ {
+ pos = Math::Vector(4.0f, 0.0f, 0.0f);
+ }
+ pos = Transform(*mat, pos);
+
+ vehicle = new CObject(m_iMan);
+ if ( !vehicle->CreateVehicle(pos, angle, m_type, -1.0f, false, false) )
+ {
+ delete vehicle;
+ m_displayText->DisplayError(ERR_TOOMANY, m_object);
+ return false;
+ }
+ vehicle->UpdateMapping();
+ vehicle->SetLock(true); // not usable
+ vehicle->SetRange(30.0f);
+
+ physics = vehicle->RetPhysics();
+ if ( physics != 0 )
+ {
+ physics->SetFreeze(true); // it doesn't move
+ }
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ name = m_main->RetNewScriptName(m_type, i);
+ if ( name == 0 ) break;
+ vehicle->ReadProgram(i, name);
+ }
+
+ return true;
+}
+
+// Seeking the vehicle during manufacture.
+
+CObject* CAutoFactory::SearchVehicle()
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ ObjectType type;
+ float dist;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetLock() ) continue;
+
+ type = pObj->RetType();
+ if ( type != m_type ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, m_fretPos);
+
+ if ( dist < 8.0f ) return pObj;
+ }
+
+ return 0;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoFactory::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, dim, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ dim.x = 33.0f/640.0f;
+ dim.y = 33.0f/480.0f;
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = 0.0f;
+ pos.y = oy+sy*2.6f;
+ ddim.x = 138.0f/640.0f;
+ ddim.y = 222.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 6, EVENT_WINDOW3);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*8.2f;
+ pw->CreateButton(pos, dim, 128+9, EVENT_OBJECT_FACTORYwa);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+10, EVENT_OBJECT_FACTORYta);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+11, EVENT_OBJECT_FACTORYfa);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+22, EVENT_OBJECT_FACTORYia);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*7.1f;
+ pw->CreateButton(pos, dim, 128+12, EVENT_OBJECT_FACTORYws);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+13, EVENT_OBJECT_FACTORYts);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+14, EVENT_OBJECT_FACTORYfs);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+24, EVENT_OBJECT_FACTORYis);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*6.0f;
+ pw->CreateButton(pos, dim, 128+15, EVENT_OBJECT_FACTORYwc);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+16, EVENT_OBJECT_FACTORYtc);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+17, EVENT_OBJECT_FACTORYfc);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+23, EVENT_OBJECT_FACTORYic);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*4.9f;
+ pw->CreateButton(pos, dim, 128+25, EVENT_OBJECT_FACTORYwi);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+26, EVENT_OBJECT_FACTORYti);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+27, EVENT_OBJECT_FACTORYfi);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+28, EVENT_OBJECT_FACTORYii);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*3.8f;
+ pw->CreateButton(pos, dim, 128+18, EVENT_OBJECT_FACTORYrt);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+19, EVENT_OBJECT_FACTORYrc);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+20, EVENT_OBJECT_FACTORYrr);
+ pos.x += dim.x;
+ pw->CreateButton(pos, dim, 128+29, EVENT_OBJECT_FACTORYrs);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*2.7f;
+ pw->CreateButton(pos, dim, 128+21, EVENT_OBJECT_FACTORYsa);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 101, EVENT_OBJECT_TYPE);
+
+ UpdateInterface();
+ return true;
+}
+
+// Updates the status of all interface buttons.
+
+void CAutoFactory::UpdateInterface()
+{
+ CWindow* pw;
+
+ if ( !m_object->RetSelect() ) return;
+
+ CAuto::UpdateInterface();
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+
+ UpdateButton(pw, EVENT_OBJECT_FACTORYwa, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYta, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYfa, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYia, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYws, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYts, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYfs, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYis, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYwc, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYtc, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYfc, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYic, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYwi, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYti, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYfi, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYii, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYrt, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYrc, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYrr, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYrs, m_bBusy);
+ UpdateButton(pw, EVENT_OBJECT_FACTORYsa, m_bBusy);
+}
+
+// Updates the status of one interface button.
+
+void CAutoFactory::UpdateButton(CWindow *pw, EventMsg event, bool bBusy)
+{
+ bool bEnable = true;
+
+ EnableInterface(pw, event, !bBusy);
+
+ if ( event == EVENT_OBJECT_FACTORYta )
+ {
+ bEnable = g_researchDone&RESEARCH_TANK;
+ }
+ if ( event == EVENT_OBJECT_FACTORYfa )
+ {
+ bEnable = g_researchDone&RESEARCH_FLY;
+ }
+ if ( event == EVENT_OBJECT_FACTORYia )
+ {
+ bEnable = g_researchDone&RESEARCH_iPAW;
+ }
+
+ if ( event == EVENT_OBJECT_FACTORYws )
+ {
+ bEnable = g_researchDone&RESEARCH_SNIFFER;
+ }
+ if ( event == EVENT_OBJECT_FACTORYts )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_SNIFFER) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYfs )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_SNIFFER) &&
+ (g_researchDone&RESEARCH_FLY) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYis )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_SNIFFER) &&
+ (g_researchDone&RESEARCH_iPAW) );
+ }
+
+ if ( event == EVENT_OBJECT_FACTORYwc )
+ {
+ bEnable = g_researchDone&RESEARCH_CANON;
+ }
+ if ( event == EVENT_OBJECT_FACTORYtc )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_CANON) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYfc )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_CANON) &&
+ (g_researchDone&RESEARCH_FLY) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYic )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_CANON) &&
+ (g_researchDone&RESEARCH_iPAW) );
+ }
+
+ if ( event == EVENT_OBJECT_FACTORYwi )
+ {
+ bEnable = g_researchDone&RESEARCH_iGUN;
+ }
+ if ( event == EVENT_OBJECT_FACTORYti )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_iGUN) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYfi )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_iGUN) &&
+ (g_researchDone&RESEARCH_FLY) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYii )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_iGUN) &&
+ (g_researchDone&RESEARCH_iPAW) );
+ }
+
+ if ( event == EVENT_OBJECT_FACTORYrt )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_THUMP) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYrc )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_PHAZER) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYrr )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_RECYCLER) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+ if ( event == EVENT_OBJECT_FACTORYrs )
+ {
+ bEnable = ( (g_researchDone&RESEARCH_SHIELD) &&
+ (g_researchDone&RESEARCH_TANK) );
+ }
+
+ if ( event == EVENT_OBJECT_FACTORYsa )
+ {
+ bEnable = g_researchDone&RESEARCH_SUBM;
+ }
+
+ DeadInterface(pw, event, bEnable);
+}
+
+// Plays the sound of the manipulator arm.
+
+void CAutoFactory::SoundManip(float time, float amplitude, float frequency)
+{
+ int i;
+
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
+ m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
+}
+
diff --git a/src/object/auto/autofactory.h b/src/object/auto/autofactory.h
index d41dd62..acbdf40 100644
--- a/src/object/auto/autofactory.h
+++ b/src/object/auto/autofactory.h
@@ -1,74 +1,74 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autofactory.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoFactoryPhase
-{
- AFP_WAIT = 1, // expected metal
- AFP_CLOSE_S = 2, // closes doors (shift)
- AFP_CLOSE_T = 3, // closes doors (turn)
- AFP_BUILD = 4, // building the vehicle
- AFP_OPEN_T = 5, // opens the doors (turn)
- AFP_OPEN_S = 6, // opens the doors (shift)
- AFP_ADVANCE = 7, // advance at the door
-};
-
-
-
-class CAutoFactory : public CAuto
-{
-public:
- CAutoFactory(CInstanceManager* iMan, CObject* object);
- ~CAutoFactory();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- void UpdateInterface();
- void UpdateButton(CWindow *pw, EventMsg event, bool bBusy);
-
- CObject* SearchFret();
- bool NearestVehicle();
- bool CreateVehicle();
- CObject* SearchVehicle();
-
- void SoundManip(float time, float amplitude, float frequency);
-
-protected:
- AutoFactoryPhase m_phase;
- float m_progress;
- float m_speed;
- float m_lastParticule;
- Math::Vector m_fretPos;
- int m_channelSound;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autofactory.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoFactoryPhase
+{
+ AFP_WAIT = 1, // expected metal
+ AFP_CLOSE_S = 2, // closes doors (shift)
+ AFP_CLOSE_T = 3, // closes doors (turn)
+ AFP_BUILD = 4, // building the vehicle
+ AFP_OPEN_T = 5, // opens the doors (turn)
+ AFP_OPEN_S = 6, // opens the doors (shift)
+ AFP_ADVANCE = 7, // advance at the door
+};
+
+
+
+class CAutoFactory : public CAuto
+{
+public:
+ CAutoFactory(CInstanceManager* iMan, CObject* object);
+ ~CAutoFactory();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ void UpdateInterface();
+ void UpdateButton(CWindow *pw, EventMsg event, bool bBusy);
+
+ CObject* SearchFret();
+ bool NearestVehicle();
+ bool CreateVehicle();
+ CObject* SearchVehicle();
+
+ void SoundManip(float time, float amplitude, float frequency);
+
+protected:
+ AutoFactoryPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_lastParticule;
+ Math::Vector m_fretPos;
+ int m_channelSound;
+};
+
diff --git a/src/object/auto/autoflag.cpp b/src/object/auto/autoflag.cpp
index 2c9ebdc..ea74b17 100644
--- a/src/object/auto/autoflag.cpp
+++ b/src/object/auto/autoflag.cpp
@@ -1,162 +1,162 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoflag.h"
-
-#include "math/geometry.h"
-#include "old/terrain.h"
-
-
-
-#define ADJUST_ANGLE false // true -> adjusts the angles of the members
-
-
-#if ADJUST_ANGLE
-static float g_flag1 = 6.00f;
-static float g_flag2 = 0.10f;
-static float g_flag3 = 2.00f;
-#endif
-
-
-// Object's constructor.
-
-CAutoFlag::CAutoFlag(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
-}
-
-// Object's destructor.
-
-CAutoFlag::~CAutoFlag()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoFlag::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoFlag::Init()
-{
- Math::Vector wind;
- float angle;
-
- m_time = 0.0f;
- m_param = 0;
- m_progress = 0.0f;
-
- wind = m_terrain->RetWind();
- angle = Math::RotateAngle(wind.x, -wind.z);
- m_object->SetAngleY(0, angle); // directs the flag in the wind
-
- m_strong = wind.Length();
-}
-
-
-// Beginning of an action (1 = shakes).
-
-void CAutoFlag::Start(int param)
-{
- if ( m_param == 0 )
- {
- m_param = param;
- m_progress = 0.0f;
- }
-}
-
-
-// Management of an event.
-
-bool CAutoFlag::EventProcess(const Event &event)
-{
- float angle;
- int i;
-
- CAuto::EventProcess(event);
-
-#if ADJUST_ANGLE
- if ( event.event == EVENT_KEYDOWN )
- {
- if ( event.param == 'E' ) g_flag1 += 0.1f;
- if ( event.param == 'D' ) g_flag1 -= 0.1f;
- if ( event.param == 'R' ) g_flag2 += 0.1f;
- if ( event.param == 'F' ) g_flag2 -= 0.1f;
- if ( event.param == 'T' ) g_flag3 += 0.1f;
- if ( event.param == 'G' ) g_flag3 -= 0.1f;
- }
-#endif
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- if ( m_param == 1 ) // shakes?
- {
- m_progress += event.rTime*(1.0f/2.0f);
- if ( m_progress < 1.0f )
- {
- angle = sinf(m_progress*Math::PI*8.0f)*0.3f*(1.0f-m_progress);
- m_object->SetAngleX(0, angle);
- angle = sinf(m_progress*Math::PI*4.0f)*0.3f*(1.0f-m_progress);
- m_object->SetAngleZ(0, angle);
- }
- else
- {
- m_object->SetAngleX(0, 0.0f);
- m_object->SetAngleZ(0, 0.0f);
- m_param = 0;
- m_progress = 0.0f;
- }
- }
-
- if ( m_strong == 0.0f ) return true; // no wind?
-
- for ( i=0 ; i<4 ; i++ )
- {
-#if ADJUST_ANGLE
- angle = sinf(m_time*g_flag1+i*2.0f)*((i+g_flag3)*g_flag2);
-#else
- angle = sinf(m_time*6.0f+i*2.0f)*((i+2.0f)*0.1f);
-#endif
- m_object->SetAngleY(1+i, angle);
- }
-
-#if ADJUST_ANGLE
- char s[100];
- sprintf(s, "a=%.2f b=%.2f c=%.2f", g_flag1, g_flag2, g_flag3);
- m_engine->SetInfoText(4, s);
-#endif
- return true;
-}
-
-
-// Returns an error due the state of the automation
-
-Error CAutoFlag::RetError()
-{
- return ERR_OK;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoflag.h"
+
+#include "math/geometry.h"
+#include "old/terrain.h"
+
+
+
+#define ADJUST_ANGLE false // true -> adjusts the angles of the members
+
+
+#if ADJUST_ANGLE
+static float g_flag1 = 6.00f;
+static float g_flag2 = 0.10f;
+static float g_flag3 = 2.00f;
+#endif
+
+
+// Object's constructor.
+
+CAutoFlag::CAutoFlag(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+}
+
+// Object's destructor.
+
+CAutoFlag::~CAutoFlag()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoFlag::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoFlag::Init()
+{
+ Math::Vector wind;
+ float angle;
+
+ m_time = 0.0f;
+ m_param = 0;
+ m_progress = 0.0f;
+
+ wind = m_terrain->RetWind();
+ angle = Math::RotateAngle(wind.x, -wind.z);
+ m_object->SetAngleY(0, angle); // directs the flag in the wind
+
+ m_strong = wind.Length();
+}
+
+
+// Beginning of an action (1 = shakes).
+
+void CAutoFlag::Start(int param)
+{
+ if ( m_param == 0 )
+ {
+ m_param = param;
+ m_progress = 0.0f;
+ }
+}
+
+
+// Management of an event.
+
+bool CAutoFlag::EventProcess(const Event &event)
+{
+ float angle;
+ int i;
+
+ CAuto::EventProcess(event);
+
+#if ADJUST_ANGLE
+ if ( event.event == EVENT_KEYDOWN )
+ {
+ if ( event.param == 'E' ) g_flag1 += 0.1f;
+ if ( event.param == 'D' ) g_flag1 -= 0.1f;
+ if ( event.param == 'R' ) g_flag2 += 0.1f;
+ if ( event.param == 'F' ) g_flag2 -= 0.1f;
+ if ( event.param == 'T' ) g_flag3 += 0.1f;
+ if ( event.param == 'G' ) g_flag3 -= 0.1f;
+ }
+#endif
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ if ( m_param == 1 ) // shakes?
+ {
+ m_progress += event.rTime*(1.0f/2.0f);
+ if ( m_progress < 1.0f )
+ {
+ angle = sinf(m_progress*Math::PI*8.0f)*0.3f*(1.0f-m_progress);
+ m_object->SetAngleX(0, angle);
+ angle = sinf(m_progress*Math::PI*4.0f)*0.3f*(1.0f-m_progress);
+ m_object->SetAngleZ(0, angle);
+ }
+ else
+ {
+ m_object->SetAngleX(0, 0.0f);
+ m_object->SetAngleZ(0, 0.0f);
+ m_param = 0;
+ m_progress = 0.0f;
+ }
+ }
+
+ if ( m_strong == 0.0f ) return true; // no wind?
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+#if ADJUST_ANGLE
+ angle = sinf(m_time*g_flag1+i*2.0f)*((i+g_flag3)*g_flag2);
+#else
+ angle = sinf(m_time*6.0f+i*2.0f)*((i+2.0f)*0.1f);
+#endif
+ m_object->SetAngleY(1+i, angle);
+ }
+
+#if ADJUST_ANGLE
+ char s[100];
+ sprintf(s, "a=%.2f b=%.2f c=%.2f", g_flag1, g_flag2, g_flag3);
+ m_engine->SetInfoText(4, s);
+#endif
+ return true;
+}
+
+
+// Returns an error due the state of the automation
+
+Error CAutoFlag::RetError()
+{
+ return ERR_OK;
+}
+
+
diff --git a/src/object/auto/autoflag.h b/src/object/auto/autoflag.h
index b503363..fdec682 100644
--- a/src/object/auto/autoflag.h
+++ b/src/object/auto/autoflag.h
@@ -1,46 +1,46 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoflag.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-class CAutoFlag : public CAuto
-{
-public:
- CAutoFlag(CInstanceManager* iMan, CObject* object);
- ~CAutoFlag();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- void Start(int param);
- bool EventProcess(const Event &event);
- Error RetError();
-
-protected:
-
-protected:
- float m_strong;
- int m_param;
- float m_progress;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoflag.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+class CAutoFlag : public CAuto
+{
+public:
+ CAutoFlag(CInstanceManager* iMan, CObject* object);
+ ~CAutoFlag();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ void Start(int param);
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+protected:
+
+protected:
+ float m_strong;
+ int m_param;
+ float m_progress;
+};
+
diff --git a/src/object/auto/autohuston.cpp b/src/object/auto/autohuston.cpp
index 3495437..a96bcb8 100644
--- a/src/object/auto/autohuston.cpp
+++ b/src/object/auto/autohuston.cpp
@@ -1,296 +1,296 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autohuston.h"
-
-#include "ui/interface.h"
-#include "ui/window.h"
-
-
-
-
-// Object's constructor.
-
-CAutoHuston::CAutoHuston(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Math::Vector pos;
- int i;
-
- for ( i=0 ; i<HUSTONMAXLENS ; i++ )
- {
- m_lens[i].parti = -1;
- }
-
- pos = m_object->RetPosition(0);
- m_lens[0].type = PARTISELR;
- m_lens[1].type = PARTISELR;
- m_lens[2].type = PARTISELR;
- m_lens[3].type = PARTISELR;
- m_lens[0].pos = pos+Math::Vector(0.0f+13.0f, 34.0f, 30.0f );
- m_lens[1].pos = pos+Math::Vector(0.0f-13.0f, 34.0f, 30.0f );
- m_lens[2].pos = pos+Math::Vector(0.0f , 34.0f, 30.0f+13.0f);
- m_lens[3].pos = pos+Math::Vector(0.0f , 34.0f, 30.0f-13.0f);
- m_lens[0].dim = 4.0f;
- m_lens[1].dim = 4.0f;
- m_lens[2].dim = 4.0f;
- m_lens[3].dim = 4.0f;
- m_lens[0].total = 1.0f;
- m_lens[1].total = 1.0f;
- m_lens[2].total = 1.0f;
- m_lens[3].total = 1.0f;
- m_lens[0].off = 0.4f;
- m_lens[1].off = 0.4f;
- m_lens[2].off = 0.4f;
- m_lens[3].off = 0.4f;
-
- // Part under the radar.
- i = 4;
- m_lens[i].type = PARTISELR;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 9.9f, 40.1f);
- m_lens[i].dim = 1.8f;
- m_lens[i].total = 0.4f;
- m_lens[i].off = 0.2f;
- i ++;
-
- m_lens[i].type = PARTISELY;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 7.2f, 34.8f);
- m_lens[i].dim = 0.4f;
- m_lens[i].total = 0.7f;
- m_lens[i].off = 0.3f;
- i ++;
- m_lens[i].type = PARTISELY;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 34.3f);
- m_lens[i].dim = 0.4f;
- m_lens[i].total = 0.7f;
- m_lens[i].off = 0.3f;
- i ++;
- m_lens[i].type = PARTISELR;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.4f);
- m_lens[i].dim = 0.4f;
- m_lens[i].total = 0.0f;
- m_lens[i].off = 0.0f;
- i ++;
- m_lens[i].type = PARTISELR;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.0f);
- m_lens[i].dim = 0.4f;
- m_lens[i].total = 1.0f;
- m_lens[i].off = 0.5f;
- i ++;
-
- m_lens[i].type = PARTISELY;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 8.5f, 14.0f);
- m_lens[i].dim = 1.2f;
- m_lens[i].total = 0.8f;
- m_lens[i].off = 0.2f;
- i ++;
-
- m_lens[i].type = PARTISELR;
- m_lens[i].pos = pos+Math::Vector(4.0f, 6.0f, 8.6f);
- m_lens[i].dim = 1.0f;
- m_lens[i].total = 0.9f;
- m_lens[i].off = 0.7f;
- i ++;
-
- // Part with three windows.
- m_lens[i].type = PARTISELR;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 9.9f, -19.9f);
- m_lens[i].dim = 1.0f;
- m_lens[i].total = 0.6f;
- m_lens[i].off = 0.3f;
- i ++;
-
- m_lens[i].type = PARTISELY;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 7.2f, 34.8f-60.0f);
- m_lens[i].dim = 0.4f;
- m_lens[i].total = 0.7f;
- m_lens[i].off = 0.3f;
- i ++;
- m_lens[i].type = PARTISELY;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 34.3f-60.0f);
- m_lens[i].dim = 0.4f;
- m_lens[i].total = 0.0f;
- m_lens[i].off = 0.0f;
- i ++;
- m_lens[i].type = PARTISELR;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.4f-60.0f);
- m_lens[i].dim = 0.4f;
- m_lens[i].total = 0.6f;
- m_lens[i].off = 0.4f;
- i ++;
- m_lens[i].type = PARTISELR;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.0f-60.0f);
- m_lens[i].dim = 0.4f;
- m_lens[i].total = 0.8f;
- m_lens[i].off = 0.2f;
- i ++;
-
- m_lens[i].type = PARTISELY;
- m_lens[i].pos = pos+Math::Vector(-6.5f, 13.5f, -37.0f);
- m_lens[i].dim = 1.0f;
- m_lens[i].total = 0.0f;
- m_lens[i].off = 0.0f;
- i ++;
-
- m_lens[i].type = PARTISELY;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 12.2f, -39.8f);
- m_lens[i].dim = 1.8f;
- m_lens[i].total = 1.5f;
- m_lens[i].off = 0.5f;
- i ++;
-
- m_lens[i].type = PARTISELY;
- m_lens[i].pos = pos+Math::Vector(-7.0f, 8.5f, -47.0f);
- m_lens[i].dim = 0.6f;
- m_lens[i].total = 0.7f;
- m_lens[i].off = 0.5f;
- i ++;
-
- m_lensTotal = i;
-
- Init();
-}
-
-// Object's destructor.
-
-CAutoHuston::~CAutoHuston()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoHuston::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoHuston::Init()
-{
- m_time = 0.0f;
-
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-}
-
-
-// Start the object.
-
-void CAutoHuston::Start(int param)
-{
-}
-
-
-// Management of an event.
-
-bool CAutoHuston::EventProcess(const Event &event)
-{
- Math::Vector speed;
- Math::Point dim;
- float angle;
- int i;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
-
- angle = -m_time*1.0f;
- m_object->SetAngleY(1, angle); // rotates the radar
- angle = sinf(m_time*4.0f)*0.3f;
- m_object->SetAngleX(2, angle);
-
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
-
- // Flashes the keys.
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- for ( i=0 ; i<m_lensTotal ; i++ )
- {
- if ( m_lens[i].total != 0.0f &&
- Math::Mod(m_time, m_lens[i].total) < m_lens[i].off )
- {
- if ( m_lens[i].parti != -1 )
- {
- m_particule->DeleteParticule(m_lens[i].parti);
- m_lens[i].parti = -1;
- }
- }
- else
- {
- if ( m_lens[i].parti == -1 )
- {
- dim.x = m_lens[i].dim;
- dim.y = dim.x;
- m_lens[i].parti = m_particule->CreateParticule(m_lens[i].pos, speed, dim, m_lens[i].type, 1.0f, 0.0f, 0.0f);
- }
- }
- }
-
- return true;
-}
-
-// Stops the controller.
-
-bool CAutoHuston::Abort()
-{
- return true;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoHuston::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 115, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-
-// Returns an error due to state of the automation.
-
-Error CAutoHuston::RetError()
-{
- return ERR_OK;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autohuston.h"
+
+#include "ui/interface.h"
+#include "ui/window.h"
+
+
+
+
+// Object's constructor.
+
+CAutoHuston::CAutoHuston(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Math::Vector pos;
+ int i;
+
+ for ( i=0 ; i<HUSTONMAXLENS ; i++ )
+ {
+ m_lens[i].parti = -1;
+ }
+
+ pos = m_object->RetPosition(0);
+ m_lens[0].type = PARTISELR;
+ m_lens[1].type = PARTISELR;
+ m_lens[2].type = PARTISELR;
+ m_lens[3].type = PARTISELR;
+ m_lens[0].pos = pos+Math::Vector(0.0f+13.0f, 34.0f, 30.0f );
+ m_lens[1].pos = pos+Math::Vector(0.0f-13.0f, 34.0f, 30.0f );
+ m_lens[2].pos = pos+Math::Vector(0.0f , 34.0f, 30.0f+13.0f);
+ m_lens[3].pos = pos+Math::Vector(0.0f , 34.0f, 30.0f-13.0f);
+ m_lens[0].dim = 4.0f;
+ m_lens[1].dim = 4.0f;
+ m_lens[2].dim = 4.0f;
+ m_lens[3].dim = 4.0f;
+ m_lens[0].total = 1.0f;
+ m_lens[1].total = 1.0f;
+ m_lens[2].total = 1.0f;
+ m_lens[3].total = 1.0f;
+ m_lens[0].off = 0.4f;
+ m_lens[1].off = 0.4f;
+ m_lens[2].off = 0.4f;
+ m_lens[3].off = 0.4f;
+
+ // Part under the radar.
+ i = 4;
+ m_lens[i].type = PARTISELR;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 9.9f, 40.1f);
+ m_lens[i].dim = 1.8f;
+ m_lens[i].total = 0.4f;
+ m_lens[i].off = 0.2f;
+ i ++;
+
+ m_lens[i].type = PARTISELY;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 7.2f, 34.8f);
+ m_lens[i].dim = 0.4f;
+ m_lens[i].total = 0.7f;
+ m_lens[i].off = 0.3f;
+ i ++;
+ m_lens[i].type = PARTISELY;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 34.3f);
+ m_lens[i].dim = 0.4f;
+ m_lens[i].total = 0.7f;
+ m_lens[i].off = 0.3f;
+ i ++;
+ m_lens[i].type = PARTISELR;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.4f);
+ m_lens[i].dim = 0.4f;
+ m_lens[i].total = 0.0f;
+ m_lens[i].off = 0.0f;
+ i ++;
+ m_lens[i].type = PARTISELR;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.0f);
+ m_lens[i].dim = 0.4f;
+ m_lens[i].total = 1.0f;
+ m_lens[i].off = 0.5f;
+ i ++;
+
+ m_lens[i].type = PARTISELY;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 8.5f, 14.0f);
+ m_lens[i].dim = 1.2f;
+ m_lens[i].total = 0.8f;
+ m_lens[i].off = 0.2f;
+ i ++;
+
+ m_lens[i].type = PARTISELR;
+ m_lens[i].pos = pos+Math::Vector(4.0f, 6.0f, 8.6f);
+ m_lens[i].dim = 1.0f;
+ m_lens[i].total = 0.9f;
+ m_lens[i].off = 0.7f;
+ i ++;
+
+ // Part with three windows.
+ m_lens[i].type = PARTISELR;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 9.9f, -19.9f);
+ m_lens[i].dim = 1.0f;
+ m_lens[i].total = 0.6f;
+ m_lens[i].off = 0.3f;
+ i ++;
+
+ m_lens[i].type = PARTISELY;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 7.2f, 34.8f-60.0f);
+ m_lens[i].dim = 0.4f;
+ m_lens[i].total = 0.7f;
+ m_lens[i].off = 0.3f;
+ i ++;
+ m_lens[i].type = PARTISELY;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 34.3f-60.0f);
+ m_lens[i].dim = 0.4f;
+ m_lens[i].total = 0.0f;
+ m_lens[i].off = 0.0f;
+ i ++;
+ m_lens[i].type = PARTISELR;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.4f-60.0f);
+ m_lens[i].dim = 0.4f;
+ m_lens[i].total = 0.6f;
+ m_lens[i].off = 0.4f;
+ i ++;
+ m_lens[i].type = PARTISELR;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 6.5f, 33.0f-60.0f);
+ m_lens[i].dim = 0.4f;
+ m_lens[i].total = 0.8f;
+ m_lens[i].off = 0.2f;
+ i ++;
+
+ m_lens[i].type = PARTISELY;
+ m_lens[i].pos = pos+Math::Vector(-6.5f, 13.5f, -37.0f);
+ m_lens[i].dim = 1.0f;
+ m_lens[i].total = 0.0f;
+ m_lens[i].off = 0.0f;
+ i ++;
+
+ m_lens[i].type = PARTISELY;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 12.2f, -39.8f);
+ m_lens[i].dim = 1.8f;
+ m_lens[i].total = 1.5f;
+ m_lens[i].off = 0.5f;
+ i ++;
+
+ m_lens[i].type = PARTISELY;
+ m_lens[i].pos = pos+Math::Vector(-7.0f, 8.5f, -47.0f);
+ m_lens[i].dim = 0.6f;
+ m_lens[i].total = 0.7f;
+ m_lens[i].off = 0.5f;
+ i ++;
+
+ m_lensTotal = i;
+
+ Init();
+}
+
+// Object's destructor.
+
+CAutoHuston::~CAutoHuston()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoHuston::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoHuston::Init()
+{
+ m_time = 0.0f;
+
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+}
+
+
+// Start the object.
+
+void CAutoHuston::Start(int param)
+{
+}
+
+
+// Management of an event.
+
+bool CAutoHuston::EventProcess(const Event &event)
+{
+ Math::Vector speed;
+ Math::Point dim;
+ float angle;
+ int i;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+
+ angle = -m_time*1.0f;
+ m_object->SetAngleY(1, angle); // rotates the radar
+ angle = sinf(m_time*4.0f)*0.3f;
+ m_object->SetAngleX(2, angle);
+
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+
+ // Flashes the keys.
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ for ( i=0 ; i<m_lensTotal ; i++ )
+ {
+ if ( m_lens[i].total != 0.0f &&
+ Math::Mod(m_time, m_lens[i].total) < m_lens[i].off )
+ {
+ if ( m_lens[i].parti != -1 )
+ {
+ m_particule->DeleteParticule(m_lens[i].parti);
+ m_lens[i].parti = -1;
+ }
+ }
+ else
+ {
+ if ( m_lens[i].parti == -1 )
+ {
+ dim.x = m_lens[i].dim;
+ dim.y = dim.x;
+ m_lens[i].parti = m_particule->CreateParticule(m_lens[i].pos, speed, dim, m_lens[i].type, 1.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+
+ return true;
+}
+
+// Stops the controller.
+
+bool CAutoHuston::Abort()
+{
+ return true;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoHuston::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 115, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+
+// Returns an error due to state of the automation.
+
+Error CAutoHuston::RetError()
+{
+ return ERR_OK;
+}
+
diff --git a/src/object/auto/autohuston.h b/src/object/auto/autohuston.h
index a12c4f2..a59f8f2 100644
--- a/src/object/auto/autohuston.h
+++ b/src/object/auto/autohuston.h
@@ -1,65 +1,65 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autohuston.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-#include "old/particule.h"
-
-
-
-struct HustonLens
-{
- int parti;
- ParticuleType type;
- Math::Vector pos;
- float dim;
- float total;
- float off;
-};
-
-
-const int HUSTONMAXLENS = 20;
-
-
-class CAutoHuston : public CAuto
-{
-public:
- CAutoHuston(CInstanceManager* iMan, CObject* object);
- ~CAutoHuston();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- void Start(int param);
- bool EventProcess(const Event &event);
- bool Abort();
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
-protected:
-
-protected:
- float m_progress;
- float m_speed;
- HustonLens m_lens[HUSTONMAXLENS];
- int m_lensTotal;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autohuston.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+#include "old/particule.h"
+
+
+
+struct HustonLens
+{
+ int parti;
+ ParticuleType type;
+ Math::Vector pos;
+ float dim;
+ float total;
+ float off;
+};
+
+
+const int HUSTONMAXLENS = 20;
+
+
+class CAutoHuston : public CAuto
+{
+public:
+ CAutoHuston(CInstanceManager* iMan, CObject* object);
+ ~CAutoHuston();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ void Start(int param);
+ bool EventProcess(const Event &event);
+ bool Abort();
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+protected:
+
+protected:
+ float m_progress;
+ float m_speed;
+ HustonLens m_lens[HUSTONMAXLENS];
+ int m_lensTotal;
+};
+
diff --git a/src/object/auto/autoinfo.cpp b/src/object/auto/autoinfo.cpp
index 6e00d44..56fd8c7 100644
--- a/src/object/auto/autoinfo.cpp
+++ b/src/object/auto/autoinfo.cpp
@@ -1,517 +1,517 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoinfo.h"
-
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/list.h"
-#include "ui/window.h"
-
-
-
-
-
-// Object's constructor.
-
-CAutoInfo::CAutoInfo(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
-}
-
-// Object's destructor.
-
-CAutoInfo::~CAutoInfo()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoInfo::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoInfo::Init()
-{
- m_phase = AIP_WAIT;
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_bLastVirus = false;
-
- CAuto::Init();
-}
-
-
-// Start a emission.
-
-void CAutoInfo::Start(int param)
-{
- Math::Vector pos, speed;
- Math::Point dim;
-
- if ( param == 0 ) // instruction "receive" ?
- {
- m_phase = AIP_EMETTE;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- else if ( param == 2 ) // instruction "send" ?
- {
- m_phase = AIP_RECEIVE;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- else
- {
- m_phase = AIP_ERROR;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
-
- m_lastParticule = 0;
- m_goal = m_object->RetPosition(0);
-
- if ( m_phase == AIP_EMETTE )
- {
- pos = m_goal;
- pos.y += 9.5f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 30.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISPHERE4, 1.5f, 0.0f, 0.0f);
-
- m_sound->Play(SOUND_LABO, pos, 1.0f, 2.0f);
- }
- if ( m_phase == AIP_RECEIVE )
- {
- pos = m_goal;
- pos.y += 9.5f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 50.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISPHERE6, 1.5f, 0.0f, 0.0f);
-
- m_sound->Play(SOUND_LABO, pos, 1.0f, 2.0f);
- }
- if ( m_phase == AIP_ERROR )
- {
- m_sound->Play(SOUND_GGG, pos, 1.0f, 0.5f);
- }
-}
-
-
-// Management of an event.
-
-bool CAutoInfo::EventProcess(const Event &event)
-{
- Math::Vector pos, speed;
- Math::Point dim;
- float duration, angle, rTime;
- int i;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
-
- angle = m_object->RetAngleY(1);
- angle += Math::Rand()*0.3f;
- m_object->SetAngleY(1, angle);
-
- m_object->SetAngleX(2, (Math::Rand()-0.5f)*0.3f);
- m_object->SetAngleX(4, (Math::Rand()-0.5f)*0.3f);
- m_object->SetAngleX(6, (Math::Rand()-0.5f)*0.3f);
-
- m_object->SetAngleZ(2, (Math::Rand()-0.5f)*0.3f);
- m_object->SetAngleZ(4, (Math::Rand()-0.5f)*0.3f);
- m_object->SetAngleZ(6, (Math::Rand()-0.5f)*0.3f);
-
- UpdateListVirus();
- }
- m_bLastVirus = true;
- return true;
- }
- else
- {
- if ( m_bLastVirus )
- {
- m_bLastVirus = false;
- UpdateList(); // normally returns the list
- }
- else
- {
- if ( m_object->RetInfoUpdate() )
- {
- UpdateList(); // updates the list
- }
- }
- }
-
- UpdateInterface(event.rTime);
-
- rTime = event.rTime;
-
- if ( m_phase == AIP_EMETTE ) // instruction "receive" ?
- {
- if ( m_progress < 0.5f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- for ( i=0 ; i<4 ; i++ )
- {
- pos = m_goal;
- pos.y += 9.5f;
- speed.x = (Math::Rand()-0.5f)*50.0f;
- speed.z = (Math::Rand()-0.5f)*50.0f;
- speed.y = (Math::Rand()-0.5f)*50.0f;
- speed *= 0.5f+m_progress*0.5f;
- dim.x = 0.6f;
- dim.y = dim.x;
- duration = Math::Rand()*0.5f+0.5f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
- duration, 0.0f,
- duration*0.9f, 0.7f);
- }
- }
-
- if ( m_progress < 1.0f )
- {
- m_progress += rTime*m_speed;
-
- m_object->SetAngleZ(2, m_progress*2.0f*Math::PI);
- m_object->SetAngleZ(4, m_progress*2.0f*Math::PI);
- m_object->SetAngleZ(6, m_progress*2.0f*Math::PI);
- }
- else
- {
- m_phase = AIP_WAIT;
-
- m_object->SetAngleX(2, 0.0f);
- m_object->SetAngleX(4, 0.0f);
- m_object->SetAngleX(6, 0.0f);
-
- m_object->SetAngleZ(2, 0.0f);
- m_object->SetAngleZ(4, 0.0f);
- m_object->SetAngleZ(6, 0.0f);
- }
- }
-
- if ( m_phase == AIP_RECEIVE ) // instruction "send" ?
- {
- if ( m_progress < 0.5f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- for ( i=0 ; i<4 ; i++ )
- {
- pos = m_goal;
- pos.y += 9.5f;
- speed = pos;
- pos.x += (Math::Rand()-0.5f)*40.0f;
- pos.y += (Math::Rand()-0.5f)*40.0f;
- pos.z += (Math::Rand()-0.5f)*40.0f;
- speed = (speed-pos)*1.0f;
-//? speed *= 0.5f+m_progress*0.5f;
- dim.x = 0.6f;
- dim.y = dim.x;
- duration = Math::Rand()*0.5f+0.5f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
- duration, 0.0f,
- duration*0.9f, 0.7f);
- }
- }
-
- if ( m_progress < 1.0f )
- {
- m_progress += rTime*m_speed;
-
- m_object->SetAngleZ(2, m_progress*2.0f*Math::PI);
- m_object->SetAngleZ(4, m_progress*2.0f*Math::PI);
- m_object->SetAngleZ(6, m_progress*2.0f*Math::PI);
- }
- else
- {
- m_phase = AIP_WAIT;
-
- m_object->SetAngleX(2, 0.0f);
- m_object->SetAngleX(4, 0.0f);
- m_object->SetAngleX(6, 0.0f);
-
- m_object->SetAngleZ(2, 0.0f);
- m_object->SetAngleZ(4, 0.0f);
- m_object->SetAngleZ(6, 0.0f);
- }
- }
-
- if ( m_phase == AIP_ERROR )
- {
- if ( m_progress < 0.5f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_goal;
- speed.x = (Math::Rand()-0.5f)*5.0f;
- speed.z = (Math::Rand()-0.5f)*5.0f;
- speed.y = 5.0f+Math::Rand()*5.0f;
- dim.x = 5.0f+Math::Rand()*5.0f;
- dim.y = dim.x;
- duration = Math::Rand()*0.5f+0.5f;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 4.0f);
- }
-
- if ( m_progress < 1.0f )
- {
- m_progress += rTime*m_speed;
- rTime = 0.0f; // stops the rotation
-
- if ( m_progress < 0.5f )
- {
- angle = m_progress/0.5f;
- }
- else
- {
- angle = 1.0f-(m_progress-0.5f)/0.5f;
- }
- m_object->SetAngleX(2, angle*0.5f);
- m_object->SetAngleX(4, angle*0.5f);
- m_object->SetAngleX(6, angle*0.5f);
-
- m_object->SetAngleZ(2, (Math::Rand()-0.5f)*0.2f);
- m_object->SetAngleZ(4, (Math::Rand()-0.5f)*0.2f);
- m_object->SetAngleZ(6, (Math::Rand()-0.5f)*0.2f);
- }
- else
- {
- m_phase = AIP_WAIT;
-
- m_object->SetAngleX(2, 0.0f);
- m_object->SetAngleX(4, 0.0f);
- m_object->SetAngleX(6, 0.0f);
-
- m_object->SetAngleZ(2, 0.0f);
- m_object->SetAngleZ(4, 0.0f);
- m_object->SetAngleZ(6, 0.0f);
- }
- }
-
- angle = m_object->RetAngleY(1);
- angle += rTime*0.5f;
- m_object->SetAngleY(1, angle);
-
- m_object->SetAngleX(3, sinf(m_time*6.0f+Math::PI*0.0f/3.0f)*0.3f);
- m_object->SetAngleX(5, sinf(m_time*6.0f+Math::PI*2.0f/3.0f)*0.3f);
- m_object->SetAngleX(7, sinf(m_time*6.0f+Math::PI*4.0f/3.0f)*0.3f);
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoInfo::RetError()
-{
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- return ERR_OK;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoInfo::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- CList* pl;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*7.0f;
- pos.y = oy+sy*0.0f;
- ddim.x = 160.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pl = pw->CreateList(pos, ddim, 1, EVENT_OBJECT_GINFO, 1.10f);
- pl->SetSelectCap(false);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 112, EVENT_OBJECT_TYPE);
-
- UpdateList();
- return true;
-}
-
-// Updates the state of all buttons on the interface,
-// following the time that elapses ...
-
-void CAutoInfo::UpdateInterface(float rTime)
-{
- CAuto::UpdateInterface(rTime);
-}
-
-
-// Updates the contents of the list.
-
-void CAutoInfo::UpdateList()
-{
- CWindow* pw;
- CList* pl;
- Info info;
- int total, i;
- char text[100];
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pl = (CList*)pw->SearchControl(EVENT_OBJECT_GINFO);
- if ( pl == 0 ) return;
-
- pl->Flush();
- total = m_object->RetInfoTotal();
- if ( total == 0 )
- {
- pl->ClearState(STATE_ENABLE);
- }
- else
- {
- pl->SetState(STATE_ENABLE);
-
- for ( i=0 ; i<total ; i++ )
- {
- info = m_object->RetInfo(i);
- sprintf(text, "%s = %.2f", info.name, info.value);
- pl->SetName(i, text);
- }
- }
-
- m_object->SetInfoUpdate(false);
-}
-
-// Updates the content of contaminating the list.
-
-void CAutoInfo::UpdateListVirus()
-{
- CWindow* pw;
- CList* pl;
- int i, j, max;
- char text[100];
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pl = (CList*)pw->SearchControl(EVENT_OBJECT_GINFO);
- if ( pl == 0 ) return;
-
- pl->SetState(STATE_ENABLE);
-
- pl->Flush();
- for ( i=0 ; i<4 ; i++ )
- {
- max = (int)(2.0f+Math::Rand()*10.0f);
- for ( j=0 ; j<max ; j++ )
- {
- do
- {
- text[j] = ' '+(int)(Math::Rand()*94.0f);
- }
- while ( text[j] == '\\' );
- }
- text[j] = 0;
-
- pl->SetName(i, text);
- }
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoInfo::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == AIP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoInfo::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoInfoPhase)OpInt(line, "aPhase", AIP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoinfo.h"
+
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/list.h"
+#include "ui/window.h"
+
+
+
+
+
+// Object's constructor.
+
+CAutoInfo::CAutoInfo(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+}
+
+// Object's destructor.
+
+CAutoInfo::~CAutoInfo()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoInfo::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoInfo::Init()
+{
+ m_phase = AIP_WAIT;
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_bLastVirus = false;
+
+ CAuto::Init();
+}
+
+
+// Start a emission.
+
+void CAutoInfo::Start(int param)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+
+ if ( param == 0 ) // instruction "receive" ?
+ {
+ m_phase = AIP_EMETTE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ else if ( param == 2 ) // instruction "send" ?
+ {
+ m_phase = AIP_RECEIVE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ else
+ {
+ m_phase = AIP_ERROR;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+
+ m_lastParticule = 0;
+ m_goal = m_object->RetPosition(0);
+
+ if ( m_phase == AIP_EMETTE )
+ {
+ pos = m_goal;
+ pos.y += 9.5f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 30.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISPHERE4, 1.5f, 0.0f, 0.0f);
+
+ m_sound->Play(SOUND_LABO, pos, 1.0f, 2.0f);
+ }
+ if ( m_phase == AIP_RECEIVE )
+ {
+ pos = m_goal;
+ pos.y += 9.5f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 50.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISPHERE6, 1.5f, 0.0f, 0.0f);
+
+ m_sound->Play(SOUND_LABO, pos, 1.0f, 2.0f);
+ }
+ if ( m_phase == AIP_ERROR )
+ {
+ m_sound->Play(SOUND_GGG, pos, 1.0f, 0.5f);
+ }
+}
+
+
+// Management of an event.
+
+bool CAutoInfo::EventProcess(const Event &event)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float duration, angle, rTime;
+ int i;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+
+ angle = m_object->RetAngleY(1);
+ angle += Math::Rand()*0.3f;
+ m_object->SetAngleY(1, angle);
+
+ m_object->SetAngleX(2, (Math::Rand()-0.5f)*0.3f);
+ m_object->SetAngleX(4, (Math::Rand()-0.5f)*0.3f);
+ m_object->SetAngleX(6, (Math::Rand()-0.5f)*0.3f);
+
+ m_object->SetAngleZ(2, (Math::Rand()-0.5f)*0.3f);
+ m_object->SetAngleZ(4, (Math::Rand()-0.5f)*0.3f);
+ m_object->SetAngleZ(6, (Math::Rand()-0.5f)*0.3f);
+
+ UpdateListVirus();
+ }
+ m_bLastVirus = true;
+ return true;
+ }
+ else
+ {
+ if ( m_bLastVirus )
+ {
+ m_bLastVirus = false;
+ UpdateList(); // normally returns the list
+ }
+ else
+ {
+ if ( m_object->RetInfoUpdate() )
+ {
+ UpdateList(); // updates the list
+ }
+ }
+ }
+
+ UpdateInterface(event.rTime);
+
+ rTime = event.rTime;
+
+ if ( m_phase == AIP_EMETTE ) // instruction "receive" ?
+ {
+ if ( m_progress < 0.5f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ pos = m_goal;
+ pos.y += 9.5f;
+ speed.x = (Math::Rand()-0.5f)*50.0f;
+ speed.z = (Math::Rand()-0.5f)*50.0f;
+ speed.y = (Math::Rand()-0.5f)*50.0f;
+ speed *= 0.5f+m_progress*0.5f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ duration = Math::Rand()*0.5f+0.5f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
+ duration, 0.0f,
+ duration*0.9f, 0.7f);
+ }
+ }
+
+ if ( m_progress < 1.0f )
+ {
+ m_progress += rTime*m_speed;
+
+ m_object->SetAngleZ(2, m_progress*2.0f*Math::PI);
+ m_object->SetAngleZ(4, m_progress*2.0f*Math::PI);
+ m_object->SetAngleZ(6, m_progress*2.0f*Math::PI);
+ }
+ else
+ {
+ m_phase = AIP_WAIT;
+
+ m_object->SetAngleX(2, 0.0f);
+ m_object->SetAngleX(4, 0.0f);
+ m_object->SetAngleX(6, 0.0f);
+
+ m_object->SetAngleZ(2, 0.0f);
+ m_object->SetAngleZ(4, 0.0f);
+ m_object->SetAngleZ(6, 0.0f);
+ }
+ }
+
+ if ( m_phase == AIP_RECEIVE ) // instruction "send" ?
+ {
+ if ( m_progress < 0.5f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ pos = m_goal;
+ pos.y += 9.5f;
+ speed = pos;
+ pos.x += (Math::Rand()-0.5f)*40.0f;
+ pos.y += (Math::Rand()-0.5f)*40.0f;
+ pos.z += (Math::Rand()-0.5f)*40.0f;
+ speed = (speed-pos)*1.0f;
+//? speed *= 0.5f+m_progress*0.5f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ duration = Math::Rand()*0.5f+0.5f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
+ duration, 0.0f,
+ duration*0.9f, 0.7f);
+ }
+ }
+
+ if ( m_progress < 1.0f )
+ {
+ m_progress += rTime*m_speed;
+
+ m_object->SetAngleZ(2, m_progress*2.0f*Math::PI);
+ m_object->SetAngleZ(4, m_progress*2.0f*Math::PI);
+ m_object->SetAngleZ(6, m_progress*2.0f*Math::PI);
+ }
+ else
+ {
+ m_phase = AIP_WAIT;
+
+ m_object->SetAngleX(2, 0.0f);
+ m_object->SetAngleX(4, 0.0f);
+ m_object->SetAngleX(6, 0.0f);
+
+ m_object->SetAngleZ(2, 0.0f);
+ m_object->SetAngleZ(4, 0.0f);
+ m_object->SetAngleZ(6, 0.0f);
+ }
+ }
+
+ if ( m_phase == AIP_ERROR )
+ {
+ if ( m_progress < 0.5f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_goal;
+ speed.x = (Math::Rand()-0.5f)*5.0f;
+ speed.z = (Math::Rand()-0.5f)*5.0f;
+ speed.y = 5.0f+Math::Rand()*5.0f;
+ dim.x = 5.0f+Math::Rand()*5.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*0.5f+0.5f;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 4.0f);
+ }
+
+ if ( m_progress < 1.0f )
+ {
+ m_progress += rTime*m_speed;
+ rTime = 0.0f; // stops the rotation
+
+ if ( m_progress < 0.5f )
+ {
+ angle = m_progress/0.5f;
+ }
+ else
+ {
+ angle = 1.0f-(m_progress-0.5f)/0.5f;
+ }
+ m_object->SetAngleX(2, angle*0.5f);
+ m_object->SetAngleX(4, angle*0.5f);
+ m_object->SetAngleX(6, angle*0.5f);
+
+ m_object->SetAngleZ(2, (Math::Rand()-0.5f)*0.2f);
+ m_object->SetAngleZ(4, (Math::Rand()-0.5f)*0.2f);
+ m_object->SetAngleZ(6, (Math::Rand()-0.5f)*0.2f);
+ }
+ else
+ {
+ m_phase = AIP_WAIT;
+
+ m_object->SetAngleX(2, 0.0f);
+ m_object->SetAngleX(4, 0.0f);
+ m_object->SetAngleX(6, 0.0f);
+
+ m_object->SetAngleZ(2, 0.0f);
+ m_object->SetAngleZ(4, 0.0f);
+ m_object->SetAngleZ(6, 0.0f);
+ }
+ }
+
+ angle = m_object->RetAngleY(1);
+ angle += rTime*0.5f;
+ m_object->SetAngleY(1, angle);
+
+ m_object->SetAngleX(3, sinf(m_time*6.0f+Math::PI*0.0f/3.0f)*0.3f);
+ m_object->SetAngleX(5, sinf(m_time*6.0f+Math::PI*2.0f/3.0f)*0.3f);
+ m_object->SetAngleX(7, sinf(m_time*6.0f+Math::PI*4.0f/3.0f)*0.3f);
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoInfo::RetError()
+{
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ return ERR_OK;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoInfo::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ CList* pl;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*7.0f;
+ pos.y = oy+sy*0.0f;
+ ddim.x = 160.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pl = pw->CreateList(pos, ddim, 1, EVENT_OBJECT_GINFO, 1.10f);
+ pl->SetSelectCap(false);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 112, EVENT_OBJECT_TYPE);
+
+ UpdateList();
+ return true;
+}
+
+// Updates the state of all buttons on the interface,
+// following the time that elapses ...
+
+void CAutoInfo::UpdateInterface(float rTime)
+{
+ CAuto::UpdateInterface(rTime);
+}
+
+
+// Updates the contents of the list.
+
+void CAutoInfo::UpdateList()
+{
+ CWindow* pw;
+ CList* pl;
+ Info info;
+ int total, i;
+ char text[100];
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pl = (CList*)pw->SearchControl(EVENT_OBJECT_GINFO);
+ if ( pl == 0 ) return;
+
+ pl->Flush();
+ total = m_object->RetInfoTotal();
+ if ( total == 0 )
+ {
+ pl->ClearState(STATE_ENABLE);
+ }
+ else
+ {
+ pl->SetState(STATE_ENABLE);
+
+ for ( i=0 ; i<total ; i++ )
+ {
+ info = m_object->RetInfo(i);
+ sprintf(text, "%s = %.2f", info.name, info.value);
+ pl->SetName(i, text);
+ }
+ }
+
+ m_object->SetInfoUpdate(false);
+}
+
+// Updates the content of contaminating the list.
+
+void CAutoInfo::UpdateListVirus()
+{
+ CWindow* pw;
+ CList* pl;
+ int i, j, max;
+ char text[100];
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pl = (CList*)pw->SearchControl(EVENT_OBJECT_GINFO);
+ if ( pl == 0 ) return;
+
+ pl->SetState(STATE_ENABLE);
+
+ pl->Flush();
+ for ( i=0 ; i<4 ; i++ )
+ {
+ max = (int)(2.0f+Math::Rand()*10.0f);
+ for ( j=0 ; j<max ; j++ )
+ {
+ do
+ {
+ text[j] = ' '+(int)(Math::Rand()*94.0f);
+ }
+ while ( text[j] == '\\' );
+ }
+ text[j] = 0;
+
+ pl->SetName(i, text);
+ }
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoInfo::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == AIP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoInfo::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoInfoPhase)OpInt(line, "aPhase", AIP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autoinfo.h b/src/object/auto/autoinfo.h
index cf3d1d4..cfe3c1b 100644
--- a/src/object/auto/autoinfo.h
+++ b/src/object/auto/autoinfo.h
@@ -1,68 +1,68 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoinfo.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoInfoPhase
-{
- AIP_WAIT = 1,
- AIP_EMETTE = 2,
- AIP_RECEIVE = 3,
- AIP_ERROR = 4,
-};
-
-
-
-class CAutoInfo : public CAuto
-{
-public:
- CAutoInfo(CInstanceManager* iMan, CObject* object);
- ~CAutoInfo();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- void Start(int param);
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- void UpdateInterface(float rTime);
- void UpdateList();
- void UpdateListVirus();
-
-protected:
- AutoInfoPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
- Math::Vector m_goal;
- bool m_bLastVirus;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoinfo.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoInfoPhase
+{
+ AIP_WAIT = 1,
+ AIP_EMETTE = 2,
+ AIP_RECEIVE = 3,
+ AIP_ERROR = 4,
+};
+
+
+
+class CAutoInfo : public CAuto
+{
+public:
+ CAutoInfo(CInstanceManager* iMan, CObject* object);
+ ~CAutoInfo();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ void Start(int param);
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ void UpdateInterface(float rTime);
+ void UpdateList();
+ void UpdateListVirus();
+
+protected:
+ AutoInfoPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+ Math::Vector m_goal;
+ bool m_bLastVirus;
+};
+
diff --git a/src/object/auto/autojostle.cpp b/src/object/auto/autojostle.cpp
index 6917ae7..3944297 100644
--- a/src/object/auto/autojostle.cpp
+++ b/src/object/auto/autojostle.cpp
@@ -1,142 +1,142 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autojostle.h"
-
-
-
-
-// Object's constructor.
-
-CAutoJostle::CAutoJostle(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
-}
-
-// Object's destructor.
-
-CAutoJostle::~CAutoJostle()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoJostle::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoJostle::Init()
-{
- m_time = 0.0f;
- m_error = ERR_CONTINUE;
-
- CAuto::Init();
-}
-
-
-// Start an emission.
-
-void CAutoJostle::Start(int param, float force)
-{
- ObjectType type;
-
- if ( force < 0.0f ) force = 0.0f;
- if ( force > 1.0f ) force = 1.0f;
-
- m_force = force;
- m_progress = 0.0f;
- m_speed = 1.0f/(0.5f+force*1.0f); // 0.5 .. 1.5
- m_time = 0.0f;
- m_error = ERR_CONTINUE;
-
- type = m_object->RetType();
- if ( type >= OBJECT_PLANT5 &&
- type <= OBJECT_PLANT7 ) // clover?
- {
- m_force *= 3.0f;
- }
-}
-
-
-// Management of an event.
-
-bool CAutoJostle::EventProcess(const Event &event)
-{
- Math::Vector dir;
- float factor, angle, zoom;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- if ( m_progress < 1.0f )
- {
- m_progress += event.rTime*m_speed;
-
- if ( m_progress < 0.5f )
- {
- factor = m_progress/0.5f;
- }
- else
- {
- factor = 2.0f-m_progress/0.5f;
- }
- factor *= m_force;
-
- dir.x = sinf(m_progress*Math::PI*4.0f);
- dir.z = cosf(m_progress*Math::PI*4.0f);
-
- angle = sinf(m_time*10.0f)*factor*0.04f;
- m_object->SetAngleX(0, angle*dir.z);
- m_object->SetAngleZ(0, angle*dir.x);
-
- zoom = 1.0f+sinf(m_time*8.0f)*factor*0.06f;
- m_object->SetZoomX(0, zoom);
- zoom = 1.0f+sinf(m_time*5.0f)*factor*0.06f;
- m_object->SetZoomY(0, zoom);
- zoom = 1.0f+sinf(m_time*7.0f)*factor*0.06f;
- m_object->SetZoomZ(0, zoom);
- }
- else
- {
- m_object->SetAngleX(0, 0.0f);
- m_object->SetAngleZ(0, 0.0f);
- m_object->SetZoom(0, Math::Vector(1.0f, 1.0f, 1.0f));
- m_error = ERR_STOP;
- }
-
- return true;
-}
-
-
-// Indicates whether the controller has completed its activity.
-
-Error CAutoJostle::IsEnded()
-{
- return m_error;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autojostle.h"
+
+
+
+
+// Object's constructor.
+
+CAutoJostle::CAutoJostle(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+}
+
+// Object's destructor.
+
+CAutoJostle::~CAutoJostle()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoJostle::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoJostle::Init()
+{
+ m_time = 0.0f;
+ m_error = ERR_CONTINUE;
+
+ CAuto::Init();
+}
+
+
+// Start an emission.
+
+void CAutoJostle::Start(int param, float force)
+{
+ ObjectType type;
+
+ if ( force < 0.0f ) force = 0.0f;
+ if ( force > 1.0f ) force = 1.0f;
+
+ m_force = force;
+ m_progress = 0.0f;
+ m_speed = 1.0f/(0.5f+force*1.0f); // 0.5 .. 1.5
+ m_time = 0.0f;
+ m_error = ERR_CONTINUE;
+
+ type = m_object->RetType();
+ if ( type >= OBJECT_PLANT5 &&
+ type <= OBJECT_PLANT7 ) // clover?
+ {
+ m_force *= 3.0f;
+ }
+}
+
+
+// Management of an event.
+
+bool CAutoJostle::EventProcess(const Event &event)
+{
+ Math::Vector dir;
+ float factor, angle, zoom;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ if ( m_progress < 1.0f )
+ {
+ m_progress += event.rTime*m_speed;
+
+ if ( m_progress < 0.5f )
+ {
+ factor = m_progress/0.5f;
+ }
+ else
+ {
+ factor = 2.0f-m_progress/0.5f;
+ }
+ factor *= m_force;
+
+ dir.x = sinf(m_progress*Math::PI*4.0f);
+ dir.z = cosf(m_progress*Math::PI*4.0f);
+
+ angle = sinf(m_time*10.0f)*factor*0.04f;
+ m_object->SetAngleX(0, angle*dir.z);
+ m_object->SetAngleZ(0, angle*dir.x);
+
+ zoom = 1.0f+sinf(m_time*8.0f)*factor*0.06f;
+ m_object->SetZoomX(0, zoom);
+ zoom = 1.0f+sinf(m_time*5.0f)*factor*0.06f;
+ m_object->SetZoomY(0, zoom);
+ zoom = 1.0f+sinf(m_time*7.0f)*factor*0.06f;
+ m_object->SetZoomZ(0, zoom);
+ }
+ else
+ {
+ m_object->SetAngleX(0, 0.0f);
+ m_object->SetAngleZ(0, 0.0f);
+ m_object->SetZoom(0, Math::Vector(1.0f, 1.0f, 1.0f));
+ m_error = ERR_STOP;
+ }
+
+ return true;
+}
+
+
+// Indicates whether the controller has completed its activity.
+
+Error CAutoJostle::IsEnded()
+{
+ return m_error;
+}
+
+
diff --git a/src/object/auto/autojostle.h b/src/object/auto/autojostle.h
index c76f953..70bb5e6 100644
--- a/src/object/auto/autojostle.h
+++ b/src/object/auto/autojostle.h
@@ -1,48 +1,48 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autojostle.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-class CAutoJostle : public CAuto
-{
-public:
- CAutoJostle(CInstanceManager* iMan, CObject* object);
- ~CAutoJostle();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- void Start(int param, float force);
- bool EventProcess(const Event &event);
- Error IsEnded();
-
-protected:
-
-protected:
- float m_force;
- float m_progress;
- float m_speed;
- float m_lastParticule;
- Error m_error;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autojostle.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+class CAutoJostle : public CAuto
+{
+public:
+ CAutoJostle(CInstanceManager* iMan, CObject* object);
+ ~CAutoJostle();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ void Start(int param, float force);
+ bool EventProcess(const Event &event);
+ Error IsEnded();
+
+protected:
+
+protected:
+ float m_force;
+ float m_progress;
+ float m_speed;
+ float m_lastParticule;
+ Error m_error;
+};
+
diff --git a/src/object/auto/autokid.cpp b/src/object/auto/autokid.cpp
index 9177aa8..e5987cc 100644
--- a/src/object/auto/autokid.cpp
+++ b/src/object/auto/autokid.cpp
@@ -1,201 +1,201 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autokid.h"
-
-#include "old/particule.h"
-#include "old/water.h"
-
-
-
-// Object's constructor.
-
-CAutoKid::CAutoKid(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- m_soundChannel = -1;
- Init();
-}
-
-// Object's constructor.
-
-CAutoKid::~CAutoKid()
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-}
-
-
-// Destroys the object.
-
-void CAutoKid::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoKid::Init()
-{
- Math::Vector pos;
-
- m_speed = 1.0f/1.0f;
- m_progress = 0.0f;
- m_lastParticule = 0.0f;
-
- if ( m_type == OBJECT_TEEN36 ) // trunk ?
- {
- pos = m_object->RetPosition(0);
- m_speed = 1.0f/(1.0f+(Math::Mod(pos.x/10.0f-0.5f, 1.0f)*0.2f));
- m_progress = Math::Mod(pos.x/10.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_TEEN37 ) // boat?
- {
- pos = m_object->RetPosition(0);
- m_speed = 1.0f/(1.0f+(Math::Mod(pos.x/10.0f-0.5f, 1.0f)*0.2f))*2.5f;
- m_progress = Math::Mod(pos.x/10.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_TEEN38 ) // fan?
- {
- if ( m_soundChannel == -1 )
- {
-//? m_soundChannel = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 1.0f, 0.5f, true);
- m_bSilent = false;
- }
- }
-}
-
-
-// Management of an event.
-
-bool CAutoKid::EventProcess(const Event &event)
-{
- Math::Vector vib, pos, speed;
- Math::Point dim;
-
- CAuto::EventProcess(event);
-
- if ( m_soundChannel != -1 )
- {
- if ( m_engine->RetPause() )
- {
- if ( !m_bSilent )
- {
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.1f, SOPER_CONTINUE);
- m_bSilent = true;
- }
- }
- else
- {
- if ( m_bSilent )
- {
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 0.1f, SOPER_CONTINUE);
- m_bSilent = false;
- }
- }
- }
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
-
- if ( m_type == OBJECT_TEEN36 ) // trunk?
- {
- vib.x = 0.0f;
- vib.y = sinf(m_progress)*1.0f;
- vib.z = 0.0f;
- m_object->SetLinVibration(vib);
-
- vib.x = 0.0f;
- vib.y = 0.0f;
- vib.z = sinf(m_progress*0.5f)*0.05f;
- m_object->SetCirVibration(vib);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.15f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.y = m_water->RetLevel()+1.0f;
- pos.x += (Math::Rand()-0.5f)*50.0f;
- pos.z += (Math::Rand()-0.5f)*50.0f;
- speed.y = 0.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- dim.x = 50.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFLIC, 3.0f, 0.0f, 0.0f);
- }
- }
-
- if ( m_type == OBJECT_TEEN37 ) // boat?
- {
- vib.x = 0.0f;
- vib.y = sinf(m_progress)*1.0f;
- vib.z = 0.0f;
- m_object->SetLinVibration(vib);
-
- vib.x = 0.0f;
- vib.y = 0.0f;
- vib.z = sinf(m_progress*0.5f)*0.15f;
- m_object->SetCirVibration(vib);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.15f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.y = m_water->RetLevel()+1.0f;
- pos.x += (Math::Rand()-0.5f)*20.0f;
- pos.z += (Math::Rand()-0.5f)*20.0f;
- speed.y = 0.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- dim.x = 20.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFLIC, 3.0f, 0.0f, 0.0f);
- }
- }
-
- if ( m_type == OBJECT_TEEN38 ) // fan?
- {
- m_object->SetAngleY(1, sinf(m_progress*0.6f)*0.4f);
- m_object->SetAngleX(2, m_progress*5.0f);
- }
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoKid::RetError()
-{
- return ERR_OK;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autokid.h"
+
+#include "old/particule.h"
+#include "old/water.h"
+
+
+
+// Object's constructor.
+
+CAutoKid::CAutoKid(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ m_soundChannel = -1;
+ Init();
+}
+
+// Object's constructor.
+
+CAutoKid::~CAutoKid()
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+}
+
+
+// Destroys the object.
+
+void CAutoKid::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoKid::Init()
+{
+ Math::Vector pos;
+
+ m_speed = 1.0f/1.0f;
+ m_progress = 0.0f;
+ m_lastParticule = 0.0f;
+
+ if ( m_type == OBJECT_TEEN36 ) // trunk ?
+ {
+ pos = m_object->RetPosition(0);
+ m_speed = 1.0f/(1.0f+(Math::Mod(pos.x/10.0f-0.5f, 1.0f)*0.2f));
+ m_progress = Math::Mod(pos.x/10.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_TEEN37 ) // boat?
+ {
+ pos = m_object->RetPosition(0);
+ m_speed = 1.0f/(1.0f+(Math::Mod(pos.x/10.0f-0.5f, 1.0f)*0.2f))*2.5f;
+ m_progress = Math::Mod(pos.x/10.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_TEEN38 ) // fan?
+ {
+ if ( m_soundChannel == -1 )
+ {
+//? m_soundChannel = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 1.0f, 0.5f, true);
+ m_bSilent = false;
+ }
+ }
+}
+
+
+// Management of an event.
+
+bool CAutoKid::EventProcess(const Event &event)
+{
+ Math::Vector vib, pos, speed;
+ Math::Point dim;
+
+ CAuto::EventProcess(event);
+
+ if ( m_soundChannel != -1 )
+ {
+ if ( m_engine->RetPause() )
+ {
+ if ( !m_bSilent )
+ {
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.1f, SOPER_CONTINUE);
+ m_bSilent = true;
+ }
+ }
+ else
+ {
+ if ( m_bSilent )
+ {
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.5f, 0.1f, SOPER_CONTINUE);
+ m_bSilent = false;
+ }
+ }
+ }
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+
+ if ( m_type == OBJECT_TEEN36 ) // trunk?
+ {
+ vib.x = 0.0f;
+ vib.y = sinf(m_progress)*1.0f;
+ vib.z = 0.0f;
+ m_object->SetLinVibration(vib);
+
+ vib.x = 0.0f;
+ vib.y = 0.0f;
+ vib.z = sinf(m_progress*0.5f)*0.05f;
+ m_object->SetCirVibration(vib);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.15f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.y = m_water->RetLevel()+1.0f;
+ pos.x += (Math::Rand()-0.5f)*50.0f;
+ pos.z += (Math::Rand()-0.5f)*50.0f;
+ speed.y = 0.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ dim.x = 50.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFLIC, 3.0f, 0.0f, 0.0f);
+ }
+ }
+
+ if ( m_type == OBJECT_TEEN37 ) // boat?
+ {
+ vib.x = 0.0f;
+ vib.y = sinf(m_progress)*1.0f;
+ vib.z = 0.0f;
+ m_object->SetLinVibration(vib);
+
+ vib.x = 0.0f;
+ vib.y = 0.0f;
+ vib.z = sinf(m_progress*0.5f)*0.15f;
+ m_object->SetCirVibration(vib);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.15f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.y = m_water->RetLevel()+1.0f;
+ pos.x += (Math::Rand()-0.5f)*20.0f;
+ pos.z += (Math::Rand()-0.5f)*20.0f;
+ speed.y = 0.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ dim.x = 20.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFLIC, 3.0f, 0.0f, 0.0f);
+ }
+ }
+
+ if ( m_type == OBJECT_TEEN38 ) // fan?
+ {
+ m_object->SetAngleY(1, sinf(m_progress*0.6f)*0.4f);
+ m_object->SetAngleX(2, m_progress*5.0f);
+ }
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoKid::RetError()
+{
+ return ERR_OK;
+}
+
+
diff --git a/src/object/auto/autokid.h b/src/object/auto/autokid.h
index 900eb92..6d4258f 100644
--- a/src/object/auto/autokid.h
+++ b/src/object/auto/autokid.h
@@ -1,47 +1,47 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autokid.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-class CAutoKid : public CAuto
-{
-public:
- CAutoKid(CInstanceManager* iMan, CObject* object);
- ~CAutoKid();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
-protected:
-
-protected:
- float m_speed;
- float m_progress;
- float m_lastParticule;
- int m_soundChannel;
- bool m_bSilent;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autokid.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+class CAutoKid : public CAuto
+{
+public:
+ CAutoKid(CInstanceManager* iMan, CObject* object);
+ ~CAutoKid();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+protected:
+
+protected:
+ float m_speed;
+ float m_progress;
+ float m_lastParticule;
+ int m_soundChannel;
+ bool m_bSilent;
+};
+
diff --git a/src/object/auto/autolabo.cpp b/src/object/auto/autolabo.cpp
index b675581..4239f49 100644
--- a/src/object/auto/autolabo.cpp
+++ b/src/object/auto/autolabo.cpp
@@ -1,610 +1,610 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autolabo.h"
-
-#include "common/global.h"
-#include "common/misc.h"
-#include "math/geometry.h"
-#include "object/robotmain.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-
-
-
-const float LABO_DELAY = 20.0f; // duration of the analysis
-
-
-
-
-// Object's constructor.
-
-CAutoLabo::CAutoLabo(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- int i;
-
- for ( i=0 ; i<3 ; i++ )
- {
- m_partiRank[i] = -1;
- }
- m_partiSphere = -1;
-
- m_soundChannel = -1;
- Init();
-}
-
-// Object's destructor.
-
-CAutoLabo::~CAutoLabo()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoLabo::DeleteObject(bool bAll)
-{
- int i;
-
- for ( i=0 ; i<3 ; i++ )
- {
- if ( m_partiRank[i] != -1 )
- {
- m_particule->DeleteParticule(m_partiRank[i]);
- m_partiRank[i] = -1;
- }
- }
-
- if ( m_partiSphere != -1 )
- {
- m_particule->DeleteParticule(m_partiSphere);
- m_partiSphere = -1;
- }
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoLabo::Init()
-{
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastParticule = 0.0f;
-
- m_phase = ALAP_WAIT; // waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoLabo::EventProcess(const Event &event)
-{
- CObject* power;
- Math::Vector pos, goal, speed;
- Math::Point dim, rot;
- float angle;
- int i;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
-
- if ( event.event == EVENT_UPDINTERFACE )
- {
- if ( m_object->RetSelect() ) CreateInterface(true);
- }
-
- if ( m_object->RetSelect() && // center selected?
- (event.event == EVENT_OBJECT_RiPAW ||
- event.event == EVENT_OBJECT_RiGUN) )
- {
- if ( m_phase != ALAP_WAIT )
- {
- return false;
- }
-
- m_research = event.event;
-
- if ( TestResearch(m_research) )
- {
- m_displayText->DisplayError(ERR_LABO_ALREADY, m_object);
- return false;
- }
-
- power = m_object->RetPower();
- if ( power == 0 )
- {
- m_displayText->DisplayError(ERR_LABO_NULL, m_object);
- return false;
- }
- if ( power->RetType() != OBJECT_BULLET )
- {
- m_displayText->DisplayError(ERR_LABO_BAD, m_object);
- return false;
- }
-
- SetBusy(true);
- InitProgressTotal(1.0f+1.5f+1.5f+LABO_DELAY+1.5f+1.5f+1.0f);
- UpdateInterface();
-
- power->SetLock(true); // ball longer usable
-
- SoundManip(1.0f, 1.0f, 1.0f);
- m_phase = ALAP_OPEN1;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- return true;
- }
-
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
- }
- return true;
- }
-
- EventProgress(event.rTime);
-
- if ( m_phase == ALAP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- m_phase = ALAP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == ALAP_OPEN1 )
- {
- if ( m_progress < 1.0f )
- {
- angle = 80.0f-(35.0f*m_progress);
- m_object->SetAngleZ(3, angle*Math::PI/180.0f);
- m_object->SetAngleZ(4, angle*Math::PI/180.0f);
- m_object->SetAngleZ(5, angle*Math::PI/180.0f);
- }
- else
- {
- m_object->SetAngleZ(3, 45.0f*Math::PI/180.0f);
- m_object->SetAngleZ(4, 45.0f*Math::PI/180.0f);
- m_object->SetAngleZ(5, 45.0f*Math::PI/180.0f);
-
- SoundManip(1.5f, 1.0f, 0.7f);
- m_phase = ALAP_OPEN2;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
-
- if ( m_phase == ALAP_OPEN2 )
- {
- if ( m_progress < 1.0f )
- {
- pos.x = -9.0f;
- pos.y = 3.0f+m_progress*10.0f;
- pos.z = 0.0f;
- m_object->SetPosition(1, pos);
- }
- else
- {
- m_object->SetPosition(1, Math::Vector(-9.0f, 13.0f, 0.0f));
-
- SoundManip(1.5f, 1.0f, 0.5f);
- m_phase = ALAP_OPEN3;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
-
- if ( m_phase == ALAP_OPEN3 )
- {
- if ( m_progress < 1.0f )
- {
- angle = (1.0f-m_progress)*Math::PI/2.0f;
- m_object->SetAngleZ(1, angle);
- }
- else
- {
- m_object->SetAngleZ(1, 0.0f);
-
- goal = m_object->RetPosition(0);
- goal.y += 3.0f;
- pos = goal;
- pos.x -= 4.0f;
- pos.y += 4.0f;
- for ( i=0 ; i<3 ; i++ )
- {
- m_partiRank[i] = m_particule->CreateRay(pos, goal,
- PARTIRAY2,
- Math::Point(2.9f, 2.9f),
- LABO_DELAY);
- }
-
- m_soundChannel = m_sound->Play(SOUND_LABO, m_object->RetPosition(0), 0.0f, 0.25f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.60f, 2.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.00f, 8.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.60f, 8.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.25f, 2.0f, SOPER_STOP);
-
- pos = m_object->RetPosition(0);
- pos.y += 4.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 4.0f;
- dim.y = dim.x;
- m_partiSphere = m_particule->CreateParticule(pos, speed, dim, PARTISPHERE2, LABO_DELAY, 0.0f, 0.0f);
-
- m_phase = ALAP_ANALYSE;
- m_progress = 0.0f;
- m_speed = 1.0f/LABO_DELAY;
- }
- }
-
- if ( m_phase == ALAP_ANALYSE )
- {
- if ( m_progress < 1.0f )
- {
- power = m_object->RetPower();
- if ( power != 0 )
- {
- power->SetZoom(0, 1.0f-m_progress);
- }
-
- angle = m_object->RetAngleY(2);
- if ( m_progress < 0.5f )
- {
- angle -= event.rTime*m_progress*20.0f;
- }
- else
- {
- angle -= event.rTime*(20.0f-m_progress*20.0f);
- }
- m_object->SetAngleY(2, angle); // rotates the analyzer
-
- angle += m_object->RetAngleY(0);
- for ( i=0 ; i<3 ; i++ )
- {
- rot = Math::RotatePoint(-angle, -4.0f);
- pos = m_object->RetPosition(0);
- pos.x += rot.x;
- pos.z += rot.y;
- pos.y += 3.0f+4.0f;;
- m_particule->SetPosition(m_partiRank[i], pos); // adjusts ray
-
- angle += Math::PI*2.0f/3.0f;
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- if ( m_progress > 0.25f &&
- m_progress < 0.80f )
- {
- pos = m_object->RetPosition(0);
- pos.y += 3.0f;
- pos.x += (Math::Rand()-0.5f)*2.0f;
- pos.z += (Math::Rand()-0.5f)*2.0f;
- speed.y = Math::Rand()*5.0f+5.0f;
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- dim.x = Math::Rand()*0.4f*m_progress+1.0f;
- dim.y = dim.x;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK2,
- 2.0f+2.0f*m_progress, 10.0f, 1.5f, 1.4f);
- }
- }
- }
- else
- {
- SetResearch(m_research); // research done
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- m_object->SetPower(0);
- power->DeleteObject(); // destroys the ball
- delete power;
- }
-
- m_displayText->DisplayError(INFO_LABO, m_object);
-
- SoundManip(1.5f, 1.0f, 0.5f);
- m_phase = ALAP_CLOSE1;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
-
- if ( m_phase == ALAP_CLOSE1 )
- {
- if ( m_progress < 1.0f )
- {
- angle = m_progress*Math::PI/2.0f;
- m_object->SetAngleZ(1, angle);
- }
- else
- {
- m_object->SetAngleZ(1, Math::PI/2.0f);
-
- SoundManip(1.5f, 1.0f, 0.7f);
- m_phase = ALAP_CLOSE2;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
-
- if ( m_phase == ALAP_CLOSE2 )
- {
- if ( m_progress < 1.0f )
- {
- pos.x = -9.0f;
- pos.y = 3.0f+(1.0f-m_progress)*10.0f;;
- pos.z = 0.0f;
- m_object->SetPosition(1, pos);
- }
- else
- {
- m_object->SetPosition(1, Math::Vector(-9.0f, 3.0f, 0.0f));
-
- SoundManip(1.0f, 1.0f, 1.0f);
- m_phase = ALAP_CLOSE3;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ALAP_CLOSE3 )
- {
- if ( m_progress < 1.0f )
- {
- angle = 45.0f+(35.0f*m_progress);
- m_object->SetAngleZ(3, angle*Math::PI/180.0f);
- m_object->SetAngleZ(4, angle*Math::PI/180.0f);
- m_object->SetAngleZ(5, angle*Math::PI/180.0f);
- }
- else
- {
- m_object->SetAngleZ(3, 80.0f*Math::PI/180.0f);
- m_object->SetAngleZ(4, 80.0f*Math::PI/180.0f);
- m_object->SetAngleZ(5, 80.0f*Math::PI/180.0f);
-
- SetBusy(false);
- UpdateInterface();
-
- m_phase = ALAP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoLabo::RetError()
-{
- CObject* pObj;
- ObjectType type;
-
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- pObj = m_object->RetPower();
- if ( pObj == 0 ) return ERR_LABO_NULL;
- type = pObj->RetType();
- if ( type != OBJECT_BULLET ) return ERR_LABO_BAD;
-
- return ERR_OK;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoLabo::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, dim, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- dim.x = 33.0f/640.0f;
- dim.y = 33.0f/480.0f;
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*7.0f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 64+45, EVENT_OBJECT_RiPAW);
-
- pos.x = ox+sx*8.0f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 64+46, EVENT_OBJECT_RiGUN);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 111, EVENT_OBJECT_TYPE);
-
- UpdateInterface();
-
- return true;
-}
-
-// Updates the status of all interface buttons.
-
-void CAutoLabo::UpdateInterface()
-{
- CWindow* pw;
-
- if ( !m_object->RetSelect() ) return;
-
- CAuto::UpdateInterface();
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- DeadInterface(pw, EVENT_OBJECT_RiPAW, g_researchEnable&RESEARCH_iPAW);
- DeadInterface(pw, EVENT_OBJECT_RiGUN, g_researchEnable&RESEARCH_iGUN);
-
- OkayButton(pw, EVENT_OBJECT_RiPAW);
- OkayButton(pw, EVENT_OBJECT_RiGUN);
-
- VisibleInterface(pw, EVENT_OBJECT_RiPAW, !m_bBusy);
- VisibleInterface(pw, EVENT_OBJECT_RiGUN, !m_bBusy);
-}
-
-// Indicates the research conducted for a button.
-
-void CAutoLabo::OkayButton(CWindow *pw, EventMsg event)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_OKAY, TestResearch(event));
-}
-
-
-// Test whether a search has already been done.
-
-bool CAutoLabo::TestResearch(EventMsg event)
-{
- if ( event == EVENT_OBJECT_RiPAW ) return (g_researchDone & RESEARCH_iPAW);
- if ( event == EVENT_OBJECT_RiGUN ) return (g_researchDone & RESEARCH_iGUN);
-
- return false;
-}
-
-// Indicates a search as made.
-
-void CAutoLabo::SetResearch(EventMsg event)
-{
- Event newEvent;
-
- if ( event == EVENT_OBJECT_RiPAW ) g_researchDone |= RESEARCH_iPAW;
- if ( event == EVENT_OBJECT_RiGUN ) g_researchDone |= RESEARCH_iGUN;
-
- m_main->WriteFreeParam();
-
- m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
- m_event->AddEvent(newEvent);
- UpdateInterface();
-}
-
-// Plays the sound of the manipulator arm.
-
-void CAutoLabo::SoundManip(float time, float amplitude, float frequency)
-{
- int i;
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoLabo::Write(char *line)
-{
- Math::Vector pos;
- char name[100];
-
- if ( m_phase == ALAP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- sprintf(name, " aResearch=%d", m_research);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoLabo::Read(char *line)
-{
- Math::Vector pos;
-
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoLaboPhase)OpInt(line, "aPhase", ALAP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
- m_research = (EventMsg)OpInt(line, "aResearch", 0);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autolabo.h"
+
+#include "common/global.h"
+#include "common/misc.h"
+#include "math/geometry.h"
+#include "object/robotmain.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+
+
+
+const float LABO_DELAY = 20.0f; // duration of the analysis
+
+
+
+
+// Object's constructor.
+
+CAutoLabo::CAutoLabo(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ int i;
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ m_partiRank[i] = -1;
+ }
+ m_partiSphere = -1;
+
+ m_soundChannel = -1;
+ Init();
+}
+
+// Object's destructor.
+
+CAutoLabo::~CAutoLabo()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoLabo::DeleteObject(bool bAll)
+{
+ int i;
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ if ( m_partiRank[i] != -1 )
+ {
+ m_particule->DeleteParticule(m_partiRank[i]);
+ m_partiRank[i] = -1;
+ }
+ }
+
+ if ( m_partiSphere != -1 )
+ {
+ m_particule->DeleteParticule(m_partiSphere);
+ m_partiSphere = -1;
+ }
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoLabo::Init()
+{
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+
+ m_phase = ALAP_WAIT; // waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoLabo::EventProcess(const Event &event)
+{
+ CObject* power;
+ Math::Vector pos, goal, speed;
+ Math::Point dim, rot;
+ float angle;
+ int i;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+
+ if ( event.event == EVENT_UPDINTERFACE )
+ {
+ if ( m_object->RetSelect() ) CreateInterface(true);
+ }
+
+ if ( m_object->RetSelect() && // center selected?
+ (event.event == EVENT_OBJECT_RiPAW ||
+ event.event == EVENT_OBJECT_RiGUN) )
+ {
+ if ( m_phase != ALAP_WAIT )
+ {
+ return false;
+ }
+
+ m_research = event.event;
+
+ if ( TestResearch(m_research) )
+ {
+ m_displayText->DisplayError(ERR_LABO_ALREADY, m_object);
+ return false;
+ }
+
+ power = m_object->RetPower();
+ if ( power == 0 )
+ {
+ m_displayText->DisplayError(ERR_LABO_NULL, m_object);
+ return false;
+ }
+ if ( power->RetType() != OBJECT_BULLET )
+ {
+ m_displayText->DisplayError(ERR_LABO_BAD, m_object);
+ return false;
+ }
+
+ SetBusy(true);
+ InitProgressTotal(1.0f+1.5f+1.5f+LABO_DELAY+1.5f+1.5f+1.0f);
+ UpdateInterface();
+
+ power->SetLock(true); // ball longer usable
+
+ SoundManip(1.0f, 1.0f, 1.0f);
+ m_phase = ALAP_OPEN1;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ return true;
+ }
+
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+ }
+ return true;
+ }
+
+ EventProgress(event.rTime);
+
+ if ( m_phase == ALAP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_phase = ALAP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == ALAP_OPEN1 )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = 80.0f-(35.0f*m_progress);
+ m_object->SetAngleZ(3, angle*Math::PI/180.0f);
+ m_object->SetAngleZ(4, angle*Math::PI/180.0f);
+ m_object->SetAngleZ(5, angle*Math::PI/180.0f);
+ }
+ else
+ {
+ m_object->SetAngleZ(3, 45.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(4, 45.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(5, 45.0f*Math::PI/180.0f);
+
+ SoundManip(1.5f, 1.0f, 0.7f);
+ m_phase = ALAP_OPEN2;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+
+ if ( m_phase == ALAP_OPEN2 )
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos.x = -9.0f;
+ pos.y = 3.0f+m_progress*10.0f;
+ pos.z = 0.0f;
+ m_object->SetPosition(1, pos);
+ }
+ else
+ {
+ m_object->SetPosition(1, Math::Vector(-9.0f, 13.0f, 0.0f));
+
+ SoundManip(1.5f, 1.0f, 0.5f);
+ m_phase = ALAP_OPEN3;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+
+ if ( m_phase == ALAP_OPEN3 )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = (1.0f-m_progress)*Math::PI/2.0f;
+ m_object->SetAngleZ(1, angle);
+ }
+ else
+ {
+ m_object->SetAngleZ(1, 0.0f);
+
+ goal = m_object->RetPosition(0);
+ goal.y += 3.0f;
+ pos = goal;
+ pos.x -= 4.0f;
+ pos.y += 4.0f;
+ for ( i=0 ; i<3 ; i++ )
+ {
+ m_partiRank[i] = m_particule->CreateRay(pos, goal,
+ PARTIRAY2,
+ Math::Point(2.9f, 2.9f),
+ LABO_DELAY);
+ }
+
+ m_soundChannel = m_sound->Play(SOUND_LABO, m_object->RetPosition(0), 0.0f, 0.25f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.60f, 2.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.00f, 8.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 0.60f, 8.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.25f, 2.0f, SOPER_STOP);
+
+ pos = m_object->RetPosition(0);
+ pos.y += 4.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 4.0f;
+ dim.y = dim.x;
+ m_partiSphere = m_particule->CreateParticule(pos, speed, dim, PARTISPHERE2, LABO_DELAY, 0.0f, 0.0f);
+
+ m_phase = ALAP_ANALYSE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/LABO_DELAY;
+ }
+ }
+
+ if ( m_phase == ALAP_ANALYSE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ power->SetZoom(0, 1.0f-m_progress);
+ }
+
+ angle = m_object->RetAngleY(2);
+ if ( m_progress < 0.5f )
+ {
+ angle -= event.rTime*m_progress*20.0f;
+ }
+ else
+ {
+ angle -= event.rTime*(20.0f-m_progress*20.0f);
+ }
+ m_object->SetAngleY(2, angle); // rotates the analyzer
+
+ angle += m_object->RetAngleY(0);
+ for ( i=0 ; i<3 ; i++ )
+ {
+ rot = Math::RotatePoint(-angle, -4.0f);
+ pos = m_object->RetPosition(0);
+ pos.x += rot.x;
+ pos.z += rot.y;
+ pos.y += 3.0f+4.0f;;
+ m_particule->SetPosition(m_partiRank[i], pos); // adjusts ray
+
+ angle += Math::PI*2.0f/3.0f;
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ if ( m_progress > 0.25f &&
+ m_progress < 0.80f )
+ {
+ pos = m_object->RetPosition(0);
+ pos.y += 3.0f;
+ pos.x += (Math::Rand()-0.5f)*2.0f;
+ pos.z += (Math::Rand()-0.5f)*2.0f;
+ speed.y = Math::Rand()*5.0f+5.0f;
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ dim.x = Math::Rand()*0.4f*m_progress+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK2,
+ 2.0f+2.0f*m_progress, 10.0f, 1.5f, 1.4f);
+ }
+ }
+ }
+ else
+ {
+ SetResearch(m_research); // research done
+
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ m_object->SetPower(0);
+ power->DeleteObject(); // destroys the ball
+ delete power;
+ }
+
+ m_displayText->DisplayError(INFO_LABO, m_object);
+
+ SoundManip(1.5f, 1.0f, 0.5f);
+ m_phase = ALAP_CLOSE1;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+
+ if ( m_phase == ALAP_CLOSE1 )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = m_progress*Math::PI/2.0f;
+ m_object->SetAngleZ(1, angle);
+ }
+ else
+ {
+ m_object->SetAngleZ(1, Math::PI/2.0f);
+
+ SoundManip(1.5f, 1.0f, 0.7f);
+ m_phase = ALAP_CLOSE2;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+
+ if ( m_phase == ALAP_CLOSE2 )
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos.x = -9.0f;
+ pos.y = 3.0f+(1.0f-m_progress)*10.0f;;
+ pos.z = 0.0f;
+ m_object->SetPosition(1, pos);
+ }
+ else
+ {
+ m_object->SetPosition(1, Math::Vector(-9.0f, 3.0f, 0.0f));
+
+ SoundManip(1.0f, 1.0f, 1.0f);
+ m_phase = ALAP_CLOSE3;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ALAP_CLOSE3 )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = 45.0f+(35.0f*m_progress);
+ m_object->SetAngleZ(3, angle*Math::PI/180.0f);
+ m_object->SetAngleZ(4, angle*Math::PI/180.0f);
+ m_object->SetAngleZ(5, angle*Math::PI/180.0f);
+ }
+ else
+ {
+ m_object->SetAngleZ(3, 80.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(4, 80.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(5, 80.0f*Math::PI/180.0f);
+
+ SetBusy(false);
+ UpdateInterface();
+
+ m_phase = ALAP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoLabo::RetError()
+{
+ CObject* pObj;
+ ObjectType type;
+
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ pObj = m_object->RetPower();
+ if ( pObj == 0 ) return ERR_LABO_NULL;
+ type = pObj->RetType();
+ if ( type != OBJECT_BULLET ) return ERR_LABO_BAD;
+
+ return ERR_OK;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoLabo::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, dim, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ dim.x = 33.0f/640.0f;
+ dim.y = 33.0f/480.0f;
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*7.0f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 64+45, EVENT_OBJECT_RiPAW);
+
+ pos.x = ox+sx*8.0f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 64+46, EVENT_OBJECT_RiGUN);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 111, EVENT_OBJECT_TYPE);
+
+ UpdateInterface();
+
+ return true;
+}
+
+// Updates the status of all interface buttons.
+
+void CAutoLabo::UpdateInterface()
+{
+ CWindow* pw;
+
+ if ( !m_object->RetSelect() ) return;
+
+ CAuto::UpdateInterface();
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ DeadInterface(pw, EVENT_OBJECT_RiPAW, g_researchEnable&RESEARCH_iPAW);
+ DeadInterface(pw, EVENT_OBJECT_RiGUN, g_researchEnable&RESEARCH_iGUN);
+
+ OkayButton(pw, EVENT_OBJECT_RiPAW);
+ OkayButton(pw, EVENT_OBJECT_RiGUN);
+
+ VisibleInterface(pw, EVENT_OBJECT_RiPAW, !m_bBusy);
+ VisibleInterface(pw, EVENT_OBJECT_RiGUN, !m_bBusy);
+}
+
+// Indicates the research conducted for a button.
+
+void CAutoLabo::OkayButton(CWindow *pw, EventMsg event)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_OKAY, TestResearch(event));
+}
+
+
+// Test whether a search has already been done.
+
+bool CAutoLabo::TestResearch(EventMsg event)
+{
+ if ( event == EVENT_OBJECT_RiPAW ) return (g_researchDone & RESEARCH_iPAW);
+ if ( event == EVENT_OBJECT_RiGUN ) return (g_researchDone & RESEARCH_iGUN);
+
+ return false;
+}
+
+// Indicates a search as made.
+
+void CAutoLabo::SetResearch(EventMsg event)
+{
+ Event newEvent;
+
+ if ( event == EVENT_OBJECT_RiPAW ) g_researchDone |= RESEARCH_iPAW;
+ if ( event == EVENT_OBJECT_RiGUN ) g_researchDone |= RESEARCH_iGUN;
+
+ m_main->WriteFreeParam();
+
+ m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
+ m_event->AddEvent(newEvent);
+ UpdateInterface();
+}
+
+// Plays the sound of the manipulator arm.
+
+void CAutoLabo::SoundManip(float time, float amplitude, float frequency)
+{
+ int i;
+
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
+ m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoLabo::Write(char *line)
+{
+ Math::Vector pos;
+ char name[100];
+
+ if ( m_phase == ALAP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ sprintf(name, " aResearch=%d", m_research);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoLabo::Read(char *line)
+{
+ Math::Vector pos;
+
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoLaboPhase)OpInt(line, "aPhase", ALAP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+ m_research = (EventMsg)OpInt(line, "aResearch", 0);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autolabo.h b/src/object/auto/autolabo.h
index d94eb9e..244e633 100644
--- a/src/object/auto/autolabo.h
+++ b/src/object/auto/autolabo.h
@@ -1,75 +1,75 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autolabo.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoLaboPhase
-{
- ALAP_WAIT = 1,
- ALAP_OPEN1 = 2,
- ALAP_OPEN2 = 3,
- ALAP_OPEN3 = 4,
- ALAP_ANALYSE = 5,
- ALAP_CLOSE1 = 6,
- ALAP_CLOSE2 = 7,
- ALAP_CLOSE3 = 8,
-};
-
-
-
-class CAutoLabo : public CAuto
-{
-public:
- CAutoLabo(CInstanceManager* iMan, CObject* object);
- ~CAutoLabo();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- void UpdateInterface();
- void OkayButton(CWindow *pw, EventMsg event);
- bool TestResearch(EventMsg event);
- void SetResearch(EventMsg event);
- void SoundManip(float time, float amplitude, float frequency);
-
-protected:
- AutoLaboPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
- EventMsg m_research;
- int m_partiRank[3];
- int m_partiSphere;
- int m_soundChannel;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autolabo.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoLaboPhase
+{
+ ALAP_WAIT = 1,
+ ALAP_OPEN1 = 2,
+ ALAP_OPEN2 = 3,
+ ALAP_OPEN3 = 4,
+ ALAP_ANALYSE = 5,
+ ALAP_CLOSE1 = 6,
+ ALAP_CLOSE2 = 7,
+ ALAP_CLOSE3 = 8,
+};
+
+
+
+class CAutoLabo : public CAuto
+{
+public:
+ CAutoLabo(CInstanceManager* iMan, CObject* object);
+ ~CAutoLabo();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ void UpdateInterface();
+ void OkayButton(CWindow *pw, EventMsg event);
+ bool TestResearch(EventMsg event);
+ void SetResearch(EventMsg event);
+ void SoundManip(float time, float amplitude, float frequency);
+
+protected:
+ AutoLaboPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+ EventMsg m_research;
+ int m_partiRank[3];
+ int m_partiSphere;
+ int m_soundChannel;
+};
+
diff --git a/src/object/auto/automush.cpp b/src/object/auto/automush.cpp
index 366dbb5..c3eaaaf 100644
--- a/src/object/auto/automush.cpp
+++ b/src/object/auto/automush.cpp
@@ -1,344 +1,344 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/automush.h"
-
-#include "common/iman.h"
-#include "script/cmdtoken.h"
-
-
-
-
-// Object's constructor.
-
-CAutoMush::CAutoMush(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
-}
-
-// Object's destructor.
-
-CAutoMush::~CAutoMush()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoMush::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoMush::Init()
-{
- m_phase = AMP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/4.0f;
-
- m_time = 0.0f;
- m_lastParticule = 0.0f;
-}
-
-
-// Management of an event.
-
-bool CAutoMush::EventProcess(const Event &event)
-{
- Math::Vector pos, speed, dir;
- Math::Point dim;
- float factor, zoom, size, angle;
- int i, channel;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
-
- factor = 0.0f;
- size = 1.0f;
-
- if ( m_phase == AMP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- if ( !SearchTarget() )
- {
- m_phase = AMP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/(2.0f+Math::Rand()*2.0f);
- }
- else
- {
- m_phase = AMP_SNIF;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
- }
-
- if ( m_phase == AMP_SNIF )
- {
- if ( m_progress < 1.0f )
- {
- factor = m_progress;
- }
- else
- {
- m_phase = AMP_ZOOM;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == AMP_ZOOM )
- {
- if ( m_progress < 1.0f )
- {
- factor = 1.0f;
- size = 1.0f+m_progress*0.3f;
- }
- else
- {
- m_sound->Play(SOUND_MUSHROOM, m_object->RetPosition(0));
-
- m_phase = AMP_FIRE;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == AMP_FIRE )
- {
- if ( m_progress < 1.0f )
- {
- factor = 1.0f-m_progress;
- size = 1.0f+(1.0f-m_progress)*0.3f;
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- for ( i=0 ; i<10 ; i++ )
- {
- pos = m_object->RetPosition(0);
- pos.y += 5.0f;
- speed.x = (Math::Rand()-0.5f)*200.0f;
- speed.z = (Math::Rand()-0.5f)*200.0f;
- speed.y = -(20.0f+Math::Rand()*20.0f);
- dim.x = 1.0f;
- dim.y = dim.x;
- channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN2, 2.0f, 100.0f, 0.0f);
- m_particule->SetObjectFather(channel, m_object);
- }
- }
- }
- else
- {
- m_phase = AMP_SMOKE;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == AMP_SMOKE )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.y += 5.0f;
- speed.x = (Math::Rand()-0.5f)*4.0f;
- speed.z = (Math::Rand()-0.5f)*4.0f;
- speed.y = -(0.5f+Math::Rand()*0.5f);
- dim.x = Math::Rand()*2.5f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 0.0f);
- }
- }
- else
- {
- m_phase = AMP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/(2.0f+Math::Rand()*2.0f);
- }
- }
-
- if ( factor != 0.0f || size != 1.0f )
- {
- dir.x = sinf(m_time*Math::PI*4.0f);
- dir.z = cosf(m_time*Math::PI*4.0f);
-
- angle = sinf(m_time*10.0f)*factor*0.04f;
- m_object->SetAngleX(0, angle*dir.z);
- m_object->SetAngleZ(0, angle*dir.x);
-
- zoom = 1.0f+sinf(m_time*8.0f)*factor*0.06f;
- m_object->SetZoomX(0, zoom*size);
- zoom = 1.0f+sinf(m_time*5.0f)*factor*0.06f;
- m_object->SetZoomY(0, zoom*size);
- zoom = 1.0f+sinf(m_time*7.0f)*factor*0.06f;
- m_object->SetZoomZ(0, zoom*size);
- }
- else
- {
- m_object->SetAngleX(0, 0.0f);
- m_object->SetAngleZ(0, 0.0f);
- m_object->SetZoom(0, Math::Vector(1.0f, 1.0f, 1.0f));
- }
-
- return true;
-}
-
-
-// Seeking a nearby target.
-
-bool CAutoMush::SearchTarget()
-{
- CObject* pObj;
- Math::Vector iPos, oPos;
- ObjectType type;
- float dist;
- int i;
-
- iPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetLock() ) continue;
-
- type = pObj->RetType();
- 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_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr &&
- 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 &&
- type != OBJECT_HUMAN ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, iPos);
- if ( dist < 50.0f ) return true;
- }
-
- return false;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoMush::RetError()
-{
- return ERR_OK;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoMush::Write(char *line)
-{
- Math::Vector pos;
- char name[100];
-
- if ( m_phase == AMP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoMush::Read(char *line)
-{
- Math::Vector pos;
-
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoMushPhase)OpInt(line, "aPhase", AMP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/automush.h"
+
+#include "common/iman.h"
+#include "script/cmdtoken.h"
+
+
+
+
+// Object's constructor.
+
+CAutoMush::CAutoMush(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+}
+
+// Object's destructor.
+
+CAutoMush::~CAutoMush()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoMush::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoMush::Init()
+{
+ m_phase = AMP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/4.0f;
+
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+}
+
+
+// Management of an event.
+
+bool CAutoMush::EventProcess(const Event &event)
+{
+ Math::Vector pos, speed, dir;
+ Math::Point dim;
+ float factor, zoom, size, angle;
+ int i, channel;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+
+ factor = 0.0f;
+ size = 1.0f;
+
+ if ( m_phase == AMP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ if ( !SearchTarget() )
+ {
+ m_phase = AMP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/(2.0f+Math::Rand()*2.0f);
+ }
+ else
+ {
+ m_phase = AMP_SNIF;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+ }
+
+ if ( m_phase == AMP_SNIF )
+ {
+ if ( m_progress < 1.0f )
+ {
+ factor = m_progress;
+ }
+ else
+ {
+ m_phase = AMP_ZOOM;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == AMP_ZOOM )
+ {
+ if ( m_progress < 1.0f )
+ {
+ factor = 1.0f;
+ size = 1.0f+m_progress*0.3f;
+ }
+ else
+ {
+ m_sound->Play(SOUND_MUSHROOM, m_object->RetPosition(0));
+
+ m_phase = AMP_FIRE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == AMP_FIRE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ factor = 1.0f-m_progress;
+ size = 1.0f+(1.0f-m_progress)*0.3f;
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ pos = m_object->RetPosition(0);
+ pos.y += 5.0f;
+ speed.x = (Math::Rand()-0.5f)*200.0f;
+ speed.z = (Math::Rand()-0.5f)*200.0f;
+ speed.y = -(20.0f+Math::Rand()*20.0f);
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN2, 2.0f, 100.0f, 0.0f);
+ m_particule->SetObjectFather(channel, m_object);
+ }
+ }
+ }
+ else
+ {
+ m_phase = AMP_SMOKE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == AMP_SMOKE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.y += 5.0f;
+ speed.x = (Math::Rand()-0.5f)*4.0f;
+ speed.z = (Math::Rand()-0.5f)*4.0f;
+ speed.y = -(0.5f+Math::Rand()*0.5f);
+ dim.x = Math::Rand()*2.5f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 0.0f);
+ }
+ }
+ else
+ {
+ m_phase = AMP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/(2.0f+Math::Rand()*2.0f);
+ }
+ }
+
+ if ( factor != 0.0f || size != 1.0f )
+ {
+ dir.x = sinf(m_time*Math::PI*4.0f);
+ dir.z = cosf(m_time*Math::PI*4.0f);
+
+ angle = sinf(m_time*10.0f)*factor*0.04f;
+ m_object->SetAngleX(0, angle*dir.z);
+ m_object->SetAngleZ(0, angle*dir.x);
+
+ zoom = 1.0f+sinf(m_time*8.0f)*factor*0.06f;
+ m_object->SetZoomX(0, zoom*size);
+ zoom = 1.0f+sinf(m_time*5.0f)*factor*0.06f;
+ m_object->SetZoomY(0, zoom*size);
+ zoom = 1.0f+sinf(m_time*7.0f)*factor*0.06f;
+ m_object->SetZoomZ(0, zoom*size);
+ }
+ else
+ {
+ m_object->SetAngleX(0, 0.0f);
+ m_object->SetAngleZ(0, 0.0f);
+ m_object->SetZoom(0, Math::Vector(1.0f, 1.0f, 1.0f));
+ }
+
+ return true;
+}
+
+
+// Seeking a nearby target.
+
+bool CAutoMush::SearchTarget()
+{
+ CObject* pObj;
+ Math::Vector iPos, oPos;
+ ObjectType type;
+ float dist;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetLock() ) continue;
+
+ type = pObj->RetType();
+ 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_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_MOBILEdr &&
+ 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 &&
+ type != OBJECT_HUMAN ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, iPos);
+ if ( dist < 50.0f ) return true;
+ }
+
+ return false;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoMush::RetError()
+{
+ return ERR_OK;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoMush::Write(char *line)
+{
+ Math::Vector pos;
+ char name[100];
+
+ if ( m_phase == AMP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoMush::Read(char *line)
+{
+ Math::Vector pos;
+
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoMushPhase)OpInt(line, "aPhase", AMP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/automush.h b/src/object/auto/automush.h
index 5c8d62d..113d22f 100644
--- a/src/object/auto/automush.h
+++ b/src/object/auto/automush.h
@@ -1,61 +1,61 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// automush.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoMushPhase
-{
- AMP_WAIT = 1,
- AMP_SNIF = 2,
- AMP_ZOOM = 3,
- AMP_FIRE = 4,
- AMP_SMOKE = 5,
-};
-
-
-
-class CAutoMush : public CAuto
-{
-public:
- CAutoMush(CInstanceManager* iMan, CObject* object);
- ~CAutoMush();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- bool SearchTarget();
-
-protected:
- AutoMushPhase m_phase;
- float m_progress;
- float m_speed;
- float m_lastParticule;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// automush.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoMushPhase
+{
+ AMP_WAIT = 1,
+ AMP_SNIF = 2,
+ AMP_ZOOM = 3,
+ AMP_FIRE = 4,
+ AMP_SMOKE = 5,
+};
+
+
+
+class CAutoMush : public CAuto
+{
+public:
+ CAutoMush(CInstanceManager* iMan, CObject* object);
+ ~CAutoMush();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ bool SearchTarget();
+
+protected:
+ AutoMushPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_lastParticule;
+};
+
diff --git a/src/object/auto/autonest.cpp b/src/object/auto/autonest.cpp
index a1fdf67..f3c70fb 100644
--- a/src/object/auto/autonest.cpp
+++ b/src/object/auto/autonest.cpp
@@ -1,275 +1,275 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autonest.h"
-
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "script/cmdtoken.h"
-
-
-
-
-// Object's constructor.
-
-CAutoNest::CAutoNest(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
-}
-
-// Object's destructor.
-
-CAutoNest::~CAutoNest()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoNest::DeleteObject(bool bAll)
-{
- CObject* fret;
-
- if ( !bAll )
- {
- fret = SearchFret();
- if ( fret != 0 )
- {
- fret->DeleteObject();
- delete fret;
- }
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoNest::Init()
-{
- Math::Vector pos;
-
- m_phase = ANP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/4.0f;
-
- m_time = 0.0f;
- m_lastParticule = 0.0f;
-
- pos = m_object->RetPosition(0);
- m_terrain->MoveOnFloor(pos);
- m_fretPos = pos;
-}
-
-
-// Management of an event.
-
-bool CAutoNest::EventProcess(const Event &event)
-{
- CObject* fret;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
-
- if ( m_phase == ANP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- if ( !SearchFree(m_fretPos) )
- {
- m_phase = ANP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/4.0f;
- }
- else
- {
- CreateFret(m_fretPos, 0.0f, OBJECT_BULLET);
- m_phase = ANP_BIRTH;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- }
- }
- }
-
- if ( m_phase == ANP_BIRTH )
- {
- fret = SearchFret();
-
- if ( m_progress < 1.0f )
- {
- if ( fret != 0 )
- {
- fret->SetZoom(0, m_progress);
- }
- }
- else
- {
- if ( fret != 0 )
- {
- fret->SetZoom(0, 1.0f);
- fret->SetLock(false);
- }
-
- m_phase = ANP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/5.0f;
- }
- }
-
- return true;
-}
-
-
-// Seeks if a site is free.
-
-bool CAutoNest::SearchFree(Math::Vector pos)
-{
- CObject* pObj;
- Math::Vector sPos;
- ObjectType type;
- float sRadius, distance;
- int i, j;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_NEST ) continue;
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, sPos, sRadius) )
- {
- distance = Math::Distance(sPos, pos);
- distance -= sRadius;
- if ( distance < 2.0f ) return false; // location occupied
- }
- }
-
- return true; // free location
-}
-
-// Create a transportable object.
-
-void CAutoNest::CreateFret(Math::Vector pos, float angle, ObjectType type)
-{
- CObject* fret;
-
- fret = new CObject(m_iMan);
- if ( !fret->CreateResource(pos, angle, type) )
- {
- delete fret;
- return;
- }
- fret->SetLock(true); // not usable
- fret->SetZoom(0, 0.0f);
-}
-
-// Looking for the ball during manufacture.
-
-CObject* CAutoNest::SearchFret()
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetLock() ) continue;
-
- type = pObj->RetType();
- if ( type != OBJECT_BULLET ) continue;
-
- oPos = pObj->RetPosition(0);
- if ( oPos.x == m_fretPos.x &&
- oPos.z == m_fretPos.z )
- {
- return pObj;
- }
- }
-
- return 0;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoNest::RetError()
-{
- return ERR_OK;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoNest::Write(char *line)
-{
- Math::Vector pos;
- char name[100];
-
- if ( m_phase == ANP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoNest::Read(char *line)
-{
- Math::Vector pos;
-
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoNestPhase)OpInt(line, "aPhase", ANP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autonest.h"
+
+#include "common/iman.h"
+#include "old/terrain.h"
+#include "script/cmdtoken.h"
+
+
+
+
+// Object's constructor.
+
+CAutoNest::CAutoNest(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+}
+
+// Object's destructor.
+
+CAutoNest::~CAutoNest()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoNest::DeleteObject(bool bAll)
+{
+ CObject* fret;
+
+ if ( !bAll )
+ {
+ fret = SearchFret();
+ if ( fret != 0 )
+ {
+ fret->DeleteObject();
+ delete fret;
+ }
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoNest::Init()
+{
+ Math::Vector pos;
+
+ m_phase = ANP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/4.0f;
+
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+
+ pos = m_object->RetPosition(0);
+ m_terrain->MoveOnFloor(pos);
+ m_fretPos = pos;
+}
+
+
+// Management of an event.
+
+bool CAutoNest::EventProcess(const Event &event)
+{
+ CObject* fret;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+
+ if ( m_phase == ANP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ if ( !SearchFree(m_fretPos) )
+ {
+ m_phase = ANP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/4.0f;
+ }
+ else
+ {
+ CreateFret(m_fretPos, 0.0f, OBJECT_BULLET);
+ m_phase = ANP_BIRTH;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ }
+ }
+ }
+
+ if ( m_phase == ANP_BIRTH )
+ {
+ fret = SearchFret();
+
+ if ( m_progress < 1.0f )
+ {
+ if ( fret != 0 )
+ {
+ fret->SetZoom(0, m_progress);
+ }
+ }
+ else
+ {
+ if ( fret != 0 )
+ {
+ fret->SetZoom(0, 1.0f);
+ fret->SetLock(false);
+ }
+
+ m_phase = ANP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/5.0f;
+ }
+ }
+
+ return true;
+}
+
+
+// Seeks if a site is free.
+
+bool CAutoNest::SearchFree(Math::Vector pos)
+{
+ CObject* pObj;
+ Math::Vector sPos;
+ ObjectType type;
+ float sRadius, distance;
+ int i, j;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_NEST ) continue;
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, sPos, sRadius) )
+ {
+ distance = Math::Distance(sPos, pos);
+ distance -= sRadius;
+ if ( distance < 2.0f ) return false; // location occupied
+ }
+ }
+
+ return true; // free location
+}
+
+// Create a transportable object.
+
+void CAutoNest::CreateFret(Math::Vector pos, float angle, ObjectType type)
+{
+ CObject* fret;
+
+ fret = new CObject(m_iMan);
+ if ( !fret->CreateResource(pos, angle, type) )
+ {
+ delete fret;
+ return;
+ }
+ fret->SetLock(true); // not usable
+ fret->SetZoom(0, 0.0f);
+}
+
+// Looking for the ball during manufacture.
+
+CObject* CAutoNest::SearchFret()
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ ObjectType type;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetLock() ) continue;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_BULLET ) continue;
+
+ oPos = pObj->RetPosition(0);
+ if ( oPos.x == m_fretPos.x &&
+ oPos.z == m_fretPos.z )
+ {
+ return pObj;
+ }
+ }
+
+ return 0;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoNest::RetError()
+{
+ return ERR_OK;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoNest::Write(char *line)
+{
+ Math::Vector pos;
+ char name[100];
+
+ if ( m_phase == ANP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoNest::Read(char *line)
+{
+ Math::Vector pos;
+
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoNestPhase)OpInt(line, "aPhase", ANP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autonest.h b/src/object/auto/autonest.h
index e697a3b..612551d 100644
--- a/src/object/auto/autonest.h
+++ b/src/object/auto/autonest.h
@@ -1,61 +1,61 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autonest.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoNestPhase
-{
- ANP_WAIT = 1,
- ANP_BIRTH = 2, // appearance of a ball
-};
-
-
-
-class CAutoNest : public CAuto
-{
-public:
- CAutoNest(CInstanceManager* iMan, CObject* object);
- ~CAutoNest();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- bool SearchFree(Math::Vector pos);
- void CreateFret(Math::Vector pos, float angle, ObjectType type);
- CObject* SearchFret();
-
-protected:
- AutoNestPhase m_phase;
- float m_progress;
- float m_speed;
- float m_lastParticule;
- Math::Vector m_fretPos;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autonest.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoNestPhase
+{
+ ANP_WAIT = 1,
+ ANP_BIRTH = 2, // appearance of a ball
+};
+
+
+
+class CAutoNest : public CAuto
+{
+public:
+ CAutoNest(CInstanceManager* iMan, CObject* object);
+ ~CAutoNest();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ bool SearchFree(Math::Vector pos);
+ void CreateFret(Math::Vector pos, float angle, ObjectType type);
+ CObject* SearchFret();
+
+protected:
+ AutoNestPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_lastParticule;
+ Math::Vector m_fretPos;
+};
+
diff --git a/src/object/auto/autonuclear.cpp b/src/object/auto/autonuclear.cpp
index 435bfc6..05f0b29 100644
--- a/src/object/auto/autonuclear.cpp
+++ b/src/object/auto/autonuclear.cpp
@@ -1,484 +1,484 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autonuclear.h"
-
-#include "common/iman.h"
-#include "math/geometry.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-
-
-
-const float NUCLEAR_DELAY = 30.0f; // duration of the generation
-
-
-
-
-// Object's constructor.
-
-CAutoNuclear::CAutoNuclear(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- m_channelSound = -1;
- Init();
-}
-
-// Object's destructor.
-
-CAutoNuclear::~CAutoNuclear()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoNuclear::DeleteObject(bool bAll)
-{
- CObject* fret;
-
- if ( !bAll )
- {
- fret = SearchUranium();
- if ( fret != 0 )
- {
- fret->DeleteObject(); // destroys the metal
- delete fret;
- }
- }
-
- if ( m_channelSound != -1 )
- {
- m_sound->FlushEnvelope(m_channelSound);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_channelSound = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoNuclear::Init()
-{
- Math::Matrix* mat;
-
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastParticule = 0.0f;
-
- mat = m_object->RetWorldMatrix(0);
- m_pos = Math::Transform(*mat, Math::Vector(22.0f, 4.0f, 0.0f));
-
- m_phase = ANUP_WAIT; // waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoNuclear::EventProcess(const Event &event)
-{
- CObject* fret;
- Math::Matrix* mat;
- Math::Vector pos, goal, speed;
- Math::Point dim, rot;
- float angle;
- int i, max;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
- }
- return true;
- }
-
- EventProgress(event.rTime);
-
- if ( m_phase == ANUP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- fret = SearchUranium(); // transform uranium?
- if ( fret == 0 || SearchVehicle() )
- {
- m_phase = ANUP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- else
- {
- fret->SetLock(true); // usable uranium
-
- SetBusy(true);
- InitProgressTotal(1.5f+NUCLEAR_DELAY+1.5f);
- UpdateInterface();
-
- m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.4f);
-
- m_phase = ANUP_CLOSE;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
- }
-
- if ( m_phase == ANUP_CLOSE )
- {
- if ( m_progress < 1.0f )
- {
- angle = (1.0f-m_progress)*(135.0f*Math::PI/180.0f);
- m_object->SetAngleZ(1, angle);
- }
- else
- {
- m_object->SetAngleZ(1, 0.0f);
-
- mat = m_object->RetWorldMatrix(0);
- max = (int)(10.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<max ; i++ )
- {
- pos.x = 27.0f;
- pos.y = 0.0f;
- pos.z = (Math::Rand()-0.5f)*8.0f;
- pos = Transform(*mat, pos);
- speed.y = 0.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH);
- }
-
- m_sound->Play(SOUND_CLOSE, m_object->RetPosition(0), 1.0f, 1.0f);
-
- m_channelSound = m_sound->Play(SOUND_NUCLEAR, m_object->RetPosition(0), 1.0f, 0.1f, true);
- m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, NUCLEAR_DELAY-1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP);
-
- m_phase = ANUP_GENERATE;
- m_progress = 0.0f;
- m_speed = 1.0f/NUCLEAR_DELAY;
- }
- }
-
- if ( m_phase == ANUP_GENERATE )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.y += 30.0f;
- pos.x += (Math::Rand()-0.5f)*6.0f;
- pos.z += (Math::Rand()-0.5f)*6.0f;
- speed.y = Math::Rand()*15.0f+15.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- dim.x = Math::Rand()*8.0f+8.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH);
-
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.y = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- dim.x = 2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 1.0f, 0.0f, 0.0f);
- }
- }
- else
- {
- fret = SearchUranium();
- if ( fret != 0 )
- {
- fret->DeleteObject(); // destroyed uranium
- delete fret;
- m_object->SetPower(0);
- }
-
- CreatePower(); // creates the atomic cell
-
- max = (int)(20.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<max ; i++ )
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*3.0f;
- pos.y += (Math::Rand()-0.5f)*3.0f;
- pos.z += (Math::Rand()-0.5f)*3.0f;
- speed.y = 0.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, Math::Rand()*5.0f+5.0f, 0.0f, 0.0f);
- }
-
- m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.4f);
-
- m_phase = ANUP_OPEN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
-
- if ( m_phase == ANUP_OPEN )
- {
- if ( m_progress < 1.0f )
- {
- angle = m_progress*(135.0f*Math::PI/180.0f);
- m_object->SetAngleZ(1, angle);
- }
- else
- {
- m_object->SetAngleZ(1, 135.0f*Math::PI/180.0f);
-
- SetBusy(false);
- UpdateInterface();
-
- m_displayText->DisplayError(INFO_NUCLEAR, m_object);
-
- m_phase = ANUP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- return true;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoNuclear::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 110, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-
-// Seeking the uranium.
-
-CObject* CAutoNuclear::SearchUranium()
-{
- CObject* pObj;
-
- pObj = m_object->RetPower();
- if ( pObj == 0 ) return 0;
- if ( pObj->RetType() == OBJECT_URANIUM ) return pObj;
- return 0;
-}
-
-// Seeks if a vehicle is too close.
-
-bool CAutoNuclear::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- float oRadius, dist;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr &&
- type != OBJECT_MOTHER &&
- type != OBJECT_ANT &&
- type != OBJECT_SPIDER &&
- type != OBJECT_BEE &&
- type != OBJECT_WORM ) continue;
-
- if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
- dist = Math::Distance(oPos, m_pos)-oRadius;
-
- if ( dist < 10.0f ) return true;
- }
-
- return false;
-}
-
-// Creates an object stack.
-
-void CAutoNuclear::CreatePower()
-{
- CObject* power;
- Math::Vector pos;
- float angle;
-
- pos = m_object->RetPosition(0);
- angle = m_object->RetAngleY(0);
-
- power = new CObject(m_iMan);
- if ( !power->CreateResource(pos, angle, OBJECT_ATOMIC) )
- {
- delete power;
- m_displayText->DisplayError(ERR_TOOMANY, m_object);
- return;
- }
-
- power->SetTruck(m_object);
- power->SetPosition(0, Math::Vector(22.0f, 3.0f, 0.0f));
- m_object->SetPower(power);
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoNuclear::RetError()
-{
- CObject* pObj;
- ObjectType type;
-//? TerrainRes res;
-
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
-//? res = m_terrain->RetResource(m_object->RetPosition(0));
-//? if ( res != TR_POWER ) return ERR_NUCLEAR_NULL;
-
-//? if ( m_object->RetEnergy() < ENERGY_POWER ) return ERR_NUCLEAR_LOW;
-
- pObj = m_object->RetPower();
- if ( pObj == 0 ) return ERR_NUCLEAR_EMPTY;
- if ( pObj->RetLock() ) return ERR_OK;
- type = pObj->RetType();
- if ( type == OBJECT_ATOMIC ) return ERR_OK;
- if ( type != OBJECT_URANIUM ) return ERR_NUCLEAR_BAD;
-
- return ERR_OK;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoNuclear::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == ANUP_STOP ||
- m_phase == ANUP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoNuclear::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoNuclearPhase)OpInt(line, "aPhase", ANUP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autonuclear.h"
+
+#include "common/iman.h"
+#include "math/geometry.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+
+
+
+const float NUCLEAR_DELAY = 30.0f; // duration of the generation
+
+
+
+
+// Object's constructor.
+
+CAutoNuclear::CAutoNuclear(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ m_channelSound = -1;
+ Init();
+}
+
+// Object's destructor.
+
+CAutoNuclear::~CAutoNuclear()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoNuclear::DeleteObject(bool bAll)
+{
+ CObject* fret;
+
+ if ( !bAll )
+ {
+ fret = SearchUranium();
+ if ( fret != 0 )
+ {
+ fret->DeleteObject(); // destroys the metal
+ delete fret;
+ }
+ }
+
+ if ( m_channelSound != -1 )
+ {
+ m_sound->FlushEnvelope(m_channelSound);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_channelSound = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoNuclear::Init()
+{
+ Math::Matrix* mat;
+
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+
+ mat = m_object->RetWorldMatrix(0);
+ m_pos = Math::Transform(*mat, Math::Vector(22.0f, 4.0f, 0.0f));
+
+ m_phase = ANUP_WAIT; // waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoNuclear::EventProcess(const Event &event)
+{
+ CObject* fret;
+ Math::Matrix* mat;
+ Math::Vector pos, goal, speed;
+ Math::Point dim, rot;
+ float angle;
+ int i, max;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+ }
+ return true;
+ }
+
+ EventProgress(event.rTime);
+
+ if ( m_phase == ANUP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ fret = SearchUranium(); // transform uranium?
+ if ( fret == 0 || SearchVehicle() )
+ {
+ m_phase = ANUP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ else
+ {
+ fret->SetLock(true); // usable uranium
+
+ SetBusy(true);
+ InitProgressTotal(1.5f+NUCLEAR_DELAY+1.5f);
+ UpdateInterface();
+
+ m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.4f);
+
+ m_phase = ANUP_CLOSE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+ }
+
+ if ( m_phase == ANUP_CLOSE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = (1.0f-m_progress)*(135.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(1, angle);
+ }
+ else
+ {
+ m_object->SetAngleZ(1, 0.0f);
+
+ mat = m_object->RetWorldMatrix(0);
+ max = (int)(10.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<max ; i++ )
+ {
+ pos.x = 27.0f;
+ pos.y = 0.0f;
+ pos.z = (Math::Rand()-0.5f)*8.0f;
+ pos = Transform(*mat, pos);
+ speed.y = 0.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH);
+ }
+
+ m_sound->Play(SOUND_CLOSE, m_object->RetPosition(0), 1.0f, 1.0f);
+
+ m_channelSound = m_sound->Play(SOUND_NUCLEAR, m_object->RetPosition(0), 1.0f, 0.1f, true);
+ m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, NUCLEAR_DELAY-1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP);
+
+ m_phase = ANUP_GENERATE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/NUCLEAR_DELAY;
+ }
+ }
+
+ if ( m_phase == ANUP_GENERATE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.y += 30.0f;
+ pos.x += (Math::Rand()-0.5f)*6.0f;
+ pos.z += (Math::Rand()-0.5f)*6.0f;
+ speed.y = Math::Rand()*15.0f+15.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ dim.x = Math::Rand()*8.0f+8.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH);
+
+ pos = m_pos;
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.y = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ dim.x = 2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 1.0f, 0.0f, 0.0f);
+ }
+ }
+ else
+ {
+ fret = SearchUranium();
+ if ( fret != 0 )
+ {
+ fret->DeleteObject(); // destroyed uranium
+ delete fret;
+ m_object->SetPower(0);
+ }
+
+ CreatePower(); // creates the atomic cell
+
+ max = (int)(20.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<max ; i++ )
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*3.0f;
+ pos.y += (Math::Rand()-0.5f)*3.0f;
+ pos.z += (Math::Rand()-0.5f)*3.0f;
+ speed.y = 0.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ dim.x = Math::Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, Math::Rand()*5.0f+5.0f, 0.0f, 0.0f);
+ }
+
+ m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 1.4f);
+
+ m_phase = ANUP_OPEN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+
+ if ( m_phase == ANUP_OPEN )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = m_progress*(135.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(1, angle);
+ }
+ else
+ {
+ m_object->SetAngleZ(1, 135.0f*Math::PI/180.0f);
+
+ SetBusy(false);
+ UpdateInterface();
+
+ m_displayText->DisplayError(INFO_NUCLEAR, m_object);
+
+ m_phase = ANUP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ return true;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoNuclear::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 110, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+
+// Seeking the uranium.
+
+CObject* CAutoNuclear::SearchUranium()
+{
+ CObject* pObj;
+
+ pObj = m_object->RetPower();
+ if ( pObj == 0 ) return 0;
+ if ( pObj->RetType() == OBJECT_URANIUM ) return pObj;
+ return 0;
+}
+
+// Seeks if a vehicle is too close.
+
+bool CAutoNuclear::SearchVehicle()
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ ObjectType type;
+ float oRadius, dist;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_HUMAN &&
+ type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis &&
+ type != OBJECT_MOBILErt &&
+ type != OBJECT_MOBILErc &&
+ type != OBJECT_MOBILErr &&
+ type != OBJECT_MOBILErs &&
+ type != OBJECT_MOBILEsa &&
+ type != OBJECT_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_MOBILEdr &&
+ type != OBJECT_MOTHER &&
+ type != OBJECT_ANT &&
+ type != OBJECT_SPIDER &&
+ type != OBJECT_BEE &&
+ type != OBJECT_WORM ) continue;
+
+ if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
+ dist = Math::Distance(oPos, m_pos)-oRadius;
+
+ if ( dist < 10.0f ) return true;
+ }
+
+ return false;
+}
+
+// Creates an object stack.
+
+void CAutoNuclear::CreatePower()
+{
+ CObject* power;
+ Math::Vector pos;
+ float angle;
+
+ pos = m_object->RetPosition(0);
+ angle = m_object->RetAngleY(0);
+
+ power = new CObject(m_iMan);
+ if ( !power->CreateResource(pos, angle, OBJECT_ATOMIC) )
+ {
+ delete power;
+ m_displayText->DisplayError(ERR_TOOMANY, m_object);
+ return;
+ }
+
+ power->SetTruck(m_object);
+ power->SetPosition(0, Math::Vector(22.0f, 3.0f, 0.0f));
+ m_object->SetPower(power);
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoNuclear::RetError()
+{
+ CObject* pObj;
+ ObjectType type;
+//? TerrainRes res;
+
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+//? res = m_terrain->RetResource(m_object->RetPosition(0));
+//? if ( res != TR_POWER ) return ERR_NUCLEAR_NULL;
+
+//? if ( m_object->RetEnergy() < ENERGY_POWER ) return ERR_NUCLEAR_LOW;
+
+ pObj = m_object->RetPower();
+ if ( pObj == 0 ) return ERR_NUCLEAR_EMPTY;
+ if ( pObj->RetLock() ) return ERR_OK;
+ type = pObj->RetType();
+ if ( type == OBJECT_ATOMIC ) return ERR_OK;
+ if ( type != OBJECT_URANIUM ) return ERR_NUCLEAR_BAD;
+
+ return ERR_OK;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoNuclear::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == ANUP_STOP ||
+ m_phase == ANUP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoNuclear::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoNuclearPhase)OpInt(line, "aPhase", ANUP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autonuclear.h b/src/object/auto/autonuclear.h
index 3054887..8a4b0da 100644
--- a/src/object/auto/autonuclear.h
+++ b/src/object/auto/autonuclear.h
@@ -1,68 +1,68 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autonuclear.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoNuclearPhase
-{
- ANUP_STOP = 1,
- ANUP_WAIT = 2,
- ANUP_CLOSE = 3,
- ANUP_GENERATE = 4,
- ANUP_OPEN = 5,
-};
-
-
-
-class CAutoNuclear : public CAuto
-{
-public:
- CAutoNuclear(CInstanceManager* iMan, CObject* object);
- ~CAutoNuclear();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- CObject* SearchUranium();
- bool SearchVehicle();
- void CreatePower();
-
-protected:
- AutoNuclearPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
- Math::Vector m_pos;
- int m_channelSound;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autonuclear.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoNuclearPhase
+{
+ ANUP_STOP = 1,
+ ANUP_WAIT = 2,
+ ANUP_CLOSE = 3,
+ ANUP_GENERATE = 4,
+ ANUP_OPEN = 5,
+};
+
+
+
+class CAutoNuclear : public CAuto
+{
+public:
+ CAutoNuclear(CInstanceManager* iMan, CObject* object);
+ ~CAutoNuclear();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ CObject* SearchUranium();
+ bool SearchVehicle();
+ void CreatePower();
+
+protected:
+ AutoNuclearPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+ Math::Vector m_pos;
+ int m_channelSound;
+};
+
diff --git a/src/object/auto/autopara.cpp b/src/object/auto/autopara.cpp
index 31e214d..80ce90a 100644
--- a/src/object/auto/autopara.cpp
+++ b/src/object/auto/autopara.cpp
@@ -1,327 +1,327 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autopara.h"
-
-
-#include "common/iman.h"
-#include "math/geometry.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-
-
-
-
-// Object's constructor.
-
-CAutoPara::CAutoPara(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- m_channelSound = -1;
- Init();
-}
-
-// Object's destructor.
-
-CAutoPara::~CAutoPara()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoPara::DeleteObject(bool bAll)
-{
- if ( m_channelSound != -1 )
- {
- m_sound->FlushEnvelope(m_channelSound);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_channelSound = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoPara::Init()
-{
- Math::Matrix* mat;
-
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastParticule = 0.0f;
-
- mat = m_object->RetWorldMatrix(0);
- m_pos = Math::Transform(*mat, Math::Vector(22.0f, 4.0f, 0.0f));
-
- m_phase = APAP_WAIT; // waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- CAuto::Init();
-}
-
-
-// Reception of lightning.
-
-void CAutoPara::StartBlitz()
-{
- m_phase = APAP_BLITZ;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-}
-
-
-// Management of an event.
-
-bool CAutoPara::EventProcess(const Event &event)
-{
- Math::Vector pos, speed;
- Math::Point dim;
- int i;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
- }
- return true;
- }
-
- EventProgress(event.rTime);
-
- if ( m_phase == APAP_BLITZ )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- for ( i=0 ; i<10 ; i++ )
- {
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*m_progress*40.0f;
- pos.z += (Math::Rand()-0.5f)*m_progress*40.0f;
- pos.y += 50.0f-m_progress*50.0f;
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = 5.0f+Math::Rand()*5.0f;
- dim.x = 2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 1.0f, 20.0f, 0.5f);
- }
- }
- }
- else
- {
- m_phase = APAP_CHARGE;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_phase == APAP_CHARGE )
- {
- if ( m_progress < 1.0f )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- for ( i=0 ; i<2 ; i++ )
- {
- pos = m_object->RetPosition(0);
- pos.y += 16.0f;
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = -Math::Rand()*30.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 1.0f, 0.0f, 0.0f);
- }
- }
-
- ChargeObject(event.rTime);
- }
- else
- {
- m_phase = APAP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- return true;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoPara::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 113, EVENT_OBJECT_TYPE);
-
- pos.x = ox+sx*10.2f;
- pos.y = oy+sy*0.5f;
- ddim.x = 33.0f/640.0f;
- ddim.y = 33.0f/480.0f;
- pw->CreateButton(pos, ddim, 41, EVENT_OBJECT_LIMIT);
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoPara::RetError()
-{
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
- return ERR_OK;
-}
-
-
-// Load all objects under the lightning rod.
-
-void CAutoPara::ChargeObject(float rTime)
-{
- CObject* pObj;
- CObject* power;
- Math::Vector sPos, oPos;
- float dist, energy;
- int i;
-
- sPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, sPos);
- if ( dist > 20.0f ) continue;
-
- if ( pObj->RetTruck() == 0 && pObj->RetType() == OBJECT_POWER )
- {
- energy = pObj->RetEnergy();
- energy += rTime/2.0f;
- if ( energy > 1.0f ) energy = 1.0f;
- pObj->SetEnergy(energy);
- }
-
- power = pObj->RetPower();
- if ( power != 0 && power->RetType() == OBJECT_POWER )
- {
- energy = power->RetEnergy();
- energy += rTime/2.0f;
- if ( energy > 1.0f ) energy = 1.0f;
- power->SetEnergy(energy);
- }
-
- power = pObj->RetFret();
- if ( power != 0 && power->RetType() == OBJECT_POWER )
- {
- energy = power->RetEnergy();
- energy += rTime/2.0f;
- if ( energy > 1.0f ) energy = 1.0f;
- power->SetEnergy(energy);
- }
- }
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoPara::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == APAP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoPara::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoParaPhase)OpInt(line, "aPhase", APAP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autopara.h"
+
+
+#include "common/iman.h"
+#include "math/geometry.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+
+
+
+
+// Object's constructor.
+
+CAutoPara::CAutoPara(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ m_channelSound = -1;
+ Init();
+}
+
+// Object's destructor.
+
+CAutoPara::~CAutoPara()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoPara::DeleteObject(bool bAll)
+{
+ if ( m_channelSound != -1 )
+ {
+ m_sound->FlushEnvelope(m_channelSound);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_channelSound = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoPara::Init()
+{
+ Math::Matrix* mat;
+
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+
+ mat = m_object->RetWorldMatrix(0);
+ m_pos = Math::Transform(*mat, Math::Vector(22.0f, 4.0f, 0.0f));
+
+ m_phase = APAP_WAIT; // waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ CAuto::Init();
+}
+
+
+// Reception of lightning.
+
+void CAutoPara::StartBlitz()
+{
+ m_phase = APAP_BLITZ;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+}
+
+
+// Management of an event.
+
+bool CAutoPara::EventProcess(const Event &event)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+ int i;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+ }
+ return true;
+ }
+
+ EventProgress(event.rTime);
+
+ if ( m_phase == APAP_BLITZ )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*m_progress*40.0f;
+ pos.z += (Math::Rand()-0.5f)*m_progress*40.0f;
+ pos.y += 50.0f-m_progress*50.0f;
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ speed.y = 5.0f+Math::Rand()*5.0f;
+ dim.x = 2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 1.0f, 20.0f, 0.5f);
+ }
+ }
+ }
+ else
+ {
+ m_phase = APAP_CHARGE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_phase == APAP_CHARGE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ for ( i=0 ; i<2 ; i++ )
+ {
+ pos = m_object->RetPosition(0);
+ pos.y += 16.0f;
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = -Math::Rand()*30.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 1.0f, 0.0f, 0.0f);
+ }
+ }
+
+ ChargeObject(event.rTime);
+ }
+ else
+ {
+ m_phase = APAP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ return true;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoPara::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 113, EVENT_OBJECT_TYPE);
+
+ pos.x = ox+sx*10.2f;
+ pos.y = oy+sy*0.5f;
+ ddim.x = 33.0f/640.0f;
+ ddim.y = 33.0f/480.0f;
+ pw->CreateButton(pos, ddim, 41, EVENT_OBJECT_LIMIT);
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoPara::RetError()
+{
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+ return ERR_OK;
+}
+
+
+// Load all objects under the lightning rod.
+
+void CAutoPara::ChargeObject(float rTime)
+{
+ CObject* pObj;
+ CObject* power;
+ Math::Vector sPos, oPos;
+ float dist, energy;
+ int i;
+
+ sPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, sPos);
+ if ( dist > 20.0f ) continue;
+
+ if ( pObj->RetTruck() == 0 && pObj->RetType() == OBJECT_POWER )
+ {
+ energy = pObj->RetEnergy();
+ energy += rTime/2.0f;
+ if ( energy > 1.0f ) energy = 1.0f;
+ pObj->SetEnergy(energy);
+ }
+
+ power = pObj->RetPower();
+ if ( power != 0 && power->RetType() == OBJECT_POWER )
+ {
+ energy = power->RetEnergy();
+ energy += rTime/2.0f;
+ if ( energy > 1.0f ) energy = 1.0f;
+ power->SetEnergy(energy);
+ }
+
+ power = pObj->RetFret();
+ if ( power != 0 && power->RetType() == OBJECT_POWER )
+ {
+ energy = power->RetEnergy();
+ energy += rTime/2.0f;
+ if ( energy > 1.0f ) energy = 1.0f;
+ power->SetEnergy(energy);
+ }
+ }
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoPara::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == APAP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoPara::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoParaPhase)OpInt(line, "aPhase", APAP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autopara.h b/src/object/auto/autopara.h
index e28aa47..b230fd2 100644
--- a/src/object/auto/autopara.h
+++ b/src/object/auto/autopara.h
@@ -1,65 +1,65 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autopara.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoParaPhase
-{
- APAP_WAIT = 1,
- APAP_BLITZ = 2,
- APAP_CHARGE = 3,
-};
-
-
-
-class CAutoPara : public CAuto
-{
-public:
- CAutoPara(CInstanceManager* iMan, CObject* object);
- ~CAutoPara();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
- void StartBlitz();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- void ChargeObject(float rTime);
-
-protected:
- AutoParaPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
- Math::Vector m_pos;
- int m_channelSound;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autopara.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoParaPhase
+{
+ APAP_WAIT = 1,
+ APAP_BLITZ = 2,
+ APAP_CHARGE = 3,
+};
+
+
+
+class CAutoPara : public CAuto
+{
+public:
+ CAutoPara(CInstanceManager* iMan, CObject* object);
+ ~CAutoPara();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+ void StartBlitz();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ void ChargeObject(float rTime);
+
+protected:
+ AutoParaPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+ Math::Vector m_pos;
+ int m_channelSound;
+};
+
diff --git a/src/object/auto/autoportico.cpp b/src/object/auto/autoportico.cpp
index ee3376f..5665556 100644
--- a/src/object/auto/autoportico.cpp
+++ b/src/object/auto/autoportico.cpp
@@ -1,425 +1,425 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoportico.h"
-
-
-#include "object/robotmain.h"
-
-
-
-
-const int PARAM_DEPOSE = 2; // run=2 -> deposits the spaceship
-
-const float PORTICO_POSa = 75.0f;
-const float PORTICO_POSb = 65.0f;
-const float PORTICO_ANGLE1a = ( 25.0f*Math::PI/180.0f);
-const float PORTICO_ANGLE1b = ( 70.0f*Math::PI/180.0f);
-const float PORTICO_ANGLE2a = (-37.5f*Math::PI/180.0f);
-const float PORTICO_ANGLE2b = (-62.5f*Math::PI/180.0f);
-const float PORTICO_ANGLE3a = (-77.5f*Math::PI/180.0f);
-const float PORTICO_ANGLE3b = (-30.0f*Math::PI/180.0f);
-
-const float PORTICO_TIME_MOVE = 16.0f;
-const float PORTICO_TIME_DOWN = 4.0f;
-const float PORTICO_TIME_OPEN = 12.0f;
-
-
-
-
-// Si progress=0, return a.
-// Si progress=1, return b.
-
-float Progress(float a, float b, float progress)
-{
- return a+(b-a)*progress;
-}
-
-
-
-// Object's constructor.
-
-CAutoPortico::CAutoPortico(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
- m_phase = APOP_WAIT;
- m_soundChannel = -1;
-}
-
-// Object's destructor.
-
-CAutoPortico::~CAutoPortico()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoPortico::DeleteObject(bool bAll)
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoPortico::Init()
-{
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- m_posTrack = 0.0f;
-
- m_phase = APOP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- m_cameraProgress = 0.0f;
- m_cameraSpeed = 1.0f/(PORTICO_TIME_MOVE-2.0f);
-}
-
-
-// Starts the object.
-
-void CAutoPortico::Start(int param)
-{
- Math::Vector pos;
-
- pos = m_object->RetPosition(0);
- m_finalPos = pos;
- pos.z += PORTICO_TIME_MOVE*5.0f; // back to start
- m_object->SetPosition(0, pos);
- m_finalPos.z += PORTICO_TIME_OPEN*5.3f;
-
- m_object->SetPosition(1, Math::Vector(0.0f, PORTICO_POSa, 0.0f));
- m_object->SetAngleY(2, PORTICO_ANGLE1a);
- m_object->SetAngleY(3, PORTICO_ANGLE2a);
- m_object->SetAngleY(4, PORTICO_ANGLE3a);
- m_object->SetAngleY(5, -PORTICO_ANGLE1a);
- m_object->SetAngleY(6, -PORTICO_ANGLE2a);
- m_object->SetAngleY(7, -PORTICO_ANGLE3a);
-
- m_phase = APOP_START;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- m_param = param;
-}
-
-
-// Management of an event.
-
-bool CAutoPortico::EventProcess(const Event &event)
-{
- CObject* pObj;
- Math::Vector pos;
- float angle;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
-
- if ( m_phase == APOP_START )
- {
- if ( m_param == PARAM_DEPOSE ) // deposits the ship?
- {
- m_startPos = m_object->RetPosition(0);
-
- m_soundChannel = m_sound->Play(SOUND_MOTORr, m_object->RetPosition(0), 0.0f, 0.3f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, 0.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, PORTICO_TIME_MOVE-0.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 0.5f, SOPER_STOP);
-
- m_phase = APOP_MOVE;
- m_progress = 0.0f;
- m_speed = 1.0f/PORTICO_TIME_MOVE;
-
- m_main->SetMovieLock(true); // blocks everything until the end of the landing
-
- m_camera->SetType(CAMERA_SCRIPT);
-
- pos = m_startPos;
- pos.x += -100.0f;
- pos.y += 9.0f;
- pos.z += -200.0f;
- m_camera->SetScriptEye(pos);
-
- pos = m_object->RetPosition(0);
- pos.x += 0.0f;
- pos.y += 10.0f;
- pos.z += -40.0f;
- m_camera->SetScriptLookat(pos);
-
- m_camera->FixCamera();
- }
- }
-
- angle = -m_time*1.0f;
- m_object->SetAngleY(8, angle); // rotates the radar right
- angle = sinf(m_time*4.0f)*0.3f;
- m_object->SetAngleX(9, angle);
-
- angle = -m_time*1.0f+Math::PI/2.3f;
- m_object->SetAngleY(10, angle); // turns the left side radar
- angle = sinf(m_time*4.0f)*0.3f;
- m_object->SetAngleX(11, angle);
-
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_phase == APOP_WAIT ) return true;
-
- m_progress += event.rTime*m_speed;
- m_cameraProgress += event.rTime*m_cameraSpeed;
-
- if ( m_phase == APOP_MOVE )
- {
- if ( m_progress < 1.0f )
- {
- pos = m_object->RetPosition(0);
- pos.z -= event.rTime*5.0f; // advance
- m_object->SetPosition(0, pos);
-
- m_posTrack += event.rTime*0.5f;
- UpdateTrackMapping(m_posTrack, m_posTrack);
- }
- else
- {
- m_phase = APOP_WAIT1;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == APOP_WAIT1 )
- {
- if ( m_progress >= 1.0f )
- {
- m_soundChannel = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.5f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.6f, PORTICO_TIME_DOWN-1.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 1.0f, SOPER_STOP);
-
- m_phase = APOP_DOWN;
- m_progress = 0.0f;
- m_speed = 1.0f/PORTICO_TIME_DOWN;
- }
- }
-
- if ( m_phase == APOP_DOWN )
- {
- if ( m_progress < 1.0f )
- {
- pos.x = 0.0f;
- pos.y = Progress(PORTICO_POSa, PORTICO_POSb, m_progress);
- pos.z = 0.0f;
- m_object->SetPosition(1, pos);
- }
- else
- {
- pos.x = 0.0f;
- pos.y = PORTICO_POSb;
- pos.z = 0.0f;
- m_object->SetPosition(1, pos);
-
- m_phase = APOP_WAIT2;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == APOP_WAIT2 )
- {
- if ( m_progress >= 1.0f )
- {
- m_soundChannel = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 1.0f, 0.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 1.0f, PORTICO_TIME_OPEN/2.0f-0.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP);
-
- m_soundChannel = m_sound->Play(SOUND_MOTORr, m_object->RetPosition(0), 0.0f, 0.3f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, 0.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, PORTICO_TIME_OPEN-0.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 0.5f, SOPER_STOP);
-
- m_phase = APOP_OPEN;
- m_progress = 0.0f;
- m_speed = 1.0f/PORTICO_TIME_OPEN;
- }
- }
-
- if ( m_phase == APOP_OPEN )
- {
- if ( m_progress < 1.0f )
- {
- pos = m_object->RetPosition(0);
- pos.z += event.rTime*5.3f; // back
- m_object->SetPosition(0, pos);
-
- m_posTrack -= event.rTime*1.0f;
- UpdateTrackMapping(m_posTrack, m_posTrack);
-
- if ( m_progress < 0.5f )
- {
- angle = Progress(PORTICO_ANGLE1a, PORTICO_ANGLE1b, m_progress/0.5f);
- m_object->SetAngleY(2, angle);
- m_object->SetAngleY(5, -angle);
- angle = Progress(PORTICO_ANGLE2a, PORTICO_ANGLE2b, m_progress/0.5f);
- m_object->SetAngleY(3, angle);
- m_object->SetAngleY(6, -angle);
- angle = Progress(PORTICO_ANGLE3a, PORTICO_ANGLE3b, m_progress/0.5f);
- m_object->SetAngleY(4, angle);
- m_object->SetAngleY(7, -angle);
- }
- else
- {
- m_object->SetAngleY(2, PORTICO_ANGLE1b);
- m_object->SetAngleY(3, PORTICO_ANGLE2b);
- m_object->SetAngleY(4, PORTICO_ANGLE3b);
- m_object->SetAngleY(5, -PORTICO_ANGLE1b);
- m_object->SetAngleY(6, -PORTICO_ANGLE2b);
- m_object->SetAngleY(7, -PORTICO_ANGLE3b);
- }
- }
- else
- {
- m_main->SetMovieLock(false); // you can play!
-
- pObj = m_main->SearchHuman();
- m_main->SelectObject(pObj);
- m_camera->SetObject(pObj);
- m_camera->SetType(CAMERA_BACK);
-
- m_phase = APOP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
- }
- }
-
- if ( m_soundChannel != -1 )
- {
-//? m_sound->Position(m_soundChannel, m_object->RetPosition(0));
- pos = m_engine->RetEyePt();
- m_sound->Position(m_soundChannel, pos);
- }
-
- if ( m_cameraProgress < 1.0f )
- {
- if ( m_cameraProgress < 0.5f )
- {
- }
- else
- {
- pos = m_startPos;
- pos.x += -100.0f-(m_cameraProgress-0.5f)*1.0f*120.0f;
- pos.y += 9.0f;
- pos.z += -200.0f+(m_cameraProgress-0.5f)*1.0f*210.0f;
- m_camera->SetScriptEye(pos);
- }
-
- pos = m_object->RetPosition(0);
- pos.x += 0.0f;
- pos.y += 10.0f;
- pos.z += -40.0f;
- m_camera->SetScriptLookat(pos);
- }
-
- return true;
-}
-
-// Stops the controller.
-
-bool CAutoPortico::Abort()
-{
- CObject* pObj;
-
- m_object->SetPosition(0, m_finalPos);
- m_object->SetPosition(1, Math::Vector(0.0f, PORTICO_POSb, 0.0f));
- m_object->SetAngleY(2, PORTICO_ANGLE1b);
- m_object->SetAngleY(3, PORTICO_ANGLE2b);
- m_object->SetAngleY(4, PORTICO_ANGLE3b);
- m_object->SetAngleY(5, -PORTICO_ANGLE1b);
- m_object->SetAngleY(6, -PORTICO_ANGLE2b);
- m_object->SetAngleY(7, -PORTICO_ANGLE3b);
-
- m_main->SetMovieLock(false); // you can play!
-
- pObj = m_main->SearchHuman();
- m_main->SelectObject(pObj);
- m_camera->SetObject(pObj);
- m_camera->SetType(CAMERA_BACK);
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- m_phase = APOP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/2.0f;
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoPortico::RetError()
-{
- return ERR_OK;
-}
-
-
-// Updates the mapping of the texture of the caterpillars.
-
-void CAutoPortico::UpdateTrackMapping(float left, float right)
-{
- D3DMATERIAL7 mat;
- float limit[2];
- int rank;
-
- ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
- mat.diffuse.r = 1.0f;
- mat.diffuse.g = 1.0f;
- mat.diffuse.b = 1.0f; // blank
- mat.ambient.r = 0.5f;
- mat.ambient.g = 0.5f;
- mat.ambient.b = 0.5f;
-
- rank = m_object->RetObjectRank(0);
-
- limit[0] = 0.0f;
- limit[1] = 1000000.0f;
-
- m_engine->TrackTextureMapping(rank, mat, D3DSTATEPART1, "lemt.tga", "",
- limit[0], limit[1], D3DMAPPINGX,
- right, 8.0f, 8.0f, 192.0f, 256.0f);
-
- m_engine->TrackTextureMapping(rank, mat, D3DSTATEPART2, "lemt.tga", "",
- limit[0], limit[1], D3DMAPPINGX,
- left, 8.0f, 8.0f, 192.0f, 256.0f);
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoportico.h"
+
+
+#include "object/robotmain.h"
+
+
+
+
+const int PARAM_DEPOSE = 2; // run=2 -> deposits the spaceship
+
+const float PORTICO_POSa = 75.0f;
+const float PORTICO_POSb = 65.0f;
+const float PORTICO_ANGLE1a = ( 25.0f*Math::PI/180.0f);
+const float PORTICO_ANGLE1b = ( 70.0f*Math::PI/180.0f);
+const float PORTICO_ANGLE2a = (-37.5f*Math::PI/180.0f);
+const float PORTICO_ANGLE2b = (-62.5f*Math::PI/180.0f);
+const float PORTICO_ANGLE3a = (-77.5f*Math::PI/180.0f);
+const float PORTICO_ANGLE3b = (-30.0f*Math::PI/180.0f);
+
+const float PORTICO_TIME_MOVE = 16.0f;
+const float PORTICO_TIME_DOWN = 4.0f;
+const float PORTICO_TIME_OPEN = 12.0f;
+
+
+
+
+// Si progress=0, return a.
+// Si progress=1, return b.
+
+float Progress(float a, float b, float progress)
+{
+ return a+(b-a)*progress;
+}
+
+
+
+// Object's constructor.
+
+CAutoPortico::CAutoPortico(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+ m_phase = APOP_WAIT;
+ m_soundChannel = -1;
+}
+
+// Object's destructor.
+
+CAutoPortico::~CAutoPortico()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoPortico::DeleteObject(bool bAll)
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoPortico::Init()
+{
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+ m_posTrack = 0.0f;
+
+ m_phase = APOP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ m_cameraProgress = 0.0f;
+ m_cameraSpeed = 1.0f/(PORTICO_TIME_MOVE-2.0f);
+}
+
+
+// Starts the object.
+
+void CAutoPortico::Start(int param)
+{
+ Math::Vector pos;
+
+ pos = m_object->RetPosition(0);
+ m_finalPos = pos;
+ pos.z += PORTICO_TIME_MOVE*5.0f; // back to start
+ m_object->SetPosition(0, pos);
+ m_finalPos.z += PORTICO_TIME_OPEN*5.3f;
+
+ m_object->SetPosition(1, Math::Vector(0.0f, PORTICO_POSa, 0.0f));
+ m_object->SetAngleY(2, PORTICO_ANGLE1a);
+ m_object->SetAngleY(3, PORTICO_ANGLE2a);
+ m_object->SetAngleY(4, PORTICO_ANGLE3a);
+ m_object->SetAngleY(5, -PORTICO_ANGLE1a);
+ m_object->SetAngleY(6, -PORTICO_ANGLE2a);
+ m_object->SetAngleY(7, -PORTICO_ANGLE3a);
+
+ m_phase = APOP_START;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ m_param = param;
+}
+
+
+// Management of an event.
+
+bool CAutoPortico::EventProcess(const Event &event)
+{
+ CObject* pObj;
+ Math::Vector pos;
+ float angle;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+
+ if ( m_phase == APOP_START )
+ {
+ if ( m_param == PARAM_DEPOSE ) // deposits the ship?
+ {
+ m_startPos = m_object->RetPosition(0);
+
+ m_soundChannel = m_sound->Play(SOUND_MOTORr, m_object->RetPosition(0), 0.0f, 0.3f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, 0.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, PORTICO_TIME_MOVE-0.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 0.5f, SOPER_STOP);
+
+ m_phase = APOP_MOVE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/PORTICO_TIME_MOVE;
+
+ m_main->SetMovieLock(true); // blocks everything until the end of the landing
+
+ m_camera->SetType(CAMERA_SCRIPT);
+
+ pos = m_startPos;
+ pos.x += -100.0f;
+ pos.y += 9.0f;
+ pos.z += -200.0f;
+ m_camera->SetScriptEye(pos);
+
+ pos = m_object->RetPosition(0);
+ pos.x += 0.0f;
+ pos.y += 10.0f;
+ pos.z += -40.0f;
+ m_camera->SetScriptLookat(pos);
+
+ m_camera->FixCamera();
+ }
+ }
+
+ angle = -m_time*1.0f;
+ m_object->SetAngleY(8, angle); // rotates the radar right
+ angle = sinf(m_time*4.0f)*0.3f;
+ m_object->SetAngleX(9, angle);
+
+ angle = -m_time*1.0f+Math::PI/2.3f;
+ m_object->SetAngleY(10, angle); // turns the left side radar
+ angle = sinf(m_time*4.0f)*0.3f;
+ m_object->SetAngleX(11, angle);
+
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_phase == APOP_WAIT ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_cameraProgress += event.rTime*m_cameraSpeed;
+
+ if ( m_phase == APOP_MOVE )
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos = m_object->RetPosition(0);
+ pos.z -= event.rTime*5.0f; // advance
+ m_object->SetPosition(0, pos);
+
+ m_posTrack += event.rTime*0.5f;
+ UpdateTrackMapping(m_posTrack, m_posTrack);
+ }
+ else
+ {
+ m_phase = APOP_WAIT1;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == APOP_WAIT1 )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_soundChannel = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.5f, 1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.3f, 0.6f, PORTICO_TIME_DOWN-1.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 1.0f, SOPER_STOP);
+
+ m_phase = APOP_DOWN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/PORTICO_TIME_DOWN;
+ }
+ }
+
+ if ( m_phase == APOP_DOWN )
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos.x = 0.0f;
+ pos.y = Progress(PORTICO_POSa, PORTICO_POSb, m_progress);
+ pos.z = 0.0f;
+ m_object->SetPosition(1, pos);
+ }
+ else
+ {
+ pos.x = 0.0f;
+ pos.y = PORTICO_POSb;
+ pos.z = 0.0f;
+ m_object->SetPosition(1, pos);
+
+ m_phase = APOP_WAIT2;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == APOP_WAIT2 )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_soundChannel = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.5f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.5f, 1.0f, 0.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.5f, 1.0f, PORTICO_TIME_OPEN/2.0f-0.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP);
+
+ m_soundChannel = m_sound->Play(SOUND_MOTORr, m_object->RetPosition(0), 0.0f, 0.3f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, 0.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.6f, PORTICO_TIME_OPEN-0.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.3f, 0.5f, SOPER_STOP);
+
+ m_phase = APOP_OPEN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/PORTICO_TIME_OPEN;
+ }
+ }
+
+ if ( m_phase == APOP_OPEN )
+ {
+ if ( m_progress < 1.0f )
+ {
+ pos = m_object->RetPosition(0);
+ pos.z += event.rTime*5.3f; // back
+ m_object->SetPosition(0, pos);
+
+ m_posTrack -= event.rTime*1.0f;
+ UpdateTrackMapping(m_posTrack, m_posTrack);
+
+ if ( m_progress < 0.5f )
+ {
+ angle = Progress(PORTICO_ANGLE1a, PORTICO_ANGLE1b, m_progress/0.5f);
+ m_object->SetAngleY(2, angle);
+ m_object->SetAngleY(5, -angle);
+ angle = Progress(PORTICO_ANGLE2a, PORTICO_ANGLE2b, m_progress/0.5f);
+ m_object->SetAngleY(3, angle);
+ m_object->SetAngleY(6, -angle);
+ angle = Progress(PORTICO_ANGLE3a, PORTICO_ANGLE3b, m_progress/0.5f);
+ m_object->SetAngleY(4, angle);
+ m_object->SetAngleY(7, -angle);
+ }
+ else
+ {
+ m_object->SetAngleY(2, PORTICO_ANGLE1b);
+ m_object->SetAngleY(3, PORTICO_ANGLE2b);
+ m_object->SetAngleY(4, PORTICO_ANGLE3b);
+ m_object->SetAngleY(5, -PORTICO_ANGLE1b);
+ m_object->SetAngleY(6, -PORTICO_ANGLE2b);
+ m_object->SetAngleY(7, -PORTICO_ANGLE3b);
+ }
+ }
+ else
+ {
+ m_main->SetMovieLock(false); // you can play!
+
+ pObj = m_main->SearchHuman();
+ m_main->SelectObject(pObj);
+ m_camera->SetObject(pObj);
+ m_camera->SetType(CAMERA_BACK);
+
+ m_phase = APOP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+ }
+ }
+
+ if ( m_soundChannel != -1 )
+ {
+//? m_sound->Position(m_soundChannel, m_object->RetPosition(0));
+ pos = m_engine->RetEyePt();
+ m_sound->Position(m_soundChannel, pos);
+ }
+
+ if ( m_cameraProgress < 1.0f )
+ {
+ if ( m_cameraProgress < 0.5f )
+ {
+ }
+ else
+ {
+ pos = m_startPos;
+ pos.x += -100.0f-(m_cameraProgress-0.5f)*1.0f*120.0f;
+ pos.y += 9.0f;
+ pos.z += -200.0f+(m_cameraProgress-0.5f)*1.0f*210.0f;
+ m_camera->SetScriptEye(pos);
+ }
+
+ pos = m_object->RetPosition(0);
+ pos.x += 0.0f;
+ pos.y += 10.0f;
+ pos.z += -40.0f;
+ m_camera->SetScriptLookat(pos);
+ }
+
+ return true;
+}
+
+// Stops the controller.
+
+bool CAutoPortico::Abort()
+{
+ CObject* pObj;
+
+ m_object->SetPosition(0, m_finalPos);
+ m_object->SetPosition(1, Math::Vector(0.0f, PORTICO_POSb, 0.0f));
+ m_object->SetAngleY(2, PORTICO_ANGLE1b);
+ m_object->SetAngleY(3, PORTICO_ANGLE2b);
+ m_object->SetAngleY(4, PORTICO_ANGLE3b);
+ m_object->SetAngleY(5, -PORTICO_ANGLE1b);
+ m_object->SetAngleY(6, -PORTICO_ANGLE2b);
+ m_object->SetAngleY(7, -PORTICO_ANGLE3b);
+
+ m_main->SetMovieLock(false); // you can play!
+
+ pObj = m_main->SearchHuman();
+ m_main->SelectObject(pObj);
+ m_camera->SetObject(pObj);
+ m_camera->SetType(CAMERA_BACK);
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ m_phase = APOP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/2.0f;
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoPortico::RetError()
+{
+ return ERR_OK;
+}
+
+
+// Updates the mapping of the texture of the caterpillars.
+
+void CAutoPortico::UpdateTrackMapping(float left, float right)
+{
+ D3DMATERIAL7 mat;
+ float limit[2];
+ int rank;
+
+ ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
+ mat.diffuse.r = 1.0f;
+ mat.diffuse.g = 1.0f;
+ mat.diffuse.b = 1.0f; // blank
+ mat.ambient.r = 0.5f;
+ mat.ambient.g = 0.5f;
+ mat.ambient.b = 0.5f;
+
+ rank = m_object->RetObjectRank(0);
+
+ limit[0] = 0.0f;
+ limit[1] = 1000000.0f;
+
+ m_engine->TrackTextureMapping(rank, mat, D3DSTATEPART1, "lemt.tga", "",
+ limit[0], limit[1], D3DMAPPINGX,
+ right, 8.0f, 8.0f, 192.0f, 256.0f);
+
+ m_engine->TrackTextureMapping(rank, mat, D3DSTATEPART2, "lemt.tga", "",
+ limit[0], limit[1], D3DMAPPINGX,
+ left, 8.0f, 8.0f, 192.0f, 256.0f);
+}
+
diff --git a/src/object/auto/autoportico.h b/src/object/auto/autoportico.h
index 566c358..f2cd6d1 100644
--- a/src/object/auto/autoportico.h
+++ b/src/object/auto/autoportico.h
@@ -1,69 +1,69 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoportico.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoPorticoPhase
-{
- APOP_WAIT = 1, // waits
- APOP_START = 2, // start of the action
- APOP_MOVE = 3, // advance
- APOP_WAIT1 = 4, // waits
- APOP_DOWN = 5, // down
- APOP_WAIT2 = 6, // waits
- APOP_OPEN = 7, // opens
-};
-
-
-
-class CAutoPortico : public CAuto
-{
-public:
- CAutoPortico(CInstanceManager* iMan, CObject* object);
- ~CAutoPortico();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- void Start(int param);
- bool EventProcess(const Event &event);
- bool Abort();
- Error RetError();
-
-protected:
- void UpdateTrackMapping(float left, float right);
-
-protected:
- AutoPorticoPhase m_phase;
- float m_progress;
- float m_speed;
- float m_cameraProgress;
- float m_cameraSpeed;
- float m_lastParticule;
- Math::Vector m_finalPos;
- Math::Vector m_startPos;
- float m_posTrack;
- int m_param;
- int m_soundChannel;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoportico.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoPorticoPhase
+{
+ APOP_WAIT = 1, // waits
+ APOP_START = 2, // start of the action
+ APOP_MOVE = 3, // advance
+ APOP_WAIT1 = 4, // waits
+ APOP_DOWN = 5, // down
+ APOP_WAIT2 = 6, // waits
+ APOP_OPEN = 7, // opens
+};
+
+
+
+class CAutoPortico : public CAuto
+{
+public:
+ CAutoPortico(CInstanceManager* iMan, CObject* object);
+ ~CAutoPortico();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ void Start(int param);
+ bool EventProcess(const Event &event);
+ bool Abort();
+ Error RetError();
+
+protected:
+ void UpdateTrackMapping(float left, float right);
+
+protected:
+ AutoPorticoPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_cameraProgress;
+ float m_cameraSpeed;
+ float m_lastParticule;
+ Math::Vector m_finalPos;
+ Math::Vector m_startPos;
+ float m_posTrack;
+ int m_param;
+ int m_soundChannel;
+};
+
diff --git a/src/object/auto/autoradar.cpp b/src/object/auto/autoradar.cpp
index b8bee44..1cb20d6 100644
--- a/src/object/auto/autoradar.cpp
+++ b/src/object/auto/autoradar.cpp
@@ -1,306 +1,306 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoradar.h"
-
-#include "common/iman.h"
-#include "math/geometry.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-#include "ui/gauge.h"
-
-
-// Object's constructor.
-
-CAutoRadar::CAutoRadar(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
- m_phase = ARAP_WAIT;
- m_totalDetect = 0;
-}
-
-// Object's destructor.
-
-CAutoRadar::~CAutoRadar()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoRadar::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoRadar::Init()
-{
- m_phase = ARAP_SEARCH;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
-
- m_aTime = 0.0f;
- m_time = 0.0f;
- m_timeVirus = 0.0f;
-}
-
-
-// Management of an event.
-
-bool CAutoRadar::EventProcess(const Event &event)
-{
- Math::Vector pos, ePos;
- float speed, angle, prog, freq, ampl;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_phase == ARAP_WAIT ) return true;
-
- m_progress += event.rTime*m_speed;
- m_aTime += event.rTime;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
-
- angle = m_object->RetAngleY(1);
- angle += (Math::Rand()-0.2f)*0.5f;
- m_object->SetAngleY(1, angle);
-
- angle = m_object->RetAngleY(2);
- angle += (Math::Rand()-0.8f)*1.0f;
- m_object->SetAngleY(2, angle);
-
- m_object->SetAngleX(3, (Math::Rand()-0.5f)*0.3f);
-
- m_totalDetect = (int)(Math::Rand()*10.0f);
- UpdateInterface();
- }
- return true;
- }
-
- if ( m_phase == ARAP_SEARCH )
- {
- if ( m_progress < 1.0f )
- {
- speed = Math::Min(10.0f, m_progress*50.0f);
- angle = m_object->RetAngleY(1);
- angle += event.rTime*speed;
- m_object->SetAngleY(1, angle);
- }
- else
- {
- if ( !SearchEnemy(ePos) )
- {
- m_phase = ARAP_SEARCH;
- m_progress = 10.0f/50.0f; // full speed immediately
- m_speed = 1.0f/3.0f;
- }
- else
- {
- pos = m_object->RetPosition(0);
- m_start = m_object->RetAngleY(1);
- m_angle = m_start-Math::NormAngle(m_start)+Math::PI*2.0f;
- m_angle += Math::RotateAngle(pos.x-ePos.x, ePos.z-pos.z);
- m_angle += Math::PI-m_object->RetAngleY(0);
-
- m_phase = ARAP_SHOW;
- m_progress = 0.0f;
- m_speed = 1.0f/(fabs(m_angle-m_start)/10.0f);
- }
- }
- }
-
- if ( m_phase == ARAP_SHOW )
- {
- if ( m_progress < 1.0f )
- {
- angle = m_start + (m_angle-m_start)*m_progress;
- m_object->SetAngleY(1, angle);
- }
- else
- {
- m_sound->Play(SOUND_RADAR, m_object->RetPosition(0));
-
- m_phase = ARAP_SINUS;
- m_progress = 0.0f;
- m_speed = 1.0f/4.0f;
- m_time = 0.0f;
- }
- }
-
- if ( m_phase == ARAP_SINUS )
- {
- if ( m_progress < 1.0f )
- {
- prog = Math::Min(1.0f, m_progress*2.0f);
- freq = 16.0f*(prog+1.0f);
- ampl = 0.2f-prog*0.2f;
- angle = m_angle + sinf(m_time*freq)*ampl;
- m_object->SetAngleY(1, angle);
- }
- else
- {
- m_phase = ARAP_SEARCH;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- }
- }
-
- angle = -m_aTime*2.0f;
- m_object->SetAngleY(2, angle);
-
- angle = sinf(m_aTime*4.0f)*0.3f;
- m_object->SetAngleX(3, angle);
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoRadar::RetError()
-{
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- return ERR_OK;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoRadar::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, dim, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*7.0f;
- pos.y = oy+sy*0.6f;
- dim.x = 160.0f/640.0f;
- dim.y = 26.0f/480.0f;
- pw->CreateGauge(pos, dim, 1, EVENT_OBJECT_GRADAR);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 105, EVENT_OBJECT_TYPE);
-
- UpdateInterface();
- return true;
-}
-
-// Updates the status of all interface buttons.
-
-void CAutoRadar::UpdateInterface()
-{
- CWindow* pw;
- CGauge* pg;
- float level;
-
- if ( !m_object->RetSelect() ) return;
-
- CAuto::UpdateInterface();
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GRADAR);
- if ( pg != 0 )
- {
- level = (float)m_totalDetect*(1.0f/8.0f);
- if ( level > 1.0f ) level = 1.0f;
- pg->SetLevel(level);
- }
-}
-
-
-// Seeking the position of an enemy.
-
-bool CAutoRadar::SearchEnemy(Math::Vector &pos)
-{
- CObject* pObj;
- CObject* pBest = 0;
- Math::Vector iPos, oPos;
- ObjectType oType;
- float distance, min;
- int i;
-
- iPos = m_object->RetPosition(0);
- min = 1000000.0f;
- m_totalDetect = 0;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue;
-
- oType = pObj->RetType();
- if ( oType != OBJECT_ANT &&
- oType != OBJECT_SPIDER &&
- oType != OBJECT_BEE &&
- oType != OBJECT_WORM &&
- oType != OBJECT_MOTHER ) continue;
-
- m_totalDetect ++;
-
- oPos = pObj->RetPosition(0);
- distance = Math::Distance(oPos, iPos);
- if ( distance < min )
- {
- min = distance;
- pBest = pObj;
- }
- }
-
- UpdateInterface();
-
- if ( pBest == 0 ) return false;
- pos = pBest->RetPosition(0);
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoradar.h"
+
+#include "common/iman.h"
+#include "math/geometry.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+#include "ui/gauge.h"
+
+
+// Object's constructor.
+
+CAutoRadar::CAutoRadar(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+ m_phase = ARAP_WAIT;
+ m_totalDetect = 0;
+}
+
+// Object's destructor.
+
+CAutoRadar::~CAutoRadar()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoRadar::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoRadar::Init()
+{
+ m_phase = ARAP_SEARCH;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+
+ m_aTime = 0.0f;
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+}
+
+
+// Management of an event.
+
+bool CAutoRadar::EventProcess(const Event &event)
+{
+ Math::Vector pos, ePos;
+ float speed, angle, prog, freq, ampl;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_phase == ARAP_WAIT ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_aTime += event.rTime;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+
+ angle = m_object->RetAngleY(1);
+ angle += (Math::Rand()-0.2f)*0.5f;
+ m_object->SetAngleY(1, angle);
+
+ angle = m_object->RetAngleY(2);
+ angle += (Math::Rand()-0.8f)*1.0f;
+ m_object->SetAngleY(2, angle);
+
+ m_object->SetAngleX(3, (Math::Rand()-0.5f)*0.3f);
+
+ m_totalDetect = (int)(Math::Rand()*10.0f);
+ UpdateInterface();
+ }
+ return true;
+ }
+
+ if ( m_phase == ARAP_SEARCH )
+ {
+ if ( m_progress < 1.0f )
+ {
+ speed = Math::Min(10.0f, m_progress*50.0f);
+ angle = m_object->RetAngleY(1);
+ angle += event.rTime*speed;
+ m_object->SetAngleY(1, angle);
+ }
+ else
+ {
+ if ( !SearchEnemy(ePos) )
+ {
+ m_phase = ARAP_SEARCH;
+ m_progress = 10.0f/50.0f; // full speed immediately
+ m_speed = 1.0f/3.0f;
+ }
+ else
+ {
+ pos = m_object->RetPosition(0);
+ m_start = m_object->RetAngleY(1);
+ m_angle = m_start-Math::NormAngle(m_start)+Math::PI*2.0f;
+ m_angle += Math::RotateAngle(pos.x-ePos.x, ePos.z-pos.z);
+ m_angle += Math::PI-m_object->RetAngleY(0);
+
+ m_phase = ARAP_SHOW;
+ m_progress = 0.0f;
+ m_speed = 1.0f/(fabs(m_angle-m_start)/10.0f);
+ }
+ }
+ }
+
+ if ( m_phase == ARAP_SHOW )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = m_start + (m_angle-m_start)*m_progress;
+ m_object->SetAngleY(1, angle);
+ }
+ else
+ {
+ m_sound->Play(SOUND_RADAR, m_object->RetPosition(0));
+
+ m_phase = ARAP_SINUS;
+ m_progress = 0.0f;
+ m_speed = 1.0f/4.0f;
+ m_time = 0.0f;
+ }
+ }
+
+ if ( m_phase == ARAP_SINUS )
+ {
+ if ( m_progress < 1.0f )
+ {
+ prog = Math::Min(1.0f, m_progress*2.0f);
+ freq = 16.0f*(prog+1.0f);
+ ampl = 0.2f-prog*0.2f;
+ angle = m_angle + sinf(m_time*freq)*ampl;
+ m_object->SetAngleY(1, angle);
+ }
+ else
+ {
+ m_phase = ARAP_SEARCH;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ }
+ }
+
+ angle = -m_aTime*2.0f;
+ m_object->SetAngleY(2, angle);
+
+ angle = sinf(m_aTime*4.0f)*0.3f;
+ m_object->SetAngleX(3, angle);
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoRadar::RetError()
+{
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ return ERR_OK;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoRadar::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, dim, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*7.0f;
+ pos.y = oy+sy*0.6f;
+ dim.x = 160.0f/640.0f;
+ dim.y = 26.0f/480.0f;
+ pw->CreateGauge(pos, dim, 1, EVENT_OBJECT_GRADAR);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 105, EVENT_OBJECT_TYPE);
+
+ UpdateInterface();
+ return true;
+}
+
+// Updates the status of all interface buttons.
+
+void CAutoRadar::UpdateInterface()
+{
+ CWindow* pw;
+ CGauge* pg;
+ float level;
+
+ if ( !m_object->RetSelect() ) return;
+
+ CAuto::UpdateInterface();
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GRADAR);
+ if ( pg != 0 )
+ {
+ level = (float)m_totalDetect*(1.0f/8.0f);
+ if ( level > 1.0f ) level = 1.0f;
+ pg->SetLevel(level);
+ }
+}
+
+
+// Seeking the position of an enemy.
+
+bool CAutoRadar::SearchEnemy(Math::Vector &pos)
+{
+ CObject* pObj;
+ CObject* pBest = 0;
+ Math::Vector iPos, oPos;
+ ObjectType oType;
+ float distance, min;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+ min = 1000000.0f;
+ m_totalDetect = 0;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue;
+
+ oType = pObj->RetType();
+ if ( oType != OBJECT_ANT &&
+ oType != OBJECT_SPIDER &&
+ oType != OBJECT_BEE &&
+ oType != OBJECT_WORM &&
+ oType != OBJECT_MOTHER ) continue;
+
+ m_totalDetect ++;
+
+ oPos = pObj->RetPosition(0);
+ distance = Math::Distance(oPos, iPos);
+ if ( distance < min )
+ {
+ min = distance;
+ pBest = pObj;
+ }
+ }
+
+ UpdateInterface();
+
+ if ( pBest == 0 ) return false;
+ pos = pBest->RetPosition(0);
+ return true;
+}
+
+
diff --git a/src/object/auto/autoradar.h b/src/object/auto/autoradar.h
index 5a5020b..8b38ff9 100644
--- a/src/object/auto/autoradar.h
+++ b/src/object/auto/autoradar.h
@@ -1,64 +1,64 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoradar.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoRadarPhase
-{
- ARAP_WAIT = 1, // waiting
- ARAP_SEARCH = 2, // seeking
- ARAP_SHOW = 3, // watching
- ARAP_SINUS = 4, // oscillates
-};
-
-
-
-class CAutoRadar : public CAuto
-{
-public:
- CAutoRadar(CInstanceManager* iMan, CObject* object);
- ~CAutoRadar();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- bool CreateInterface(bool bSelect);
- Error RetError();
-
-protected:
- void UpdateInterface();
- bool SearchEnemy(Math::Vector &pos);
-
-protected:
- AutoRadarPhase m_phase;
- float m_progress;
- float m_speed;
- float m_aTime;
- float m_timeVirus;
- float m_lastParticule;
- float m_angle;
- float m_start;
- int m_totalDetect;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoradar.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoRadarPhase
+{
+ ARAP_WAIT = 1, // waiting
+ ARAP_SEARCH = 2, // seeking
+ ARAP_SHOW = 3, // watching
+ ARAP_SINUS = 4, // oscillates
+};
+
+
+
+class CAutoRadar : public CAuto
+{
+public:
+ CAutoRadar(CInstanceManager* iMan, CObject* object);
+ ~CAutoRadar();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ bool CreateInterface(bool bSelect);
+ Error RetError();
+
+protected:
+ void UpdateInterface();
+ bool SearchEnemy(Math::Vector &pos);
+
+protected:
+ AutoRadarPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_aTime;
+ float m_timeVirus;
+ float m_lastParticule;
+ float m_angle;
+ float m_start;
+ int m_totalDetect;
+};
+
diff --git a/src/object/auto/autorepair.cpp b/src/object/auto/autorepair.cpp
index b56f771..ad5deee 100644
--- a/src/object/auto/autorepair.cpp
+++ b/src/object/auto/autorepair.cpp
@@ -1,339 +1,339 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autorepair.h"
-
-#include "common/iman.h"
-#include "physics/physics.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-
-
-// Object's constructor.
-
-CAutoRepair::CAutoRepair(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
- m_phase = ARP_WAIT; // paused until the first Init ()
-}
-
-// Object's destructor.
-
-CAutoRepair::~CAutoRepair()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoRepair::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoRepair::Init()
-{
- m_phase = ARP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastParticule = 0.0f;
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoRepair::EventProcess(const Event &event)
-{
- CObject* vehicule;
- Math::Vector pos, speed;
- Math::Point dim;
- float angle, shield;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
- }
- return true;
- }
-
- if ( m_phase == ARP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- if ( SearchVehicle() == 0 )
- {
- m_phase = ARP_WAIT; // still waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- else
- {
- m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 0.8f);
-
- m_phase = ARP_DOWN;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- }
- }
- }
-
- if ( m_phase == ARP_DOWN )
- {
- if ( m_progress < 1.0f )
- {
- angle = -m_progress*(Math::PI/2.0f)+Math::PI/2.0f;
- m_object->SetAngleZ(1, angle);
- }
- else
- {
- m_object->SetAngleZ(1, 0.0f);
- m_sound->Play(SOUND_REPAIR, m_object->RetPosition(0));
-
- m_phase = ARP_REPAIR;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ARP_REPAIR )
- {
- vehicule = SearchVehicle();
- if ( m_progress < 1.0f ||
- (vehicule != 0 && vehicule->RetShield() < 1.0f) )
- {
- if ( vehicule != 0 )
- {
- shield = vehicule->RetShield();
- shield += event.rTime*0.2f;
- if ( shield > 1.0f ) shield = 1.0f;
- vehicule->SetShield(shield);
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- pos.y += 1.0f;
- speed.x = (Math::Rand()-0.5f)*12.0f;
- speed.z = (Math::Rand()-0.5f)*12.0f;
- speed.y = Math::Rand()*15.0f;
- dim.x = Math::Rand()*6.0f+4.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
- }
- }
- else
- {
- m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 0.8f);
-
- m_phase = ARP_UP;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- }
- }
-
- if ( m_phase == ARP_UP )
- {
- if ( m_progress < 1.0f )
- {
- angle = -(1.0f-m_progress)*(Math::PI/2.0f)+Math::PI/2.0f;
- m_object->SetAngleZ(1, angle);
- }
- else
- {
- m_object->SetAngleZ(1, Math::PI/2.0f);
-
- m_phase = ARP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- return true;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoRepair::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 106, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-
-// Seeking the vehicle on the station.
-
-CObject* CAutoRepair::SearchVehicle()
-{
- CObject* pObj;
- CPhysics* physics;
- Math::Vector sPos, oPos;
- ObjectType type;
- float dist;
- int i;
-
- sPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- 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_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr ) continue;
-
- physics = pObj->RetPhysics();
- if ( physics != 0 && !physics->RetLand() ) continue; // in flight?
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, sPos);
- if ( dist <= 5.0f ) return pObj;
- }
-
- return 0;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoRepair::RetError()
-{
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- return ERR_OK;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoRepair::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == ARP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoRepair::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoRepairPhase)OpInt(line, "aPhase", ARP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autorepair.h"
+
+#include "common/iman.h"
+#include "physics/physics.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+
+
+// Object's constructor.
+
+CAutoRepair::CAutoRepair(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+ m_phase = ARP_WAIT; // paused until the first Init ()
+}
+
+// Object's destructor.
+
+CAutoRepair::~CAutoRepair()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoRepair::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoRepair::Init()
+{
+ m_phase = ARP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoRepair::EventProcess(const Event &event)
+{
+ CObject* vehicule;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float angle, shield;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+ }
+ return true;
+ }
+
+ if ( m_phase == ARP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ if ( SearchVehicle() == 0 )
+ {
+ m_phase = ARP_WAIT; // still waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ else
+ {
+ m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 0.8f);
+
+ m_phase = ARP_DOWN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ }
+ }
+ }
+
+ if ( m_phase == ARP_DOWN )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = -m_progress*(Math::PI/2.0f)+Math::PI/2.0f;
+ m_object->SetAngleZ(1, angle);
+ }
+ else
+ {
+ m_object->SetAngleZ(1, 0.0f);
+ m_sound->Play(SOUND_REPAIR, m_object->RetPosition(0));
+
+ m_phase = ARP_REPAIR;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ARP_REPAIR )
+ {
+ vehicule = SearchVehicle();
+ if ( m_progress < 1.0f ||
+ (vehicule != 0 && vehicule->RetShield() < 1.0f) )
+ {
+ if ( vehicule != 0 )
+ {
+ shield = vehicule->RetShield();
+ shield += event.rTime*0.2f;
+ if ( shield > 1.0f ) shield = 1.0f;
+ vehicule->SetShield(shield);
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ pos.y += 1.0f;
+ speed.x = (Math::Rand()-0.5f)*12.0f;
+ speed.z = (Math::Rand()-0.5f)*12.0f;
+ speed.y = Math::Rand()*15.0f;
+ dim.x = Math::Rand()*6.0f+4.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
+ }
+ }
+ else
+ {
+ m_sound->Play(SOUND_OPEN, m_object->RetPosition(0), 1.0f, 0.8f);
+
+ m_phase = ARP_UP;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ }
+ }
+
+ if ( m_phase == ARP_UP )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = -(1.0f-m_progress)*(Math::PI/2.0f)+Math::PI/2.0f;
+ m_object->SetAngleZ(1, angle);
+ }
+ else
+ {
+ m_object->SetAngleZ(1, Math::PI/2.0f);
+
+ m_phase = ARP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ return true;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoRepair::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 106, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+
+// Seeking the vehicle on the station.
+
+CObject* CAutoRepair::SearchVehicle()
+{
+ CObject* pObj;
+ CPhysics* physics;
+ Math::Vector sPos, oPos;
+ ObjectType type;
+ float dist;
+ int i;
+
+ sPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ 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_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_MOBILEdr ) continue;
+
+ physics = pObj->RetPhysics();
+ if ( physics != 0 && !physics->RetLand() ) continue; // in flight?
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, sPos);
+ if ( dist <= 5.0f ) return pObj;
+ }
+
+ return 0;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoRepair::RetError()
+{
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ return ERR_OK;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoRepair::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == ARP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoRepair::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoRepairPhase)OpInt(line, "aPhase", ARP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autorepair.h b/src/object/auto/autorepair.h
index 1178529..1279ba3 100644
--- a/src/object/auto/autorepair.h
+++ b/src/object/auto/autorepair.h
@@ -1,65 +1,65 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autorepair.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoRepairPhase
-{
- ARP_WAIT = 1, // expected metal
- ARP_DOWN = 2, // down the cover
- ARP_REPAIR = 3, // repair the vehicle
- ARP_UP = 4, // back cover
-
-};
-
-
-
-class CAutoRepair : public CAuto
-{
-public:
- CAutoRepair(CInstanceManager* iMan, CObject* object);
- ~CAutoRepair();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- CObject* SearchVehicle();
-
-protected:
- AutoRepairPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autorepair.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoRepairPhase
+{
+ ARP_WAIT = 1, // expected metal
+ ARP_DOWN = 2, // down the cover
+ ARP_REPAIR = 3, // repair the vehicle
+ ARP_UP = 4, // back cover
+
+};
+
+
+
+class CAutoRepair : public CAuto
+{
+public:
+ CAutoRepair(CInstanceManager* iMan, CObject* object);
+ ~CAutoRepair();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ CObject* SearchVehicle();
+
+protected:
+ AutoRepairPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+};
+
+
diff --git a/src/object/auto/autoresearch.cpp b/src/object/auto/autoresearch.cpp
index abf228c..bc6dbd0 100644
--- a/src/object/auto/autoresearch.cpp
+++ b/src/object/auto/autoresearch.cpp
@@ -1,608 +1,608 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoresearch.h"
-
-#include "common/global.h"
-#include "math/geometry.h"
-#include "object/robotmain.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/gauge.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-
-
-
-const float SEARCH_TIME = 30.0f; // duration of a research
-
-
-
-// Object's constructor.
-
-CAutoResearch::CAutoResearch(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- int i;
-
- for ( i=0 ; i<6 ; i++ )
- {
- m_partiStop[i] = -1;
- }
- m_channelSound = -1;
-
- Init();
-}
-
-// Object's destructor.
-
-CAutoResearch::~CAutoResearch()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoResearch::DeleteObject(bool bAll)
-{
- if ( m_channelSound != -1 )
- {
- m_sound->FlushEnvelope(m_channelSound);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_channelSound = -1;
- }
-
- FireStopUpdate(0.0f, false);
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoResearch::Init()
-{
- m_phase = ALP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastUpdateTime = 0.0f;
- m_lastParticule = 0.0f;
-}
-
-
-// Management of an event.
-
-bool CAutoResearch::EventProcess(const Event &event)
-{
- CObject* power;
- Math::Vector pos, speed;
- Error message;
- Math::Point dim;
- float angle, time;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
-
- if ( event.event == EVENT_UPDINTERFACE )
- {
- if ( m_object->RetSelect() ) CreateInterface(true);
- }
-
- if ( m_object->RetSelect() && // center selected?
- (event.event == EVENT_OBJECT_RTANK ||
- event.event == EVENT_OBJECT_RFLY ||
- event.event == EVENT_OBJECT_RTHUMP ||
- event.event == EVENT_OBJECT_RCANON ||
- event.event == EVENT_OBJECT_RTOWER ||
- event.event == EVENT_OBJECT_RPHAZER ||
- event.event == EVENT_OBJECT_RSHIELD ||
- event.event == EVENT_OBJECT_RATOMIC ) )
- {
- if ( m_phase != ALP_WAIT )
- {
- return false;
- }
-
- m_research = event.event;
-
- if ( TestResearch(m_research) )
- {
- m_displayText->DisplayError(ERR_RESEARCH_ALREADY, m_object);
- return false;
- }
-
- power = m_object->RetPower();
- if ( power == 0 )
- {
- m_displayText->DisplayError(ERR_RESEARCH_POWER, m_object);
- return false;
- }
- if ( power->RetCapacity() > 1.0f )
- {
- m_displayText->DisplayError(ERR_RESEARCH_TYPE, m_object);
- return false;
- }
- if ( power->RetEnergy() < 1.0f )
- {
- m_displayText->DisplayError(ERR_RESEARCH_ENERGY, m_object);
- return false;
- }
-
- time = SEARCH_TIME;
- if ( event.event == EVENT_OBJECT_RTANK ) time *= 0.3f;
- if ( event.event == EVENT_OBJECT_RFLY ) time *= 0.3f;
- if ( event.event == EVENT_OBJECT_RATOMIC ) time *= 2.0f;
-
- SetBusy(true);
- InitProgressTotal(time);
- UpdateInterface();
-
- m_channelSound = m_sound->Play(SOUND_RESEARCH, m_object->RetPosition(0), 0.0f, 1.0f, true);
- m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, time-4.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP);
-
- m_phase = ALP_SEARCH;
- m_progress = 0.0f;
- m_speed = 1.0f/time;
- return true;
- }
-
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
- }
- return true;
- }
-
- UpdateInterface(event.rTime);
- EventProgress(event.rTime);
-
- angle = m_time*0.1f;
- m_object->SetAngleY(1, angle); // rotates the antenna
-
- angle = (30.0f+sinf(m_time*0.3f)*20.0f)*Math::PI/180.0f;
- m_object->SetAngleZ(2, angle); // directs the antenna
-
- if ( m_phase == ALP_WAIT )
- {
- FireStopUpdate(m_progress, false); // extinguished
- return true;
- }
-
- if ( m_phase == ALP_SEARCH )
- {
- FireStopUpdate(m_progress, true); // flashes
- if ( m_progress < 1.0f )
- {
- power = m_object->RetPower();
- if ( power == 0 ) // more battery?
- {
- SetBusy(false);
- UpdateInterface();
-
- m_phase = ALP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- return true;
- }
- power->SetEnergy(1.0f-m_progress);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*6.0f;
- pos.z += (Math::Rand()-0.5f)*6.0f;
- pos.y += 11.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = Math::Rand()*20.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIVAPOR);
- }
- }
- else
- {
- SetResearch(m_research); // research done
- m_displayText->DisplayError(INFO_RESEARCH, m_object);
-
- message = ERR_OK;
- if ( m_research == EVENT_OBJECT_RTANK ) message = INFO_RESEARCHTANK;
- if ( m_research == EVENT_OBJECT_RFLY ) message = INFO_RESEARCHFLY;
- if ( m_research == EVENT_OBJECT_RTHUMP ) message = INFO_RESEARCHTHUMP;
- if ( m_research == EVENT_OBJECT_RCANON ) message = INFO_RESEARCHCANON;
- if ( m_research == EVENT_OBJECT_RTOWER ) message = INFO_RESEARCHTOWER;
- if ( m_research == EVENT_OBJECT_RPHAZER ) message = INFO_RESEARCHPHAZER;
- if ( m_research == EVENT_OBJECT_RSHIELD ) message = INFO_RESEARCHSHIELD;
- if ( m_research == EVENT_OBJECT_RATOMIC ) message = INFO_RESEARCHATOMIC;
- if ( message != ERR_OK )
- {
- m_displayText->DisplayError(message, m_object);
- }
-
- SetBusy(false);
- UpdateInterface();
-
- m_phase = ALP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoResearch::RetError()
-{
- CObject* power;
-
- if ( m_phase == ALP_SEARCH )
- {
- return ERR_OK;
- }
-
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- power = m_object->RetPower();
- if ( power == 0 )
- {
- return ERR_RESEARCH_POWER;
- }
- if ( power != 0 && power->RetCapacity() > 1.0f )
- {
- return ERR_RESEARCH_TYPE;
- }
- if ( power != 0 && power->RetEnergy() < 1.0f )
- {
- return ERR_RESEARCH_ENERGY;
- }
-
- return ERR_OK;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoResearch::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, dim, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- dim.x = 33.0f/640.0f;
- dim.y = 33.0f/480.0f;
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*7.0f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, dim, 64+0, EVENT_OBJECT_RTANK);
-
- pos.x = ox+sx*8.0f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, dim, 64+1, EVENT_OBJECT_RFLY);
-
- pos.x = ox+sx*9.0f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, dim, 64+3, EVENT_OBJECT_RCANON);
-
- pos.x = ox+sx*10.0f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, dim, 64+4, EVENT_OBJECT_RTOWER);
-
- pos.x = ox+sx*7.0f;
- pos.y = oy+sy*0.0f;
- pw->CreateButton(pos, dim, 64+7, EVENT_OBJECT_RATOMIC);
-
- pos.x = ox+sx*8.0f;
- pos.y = oy+sy*0.0f;
- pw->CreateButton(pos, dim, 64+2, EVENT_OBJECT_RTHUMP);
-
- pos.x = ox+sx*9.0f;
- pos.y = oy+sy*0.0f;
- pw->CreateButton(pos, dim, 64+6, EVENT_OBJECT_RSHIELD);
-
- pos.x = ox+sx*10.0f;
- pos.y = oy+sy*0.0f;
- pw->CreateButton(pos, dim, 64+5, EVENT_OBJECT_RPHAZER);
-
- pos.x = ox+sx*14.5f;
- pos.y = oy+sy*0;
- ddim.x = 14.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 102, EVENT_OBJECT_TYPE);
-
- UpdateInterface();
-
- return true;
-}
-
-// Updates the status of all interface buttons.
-
-void CAutoResearch::UpdateInterface()
-{
- CWindow* pw;
-
- if ( !m_object->RetSelect() ) return;
-
- CAuto::UpdateInterface();
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- DeadInterface(pw, EVENT_OBJECT_RTANK, g_researchEnable&RESEARCH_TANK);
- DeadInterface(pw, EVENT_OBJECT_RFLY, g_researchEnable&RESEARCH_FLY);
- DeadInterface(pw, EVENT_OBJECT_RTHUMP, g_researchEnable&RESEARCH_THUMP);
- DeadInterface(pw, EVENT_OBJECT_RCANON, g_researchEnable&RESEARCH_CANON);
- DeadInterface(pw, EVENT_OBJECT_RTOWER, g_researchEnable&RESEARCH_TOWER);
- DeadInterface(pw, EVENT_OBJECT_RPHAZER, g_researchEnable&RESEARCH_PHAZER);
- DeadInterface(pw, EVENT_OBJECT_RSHIELD, g_researchEnable&RESEARCH_SHIELD);
- DeadInterface(pw, EVENT_OBJECT_RATOMIC, g_researchEnable&RESEARCH_ATOMIC);
-
- OkayButton(pw, EVENT_OBJECT_RTANK);
- OkayButton(pw, EVENT_OBJECT_RFLY);
- OkayButton(pw, EVENT_OBJECT_RTHUMP);
- OkayButton(pw, EVENT_OBJECT_RCANON);
- OkayButton(pw, EVENT_OBJECT_RTOWER);
- OkayButton(pw, EVENT_OBJECT_RPHAZER);
- OkayButton(pw, EVENT_OBJECT_RSHIELD);
- OkayButton(pw, EVENT_OBJECT_RATOMIC);
-
- VisibleInterface(pw, EVENT_OBJECT_RTANK, !m_bBusy);
- VisibleInterface(pw, EVENT_OBJECT_RFLY, !m_bBusy);
- VisibleInterface(pw, EVENT_OBJECT_RTHUMP, !m_bBusy);
- VisibleInterface(pw, EVENT_OBJECT_RCANON, !m_bBusy);
- VisibleInterface(pw, EVENT_OBJECT_RTOWER, !m_bBusy);
- VisibleInterface(pw, EVENT_OBJECT_RPHAZER, !m_bBusy);
- VisibleInterface(pw, EVENT_OBJECT_RSHIELD, !m_bBusy);
- VisibleInterface(pw, EVENT_OBJECT_RATOMIC, !m_bBusy);
-}
-
-// Updates the state of all buttons on the interface,
-// following the time that elapses ...
-
-void CAutoResearch::UpdateInterface(float rTime)
-{
- CWindow* pw;
- CGauge* pg;
- CObject* power;
- float energy;
-
- CAuto::UpdateInterface(rTime);
-
- if ( m_time < m_lastUpdateTime+0.1f ) return;
- m_lastUpdateTime = m_time;
-
- if ( !m_object->RetSelect() ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
- if ( pg != 0 )
- {
- energy = 0.0f;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- }
- pg->SetLevel(energy);
- }
-}
-
-// Research shows already performed button.
-
-void CAutoResearch::OkayButton(CWindow *pw, EventMsg event)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_OKAY, TestResearch(event));
-}
-
-
-// Test whether a search has already been done.
-
-bool CAutoResearch::TestResearch(EventMsg event)
-{
- if ( event == EVENT_OBJECT_RTANK ) return (g_researchDone & RESEARCH_TANK );
- if ( event == EVENT_OBJECT_RFLY ) return (g_researchDone & RESEARCH_FLY );
- if ( event == EVENT_OBJECT_RTHUMP ) return (g_researchDone & RESEARCH_THUMP );
- if ( event == EVENT_OBJECT_RCANON ) return (g_researchDone & RESEARCH_CANON );
- if ( event == EVENT_OBJECT_RTOWER ) return (g_researchDone & RESEARCH_TOWER );
- if ( event == EVENT_OBJECT_RPHAZER ) return (g_researchDone & RESEARCH_PHAZER );
- if ( event == EVENT_OBJECT_RSHIELD ) return (g_researchDone & RESEARCH_SHIELD);
- if ( event == EVENT_OBJECT_RATOMIC ) return (g_researchDone & RESEARCH_ATOMIC);
-
- return false;
-}
-
-// Indicates a search as made.
-
-void CAutoResearch::SetResearch(EventMsg event)
-{
- Event newEvent;
-
- if ( event == EVENT_OBJECT_RTANK ) g_researchDone |= RESEARCH_TANK;
- if ( event == EVENT_OBJECT_RFLY ) g_researchDone |= RESEARCH_FLY;
- if ( event == EVENT_OBJECT_RTHUMP ) g_researchDone |= RESEARCH_THUMP;
- if ( event == EVENT_OBJECT_RCANON ) g_researchDone |= RESEARCH_CANON;
- if ( event == EVENT_OBJECT_RTOWER ) g_researchDone |= RESEARCH_TOWER;
- if ( event == EVENT_OBJECT_RPHAZER ) g_researchDone |= RESEARCH_PHAZER;
- if ( event == EVENT_OBJECT_RSHIELD ) g_researchDone |= RESEARCH_SHIELD;
- if ( event == EVENT_OBJECT_RATOMIC ) g_researchDone |= RESEARCH_ATOMIC;
-
- m_main->WriteFreeParam();
-
- m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
- m_event->AddEvent(newEvent);
- UpdateInterface();
-}
-
-
-// Updates the stop lights.
-
-void CAutoResearch::FireStopUpdate(float progress, bool bLightOn)
-{
- Math::Matrix* mat;
- Math::Vector pos, speed;
- Math::Point dim;
- int i;
-
- static float listpos[12] =
- {
- 9.5f, 0.0f,
- 4.7f, 8.2f,
- -4.7f, 8.2f,
- -9.5f, 0.0f,
- -4.7f, -8.2f,
- 4.7f, -8.2f,
- };
-
- if ( !bLightOn ) // �teint ?
- {
- for ( i=0 ; i<6 ; i++ )
- {
- if ( m_partiStop[i] != -1 )
- {
- m_particule->DeleteParticule(m_partiStop[i]);
- m_partiStop[i] = -1;
- }
- }
- return;
- }
-
- mat = m_object->RetWorldMatrix(0);
-
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 2.0f;
- dim.y = dim.x;
-
- for ( i=0 ; i<6 ; i++ )
- {
- if ( Math::Mod(progress, 0.025f) < 0.005f )
- {
- if ( m_partiStop[i] != -1 )
- {
- m_particule->DeleteParticule(m_partiStop[i]);
- m_partiStop[i] = -1;
- }
- }
- else
- {
- if ( m_partiStop[i] == -1 )
- {
- pos.x = listpos[i*2+0];
- pos.y = 11.5f;
- pos.z = listpos[i*2+1];
- pos = Math::Transform(*mat, pos);
- m_partiStop[i] = m_particule->CreateParticule(pos, speed,
- dim, PARTISELY,
- 1.0f, 0.0f, 0.0f);
- }
- }
- }
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoResearch::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == ALP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- sprintf(name, " aResearch=%d", m_research);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoResearch::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoResearchPhase)OpInt(line, "aPhase", ALP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
- m_research = (EventMsg)OpInt(line, "aResearch", 0);
-
- m_lastUpdateTime = 0.0f;
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoresearch.h"
+
+#include "common/global.h"
+#include "math/geometry.h"
+#include "object/robotmain.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/gauge.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+
+
+
+const float SEARCH_TIME = 30.0f; // duration of a research
+
+
+
+// Object's constructor.
+
+CAutoResearch::CAutoResearch(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ int i;
+
+ for ( i=0 ; i<6 ; i++ )
+ {
+ m_partiStop[i] = -1;
+ }
+ m_channelSound = -1;
+
+ Init();
+}
+
+// Object's destructor.
+
+CAutoResearch::~CAutoResearch()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoResearch::DeleteObject(bool bAll)
+{
+ if ( m_channelSound != -1 )
+ {
+ m_sound->FlushEnvelope(m_channelSound);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_channelSound = -1;
+ }
+
+ FireStopUpdate(0.0f, false);
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoResearch::Init()
+{
+ m_phase = ALP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastUpdateTime = 0.0f;
+ m_lastParticule = 0.0f;
+}
+
+
+// Management of an event.
+
+bool CAutoResearch::EventProcess(const Event &event)
+{
+ CObject* power;
+ Math::Vector pos, speed;
+ Error message;
+ Math::Point dim;
+ float angle, time;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+
+ if ( event.event == EVENT_UPDINTERFACE )
+ {
+ if ( m_object->RetSelect() ) CreateInterface(true);
+ }
+
+ if ( m_object->RetSelect() && // center selected?
+ (event.event == EVENT_OBJECT_RTANK ||
+ event.event == EVENT_OBJECT_RFLY ||
+ event.event == EVENT_OBJECT_RTHUMP ||
+ event.event == EVENT_OBJECT_RCANON ||
+ event.event == EVENT_OBJECT_RTOWER ||
+ event.event == EVENT_OBJECT_RPHAZER ||
+ event.event == EVENT_OBJECT_RSHIELD ||
+ event.event == EVENT_OBJECT_RATOMIC ) )
+ {
+ if ( m_phase != ALP_WAIT )
+ {
+ return false;
+ }
+
+ m_research = event.event;
+
+ if ( TestResearch(m_research) )
+ {
+ m_displayText->DisplayError(ERR_RESEARCH_ALREADY, m_object);
+ return false;
+ }
+
+ power = m_object->RetPower();
+ if ( power == 0 )
+ {
+ m_displayText->DisplayError(ERR_RESEARCH_POWER, m_object);
+ return false;
+ }
+ if ( power->RetCapacity() > 1.0f )
+ {
+ m_displayText->DisplayError(ERR_RESEARCH_TYPE, m_object);
+ return false;
+ }
+ if ( power->RetEnergy() < 1.0f )
+ {
+ m_displayText->DisplayError(ERR_RESEARCH_ENERGY, m_object);
+ return false;
+ }
+
+ time = SEARCH_TIME;
+ if ( event.event == EVENT_OBJECT_RTANK ) time *= 0.3f;
+ if ( event.event == EVENT_OBJECT_RFLY ) time *= 0.3f;
+ if ( event.event == EVENT_OBJECT_RATOMIC ) time *= 2.0f;
+
+ SetBusy(true);
+ InitProgressTotal(time);
+ UpdateInterface();
+
+ m_channelSound = m_sound->Play(SOUND_RESEARCH, m_object->RetPosition(0), 0.0f, 1.0f, true);
+ m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_channelSound, 1.0f, 1.0f, time-4.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 2.0f, SOPER_STOP);
+
+ m_phase = ALP_SEARCH;
+ m_progress = 0.0f;
+ m_speed = 1.0f/time;
+ return true;
+ }
+
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+ }
+ return true;
+ }
+
+ UpdateInterface(event.rTime);
+ EventProgress(event.rTime);
+
+ angle = m_time*0.1f;
+ m_object->SetAngleY(1, angle); // rotates the antenna
+
+ angle = (30.0f+sinf(m_time*0.3f)*20.0f)*Math::PI/180.0f;
+ m_object->SetAngleZ(2, angle); // directs the antenna
+
+ if ( m_phase == ALP_WAIT )
+ {
+ FireStopUpdate(m_progress, false); // extinguished
+ return true;
+ }
+
+ if ( m_phase == ALP_SEARCH )
+ {
+ FireStopUpdate(m_progress, true); // flashes
+ if ( m_progress < 1.0f )
+ {
+ power = m_object->RetPower();
+ if ( power == 0 ) // more battery?
+ {
+ SetBusy(false);
+ UpdateInterface();
+
+ m_phase = ALP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ return true;
+ }
+ power->SetEnergy(1.0f-m_progress);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*6.0f;
+ pos.z += (Math::Rand()-0.5f)*6.0f;
+ pos.y += 11.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = Math::Rand()*20.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIVAPOR);
+ }
+ }
+ else
+ {
+ SetResearch(m_research); // research done
+ m_displayText->DisplayError(INFO_RESEARCH, m_object);
+
+ message = ERR_OK;
+ if ( m_research == EVENT_OBJECT_RTANK ) message = INFO_RESEARCHTANK;
+ if ( m_research == EVENT_OBJECT_RFLY ) message = INFO_RESEARCHFLY;
+ if ( m_research == EVENT_OBJECT_RTHUMP ) message = INFO_RESEARCHTHUMP;
+ if ( m_research == EVENT_OBJECT_RCANON ) message = INFO_RESEARCHCANON;
+ if ( m_research == EVENT_OBJECT_RTOWER ) message = INFO_RESEARCHTOWER;
+ if ( m_research == EVENT_OBJECT_RPHAZER ) message = INFO_RESEARCHPHAZER;
+ if ( m_research == EVENT_OBJECT_RSHIELD ) message = INFO_RESEARCHSHIELD;
+ if ( m_research == EVENT_OBJECT_RATOMIC ) message = INFO_RESEARCHATOMIC;
+ if ( message != ERR_OK )
+ {
+ m_displayText->DisplayError(message, m_object);
+ }
+
+ SetBusy(false);
+ UpdateInterface();
+
+ m_phase = ALP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoResearch::RetError()
+{
+ CObject* power;
+
+ if ( m_phase == ALP_SEARCH )
+ {
+ return ERR_OK;
+ }
+
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ power = m_object->RetPower();
+ if ( power == 0 )
+ {
+ return ERR_RESEARCH_POWER;
+ }
+ if ( power != 0 && power->RetCapacity() > 1.0f )
+ {
+ return ERR_RESEARCH_TYPE;
+ }
+ if ( power != 0 && power->RetEnergy() < 1.0f )
+ {
+ return ERR_RESEARCH_ENERGY;
+ }
+
+ return ERR_OK;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoResearch::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, dim, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ dim.x = 33.0f/640.0f;
+ dim.y = 33.0f/480.0f;
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*7.0f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, dim, 64+0, EVENT_OBJECT_RTANK);
+
+ pos.x = ox+sx*8.0f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, dim, 64+1, EVENT_OBJECT_RFLY);
+
+ pos.x = ox+sx*9.0f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, dim, 64+3, EVENT_OBJECT_RCANON);
+
+ pos.x = ox+sx*10.0f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, dim, 64+4, EVENT_OBJECT_RTOWER);
+
+ pos.x = ox+sx*7.0f;
+ pos.y = oy+sy*0.0f;
+ pw->CreateButton(pos, dim, 64+7, EVENT_OBJECT_RATOMIC);
+
+ pos.x = ox+sx*8.0f;
+ pos.y = oy+sy*0.0f;
+ pw->CreateButton(pos, dim, 64+2, EVENT_OBJECT_RTHUMP);
+
+ pos.x = ox+sx*9.0f;
+ pos.y = oy+sy*0.0f;
+ pw->CreateButton(pos, dim, 64+6, EVENT_OBJECT_RSHIELD);
+
+ pos.x = ox+sx*10.0f;
+ pos.y = oy+sy*0.0f;
+ pw->CreateButton(pos, dim, 64+5, EVENT_OBJECT_RPHAZER);
+
+ pos.x = ox+sx*14.5f;
+ pos.y = oy+sy*0;
+ ddim.x = 14.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 102, EVENT_OBJECT_TYPE);
+
+ UpdateInterface();
+
+ return true;
+}
+
+// Updates the status of all interface buttons.
+
+void CAutoResearch::UpdateInterface()
+{
+ CWindow* pw;
+
+ if ( !m_object->RetSelect() ) return;
+
+ CAuto::UpdateInterface();
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ DeadInterface(pw, EVENT_OBJECT_RTANK, g_researchEnable&RESEARCH_TANK);
+ DeadInterface(pw, EVENT_OBJECT_RFLY, g_researchEnable&RESEARCH_FLY);
+ DeadInterface(pw, EVENT_OBJECT_RTHUMP, g_researchEnable&RESEARCH_THUMP);
+ DeadInterface(pw, EVENT_OBJECT_RCANON, g_researchEnable&RESEARCH_CANON);
+ DeadInterface(pw, EVENT_OBJECT_RTOWER, g_researchEnable&RESEARCH_TOWER);
+ DeadInterface(pw, EVENT_OBJECT_RPHAZER, g_researchEnable&RESEARCH_PHAZER);
+ DeadInterface(pw, EVENT_OBJECT_RSHIELD, g_researchEnable&RESEARCH_SHIELD);
+ DeadInterface(pw, EVENT_OBJECT_RATOMIC, g_researchEnable&RESEARCH_ATOMIC);
+
+ OkayButton(pw, EVENT_OBJECT_RTANK);
+ OkayButton(pw, EVENT_OBJECT_RFLY);
+ OkayButton(pw, EVENT_OBJECT_RTHUMP);
+ OkayButton(pw, EVENT_OBJECT_RCANON);
+ OkayButton(pw, EVENT_OBJECT_RTOWER);
+ OkayButton(pw, EVENT_OBJECT_RPHAZER);
+ OkayButton(pw, EVENT_OBJECT_RSHIELD);
+ OkayButton(pw, EVENT_OBJECT_RATOMIC);
+
+ VisibleInterface(pw, EVENT_OBJECT_RTANK, !m_bBusy);
+ VisibleInterface(pw, EVENT_OBJECT_RFLY, !m_bBusy);
+ VisibleInterface(pw, EVENT_OBJECT_RTHUMP, !m_bBusy);
+ VisibleInterface(pw, EVENT_OBJECT_RCANON, !m_bBusy);
+ VisibleInterface(pw, EVENT_OBJECT_RTOWER, !m_bBusy);
+ VisibleInterface(pw, EVENT_OBJECT_RPHAZER, !m_bBusy);
+ VisibleInterface(pw, EVENT_OBJECT_RSHIELD, !m_bBusy);
+ VisibleInterface(pw, EVENT_OBJECT_RATOMIC, !m_bBusy);
+}
+
+// Updates the state of all buttons on the interface,
+// following the time that elapses ...
+
+void CAutoResearch::UpdateInterface(float rTime)
+{
+ CWindow* pw;
+ CGauge* pg;
+ CObject* power;
+ float energy;
+
+ CAuto::UpdateInterface(rTime);
+
+ if ( m_time < m_lastUpdateTime+0.1f ) return;
+ m_lastUpdateTime = m_time;
+
+ if ( !m_object->RetSelect() ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
+ if ( pg != 0 )
+ {
+ energy = 0.0f;
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ }
+ pg->SetLevel(energy);
+ }
+}
+
+// Research shows already performed button.
+
+void CAutoResearch::OkayButton(CWindow *pw, EventMsg event)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_OKAY, TestResearch(event));
+}
+
+
+// Test whether a search has already been done.
+
+bool CAutoResearch::TestResearch(EventMsg event)
+{
+ if ( event == EVENT_OBJECT_RTANK ) return (g_researchDone & RESEARCH_TANK );
+ if ( event == EVENT_OBJECT_RFLY ) return (g_researchDone & RESEARCH_FLY );
+ if ( event == EVENT_OBJECT_RTHUMP ) return (g_researchDone & RESEARCH_THUMP );
+ if ( event == EVENT_OBJECT_RCANON ) return (g_researchDone & RESEARCH_CANON );
+ if ( event == EVENT_OBJECT_RTOWER ) return (g_researchDone & RESEARCH_TOWER );
+ if ( event == EVENT_OBJECT_RPHAZER ) return (g_researchDone & RESEARCH_PHAZER );
+ if ( event == EVENT_OBJECT_RSHIELD ) return (g_researchDone & RESEARCH_SHIELD);
+ if ( event == EVENT_OBJECT_RATOMIC ) return (g_researchDone & RESEARCH_ATOMIC);
+
+ return false;
+}
+
+// Indicates a search as made.
+
+void CAutoResearch::SetResearch(EventMsg event)
+{
+ Event newEvent;
+
+ if ( event == EVENT_OBJECT_RTANK ) g_researchDone |= RESEARCH_TANK;
+ if ( event == EVENT_OBJECT_RFLY ) g_researchDone |= RESEARCH_FLY;
+ if ( event == EVENT_OBJECT_RTHUMP ) g_researchDone |= RESEARCH_THUMP;
+ if ( event == EVENT_OBJECT_RCANON ) g_researchDone |= RESEARCH_CANON;
+ if ( event == EVENT_OBJECT_RTOWER ) g_researchDone |= RESEARCH_TOWER;
+ if ( event == EVENT_OBJECT_RPHAZER ) g_researchDone |= RESEARCH_PHAZER;
+ if ( event == EVENT_OBJECT_RSHIELD ) g_researchDone |= RESEARCH_SHIELD;
+ if ( event == EVENT_OBJECT_RATOMIC ) g_researchDone |= RESEARCH_ATOMIC;
+
+ m_main->WriteFreeParam();
+
+ m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
+ m_event->AddEvent(newEvent);
+ UpdateInterface();
+}
+
+
+// Updates the stop lights.
+
+void CAutoResearch::FireStopUpdate(float progress, bool bLightOn)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ int i;
+
+ static float listpos[12] =
+ {
+ 9.5f, 0.0f,
+ 4.7f, 8.2f,
+ -4.7f, 8.2f,
+ -9.5f, 0.0f,
+ -4.7f, -8.2f,
+ 4.7f, -8.2f,
+ };
+
+ if ( !bLightOn ) // �teint ?
+ {
+ for ( i=0 ; i<6 ; i++ )
+ {
+ if ( m_partiStop[i] != -1 )
+ {
+ m_particule->DeleteParticule(m_partiStop[i]);
+ m_partiStop[i] = -1;
+ }
+ }
+ return;
+ }
+
+ mat = m_object->RetWorldMatrix(0);
+
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 2.0f;
+ dim.y = dim.x;
+
+ for ( i=0 ; i<6 ; i++ )
+ {
+ if ( Math::Mod(progress, 0.025f) < 0.005f )
+ {
+ if ( m_partiStop[i] != -1 )
+ {
+ m_particule->DeleteParticule(m_partiStop[i]);
+ m_partiStop[i] = -1;
+ }
+ }
+ else
+ {
+ if ( m_partiStop[i] == -1 )
+ {
+ pos.x = listpos[i*2+0];
+ pos.y = 11.5f;
+ pos.z = listpos[i*2+1];
+ pos = Math::Transform(*mat, pos);
+ m_partiStop[i] = m_particule->CreateParticule(pos, speed,
+ dim, PARTISELY,
+ 1.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoResearch::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == ALP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ sprintf(name, " aResearch=%d", m_research);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoResearch::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoResearchPhase)OpInt(line, "aPhase", ALP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+ m_research = (EventMsg)OpInt(line, "aResearch", 0);
+
+ m_lastUpdateTime = 0.0f;
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autoresearch.h b/src/object/auto/autoresearch.h
index c36edd6..b60f4bd 100644
--- a/src/object/auto/autoresearch.h
+++ b/src/object/auto/autoresearch.h
@@ -1,70 +1,70 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoresearch.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoResearchPhase
-{
- ALP_WAIT = 1,
- ALP_SEARCH = 2, // research in progress
-};
-
-
-
-class CAutoResearch : public CAuto
-{
-public:
- CAutoResearch(CInstanceManager* iMan, CObject* object);
- ~CAutoResearch();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- void UpdateInterface();
- void UpdateInterface(float rTime);
- void OkayButton(CWindow *pw, EventMsg event);
- bool TestResearch(EventMsg event);
- void SetResearch(EventMsg event);
- void FireStopUpdate(float progress, bool bLightOn);
-
-protected:
- AutoResearchPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastUpdateTime;
- float m_lastParticule;
- EventMsg m_research;
- int m_partiStop[6];
- int m_channelSound;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoresearch.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoResearchPhase
+{
+ ALP_WAIT = 1,
+ ALP_SEARCH = 2, // research in progress
+};
+
+
+
+class CAutoResearch : public CAuto
+{
+public:
+ CAutoResearch(CInstanceManager* iMan, CObject* object);
+ ~CAutoResearch();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ void UpdateInterface();
+ void UpdateInterface(float rTime);
+ void OkayButton(CWindow *pw, EventMsg event);
+ bool TestResearch(EventMsg event);
+ void SetResearch(EventMsg event);
+ void FireStopUpdate(float progress, bool bLightOn);
+
+protected:
+ AutoResearchPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastUpdateTime;
+ float m_lastParticule;
+ EventMsg m_research;
+ int m_partiStop[6];
+ int m_channelSound;
+};
+
diff --git a/src/object/auto/autoroot.cpp b/src/object/auto/autoroot.cpp
index cd3435e..9282a01 100644
--- a/src/object/auto/autoroot.cpp
+++ b/src/object/auto/autoroot.cpp
@@ -1,120 +1,120 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autoroot.h"
-
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "math/geometry.h"
-
-
-
-
-// Object's constructor.
-
-CAutoRoot::CAutoRoot(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
-}
-
-// Object's destructor.
-
-CAutoRoot::~CAutoRoot()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoRoot::DeleteObject(bool bAll)
-{
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoRoot::Init()
-{
- Math::Matrix* mat;
- Math::Vector pos, speed;
- Math::Point dim;
-
- m_time = 0.0f;
- m_lastParticule = 0.0f;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(-5.0f, 28.0f, -4.0f); // peak position
- pos = Math::Transform(*mat, pos);
- m_center = pos;
-
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 100.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(m_center, speed, dim, PARTISPHERE5, 0.5f, 0.0f, 0.0f);
-
- m_terrain->AddFlyingLimit(pos, 100.0f, 80.0f, pos.y-60.0f);
-}
-
-
-// Management of an event.
-
-bool CAutoRoot::EventProcess(const Event &event)
-{
- Math::Vector pos, speed;
- Math::Point dim;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_object->SetZoomX(1, 1.0f+sinf(m_time*2.0f)*0.2f);
- m_object->SetZoomY(1, 1.0f+sinf(m_time*2.3f)*0.2f);
- m_object->SetZoomZ(1, 1.0f+sinf(m_time*2.7f)*0.2f);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_center;
- pos.x += (Math::Rand()-0.5f)*8.0f;
- pos.z += (Math::Rand()-0.5f)*8.0f;
- pos.y += 0.0f;
- speed.x = (Math::Rand()-0.5f)*12.0f;
- speed.z = (Math::Rand()-0.5f)*12.0f;
- speed.y = Math::Rand()*12.0f;
- dim.x = Math::Rand()*6.0f+4.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIROOT, 1.0f, 0.0f, 0.0f);
- }
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoRoot::RetError()
-{
- return ERR_OK;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autoroot.h"
+
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "math/geometry.h"
+
+
+
+
+// Object's constructor.
+
+CAutoRoot::CAutoRoot(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+}
+
+// Object's destructor.
+
+CAutoRoot::~CAutoRoot()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoRoot::DeleteObject(bool bAll)
+{
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoRoot::Init()
+{
+ Math::Matrix* mat;
+ Math::Vector pos, speed;
+ Math::Point dim;
+
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(-5.0f, 28.0f, -4.0f); // peak position
+ pos = Math::Transform(*mat, pos);
+ m_center = pos;
+
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 100.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(m_center, speed, dim, PARTISPHERE5, 0.5f, 0.0f, 0.0f);
+
+ m_terrain->AddFlyingLimit(pos, 100.0f, 80.0f, pos.y-60.0f);
+}
+
+
+// Management of an event.
+
+bool CAutoRoot::EventProcess(const Event &event)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_object->SetZoomX(1, 1.0f+sinf(m_time*2.0f)*0.2f);
+ m_object->SetZoomY(1, 1.0f+sinf(m_time*2.3f)*0.2f);
+ m_object->SetZoomZ(1, 1.0f+sinf(m_time*2.7f)*0.2f);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_center;
+ pos.x += (Math::Rand()-0.5f)*8.0f;
+ pos.z += (Math::Rand()-0.5f)*8.0f;
+ pos.y += 0.0f;
+ speed.x = (Math::Rand()-0.5f)*12.0f;
+ speed.z = (Math::Rand()-0.5f)*12.0f;
+ speed.y = Math::Rand()*12.0f;
+ dim.x = Math::Rand()*6.0f+4.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIROOT, 1.0f, 0.0f, 0.0f);
+ }
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoRoot::RetError()
+{
+ return ERR_OK;
+}
+
+
diff --git a/src/object/auto/autoroot.h b/src/object/auto/autoroot.h
index 8bf397d..1ecd5ba 100644
--- a/src/object/auto/autoroot.h
+++ b/src/object/auto/autoroot.h
@@ -1,44 +1,44 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autoroot.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-class CAutoRoot : public CAuto
-{
-public:
- CAutoRoot(CInstanceManager* iMan, CObject* object);
- ~CAutoRoot();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
-protected:
-
-protected:
- float m_lastParticule;
- Math::Vector m_center;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autoroot.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+class CAutoRoot : public CAuto
+{
+public:
+ CAutoRoot(CInstanceManager* iMan, CObject* object);
+ ~CAutoRoot();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+protected:
+
+protected:
+ float m_lastParticule;
+ Math::Vector m_center;
+};
+
diff --git a/src/object/auto/autosafe.cpp b/src/object/auto/autosafe.cpp
index 6965851..11aac18 100644
--- a/src/object/auto/autosafe.cpp
+++ b/src/object/auto/autosafe.cpp
@@ -1,612 +1,612 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autosafe.h"
-
-#include "common/iman.h"
-#include "math/geometry.h"
-#include "object/robotmain.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/window.h"
-
-
-const float OPEN_DELAY = 8.0f; // duration of opening
-
-
-// Object's constructor.
-
-CAutoSafe::CAutoSafe(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- int i;
-
- for ( i=0 ; i<4 ; i++ )
- {
- m_bKey[i] = false;
- m_keyParti[i] = -1;
- }
-
- m_bLock = false;
- m_lastParticule = 0.0f;
- m_channelSound = -1;
- Init();
-}
-
-// Object's destructor.
-
-CAutoSafe::~CAutoSafe()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoSafe::DeleteObject(bool bAll)
-{
- CObject* pObj;
-
- pObj = SearchVehicle();
- if ( pObj != 0 )
- {
- pObj->DeleteObject();
- delete pObj;
- }
-
- if ( m_channelSound != -1 )
- {
- m_sound->FlushEnvelope(m_channelSound);
- m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_channelSound = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoSafe::Init()
-{
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastParticule = 0.0f;
-
- m_countKeys = 0;
- m_actualAngle = 0.0f;
- m_finalAngle = 0.0f;
-
- m_phase = ASAP_WAIT; // waiting ...
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoSafe::EventProcess(const Event &event)
-{
- CObject* pObj;
- Math::Vector pos, speed;
- Math::Point dim;
- int i, count;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
- }
- return true;
- }
-
- EventProgress(event.rTime);
-
- if ( !m_bLock )
- {
- pObj = SearchVehicle();
- if ( pObj != 0 )
- {
- pObj->SetLock(true); // object not yet usable
- m_main->CreateShortcuts();
- m_bLock = true;
- }
- }
-
- if ( m_phase == ASAP_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
- count = CountKeys(); // count these key
- if ( count != m_countKeys )
- {
- m_countKeys = count;
-
- if ( count == 0 ) m_finalAngle = 0.0f*Math::PI/180.0f;
- if ( count == 1 ) m_finalAngle = 5.0f*Math::PI/180.0f;
- if ( count == 2 ) m_finalAngle = 10.0f*Math::PI/180.0f;
- if ( count == 3 ) m_finalAngle = 15.0f*Math::PI/180.0f;
- if ( count == 4 ) m_finalAngle = 120.0f*Math::PI/180.0f;
-
- if ( count == 4 ) // all the keys?
- {
- LockKeys();
-
- m_channelSound = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 1.0f, 0.25f, true);
- m_sound->AddEnvelope(m_channelSound, 1.0f, 2.00f, OPEN_DELAY, SOPER_STOP);
-
- m_phase = ASAP_OPEN;
- m_progress = 0.0f;
- m_speed = 1.0f/OPEN_DELAY;
- return true;
- }
- else
- {
- m_channelSound = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 1.0f, 0.25f, true);
- m_sound->AddEnvelope(m_channelSound, 1.0f, 0.35f, 0.5f, SOPER_STOP);
- }
- }
-
- m_phase = ASAP_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ASAP_OPEN )
- {
- if ( m_progress < 1.0f )
- {
- DownKeys(m_progress);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- for ( i=0 ; i<10 ; i++ )
- {
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- speed.x = (Math::Rand()-0.5f)*4.0f;
- speed.z = (Math::Rand()-0.5f)*4.0f;
- speed.y = Math::Rand()*15.0f;
- dim.x = Math::Rand()*6.0f+4.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
- }
-
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- speed.x = (Math::Rand()-0.5f)*4.0f;
- speed.z = (Math::Rand()-0.5f)*4.0f;
- speed.y = Math::Rand()*10.0f;
- dim.x = Math::Rand()*3.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 1.0f, 0.0f, 0.0f);
-
- for ( i=0 ; i<4 ; i++ )
- {
- pos = m_keyPos[i];
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = 1.0f+Math::Rand()*1.0f;
- dim.x = Math::Rand()*1.5f+1.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 0.0f);
- }
- }
- }
- else
- {
- DeleteKeys();
-
- pObj = SearchVehicle();
- if ( pObj != 0 )
- {
- pObj->SetLock(false); // object usable
- m_main->CreateShortcuts();
- }
-
- m_object->FlushCrashShere();
- m_object->SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 0.0f);
-
- m_sound->Play(SOUND_FINDING, m_object->RetPosition(0));
-
- m_phase = ASAP_FINISH;
- m_progress = 0.0f;
- m_speed = 1.0f/100.0f;
- }
- }
-
- if ( m_phase == ASAP_FINISH )
- {
- if ( m_progress >= 1.0f )
- {
- m_phase = ASAP_FINISH;
- m_progress = 0.0f;
- m_speed = 1.0f/100.0f;
- }
- }
-
- // Opens or closes the doors.
- if ( m_actualAngle != m_finalAngle )
- {
- if ( m_actualAngle < m_finalAngle )
- {
- m_actualAngle += (105.0f*Math::PI/180.0f)*event.rTime/OPEN_DELAY;
- if ( m_actualAngle > m_finalAngle ) m_actualAngle = m_finalAngle;
- }
- else
- {
- m_actualAngle -= (105.0f*Math::PI/180.0f)*event.rTime/OPEN_DELAY;
- if ( m_actualAngle < m_finalAngle ) m_actualAngle = m_finalAngle;
- }
- m_object->SetAngleZ(1, m_actualAngle);
- m_object->SetAngleZ(2, -m_actualAngle);
- }
-
- // Blinks the keys.
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 2.0f;
- dim.y = dim.x;
- for ( i=0 ; i<4 ; i++ )
- {
- if ( m_phase != ASAP_WAIT || !m_bKey[i] || Math::Mod(m_time, 1.0f) < 0.4f )
- {
- if ( m_keyParti[i] != -1 )
- {
- m_particule->DeleteParticule(m_keyParti[i]);
- m_keyParti[i] = -1;
- }
- }
- else
- {
- if ( m_keyParti[i] == -1 )
- {
- pos = m_keyPos[i];
- pos.y += 2.2f;
- m_keyParti[i] = m_particule->CreateParticule(pos, speed, dim, PARTISELY, 1.0f, 0.0f, 0.0f);
- }
- }
- }
-
- return true;
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoSafe::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 114, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoSafe::RetError()
-{
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
- return ERR_OK;
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoSafe::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == ASAP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoSafe::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoSafePhase)OpInt(line, "aPhase", ASAP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
-
- m_lastParticule = 0.0f;
-
- return true;
-}
-
-
-// Counts the number of keys
-
-int CAutoSafe::CountKeys()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- Math::Point rot;
- ObjectType oType;
- float dist, angle, limit, cAngle, oAngle;
- int i, index;
-
- cPos = m_object->RetPosition(0);
- cAngle = m_object->RetAngleY(0);
-
- for ( index=0 ; index<4 ; index++ )
- {
- m_bKey[index] = false;
- m_keyPos[index] = cPos;
- }
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( pObj->RetTruck() != 0 ) continue;
-
- if ( oType != OBJECT_KEYa &&
- oType != OBJECT_KEYb &&
- oType != OBJECT_KEYc &&
- oType != OBJECT_KEYd ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, cPos);
- if ( dist > 20.0f ) continue;
-
- if ( oType == OBJECT_KEYa )
- {
- limit = Math::PI*1.0f;
- oAngle = Math::PI*0.0f;
- index = 0;
- }
- if ( oType == OBJECT_KEYb )
- {
- limit = Math::PI*0.0f;
- oAngle = Math::PI*1.0f;
- index = 1;
- }
- if ( oType == OBJECT_KEYc )
- {
- limit = Math::PI*1.5f;
- oAngle = Math::PI*0.5f;
- index = 2;
- }
- if ( oType == OBJECT_KEYd )
- {
- limit = Math::PI*0.5f;
- oAngle = Math::PI*0.0f;
- index = 3;
- }
-
- angle = Math::RotateAngle(oPos.x-cPos.x, oPos.z-cPos.z)+cAngle;
- if ( !Math::TestAngle(angle, limit-8.0f*Math::PI/180.0f, limit+8.0f*Math::PI/180.0f) ) continue;
-
- // Key changes the shape of the base.
- rot = Math::RotatePoint(Math::Point(cPos.x, cPos.z), limit-cAngle, Math::Point(cPos.x+16.0f, cPos.z));
- oPos.x = rot.x;
- oPos.z = rot.y;
- oPos.y = cPos.y+1.0f;
- pObj->SetPosition(0, oPos);
- pObj->SetAngleY(0, oAngle+cAngle);
- m_keyPos[index] = oPos;
-
- m_bKey[index] = true;
- }
-
- i = 0;
- for ( index=0 ; index<4 ; index++ )
- {
- if ( m_bKey[index] ) i++;
- }
- return i;
-}
-
-// Blocks all keys.
-
-void CAutoSafe::LockKeys()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType oType;
- float dist;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( pObj->RetTruck() != 0 ) continue;
-
- if ( oType != OBJECT_KEYa &&
- oType != OBJECT_KEYb &&
- oType != OBJECT_KEYc &&
- oType != OBJECT_KEYd ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, cPos);
- if ( dist > 20.0f ) continue;
-
- pObj->SetLock(true);
- }
-}
-
-// Sent down all the keys.
-
-void CAutoSafe::DownKeys(float progress)
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType oType;
- float dist;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( pObj->RetTruck() != 0 ) continue;
-
- if ( oType != OBJECT_KEYa &&
- oType != OBJECT_KEYb &&
- oType != OBJECT_KEYc &&
- oType != OBJECT_KEYd ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, cPos);
- if ( dist > 20.0f ) continue;
-
- oPos.y = cPos.y+1.0f-progress*2.2f;
- pObj->SetPosition(0, oPos);
- }
-}
-
-// Delete all the keys.
-
-void CAutoSafe::DeleteKeys()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType oType;
- float dist;
- int i;
- bool bDelete;
-
- cPos = m_object->RetPosition(0);
-
- do
- {
- bDelete = false;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( pObj->RetTruck() != 0 ) continue;
-
- if ( oType != OBJECT_KEYa &&
- oType != OBJECT_KEYb &&
- oType != OBJECT_KEYc &&
- oType != OBJECT_KEYd ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, cPos);
- if ( dist > 20.0f ) continue;
-
- pObj->DeleteObject();
- delete pObj;
- bDelete = true;
- }
- }
- while ( bDelete );
-}
-
-// Seeking a vehicle in the safe.
-
-CObject* CAutoSafe::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector cPos, oPos;
- ObjectType oType;
- float dist;
- int i;
-
- cPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( pObj == m_object ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, cPos);
- if ( dist <= 4.0f ) return pObj;
- }
- return 0;
-}
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autosafe.h"
+
+#include "common/iman.h"
+#include "math/geometry.h"
+#include "object/robotmain.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/window.h"
+
+
+const float OPEN_DELAY = 8.0f; // duration of opening
+
+
+// Object's constructor.
+
+CAutoSafe::CAutoSafe(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ int i;
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ m_bKey[i] = false;
+ m_keyParti[i] = -1;
+ }
+
+ m_bLock = false;
+ m_lastParticule = 0.0f;
+ m_channelSound = -1;
+ Init();
+}
+
+// Object's destructor.
+
+CAutoSafe::~CAutoSafe()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoSafe::DeleteObject(bool bAll)
+{
+ CObject* pObj;
+
+ pObj = SearchVehicle();
+ if ( pObj != 0 )
+ {
+ pObj->DeleteObject();
+ delete pObj;
+ }
+
+ if ( m_channelSound != -1 )
+ {
+ m_sound->FlushEnvelope(m_channelSound);
+ m_sound->AddEnvelope(m_channelSound, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_channelSound = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoSafe::Init()
+{
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastParticule = 0.0f;
+
+ m_countKeys = 0;
+ m_actualAngle = 0.0f;
+ m_finalAngle = 0.0f;
+
+ m_phase = ASAP_WAIT; // waiting ...
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoSafe::EventProcess(const Event &event)
+{
+ CObject* pObj;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ int i, count;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+ }
+ return true;
+ }
+
+ EventProgress(event.rTime);
+
+ if ( !m_bLock )
+ {
+ pObj = SearchVehicle();
+ if ( pObj != 0 )
+ {
+ pObj->SetLock(true); // object not yet usable
+ m_main->CreateShortcuts();
+ m_bLock = true;
+ }
+ }
+
+ if ( m_phase == ASAP_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ count = CountKeys(); // count these key
+ if ( count != m_countKeys )
+ {
+ m_countKeys = count;
+
+ if ( count == 0 ) m_finalAngle = 0.0f*Math::PI/180.0f;
+ if ( count == 1 ) m_finalAngle = 5.0f*Math::PI/180.0f;
+ if ( count == 2 ) m_finalAngle = 10.0f*Math::PI/180.0f;
+ if ( count == 3 ) m_finalAngle = 15.0f*Math::PI/180.0f;
+ if ( count == 4 ) m_finalAngle = 120.0f*Math::PI/180.0f;
+
+ if ( count == 4 ) // all the keys?
+ {
+ LockKeys();
+
+ m_channelSound = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 1.0f, 0.25f, true);
+ m_sound->AddEnvelope(m_channelSound, 1.0f, 2.00f, OPEN_DELAY, SOPER_STOP);
+
+ m_phase = ASAP_OPEN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/OPEN_DELAY;
+ return true;
+ }
+ else
+ {
+ m_channelSound = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 1.0f, 0.25f, true);
+ m_sound->AddEnvelope(m_channelSound, 1.0f, 0.35f, 0.5f, SOPER_STOP);
+ }
+ }
+
+ m_phase = ASAP_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ASAP_OPEN )
+ {
+ if ( m_progress < 1.0f )
+ {
+ DownKeys(m_progress);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ speed.x = (Math::Rand()-0.5f)*4.0f;
+ speed.z = (Math::Rand()-0.5f)*4.0f;
+ speed.y = Math::Rand()*15.0f;
+ dim.x = Math::Rand()*6.0f+4.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
+ }
+
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ speed.x = (Math::Rand()-0.5f)*4.0f;
+ speed.z = (Math::Rand()-0.5f)*4.0f;
+ speed.y = Math::Rand()*10.0f;
+ dim.x = Math::Rand()*3.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 1.0f, 0.0f, 0.0f);
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ pos = m_keyPos[i];
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = 1.0f+Math::Rand()*1.0f;
+ dim.x = Math::Rand()*1.5f+1.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+ else
+ {
+ DeleteKeys();
+
+ pObj = SearchVehicle();
+ if ( pObj != 0 )
+ {
+ pObj->SetLock(false); // object usable
+ m_main->CreateShortcuts();
+ }
+
+ m_object->FlushCrashShere();
+ m_object->SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 0.0f);
+
+ m_sound->Play(SOUND_FINDING, m_object->RetPosition(0));
+
+ m_phase = ASAP_FINISH;
+ m_progress = 0.0f;
+ m_speed = 1.0f/100.0f;
+ }
+ }
+
+ if ( m_phase == ASAP_FINISH )
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_phase = ASAP_FINISH;
+ m_progress = 0.0f;
+ m_speed = 1.0f/100.0f;
+ }
+ }
+
+ // Opens or closes the doors.
+ if ( m_actualAngle != m_finalAngle )
+ {
+ if ( m_actualAngle < m_finalAngle )
+ {
+ m_actualAngle += (105.0f*Math::PI/180.0f)*event.rTime/OPEN_DELAY;
+ if ( m_actualAngle > m_finalAngle ) m_actualAngle = m_finalAngle;
+ }
+ else
+ {
+ m_actualAngle -= (105.0f*Math::PI/180.0f)*event.rTime/OPEN_DELAY;
+ if ( m_actualAngle < m_finalAngle ) m_actualAngle = m_finalAngle;
+ }
+ m_object->SetAngleZ(1, m_actualAngle);
+ m_object->SetAngleZ(2, -m_actualAngle);
+ }
+
+ // Blinks the keys.
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 2.0f;
+ dim.y = dim.x;
+ for ( i=0 ; i<4 ; i++ )
+ {
+ if ( m_phase != ASAP_WAIT || !m_bKey[i] || Math::Mod(m_time, 1.0f) < 0.4f )
+ {
+ if ( m_keyParti[i] != -1 )
+ {
+ m_particule->DeleteParticule(m_keyParti[i]);
+ m_keyParti[i] = -1;
+ }
+ }
+ else
+ {
+ if ( m_keyParti[i] == -1 )
+ {
+ pos = m_keyPos[i];
+ pos.y += 2.2f;
+ m_keyParti[i] = m_particule->CreateParticule(pos, speed, dim, PARTISELY, 1.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+
+ return true;
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoSafe::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 114, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoSafe::RetError()
+{
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+ return ERR_OK;
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoSafe::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == ASAP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoSafe::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoSafePhase)OpInt(line, "aPhase", ASAP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+
+ m_lastParticule = 0.0f;
+
+ return true;
+}
+
+
+// Counts the number of keys
+
+int CAutoSafe::CountKeys()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ Math::Point rot;
+ ObjectType oType;
+ float dist, angle, limit, cAngle, oAngle;
+ int i, index;
+
+ cPos = m_object->RetPosition(0);
+ cAngle = m_object->RetAngleY(0);
+
+ for ( index=0 ; index<4 ; index++ )
+ {
+ m_bKey[index] = false;
+ m_keyPos[index] = cPos;
+ }
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ if ( oType != OBJECT_KEYa &&
+ oType != OBJECT_KEYb &&
+ oType != OBJECT_KEYc &&
+ oType != OBJECT_KEYd ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, cPos);
+ if ( dist > 20.0f ) continue;
+
+ if ( oType == OBJECT_KEYa )
+ {
+ limit = Math::PI*1.0f;
+ oAngle = Math::PI*0.0f;
+ index = 0;
+ }
+ if ( oType == OBJECT_KEYb )
+ {
+ limit = Math::PI*0.0f;
+ oAngle = Math::PI*1.0f;
+ index = 1;
+ }
+ if ( oType == OBJECT_KEYc )
+ {
+ limit = Math::PI*1.5f;
+ oAngle = Math::PI*0.5f;
+ index = 2;
+ }
+ if ( oType == OBJECT_KEYd )
+ {
+ limit = Math::PI*0.5f;
+ oAngle = Math::PI*0.0f;
+ index = 3;
+ }
+
+ angle = Math::RotateAngle(oPos.x-cPos.x, oPos.z-cPos.z)+cAngle;
+ if ( !Math::TestAngle(angle, limit-8.0f*Math::PI/180.0f, limit+8.0f*Math::PI/180.0f) ) continue;
+
+ // Key changes the shape of the base.
+ rot = Math::RotatePoint(Math::Point(cPos.x, cPos.z), limit-cAngle, Math::Point(cPos.x+16.0f, cPos.z));
+ oPos.x = rot.x;
+ oPos.z = rot.y;
+ oPos.y = cPos.y+1.0f;
+ pObj->SetPosition(0, oPos);
+ pObj->SetAngleY(0, oAngle+cAngle);
+ m_keyPos[index] = oPos;
+
+ m_bKey[index] = true;
+ }
+
+ i = 0;
+ for ( index=0 ; index<4 ; index++ )
+ {
+ if ( m_bKey[index] ) i++;
+ }
+ return i;
+}
+
+// Blocks all keys.
+
+void CAutoSafe::LockKeys()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType oType;
+ float dist;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ if ( oType != OBJECT_KEYa &&
+ oType != OBJECT_KEYb &&
+ oType != OBJECT_KEYc &&
+ oType != OBJECT_KEYd ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, cPos);
+ if ( dist > 20.0f ) continue;
+
+ pObj->SetLock(true);
+ }
+}
+
+// Sent down all the keys.
+
+void CAutoSafe::DownKeys(float progress)
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType oType;
+ float dist;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ if ( oType != OBJECT_KEYa &&
+ oType != OBJECT_KEYb &&
+ oType != OBJECT_KEYc &&
+ oType != OBJECT_KEYd ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, cPos);
+ if ( dist > 20.0f ) continue;
+
+ oPos.y = cPos.y+1.0f-progress*2.2f;
+ pObj->SetPosition(0, oPos);
+ }
+}
+
+// Delete all the keys.
+
+void CAutoSafe::DeleteKeys()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType oType;
+ float dist;
+ int i;
+ bool bDelete;
+
+ cPos = m_object->RetPosition(0);
+
+ do
+ {
+ bDelete = false;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ if ( oType != OBJECT_KEYa &&
+ oType != OBJECT_KEYb &&
+ oType != OBJECT_KEYc &&
+ oType != OBJECT_KEYd ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, cPos);
+ if ( dist > 20.0f ) continue;
+
+ pObj->DeleteObject();
+ delete pObj;
+ bDelete = true;
+ }
+ }
+ while ( bDelete );
+}
+
+// Seeking a vehicle in the safe.
+
+CObject* CAutoSafe::SearchVehicle()
+{
+ CObject* pObj;
+ Math::Vector cPos, oPos;
+ ObjectType oType;
+ float dist;
+ int i;
+
+ cPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( pObj == m_object ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, cPos);
+ if ( dist <= 4.0f ) return pObj;
+ }
+ return 0;
+}
+
+
+
diff --git a/src/object/auto/autosafe.h b/src/object/auto/autosafe.h
index 4194349..d17435b 100644
--- a/src/object/auto/autosafe.h
+++ b/src/object/auto/autosafe.h
@@ -1,74 +1,74 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autosafe.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoSafePhase
-{
- ASAP_WAIT = 1,
- ASAP_OPEN = 2,
- ASAP_FINISH = 3,
-};
-
-
-
-class CAutoSafe : public CAuto
-{
-public:
- CAutoSafe(CInstanceManager* iMan, CObject* object);
- ~CAutoSafe();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- int CountKeys();
- void LockKeys();
- void DownKeys(float progress);
- void DeleteKeys();
- CObject* SearchVehicle();
-
-protected:
- AutoSafePhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastParticule;
- int m_channelSound;
- bool m_bLock;
- int m_countKeys;
- float m_actualAngle;
- float m_finalAngle;
- bool m_bKey[4];
- Math::Vector m_keyPos[4];
- int m_keyParti[4];
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autosafe.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoSafePhase
+{
+ ASAP_WAIT = 1,
+ ASAP_OPEN = 2,
+ ASAP_FINISH = 3,
+};
+
+
+
+class CAutoSafe : public CAuto
+{
+public:
+ CAutoSafe(CInstanceManager* iMan, CObject* object);
+ ~CAutoSafe();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ int CountKeys();
+ void LockKeys();
+ void DownKeys(float progress);
+ void DeleteKeys();
+ CObject* SearchVehicle();
+
+protected:
+ AutoSafePhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastParticule;
+ int m_channelSound;
+ bool m_bLock;
+ int m_countKeys;
+ float m_actualAngle;
+ float m_finalAngle;
+ bool m_bKey[4];
+ Math::Vector m_keyPos[4];
+ int m_keyParti[4];
+};
+
diff --git a/src/object/auto/autostation.cpp b/src/object/auto/autostation.cpp
index ddd5888..dba4ed8 100644
--- a/src/object/auto/autostation.cpp
+++ b/src/object/auto/autostation.cpp
@@ -1,370 +1,370 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autostation.h"
-
-#include "common/iman.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "math/geometry.h"
-#include "ui/interface.h"
-#include "ui/gauge.h"
-#include "ui/window.h"
-
-
-
-
-// Object's constructor.
-
-CAutoStation::CAutoStation(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- Init();
-}
-
-// Object's destructor.
-
-CAutoStation::~CAutoStation()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoStation::DeleteObject(bool bAll)
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->Stop(m_soundChannel);
- m_soundChannel = -1;
- }
-
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoStation::Init()
-{
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastUpdateTime = 0.0f;
- m_lastParticule = 0.0f;
- m_soundChannel = -1;
- m_bLastVirus = false;
-
- CAuto::Init();
-}
-
-
-// Management of an event.
-
-bool CAutoStation::EventProcess(const Event &event)
-{
- Math::Matrix* mat;
- Math::Vector pos, ppos, speed;
- Math::Point dim;
- CObject* vehicule;
- CObject* power;
- TerrainRes res;
- float big, energy, used, add, freq;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( !m_bLastVirus )
- {
- m_bLastVirus = true;
- m_energyVirus = m_object->RetEnergy();
- }
-
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
-
- m_object->SetEnergy(Math::Rand());
- }
- return true;
- }
- else
- {
- if ( m_bLastVirus )
- {
- m_bLastVirus = false;
- m_object->SetEnergy(m_energyVirus);
- }
- }
-
- UpdateInterface(event.rTime);
-
- big = m_object->RetEnergy();
-
- res = m_terrain->RetResource(m_object->RetPosition(0));
- if ( res == TR_POWER )
- {
- big += event.rTime*0.01f; // recharges the large battery
- }
-
- used = big;
- freq = 1.0f;
- if ( big > 0.0f )
- {
- vehicule = SearchVehicle();
- if ( vehicule != 0 )
- {
- power = vehicule->RetPower();
- if ( power != 0 && power->RetCapacity() == 1.0f )
- {
- energy = power->RetEnergy();
- add = event.rTime*0.2f;
- if ( add > big*4.0f ) add = big*4.0f;
- if ( add > 1.0f-energy ) add = 1.0f-energy;
- energy += add; // Charging the battery
- power->SetEnergy(energy);
- if ( energy < freq ) freq = energy;
- big -= add/4.0f; // discharge the large battery
- }
-
- power = vehicule->RetFret();
- if ( power != 0 && power->RetType() == OBJECT_POWER )
- {
- energy = power->RetEnergy();
- add = event.rTime*0.2f;
- if ( add > big*4.0f ) add = big*4.0f;
- if ( add > 1.0f-energy ) add = 1.0f-energy;
- energy += add; // Charging the battery
- power->SetEnergy(energy);
- if ( energy < freq ) freq = energy;
- big -= add/4.0f; // discharge the large battery
- }
- }
- }
- used -= big; // energy used
-
- if ( freq < 1.0f ) // charging in progress?
- {
- freq = 1.0f+3.0f*freq;
- if ( m_soundChannel == -1 )
- {
- m_soundChannel = m_sound->Play(SOUND_STATION, m_object->RetPosition(0),
- 0.3f, freq, true);
- }
- m_sound->Frequency(m_soundChannel, freq);
- }
- else
- {
- if ( m_soundChannel != -1 )
- {
- m_sound->Stop(m_soundChannel);
- m_soundChannel = -1;
- }
- }
-
- if ( used != 0.0f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(-15.0f, 7.0f, 0.0f); // battery position
- pos = Math::Transform(*mat, pos);
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.y = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- ppos.x = pos.x;
- ppos.y = pos.y+(Math::Rand()-0.5f)*4.0f;
- ppos.z = pos.z;
- dim.x = 1.5f;
- dim.y = 1.5f;
- m_particule->CreateParticule(ppos, speed, dim, PARTIBLITZ, 1.0f, 0.0f, 0.0f);
-
-#if 0
- ppos = pos;
- ppos.y += 1.0f;
- ppos.x += (Math::Rand()-0.5f)*3.0f;
- ppos.z += (Math::Rand()-0.5f)*3.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 2.5f+Math::Rand()*6.0f;
- dim.x = Math::Rand()*1.5f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(ppos, speed, dim, PARTISMOKE3, 4.0f);
-#else
- ppos = pos;
- ppos.y += 1.0f;
- ppos.x += (Math::Rand()-0.5f)*3.0f;
- ppos.z += (Math::Rand()-0.5f)*3.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 2.5f+Math::Rand()*5.0f;
- dim.x = Math::Rand()*1.0f+0.6f;
- dim.y = dim.x;
- m_particule->CreateParticule(ppos, speed, dim, PARTIVAPOR, 3.0f);
-#endif
- }
-
- if ( big < 0.0f ) big = 0.0f;
- if ( big > 1.0f ) big = 1.0f;
- m_object->SetEnergy(big); // Shift the large battery
-
- return true;
-}
-
-
-// Seeking the vehicle on the station.
-
-CObject* CAutoStation::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector sPos, oPos;
- ObjectType type;
- float dist;
- int i;
-
- sPos = m_object->RetPosition(0);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( 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 ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, sPos);
- if ( dist <= 5.0f ) return pObj;
- }
-
- return 0;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoStation::RetError()
-{
- TerrainRes res;
-
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- res = m_terrain->RetResource(m_object->RetPosition(0));
- if ( res != TR_POWER ) return ERR_STATION_NULL;
-
- return ERR_OK;
-}
-
-
-// Crée toute l'interface lorsque l'objet est sélectionné .
-
-bool CAutoStation::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*14.5f;
- pos.y = oy+sy*0;
- ddim.x = 14.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 104, EVENT_OBJECT_TYPE);
-
- return true;
-}
-
-// Updates the state of all buttons on the interface,
-// following the time that elapses ...
-
-void CAutoStation::UpdateInterface(float rTime)
-{
- CWindow* pw;
- CGauge* pg;
-
- CAuto::UpdateInterface(rTime);
-
- if ( m_time < m_lastUpdateTime+0.1f ) return;
- m_lastUpdateTime = m_time;
-
- if ( !m_object->RetSelect() ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
- if ( pg != 0 )
- {
- pg->SetLevel(m_object->RetEnergy());
- }
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autostation.h"
+
+#include "common/iman.h"
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "math/geometry.h"
+#include "ui/interface.h"
+#include "ui/gauge.h"
+#include "ui/window.h"
+
+
+
+
+// Object's constructor.
+
+CAutoStation::CAutoStation(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ Init();
+}
+
+// Object's destructor.
+
+CAutoStation::~CAutoStation()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoStation::DeleteObject(bool bAll)
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->Stop(m_soundChannel);
+ m_soundChannel = -1;
+ }
+
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoStation::Init()
+{
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastUpdateTime = 0.0f;
+ m_lastParticule = 0.0f;
+ m_soundChannel = -1;
+ m_bLastVirus = false;
+
+ CAuto::Init();
+}
+
+
+// Management of an event.
+
+bool CAutoStation::EventProcess(const Event &event)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, ppos, speed;
+ Math::Point dim;
+ CObject* vehicule;
+ CObject* power;
+ TerrainRes res;
+ float big, energy, used, add, freq;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( !m_bLastVirus )
+ {
+ m_bLastVirus = true;
+ m_energyVirus = m_object->RetEnergy();
+ }
+
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+
+ m_object->SetEnergy(Math::Rand());
+ }
+ return true;
+ }
+ else
+ {
+ if ( m_bLastVirus )
+ {
+ m_bLastVirus = false;
+ m_object->SetEnergy(m_energyVirus);
+ }
+ }
+
+ UpdateInterface(event.rTime);
+
+ big = m_object->RetEnergy();
+
+ res = m_terrain->RetResource(m_object->RetPosition(0));
+ if ( res == TR_POWER )
+ {
+ big += event.rTime*0.01f; // recharges the large battery
+ }
+
+ used = big;
+ freq = 1.0f;
+ if ( big > 0.0f )
+ {
+ vehicule = SearchVehicle();
+ if ( vehicule != 0 )
+ {
+ power = vehicule->RetPower();
+ if ( power != 0 && power->RetCapacity() == 1.0f )
+ {
+ energy = power->RetEnergy();
+ add = event.rTime*0.2f;
+ if ( add > big*4.0f ) add = big*4.0f;
+ if ( add > 1.0f-energy ) add = 1.0f-energy;
+ energy += add; // Charging the battery
+ power->SetEnergy(energy);
+ if ( energy < freq ) freq = energy;
+ big -= add/4.0f; // discharge the large battery
+ }
+
+ power = vehicule->RetFret();
+ if ( power != 0 && power->RetType() == OBJECT_POWER )
+ {
+ energy = power->RetEnergy();
+ add = event.rTime*0.2f;
+ if ( add > big*4.0f ) add = big*4.0f;
+ if ( add > 1.0f-energy ) add = 1.0f-energy;
+ energy += add; // Charging the battery
+ power->SetEnergy(energy);
+ if ( energy < freq ) freq = energy;
+ big -= add/4.0f; // discharge the large battery
+ }
+ }
+ }
+ used -= big; // energy used
+
+ if ( freq < 1.0f ) // charging in progress?
+ {
+ freq = 1.0f+3.0f*freq;
+ if ( m_soundChannel == -1 )
+ {
+ m_soundChannel = m_sound->Play(SOUND_STATION, m_object->RetPosition(0),
+ 0.3f, freq, true);
+ }
+ m_sound->Frequency(m_soundChannel, freq);
+ }
+ else
+ {
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->Stop(m_soundChannel);
+ m_soundChannel = -1;
+ }
+ }
+
+ if ( used != 0.0f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(-15.0f, 7.0f, 0.0f); // battery position
+ pos = Math::Transform(*mat, pos);
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.y = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ ppos.x = pos.x;
+ ppos.y = pos.y+(Math::Rand()-0.5f)*4.0f;
+ ppos.z = pos.z;
+ dim.x = 1.5f;
+ dim.y = 1.5f;
+ m_particule->CreateParticule(ppos, speed, dim, PARTIBLITZ, 1.0f, 0.0f, 0.0f);
+
+#if 0
+ ppos = pos;
+ ppos.y += 1.0f;
+ ppos.x += (Math::Rand()-0.5f)*3.0f;
+ ppos.z += (Math::Rand()-0.5f)*3.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 2.5f+Math::Rand()*6.0f;
+ dim.x = Math::Rand()*1.5f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(ppos, speed, dim, PARTISMOKE3, 4.0f);
+#else
+ ppos = pos;
+ ppos.y += 1.0f;
+ ppos.x += (Math::Rand()-0.5f)*3.0f;
+ ppos.z += (Math::Rand()-0.5f)*3.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 2.5f+Math::Rand()*5.0f;
+ dim.x = Math::Rand()*1.0f+0.6f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(ppos, speed, dim, PARTIVAPOR, 3.0f);
+#endif
+ }
+
+ if ( big < 0.0f ) big = 0.0f;
+ if ( big > 1.0f ) big = 1.0f;
+ m_object->SetEnergy(big); // Shift the large battery
+
+ return true;
+}
+
+
+// Seeking the vehicle on the station.
+
+CObject* CAutoStation::SearchVehicle()
+{
+ CObject* pObj;
+ Math::Vector sPos, oPos;
+ ObjectType type;
+ float dist;
+ int i;
+
+ sPos = m_object->RetPosition(0);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( 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 ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, sPos);
+ if ( dist <= 5.0f ) return pObj;
+ }
+
+ return 0;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoStation::RetError()
+{
+ TerrainRes res;
+
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ res = m_terrain->RetResource(m_object->RetPosition(0));
+ if ( res != TR_POWER ) return ERR_STATION_NULL;
+
+ return ERR_OK;
+}
+
+
+// Crée toute l'interface lorsque l'objet est sélectionné .
+
+bool CAutoStation::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*14.5f;
+ pos.y = oy+sy*0;
+ ddim.x = 14.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 104, EVENT_OBJECT_TYPE);
+
+ return true;
+}
+
+// Updates the state of all buttons on the interface,
+// following the time that elapses ...
+
+void CAutoStation::UpdateInterface(float rTime)
+{
+ CWindow* pw;
+ CGauge* pg;
+
+ CAuto::UpdateInterface(rTime);
+
+ if ( m_time < m_lastUpdateTime+0.1f ) return;
+ m_lastUpdateTime = m_time;
+
+ if ( !m_object->RetSelect() ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
+ if ( pg != 0 )
+ {
+ pg->SetLevel(m_object->RetEnergy());
+ }
+}
+
+
diff --git a/src/object/auto/autostation.h b/src/object/auto/autostation.h
index b4584f2..5bf2b72 100644
--- a/src/object/auto/autostation.h
+++ b/src/object/auto/autostation.h
@@ -1,56 +1,56 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autostation.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-class CAutoStation : public CAuto
-{
-public:
- CAutoStation(CInstanceManager* iMan, CObject* object);
- ~CAutoStation();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
-protected:
- void UpdateInterface(float rTime);
-
- CObject* SearchVehicle();
-
-protected:
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastUpdateTime;
- float m_lastParticule;
- int m_soundChannel;
- Math::Vector m_fretPos;
- bool m_bLastVirus;
- float m_energyVirus;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autostation.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+class CAutoStation : public CAuto
+{
+public:
+ CAutoStation(CInstanceManager* iMan, CObject* object);
+ ~CAutoStation();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+protected:
+ void UpdateInterface(float rTime);
+
+ CObject* SearchVehicle();
+
+protected:
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastUpdateTime;
+ float m_lastParticule;
+ int m_soundChannel;
+ Math::Vector m_fretPos;
+ bool m_bLastVirus;
+ float m_energyVirus;
+};
+
diff --git a/src/object/auto/autotower.cpp b/src/object/auto/autotower.cpp
index ec92341..5f185fe 100644
--- a/src/object/auto/autotower.cpp
+++ b/src/object/auto/autotower.cpp
@@ -1,541 +1,541 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/auto/autotower.h"
-
-#include "common/iman.h"
-#include "math/geometry.h"
-#include "physics/physics.h"
-#include "script/cmdtoken.h"
-#include "ui/interface.h"
-#include "ui/displaytext.h"
-#include "ui/window.h"
-#include "ui/gauge.h"
-
-
-const float TOWER_SCOPE = 200.0f; // range of beam
-const float ENERGY_FIRE = 0.125f; // energy consumed by fire
-
-
-// Object's constructor.
-
-CAutoTower::CAutoTower(CInstanceManager* iMan, CObject* object)
- : CAuto(iMan, object)
-{
- int i;
-
- for ( i=0 ; i<4 ; i++ )
- {
- m_partiStop[i] = -1;
- }
-
- Init();
- m_phase = ATP_WAIT; // paused until the first Init ()
- m_time = 0.0f;
- m_lastUpdateTime = 0.0f;
-}
-
-// Object's destructor.
-
-CAutoTower::~CAutoTower()
-{
-}
-
-
-// Destroys the object.
-
-void CAutoTower::DeleteObject(bool bAll)
-{
- FireStopUpdate(0.0f, false);
- CAuto::DeleteObject(bAll);
-}
-
-
-// Initialize the object.
-
-void CAutoTower::Init()
-{
- m_phase = ATP_ZERO;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-
- m_time = 0.0f;
- m_timeVirus = 0.0f;
- m_lastUpdateTime = 0.0f;
- m_lastParticule = 0.0f;
-}
-
-
-// Management of an event.
-
-bool CAutoTower::EventProcess(const Event &event)
-{
- CObject* power;
- CObject* target;
- Math::Vector pos;
- float angle, energy, quick;
-
- CAuto::EventProcess(event);
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_timeVirus -= event.rTime;
-
- if ( m_object->RetVirusMode() ) // contaminated by a virus?
- {
- if ( m_timeVirus <= 0.0f )
- {
- m_timeVirus = 0.1f+Math::Rand()*0.3f;
-
- angle = m_object->RetAngleY(1);
- angle += Math::Rand()*0.5f;
- m_object->SetAngleY(1, angle);
-
- m_object->SetAngleZ(2, Math::Rand()*0.5f);
- }
- return true;
- }
-
- UpdateInterface(event.rTime);
-
- if ( m_phase == ATP_WAIT ) return true;
-
- m_progress += event.rTime*m_speed;
-
- if ( m_phase == ATP_ZERO )
- {
- FireStopUpdate(m_progress, true); // blinks
- if ( m_progress < 1.0f )
- {
- energy = 0.0f;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- }
- if ( energy >= ENERGY_FIRE )
- {
- m_phase = ATP_SEARCH;
- m_progress = 0.0f;
- m_speed = 1.0f/3.0f;
- }
- }
- else
- {
- m_phase = ATP_ZERO;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- if ( m_phase == ATP_SEARCH )
- {
- FireStopUpdate(m_progress, false); // extinguished
- if ( m_progress < 1.0f )
- {
- quick = 1.0f;
-//? if ( g_researchDone & RESEARCH_QUICK ) quick = 3.0f;
-
- angle = m_object->RetAngleY(1);
- angle -= event.rTime*quick*2.0f;
- m_object->SetAngleY(1, angle);
-
- angle = m_object->RetAngleZ(2);
- angle += event.rTime*quick*0.5f;
- if ( angle > 0.0f ) angle = 0.0f;
- m_object->SetAngleZ(2, angle);
- }
- else
- {
- energy = 0.0f;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- }
-
- target = SearchTarget(m_targetPos);
- if ( energy < ENERGY_FIRE )
- {
- m_displayText->DisplayError(ERR_TOWER_ENERGY, m_object);
- }
- if ( target == 0 || energy < ENERGY_FIRE )
- {
- m_phase = ATP_ZERO;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- else
- {
- pos = m_object->RetPosition(0);
- pos.y += 24.5f;
- m_angleYfinal = Math::RotateAngle(m_targetPos.x-pos.x, pos.z-m_targetPos.z); // CW !
- m_angleYfinal += Math::PI*2.0f;
- m_angleYfinal -= m_object->RetAngleY(0);
- m_angleYactual = Math::NormAngle(m_object->RetAngleY(1));
-
- m_angleZfinal = -Math::PI/2.0f;
- m_angleZfinal -= Math::RotateAngle(Math::DistanceProjected(m_targetPos, pos), pos.y-m_targetPos.y); // CW !
- m_angleZactual = m_object->RetAngleZ(2);
-
- m_phase = ATP_TURN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
-//? if ( g_researchDone & RESEARCH_QUICK ) m_speed = 1.0f/0.2f;
- }
- }
- }
-
- if ( m_phase == ATP_TURN )
- {
- if ( m_progress < 1.0f )
- {
- angle = m_angleYactual+(m_angleYfinal-m_angleYactual)*m_progress;
- m_object->SetAngleY(1, angle);
-
- angle = m_angleZactual+(m_angleZfinal-m_angleZactual)*m_progress;
- m_object->SetAngleZ(2, angle);
- }
- else
- {
- m_object->SetAngleY(1, m_angleYfinal);
- m_object->SetAngleZ(2, m_angleZfinal);
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- energy -= ENERGY_FIRE/power->RetCapacity();
- power->SetEnergy(energy);
- }
-
- m_sound->Play(SOUND_GGG, m_object->RetPosition(0));
-
- m_phase = ATP_FIRE;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- }
- }
-
- if ( m_phase == ATP_FIRE )
- {
- if ( m_progress == 0.0f )
- {
- pos = m_object->RetPosition(0);
- pos.y += 24.5f;
- m_particule->CreateRay(pos, m_targetPos, PARTIRAY1,
- Math::Point(5.0f, 5.0f), 1.5f);
- }
- if ( m_progress >= 1.0f )
- {
- m_phase = ATP_ZERO;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
-
- return true;
-}
-
-
-// Seeks the nearest target object.
-
-CObject* CAutoTower::SearchTarget(Math::Vector &impact)
-{
- CObject* pObj;
- CObject* pBest = 0;
- CPhysics* physics;
- Math::Vector iPos, oPos;
- ObjectType oType;
- float distance, min, radius, speed;
- int i;
-
- iPos = m_object->RetPosition(0);
- min = 1000000.0f;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( oType != OBJECT_MOTHER &&
- oType != OBJECT_ANT &&
- oType != OBJECT_SPIDER &&
- oType != OBJECT_BEE &&
- oType != OBJECT_WORM ) continue;
-
- if ( !pObj->RetActif() ) continue; // inactive?
-
-//? if ( g_researchDone & RESEARCH_QUICK )
- if ( false )
- {
- physics = pObj->RetPhysics();
- if ( physics != 0 )
- {
- speed = fabs(physics->RetLinMotionX(MO_REASPEED));
- if ( speed > 20.0f ) continue; // moving too fast?
- }
- }
-
- if ( !pObj->GetCrashSphere(0, oPos, radius) ) continue;
- distance = Math::Distance(oPos, iPos);
- if ( distance > TOWER_SCOPE ) continue; // too far
- if ( distance < min )
- {
- min = distance;
- pBest = pObj;
- }
- }
- if ( pBest == 0 ) return 0;
-
- impact = pBest->RetPosition(0);
- return pBest;
-}
-
-
-// Returns an error due the state of the automation.
-
-Error CAutoTower::RetError()
-{
- CObject* power;
-
- if ( m_object->RetVirusMode() )
- {
- return ERR_BAT_VIRUS;
- }
-
- power = m_object->RetPower();
- if ( power == 0 )
- {
- return ERR_TOWER_POWER; // no battery
- }
- else
- {
- if ( power->RetEnergy() < ENERGY_FIRE )
- {
- return ERR_TOWER_ENERGY; // not enough energy
- }
- }
- return ERR_OK;
-}
-
-
-// Updates the stop lights.
-
-void CAutoTower::FireStopUpdate(float progress, bool bLightOn)
-{
- Math::Matrix* mat;
- Math::Vector pos, speed;
- Math::Point dim;
- int i;
-
- static float listpos[8] =
- {
- 4.5f, 0.0f,
- 0.0f, 4.5f,
- -4.5f, 0.0f,
- 0.0f, -4.5f,
- };
-
- if ( !bLightOn ) // extinguished?
- {
- for ( i=0 ; i<4 ; i++ )
- {
- if ( m_partiStop[i] != -1 )
- {
- m_particule->DeleteParticule(m_partiStop[i]);
- m_partiStop[i] = -1;
- }
- }
- return;
- }
-
- mat = m_object->RetWorldMatrix(0);
-
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 2.0f;
- dim.y = dim.x;
-
- for ( i=0 ; i<4 ; i++ )
- {
- if ( Math::Mod(progress+i*0.125f, 0.5f) < 0.2f )
- {
- if ( m_partiStop[i] != -1 )
- {
- m_particule->DeleteParticule(m_partiStop[i]);
- m_partiStop[i] = -1;
- }
- }
- else
- {
- if ( m_partiStop[i] == -1 )
- {
- pos.x = listpos[i*2+0];
- pos.y = 18.0f;
- pos.z = listpos[i*2+1];
- pos = Transform(*mat, pos);
- m_partiStop[i] = m_particule->CreateParticule(pos, speed,
- dim, PARTISELR,
- 1.0f, 0.0f, 0.0f);
- }
- }
- }
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CAutoTower::CreateInterface(bool bSelect)
-{
- CWindow* pw;
- Math::Point pos, ddim;
- float ox, oy, sx, sy;
-
- CAuto::CreateInterface(bSelect);
-
- if ( !bSelect ) return true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- pos.x = ox+sx*14.5f;
- pos.y = oy+sy*0;
- ddim.x = 14.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0;
- ddim.x = 66.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGroup(pos, ddim, 107, EVENT_OBJECT_TYPE);
-
- pos.x = ox+sx*10.2f;
- pos.y = oy+sy*0.5f;
- ddim.x = 33.0f/640.0f;
- ddim.y = 33.0f/480.0f;
- pw->CreateButton(pos, ddim, 41, EVENT_OBJECT_LIMIT);
-
- return true;
-}
-
-// Updates the state of all buttons on the interface,
-// following the time that elapses ...
-
-void CAutoTower::UpdateInterface(float rTime)
-{
- CWindow* pw;
- CGauge* pg;
- CObject* power;
- float energy;
-
- CAuto::UpdateInterface(rTime);
-
- if ( m_time < m_lastUpdateTime+0.1f ) return;
- m_lastUpdateTime = m_time;
-
- if ( !m_object->RetSelect() ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
- if ( pg != 0 )
- {
- energy = 0.0f;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- }
- pg->SetLevel(energy);
- }
-}
-
-
-// Saves all parameters of the controller.
-
-bool CAutoTower::Write(char *line)
-{
- char name[100];
-
- if ( m_phase == ATP_WAIT ) return false;
-
- sprintf(name, " aExist=%d", 1);
- strcat(line, name);
-
- CAuto::Write(line);
-
- sprintf(name, " aPhase=%d", m_phase);
- strcat(line, name);
-
- sprintf(name, " aProgress=%.2f", m_progress);
- strcat(line, name);
-
- sprintf(name, " aSpeed=%.2f", m_speed);
- strcat(line, name);
-
- sprintf(name, " aTargetPos=%.2f;%.2f;%.2f", m_targetPos.x, m_targetPos.y, m_targetPos.z);
- strcat(line, name);
-
- sprintf(name, " aAngleYactual=%.2f", m_angleYactual);
- strcat(line, name);
-
- sprintf(name, " aAngleZactual=%.2f", m_angleZactual);
- strcat(line, name);
-
- sprintf(name, " aAngleYfinal=%.2f", m_angleYfinal);
- strcat(line, name);
-
- sprintf(name, " aAngleZfinal=%.2f", m_angleZfinal);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the controller.
-
-bool CAutoTower::Read(char *line)
-{
- if ( OpInt(line, "aExist", 0) == 0 ) return false;
-
- CAuto::Read(line);
-
- m_phase = (AutoTowerPhase)OpInt(line, "aPhase", ATP_WAIT);
- m_progress = OpFloat(line, "aProgress", 0.0f);
- m_speed = OpFloat(line, "aSpeed", 1.0f);
- m_targetPos = OpDir(line, "aTargetPos");
- m_angleYactual = OpFloat(line, "aAngleYactual", 0.0f);
- m_angleZactual = OpFloat(line, "aAngleZactual", 0.0f);
- m_angleYfinal = OpFloat(line, "aAngleYfinal", 0.0f);
- m_angleZfinal = OpFloat(line, "aAngleZfinal", 0.0f);
-
- m_lastUpdateTime = 0.0f;
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/auto/autotower.h"
+
+#include "common/iman.h"
+#include "math/geometry.h"
+#include "physics/physics.h"
+#include "script/cmdtoken.h"
+#include "ui/interface.h"
+#include "ui/displaytext.h"
+#include "ui/window.h"
+#include "ui/gauge.h"
+
+
+const float TOWER_SCOPE = 200.0f; // range of beam
+const float ENERGY_FIRE = 0.125f; // energy consumed by fire
+
+
+// Object's constructor.
+
+CAutoTower::CAutoTower(CInstanceManager* iMan, CObject* object)
+ : CAuto(iMan, object)
+{
+ int i;
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ m_partiStop[i] = -1;
+ }
+
+ Init();
+ m_phase = ATP_WAIT; // paused until the first Init ()
+ m_time = 0.0f;
+ m_lastUpdateTime = 0.0f;
+}
+
+// Object's destructor.
+
+CAutoTower::~CAutoTower()
+{
+}
+
+
+// Destroys the object.
+
+void CAutoTower::DeleteObject(bool bAll)
+{
+ FireStopUpdate(0.0f, false);
+ CAuto::DeleteObject(bAll);
+}
+
+
+// Initialize the object.
+
+void CAutoTower::Init()
+{
+ m_phase = ATP_ZERO;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+
+ m_time = 0.0f;
+ m_timeVirus = 0.0f;
+ m_lastUpdateTime = 0.0f;
+ m_lastParticule = 0.0f;
+}
+
+
+// Management of an event.
+
+bool CAutoTower::EventProcess(const Event &event)
+{
+ CObject* power;
+ CObject* target;
+ Math::Vector pos;
+ float angle, energy, quick;
+
+ CAuto::EventProcess(event);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_timeVirus -= event.rTime;
+
+ if ( m_object->RetVirusMode() ) // contaminated by a virus?
+ {
+ if ( m_timeVirus <= 0.0f )
+ {
+ m_timeVirus = 0.1f+Math::Rand()*0.3f;
+
+ angle = m_object->RetAngleY(1);
+ angle += Math::Rand()*0.5f;
+ m_object->SetAngleY(1, angle);
+
+ m_object->SetAngleZ(2, Math::Rand()*0.5f);
+ }
+ return true;
+ }
+
+ UpdateInterface(event.rTime);
+
+ if ( m_phase == ATP_WAIT ) return true;
+
+ m_progress += event.rTime*m_speed;
+
+ if ( m_phase == ATP_ZERO )
+ {
+ FireStopUpdate(m_progress, true); // blinks
+ if ( m_progress < 1.0f )
+ {
+ energy = 0.0f;
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ }
+ if ( energy >= ENERGY_FIRE )
+ {
+ m_phase = ATP_SEARCH;
+ m_progress = 0.0f;
+ m_speed = 1.0f/3.0f;
+ }
+ }
+ else
+ {
+ m_phase = ATP_ZERO;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ if ( m_phase == ATP_SEARCH )
+ {
+ FireStopUpdate(m_progress, false); // extinguished
+ if ( m_progress < 1.0f )
+ {
+ quick = 1.0f;
+//? if ( g_researchDone & RESEARCH_QUICK ) quick = 3.0f;
+
+ angle = m_object->RetAngleY(1);
+ angle -= event.rTime*quick*2.0f;
+ m_object->SetAngleY(1, angle);
+
+ angle = m_object->RetAngleZ(2);
+ angle += event.rTime*quick*0.5f;
+ if ( angle > 0.0f ) angle = 0.0f;
+ m_object->SetAngleZ(2, angle);
+ }
+ else
+ {
+ energy = 0.0f;
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ }
+
+ target = SearchTarget(m_targetPos);
+ if ( energy < ENERGY_FIRE )
+ {
+ m_displayText->DisplayError(ERR_TOWER_ENERGY, m_object);
+ }
+ if ( target == 0 || energy < ENERGY_FIRE )
+ {
+ m_phase = ATP_ZERO;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ else
+ {
+ pos = m_object->RetPosition(0);
+ pos.y += 24.5f;
+ m_angleYfinal = Math::RotateAngle(m_targetPos.x-pos.x, pos.z-m_targetPos.z); // CW !
+ m_angleYfinal += Math::PI*2.0f;
+ m_angleYfinal -= m_object->RetAngleY(0);
+ m_angleYactual = Math::NormAngle(m_object->RetAngleY(1));
+
+ m_angleZfinal = -Math::PI/2.0f;
+ m_angleZfinal -= Math::RotateAngle(Math::DistanceProjected(m_targetPos, pos), pos.y-m_targetPos.y); // CW !
+ m_angleZactual = m_object->RetAngleZ(2);
+
+ m_phase = ATP_TURN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+//? if ( g_researchDone & RESEARCH_QUICK ) m_speed = 1.0f/0.2f;
+ }
+ }
+ }
+
+ if ( m_phase == ATP_TURN )
+ {
+ if ( m_progress < 1.0f )
+ {
+ angle = m_angleYactual+(m_angleYfinal-m_angleYactual)*m_progress;
+ m_object->SetAngleY(1, angle);
+
+ angle = m_angleZactual+(m_angleZfinal-m_angleZactual)*m_progress;
+ m_object->SetAngleZ(2, angle);
+ }
+ else
+ {
+ m_object->SetAngleY(1, m_angleYfinal);
+ m_object->SetAngleZ(2, m_angleZfinal);
+
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ energy -= ENERGY_FIRE/power->RetCapacity();
+ power->SetEnergy(energy);
+ }
+
+ m_sound->Play(SOUND_GGG, m_object->RetPosition(0));
+
+ m_phase = ATP_FIRE;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ }
+ }
+
+ if ( m_phase == ATP_FIRE )
+ {
+ if ( m_progress == 0.0f )
+ {
+ pos = m_object->RetPosition(0);
+ pos.y += 24.5f;
+ m_particule->CreateRay(pos, m_targetPos, PARTIRAY1,
+ Math::Point(5.0f, 5.0f), 1.5f);
+ }
+ if ( m_progress >= 1.0f )
+ {
+ m_phase = ATP_ZERO;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+
+ return true;
+}
+
+
+// Seeks the nearest target object.
+
+CObject* CAutoTower::SearchTarget(Math::Vector &impact)
+{
+ CObject* pObj;
+ CObject* pBest = 0;
+ CPhysics* physics;
+ Math::Vector iPos, oPos;
+ ObjectType oType;
+ float distance, min, radius, speed;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+ min = 1000000.0f;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( oType != OBJECT_MOTHER &&
+ oType != OBJECT_ANT &&
+ oType != OBJECT_SPIDER &&
+ oType != OBJECT_BEE &&
+ oType != OBJECT_WORM ) continue;
+
+ if ( !pObj->RetActif() ) continue; // inactive?
+
+//? if ( g_researchDone & RESEARCH_QUICK )
+ if ( false )
+ {
+ physics = pObj->RetPhysics();
+ if ( physics != 0 )
+ {
+ speed = fabs(physics->RetLinMotionX(MO_REASPEED));
+ if ( speed > 20.0f ) continue; // moving too fast?
+ }
+ }
+
+ if ( !pObj->GetCrashSphere(0, oPos, radius) ) continue;
+ distance = Math::Distance(oPos, iPos);
+ if ( distance > TOWER_SCOPE ) continue; // too far
+ if ( distance < min )
+ {
+ min = distance;
+ pBest = pObj;
+ }
+ }
+ if ( pBest == 0 ) return 0;
+
+ impact = pBest->RetPosition(0);
+ return pBest;
+}
+
+
+// Returns an error due the state of the automation.
+
+Error CAutoTower::RetError()
+{
+ CObject* power;
+
+ if ( m_object->RetVirusMode() )
+ {
+ return ERR_BAT_VIRUS;
+ }
+
+ power = m_object->RetPower();
+ if ( power == 0 )
+ {
+ return ERR_TOWER_POWER; // no battery
+ }
+ else
+ {
+ if ( power->RetEnergy() < ENERGY_FIRE )
+ {
+ return ERR_TOWER_ENERGY; // not enough energy
+ }
+ }
+ return ERR_OK;
+}
+
+
+// Updates the stop lights.
+
+void CAutoTower::FireStopUpdate(float progress, bool bLightOn)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ int i;
+
+ static float listpos[8] =
+ {
+ 4.5f, 0.0f,
+ 0.0f, 4.5f,
+ -4.5f, 0.0f,
+ 0.0f, -4.5f,
+ };
+
+ if ( !bLightOn ) // extinguished?
+ {
+ for ( i=0 ; i<4 ; i++ )
+ {
+ if ( m_partiStop[i] != -1 )
+ {
+ m_particule->DeleteParticule(m_partiStop[i]);
+ m_partiStop[i] = -1;
+ }
+ }
+ return;
+ }
+
+ mat = m_object->RetWorldMatrix(0);
+
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 2.0f;
+ dim.y = dim.x;
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ if ( Math::Mod(progress+i*0.125f, 0.5f) < 0.2f )
+ {
+ if ( m_partiStop[i] != -1 )
+ {
+ m_particule->DeleteParticule(m_partiStop[i]);
+ m_partiStop[i] = -1;
+ }
+ }
+ else
+ {
+ if ( m_partiStop[i] == -1 )
+ {
+ pos.x = listpos[i*2+0];
+ pos.y = 18.0f;
+ pos.z = listpos[i*2+1];
+ pos = Transform(*mat, pos);
+ m_partiStop[i] = m_particule->CreateParticule(pos, speed,
+ dim, PARTISELR,
+ 1.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CAutoTower::CreateInterface(bool bSelect)
+{
+ CWindow* pw;
+ Math::Point pos, ddim;
+ float ox, oy, sx, sy;
+
+ CAuto::CreateInterface(bSelect);
+
+ if ( !bSelect ) return true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ pos.x = ox+sx*14.5f;
+ pos.y = oy+sy*0;
+ ddim.x = 14.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0;
+ ddim.x = 66.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 107, EVENT_OBJECT_TYPE);
+
+ pos.x = ox+sx*10.2f;
+ pos.y = oy+sy*0.5f;
+ ddim.x = 33.0f/640.0f;
+ ddim.y = 33.0f/480.0f;
+ pw->CreateButton(pos, ddim, 41, EVENT_OBJECT_LIMIT);
+
+ return true;
+}
+
+// Updates the state of all buttons on the interface,
+// following the time that elapses ...
+
+void CAutoTower::UpdateInterface(float rTime)
+{
+ CWindow* pw;
+ CGauge* pg;
+ CObject* power;
+ float energy;
+
+ CAuto::UpdateInterface(rTime);
+
+ if ( m_time < m_lastUpdateTime+0.1f ) return;
+ m_lastUpdateTime = m_time;
+
+ if ( !m_object->RetSelect() ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
+ if ( pg != 0 )
+ {
+ energy = 0.0f;
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ }
+ pg->SetLevel(energy);
+ }
+}
+
+
+// Saves all parameters of the controller.
+
+bool CAutoTower::Write(char *line)
+{
+ char name[100];
+
+ if ( m_phase == ATP_WAIT ) return false;
+
+ sprintf(name, " aExist=%d", 1);
+ strcat(line, name);
+
+ CAuto::Write(line);
+
+ sprintf(name, " aPhase=%d", m_phase);
+ strcat(line, name);
+
+ sprintf(name, " aProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ sprintf(name, " aSpeed=%.2f", m_speed);
+ strcat(line, name);
+
+ sprintf(name, " aTargetPos=%.2f;%.2f;%.2f", m_targetPos.x, m_targetPos.y, m_targetPos.z);
+ strcat(line, name);
+
+ sprintf(name, " aAngleYactual=%.2f", m_angleYactual);
+ strcat(line, name);
+
+ sprintf(name, " aAngleZactual=%.2f", m_angleZactual);
+ strcat(line, name);
+
+ sprintf(name, " aAngleYfinal=%.2f", m_angleYfinal);
+ strcat(line, name);
+
+ sprintf(name, " aAngleZfinal=%.2f", m_angleZfinal);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the controller.
+
+bool CAutoTower::Read(char *line)
+{
+ if ( OpInt(line, "aExist", 0) == 0 ) return false;
+
+ CAuto::Read(line);
+
+ m_phase = (AutoTowerPhase)OpInt(line, "aPhase", ATP_WAIT);
+ m_progress = OpFloat(line, "aProgress", 0.0f);
+ m_speed = OpFloat(line, "aSpeed", 1.0f);
+ m_targetPos = OpDir(line, "aTargetPos");
+ m_angleYactual = OpFloat(line, "aAngleYactual", 0.0f);
+ m_angleZactual = OpFloat(line, "aAngleZactual", 0.0f);
+ m_angleYfinal = OpFloat(line, "aAngleYfinal", 0.0f);
+ m_angleZfinal = OpFloat(line, "aAngleZfinal", 0.0f);
+
+ m_lastUpdateTime = 0.0f;
+
+ return true;
+}
+
+
diff --git a/src/object/auto/autotower.h b/src/object/auto/autotower.h
index b64ad3d..c9393ff 100644
--- a/src/object/auto/autotower.h
+++ b/src/object/auto/autotower.h
@@ -1,74 +1,74 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// autotower.h
-
-#pragma once
-
-
-#include "object/auto/auto.h"
-
-
-
-enum AutoTowerPhase
-{
- ATP_WAIT = 1,
- ATP_ZERO = 2, // more energy
- ATP_SEARCH = 3, // search a target
- ATP_TURN = 4, // turns to the target
- ATP_FIRE = 5, // shoots on the target
-};
-
-
-
-class CAutoTower : public CAuto
-{
-public:
- CAutoTower(CInstanceManager* iMan, CObject* object);
- ~CAutoTower();
-
- void DeleteObject(bool bAll=false);
-
- void Init();
- bool EventProcess(const Event &event);
- Error RetError();
-
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
-protected:
- void UpdateInterface(float rTime);
-
- CObject* SearchTarget(Math::Vector &impact);
- void FireStopUpdate(float progress, bool bLightOn);
-
-protected:
- AutoTowerPhase m_phase;
- float m_progress;
- float m_speed;
- float m_timeVirus;
- float m_lastUpdateTime;
- float m_lastParticule;
- Math::Vector m_targetPos;
- float m_angleYactual;
- float m_angleZactual;
- float m_angleYfinal;
- float m_angleZfinal;
- int m_partiStop[4];
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// autotower.h
+
+#pragma once
+
+
+#include "object/auto/auto.h"
+
+
+
+enum AutoTowerPhase
+{
+ ATP_WAIT = 1,
+ ATP_ZERO = 2, // more energy
+ ATP_SEARCH = 3, // search a target
+ ATP_TURN = 4, // turns to the target
+ ATP_FIRE = 5, // shoots on the target
+};
+
+
+
+class CAutoTower : public CAuto
+{
+public:
+ CAutoTower(CInstanceManager* iMan, CObject* object);
+ ~CAutoTower();
+
+ void DeleteObject(bool bAll=false);
+
+ void Init();
+ bool EventProcess(const Event &event);
+ Error RetError();
+
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+protected:
+ void UpdateInterface(float rTime);
+
+ CObject* SearchTarget(Math::Vector &impact);
+ void FireStopUpdate(float progress, bool bLightOn);
+
+protected:
+ AutoTowerPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_timeVirus;
+ float m_lastUpdateTime;
+ float m_lastParticule;
+ Math::Vector m_targetPos;
+ float m_angleYactual;
+ float m_angleZactual;
+ float m_angleYfinal;
+ float m_angleZfinal;
+ int m_partiStop[4];
+};
+
diff --git a/src/object/brain.cpp b/src/object/brain.cpp
index afc9903..b720992 100644
--- a/src/object/brain.cpp
+++ b/src/object/brain.cpp
@@ -1,2999 +1,2999 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <stdio.h>
-
-#include "object/brain.h"
-
-#include "CBot/CBotDll.h"
-#include "common/struct.h"
-#include "math/geometry.h"
-#include "math/const.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/language.h"
-#include "common/global.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "old/math3d.h"
-#include "object/robotmain.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "old/camera.h"
-#include "object/object.h"
-#include "physics/physics.h"
-#include "object/motion/motion.h"
-#include "object/motion/motionspider.h"
-#include "old/pyro.h"
-#include "object/task/taskmanager.h"
-#include "object/task/task.h"
-#include "object/task/taskmanip.h"
-#include "object/task/taskflag.h"
-#include "object/task/taskshield.h"
-#include "script/script.h"
-#include "ui/studio.h"
-#include "ui/interface.h"
-#include "ui/button.h"
-#include "ui/color.h"
-#include "ui/edit.h"
-#include "ui/list.h"
-#include "ui/label.h"
-#include "ui/group.h"
-#include "ui/gauge.h"
-#include "ui/slider.h"
-#include "ui/compass.h"
-#include "ui/target.h"
-#include "ui/window.h"
-#include "ui/displaytext.h"
-#include "old/text.h"
-#include "old/sound.h"
-#include "old/particule.h"
-#include "script/cmdtoken.h"
-
-
-
-const int MAXTRACERECORD = 1000;
-
-
-
-// Object's constructor.
-
-CBrain::CBrain(CInstanceManager* iMan, CObject* object)
-{
- int i;
-
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_BRAIN, this, 100);
-
- m_object = object;
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
- m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_physics = 0;
- m_motion = 0;
- m_primaryTask = 0;
- m_secondaryTask = 0;
- m_studio = 0;
-
- m_program = -1;
- m_bActivity = true;
- m_bBurn = false;
- m_bActiveVirus = false;
- m_time = 0.0f;
- m_burnTime = 0.0f;
- m_lastUpdateTime = 0.0f;
- m_lastHumanTime = 0.0f;
- m_lastWormTime = 0.0f;
- m_antTarget = 0;
- m_beeBullet = 0;
- m_lastAlarmTime = 0.0f;
- m_soundChannelAlarm = -1;
- m_flagColor = 0;
-
- m_buttonAxe = EVENT_NULL;
- m_defaultEnter = EVENT_NULL;
- m_manipStyle = EVENT_OBJECT_MFRONT;
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- m_script[i] = 0;
- m_scriptName[i][0] = 0;
- }
- m_scriptRun = -1;
- m_soluceName[0] = 0;
- m_selScript = 0;
-
- m_bTraceRecord = false;
- m_traceRecordBuffer = 0;
-}
-
-// Object's destructor.
-
-CBrain::~CBrain()
-{
- int i;
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- delete m_script[i];
- }
-
- delete m_primaryTask;
- delete m_secondaryTask;
- delete m_studio;
- delete m_traceRecordBuffer;
- m_iMan->DeleteInstance(CLASS_BRAIN, this);
-}
-
-
-// Destroys the object.
-
-void CBrain::DeleteObject(bool bAll)
-{
- if ( m_soundChannelAlarm != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannelAlarm);
- m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 0.5f, 0.5f, SOPER_STOP);
- m_soundChannelAlarm = -1;
- }
-
- if ( !bAll )
- {
- if ( m_beeBullet != 0 )
- {
- m_beeBullet->DeleteObject();
- delete m_beeBullet;
- m_beeBullet = 0;
- }
- }
-
- if ( m_studio != 0 ) // current edition?
- {
- StopEditScript(true);
- }
-}
-
-
-void CBrain::SetPhysics(CPhysics* physics)
-{
- m_physics = physics;
-}
-
-void CBrain::SetMotion(CMotion* motion)
-{
- m_motion = motion;
-}
-
-
-// Saves all parameters of the object.
-
-bool CBrain::Write(char *line)
-{
- char name[100];
-
- sprintf(name, " bVirusActive=%d", m_bActiveVirus);
- strcat(line, name);
-
- return true;
-}
-
-// Restores all parameters of the object.
-
-bool CBrain::Read(char *line)
-{
- m_bActiveVirus = OpInt(line, "bVirusActive", 0);
-
- return true;
-}
-
-
-// Management of an event.
-
-bool CBrain::EventProcess(const Event &event)
-{
- CWindow* pw;
- CControl* pc;
- CSlider* ps;
- EventMsg action;
- ObjectType type;
- Error err;
- float axeX, axeY, axeZ, factor;
-
- type = m_object->RetType();
-
- if ( m_primaryTask != 0 ) // current task?
- {
- m_primaryTask->EventProcess(event);
- }
-
- if ( m_secondaryTask != 0 ) // current task?
- {
- m_secondaryTask->EventProcess(event);
- }
-
- action = EVENT_NULL;
-
- if ( event.event == EVENT_KEYDOWN &&
- (event.param == m_engine->RetKey(KEYRANK_ACTION, 0) ||
- event.param == m_engine->RetKey(KEYRANK_ACTION, 1) ) &&
- !m_main->RetEditLock() )
- {
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw != 0 )
- {
- pc = pw->SearchControl(m_defaultEnter);
- if ( pc != 0 )
- {
- if ( pc->TestState(STATE_ENABLE) )
- {
- action = m_defaultEnter;
- }
- }
- }
- }
- else
- {
- action = event.event;
- }
-
- if ( action == EVENT_NULL ) return true;
-
- if ( action == EVENT_UPDINTERFACE )
- {
- if ( m_object->RetSelect() ) CreateInterface(true);
- }
-
- if ( action == EVENT_FRAME )
- {
- EventFrame(event);
- }
-
- if ( m_object->RetSelect() && // robot selected?
- m_studio != 0 ) // current issue?
- {
- m_studio->EventProcess(event);
-
- if ( action == EVENT_OBJECT_PROGRUN )
- {
- if ( m_program == -1 )
- {
- RunProgram(m_selScript);
- }
- else
- {
- StopProgram();
- }
- }
- if ( action == EVENT_OBJECT_PROGSTART )
- {
- m_main->SaveOneScript(m_object);
- RunProgram(m_selScript);
- }
- if ( action == EVENT_OBJECT_PROGSTOP )
- {
- StopProgram();
- }
- if ( action == EVENT_STUDIO_OK )
- {
- StopEditScript(false);
- m_main->SaveOneScript(m_object);
- }
- if ( action == EVENT_STUDIO_CANCEL )
- {
- StopEditScript(true);
- m_main->SaveOneScript(m_object);
- }
- return true;
- }
-
- if ( !m_object->RetSelect() && // robot pas sélectionné ?
- m_program == -1 &&
- m_primaryTask == 0 )
- {
- axeX = 0.0f;
- axeY = 0.0f;
- axeZ = 0.0f;
- if ( m_object->RetBurn() ) // Gifted?
- {
- if ( !m_bBurn ) // beginning?
- {
- m_bBurn = true;
- m_burnTime = 0.0f;
- }
-
- axeZ = -1.0f; // tomb
-
- if ( !m_object->RetFixed() &&
- (type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_WORM ) )
- {
- axeY = 2.0f; // zigzag disorganized fast
- if ( type == OBJECT_WORM ) axeY = 5.0f;
- axeX = 0.5f+sinf(m_time* 1.0f)*0.5f+
- sinf(m_time* 6.0f)*2.0f+
- sinf(m_time*21.0f)*0.2f;
- factor = 1.0f-m_burnTime/15.0f; // slow motion
- if ( factor < 0.0f ) factor = 0.0f;
- axeY *= factor;
- axeX *= factor;
- }
- }
- m_physics->SetMotorSpeedX(axeY); // move forward/move back
- m_physics->SetMotorSpeedY(axeZ); // up / down
- m_physics->SetMotorSpeedZ(axeX); // rotate
- return true;
- }
-
- if ( m_program != -1 &&
- m_object->RetRuin() )
- {
- StopProgram();
- return true;
- }
-
- if ( !m_object->RetSelect() ) // robot not selected?
- {
- return true;
- }
-
- if ( m_secondaryTask != 0 ) // current task?
- {
- if ( action == EVENT_OBJECT_ENDSHIELD )
- {
- m_secondaryTask->StartTaskShield(TSM_DOWN, 0.0f);
- }
- }
- if ( m_primaryTask != 0 || // current task?
- m_program != -1 )
- {
- if ( action == EVENT_OBJECT_PROGRUN )
- {
- StopProgram();
- }
- if ( action == EVENT_OBJECT_PROGEDIT )
- {
- StartEditScript(m_selScript, m_main->RetScriptName());
- }
- if ( m_primaryTask == 0 || !m_primaryTask->IsPilot() ) return true;
- }
-
- if ( action == EVENT_OBJECT_LEFT ||
- action == EVENT_OBJECT_RIGHT ||
- action == EVENT_OBJECT_UP ||
- action == EVENT_OBJECT_DOWN ||
- action == EVENT_OBJECT_GASUP ||
- action == EVENT_OBJECT_GASDOWN )
- {
- m_buttonAxe = action;
- }
- if ( action == EVENT_LBUTTONUP ||
- action == EVENT_RBUTTONUP )
- {
- m_buttonAxe = EVENT_NULL;
- }
-
- axeX = event.axeX;
- axeY = event.axeY;
- axeZ = event.axeZ;
-
- if ( !m_main->RetTrainerPilot() &&
- m_object->RetTrainer() ) // drive vehicle?
- {
- axeX = 0.0f;
- axeY = 0.0f;
- axeZ = 0.0f; // Remote control impossible!
- }
-
- if ( m_buttonAxe == EVENT_OBJECT_LEFT ) axeX = -1.0f;
- if ( m_buttonAxe == EVENT_OBJECT_RIGHT ) axeX = 1.0f;
- if ( m_buttonAxe == EVENT_OBJECT_UP ) axeY = 1.0f;
- if ( m_buttonAxe == EVENT_OBJECT_DOWN ) axeY = -1.0f;
- if ( m_buttonAxe == EVENT_OBJECT_GASUP ) axeZ = 1.0f;
- if ( m_buttonAxe == EVENT_OBJECT_GASDOWN ) axeZ = -1.0f;
-
- if ( m_object->RetManual() ) // scribbler in manual mode?
- {
- if ( axeX != 0.0f ) axeY = 0.0f; // if running -> not moving!
- axeX *= 0.5f;
- axeY *= 0.5f;
- }
-
- if ( (g_researchDone&RESEARCH_FLY) == 0 )
- {
- axeZ = -1.0f; // tomb
- }
-
- axeX += m_camera->RetMotorTurn(); // additional power according to camera
- if ( axeX > 1.0f ) axeX = 1.0f;
- if ( axeX < -1.0f ) axeX = -1.0f;
-
- m_physics->SetMotorSpeedX(axeY); // move forward/move back
- m_physics->SetMotorSpeedY(axeZ); // up/down
- m_physics->SetMotorSpeedZ(axeX); // rotate
-
- if ( action == EVENT_OBJECT_PROGLIST )
- {
- m_selScript = RetSelScript();
- UpdateInterface();
- }
-
- if ( action == EVENT_OBJECT_PROGEDIT )
- {
- StartEditScript(m_selScript, m_main->RetScriptName());
- }
-
- if ( action == EVENT_OBJECT_PROGRUN )
- {
- StopProgram(); // stops the current program
- RunProgram(m_selScript);
- UpdateInterface();
- }
-
- err = ERR_OK;
-
- if ( m_program == -1 )
- {
- if ( action == EVENT_OBJECT_HTAKE )
- {
- err = StartTaskTake();
- }
-
- if ( action == EVENT_OBJECT_MFRONT ||
- action == EVENT_OBJECT_MBACK ||
- action == EVENT_OBJECT_MPOWER )
- {
- m_manipStyle = action;
- UpdateInterface();
- }
-
- if ( action == EVENT_OBJECT_MTAKE )
- {
- if ( m_manipStyle == EVENT_OBJECT_MFRONT )
- {
- err = StartTaskManip(TMO_AUTO, TMA_FFRONT);
- }
- if ( m_manipStyle == EVENT_OBJECT_MBACK )
- {
- err = StartTaskManip(TMO_AUTO, TMA_FBACK);
- if ( err == ERR_OK )
- {
- m_manipStyle = EVENT_OBJECT_MFRONT;
- UpdateInterface();
- }
- }
- if ( m_manipStyle == EVENT_OBJECT_MPOWER )
- {
- err = StartTaskManip(TMO_AUTO, TMA_POWER);
- if ( err == ERR_OK )
- {
- m_manipStyle = EVENT_OBJECT_MFRONT;
- UpdateInterface();
- }
- }
- }
-
- if ( action == EVENT_OBJECT_BDERRICK )
- {
- err = StartTaskBuild(OBJECT_DERRICK);
- }
- if ( action == EVENT_OBJECT_BSTATION )
- {
- err = StartTaskBuild(OBJECT_STATION);
- }
- if ( action == EVENT_OBJECT_BFACTORY )
- {
- err = StartTaskBuild(OBJECT_FACTORY);
- }
- if ( action == EVENT_OBJECT_BREPAIR )
- {
- err = StartTaskBuild(OBJECT_REPAIR);
- }
- if ( action == EVENT_OBJECT_BCONVERT )
- {
- err = StartTaskBuild(OBJECT_CONVERT);
- }
- if ( action == EVENT_OBJECT_BTOWER )
- {
- err = StartTaskBuild(OBJECT_TOWER);
- }
- if ( action == EVENT_OBJECT_BRESEARCH )
- {
- err = StartTaskBuild(OBJECT_RESEARCH);
- }
- if ( action == EVENT_OBJECT_BRADAR )
- {
- err = StartTaskBuild(OBJECT_RADAR);
- }
- if ( action == EVENT_OBJECT_BENERGY )
- {
- err = StartTaskBuild(OBJECT_ENERGY);
- }
- if ( action == EVENT_OBJECT_BLABO )
- {
- err = StartTaskBuild(OBJECT_LABO);
- }
- if ( action == EVENT_OBJECT_BNUCLEAR )
- {
- err = StartTaskBuild(OBJECT_NUCLEAR);
- }
- if ( action == EVENT_OBJECT_BPARA )
- {
- err = StartTaskBuild(OBJECT_PARA);
- }
- if ( action == EVENT_OBJECT_BINFO )
- {
- err = StartTaskBuild(OBJECT_INFO);
- }
-
- if ( action == EVENT_OBJECT_GFLAT )
- {
- GroundFlat();
- }
- if ( action == EVENT_OBJECT_FCREATE )
- {
- err = StartTaskFlag(TFL_CREATE, m_flagColor);
- }
- if ( action == EVENT_OBJECT_FDELETE )
- {
- err = StartTaskFlag(TFL_DELETE, m_flagColor);
- }
- if ( action == EVENT_OBJECT_FCOLORb ||
- action == EVENT_OBJECT_FCOLORr ||
- action == EVENT_OBJECT_FCOLORg ||
- action == EVENT_OBJECT_FCOLORy ||
- action == EVENT_OBJECT_FCOLORv )
- {
- ColorFlag(action-EVENT_OBJECT_FCOLORb);
- }
-
- if ( action == EVENT_OBJECT_SEARCH )
- {
- err = StartTaskSearch();
- }
-
- if ( action == EVENT_OBJECT_TERRAFORM )
- {
- err = StartTaskTerraform();
- }
-
- if ( action == EVENT_OBJECT_RECOVER )
- {
- err = StartTaskRecover();
- }
-
- if ( action == EVENT_OBJECT_BEGSHIELD )
- {
- err = StartTaskShield(TSM_UP);
- }
-
- if ( action == EVENT_OBJECT_DIMSHIELD )
- {
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw != 0 )
- {
- ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_DIMSHIELD);
- if ( ps != 0 )
- {
- m_object->SetParam((ps->RetVisibleValue()-(RADIUS_SHIELD_MIN/g_unit))/((RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)/g_unit));
- }
- }
- }
-
- if ( action == EVENT_OBJECT_FIRE && m_primaryTask == 0 && !m_object->RetTrainer())
- {
- if ( m_camera->RetType() != CAMERA_ONBOARD )
- {
- m_camera->SetType(CAMERA_ONBOARD);
- }
- err = StartTaskFire(0.0f);
- }
- if ( action == EVENT_OBJECT_TARGET && !m_object->RetTrainer() )
- {
- err = StartTaskGunGoal((event.pos.y-0.50f)*1.3f, (event.pos.x-0.50f)*2.0f);
- }
-
- if ( action == EVENT_OBJECT_FIREANT )
- {
-//? err = StartTaskFireAnt();
- }
-
- if ( action == EVENT_OBJECT_PEN0 ) // up
- {
- err = StartTaskPen(false, m_object->RetTraceColor());
- m_object->SetTraceDown(false);
- }
- if ( action == EVENT_OBJECT_PEN1 ) // black
- {
- err = StartTaskPen(true, 1);
- m_object->SetTraceDown(true);
- m_object->SetTraceColor(1);
- }
- if ( action == EVENT_OBJECT_PEN2 ) // yellow
- {
- err = StartTaskPen(true, 8);
- m_object->SetTraceDown(true);
- m_object->SetTraceColor(8);
- }
- if ( action == EVENT_OBJECT_PEN3 ) // orange
- {
- err = StartTaskPen(true, 7);
- m_object->SetTraceDown(true);
- m_object->SetTraceColor(7);
- }
- if ( action == EVENT_OBJECT_PEN4 ) // red
- {
- err = StartTaskPen(true, 4);
- m_object->SetTraceDown(true);
- m_object->SetTraceColor(4);
- }
- if ( action == EVENT_OBJECT_PEN5 ) // violet
- {
- err = StartTaskPen(true, 6);
- m_object->SetTraceDown(true);
- m_object->SetTraceColor(6);
- }
- if ( action == EVENT_OBJECT_PEN6 ) // blue
- {
- err = StartTaskPen(true, 14);
- m_object->SetTraceDown(true);
- m_object->SetTraceColor(14);
- }
- if ( action == EVENT_OBJECT_PEN7 ) // green
- {
- err = StartTaskPen(true, 12);
- m_object->SetTraceDown(true);
- m_object->SetTraceColor(12);
- }
- if ( action == EVENT_OBJECT_PEN8 ) // brown
- {
- err = StartTaskPen(true, 10);
- m_object->SetTraceDown(true);
- m_object->SetTraceColor(10);
- }
-
- if ( action == EVENT_OBJECT_REC ) // registered?
- {
- if ( m_bTraceRecord )
- {
- m_bTraceRecord = false;
- TraceRecordStop();
- }
- else
- {
- m_bTraceRecord = true;
- TraceRecordStart();
- }
- UpdateInterface();
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw != 0 )
- {
- UpdateScript(pw);
- }
- }
- if ( action == EVENT_OBJECT_STOP ) // stops?
- {
- if ( m_bTraceRecord )
- {
- m_bTraceRecord = false;
- TraceRecordStop();
- }
- UpdateInterface();
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw != 0 )
- {
- UpdateScript(pw);
- }
- }
-
- if ( action == EVENT_OBJECT_RESET )
- {
- m_main->ResetObject(); // reset all objects
- UpdateInterface();
- }
-
-#if 0
- if ( event.param == 'T' )
- {
- Math::Vector p1, p2;
- float h;
- p1 = m_object->RetPosition(0);
- h = m_terrain->RetFloorLevel(p1);
- p2 = p1;
- p1.x -= 20.0f;
- p1.z -= 20.0f;
- p2.x += 20.0f;
- p2.z += 20.0f;
- m_terrain->Terraform(p1, p2, h+1.0f);
- }
- if ( event.param == 'R' )
- {
- Math::Vector p1, p2;
- float h;
- p1 = m_object->RetPosition(0);
- h = m_terrain->RetFloorLevel(p1);
- p2 = p1;
- p1.x -= 20.0f;
- p1.z -= 20.0f;
- p2.x += 20.0f;
- p2.z += 20.0f;
- m_terrain->Terraform(p1, p2, h-1.0f);
- }
-#endif
- }
-
- if ( err != ERR_OK )
- {
- m_displayText->DisplayError(err, m_object);
- }
-
- return true;
-}
-
-
-// The brain is changing by time.
-
-bool CBrain::EventFrame(const Event &event)
-{
- m_time += event.rTime;
- if ( m_bBurn ) m_burnTime += event.rTime;
-
- if ( m_soundChannelAlarm != -1 )
- {
- m_sound->Position(m_soundChannelAlarm, m_object->RetPosition(0));
- }
-
- if ( m_studio != 0 ) // �urrent edition?
- {
- m_studio->EventProcess(event);
- }
-
- UpdateInterface(event.rTime);
-
- if ( m_engine->RetPause() ) return true;
- if ( !m_bActivity ) return true; // expected if idle
- if ( EndedTask() == ERR_CONTINUE ) return true; // expected if not finished ...
-
- if ( m_program != -1 ) // current program?
- {
- if ( m_script[m_program]->Continue(event) )
- {
- StopProgram();
- }
- }
-
- if ( m_bTraceRecord ) // registration of the design in progress?
- {
- TraceRecordFrame();
- }
-
- return true;
-}
-
-
-// Stops the running program.
-
-void CBrain::StopProgram()
-{
- StopTask();
-
- if ( m_object->RetType() == OBJECT_HUMAN ||
- m_object->RetType() == OBJECT_TECH ) return;
-
- if ( m_program != -1 &&
- m_script[m_program] != 0 )
- {
- m_script[m_program]->Stop();
- }
-
- BlinkScript(false); // stops flashing
-
- m_program = -1;
-
- m_physics->SetMotorSpeedX(0.0f);
- m_physics->SetMotorSpeedY(0.0f);
- m_physics->SetMotorSpeedZ(0.0f);
-
- m_motion->SetAction(-1);
-
- UpdateInterface();
- m_main->UpdateShortcuts();
- m_object->CreateSelectParticule();
-}
-
-// Stops the current task.
-
-void CBrain::StopTask()
-{
- if ( m_primaryTask != 0 )
- {
- m_primaryTask->Abort();
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-}
-
-
-// Introduces a virus into a program.
-// Returns true if it was inserted.
-
-bool CBrain::IntroduceVirus()
-{
- int i, j;
-
- for ( i=0 ; i<50 ; i++ )
- {
- j = rand()%BRAINMAXSCRIPT;
- if ( m_script[j] != 0 )
- {
- if ( m_script[j]->IntroduceVirus() ) // tries to introduce
- {
- m_bActiveVirus = true; // active virus
- return true;
- }
- }
- }
- return false;
-}
-
-// Active Virus indicates that the object is contaminated. Unlike ch'tites (??? - Programerus)
-// letters which automatically disappear after a while,
-// ActiveVirus does not disappear after you edit the program
-// (Even if the virus is not fixed).
-
-
-void CBrain::SetActiveVirus(bool bActive)
-{
- m_bActiveVirus = bActive;
-
- if ( !m_bActiveVirus ) // virus disabled?
- {
- m_object->SetVirusMode(false); // chtites (??? - Programerus) letters also
- }
-}
-
-bool CBrain::RetActiveVirus()
-{
- return m_bActiveVirus;
-}
-
-
-// Start editing a program.
-
-void CBrain::StartEditScript(int rank, char* name)
-{
- CreateInterface(false); // removes the control buttons
-
- if ( m_script[rank] == 0 )
- {
- m_script[rank] = new CScript(m_iMan, m_object, &m_secondaryTask);
- }
-
- m_studio = new CStudio(m_iMan);
- m_studio->StartEditScript(m_script[rank], name, rank);
-}
-
-// End of editing a program.
-
-void CBrain::StopEditScript(bool bCancel)
-{
- if ( !bCancel ) SetActiveVirus(false);
-
- if ( !m_studio->StopEditScript(bCancel) ) return;
-
- delete m_studio;
- m_studio = 0;
-
- CreateInterface(true); // puts the control buttons
-}
-
-
-
-// Move the manipulator arm.
-
-Error CBrain::StartTaskTake()
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskTake();
- UpdateInterface();
- return err;
-}
-
-// Move the manipulator arm.
-
-Error CBrain::StartTaskManip(TaskManipOrder order, TaskManipArm arm)
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskManip(order, arm);
- UpdateInterface();
- return err;
-}
-
-// Puts or removes a flag.
-
-Error CBrain::StartTaskFlag(TaskFlagOrder order, int rank)
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskFlag(order, rank);
- UpdateInterface();
- return err;
-}
-
-// Built a building.
-
-Error CBrain::StartTaskBuild(ObjectType type)
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskBuild(type);
- UpdateInterface();
- return err;
-}
-
-// Probe the ground.
-
-Error CBrain::StartTaskSearch()
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskSearch();
- UpdateInterface();
- return err;
-}
-
-// Terraformed the ground.
-
-Error CBrain::StartTaskTerraform()
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskTerraform();
- UpdateInterface();
- return err;
-}
-
-// Change pencil.
-
-Error CBrain::StartTaskPen(bool bDown, int color)
-{
- Error err;
-
- m_physics->SetMotorSpeedX(0.0f);
- m_physics->SetMotorSpeedY(0.0f);
- m_physics->SetMotorSpeedZ(0.0f);
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskPen(bDown, color);
- UpdateInterface();
- return err;
-}
-
-// Recovers a ruin.
-
-Error CBrain::StartTaskRecover()
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskRecover();
- UpdateInterface();
- return err;
-}
-
-// Deploys the shield.
-
-Error CBrain::StartTaskShield(TaskShieldMode mode)
-{
- Error err;
-
- if ( m_secondaryTask != 0 )
- {
- delete m_secondaryTask; // stops the current task
- m_secondaryTask = 0;
- }
-
- m_secondaryTask = new CTaskManager(m_iMan, m_object);
- err = m_secondaryTask->StartTaskShield(mode, 1000.0f);
- UpdateInterface();
- return err;
-}
-
-// Shoots.
-
-Error CBrain::StartTaskFire(float delay)
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskFire(delay);
- UpdateInterface();
- return err;
-}
-
-// Shoots to the ant.
-
-Error CBrain::StartTaskFireAnt(Math::Vector impact)
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskFireAnt(impact);
- UpdateInterface();
- return err;
-}
-
-// Adjusts upward.
-
-Error CBrain::StartTaskGunGoal(float dirV, float dirH)
-{
- Error err;
-
- if ( m_secondaryTask != 0 )
- {
- delete m_secondaryTask; // stops the current task
- m_secondaryTask = 0;
- }
-
- m_secondaryTask = new CTaskManager(m_iMan, m_object);
- err = m_secondaryTask->StartTaskGunGoal(dirV, dirH);
- UpdateInterface();
- return err;
-}
-
-// Reset.
-
-Error CBrain::StartTaskReset(Math::Vector goal, Math::Vector angle)
-{
- Error err;
-
- if ( m_primaryTask != 0 )
- {
- delete m_primaryTask; // stops the current task
- m_primaryTask = 0;
- }
-
- m_primaryTask = new CTaskManager(m_iMan, m_object);
- err = m_primaryTask->StartTaskReset(goal, angle);
- UpdateInterface();
- return err;
-}
-
-// Completes the task when the time came.
-
-Error CBrain::EndedTask()
-{
- Error err;
-
- if ( m_secondaryTask != 0 ) // current task?
- {
- err = m_secondaryTask->IsEnded();
- if ( err != ERR_CONTINUE ) // job ended?
- {
- delete m_secondaryTask;
- m_secondaryTask = 0;
- UpdateInterface();
- }
- }
-
- if ( m_primaryTask != 0 ) // current task?
- {
- err = m_primaryTask->IsEnded();
- if ( err != ERR_CONTINUE ) // job ended?
- {
- delete m_primaryTask;
- m_primaryTask = 0;
- UpdateInterface();
- }
- return err;
- }
- return ERR_STOP;
-}
-
-
-
-// Shows flat areas in the field.
-
-void CBrain::GroundFlat()
-{
- Math::Vector pos, speed;
- Math::Point dim;
- Error err;
- float level;
-
- if ( !m_physics->RetLand() )
- {
- err = ERR_FLAG_FLY;
- pos = m_object->RetPosition(0);
- if ( pos.y < m_water->RetLevel() ) err = ERR_FLAG_WATER;
- m_displayText->DisplayError(err, m_object);
- return;
- }
-
- pos = m_object->RetPosition(0);
- m_terrain->GroundFlat(pos);
- m_sound->Play(SOUND_GFLAT, pos);
-
- level = m_terrain->RetFloorLevel(pos)+2.0f;
- if ( pos.y < level ) pos.y = level; // not below the soil
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 40.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGFLAT, 1.0f);
-}
-
-
-// Not below the soil.
-
-void CBrain::ColorFlag(int color)
-{
- m_flagColor = color;
- UpdateInterface();
-}
-
-
-// Creates all the interface when the object is selected.
-
-bool CBrain::CreateInterface(bool bSelect)
-{
- ObjectType type;
- CWindow* pw;
- CButton* pb;
- CColor* pc;
- CSlider* ps;
- CTarget* pt;
- CLabel* pl;
- Math::Point pos, dim, ddim;
- float ox, oy, sx, sy;
- char name[100];
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw != 0 )
- {
- pw->Flush(); // destroys the window buttons
- m_interface->DeleteControl(EVENT_WINDOW0); // destroys the window
- }
- m_defaultEnter = EVENT_NULL;
-
- if ( !bSelect ) return true;
-
- pos.x = 0.0f;
- pos.y = 0.0f;
- dim.x = 540.0f/640.0f;
- if ( !m_main->RetShowMap() ) dim.x = 640.0f/640.0f;
- dim.y = 86.0f/480.0f;
- m_interface->CreateWindows(pos, dim, 3, EVENT_WINDOW0);
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return false;
-
- m_object->GetTooltipName(name);
- pos.x = 0.0f;
- pos.y = 64.0f/480.0f;
- ddim.x = 540.0f/640.0f;
- if ( !m_main->RetShowMap() ) ddim.x = 640.0f/640.0f;
- ddim.y = 16.0f/480.0f;
- pw->CreateLabel(pos, ddim, 0, EVENT_LABEL0, name);
-
- dim.x = 33.0f/640.0f;
- dim.y = 33.0f/480.0f;
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = 33.0f/640.0f;
- sy = 33.0f/480.0f;
-
- type = m_object->RetType();
-
- 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_MOBILEtg ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr ||
- type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ) // vehicle?
- {
- ddim.x = dim.x*5.1f;
- ddim.y = dim.y*2.0f;
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0.0f;
- pw->CreateList(pos, ddim, -1, EVENT_OBJECT_PROGLIST, 1.10f);
- UpdateScript(pw);
-
- pos.x = ox+sx*5.2f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, dim, 8, EVENT_OBJECT_PROGRUN);
- pos.y = oy+sy*0.0f;
- pw->CreateButton(pos, dim, 22, EVENT_OBJECT_PROGEDIT);
- }
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_BEE ) // driving?
- {
- pos.x = ox+sx*6.4f;
- pos.y = oy+sy*0;
- pb = pw->CreateButton(pos, dim, 29, EVENT_OBJECT_GASDOWN);
- pb->SetImmediat(true);
-
- pos.x = ox+sx*6.4f;
- pos.y = oy+sy*1;
- pb = pw->CreateButton(pos, dim, 28, EVENT_OBJECT_GASUP);
- pb->SetImmediat(true);
-
- if ( type != OBJECT_HUMAN ||
- m_object->RetOption() != 2 )
- {
- pos.x = ox+sx*15.3f;
- pos.y = oy+sy*0;
- ddim.x = 14.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGauge(pos, ddim, 2, EVENT_OBJECT_GRANGE);
- }
- }
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH )
- {
- pos.x = ox+sx*7.7f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 31, EVENT_OBJECT_HTAKE);
- DefaultEnter(pw, EVENT_OBJECT_HTAKE);
- }
-
- if ( (type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ) && // arm?
- !m_object->RetTrainer() )
- {
- pos.x = ox+sx*7.7f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 32, EVENT_OBJECT_MTAKE);
- DefaultEnter(pw, EVENT_OBJECT_MTAKE);
-
- pos.x = ox+sx*8.9f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 34, EVENT_OBJECT_MBACK);
-
- pos.x = ox+sx*9.9f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 35, EVENT_OBJECT_MPOWER);
-
- pos.x = ox+sx*10.9f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 33, EVENT_OBJECT_MFRONT);
- }
-
- if ( type == OBJECT_MOBILEsa && // underwater?
- !m_object->RetTrainer() )
- {
- pos.x = ox+sx*7.7f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 32, EVENT_OBJECT_MTAKE);
- DefaultEnter(pw, EVENT_OBJECT_MTAKE);
- }
-
- if ( type == OBJECT_HUMAN ) // builder?
- {
- pos.x = 1.0f/640.0f;
- pos.y = 4.0f/480.0f;
- ddim.x = 212.0f/640.0f;
- ddim.y = 64.0f/480.0f;
- pw->CreateGroup(pos, ddim, 27, EVENT_NULL);
-
- ddim.x = dim.x*0.9f;
- ddim.y = dim.y*0.9f;
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, ddim, 128+35, EVENT_OBJECT_BRESEARCH);
- DeadInterface(pw, EVENT_OBJECT_BRESEARCH, g_build&BUILD_RESEARCH);
-
- pos.x = ox+sx*0.9f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, ddim, 128+32, EVENT_OBJECT_BFACTORY);
- DeadInterface(pw, EVENT_OBJECT_BFACTORY, g_build&BUILD_FACTORY);
-
- pos.x = ox+sx*1.8f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, ddim, 128+34, EVENT_OBJECT_BCONVERT);
- DeadInterface(pw, EVENT_OBJECT_BCONVERT, g_build&BUILD_CONVERT);
-
- pos.x = ox+sx*2.7f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, ddim, 128+36, EVENT_OBJECT_BSTATION);
- DeadInterface(pw, EVENT_OBJECT_BSTATION, g_build&BUILD_STATION);
-
- pos.x = ox+sx*3.6f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, ddim, 128+40, EVENT_OBJECT_BRADAR);
- DeadInterface(pw, EVENT_OBJECT_BRADAR, g_build&BUILD_RADAR);
-
- pos.x = ox+sx*4.5f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, ddim, 128+41, EVENT_OBJECT_BREPAIR);
- DeadInterface(pw, EVENT_OBJECT_BREPAIR, g_build&BUILD_REPAIR);
-
- pos.x = ox+sx*5.4f;
- pos.y = oy+sy*1.0f;
- pw->CreateButton(pos, ddim, 128+44, EVENT_OBJECT_BINFO);
- DeadInterface(pw, EVENT_OBJECT_BINFO, g_build&BUILD_INFO);
-
- pos.x = ox+sx*0.0f;
- pos.y = oy+sy*0.1f;
- pw->CreateButton(pos, ddim, 128+37, EVENT_OBJECT_BTOWER);
- DeadInterface(pw, EVENT_OBJECT_BTOWER,
- (g_build&BUILD_TOWER) &&
- (g_researchDone & RESEARCH_TOWER));
-
- pos.x = ox+sx*0.9f;
- pos.y = oy+sy*0.1f;
- pw->CreateButton(pos, ddim, 128+39, EVENT_OBJECT_BENERGY);
- DeadInterface(pw, EVENT_OBJECT_BENERGY, g_build&BUILD_ENERGY);
-
- pos.x = ox+sx*1.8f;
- pos.y = oy+sy*0.1f;
- pw->CreateButton(pos, ddim, 128+33, EVENT_OBJECT_BDERRICK);
- DeadInterface(pw, EVENT_OBJECT_BDERRICK, g_build&BUILD_DERRICK);
-
- pos.x = ox+sx*2.7f;
- pos.y = oy+sy*0.1f;
- pw->CreateButton(pos, ddim, 128+42, EVENT_OBJECT_BNUCLEAR);
- DeadInterface(pw, EVENT_OBJECT_BNUCLEAR,
- (g_build&BUILD_NUCLEAR) &&
- (g_researchDone & RESEARCH_ATOMIC));
-
- pos.x = ox+sx*3.6f;
- pos.y = oy+sy*0.1f;
- pw->CreateButton(pos, ddim, 128+38, EVENT_OBJECT_BLABO);
- DeadInterface(pw, EVENT_OBJECT_BLABO, g_build&BUILD_LABO);
-
- pos.x = ox+sx*4.5f;
- pos.y = oy+sy*0.1f;
- pw->CreateButton(pos, ddim, 128+46, EVENT_OBJECT_BPARA);
- DeadInterface(pw, EVENT_OBJECT_BPARA, g_build&BUILD_PARA);
-
- pos.x = ox+sx*5.4f;
- pos.y = oy+sy*0.1f;
- pw->CreateButton(pos, ddim, 128+56, EVENT_OBJECT_BXXXX);
- DeadInterface(pw, EVENT_OBJECT_BXXXX, false);
-
- if ( g_build&BUILD_GFLAT )
- {
- pos.x = ox+sx*9.0f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 64+47, EVENT_OBJECT_GFLAT);
- }
-
- if ( g_build&BUILD_FLAG )
- {
- pos.x = ox+sx*10.1f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 64+54, EVENT_OBJECT_FCREATE);
-
- pos.x = ox+sx*11.1f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 64+55, EVENT_OBJECT_FDELETE);
-
- ddim.x = dim.x*0.4f;
- ddim.y = dim.y*0.4f;
- pos.x = ox+sx*10.1f;
- pos.y = oy+sy*2.0f-ddim.y;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORb);
- pc->SetColor(RetColor((D3DCOLOR)0x004890ff));
- pos.x += ddim.x;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORr);
- pc->SetColor(RetColor((D3DCOLOR)0x00ff0000));
- pos.x += ddim.x;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORg);
- pc->SetColor(RetColor((D3DCOLOR)0x0000ce00));
- pos.x += ddim.x;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORy);
- pc->SetColor(RetColor((D3DCOLOR)0x00ffec00));
- pos.x += ddim.x;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORv);
- pc->SetColor(RetColor((D3DCOLOR)0x00d101fe));
- }
- }
-
- if ( (type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ) && // Investigator?
- !m_object->RetTrainer() )
- {
- pos.x = ox+sx*7.7f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 40, EVENT_OBJECT_SEARCH);
- DefaultEnter(pw, EVENT_OBJECT_SEARCH);
- }
-
- if ( type == OBJECT_MOBILErt && // Terraformer?
- !m_object->RetTrainer() )
- {
- pos.x = ox+sx*7.7f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 128+18, EVENT_OBJECT_TERRAFORM);
- DefaultEnter(pw, EVENT_OBJECT_TERRAFORM);
-
- pos.x = ox+sx*10.2f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT);
- }
-
- if ( type == OBJECT_MOBILErr && // recoverer?
- !m_object->RetTrainer() )
- {
- pos.x = ox+sx*7.7f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 128+20, EVENT_OBJECT_RECOVER);
- DefaultEnter(pw, EVENT_OBJECT_RECOVER);
- }
-
- if ( type == OBJECT_MOBILErs && // shield?
- !m_object->RetTrainer() )
- {
- pos.x = ox+sx*7.7f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 39, EVENT_OBJECT_BEGSHIELD);
- DefaultEnter(pw, EVENT_OBJECT_BEGSHIELD);
-
- pos.x = ox+sx*9.0f;
- pos.y = oy+sy*0.5f;
- pw->CreateButton(pos, dim, 47, EVENT_OBJECT_ENDSHIELD);
-
-//? pos.x = ox+sx*10.2f;
-//? pos.y = oy+sy*0.5f;
-//? pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT);
-
- pos.x = ox+sx*10.5f;
- pos.y = oy+sy*0.0f;
- ddim.x = dim.x*0.5f;
- ddim.y = dim.y*2.0f;
- ps = pw->CreateSlider(pos, ddim, 0, EVENT_OBJECT_DIMSHIELD);
- ps->SetState(STATE_VALUE);
- ps->SetLimit((RADIUS_SHIELD_MIN/g_unit), (RADIUS_SHIELD_MAX/g_unit));
- ps->SetArrowStep(1.0f);
- }
-
- if ( (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_MOBILErc ) && // cannon?
- !m_object->RetTrainer() )
- {
- pos.x = ox+sx*7.7f;
- pos.y = oy+sy*0.5f;
- pb = pw->CreateButton(pos, dim, 42, EVENT_OBJECT_FIRE);
- pb->SetImmediat(true);
- DefaultEnter(pw, EVENT_OBJECT_FIRE);
-
-//? pos.x = ox+sx*10.2f;
-//? pos.y = oy+sy*0.5f;
-//? pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT);
- }
-
- if ( type == OBJECT_MOBILEdr &&
- m_object->RetManual() ) // scribbler in manual mode?
- {
- pos.x = ox+sx*6.9f;
- pos.y = oy+sy*0.0f;
- ddim.x = dim.x*2.2f;
- ddim.y = dim.y*2.0f;
- pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
-
- pos.x = ox+sx*9.3f;
- pos.y = oy+sy*0.0f;
- ddim.x = dim.x*2.2f;
- ddim.y = dim.y*2.0f;
- pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
-
- pos.x = ox+sx*9.90f;
- pos.y = oy+sy*0.50f;
- pw->CreateButton(pos, dim, 43, EVENT_OBJECT_PEN0);
-
- ddim.x = dim.x*0.5f;
- ddim.y = dim.y*0.5f;
- pos.x = ox+sx*10.15f;
- pos.y = oy+sy*1.50f;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN1); // black
- pc->SetColor(RetColor((D3DCOLOR)0x00000000));
- pos.x = ox+sx*10.65f;
- pos.y = oy+sy*1.25f;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN2); // yellow
- pc->SetColor(RetColor((D3DCOLOR)0x00ffff00));
- pos.x = ox+sx*10.90f;
- pos.y = oy+sy*0.75f;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN3); // orange
- pc->SetColor(RetColor((D3DCOLOR)0x00ff8800));
- pos.x = ox+sx*10.65f;
- pos.y = oy+sy*0.25f;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN4); // red
- pc->SetColor(RetColor((D3DCOLOR)0x00ff0000));
- pos.x = ox+sx*10.15f;
- pos.y = oy+sy*0.00f;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN5); // violet
- pc->SetColor(RetColor((D3DCOLOR)0x00ff00ff));
- pos.x = ox+sx*9.65f;
- pos.y = oy+sy*0.25f;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN6); // blue
- pc->SetColor(RetColor((D3DCOLOR)0x000066ff));
- pos.x = ox+sx*9.40f;
- pos.y = oy+sy*0.75f;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN7); // green
- pc->SetColor(RetColor((D3DCOLOR)0x0000cc00));
- pos.x = ox+sx*9.65f;
- pos.y = oy+sy*1.25f;
- pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN8); // brown
- pc->SetColor(RetColor((D3DCOLOR)0x00884400));
-
- pos.x = ox+sx*6.9f;
- pos.y = oy+sy*1.2f;
- ddim.x = dim.x*2.2f;
- ddim.y = dim.y*0.4f;
- GetResource(RES_TEXT, RT_INTERFACE_REC, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, name);
- pl->SetFontSize(9.0f);
-
- pos.x = ox+sx*7.0f;
- pos.y = oy+sy*0.3f;
- pw->CreateButton(pos, dim, 44, EVENT_OBJECT_REC);
- pos.x = ox+sx*8.0f;
- pos.y = oy+sy*0.3f;
- pw->CreateButton(pos, dim, 45, EVENT_OBJECT_STOP);
- }
-
- if ( m_object->RetToy() )
- {
- pos.x = ox+sx*12.1f;
- pos.y = oy+sy*-0.1f;
- ddim.x = dim.x*1.2f;
- ddim.y = dim.y*2.1f;
- pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
-
- pos.x = ox+sx*12.2f;
- pos.y = oy+sy*1;
- pw->CreateGroup(pos, dim, 19, EVENT_NULL); // sign SatCom
-
- pos.x = ox+sx*12.2f;
- pos.y = oy+sy*0.0f;
- pw->CreateButton(pos, dim, 128+57, EVENT_OBJECT_BHELP);
- }
- else
- {
- pos.x = ox+sx*12.3f;
- pos.y = oy+sy*-0.1f;
- ddim.x = dim.x*1.0f;
- ddim.y = dim.y*2.1f;
- pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
-
- pos.x = ox+sx*12.3f;
- pos.y = oy+sy*1;
- pw->CreateGroup(pos, dim, 19, EVENT_NULL); // sign SatCom
-
- pos.x = ox+sx*12.4f;
- pos.y = oy+sy*0.5f;
- ddim.x = dim.x*0.8f;
- ddim.y = dim.y*0.5f;
- pw->CreateButton(pos, ddim, 18, EVENT_OBJECT_BHELP);
- pos.y = oy+sy*0.0f;
- pw->CreateButton(pos, ddim, 19, EVENT_OBJECT_HELP);
- }
-
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_TECH &&
- !m_object->RetCameraLock() )
- {
-//? if ( m_main->RetShowMap() )
- if ( true )
- {
- pos.x = ox+sx*13.4f;
- pos.y = oy+sy*1;
- pw->CreateButton(pos, dim, 13, EVENT_OBJECT_CAMERA);
- }
- else
- {
- ddim.x = dim.x*0.66f;
- ddim.y = dim.y*0.66f;
- pos.x = ox+sx*(17.0f+0.66f);
- pos.y = oy+sy*0.66f;
- pw->CreateButton(pos, ddim, 13, EVENT_OBJECT_CAMERA);
- }
- }
-
- if ( m_object->RetToy() && !m_object->RetManual() )
- {
-#if 0
- ddim.x = dim.x*0.66f;
- ddim.y = dim.y*0.66f;
- pos.x = ox+sx*10.0f;
- pos.y = oy+sy*0.66f;
- pb = pw->CreateButton(pos, ddim, 55, EVENT_OBJECT_CAMERAleft);
- pb->SetImmediat(true);
- pos.x = ox+sx*(10.0f+0.66f*2.0f);
- pos.y = oy+sy*0.66f;
- pb = pw->CreateButton(pos, ddim, 48, EVENT_OBJECT_CAMERAright);
- pb->SetImmediat(true);
- pos.x = ox+sx*(10.0f+0.66f);
- pos.y = oy+sy*(0.66f*2.0f);
- pb = pw->CreateButton(pos, ddim, 49, EVENT_OBJECT_CAMERAnear);
- pb->SetImmediat(true);
- pos.x = ox+sx*(10.0f+0.66f);
- pos.y = oy+sy*0.0f;
- pb = pw->CreateButton(pos, ddim, 50, EVENT_OBJECT_CAMERAaway);
- pb->SetImmediat(true);
-#else
- pos.x = ox+sx*9.0f;
- pos.y = oy+sy*0;
- pb = pw->CreateButton(pos, dim, 55, EVENT_OBJECT_CAMERAleft);
- pb->SetImmediat(true);
- pos.x = ox+sx*11.0f;
- pos.y = oy+sy*0;
- pb = pw->CreateButton(pos, dim, 48, EVENT_OBJECT_CAMERAright);
- pb->SetImmediat(true);
- pos.x = ox+sx*10.0f;
- pos.y = oy+sy*1;
- pb = pw->CreateButton(pos, dim, 49, EVENT_OBJECT_CAMERAnear);
- pb->SetImmediat(true);
- pos.x = ox+sx*10.0f;
- pos.y = oy+sy*0;
- pb = pw->CreateButton(pos, dim, 50, EVENT_OBJECT_CAMERAaway);
- pb->SetImmediat(true);
-#endif
- }
-
- pos.x = ox+sx*13.4f;
- pos.y = oy+sy*0;
-#if _TEEN
- pw->CreateButton(pos, dim, 9, EVENT_OBJECT_RESET);
-#else
- if ( m_object->RetTrainer() ) // Training?
- {
- pw->CreateButton(pos, dim, 9, EVENT_OBJECT_RESET);
- }
- else
- {
- pw->CreateButton(pos, dim, 10, EVENT_OBJECT_DESELECT);
- }
-#endif
-
- 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 ) // vehicle?
- {
- pos.x = ox+sx*14.5f;
- pos.y = oy+sy*0;
- ddim.x = 14.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
- }
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH ||
- type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ) // vehicle?
- {
- pos.x = ox+sx*14.9f;
- pos.y = oy+sy*0;
- ddim.x = 14.0f/640.0f;
- ddim.y = 66.0f/480.0f;
- pw->CreateGauge(pos, ddim, 3, EVENT_OBJECT_GSHIELD);
- }
-
-#if 0
- if ( false )
- {
- pos.x = 505.0f/640.0f;
- pos.y = 3.0f/480.0f;
- ddim.x = 33.0f/640.0f;
- ddim.y = 33.0f/480.0f;
- pw->CreateCompass(pos, ddim, 0, EVENT_OBJECT_COMPASS);
-
- pc = (CCompass*)pw->SearchControl(EVENT_OBJECT_COMPASS);
- if ( pc != 0 )
- {
- pc->SetState(STATE_VISIBLE, m_main->RetShowMap());
- }
- }
-#endif
-
- if ( 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_MOBILErc ) // cannon?
- {
- ddim.x = 64.0f/640.0f;
- ddim.y = 64.0f/480.0f;
- pos.x = 0.5f-ddim.x/2.0f;
- pos.y = 0.5f-ddim.y/2.0f;
- pw->CreateGroup(pos, ddim, 12, EVENT_OBJECT_CROSSHAIR);
-
- pos.x = 20.0f/640.0f;
- pos.y = 100.0f/480.0f;
- ddim.x = 600.0f/640.0f;
- ddim.y = 340.0f/480.0f;
- pt = pw->CreateTarget(pos, ddim, 0, EVENT_OBJECT_TARGET);
- pt->ClearState(STATE_GLINT);
- }
-
- ddim.x = 64.0f/640.0f;
- ddim.y = 64.0f/480.0f;
- pos.x = 30.0f/640.0f;
- pos.y = 430.0f/480.0f-ddim.y;
- pw->CreateGroup(pos, ddim, 13, EVENT_OBJECT_CORNERul);
-
- ddim.x = 64.0f/640.0f;
- ddim.y = 64.0f/480.0f;
- pos.x = 610.0f/640.0f-ddim.x;
- pos.y = 430.0f/480.0f-ddim.y;
- pw->CreateGroup(pos, ddim, 14, EVENT_OBJECT_CORNERur);
-
- ddim.x = 64.0f/640.0f;
- ddim.y = 64.0f/480.0f;
- pos.x = 30.0f/640.0f;
- pos.y = 110.0f/480.0f;
- pw->CreateGroup(pos, ddim, 15, EVENT_OBJECT_CORNERdl);
-
- ddim.x = 64.0f/640.0f;
- ddim.y = 64.0f/480.0f;
- pos.x = 610.0f/640.0f-ddim.x;
- pos.y = 110.0f/480.0f;
- pw->CreateGroup(pos, ddim, 16, EVENT_OBJECT_CORNERdr);
-
- UpdateInterface();
- m_lastUpdateTime = 0.0f;
- UpdateInterface(0.0f);
-
- return true;
-}
-
-// Updates the state of all buttons on the interface,
-// following the time that elapses ...
-
-void CBrain::UpdateInterface(float rTime)
-{
- CWindow* pw;
-#if _TEEN
- CButton* pb;
-#endif
- CGauge* pg;
- CCompass* pc;
- CGroup* pgr;
- CTarget* ptg;
- CObject* power;
- Math::Vector pos, hPos;
- Math::Point ppos;
- float energy, limit, angle, range;
- int icon;
- bool bOnBoard;
-
- m_lastAlarmTime += rTime;
- if ( m_time < m_lastUpdateTime+0.1f ) return;
- m_lastUpdateTime = m_time;
-
- if ( !m_object->RetSelect() )
- {
- if ( m_soundChannelAlarm != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannelAlarm);
- m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 1.0f, 0.1f, SOPER_STOP);
- m_soundChannelAlarm = -1;
- }
- return;
- }
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
- if ( pg != 0 )
- {
- power = m_object->RetPower();
- if ( power == 0 )
- {
- energy = 0.0f;
- }
- else
- {
- energy = power->RetEnergy();
- limit = energy*power->RetCapacity();
- }
- icon = 0; // red/green
-
- if ( limit < 0.2f && energy != 0.0f ) // low but not zero?
- {
- if ( m_lastAlarmTime >= 0.8f ) // blinks?
- {
- energy = 1.0f;
- icon = 1; // brun
- }
- if ( m_lastAlarmTime >= 1.0f )
- {
- m_sound->Play(SOUND_ALARM, 0.5f); // bip-bip-bip
- m_lastAlarmTime = 0.0f;
- }
- }
- pg->SetLevel(energy);
- pg->SetIcon(icon);
- }
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GSHIELD);
- if ( pg != 0 )
- {
- pg->SetLevel(m_object->RetShield());
- }
-
- pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GRANGE);
- if ( pg != 0 )
- {
- icon = 2; // blue/red
- range = m_physics->RetReactorRange();
-
- if ( range < 0.2f && range != 0.0f && !m_physics->RetLand() )
- {
- if ( Math::Mod(m_time, 0.5f) >= 0.2f ) // blinks?
- {
- range = 1.0f;
- icon = 1; // yellow
- }
- if ( m_soundChannelAlarm == -1 )
- {
- m_soundChannelAlarm = m_sound->Play(SOUND_ALARMt, m_object->RetPosition(0), 0.0f, 0.1f, true);
- m_sound->AddEnvelope(m_soundChannelAlarm, 1.0f, 1.0f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannelAlarm, 1.0f, 1.0f, 1.0f, SOPER_LOOP);
- }
- }
- else
- {
- if ( m_soundChannelAlarm != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannelAlarm);
- m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 0.1f, 1.0f, SOPER_STOP);
- m_soundChannelAlarm = -1;
- }
- }
-
- pg->SetLevel(1.0f-range);
- pg->SetIcon(icon);
- }
-
- pc = (CCompass*)pw->SearchControl(EVENT_OBJECT_COMPASS);
- if ( pc != 0 )
- {
- angle = -(m_object->RetAngleY(0)+Math::PI/2.0f);
- pc->SetDirection(angle);
-
- pc->SetState(STATE_VISIBLE, m_main->RetShowMap());
- }
-
-#if _TEEN
- pb = (CButton*)pw->SearchControl(EVENT_OBJECT_REC);
- if ( pb != 0 )
- {
- if ( m_bTraceRecord && Math::Mod(m_time, 0.4f) >= 0.2f )
- {
- pb->SetState(STATE_CHECK);
- }
- else
- {
- pb->ClearState(STATE_CHECK);
- }
- }
-#endif
-
- bOnBoard = m_camera->RetType() == CAMERA_ONBOARD;
-
- pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CROSSHAIR);
- if ( pgr != 0 )
- {
- if ( bOnBoard )
- {
-#if 0
- angle = m_object->RetGunGoalV();
- if ( m_object->RetType() != OBJECT_MOBILErc )
- {
- angle += 10.0f*Math::PI/360.0f;
- }
- ppos.x = 0.5f-(64.0f/640.0f)/2.0f;
- ppos.y = 0.5f-(64.0f/480.0f)/2.0f;
- ppos.y += sinf(angle)*0.6f;
- pgr->SetPos(ppos);
-#else
- ppos.x = 0.50f-(64.0f/640.0f)/2.0f;
- ppos.y = 0.50f-(64.0f/480.0f)/2.0f;
- ppos.x += m_object->RetGunGoalH()/2.0f;
- ppos.y += m_object->RetGunGoalV()/1.3f;
- pgr->SetPos(ppos);
-#endif
- pgr->SetState(STATE_VISIBLE, !m_main->RetFriendAim());
- }
- else
- {
- pgr->ClearState(STATE_VISIBLE);
- }
- }
-
- ptg = (CTarget*)pw->SearchControl(EVENT_OBJECT_TARGET);
- if ( ptg != 0 )
- {
- if ( bOnBoard )
- {
- ptg->SetState(STATE_VISIBLE);
- }
- else
- {
- ptg->ClearState(STATE_VISIBLE);
- }
- }
-
- pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERul);
- if ( pgr != 0 )
- {
- pgr->SetState(STATE_VISIBLE, bOnBoard);
- }
-
- pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERur);
- if ( pgr != 0 )
- {
- pgr->SetState(STATE_VISIBLE, bOnBoard);
- }
-
- pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERdl);
- if ( pgr != 0 )
- {
- pgr->SetState(STATE_VISIBLE, bOnBoard);
- }
-
- pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERdr);
- if ( pgr != 0 )
- {
- pgr->SetState(STATE_VISIBLE, bOnBoard);
- }
-}
-
-// Updates the status of all interface buttons.
-
-void CBrain::UpdateInterface()
-{
- ObjectType type;
- CWindow* pw;
- CButton* pb;
- CSlider* ps;
-#if _TEEN
- CColor* pc;
- int color;
-#endif
- bool bEnable, bFly, bRun;
- char title[100];
-
- if ( !m_object->RetSelect() ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- type = m_object->RetType();
-
- bEnable = ( m_secondaryTask == 0 && m_program == -1 );
-
- bEnable = ( m_primaryTask == 0 && m_program == -1 );
-
- EnableInterface(pw, EVENT_OBJECT_PROGEDIT, (m_primaryTask == 0 && !m_bTraceRecord));
- EnableInterface(pw, EVENT_OBJECT_PROGLIST, bEnable && !m_bTraceRecord);
- EnableInterface(pw, EVENT_OBJECT_LEFT, bEnable);
- EnableInterface(pw, EVENT_OBJECT_RIGHT, bEnable);
- EnableInterface(pw, EVENT_OBJECT_UP, bEnable);
- EnableInterface(pw, EVENT_OBJECT_DOWN, bEnable);
- EnableInterface(pw, EVENT_OBJECT_HTAKE, bEnable);
- EnableInterface(pw, EVENT_OBJECT_MTAKE, bEnable);
- EnableInterface(pw, EVENT_OBJECT_MBACK, bEnable);
- EnableInterface(pw, EVENT_OBJECT_MPOWER, bEnable);
- EnableInterface(pw, EVENT_OBJECT_MFRONT, bEnable);
- EnableInterface(pw, EVENT_OBJECT_GFLAT, bEnable);
- EnableInterface(pw, EVENT_OBJECT_FCREATE, bEnable);
- EnableInterface(pw, EVENT_OBJECT_FDELETE, bEnable);
- EnableInterface(pw, EVENT_OBJECT_SEARCH, bEnable);
- EnableInterface(pw, EVENT_OBJECT_TERRAFORM, bEnable);
- EnableInterface(pw, EVENT_OBJECT_RECOVER, bEnable);
- EnableInterface(pw, EVENT_OBJECT_FIRE, bEnable);
- EnableInterface(pw, EVENT_OBJECT_RESET, bEnable);
-#if _TEEN
- EnableInterface(pw, EVENT_OBJECT_PEN0, bEnable);
- EnableInterface(pw, EVENT_OBJECT_PEN1, bEnable);
- EnableInterface(pw, EVENT_OBJECT_PEN2, bEnable);
- EnableInterface(pw, EVENT_OBJECT_PEN3, bEnable);
- EnableInterface(pw, EVENT_OBJECT_PEN4, bEnable);
- EnableInterface(pw, EVENT_OBJECT_PEN5, bEnable);
- EnableInterface(pw, EVENT_OBJECT_PEN6, bEnable);
- EnableInterface(pw, EVENT_OBJECT_PEN7, bEnable);
- EnableInterface(pw, EVENT_OBJECT_PEN8, bEnable);
- EnableInterface(pw, EVENT_OBJECT_REC, bEnable);
- EnableInterface(pw, EVENT_OBJECT_STOP, bEnable);
-#endif
-
- if ( type == OBJECT_HUMAN ) // builder?
- {
- EnableInterface(pw, EVENT_OBJECT_BFACTORY, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BDERRICK, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BCONVERT, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BSTATION, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BREPAIR, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BTOWER, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BRESEARCH, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BRADAR, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BENERGY, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BLABO, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BNUCLEAR, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BPARA, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BINFO, bEnable);
- EnableInterface(pw, EVENT_OBJECT_BXXXX, bEnable);
- }
-
- pb = (CButton*)pw->SearchControl(EVENT_OBJECT_GFLAT);
- if ( pb != 0 )
- {
- pb->SetState(STATE_VISIBLE, m_engine->RetGroundSpot());
- }
-
- if ( type == OBJECT_HUMAN || // builder?
- type == OBJECT_TECH )
- {
- CheckInterface(pw, EVENT_OBJECT_FCOLORb, m_flagColor==0);
- CheckInterface(pw, EVENT_OBJECT_FCOLORr, m_flagColor==1);
- CheckInterface(pw, EVENT_OBJECT_FCOLORg, m_flagColor==2);
- CheckInterface(pw, EVENT_OBJECT_FCOLORy, m_flagColor==3);
- CheckInterface(pw, EVENT_OBJECT_FCOLORv, m_flagColor==4);
- }
-
- if ( type == OBJECT_MOBILErs ) // shield?
- {
- if ( (m_secondaryTask == 0 || !m_secondaryTask->IsBusy()) && m_program == -1 )
- {
- EnableInterface(pw, EVENT_OBJECT_BEGSHIELD, (m_secondaryTask == 0));
- EnableInterface(pw, EVENT_OBJECT_ENDSHIELD, (m_secondaryTask != 0));
- DefaultEnter (pw, EVENT_OBJECT_BEGSHIELD, (m_secondaryTask == 0));
- DefaultEnter (pw, EVENT_OBJECT_ENDSHIELD, (m_secondaryTask != 0));
- }
- else
- {
- EnableInterface(pw, EVENT_OBJECT_BEGSHIELD, false);
- EnableInterface(pw, EVENT_OBJECT_ENDSHIELD, false);
- DefaultEnter (pw, EVENT_OBJECT_BEGSHIELD, false);
- DefaultEnter (pw, EVENT_OBJECT_ENDSHIELD, false);
- }
-
- ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_DIMSHIELD);
- if ( ps != 0 )
- {
- ps->SetVisibleValue((RADIUS_SHIELD_MIN/g_unit)+m_object->RetParam()*((RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)/g_unit));
- }
- }
-
- bFly = bEnable;
- if ( bFly && (type == OBJECT_HUMAN || type == OBJECT_TECH) )
- {
- if ( m_object->RetFret() != 0 ) bFly = false; // if holder -> not fly
- }
- EnableInterface(pw, EVENT_OBJECT_GASUP, bFly);
- EnableInterface(pw, EVENT_OBJECT_GASDOWN, bFly);
- if ( m_object->RetTrainer() ) // Training?
- {
- DeadInterface(pw, EVENT_OBJECT_GASUP, false);
- DeadInterface(pw, EVENT_OBJECT_GASDOWN, false);
- }
- else
- {
- DeadInterface(pw, EVENT_OBJECT_GASUP, g_researchDone&RESEARCH_FLY);
- DeadInterface(pw, EVENT_OBJECT_GASDOWN, g_researchDone&RESEARCH_FLY);
- }
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH ||
- type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr ||
- type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ) // vehicle?
- {
- bRun = false;
- if ( m_script[m_selScript] != 0 )
- {
- m_script[m_selScript]->GetTitle(title);
- if ( title[0] != 0 )
- {
- bRun = true;
- }
- }
- if ( !bEnable && m_program == -1 ) bRun = false;
- if ( m_bTraceRecord ) bRun = false;
- EnableInterface(pw, EVENT_OBJECT_PROGRUN, bRun);
-
- pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PROGRUN);
- if ( pb != 0 )
- {
- pb->SetIcon(m_program==-1?21:8); // run/stop
- }
-
-//? pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PROGEDIT);
-//? if ( pb != 0 )
-//? {
-//? pb->SetIcon(m_program==-1?22:40); // edit/debug
-//? }
-
- BlinkScript(m_program != -1); // blinks if script execution
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ) // arm?
- {
- CheckInterface(pw, EVENT_OBJECT_MPOWER, m_manipStyle==EVENT_OBJECT_MPOWER);
- CheckInterface(pw, EVENT_OBJECT_MBACK, m_manipStyle==EVENT_OBJECT_MBACK);
- CheckInterface(pw, EVENT_OBJECT_MFRONT, m_manipStyle==EVENT_OBJECT_MFRONT);
- }
-
-#if _TEEN
- if ( m_object->RetTraceDown() )
- {
- pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PEN0);
- if ( pb != 0 )
- {
- pb->ClearState(STATE_CHECK);
- }
-
- color = m_object->RetTraceColor();
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN1);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, color==1);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN2);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, color==8);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN3);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, color==7);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN4);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, color==4);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN5);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, color==6);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN6);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, color==14);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN7);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, color==12);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN8);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, color==10);
- }
- }
- else
- {
- pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PEN0);
- if ( pb != 0 )
- {
- pb->SetState(STATE_CHECK);
- }
-
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN1);
- if ( pc != 0 )
- {
- pc->ClearState(STATE_CHECK);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN2);
- if ( pc != 0 )
- {
- pc->ClearState(STATE_CHECK);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN3);
- if ( pc != 0 )
- {
- pc->ClearState(STATE_CHECK);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN4);
- if ( pc != 0 )
- {
- pc->ClearState(STATE_CHECK);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN5);
- if ( pc != 0 )
- {
- pc->ClearState(STATE_CHECK);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN6);
- if ( pc != 0 )
- {
- pc->ClearState(STATE_CHECK);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN7);
- if ( pc != 0 )
- {
- pc->ClearState(STATE_CHECK);
- }
- pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN8);
- if ( pc != 0 )
- {
- pc->ClearState(STATE_CHECK);
- }
- }
-#endif
-}
-
-// Updates the list of programs.
-
-void CBrain::UpdateScript(CWindow *pw)
-{
- CList* pl;
- char name[100];
- char title[100];
- int i;
- bool bSoluce;
-
- pl = (CList*)pw->SearchControl(EVENT_OBJECT_PROGLIST);
- if ( pl == 0 ) return;
-
-#if _SCHOOL
- bSoluce = m_main->RetSoluce4();
-#else
- bSoluce = true;
-#endif
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- sprintf(name, "%d", i+1);
-
- if ( m_script[i] != 0 )
- {
- m_script[i]->GetTitle(title);
- if ( !bSoluce && i == 3 )
- {
- title[0] = 0;
- }
- if ( title[0] != 0 )
- {
- sprintf(name, "%d: %s", i+1, title);
- }
- }
-
- pl->SetName(i, name);
- }
-
- if ( !bSoluce )
- {
- pl->SetEnable(3, false);
- }
-
- pl->SetSelect(m_selScript);
- pl->ShowSelect(true);
-}
-
-// Returns the rank of selected script.
-
-int CBrain::RetSelScript()
-{
- CWindow* pw;
- CList* pl;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return -1;
-
- pl = (CList*)pw->SearchControl(EVENT_OBJECT_PROGLIST);
- if ( pl == 0 ) return -1;
-
- return pl->RetSelect();
-}
-
-// Blinks the running program.
-
-void CBrain::BlinkScript(bool bEnable)
-{
- CWindow* pw;
- CList* pl;
-
- if ( !m_object->RetSelect() ) return; // robot not selected?
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw == 0 ) return;
-
- pl = (CList*)pw->SearchControl(EVENT_OBJECT_PROGLIST);
- if ( pl == 0 ) return;
-
- pl->SetBlink(bEnable);
-}
-
-// Check the status of a button interface.
-
-void CBrain::CheckInterface(CWindow *pw, EventMsg event, bool bState)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_CHECK, bState);
-}
-
-// Changes the state of a button interface.
-
-void CBrain::EnableInterface(CWindow *pw, EventMsg event, bool bState)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_ENABLE, bState);
-}
-
-// Changes the state of a button on the interface.
-
-void CBrain::DeadInterface(CWindow *pw, EventMsg event, bool bState)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- control->SetState(STATE_DEAD, !bState);
-}
-
-// Change the default input state of a button interface.
-
-void CBrain::DefaultEnter(CWindow *pw, EventMsg event, bool bState)
-{
- CControl* control;
-
- control = pw->SearchControl(event);
- if ( control == 0 ) return;
-
- if ( bState )
- {
- control->SetState(STATE_DEFAULT);
- m_defaultEnter = event;
- }
- else
- {
- control->ClearState(STATE_DEFAULT);
- }
-}
-
-
-// Indicates whether the object is busy with a task.
-
-bool CBrain::IsBusy()
-{
- return (m_primaryTask != 0);
-}
-
-// Management of the activity of an object.
-
-void CBrain::SetActivity(bool bMode)
-{
- m_bActivity = bMode;
-}
-
-bool CBrain::RetActivity()
-{
- return m_bActivity;
-}
-
-// Indicates whether a program is running.
-
-bool CBrain::IsProgram()
-{
- return ( m_program != -1 );
-}
-
-// Indicates whether a program exists.
-
-bool CBrain::ProgramExist(int rank)
-{
- return ( m_script[rank] != 0 );
-}
-
-// Starts a program.
-
-void CBrain::RunProgram(int rank)
-{
- if ( rank < 0 ) return;
-
- if ( m_script[rank] != 0 &&
- m_script[rank]->Run() )
- {
- m_program = rank; // start new program
- BlinkScript(true); // blink
- m_object->CreateSelectParticule();
- m_main->UpdateShortcuts();
- }
-}
-
-// Returns the first free program.
-
-int CBrain::FreeProgram()
-{
- int i;
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- if ( m_script[i] == 0 ) return i;
- }
- return -1;
-}
-
-
-// Returns the current program.
-
-int CBrain::RetProgram()
-{
- return m_program;
-}
-
-
-// Name management scripts to load.
-
-void CBrain::SetScriptRun(int rank)
-{
- m_scriptRun = rank;
-}
-
-int CBrain::RetScriptRun()
-{
- return m_scriptRun;
-}
-
-void CBrain::SetScriptName(int rank, char *name)
-{
- strcpy(m_scriptName[rank], name);
-}
-
-char* CBrain::RetScriptName(int rank)
-{
- return m_scriptName[rank];
-}
-
-void CBrain::SetSoluceName(char *name)
-{
- strcpy(m_soluceName, name);
-}
-
-char* CBrain::RetSoluceName()
-{
- return m_soluceName;
-}
-
-
-// Load a script solution, in the first free script.
-// If there is already an identical script, nothing is loaded.
-
-bool CBrain::ReadSoluce(char* filename)
-{
- int rank, i;
-
- rank = FreeProgram();
- if ( rank == -1 ) return false;
-
- if ( !ReadProgram(rank, filename) ) return false; // load solution
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- if ( i == rank || m_script[i] == 0 ) continue;
-
- if ( m_script[i]->Compare(m_script[rank]) ) // the same already?
- {
- delete m_script[rank];
- m_script[rank] = 0;
- return false;
- }
- }
-
- return true;
-}
-
-// Load a script with a text file.
-
-bool CBrain::ReadProgram(int rank, char* filename)
-{
- if ( m_script[rank] == 0 )
- {
- m_script[rank] = new CScript(m_iMan, m_object, &m_secondaryTask);
- }
-
- if ( m_script[rank]->ReadScript(filename) ) return true;
-
- delete m_script[rank];
- m_script[rank] = 0;
-
- return false;
-}
-
-// Indicates whether a program is compiled correctly.
-
-bool CBrain::RetCompile(int rank)
-{
- if ( m_script[rank] == 0 ) return false;
- return m_script[rank]->RetCompile();
-}
-
-// Saves a script in a text file.
-
-bool CBrain::WriteProgram(int rank, char* filename)
-{
- if ( m_script[rank] == 0 )
- {
- m_script[rank] = new CScript(m_iMan, m_object, &m_secondaryTask);
- }
-
- if ( m_script[rank]->WriteScript(filename) ) return true;
-
- delete m_script[rank];
- m_script[rank] = 0;
-
- return false;
-}
-
-
-// Load a stack of script implementation from a file.
-
-bool CBrain::ReadStack(FILE *file)
-{
- short op;
-
- fRead(&op, sizeof(short), 1, file);
- if ( op == 1 ) // run ?
- {
- fRead(&op, sizeof(short), 1, file); // program rank
- if ( op >= 0 && op < BRAINMAXSCRIPT )
- {
- m_program = op; // program restarts
- m_selScript = op;
- BlinkScript(true); // blink
-
- if ( m_script[op] == 0 )
- {
- m_script[op] = new CScript(m_iMan, m_object, &m_secondaryTask);
- }
- if ( !m_script[op]->ReadStack(file) ) return false;
- }
- }
-
- return true;
-}
-
-// ave the script implementation stack of a file.
-
-bool CBrain::WriteStack(FILE *file)
-{
- short op;
-
- if ( m_program != -1 && // current program?
- m_script[m_program]->IsRunning() )
- {
- op = 1; // run
- fWrite(&op, sizeof(short), 1, file);
-
- op = m_program;
- fWrite(&op, sizeof(short), 1, file);
-
- return m_script[m_program]->WriteStack(file);
- }
-
- op = 0; // stop
- fWrite(&op, sizeof(short), 1, file);
- return true;
-}
-
-
-
-// Start of registration of the design.
-
-void CBrain::TraceRecordStart()
-{
- m_traceOper = TO_STOP;
-
- m_tracePos = m_object->RetPosition(0);
- m_traceAngle = m_object->RetAngleY(0);
-
- if ( m_object->RetTraceDown() ) // pencil down?
- {
- m_traceColor = m_object->RetTraceColor();
- }
- else // pen up?
- {
- m_traceColor = -1;
- }
-
- delete m_traceRecordBuffer;
- m_traceRecordBuffer = (TraceRecord*)malloc(sizeof(TraceRecord)*MAXTRACERECORD);
- m_traceRecordIndex = 0;
-}
-
-// Saving the current drawing.
-
-void CBrain::TraceRecordFrame()
-{
- TraceOper oper = TO_STOP;
- Math::Vector pos;
- float angle, len, speed;
- int color;
-
- speed = m_physics->RetLinMotionX(MO_REASPEED);
- if ( speed > 0.0f ) oper = TO_ADVANCE;
- if ( speed < 0.0f ) oper = TO_RECEDE;
-
- speed = m_physics->RetCirMotionY(MO_REASPEED);
- if ( speed != 0.0f ) oper = TO_TURN;
-
- if ( m_object->RetTraceDown() ) // pencil down?
- {
- color = m_object->RetTraceColor();
- }
- else // pen up?
- {
- color = -1;
- }
-
- if ( oper != m_traceOper ||
- color != m_traceColor )
- {
- if ( m_traceOper == TO_ADVANCE ||
- m_traceOper == TO_RECEDE )
- {
- pos = m_object->RetPosition(0);
- len = Math::DistanceProjected(pos, m_tracePos);
- TraceRecordOper(m_traceOper, len);
- }
- if ( m_traceOper == TO_TURN )
- {
- angle = m_object->RetAngleY(0)-m_traceAngle;
- TraceRecordOper(m_traceOper, angle);
- }
-
- if ( color != m_traceColor )
- {
- TraceRecordOper(TO_PEN, (float)color);
- }
-
- m_traceOper = oper;
- m_tracePos = m_object->RetPosition(0);
- m_traceAngle = m_object->RetAngleY(0);
- m_traceColor = color;
- }
-}
-
-// End of the registration of the design. Program generates the CBOT.
-
-void CBrain::TraceRecordStop()
-{
- TraceOper lastOper, curOper;
- float lastParam, curParam;
- int max, i;
- char* buffer;
-
- if ( m_traceRecordBuffer == 0 ) return;
-
- max = 10000;
- buffer = (char*)malloc(max);
- *buffer = 0;
- strncat(buffer, "extern void object::AutoDraw()\n{\n", max-1);
-
- lastOper = TO_STOP;
- lastParam = 0.0f;
- for ( i=0 ; i<m_traceRecordIndex ; i++ )
- {
- curOper = m_traceRecordBuffer[i].oper;
- curParam = m_traceRecordBuffer[i].param;
-
- if ( curOper == lastOper )
- {
- if ( curOper == TO_PEN )
- {
- lastParam = curParam;
- }
- else
- {
- lastParam += curParam;
- }
- }
- else
- {
- TraceRecordPut(buffer, max, lastOper, lastParam);
- lastOper = curOper;
- lastParam = curParam;
- }
- }
- TraceRecordPut(buffer, max, lastOper, lastParam);
-
- delete m_traceRecordBuffer;
- m_traceRecordBuffer = 0;
-
- strncat(buffer, "}\n", max-1);
- buffer[max-1] = 0;
-
- i = m_selScript;
- if ( m_script[i] == 0 )
- {
- m_script[i] = new CScript(m_iMan, m_object, &m_secondaryTask);
- }
- m_script[i]->SendScript(buffer);
- delete buffer;
-}
-
-// Saves an instruction CBOT.
-
-bool CBrain::TraceRecordOper(TraceOper oper, float param)
-{
- int i;
-
- i = m_traceRecordIndex;
- if ( i >= MAXTRACERECORD ) return false;
-
- m_traceRecordBuffer[i].oper = oper;
- m_traceRecordBuffer[i].param = param;
-
- m_traceRecordIndex = i+1;
- return true;
-}
-
-// Generates an instruction CBOT.
-
-bool CBrain::TraceRecordPut(char *buffer, int max, TraceOper oper, float param)
-{
- char line[100];
- int color;
-
- if ( oper == TO_ADVANCE )
- {
- param /= g_unit;
- sprintf(line, "\tmove(%.1f);\n", param);
- strncat(buffer, line, max-1);
- }
-
- if ( oper == TO_RECEDE )
- {
- param /= g_unit;
- sprintf(line, "\tmove(-%.1f);\n", param);
- strncat(buffer, line, max-1);
- }
-
- if ( oper == TO_TURN )
- {
- param = -param*180.0f/Math::PI;
- sprintf(line, "\tturn(%d);\n", (int)param);
-//? sprintf(line, "\tturn(%.1f);\n", param);
- strncat(buffer, line, max-1);
- }
-
- if ( oper == TO_PEN )
- {
- color = (int)param;
- if ( color == -1 ) strncat(buffer, "\tpenup();\n", max-1);
- if ( color == 1 ) strncat(buffer, "\tpendown(Black);\n", max-1);
- if ( color == 8 ) strncat(buffer, "\tpendown(Yellow);\n", max-1);
- if ( color == 7 ) strncat(buffer, "\tpendown(Orange);\n", max-1);
- if ( color == 4 ) strncat(buffer, "\tpendown(Red);\n", max-1);
- if ( color == 6 ) strncat(buffer, "\tpendown(Purple);\n", max-1);
- if ( color == 14 ) strncat(buffer, "\tpendown(Blue);\n", max-1);
- if ( color == 12 ) strncat(buffer, "\tpendown(Green);\n", max-1);
- if ( color == 10 ) strncat(buffer, "\tpendown(Brown);\n", max-1);
- }
-
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <stdio.h>
+
+#include "object/brain.h"
+
+#include "CBot/CBotDll.h"
+#include "common/struct.h"
+#include "math/geometry.h"
+#include "math/const.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/language.h"
+#include "common/global.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "old/math3d.h"
+#include "object/robotmain.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "old/camera.h"
+#include "object/object.h"
+#include "physics/physics.h"
+#include "object/motion/motion.h"
+#include "object/motion/motionspider.h"
+#include "old/pyro.h"
+#include "object/task/taskmanager.h"
+#include "object/task/task.h"
+#include "object/task/taskmanip.h"
+#include "object/task/taskflag.h"
+#include "object/task/taskshield.h"
+#include "script/script.h"
+#include "ui/studio.h"
+#include "ui/interface.h"
+#include "ui/button.h"
+#include "ui/color.h"
+#include "ui/edit.h"
+#include "ui/list.h"
+#include "ui/label.h"
+#include "ui/group.h"
+#include "ui/gauge.h"
+#include "ui/slider.h"
+#include "ui/compass.h"
+#include "ui/target.h"
+#include "ui/window.h"
+#include "ui/displaytext.h"
+#include "old/text.h"
+#include "old/sound.h"
+#include "old/particule.h"
+#include "script/cmdtoken.h"
+
+
+
+const int MAXTRACERECORD = 1000;
+
+
+
+// Object's constructor.
+
+CBrain::CBrain(CInstanceManager* iMan, CObject* object)
+{
+ int i;
+
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_BRAIN, this, 100);
+
+ m_object = object;
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+ m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_physics = 0;
+ m_motion = 0;
+ m_primaryTask = 0;
+ m_secondaryTask = 0;
+ m_studio = 0;
+
+ m_program = -1;
+ m_bActivity = true;
+ m_bBurn = false;
+ m_bActiveVirus = false;
+ m_time = 0.0f;
+ m_burnTime = 0.0f;
+ m_lastUpdateTime = 0.0f;
+ m_lastHumanTime = 0.0f;
+ m_lastWormTime = 0.0f;
+ m_antTarget = 0;
+ m_beeBullet = 0;
+ m_lastAlarmTime = 0.0f;
+ m_soundChannelAlarm = -1;
+ m_flagColor = 0;
+
+ m_buttonAxe = EVENT_NULL;
+ m_defaultEnter = EVENT_NULL;
+ m_manipStyle = EVENT_OBJECT_MFRONT;
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ m_script[i] = 0;
+ m_scriptName[i][0] = 0;
+ }
+ m_scriptRun = -1;
+ m_soluceName[0] = 0;
+ m_selScript = 0;
+
+ m_bTraceRecord = false;
+ m_traceRecordBuffer = 0;
+}
+
+// Object's destructor.
+
+CBrain::~CBrain()
+{
+ int i;
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ delete m_script[i];
+ }
+
+ delete m_primaryTask;
+ delete m_secondaryTask;
+ delete m_studio;
+ delete m_traceRecordBuffer;
+ m_iMan->DeleteInstance(CLASS_BRAIN, this);
+}
+
+
+// Destroys the object.
+
+void CBrain::DeleteObject(bool bAll)
+{
+ if ( m_soundChannelAlarm != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannelAlarm);
+ m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 0.5f, 0.5f, SOPER_STOP);
+ m_soundChannelAlarm = -1;
+ }
+
+ if ( !bAll )
+ {
+ if ( m_beeBullet != 0 )
+ {
+ m_beeBullet->DeleteObject();
+ delete m_beeBullet;
+ m_beeBullet = 0;
+ }
+ }
+
+ if ( m_studio != 0 ) // current edition?
+ {
+ StopEditScript(true);
+ }
+}
+
+
+void CBrain::SetPhysics(CPhysics* physics)
+{
+ m_physics = physics;
+}
+
+void CBrain::SetMotion(CMotion* motion)
+{
+ m_motion = motion;
+}
+
+
+// Saves all parameters of the object.
+
+bool CBrain::Write(char *line)
+{
+ char name[100];
+
+ sprintf(name, " bVirusActive=%d", m_bActiveVirus);
+ strcat(line, name);
+
+ return true;
+}
+
+// Restores all parameters of the object.
+
+bool CBrain::Read(char *line)
+{
+ m_bActiveVirus = OpInt(line, "bVirusActive", 0);
+
+ return true;
+}
+
+
+// Management of an event.
+
+bool CBrain::EventProcess(const Event &event)
+{
+ CWindow* pw;
+ CControl* pc;
+ CSlider* ps;
+ EventMsg action;
+ ObjectType type;
+ Error err;
+ float axeX, axeY, axeZ, factor;
+
+ type = m_object->RetType();
+
+ if ( m_primaryTask != 0 ) // current task?
+ {
+ m_primaryTask->EventProcess(event);
+ }
+
+ if ( m_secondaryTask != 0 ) // current task?
+ {
+ m_secondaryTask->EventProcess(event);
+ }
+
+ action = EVENT_NULL;
+
+ if ( event.event == EVENT_KEYDOWN &&
+ (event.param == m_engine->RetKey(KEYRANK_ACTION, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_ACTION, 1) ) &&
+ !m_main->RetEditLock() )
+ {
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw != 0 )
+ {
+ pc = pw->SearchControl(m_defaultEnter);
+ if ( pc != 0 )
+ {
+ if ( pc->TestState(STATE_ENABLE) )
+ {
+ action = m_defaultEnter;
+ }
+ }
+ }
+ }
+ else
+ {
+ action = event.event;
+ }
+
+ if ( action == EVENT_NULL ) return true;
+
+ if ( action == EVENT_UPDINTERFACE )
+ {
+ if ( m_object->RetSelect() ) CreateInterface(true);
+ }
+
+ if ( action == EVENT_FRAME )
+ {
+ EventFrame(event);
+ }
+
+ if ( m_object->RetSelect() && // robot selected?
+ m_studio != 0 ) // current issue?
+ {
+ m_studio->EventProcess(event);
+
+ if ( action == EVENT_OBJECT_PROGRUN )
+ {
+ if ( m_program == -1 )
+ {
+ RunProgram(m_selScript);
+ }
+ else
+ {
+ StopProgram();
+ }
+ }
+ if ( action == EVENT_OBJECT_PROGSTART )
+ {
+ m_main->SaveOneScript(m_object);
+ RunProgram(m_selScript);
+ }
+ if ( action == EVENT_OBJECT_PROGSTOP )
+ {
+ StopProgram();
+ }
+ if ( action == EVENT_STUDIO_OK )
+ {
+ StopEditScript(false);
+ m_main->SaveOneScript(m_object);
+ }
+ if ( action == EVENT_STUDIO_CANCEL )
+ {
+ StopEditScript(true);
+ m_main->SaveOneScript(m_object);
+ }
+ return true;
+ }
+
+ if ( !m_object->RetSelect() && // robot pas sélectionné ?
+ m_program == -1 &&
+ m_primaryTask == 0 )
+ {
+ axeX = 0.0f;
+ axeY = 0.0f;
+ axeZ = 0.0f;
+ if ( m_object->RetBurn() ) // Gifted?
+ {
+ if ( !m_bBurn ) // beginning?
+ {
+ m_bBurn = true;
+ m_burnTime = 0.0f;
+ }
+
+ axeZ = -1.0f; // tomb
+
+ if ( !m_object->RetFixed() &&
+ (type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_WORM ) )
+ {
+ axeY = 2.0f; // zigzag disorganized fast
+ if ( type == OBJECT_WORM ) axeY = 5.0f;
+ axeX = 0.5f+sinf(m_time* 1.0f)*0.5f+
+ sinf(m_time* 6.0f)*2.0f+
+ sinf(m_time*21.0f)*0.2f;
+ factor = 1.0f-m_burnTime/15.0f; // slow motion
+ if ( factor < 0.0f ) factor = 0.0f;
+ axeY *= factor;
+ axeX *= factor;
+ }
+ }
+ m_physics->SetMotorSpeedX(axeY); // move forward/move back
+ m_physics->SetMotorSpeedY(axeZ); // up / down
+ m_physics->SetMotorSpeedZ(axeX); // rotate
+ return true;
+ }
+
+ if ( m_program != -1 &&
+ m_object->RetRuin() )
+ {
+ StopProgram();
+ return true;
+ }
+
+ if ( !m_object->RetSelect() ) // robot not selected?
+ {
+ return true;
+ }
+
+ if ( m_secondaryTask != 0 ) // current task?
+ {
+ if ( action == EVENT_OBJECT_ENDSHIELD )
+ {
+ m_secondaryTask->StartTaskShield(TSM_DOWN, 0.0f);
+ }
+ }
+ if ( m_primaryTask != 0 || // current task?
+ m_program != -1 )
+ {
+ if ( action == EVENT_OBJECT_PROGRUN )
+ {
+ StopProgram();
+ }
+ if ( action == EVENT_OBJECT_PROGEDIT )
+ {
+ StartEditScript(m_selScript, m_main->RetScriptName());
+ }
+ if ( m_primaryTask == 0 || !m_primaryTask->IsPilot() ) return true;
+ }
+
+ if ( action == EVENT_OBJECT_LEFT ||
+ action == EVENT_OBJECT_RIGHT ||
+ action == EVENT_OBJECT_UP ||
+ action == EVENT_OBJECT_DOWN ||
+ action == EVENT_OBJECT_GASUP ||
+ action == EVENT_OBJECT_GASDOWN )
+ {
+ m_buttonAxe = action;
+ }
+ if ( action == EVENT_LBUTTONUP ||
+ action == EVENT_RBUTTONUP )
+ {
+ m_buttonAxe = EVENT_NULL;
+ }
+
+ axeX = event.axeX;
+ axeY = event.axeY;
+ axeZ = event.axeZ;
+
+ if ( !m_main->RetTrainerPilot() &&
+ m_object->RetTrainer() ) // drive vehicle?
+ {
+ axeX = 0.0f;
+ axeY = 0.0f;
+ axeZ = 0.0f; // Remote control impossible!
+ }
+
+ if ( m_buttonAxe == EVENT_OBJECT_LEFT ) axeX = -1.0f;
+ if ( m_buttonAxe == EVENT_OBJECT_RIGHT ) axeX = 1.0f;
+ if ( m_buttonAxe == EVENT_OBJECT_UP ) axeY = 1.0f;
+ if ( m_buttonAxe == EVENT_OBJECT_DOWN ) axeY = -1.0f;
+ if ( m_buttonAxe == EVENT_OBJECT_GASUP ) axeZ = 1.0f;
+ if ( m_buttonAxe == EVENT_OBJECT_GASDOWN ) axeZ = -1.0f;
+
+ if ( m_object->RetManual() ) // scribbler in manual mode?
+ {
+ if ( axeX != 0.0f ) axeY = 0.0f; // if running -> not moving!
+ axeX *= 0.5f;
+ axeY *= 0.5f;
+ }
+
+ if ( (g_researchDone&RESEARCH_FLY) == 0 )
+ {
+ axeZ = -1.0f; // tomb
+ }
+
+ axeX += m_camera->RetMotorTurn(); // additional power according to camera
+ if ( axeX > 1.0f ) axeX = 1.0f;
+ if ( axeX < -1.0f ) axeX = -1.0f;
+
+ m_physics->SetMotorSpeedX(axeY); // move forward/move back
+ m_physics->SetMotorSpeedY(axeZ); // up/down
+ m_physics->SetMotorSpeedZ(axeX); // rotate
+
+ if ( action == EVENT_OBJECT_PROGLIST )
+ {
+ m_selScript = RetSelScript();
+ UpdateInterface();
+ }
+
+ if ( action == EVENT_OBJECT_PROGEDIT )
+ {
+ StartEditScript(m_selScript, m_main->RetScriptName());
+ }
+
+ if ( action == EVENT_OBJECT_PROGRUN )
+ {
+ StopProgram(); // stops the current program
+ RunProgram(m_selScript);
+ UpdateInterface();
+ }
+
+ err = ERR_OK;
+
+ if ( m_program == -1 )
+ {
+ if ( action == EVENT_OBJECT_HTAKE )
+ {
+ err = StartTaskTake();
+ }
+
+ if ( action == EVENT_OBJECT_MFRONT ||
+ action == EVENT_OBJECT_MBACK ||
+ action == EVENT_OBJECT_MPOWER )
+ {
+ m_manipStyle = action;
+ UpdateInterface();
+ }
+
+ if ( action == EVENT_OBJECT_MTAKE )
+ {
+ if ( m_manipStyle == EVENT_OBJECT_MFRONT )
+ {
+ err = StartTaskManip(TMO_AUTO, TMA_FFRONT);
+ }
+ if ( m_manipStyle == EVENT_OBJECT_MBACK )
+ {
+ err = StartTaskManip(TMO_AUTO, TMA_FBACK);
+ if ( err == ERR_OK )
+ {
+ m_manipStyle = EVENT_OBJECT_MFRONT;
+ UpdateInterface();
+ }
+ }
+ if ( m_manipStyle == EVENT_OBJECT_MPOWER )
+ {
+ err = StartTaskManip(TMO_AUTO, TMA_POWER);
+ if ( err == ERR_OK )
+ {
+ m_manipStyle = EVENT_OBJECT_MFRONT;
+ UpdateInterface();
+ }
+ }
+ }
+
+ if ( action == EVENT_OBJECT_BDERRICK )
+ {
+ err = StartTaskBuild(OBJECT_DERRICK);
+ }
+ if ( action == EVENT_OBJECT_BSTATION )
+ {
+ err = StartTaskBuild(OBJECT_STATION);
+ }
+ if ( action == EVENT_OBJECT_BFACTORY )
+ {
+ err = StartTaskBuild(OBJECT_FACTORY);
+ }
+ if ( action == EVENT_OBJECT_BREPAIR )
+ {
+ err = StartTaskBuild(OBJECT_REPAIR);
+ }
+ if ( action == EVENT_OBJECT_BCONVERT )
+ {
+ err = StartTaskBuild(OBJECT_CONVERT);
+ }
+ if ( action == EVENT_OBJECT_BTOWER )
+ {
+ err = StartTaskBuild(OBJECT_TOWER);
+ }
+ if ( action == EVENT_OBJECT_BRESEARCH )
+ {
+ err = StartTaskBuild(OBJECT_RESEARCH);
+ }
+ if ( action == EVENT_OBJECT_BRADAR )
+ {
+ err = StartTaskBuild(OBJECT_RADAR);
+ }
+ if ( action == EVENT_OBJECT_BENERGY )
+ {
+ err = StartTaskBuild(OBJECT_ENERGY);
+ }
+ if ( action == EVENT_OBJECT_BLABO )
+ {
+ err = StartTaskBuild(OBJECT_LABO);
+ }
+ if ( action == EVENT_OBJECT_BNUCLEAR )
+ {
+ err = StartTaskBuild(OBJECT_NUCLEAR);
+ }
+ if ( action == EVENT_OBJECT_BPARA )
+ {
+ err = StartTaskBuild(OBJECT_PARA);
+ }
+ if ( action == EVENT_OBJECT_BINFO )
+ {
+ err = StartTaskBuild(OBJECT_INFO);
+ }
+
+ if ( action == EVENT_OBJECT_GFLAT )
+ {
+ GroundFlat();
+ }
+ if ( action == EVENT_OBJECT_FCREATE )
+ {
+ err = StartTaskFlag(TFL_CREATE, m_flagColor);
+ }
+ if ( action == EVENT_OBJECT_FDELETE )
+ {
+ err = StartTaskFlag(TFL_DELETE, m_flagColor);
+ }
+ if ( action == EVENT_OBJECT_FCOLORb ||
+ action == EVENT_OBJECT_FCOLORr ||
+ action == EVENT_OBJECT_FCOLORg ||
+ action == EVENT_OBJECT_FCOLORy ||
+ action == EVENT_OBJECT_FCOLORv )
+ {
+ ColorFlag(action-EVENT_OBJECT_FCOLORb);
+ }
+
+ if ( action == EVENT_OBJECT_SEARCH )
+ {
+ err = StartTaskSearch();
+ }
+
+ if ( action == EVENT_OBJECT_TERRAFORM )
+ {
+ err = StartTaskTerraform();
+ }
+
+ if ( action == EVENT_OBJECT_RECOVER )
+ {
+ err = StartTaskRecover();
+ }
+
+ if ( action == EVENT_OBJECT_BEGSHIELD )
+ {
+ err = StartTaskShield(TSM_UP);
+ }
+
+ if ( action == EVENT_OBJECT_DIMSHIELD )
+ {
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw != 0 )
+ {
+ ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_DIMSHIELD);
+ if ( ps != 0 )
+ {
+ m_object->SetParam((ps->RetVisibleValue()-(RADIUS_SHIELD_MIN/g_unit))/((RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)/g_unit));
+ }
+ }
+ }
+
+ if ( action == EVENT_OBJECT_FIRE && m_primaryTask == 0 && !m_object->RetTrainer())
+ {
+ if ( m_camera->RetType() != CAMERA_ONBOARD )
+ {
+ m_camera->SetType(CAMERA_ONBOARD);
+ }
+ err = StartTaskFire(0.0f);
+ }
+ if ( action == EVENT_OBJECT_TARGET && !m_object->RetTrainer() )
+ {
+ err = StartTaskGunGoal((event.pos.y-0.50f)*1.3f, (event.pos.x-0.50f)*2.0f);
+ }
+
+ if ( action == EVENT_OBJECT_FIREANT )
+ {
+//? err = StartTaskFireAnt();
+ }
+
+ if ( action == EVENT_OBJECT_PEN0 ) // up
+ {
+ err = StartTaskPen(false, m_object->RetTraceColor());
+ m_object->SetTraceDown(false);
+ }
+ if ( action == EVENT_OBJECT_PEN1 ) // black
+ {
+ err = StartTaskPen(true, 1);
+ m_object->SetTraceDown(true);
+ m_object->SetTraceColor(1);
+ }
+ if ( action == EVENT_OBJECT_PEN2 ) // yellow
+ {
+ err = StartTaskPen(true, 8);
+ m_object->SetTraceDown(true);
+ m_object->SetTraceColor(8);
+ }
+ if ( action == EVENT_OBJECT_PEN3 ) // orange
+ {
+ err = StartTaskPen(true, 7);
+ m_object->SetTraceDown(true);
+ m_object->SetTraceColor(7);
+ }
+ if ( action == EVENT_OBJECT_PEN4 ) // red
+ {
+ err = StartTaskPen(true, 4);
+ m_object->SetTraceDown(true);
+ m_object->SetTraceColor(4);
+ }
+ if ( action == EVENT_OBJECT_PEN5 ) // violet
+ {
+ err = StartTaskPen(true, 6);
+ m_object->SetTraceDown(true);
+ m_object->SetTraceColor(6);
+ }
+ if ( action == EVENT_OBJECT_PEN6 ) // blue
+ {
+ err = StartTaskPen(true, 14);
+ m_object->SetTraceDown(true);
+ m_object->SetTraceColor(14);
+ }
+ if ( action == EVENT_OBJECT_PEN7 ) // green
+ {
+ err = StartTaskPen(true, 12);
+ m_object->SetTraceDown(true);
+ m_object->SetTraceColor(12);
+ }
+ if ( action == EVENT_OBJECT_PEN8 ) // brown
+ {
+ err = StartTaskPen(true, 10);
+ m_object->SetTraceDown(true);
+ m_object->SetTraceColor(10);
+ }
+
+ if ( action == EVENT_OBJECT_REC ) // registered?
+ {
+ if ( m_bTraceRecord )
+ {
+ m_bTraceRecord = false;
+ TraceRecordStop();
+ }
+ else
+ {
+ m_bTraceRecord = true;
+ TraceRecordStart();
+ }
+ UpdateInterface();
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw != 0 )
+ {
+ UpdateScript(pw);
+ }
+ }
+ if ( action == EVENT_OBJECT_STOP ) // stops?
+ {
+ if ( m_bTraceRecord )
+ {
+ m_bTraceRecord = false;
+ TraceRecordStop();
+ }
+ UpdateInterface();
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw != 0 )
+ {
+ UpdateScript(pw);
+ }
+ }
+
+ if ( action == EVENT_OBJECT_RESET )
+ {
+ m_main->ResetObject(); // reset all objects
+ UpdateInterface();
+ }
+
+#if 0
+ if ( event.param == 'T' )
+ {
+ Math::Vector p1, p2;
+ float h;
+ p1 = m_object->RetPosition(0);
+ h = m_terrain->RetFloorLevel(p1);
+ p2 = p1;
+ p1.x -= 20.0f;
+ p1.z -= 20.0f;
+ p2.x += 20.0f;
+ p2.z += 20.0f;
+ m_terrain->Terraform(p1, p2, h+1.0f);
+ }
+ if ( event.param == 'R' )
+ {
+ Math::Vector p1, p2;
+ float h;
+ p1 = m_object->RetPosition(0);
+ h = m_terrain->RetFloorLevel(p1);
+ p2 = p1;
+ p1.x -= 20.0f;
+ p1.z -= 20.0f;
+ p2.x += 20.0f;
+ p2.z += 20.0f;
+ m_terrain->Terraform(p1, p2, h-1.0f);
+ }
+#endif
+ }
+
+ if ( err != ERR_OK )
+ {
+ m_displayText->DisplayError(err, m_object);
+ }
+
+ return true;
+}
+
+
+// The brain is changing by time.
+
+bool CBrain::EventFrame(const Event &event)
+{
+ m_time += event.rTime;
+ if ( m_bBurn ) m_burnTime += event.rTime;
+
+ if ( m_soundChannelAlarm != -1 )
+ {
+ m_sound->Position(m_soundChannelAlarm, m_object->RetPosition(0));
+ }
+
+ if ( m_studio != 0 ) // �urrent edition?
+ {
+ m_studio->EventProcess(event);
+ }
+
+ UpdateInterface(event.rTime);
+
+ if ( m_engine->RetPause() ) return true;
+ if ( !m_bActivity ) return true; // expected if idle
+ if ( EndedTask() == ERR_CONTINUE ) return true; // expected if not finished ...
+
+ if ( m_program != -1 ) // current program?
+ {
+ if ( m_script[m_program]->Continue(event) )
+ {
+ StopProgram();
+ }
+ }
+
+ if ( m_bTraceRecord ) // registration of the design in progress?
+ {
+ TraceRecordFrame();
+ }
+
+ return true;
+}
+
+
+// Stops the running program.
+
+void CBrain::StopProgram()
+{
+ StopTask();
+
+ if ( m_object->RetType() == OBJECT_HUMAN ||
+ m_object->RetType() == OBJECT_TECH ) return;
+
+ if ( m_program != -1 &&
+ m_script[m_program] != 0 )
+ {
+ m_script[m_program]->Stop();
+ }
+
+ BlinkScript(false); // stops flashing
+
+ m_program = -1;
+
+ m_physics->SetMotorSpeedX(0.0f);
+ m_physics->SetMotorSpeedY(0.0f);
+ m_physics->SetMotorSpeedZ(0.0f);
+
+ m_motion->SetAction(-1);
+
+ UpdateInterface();
+ m_main->UpdateShortcuts();
+ m_object->CreateSelectParticule();
+}
+
+// Stops the current task.
+
+void CBrain::StopTask()
+{
+ if ( m_primaryTask != 0 )
+ {
+ m_primaryTask->Abort();
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+}
+
+
+// Introduces a virus into a program.
+// Returns true if it was inserted.
+
+bool CBrain::IntroduceVirus()
+{
+ int i, j;
+
+ for ( i=0 ; i<50 ; i++ )
+ {
+ j = rand()%BRAINMAXSCRIPT;
+ if ( m_script[j] != 0 )
+ {
+ if ( m_script[j]->IntroduceVirus() ) // tries to introduce
+ {
+ m_bActiveVirus = true; // active virus
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// Active Virus indicates that the object is contaminated. Unlike ch'tites (??? - Programerus)
+// letters which automatically disappear after a while,
+// ActiveVirus does not disappear after you edit the program
+// (Even if the virus is not fixed).
+
+
+void CBrain::SetActiveVirus(bool bActive)
+{
+ m_bActiveVirus = bActive;
+
+ if ( !m_bActiveVirus ) // virus disabled?
+ {
+ m_object->SetVirusMode(false); // chtites (??? - Programerus) letters also
+ }
+}
+
+bool CBrain::RetActiveVirus()
+{
+ return m_bActiveVirus;
+}
+
+
+// Start editing a program.
+
+void CBrain::StartEditScript(int rank, char* name)
+{
+ CreateInterface(false); // removes the control buttons
+
+ if ( m_script[rank] == 0 )
+ {
+ m_script[rank] = new CScript(m_iMan, m_object, &m_secondaryTask);
+ }
+
+ m_studio = new CStudio(m_iMan);
+ m_studio->StartEditScript(m_script[rank], name, rank);
+}
+
+// End of editing a program.
+
+void CBrain::StopEditScript(bool bCancel)
+{
+ if ( !bCancel ) SetActiveVirus(false);
+
+ if ( !m_studio->StopEditScript(bCancel) ) return;
+
+ delete m_studio;
+ m_studio = 0;
+
+ CreateInterface(true); // puts the control buttons
+}
+
+
+
+// Move the manipulator arm.
+
+Error CBrain::StartTaskTake()
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskTake();
+ UpdateInterface();
+ return err;
+}
+
+// Move the manipulator arm.
+
+Error CBrain::StartTaskManip(TaskManipOrder order, TaskManipArm arm)
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskManip(order, arm);
+ UpdateInterface();
+ return err;
+}
+
+// Puts or removes a flag.
+
+Error CBrain::StartTaskFlag(TaskFlagOrder order, int rank)
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskFlag(order, rank);
+ UpdateInterface();
+ return err;
+}
+
+// Built a building.
+
+Error CBrain::StartTaskBuild(ObjectType type)
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskBuild(type);
+ UpdateInterface();
+ return err;
+}
+
+// Probe the ground.
+
+Error CBrain::StartTaskSearch()
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskSearch();
+ UpdateInterface();
+ return err;
+}
+
+// Terraformed the ground.
+
+Error CBrain::StartTaskTerraform()
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskTerraform();
+ UpdateInterface();
+ return err;
+}
+
+// Change pencil.
+
+Error CBrain::StartTaskPen(bool bDown, int color)
+{
+ Error err;
+
+ m_physics->SetMotorSpeedX(0.0f);
+ m_physics->SetMotorSpeedY(0.0f);
+ m_physics->SetMotorSpeedZ(0.0f);
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskPen(bDown, color);
+ UpdateInterface();
+ return err;
+}
+
+// Recovers a ruin.
+
+Error CBrain::StartTaskRecover()
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskRecover();
+ UpdateInterface();
+ return err;
+}
+
+// Deploys the shield.
+
+Error CBrain::StartTaskShield(TaskShieldMode mode)
+{
+ Error err;
+
+ if ( m_secondaryTask != 0 )
+ {
+ delete m_secondaryTask; // stops the current task
+ m_secondaryTask = 0;
+ }
+
+ m_secondaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_secondaryTask->StartTaskShield(mode, 1000.0f);
+ UpdateInterface();
+ return err;
+}
+
+// Shoots.
+
+Error CBrain::StartTaskFire(float delay)
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskFire(delay);
+ UpdateInterface();
+ return err;
+}
+
+// Shoots to the ant.
+
+Error CBrain::StartTaskFireAnt(Math::Vector impact)
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskFireAnt(impact);
+ UpdateInterface();
+ return err;
+}
+
+// Adjusts upward.
+
+Error CBrain::StartTaskGunGoal(float dirV, float dirH)
+{
+ Error err;
+
+ if ( m_secondaryTask != 0 )
+ {
+ delete m_secondaryTask; // stops the current task
+ m_secondaryTask = 0;
+ }
+
+ m_secondaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_secondaryTask->StartTaskGunGoal(dirV, dirH);
+ UpdateInterface();
+ return err;
+}
+
+// Reset.
+
+Error CBrain::StartTaskReset(Math::Vector goal, Math::Vector angle)
+{
+ Error err;
+
+ if ( m_primaryTask != 0 )
+ {
+ delete m_primaryTask; // stops the current task
+ m_primaryTask = 0;
+ }
+
+ m_primaryTask = new CTaskManager(m_iMan, m_object);
+ err = m_primaryTask->StartTaskReset(goal, angle);
+ UpdateInterface();
+ return err;
+}
+
+// Completes the task when the time came.
+
+Error CBrain::EndedTask()
+{
+ Error err;
+
+ if ( m_secondaryTask != 0 ) // current task?
+ {
+ err = m_secondaryTask->IsEnded();
+ if ( err != ERR_CONTINUE ) // job ended?
+ {
+ delete m_secondaryTask;
+ m_secondaryTask = 0;
+ UpdateInterface();
+ }
+ }
+
+ if ( m_primaryTask != 0 ) // current task?
+ {
+ err = m_primaryTask->IsEnded();
+ if ( err != ERR_CONTINUE ) // job ended?
+ {
+ delete m_primaryTask;
+ m_primaryTask = 0;
+ UpdateInterface();
+ }
+ return err;
+ }
+ return ERR_STOP;
+}
+
+
+
+// Shows flat areas in the field.
+
+void CBrain::GroundFlat()
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+ Error err;
+ float level;
+
+ if ( !m_physics->RetLand() )
+ {
+ err = ERR_FLAG_FLY;
+ pos = m_object->RetPosition(0);
+ if ( pos.y < m_water->RetLevel() ) err = ERR_FLAG_WATER;
+ m_displayText->DisplayError(err, m_object);
+ return;
+ }
+
+ pos = m_object->RetPosition(0);
+ m_terrain->GroundFlat(pos);
+ m_sound->Play(SOUND_GFLAT, pos);
+
+ level = m_terrain->RetFloorLevel(pos)+2.0f;
+ if ( pos.y < level ) pos.y = level; // not below the soil
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 40.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGFLAT, 1.0f);
+}
+
+
+// Not below the soil.
+
+void CBrain::ColorFlag(int color)
+{
+ m_flagColor = color;
+ UpdateInterface();
+}
+
+
+// Creates all the interface when the object is selected.
+
+bool CBrain::CreateInterface(bool bSelect)
+{
+ ObjectType type;
+ CWindow* pw;
+ CButton* pb;
+ CColor* pc;
+ CSlider* ps;
+ CTarget* pt;
+ CLabel* pl;
+ Math::Point pos, dim, ddim;
+ float ox, oy, sx, sy;
+ char name[100];
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw != 0 )
+ {
+ pw->Flush(); // destroys the window buttons
+ m_interface->DeleteControl(EVENT_WINDOW0); // destroys the window
+ }
+ m_defaultEnter = EVENT_NULL;
+
+ if ( !bSelect ) return true;
+
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ dim.x = 540.0f/640.0f;
+ if ( !m_main->RetShowMap() ) dim.x = 640.0f/640.0f;
+ dim.y = 86.0f/480.0f;
+ m_interface->CreateWindows(pos, dim, 3, EVENT_WINDOW0);
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return false;
+
+ m_object->GetTooltipName(name);
+ pos.x = 0.0f;
+ pos.y = 64.0f/480.0f;
+ ddim.x = 540.0f/640.0f;
+ if ( !m_main->RetShowMap() ) ddim.x = 640.0f/640.0f;
+ ddim.y = 16.0f/480.0f;
+ pw->CreateLabel(pos, ddim, 0, EVENT_LABEL0, name);
+
+ dim.x = 33.0f/640.0f;
+ dim.y = 33.0f/480.0f;
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = 33.0f/640.0f;
+ sy = 33.0f/480.0f;
+
+ type = m_object->RetType();
+
+ 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_MOBILEtg ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr ||
+ type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ) // vehicle?
+ {
+ ddim.x = dim.x*5.1f;
+ ddim.y = dim.y*2.0f;
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0.0f;
+ pw->CreateList(pos, ddim, -1, EVENT_OBJECT_PROGLIST, 1.10f);
+ UpdateScript(pw);
+
+ pos.x = ox+sx*5.2f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, dim, 8, EVENT_OBJECT_PROGRUN);
+ pos.y = oy+sy*0.0f;
+ pw->CreateButton(pos, dim, 22, EVENT_OBJECT_PROGEDIT);
+ }
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_BEE ) // driving?
+ {
+ pos.x = ox+sx*6.4f;
+ pos.y = oy+sy*0;
+ pb = pw->CreateButton(pos, dim, 29, EVENT_OBJECT_GASDOWN);
+ pb->SetImmediat(true);
+
+ pos.x = ox+sx*6.4f;
+ pos.y = oy+sy*1;
+ pb = pw->CreateButton(pos, dim, 28, EVENT_OBJECT_GASUP);
+ pb->SetImmediat(true);
+
+ if ( type != OBJECT_HUMAN ||
+ m_object->RetOption() != 2 )
+ {
+ pos.x = ox+sx*15.3f;
+ pos.y = oy+sy*0;
+ ddim.x = 14.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 2, EVENT_OBJECT_GRANGE);
+ }
+ }
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH )
+ {
+ pos.x = ox+sx*7.7f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 31, EVENT_OBJECT_HTAKE);
+ DefaultEnter(pw, EVENT_OBJECT_HTAKE);
+ }
+
+ if ( (type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ) && // arm?
+ !m_object->RetTrainer() )
+ {
+ pos.x = ox+sx*7.7f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 32, EVENT_OBJECT_MTAKE);
+ DefaultEnter(pw, EVENT_OBJECT_MTAKE);
+
+ pos.x = ox+sx*8.9f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 34, EVENT_OBJECT_MBACK);
+
+ pos.x = ox+sx*9.9f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 35, EVENT_OBJECT_MPOWER);
+
+ pos.x = ox+sx*10.9f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 33, EVENT_OBJECT_MFRONT);
+ }
+
+ if ( type == OBJECT_MOBILEsa && // underwater?
+ !m_object->RetTrainer() )
+ {
+ pos.x = ox+sx*7.7f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 32, EVENT_OBJECT_MTAKE);
+ DefaultEnter(pw, EVENT_OBJECT_MTAKE);
+ }
+
+ if ( type == OBJECT_HUMAN ) // builder?
+ {
+ pos.x = 1.0f/640.0f;
+ pos.y = 4.0f/480.0f;
+ ddim.x = 212.0f/640.0f;
+ ddim.y = 64.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 27, EVENT_NULL);
+
+ ddim.x = dim.x*0.9f;
+ ddim.y = dim.y*0.9f;
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, ddim, 128+35, EVENT_OBJECT_BRESEARCH);
+ DeadInterface(pw, EVENT_OBJECT_BRESEARCH, g_build&BUILD_RESEARCH);
+
+ pos.x = ox+sx*0.9f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, ddim, 128+32, EVENT_OBJECT_BFACTORY);
+ DeadInterface(pw, EVENT_OBJECT_BFACTORY, g_build&BUILD_FACTORY);
+
+ pos.x = ox+sx*1.8f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, ddim, 128+34, EVENT_OBJECT_BCONVERT);
+ DeadInterface(pw, EVENT_OBJECT_BCONVERT, g_build&BUILD_CONVERT);
+
+ pos.x = ox+sx*2.7f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, ddim, 128+36, EVENT_OBJECT_BSTATION);
+ DeadInterface(pw, EVENT_OBJECT_BSTATION, g_build&BUILD_STATION);
+
+ pos.x = ox+sx*3.6f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, ddim, 128+40, EVENT_OBJECT_BRADAR);
+ DeadInterface(pw, EVENT_OBJECT_BRADAR, g_build&BUILD_RADAR);
+
+ pos.x = ox+sx*4.5f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, ddim, 128+41, EVENT_OBJECT_BREPAIR);
+ DeadInterface(pw, EVENT_OBJECT_BREPAIR, g_build&BUILD_REPAIR);
+
+ pos.x = ox+sx*5.4f;
+ pos.y = oy+sy*1.0f;
+ pw->CreateButton(pos, ddim, 128+44, EVENT_OBJECT_BINFO);
+ DeadInterface(pw, EVENT_OBJECT_BINFO, g_build&BUILD_INFO);
+
+ pos.x = ox+sx*0.0f;
+ pos.y = oy+sy*0.1f;
+ pw->CreateButton(pos, ddim, 128+37, EVENT_OBJECT_BTOWER);
+ DeadInterface(pw, EVENT_OBJECT_BTOWER,
+ (g_build&BUILD_TOWER) &&
+ (g_researchDone & RESEARCH_TOWER));
+
+ pos.x = ox+sx*0.9f;
+ pos.y = oy+sy*0.1f;
+ pw->CreateButton(pos, ddim, 128+39, EVENT_OBJECT_BENERGY);
+ DeadInterface(pw, EVENT_OBJECT_BENERGY, g_build&BUILD_ENERGY);
+
+ pos.x = ox+sx*1.8f;
+ pos.y = oy+sy*0.1f;
+ pw->CreateButton(pos, ddim, 128+33, EVENT_OBJECT_BDERRICK);
+ DeadInterface(pw, EVENT_OBJECT_BDERRICK, g_build&BUILD_DERRICK);
+
+ pos.x = ox+sx*2.7f;
+ pos.y = oy+sy*0.1f;
+ pw->CreateButton(pos, ddim, 128+42, EVENT_OBJECT_BNUCLEAR);
+ DeadInterface(pw, EVENT_OBJECT_BNUCLEAR,
+ (g_build&BUILD_NUCLEAR) &&
+ (g_researchDone & RESEARCH_ATOMIC));
+
+ pos.x = ox+sx*3.6f;
+ pos.y = oy+sy*0.1f;
+ pw->CreateButton(pos, ddim, 128+38, EVENT_OBJECT_BLABO);
+ DeadInterface(pw, EVENT_OBJECT_BLABO, g_build&BUILD_LABO);
+
+ pos.x = ox+sx*4.5f;
+ pos.y = oy+sy*0.1f;
+ pw->CreateButton(pos, ddim, 128+46, EVENT_OBJECT_BPARA);
+ DeadInterface(pw, EVENT_OBJECT_BPARA, g_build&BUILD_PARA);
+
+ pos.x = ox+sx*5.4f;
+ pos.y = oy+sy*0.1f;
+ pw->CreateButton(pos, ddim, 128+56, EVENT_OBJECT_BXXXX);
+ DeadInterface(pw, EVENT_OBJECT_BXXXX, false);
+
+ if ( g_build&BUILD_GFLAT )
+ {
+ pos.x = ox+sx*9.0f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 64+47, EVENT_OBJECT_GFLAT);
+ }
+
+ if ( g_build&BUILD_FLAG )
+ {
+ pos.x = ox+sx*10.1f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 64+54, EVENT_OBJECT_FCREATE);
+
+ pos.x = ox+sx*11.1f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 64+55, EVENT_OBJECT_FDELETE);
+
+ ddim.x = dim.x*0.4f;
+ ddim.y = dim.y*0.4f;
+ pos.x = ox+sx*10.1f;
+ pos.y = oy+sy*2.0f-ddim.y;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORb);
+ pc->SetColor(RetColor((D3DCOLOR)0x004890ff));
+ pos.x += ddim.x;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORr);
+ pc->SetColor(RetColor((D3DCOLOR)0x00ff0000));
+ pos.x += ddim.x;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORg);
+ pc->SetColor(RetColor((D3DCOLOR)0x0000ce00));
+ pos.x += ddim.x;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORy);
+ pc->SetColor(RetColor((D3DCOLOR)0x00ffec00));
+ pos.x += ddim.x;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORv);
+ pc->SetColor(RetColor((D3DCOLOR)0x00d101fe));
+ }
+ }
+
+ if ( (type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ) && // Investigator?
+ !m_object->RetTrainer() )
+ {
+ pos.x = ox+sx*7.7f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 40, EVENT_OBJECT_SEARCH);
+ DefaultEnter(pw, EVENT_OBJECT_SEARCH);
+ }
+
+ if ( type == OBJECT_MOBILErt && // Terraformer?
+ !m_object->RetTrainer() )
+ {
+ pos.x = ox+sx*7.7f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 128+18, EVENT_OBJECT_TERRAFORM);
+ DefaultEnter(pw, EVENT_OBJECT_TERRAFORM);
+
+ pos.x = ox+sx*10.2f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT);
+ }
+
+ if ( type == OBJECT_MOBILErr && // recoverer?
+ !m_object->RetTrainer() )
+ {
+ pos.x = ox+sx*7.7f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 128+20, EVENT_OBJECT_RECOVER);
+ DefaultEnter(pw, EVENT_OBJECT_RECOVER);
+ }
+
+ if ( type == OBJECT_MOBILErs && // shield?
+ !m_object->RetTrainer() )
+ {
+ pos.x = ox+sx*7.7f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 39, EVENT_OBJECT_BEGSHIELD);
+ DefaultEnter(pw, EVENT_OBJECT_BEGSHIELD);
+
+ pos.x = ox+sx*9.0f;
+ pos.y = oy+sy*0.5f;
+ pw->CreateButton(pos, dim, 47, EVENT_OBJECT_ENDSHIELD);
+
+//? pos.x = ox+sx*10.2f;
+//? pos.y = oy+sy*0.5f;
+//? pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT);
+
+ pos.x = ox+sx*10.5f;
+ pos.y = oy+sy*0.0f;
+ ddim.x = dim.x*0.5f;
+ ddim.y = dim.y*2.0f;
+ ps = pw->CreateSlider(pos, ddim, 0, EVENT_OBJECT_DIMSHIELD);
+ ps->SetState(STATE_VALUE);
+ ps->SetLimit((RADIUS_SHIELD_MIN/g_unit), (RADIUS_SHIELD_MAX/g_unit));
+ ps->SetArrowStep(1.0f);
+ }
+
+ if ( (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_MOBILErc ) && // cannon?
+ !m_object->RetTrainer() )
+ {
+ pos.x = ox+sx*7.7f;
+ pos.y = oy+sy*0.5f;
+ pb = pw->CreateButton(pos, dim, 42, EVENT_OBJECT_FIRE);
+ pb->SetImmediat(true);
+ DefaultEnter(pw, EVENT_OBJECT_FIRE);
+
+//? pos.x = ox+sx*10.2f;
+//? pos.y = oy+sy*0.5f;
+//? pw->CreateButton(pos, dim, 41, EVENT_OBJECT_LIMIT);
+ }
+
+ if ( type == OBJECT_MOBILEdr &&
+ m_object->RetManual() ) // scribbler in manual mode?
+ {
+ pos.x = ox+sx*6.9f;
+ pos.y = oy+sy*0.0f;
+ ddim.x = dim.x*2.2f;
+ ddim.y = dim.y*2.0f;
+ pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
+
+ pos.x = ox+sx*9.3f;
+ pos.y = oy+sy*0.0f;
+ ddim.x = dim.x*2.2f;
+ ddim.y = dim.y*2.0f;
+ pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
+
+ pos.x = ox+sx*9.90f;
+ pos.y = oy+sy*0.50f;
+ pw->CreateButton(pos, dim, 43, EVENT_OBJECT_PEN0);
+
+ ddim.x = dim.x*0.5f;
+ ddim.y = dim.y*0.5f;
+ pos.x = ox+sx*10.15f;
+ pos.y = oy+sy*1.50f;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN1); // black
+ pc->SetColor(RetColor((D3DCOLOR)0x00000000));
+ pos.x = ox+sx*10.65f;
+ pos.y = oy+sy*1.25f;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN2); // yellow
+ pc->SetColor(RetColor((D3DCOLOR)0x00ffff00));
+ pos.x = ox+sx*10.90f;
+ pos.y = oy+sy*0.75f;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN3); // orange
+ pc->SetColor(RetColor((D3DCOLOR)0x00ff8800));
+ pos.x = ox+sx*10.65f;
+ pos.y = oy+sy*0.25f;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN4); // red
+ pc->SetColor(RetColor((D3DCOLOR)0x00ff0000));
+ pos.x = ox+sx*10.15f;
+ pos.y = oy+sy*0.00f;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN5); // violet
+ pc->SetColor(RetColor((D3DCOLOR)0x00ff00ff));
+ pos.x = ox+sx*9.65f;
+ pos.y = oy+sy*0.25f;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN6); // blue
+ pc->SetColor(RetColor((D3DCOLOR)0x000066ff));
+ pos.x = ox+sx*9.40f;
+ pos.y = oy+sy*0.75f;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN7); // green
+ pc->SetColor(RetColor((D3DCOLOR)0x0000cc00));
+ pos.x = ox+sx*9.65f;
+ pos.y = oy+sy*1.25f;
+ pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_PEN8); // brown
+ pc->SetColor(RetColor((D3DCOLOR)0x00884400));
+
+ pos.x = ox+sx*6.9f;
+ pos.y = oy+sy*1.2f;
+ ddim.x = dim.x*2.2f;
+ ddim.y = dim.y*0.4f;
+ GetResource(RES_TEXT, RT_INTERFACE_REC, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, name);
+ pl->SetFontSize(9.0f);
+
+ pos.x = ox+sx*7.0f;
+ pos.y = oy+sy*0.3f;
+ pw->CreateButton(pos, dim, 44, EVENT_OBJECT_REC);
+ pos.x = ox+sx*8.0f;
+ pos.y = oy+sy*0.3f;
+ pw->CreateButton(pos, dim, 45, EVENT_OBJECT_STOP);
+ }
+
+ if ( m_object->RetToy() )
+ {
+ pos.x = ox+sx*12.1f;
+ pos.y = oy+sy*-0.1f;
+ ddim.x = dim.x*1.2f;
+ ddim.y = dim.y*2.1f;
+ pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
+
+ pos.x = ox+sx*12.2f;
+ pos.y = oy+sy*1;
+ pw->CreateGroup(pos, dim, 19, EVENT_NULL); // sign SatCom
+
+ pos.x = ox+sx*12.2f;
+ pos.y = oy+sy*0.0f;
+ pw->CreateButton(pos, dim, 128+57, EVENT_OBJECT_BHELP);
+ }
+ else
+ {
+ pos.x = ox+sx*12.3f;
+ pos.y = oy+sy*-0.1f;
+ ddim.x = dim.x*1.0f;
+ ddim.y = dim.y*2.1f;
+ pw->CreateGroup(pos, ddim, 20, EVENT_NULL); // solid blue bottom
+
+ pos.x = ox+sx*12.3f;
+ pos.y = oy+sy*1;
+ pw->CreateGroup(pos, dim, 19, EVENT_NULL); // sign SatCom
+
+ pos.x = ox+sx*12.4f;
+ pos.y = oy+sy*0.5f;
+ ddim.x = dim.x*0.8f;
+ ddim.y = dim.y*0.5f;
+ pw->CreateButton(pos, ddim, 18, EVENT_OBJECT_BHELP);
+ pos.y = oy+sy*0.0f;
+ pw->CreateButton(pos, ddim, 19, EVENT_OBJECT_HELP);
+ }
+
+ if ( type != OBJECT_HUMAN &&
+ type != OBJECT_TECH &&
+ !m_object->RetCameraLock() )
+ {
+//? if ( m_main->RetShowMap() )
+ if ( true )
+ {
+ pos.x = ox+sx*13.4f;
+ pos.y = oy+sy*1;
+ pw->CreateButton(pos, dim, 13, EVENT_OBJECT_CAMERA);
+ }
+ else
+ {
+ ddim.x = dim.x*0.66f;
+ ddim.y = dim.y*0.66f;
+ pos.x = ox+sx*(17.0f+0.66f);
+ pos.y = oy+sy*0.66f;
+ pw->CreateButton(pos, ddim, 13, EVENT_OBJECT_CAMERA);
+ }
+ }
+
+ if ( m_object->RetToy() && !m_object->RetManual() )
+ {
+#if 0
+ ddim.x = dim.x*0.66f;
+ ddim.y = dim.y*0.66f;
+ pos.x = ox+sx*10.0f;
+ pos.y = oy+sy*0.66f;
+ pb = pw->CreateButton(pos, ddim, 55, EVENT_OBJECT_CAMERAleft);
+ pb->SetImmediat(true);
+ pos.x = ox+sx*(10.0f+0.66f*2.0f);
+ pos.y = oy+sy*0.66f;
+ pb = pw->CreateButton(pos, ddim, 48, EVENT_OBJECT_CAMERAright);
+ pb->SetImmediat(true);
+ pos.x = ox+sx*(10.0f+0.66f);
+ pos.y = oy+sy*(0.66f*2.0f);
+ pb = pw->CreateButton(pos, ddim, 49, EVENT_OBJECT_CAMERAnear);
+ pb->SetImmediat(true);
+ pos.x = ox+sx*(10.0f+0.66f);
+ pos.y = oy+sy*0.0f;
+ pb = pw->CreateButton(pos, ddim, 50, EVENT_OBJECT_CAMERAaway);
+ pb->SetImmediat(true);
+#else
+ pos.x = ox+sx*9.0f;
+ pos.y = oy+sy*0;
+ pb = pw->CreateButton(pos, dim, 55, EVENT_OBJECT_CAMERAleft);
+ pb->SetImmediat(true);
+ pos.x = ox+sx*11.0f;
+ pos.y = oy+sy*0;
+ pb = pw->CreateButton(pos, dim, 48, EVENT_OBJECT_CAMERAright);
+ pb->SetImmediat(true);
+ pos.x = ox+sx*10.0f;
+ pos.y = oy+sy*1;
+ pb = pw->CreateButton(pos, dim, 49, EVENT_OBJECT_CAMERAnear);
+ pb->SetImmediat(true);
+ pos.x = ox+sx*10.0f;
+ pos.y = oy+sy*0;
+ pb = pw->CreateButton(pos, dim, 50, EVENT_OBJECT_CAMERAaway);
+ pb->SetImmediat(true);
+#endif
+ }
+
+ pos.x = ox+sx*13.4f;
+ pos.y = oy+sy*0;
+#if _TEEN
+ pw->CreateButton(pos, dim, 9, EVENT_OBJECT_RESET);
+#else
+ if ( m_object->RetTrainer() ) // Training?
+ {
+ pw->CreateButton(pos, dim, 9, EVENT_OBJECT_RESET);
+ }
+ else
+ {
+ pw->CreateButton(pos, dim, 10, EVENT_OBJECT_DESELECT);
+ }
+#endif
+
+ 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 ) // vehicle?
+ {
+ pos.x = ox+sx*14.5f;
+ pos.y = oy+sy*0;
+ ddim.x = 14.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 0, EVENT_OBJECT_GENERGY);
+ }
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH ||
+ type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ) // vehicle?
+ {
+ pos.x = ox+sx*14.9f;
+ pos.y = oy+sy*0;
+ ddim.x = 14.0f/640.0f;
+ ddim.y = 66.0f/480.0f;
+ pw->CreateGauge(pos, ddim, 3, EVENT_OBJECT_GSHIELD);
+ }
+
+#if 0
+ if ( false )
+ {
+ pos.x = 505.0f/640.0f;
+ pos.y = 3.0f/480.0f;
+ ddim.x = 33.0f/640.0f;
+ ddim.y = 33.0f/480.0f;
+ pw->CreateCompass(pos, ddim, 0, EVENT_OBJECT_COMPASS);
+
+ pc = (CCompass*)pw->SearchControl(EVENT_OBJECT_COMPASS);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_VISIBLE, m_main->RetShowMap());
+ }
+ }
+#endif
+
+ if ( 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_MOBILErc ) // cannon?
+ {
+ ddim.x = 64.0f/640.0f;
+ ddim.y = 64.0f/480.0f;
+ pos.x = 0.5f-ddim.x/2.0f;
+ pos.y = 0.5f-ddim.y/2.0f;
+ pw->CreateGroup(pos, ddim, 12, EVENT_OBJECT_CROSSHAIR);
+
+ pos.x = 20.0f/640.0f;
+ pos.y = 100.0f/480.0f;
+ ddim.x = 600.0f/640.0f;
+ ddim.y = 340.0f/480.0f;
+ pt = pw->CreateTarget(pos, ddim, 0, EVENT_OBJECT_TARGET);
+ pt->ClearState(STATE_GLINT);
+ }
+
+ ddim.x = 64.0f/640.0f;
+ ddim.y = 64.0f/480.0f;
+ pos.x = 30.0f/640.0f;
+ pos.y = 430.0f/480.0f-ddim.y;
+ pw->CreateGroup(pos, ddim, 13, EVENT_OBJECT_CORNERul);
+
+ ddim.x = 64.0f/640.0f;
+ ddim.y = 64.0f/480.0f;
+ pos.x = 610.0f/640.0f-ddim.x;
+ pos.y = 430.0f/480.0f-ddim.y;
+ pw->CreateGroup(pos, ddim, 14, EVENT_OBJECT_CORNERur);
+
+ ddim.x = 64.0f/640.0f;
+ ddim.y = 64.0f/480.0f;
+ pos.x = 30.0f/640.0f;
+ pos.y = 110.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 15, EVENT_OBJECT_CORNERdl);
+
+ ddim.x = 64.0f/640.0f;
+ ddim.y = 64.0f/480.0f;
+ pos.x = 610.0f/640.0f-ddim.x;
+ pos.y = 110.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 16, EVENT_OBJECT_CORNERdr);
+
+ UpdateInterface();
+ m_lastUpdateTime = 0.0f;
+ UpdateInterface(0.0f);
+
+ return true;
+}
+
+// Updates the state of all buttons on the interface,
+// following the time that elapses ...
+
+void CBrain::UpdateInterface(float rTime)
+{
+ CWindow* pw;
+#if _TEEN
+ CButton* pb;
+#endif
+ CGauge* pg;
+ CCompass* pc;
+ CGroup* pgr;
+ CTarget* ptg;
+ CObject* power;
+ Math::Vector pos, hPos;
+ Math::Point ppos;
+ float energy, limit, angle, range;
+ int icon;
+ bool bOnBoard;
+
+ m_lastAlarmTime += rTime;
+ if ( m_time < m_lastUpdateTime+0.1f ) return;
+ m_lastUpdateTime = m_time;
+
+ if ( !m_object->RetSelect() )
+ {
+ if ( m_soundChannelAlarm != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannelAlarm);
+ m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 1.0f, 0.1f, SOPER_STOP);
+ m_soundChannelAlarm = -1;
+ }
+ return;
+ }
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GENERGY);
+ if ( pg != 0 )
+ {
+ power = m_object->RetPower();
+ if ( power == 0 )
+ {
+ energy = 0.0f;
+ }
+ else
+ {
+ energy = power->RetEnergy();
+ limit = energy*power->RetCapacity();
+ }
+ icon = 0; // red/green
+
+ if ( limit < 0.2f && energy != 0.0f ) // low but not zero?
+ {
+ if ( m_lastAlarmTime >= 0.8f ) // blinks?
+ {
+ energy = 1.0f;
+ icon = 1; // brun
+ }
+ if ( m_lastAlarmTime >= 1.0f )
+ {
+ m_sound->Play(SOUND_ALARM, 0.5f); // bip-bip-bip
+ m_lastAlarmTime = 0.0f;
+ }
+ }
+ pg->SetLevel(energy);
+ pg->SetIcon(icon);
+ }
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GSHIELD);
+ if ( pg != 0 )
+ {
+ pg->SetLevel(m_object->RetShield());
+ }
+
+ pg = (CGauge*)pw->SearchControl(EVENT_OBJECT_GRANGE);
+ if ( pg != 0 )
+ {
+ icon = 2; // blue/red
+ range = m_physics->RetReactorRange();
+
+ if ( range < 0.2f && range != 0.0f && !m_physics->RetLand() )
+ {
+ if ( Math::Mod(m_time, 0.5f) >= 0.2f ) // blinks?
+ {
+ range = 1.0f;
+ icon = 1; // yellow
+ }
+ if ( m_soundChannelAlarm == -1 )
+ {
+ m_soundChannelAlarm = m_sound->Play(SOUND_ALARMt, m_object->RetPosition(0), 0.0f, 0.1f, true);
+ m_sound->AddEnvelope(m_soundChannelAlarm, 1.0f, 1.0f, 1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannelAlarm, 1.0f, 1.0f, 1.0f, SOPER_LOOP);
+ }
+ }
+ else
+ {
+ if ( m_soundChannelAlarm != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannelAlarm);
+ m_sound->AddEnvelope(m_soundChannelAlarm, 0.0f, 0.1f, 1.0f, SOPER_STOP);
+ m_soundChannelAlarm = -1;
+ }
+ }
+
+ pg->SetLevel(1.0f-range);
+ pg->SetIcon(icon);
+ }
+
+ pc = (CCompass*)pw->SearchControl(EVENT_OBJECT_COMPASS);
+ if ( pc != 0 )
+ {
+ angle = -(m_object->RetAngleY(0)+Math::PI/2.0f);
+ pc->SetDirection(angle);
+
+ pc->SetState(STATE_VISIBLE, m_main->RetShowMap());
+ }
+
+#if _TEEN
+ pb = (CButton*)pw->SearchControl(EVENT_OBJECT_REC);
+ if ( pb != 0 )
+ {
+ if ( m_bTraceRecord && Math::Mod(m_time, 0.4f) >= 0.2f )
+ {
+ pb->SetState(STATE_CHECK);
+ }
+ else
+ {
+ pb->ClearState(STATE_CHECK);
+ }
+ }
+#endif
+
+ bOnBoard = m_camera->RetType() == CAMERA_ONBOARD;
+
+ pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CROSSHAIR);
+ if ( pgr != 0 )
+ {
+ if ( bOnBoard )
+ {
+#if 0
+ angle = m_object->RetGunGoalV();
+ if ( m_object->RetType() != OBJECT_MOBILErc )
+ {
+ angle += 10.0f*Math::PI/360.0f;
+ }
+ ppos.x = 0.5f-(64.0f/640.0f)/2.0f;
+ ppos.y = 0.5f-(64.0f/480.0f)/2.0f;
+ ppos.y += sinf(angle)*0.6f;
+ pgr->SetPos(ppos);
+#else
+ ppos.x = 0.50f-(64.0f/640.0f)/2.0f;
+ ppos.y = 0.50f-(64.0f/480.0f)/2.0f;
+ ppos.x += m_object->RetGunGoalH()/2.0f;
+ ppos.y += m_object->RetGunGoalV()/1.3f;
+ pgr->SetPos(ppos);
+#endif
+ pgr->SetState(STATE_VISIBLE, !m_main->RetFriendAim());
+ }
+ else
+ {
+ pgr->ClearState(STATE_VISIBLE);
+ }
+ }
+
+ ptg = (CTarget*)pw->SearchControl(EVENT_OBJECT_TARGET);
+ if ( ptg != 0 )
+ {
+ if ( bOnBoard )
+ {
+ ptg->SetState(STATE_VISIBLE);
+ }
+ else
+ {
+ ptg->ClearState(STATE_VISIBLE);
+ }
+ }
+
+ pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERul);
+ if ( pgr != 0 )
+ {
+ pgr->SetState(STATE_VISIBLE, bOnBoard);
+ }
+
+ pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERur);
+ if ( pgr != 0 )
+ {
+ pgr->SetState(STATE_VISIBLE, bOnBoard);
+ }
+
+ pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERdl);
+ if ( pgr != 0 )
+ {
+ pgr->SetState(STATE_VISIBLE, bOnBoard);
+ }
+
+ pgr = (CGroup*)pw->SearchControl(EVENT_OBJECT_CORNERdr);
+ if ( pgr != 0 )
+ {
+ pgr->SetState(STATE_VISIBLE, bOnBoard);
+ }
+}
+
+// Updates the status of all interface buttons.
+
+void CBrain::UpdateInterface()
+{
+ ObjectType type;
+ CWindow* pw;
+ CButton* pb;
+ CSlider* ps;
+#if _TEEN
+ CColor* pc;
+ int color;
+#endif
+ bool bEnable, bFly, bRun;
+ char title[100];
+
+ if ( !m_object->RetSelect() ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ type = m_object->RetType();
+
+ bEnable = ( m_secondaryTask == 0 && m_program == -1 );
+
+ bEnable = ( m_primaryTask == 0 && m_program == -1 );
+
+ EnableInterface(pw, EVENT_OBJECT_PROGEDIT, (m_primaryTask == 0 && !m_bTraceRecord));
+ EnableInterface(pw, EVENT_OBJECT_PROGLIST, bEnable && !m_bTraceRecord);
+ EnableInterface(pw, EVENT_OBJECT_LEFT, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_RIGHT, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_UP, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_DOWN, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_HTAKE, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_MTAKE, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_MBACK, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_MPOWER, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_MFRONT, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_GFLAT, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_FCREATE, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_FDELETE, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_SEARCH, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_TERRAFORM, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_RECOVER, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_FIRE, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_RESET, bEnable);
+#if _TEEN
+ EnableInterface(pw, EVENT_OBJECT_PEN0, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_PEN1, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_PEN2, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_PEN3, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_PEN4, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_PEN5, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_PEN6, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_PEN7, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_PEN8, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_REC, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_STOP, bEnable);
+#endif
+
+ if ( type == OBJECT_HUMAN ) // builder?
+ {
+ EnableInterface(pw, EVENT_OBJECT_BFACTORY, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BDERRICK, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BCONVERT, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BSTATION, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BREPAIR, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BTOWER, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BRESEARCH, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BRADAR, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BENERGY, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BLABO, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BNUCLEAR, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BPARA, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BINFO, bEnable);
+ EnableInterface(pw, EVENT_OBJECT_BXXXX, bEnable);
+ }
+
+ pb = (CButton*)pw->SearchControl(EVENT_OBJECT_GFLAT);
+ if ( pb != 0 )
+ {
+ pb->SetState(STATE_VISIBLE, m_engine->RetGroundSpot());
+ }
+
+ if ( type == OBJECT_HUMAN || // builder?
+ type == OBJECT_TECH )
+ {
+ CheckInterface(pw, EVENT_OBJECT_FCOLORb, m_flagColor==0);
+ CheckInterface(pw, EVENT_OBJECT_FCOLORr, m_flagColor==1);
+ CheckInterface(pw, EVENT_OBJECT_FCOLORg, m_flagColor==2);
+ CheckInterface(pw, EVENT_OBJECT_FCOLORy, m_flagColor==3);
+ CheckInterface(pw, EVENT_OBJECT_FCOLORv, m_flagColor==4);
+ }
+
+ if ( type == OBJECT_MOBILErs ) // shield?
+ {
+ if ( (m_secondaryTask == 0 || !m_secondaryTask->IsBusy()) && m_program == -1 )
+ {
+ EnableInterface(pw, EVENT_OBJECT_BEGSHIELD, (m_secondaryTask == 0));
+ EnableInterface(pw, EVENT_OBJECT_ENDSHIELD, (m_secondaryTask != 0));
+ DefaultEnter (pw, EVENT_OBJECT_BEGSHIELD, (m_secondaryTask == 0));
+ DefaultEnter (pw, EVENT_OBJECT_ENDSHIELD, (m_secondaryTask != 0));
+ }
+ else
+ {
+ EnableInterface(pw, EVENT_OBJECT_BEGSHIELD, false);
+ EnableInterface(pw, EVENT_OBJECT_ENDSHIELD, false);
+ DefaultEnter (pw, EVENT_OBJECT_BEGSHIELD, false);
+ DefaultEnter (pw, EVENT_OBJECT_ENDSHIELD, false);
+ }
+
+ ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_DIMSHIELD);
+ if ( ps != 0 )
+ {
+ ps->SetVisibleValue((RADIUS_SHIELD_MIN/g_unit)+m_object->RetParam()*((RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)/g_unit));
+ }
+ }
+
+ bFly = bEnable;
+ if ( bFly && (type == OBJECT_HUMAN || type == OBJECT_TECH) )
+ {
+ if ( m_object->RetFret() != 0 ) bFly = false; // if holder -> not fly
+ }
+ EnableInterface(pw, EVENT_OBJECT_GASUP, bFly);
+ EnableInterface(pw, EVENT_OBJECT_GASDOWN, bFly);
+ if ( m_object->RetTrainer() ) // Training?
+ {
+ DeadInterface(pw, EVENT_OBJECT_GASUP, false);
+ DeadInterface(pw, EVENT_OBJECT_GASDOWN, false);
+ }
+ else
+ {
+ DeadInterface(pw, EVENT_OBJECT_GASUP, g_researchDone&RESEARCH_FLY);
+ DeadInterface(pw, EVENT_OBJECT_GASDOWN, g_researchDone&RESEARCH_FLY);
+ }
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH ||
+ type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr ||
+ type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ) // vehicle?
+ {
+ bRun = false;
+ if ( m_script[m_selScript] != 0 )
+ {
+ m_script[m_selScript]->GetTitle(title);
+ if ( title[0] != 0 )
+ {
+ bRun = true;
+ }
+ }
+ if ( !bEnable && m_program == -1 ) bRun = false;
+ if ( m_bTraceRecord ) bRun = false;
+ EnableInterface(pw, EVENT_OBJECT_PROGRUN, bRun);
+
+ pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PROGRUN);
+ if ( pb != 0 )
+ {
+ pb->SetIcon(m_program==-1?21:8); // run/stop
+ }
+
+//? pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PROGEDIT);
+//? if ( pb != 0 )
+//? {
+//? pb->SetIcon(m_program==-1?22:40); // edit/debug
+//? }
+
+ BlinkScript(m_program != -1); // blinks if script execution
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ) // arm?
+ {
+ CheckInterface(pw, EVENT_OBJECT_MPOWER, m_manipStyle==EVENT_OBJECT_MPOWER);
+ CheckInterface(pw, EVENT_OBJECT_MBACK, m_manipStyle==EVENT_OBJECT_MBACK);
+ CheckInterface(pw, EVENT_OBJECT_MFRONT, m_manipStyle==EVENT_OBJECT_MFRONT);
+ }
+
+#if _TEEN
+ if ( m_object->RetTraceDown() )
+ {
+ pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PEN0);
+ if ( pb != 0 )
+ {
+ pb->ClearState(STATE_CHECK);
+ }
+
+ color = m_object->RetTraceColor();
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN1);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, color==1);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN2);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, color==8);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN3);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, color==7);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN4);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, color==4);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN5);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, color==6);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN6);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, color==14);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN7);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, color==12);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN8);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, color==10);
+ }
+ }
+ else
+ {
+ pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PEN0);
+ if ( pb != 0 )
+ {
+ pb->SetState(STATE_CHECK);
+ }
+
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN1);
+ if ( pc != 0 )
+ {
+ pc->ClearState(STATE_CHECK);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN2);
+ if ( pc != 0 )
+ {
+ pc->ClearState(STATE_CHECK);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN3);
+ if ( pc != 0 )
+ {
+ pc->ClearState(STATE_CHECK);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN4);
+ if ( pc != 0 )
+ {
+ pc->ClearState(STATE_CHECK);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN5);
+ if ( pc != 0 )
+ {
+ pc->ClearState(STATE_CHECK);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN6);
+ if ( pc != 0 )
+ {
+ pc->ClearState(STATE_CHECK);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN7);
+ if ( pc != 0 )
+ {
+ pc->ClearState(STATE_CHECK);
+ }
+ pc = (CColor*)pw->SearchControl(EVENT_OBJECT_PEN8);
+ if ( pc != 0 )
+ {
+ pc->ClearState(STATE_CHECK);
+ }
+ }
+#endif
+}
+
+// Updates the list of programs.
+
+void CBrain::UpdateScript(CWindow *pw)
+{
+ CList* pl;
+ char name[100];
+ char title[100];
+ int i;
+ bool bSoluce;
+
+ pl = (CList*)pw->SearchControl(EVENT_OBJECT_PROGLIST);
+ if ( pl == 0 ) return;
+
+#if _SCHOOL
+ bSoluce = m_main->RetSoluce4();
+#else
+ bSoluce = true;
+#endif
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ sprintf(name, "%d", i+1);
+
+ if ( m_script[i] != 0 )
+ {
+ m_script[i]->GetTitle(title);
+ if ( !bSoluce && i == 3 )
+ {
+ title[0] = 0;
+ }
+ if ( title[0] != 0 )
+ {
+ sprintf(name, "%d: %s", i+1, title);
+ }
+ }
+
+ pl->SetName(i, name);
+ }
+
+ if ( !bSoluce )
+ {
+ pl->SetEnable(3, false);
+ }
+
+ pl->SetSelect(m_selScript);
+ pl->ShowSelect(true);
+}
+
+// Returns the rank of selected script.
+
+int CBrain::RetSelScript()
+{
+ CWindow* pw;
+ CList* pl;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return -1;
+
+ pl = (CList*)pw->SearchControl(EVENT_OBJECT_PROGLIST);
+ if ( pl == 0 ) return -1;
+
+ return pl->RetSelect();
+}
+
+// Blinks the running program.
+
+void CBrain::BlinkScript(bool bEnable)
+{
+ CWindow* pw;
+ CList* pl;
+
+ if ( !m_object->RetSelect() ) return; // robot not selected?
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw == 0 ) return;
+
+ pl = (CList*)pw->SearchControl(EVENT_OBJECT_PROGLIST);
+ if ( pl == 0 ) return;
+
+ pl->SetBlink(bEnable);
+}
+
+// Check the status of a button interface.
+
+void CBrain::CheckInterface(CWindow *pw, EventMsg event, bool bState)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_CHECK, bState);
+}
+
+// Changes the state of a button interface.
+
+void CBrain::EnableInterface(CWindow *pw, EventMsg event, bool bState)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_ENABLE, bState);
+}
+
+// Changes the state of a button on the interface.
+
+void CBrain::DeadInterface(CWindow *pw, EventMsg event, bool bState)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ control->SetState(STATE_DEAD, !bState);
+}
+
+// Change the default input state of a button interface.
+
+void CBrain::DefaultEnter(CWindow *pw, EventMsg event, bool bState)
+{
+ CControl* control;
+
+ control = pw->SearchControl(event);
+ if ( control == 0 ) return;
+
+ if ( bState )
+ {
+ control->SetState(STATE_DEFAULT);
+ m_defaultEnter = event;
+ }
+ else
+ {
+ control->ClearState(STATE_DEFAULT);
+ }
+}
+
+
+// Indicates whether the object is busy with a task.
+
+bool CBrain::IsBusy()
+{
+ return (m_primaryTask != 0);
+}
+
+// Management of the activity of an object.
+
+void CBrain::SetActivity(bool bMode)
+{
+ m_bActivity = bMode;
+}
+
+bool CBrain::RetActivity()
+{
+ return m_bActivity;
+}
+
+// Indicates whether a program is running.
+
+bool CBrain::IsProgram()
+{
+ return ( m_program != -1 );
+}
+
+// Indicates whether a program exists.
+
+bool CBrain::ProgramExist(int rank)
+{
+ return ( m_script[rank] != 0 );
+}
+
+// Starts a program.
+
+void CBrain::RunProgram(int rank)
+{
+ if ( rank < 0 ) return;
+
+ if ( m_script[rank] != 0 &&
+ m_script[rank]->Run() )
+ {
+ m_program = rank; // start new program
+ BlinkScript(true); // blink
+ m_object->CreateSelectParticule();
+ m_main->UpdateShortcuts();
+ }
+}
+
+// Returns the first free program.
+
+int CBrain::FreeProgram()
+{
+ int i;
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ if ( m_script[i] == 0 ) return i;
+ }
+ return -1;
+}
+
+
+// Returns the current program.
+
+int CBrain::RetProgram()
+{
+ return m_program;
+}
+
+
+// Name management scripts to load.
+
+void CBrain::SetScriptRun(int rank)
+{
+ m_scriptRun = rank;
+}
+
+int CBrain::RetScriptRun()
+{
+ return m_scriptRun;
+}
+
+void CBrain::SetScriptName(int rank, char *name)
+{
+ strcpy(m_scriptName[rank], name);
+}
+
+char* CBrain::RetScriptName(int rank)
+{
+ return m_scriptName[rank];
+}
+
+void CBrain::SetSoluceName(char *name)
+{
+ strcpy(m_soluceName, name);
+}
+
+char* CBrain::RetSoluceName()
+{
+ return m_soluceName;
+}
+
+
+// Load a script solution, in the first free script.
+// If there is already an identical script, nothing is loaded.
+
+bool CBrain::ReadSoluce(char* filename)
+{
+ int rank, i;
+
+ rank = FreeProgram();
+ if ( rank == -1 ) return false;
+
+ if ( !ReadProgram(rank, filename) ) return false; // load solution
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ if ( i == rank || m_script[i] == 0 ) continue;
+
+ if ( m_script[i]->Compare(m_script[rank]) ) // the same already?
+ {
+ delete m_script[rank];
+ m_script[rank] = 0;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Load a script with a text file.
+
+bool CBrain::ReadProgram(int rank, char* filename)
+{
+ if ( m_script[rank] == 0 )
+ {
+ m_script[rank] = new CScript(m_iMan, m_object, &m_secondaryTask);
+ }
+
+ if ( m_script[rank]->ReadScript(filename) ) return true;
+
+ delete m_script[rank];
+ m_script[rank] = 0;
+
+ return false;
+}
+
+// Indicates whether a program is compiled correctly.
+
+bool CBrain::RetCompile(int rank)
+{
+ if ( m_script[rank] == 0 ) return false;
+ return m_script[rank]->RetCompile();
+}
+
+// Saves a script in a text file.
+
+bool CBrain::WriteProgram(int rank, char* filename)
+{
+ if ( m_script[rank] == 0 )
+ {
+ m_script[rank] = new CScript(m_iMan, m_object, &m_secondaryTask);
+ }
+
+ if ( m_script[rank]->WriteScript(filename) ) return true;
+
+ delete m_script[rank];
+ m_script[rank] = 0;
+
+ return false;
+}
+
+
+// Load a stack of script implementation from a file.
+
+bool CBrain::ReadStack(FILE *file)
+{
+ short op;
+
+ fRead(&op, sizeof(short), 1, file);
+ if ( op == 1 ) // run ?
+ {
+ fRead(&op, sizeof(short), 1, file); // program rank
+ if ( op >= 0 && op < BRAINMAXSCRIPT )
+ {
+ m_program = op; // program restarts
+ m_selScript = op;
+ BlinkScript(true); // blink
+
+ if ( m_script[op] == 0 )
+ {
+ m_script[op] = new CScript(m_iMan, m_object, &m_secondaryTask);
+ }
+ if ( !m_script[op]->ReadStack(file) ) return false;
+ }
+ }
+
+ return true;
+}
+
+// ave the script implementation stack of a file.
+
+bool CBrain::WriteStack(FILE *file)
+{
+ short op;
+
+ if ( m_program != -1 && // current program?
+ m_script[m_program]->IsRunning() )
+ {
+ op = 1; // run
+ fWrite(&op, sizeof(short), 1, file);
+
+ op = m_program;
+ fWrite(&op, sizeof(short), 1, file);
+
+ return m_script[m_program]->WriteStack(file);
+ }
+
+ op = 0; // stop
+ fWrite(&op, sizeof(short), 1, file);
+ return true;
+}
+
+
+
+// Start of registration of the design.
+
+void CBrain::TraceRecordStart()
+{
+ m_traceOper = TO_STOP;
+
+ m_tracePos = m_object->RetPosition(0);
+ m_traceAngle = m_object->RetAngleY(0);
+
+ if ( m_object->RetTraceDown() ) // pencil down?
+ {
+ m_traceColor = m_object->RetTraceColor();
+ }
+ else // pen up?
+ {
+ m_traceColor = -1;
+ }
+
+ delete m_traceRecordBuffer;
+ m_traceRecordBuffer = (TraceRecord*)malloc(sizeof(TraceRecord)*MAXTRACERECORD);
+ m_traceRecordIndex = 0;
+}
+
+// Saving the current drawing.
+
+void CBrain::TraceRecordFrame()
+{
+ TraceOper oper = TO_STOP;
+ Math::Vector pos;
+ float angle, len, speed;
+ int color;
+
+ speed = m_physics->RetLinMotionX(MO_REASPEED);
+ if ( speed > 0.0f ) oper = TO_ADVANCE;
+ if ( speed < 0.0f ) oper = TO_RECEDE;
+
+ speed = m_physics->RetCirMotionY(MO_REASPEED);
+ if ( speed != 0.0f ) oper = TO_TURN;
+
+ if ( m_object->RetTraceDown() ) // pencil down?
+ {
+ color = m_object->RetTraceColor();
+ }
+ else // pen up?
+ {
+ color = -1;
+ }
+
+ if ( oper != m_traceOper ||
+ color != m_traceColor )
+ {
+ if ( m_traceOper == TO_ADVANCE ||
+ m_traceOper == TO_RECEDE )
+ {
+ pos = m_object->RetPosition(0);
+ len = Math::DistanceProjected(pos, m_tracePos);
+ TraceRecordOper(m_traceOper, len);
+ }
+ if ( m_traceOper == TO_TURN )
+ {
+ angle = m_object->RetAngleY(0)-m_traceAngle;
+ TraceRecordOper(m_traceOper, angle);
+ }
+
+ if ( color != m_traceColor )
+ {
+ TraceRecordOper(TO_PEN, (float)color);
+ }
+
+ m_traceOper = oper;
+ m_tracePos = m_object->RetPosition(0);
+ m_traceAngle = m_object->RetAngleY(0);
+ m_traceColor = color;
+ }
+}
+
+// End of the registration of the design. Program generates the CBOT.
+
+void CBrain::TraceRecordStop()
+{
+ TraceOper lastOper, curOper;
+ float lastParam, curParam;
+ int max, i;
+ char* buffer;
+
+ if ( m_traceRecordBuffer == 0 ) return;
+
+ max = 10000;
+ buffer = (char*)malloc(max);
+ *buffer = 0;
+ strncat(buffer, "extern void object::AutoDraw()\n{\n", max-1);
+
+ lastOper = TO_STOP;
+ lastParam = 0.0f;
+ for ( i=0 ; i<m_traceRecordIndex ; i++ )
+ {
+ curOper = m_traceRecordBuffer[i].oper;
+ curParam = m_traceRecordBuffer[i].param;
+
+ if ( curOper == lastOper )
+ {
+ if ( curOper == TO_PEN )
+ {
+ lastParam = curParam;
+ }
+ else
+ {
+ lastParam += curParam;
+ }
+ }
+ else
+ {
+ TraceRecordPut(buffer, max, lastOper, lastParam);
+ lastOper = curOper;
+ lastParam = curParam;
+ }
+ }
+ TraceRecordPut(buffer, max, lastOper, lastParam);
+
+ delete m_traceRecordBuffer;
+ m_traceRecordBuffer = 0;
+
+ strncat(buffer, "}\n", max-1);
+ buffer[max-1] = 0;
+
+ i = m_selScript;
+ if ( m_script[i] == 0 )
+ {
+ m_script[i] = new CScript(m_iMan, m_object, &m_secondaryTask);
+ }
+ m_script[i]->SendScript(buffer);
+ delete buffer;
+}
+
+// Saves an instruction CBOT.
+
+bool CBrain::TraceRecordOper(TraceOper oper, float param)
+{
+ int i;
+
+ i = m_traceRecordIndex;
+ if ( i >= MAXTRACERECORD ) return false;
+
+ m_traceRecordBuffer[i].oper = oper;
+ m_traceRecordBuffer[i].param = param;
+
+ m_traceRecordIndex = i+1;
+ return true;
+}
+
+// Generates an instruction CBOT.
+
+bool CBrain::TraceRecordPut(char *buffer, int max, TraceOper oper, float param)
+{
+ char line[100];
+ int color;
+
+ if ( oper == TO_ADVANCE )
+ {
+ param /= g_unit;
+ sprintf(line, "\tmove(%.1f);\n", param);
+ strncat(buffer, line, max-1);
+ }
+
+ if ( oper == TO_RECEDE )
+ {
+ param /= g_unit;
+ sprintf(line, "\tmove(-%.1f);\n", param);
+ strncat(buffer, line, max-1);
+ }
+
+ if ( oper == TO_TURN )
+ {
+ param = -param*180.0f/Math::PI;
+ sprintf(line, "\tturn(%d);\n", (int)param);
+//? sprintf(line, "\tturn(%.1f);\n", param);
+ strncat(buffer, line, max-1);
+ }
+
+ if ( oper == TO_PEN )
+ {
+ color = (int)param;
+ if ( color == -1 ) strncat(buffer, "\tpenup();\n", max-1);
+ if ( color == 1 ) strncat(buffer, "\tpendown(Black);\n", max-1);
+ if ( color == 8 ) strncat(buffer, "\tpendown(Yellow);\n", max-1);
+ if ( color == 7 ) strncat(buffer, "\tpendown(Orange);\n", max-1);
+ if ( color == 4 ) strncat(buffer, "\tpendown(Red);\n", max-1);
+ if ( color == 6 ) strncat(buffer, "\tpendown(Purple);\n", max-1);
+ if ( color == 14 ) strncat(buffer, "\tpendown(Blue);\n", max-1);
+ if ( color == 12 ) strncat(buffer, "\tpendown(Green);\n", max-1);
+ if ( color == 10 ) strncat(buffer, "\tpendown(Brown);\n", max-1);
+ }
+
+ return true;
+}
+
diff --git a/src/object/brain.h b/src/object/brain.h
index 7c258ae..0220ffc 100644
--- a/src/object/brain.h
+++ b/src/object/brain.h
@@ -1,218 +1,218 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// brain.h
-
-#pragma once
-
-
-#include <stdio.h>
-
-#include "common/misc.h"
-#include "common/event.h"
-#include "object/object.h"
-#include "object/task/taskmanip.h"
-#include "object/task/taskflag.h"
-#include "object/task/taskshield.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CTerrain;
-class CWater;
-class CCamera;
-class CObject;
-class CPhysics;
-class CMotion;
-class CTaskManager;
-class CInterface;
-class CWindow;
-class CDisplayText;
-class CScript;
-class CRobotMain;
-class CStudio;
-class CSound;
-class CParticule;
-
-
-const int BRAINMAXSCRIPT = 10;
-
-
-
-enum TraceOper
-{
- TO_STOP = 0, // stop
- TO_ADVANCE = 1, // advance
- TO_RECEDE = 2, // back
- TO_TURN = 3, // rotate
- TO_PEN = 4, // color change
-};
-
-struct TraceRecord
-{
- TraceOper oper;
- float param;
-};
-
-
-
-class CBrain
-{
-public:
- CBrain(CInstanceManager* iMan, CObject* object);
- ~CBrain();
-
- void DeleteObject(bool bAll=false);
-
- void SetPhysics(CPhysics* physics);
- void SetMotion(CMotion* motion);
-
- bool EventProcess(const Event &event);
- bool CreateInterface(bool bSelect);
-
- bool Write(char *line);
- bool Read(char *line);
-
- bool IsBusy();
- void SetActivity(bool bMode);
- bool RetActivity();
- bool IsProgram();
- bool ProgramExist(int rank);
- void RunProgram(int rank);
- int FreeProgram();
- int RetProgram();
- void StopProgram();
- void StopTask();
-
- bool IntroduceVirus();
- void SetActiveVirus(bool bActive);
- bool RetActiveVirus();
-
- void SetScriptRun(int rank);
- int RetScriptRun();
- void SetScriptName(int rank, char *name);
- char* RetScriptName(int rank);
- void SetSoluceName(char *name);
- char* RetSoluceName();
-
- bool ReadSoluce(char* filename);
- bool ReadProgram(int rank, char* filename);
- bool RetCompile(int rank);
- bool WriteProgram(int rank, char* filename);
- bool ReadStack(FILE *file);
- bool WriteStack(FILE *file);
-
- Error StartTaskTake();
- Error StartTaskManip(TaskManipOrder order, TaskManipArm arm);
- Error StartTaskFlag(TaskFlagOrder order, int rank);
- Error StartTaskBuild(ObjectType type);
- Error StartTaskSearch();
- Error StartTaskTerraform();
- Error StartTaskPen(bool bDown, int color);
- Error StartTaskRecover();
- Error StartTaskShield(TaskShieldMode mode);
- Error StartTaskFire(float delay);
- Error StartTaskFireAnt(Math::Vector impact);
- Error StartTaskGunGoal(float dirV, float dirH);
- Error StartTaskReset(Math::Vector goal, Math::Vector angle);
-
- void UpdateInterface(float rTime);
- void UpdateInterface();
-
-protected:
- bool EventFrame(const Event &event);
-
- void StartEditScript(int rank, char* name);
- void StopEditScript(bool bCancel);
-
- Error EndedTask();
-
- void GroundFlat();
- void ColorFlag(int color);
-
- void UpdateScript(CWindow *pw);
- int RetSelScript();
- void BlinkScript(bool bEnable);
-
- void CheckInterface(CWindow *pw, EventMsg event, bool bState);
- void EnableInterface(CWindow *pw, EventMsg event, bool bState);
- void DeadInterface(CWindow *pw, EventMsg event, bool bState);
- void DefaultEnter(CWindow *pw, EventMsg event, bool bState=true);
-
- void TraceRecordStart();
- void TraceRecordFrame();
- void TraceRecordStop();
- bool TraceRecordOper(TraceOper oper, float param);
- bool TraceRecordPut(char *buffer, int max, TraceOper oper, float param);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CTerrain* m_terrain;
- CWater* m_water;
- CCamera* m_camera;
- CObject* m_object;
- CPhysics* m_physics;
- CMotion* m_motion;
- CInterface* m_interface;
- CDisplayText* m_displayText;
- CRobotMain* m_main;
- CStudio* m_studio;
- CSound* m_sound;
- CParticule* m_particule;
- CTaskManager* m_primaryTask;
- CTaskManager* m_secondaryTask;
-
- CScript* m_script[BRAINMAXSCRIPT];
- int m_selScript; // rank of the selected script
- int m_program; // rank of the executed program / ​​-1
- bool m_bActivity;
- bool m_bBurn;
- bool m_bActiveVirus;
-
- int m_scriptRun;
- char m_scriptName[BRAINMAXSCRIPT][50];
- char m_soluceName[50];
-
- EventMsg m_buttonAxe;
- EventMsg m_manipStyle;
- EventMsg m_defaultEnter;
- EventMsg m_interfaceEvent[100];
-
- CObject* m_antTarget;
- CObject* m_beeBullet;
- float m_beeBulletSpeed;
- Math::Vector m_startPos;
- float m_time;
- float m_burnTime;
- float m_lastUpdateTime;
- float m_lastHumanTime;
- float m_lastSpiderTime;
- float m_lastWormTime;
- float m_lastBulletTime;
- float m_lastAlarmTime;
- int m_soundChannelAlarm;
- int m_flagColor;
-
- bool m_bTraceRecord;
- TraceOper m_traceOper;
- Math::Vector m_tracePos;
- float m_traceAngle;
- int m_traceColor;
- int m_traceRecordIndex;
- TraceRecord* m_traceRecordBuffer;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// brain.h
+
+#pragma once
+
+
+#include <stdio.h>
+
+#include "common/misc.h"
+#include "common/event.h"
+#include "object/object.h"
+#include "object/task/taskmanip.h"
+#include "object/task/taskflag.h"
+#include "object/task/taskshield.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CTerrain;
+class CWater;
+class CCamera;
+class CObject;
+class CPhysics;
+class CMotion;
+class CTaskManager;
+class CInterface;
+class CWindow;
+class CDisplayText;
+class CScript;
+class CRobotMain;
+class CStudio;
+class CSound;
+class CParticule;
+
+
+const int BRAINMAXSCRIPT = 10;
+
+
+
+enum TraceOper
+{
+ TO_STOP = 0, // stop
+ TO_ADVANCE = 1, // advance
+ TO_RECEDE = 2, // back
+ TO_TURN = 3, // rotate
+ TO_PEN = 4, // color change
+};
+
+struct TraceRecord
+{
+ TraceOper oper;
+ float param;
+};
+
+
+
+class CBrain
+{
+public:
+ CBrain(CInstanceManager* iMan, CObject* object);
+ ~CBrain();
+
+ void DeleteObject(bool bAll=false);
+
+ void SetPhysics(CPhysics* physics);
+ void SetMotion(CMotion* motion);
+
+ bool EventProcess(const Event &event);
+ bool CreateInterface(bool bSelect);
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+ bool IsBusy();
+ void SetActivity(bool bMode);
+ bool RetActivity();
+ bool IsProgram();
+ bool ProgramExist(int rank);
+ void RunProgram(int rank);
+ int FreeProgram();
+ int RetProgram();
+ void StopProgram();
+ void StopTask();
+
+ bool IntroduceVirus();
+ void SetActiveVirus(bool bActive);
+ bool RetActiveVirus();
+
+ void SetScriptRun(int rank);
+ int RetScriptRun();
+ void SetScriptName(int rank, char *name);
+ char* RetScriptName(int rank);
+ void SetSoluceName(char *name);
+ char* RetSoluceName();
+
+ bool ReadSoluce(char* filename);
+ bool ReadProgram(int rank, char* filename);
+ bool RetCompile(int rank);
+ bool WriteProgram(int rank, char* filename);
+ bool ReadStack(FILE *file);
+ bool WriteStack(FILE *file);
+
+ Error StartTaskTake();
+ Error StartTaskManip(TaskManipOrder order, TaskManipArm arm);
+ Error StartTaskFlag(TaskFlagOrder order, int rank);
+ Error StartTaskBuild(ObjectType type);
+ Error StartTaskSearch();
+ Error StartTaskTerraform();
+ Error StartTaskPen(bool bDown, int color);
+ Error StartTaskRecover();
+ Error StartTaskShield(TaskShieldMode mode);
+ Error StartTaskFire(float delay);
+ Error StartTaskFireAnt(Math::Vector impact);
+ Error StartTaskGunGoal(float dirV, float dirH);
+ Error StartTaskReset(Math::Vector goal, Math::Vector angle);
+
+ void UpdateInterface(float rTime);
+ void UpdateInterface();
+
+protected:
+ bool EventFrame(const Event &event);
+
+ void StartEditScript(int rank, char* name);
+ void StopEditScript(bool bCancel);
+
+ Error EndedTask();
+
+ void GroundFlat();
+ void ColorFlag(int color);
+
+ void UpdateScript(CWindow *pw);
+ int RetSelScript();
+ void BlinkScript(bool bEnable);
+
+ void CheckInterface(CWindow *pw, EventMsg event, bool bState);
+ void EnableInterface(CWindow *pw, EventMsg event, bool bState);
+ void DeadInterface(CWindow *pw, EventMsg event, bool bState);
+ void DefaultEnter(CWindow *pw, EventMsg event, bool bState=true);
+
+ void TraceRecordStart();
+ void TraceRecordFrame();
+ void TraceRecordStop();
+ bool TraceRecordOper(TraceOper oper, float param);
+ bool TraceRecordPut(char *buffer, int max, TraceOper oper, float param);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CCamera* m_camera;
+ CObject* m_object;
+ CPhysics* m_physics;
+ CMotion* m_motion;
+ CInterface* m_interface;
+ CDisplayText* m_displayText;
+ CRobotMain* m_main;
+ CStudio* m_studio;
+ CSound* m_sound;
+ CParticule* m_particule;
+ CTaskManager* m_primaryTask;
+ CTaskManager* m_secondaryTask;
+
+ CScript* m_script[BRAINMAXSCRIPT];
+ int m_selScript; // rank of the selected script
+ int m_program; // rank of the executed program / ​​-1
+ bool m_bActivity;
+ bool m_bBurn;
+ bool m_bActiveVirus;
+
+ int m_scriptRun;
+ char m_scriptName[BRAINMAXSCRIPT][50];
+ char m_soluceName[50];
+
+ EventMsg m_buttonAxe;
+ EventMsg m_manipStyle;
+ EventMsg m_defaultEnter;
+ EventMsg m_interfaceEvent[100];
+
+ CObject* m_antTarget;
+ CObject* m_beeBullet;
+ float m_beeBulletSpeed;
+ Math::Vector m_startPos;
+ float m_time;
+ float m_burnTime;
+ float m_lastUpdateTime;
+ float m_lastHumanTime;
+ float m_lastSpiderTime;
+ float m_lastWormTime;
+ float m_lastBulletTime;
+ float m_lastAlarmTime;
+ int m_soundChannelAlarm;
+ int m_flagColor;
+
+ bool m_bTraceRecord;
+ TraceOper m_traceOper;
+ Math::Vector m_tracePos;
+ float m_traceAngle;
+ int m_traceColor;
+ int m_traceRecordIndex;
+ TraceRecord* m_traceRecordBuffer;
+};
+
diff --git a/src/object/mainmovie.cpp b/src/object/mainmovie.cpp
index 082027d..7049842 100644
--- a/src/object/mainmovie.cpp
+++ b/src/object/mainmovie.cpp
@@ -1,238 +1,238 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// mainmovie.cpp
-
-
-#include <stdio.h>
-
-
-#include "object/mainmovie.h"
-
-#include "math/geometry.h"
-#include "common/iman.h"
-#include "object/motion/motionhuman.h"
-#include "object/robotmain.h"
-
-
-
-
-// Constructor of the application card.
-
-CMainMovie::CMainMovie(CInstanceManager* iMan)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_SHORT, this);
-
- m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
- m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
-
- Flush();
-}
-
-// Destructor of the application card.
-
-CMainMovie::~CMainMovie()
-{
-}
-
-
-// Stops the current movie.
-
-void CMainMovie::Flush()
-{
- m_type = MM_NONE;
-}
-
-
-// Start of a film.
-
-bool CMainMovie::Start(MainMovieType type, float time)
-{
- Math::Matrix* mat;
- Math::Vector pos;
- CObject* pObj;
- CMotion* motion;
-
- m_type = type;
- m_speed = 1.0f/time;
- m_progress = 0.0f;
-
- if ( m_type == MM_SATCOMopen )
- {
- pObj = m_main->SearchHuman();
- if ( pObj == 0 )
- {
- m_type = MM_NONE; // it's over!
- return true;
- }
-
- motion = pObj->RetMotion();
- if ( motion != 0 )
- {
- motion->SetAction(MHS_SATCOM, 0.5f); // reads the SatCom
- }
-
- m_camera->RetCamera(m_initialEye, m_initialLookat);
- m_camera->SetType(CAMERA_SCRIPT);
- m_camera->SetSmooth(CS_HARD);
- m_camera->SetScriptEye(m_initialEye);
- m_camera->SetScriptLookat(m_initialLookat);
- m_camera->FixCamera();
-
- mat = pObj->RetWorldMatrix(0);
- m_finalLookat[0] = Math::Transform(*mat, Math::Vector( 1.6f, 1.0f, 1.2f));
- m_finalEye[0] = Math::Transform(*mat, Math::Vector(-1.5f, 5.0f, 3.0f));
- m_finalLookat[1] = Math::Transform(*mat, Math::Vector( 1.6f, 1.0f, 1.2f));
- m_finalEye[1] = Math::Transform(*mat, Math::Vector( 0.8f, 3.0f, 0.8f));
- }
-
- if ( m_type == MM_SATCOMclose )
- {
- pObj = m_main->SearchHuman();
- if ( pObj != 0 )
- {
- motion = pObj->RetMotion();
- if ( motion != 0 )
- {
- motion->SetAction(-1); // finishes reading SatCom
- }
- }
-
- m_camera->SetType(CAMERA_BACK);
- m_type = MM_NONE; // it's already over!
- }
-
- return true;
-}
-
-// Stop a current movie.
-
-bool CMainMovie::Stop()
-{
- CObject* pObj;
- CMotion* motion;
-
- if ( m_type == MM_SATCOMopen )
- {
- pObj = m_main->SearchHuman();
- if ( pObj != 0 )
- {
- motion = pObj->RetMotion();
- if ( motion != 0 )
- {
- motion->SetAction(-1); // finishes reading SatCom
- }
- }
- }
-
- m_type = MM_NONE;
- return true;
-}
-
-// Indicates whether a film is in progress.
-
-bool CMainMovie::IsExist()
-{
- return (m_type != MM_NONE);
-}
-
-
-// Processing an event.
-
-bool CMainMovie::EventProcess(const Event &event)
-{
- Math::Vector initialEye, initialLookat, finalEye, finalLookat, eye, lookat;
- float progress;
-
- if ( m_type == MM_NONE ) return true;
-
- m_progress += event.rTime*m_speed;
-
- if ( m_type == MM_SATCOMopen )
- {
- if ( m_progress < 1.0f )
- {
- progress = 1.0f-powf(1.0f-m_progress, 3.0f);
-
- if ( progress < 0.6f )
- {
- progress = progress/0.6f;
- initialEye = m_initialEye;
- initialLookat = m_initialLookat;
- finalEye = m_finalEye[0];
- finalLookat = m_finalLookat[0];
- }
- else
- {
- progress = (progress-0.6f)/0.3f;
- initialEye = m_finalEye[0];
- initialLookat = m_finalLookat[0];
- finalEye = m_finalEye[1];
- finalLookat = m_finalLookat[1];
- }
- if ( progress > 1.0f ) progress = 1.0f;
-
- eye = (finalEye-initialEye)*progress+initialEye;
- lookat = (finalLookat-initialLookat)*progress+initialLookat;
- m_camera->SetScriptEye(eye);
- m_camera->SetScriptLookat(lookat);
-// m_camera->FixCamera();
- }
- else
- {
- m_stopType = m_type;
- Flush();
- return false;
- }
- }
-
- if ( m_type == MM_SATCOMclose )
- {
- if ( m_progress < 1.0f )
- {
- }
- else
- {
- m_stopType = m_type;
- Flush();
- return false;
- }
- }
-
- return true;
-}
-
-
-// Returns the type of the current movie.
-
-MainMovieType CMainMovie::RetType()
-{
- return m_type;
-}
-
-// Returns the type of movie stop.
-
-MainMovieType CMainMovie::RetStopType()
-{
- return m_stopType;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// mainmovie.cpp
+
+
+#include <stdio.h>
+
+
+#include "object/mainmovie.h"
+
+#include "math/geometry.h"
+#include "common/iman.h"
+#include "object/motion/motionhuman.h"
+#include "object/robotmain.h"
+
+
+
+
+// Constructor of the application card.
+
+CMainMovie::CMainMovie(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_SHORT, this);
+
+ m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+ m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+
+ Flush();
+}
+
+// Destructor of the application card.
+
+CMainMovie::~CMainMovie()
+{
+}
+
+
+// Stops the current movie.
+
+void CMainMovie::Flush()
+{
+ m_type = MM_NONE;
+}
+
+
+// Start of a film.
+
+bool CMainMovie::Start(MainMovieType type, float time)
+{
+ Math::Matrix* mat;
+ Math::Vector pos;
+ CObject* pObj;
+ CMotion* motion;
+
+ m_type = type;
+ m_speed = 1.0f/time;
+ m_progress = 0.0f;
+
+ if ( m_type == MM_SATCOMopen )
+ {
+ pObj = m_main->SearchHuman();
+ if ( pObj == 0 )
+ {
+ m_type = MM_NONE; // it's over!
+ return true;
+ }
+
+ motion = pObj->RetMotion();
+ if ( motion != 0 )
+ {
+ motion->SetAction(MHS_SATCOM, 0.5f); // reads the SatCom
+ }
+
+ m_camera->RetCamera(m_initialEye, m_initialLookat);
+ m_camera->SetType(CAMERA_SCRIPT);
+ m_camera->SetSmooth(CS_HARD);
+ m_camera->SetScriptEye(m_initialEye);
+ m_camera->SetScriptLookat(m_initialLookat);
+ m_camera->FixCamera();
+
+ mat = pObj->RetWorldMatrix(0);
+ m_finalLookat[0] = Math::Transform(*mat, Math::Vector( 1.6f, 1.0f, 1.2f));
+ m_finalEye[0] = Math::Transform(*mat, Math::Vector(-1.5f, 5.0f, 3.0f));
+ m_finalLookat[1] = Math::Transform(*mat, Math::Vector( 1.6f, 1.0f, 1.2f));
+ m_finalEye[1] = Math::Transform(*mat, Math::Vector( 0.8f, 3.0f, 0.8f));
+ }
+
+ if ( m_type == MM_SATCOMclose )
+ {
+ pObj = m_main->SearchHuman();
+ if ( pObj != 0 )
+ {
+ motion = pObj->RetMotion();
+ if ( motion != 0 )
+ {
+ motion->SetAction(-1); // finishes reading SatCom
+ }
+ }
+
+ m_camera->SetType(CAMERA_BACK);
+ m_type = MM_NONE; // it's already over!
+ }
+
+ return true;
+}
+
+// Stop a current movie.
+
+bool CMainMovie::Stop()
+{
+ CObject* pObj;
+ CMotion* motion;
+
+ if ( m_type == MM_SATCOMopen )
+ {
+ pObj = m_main->SearchHuman();
+ if ( pObj != 0 )
+ {
+ motion = pObj->RetMotion();
+ if ( motion != 0 )
+ {
+ motion->SetAction(-1); // finishes reading SatCom
+ }
+ }
+ }
+
+ m_type = MM_NONE;
+ return true;
+}
+
+// Indicates whether a film is in progress.
+
+bool CMainMovie::IsExist()
+{
+ return (m_type != MM_NONE);
+}
+
+
+// Processing an event.
+
+bool CMainMovie::EventProcess(const Event &event)
+{
+ Math::Vector initialEye, initialLookat, finalEye, finalLookat, eye, lookat;
+ float progress;
+
+ if ( m_type == MM_NONE ) return true;
+
+ m_progress += event.rTime*m_speed;
+
+ if ( m_type == MM_SATCOMopen )
+ {
+ if ( m_progress < 1.0f )
+ {
+ progress = 1.0f-powf(1.0f-m_progress, 3.0f);
+
+ if ( progress < 0.6f )
+ {
+ progress = progress/0.6f;
+ initialEye = m_initialEye;
+ initialLookat = m_initialLookat;
+ finalEye = m_finalEye[0];
+ finalLookat = m_finalLookat[0];
+ }
+ else
+ {
+ progress = (progress-0.6f)/0.3f;
+ initialEye = m_finalEye[0];
+ initialLookat = m_finalLookat[0];
+ finalEye = m_finalEye[1];
+ finalLookat = m_finalLookat[1];
+ }
+ if ( progress > 1.0f ) progress = 1.0f;
+
+ eye = (finalEye-initialEye)*progress+initialEye;
+ lookat = (finalLookat-initialLookat)*progress+initialLookat;
+ m_camera->SetScriptEye(eye);
+ m_camera->SetScriptLookat(lookat);
+// m_camera->FixCamera();
+ }
+ else
+ {
+ m_stopType = m_type;
+ Flush();
+ return false;
+ }
+ }
+
+ if ( m_type == MM_SATCOMclose )
+ {
+ if ( m_progress < 1.0f )
+ {
+ }
+ else
+ {
+ m_stopType = m_type;
+ Flush();
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+// Returns the type of the current movie.
+
+MainMovieType CMainMovie::RetType()
+{
+ return m_type;
+}
+
+// Returns the type of movie stop.
+
+MainMovieType CMainMovie::RetStopType()
+{
+ return m_stopType;
+}
+
+
diff --git a/src/object/mainmovie.h b/src/object/mainmovie.h
index 3d4f375..23721fb 100644
--- a/src/object/mainmovie.h
+++ b/src/object/mainmovie.h
@@ -1,80 +1,80 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// mainmovie.h
-
-#pragma once
-
-
-#include "common/event.h"
-#include "math/vector.h"
-
-
-class CInstanceManager;
-class CEvent;
-class CD3DEngine;
-class CInterface;
-class CRobotMain;
-class CCamera;
-class CSound;
-
-
-
-
-enum MainMovieType
-{
- MM_NONE,
- MM_SATCOMopen,
- MM_SATCOMclose,
-};
-
-
-
-class CMainMovie
-{
-public:
- CMainMovie(CInstanceManager* iMan);
- ~CMainMovie();
-
- void Flush();
- bool Start(MainMovieType type, float time);
- bool Stop();
- bool IsExist();
- bool EventProcess(const Event &event);
- MainMovieType RetType();
- MainMovieType RetStopType();
-
-protected:
-
-protected:
- CInstanceManager* m_iMan;
- CEvent* m_event;
- CD3DEngine* m_engine;
- CInterface* m_interface;
- CRobotMain* m_main;
- CCamera* m_camera;
- CSound* m_sound;
-
- MainMovieType m_type;
- MainMovieType m_stopType;
- float m_speed;
- float m_progress;
- Math::Vector m_initialEye;
- Math::Vector m_initialLookat;
- Math::Vector m_finalEye[2];
- Math::Vector m_finalLookat[2];
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// mainmovie.h
+
+#pragma once
+
+
+#include "common/event.h"
+#include "math/vector.h"
+
+
+class CInstanceManager;
+class CEvent;
+class CD3DEngine;
+class CInterface;
+class CRobotMain;
+class CCamera;
+class CSound;
+
+
+
+
+enum MainMovieType
+{
+ MM_NONE,
+ MM_SATCOMopen,
+ MM_SATCOMclose,
+};
+
+
+
+class CMainMovie
+{
+public:
+ CMainMovie(CInstanceManager* iMan);
+ ~CMainMovie();
+
+ void Flush();
+ bool Start(MainMovieType type, float time);
+ bool Stop();
+ bool IsExist();
+ bool EventProcess(const Event &event);
+ MainMovieType RetType();
+ MainMovieType RetStopType();
+
+protected:
+
+protected:
+ CInstanceManager* m_iMan;
+ CEvent* m_event;
+ CD3DEngine* m_engine;
+ CInterface* m_interface;
+ CRobotMain* m_main;
+ CCamera* m_camera;
+ CSound* m_sound;
+
+ MainMovieType m_type;
+ MainMovieType m_stopType;
+ float m_speed;
+ float m_progress;
+ Math::Vector m_initialEye;
+ Math::Vector m_initialLookat;
+ Math::Vector m_finalEye[2];
+ Math::Vector m_finalLookat[2];
+};
+
diff --git a/src/object/motion/motion.cpp b/src/object/motion/motion.cpp
index 3231f7a..5ffa63c 100644
--- a/src/object/motion/motion.cpp
+++ b/src/object/motion/motion.cpp
@@ -1,239 +1,239 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motion.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motion.h"
-
-#include "common/iman.h"
-#include "script/cmdtoken.h"
-
-
-
-
-// Object's constructor.
-
-CMotion::CMotion(CInstanceManager* iMan, CObject* object)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_MOTION, this, 100);
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
-
- m_object = object;
- m_physics = 0;
- m_brain = 0;
-
- m_actionType = -1;
- m_actionTime = 0.0f;
- m_progress = 0.0f;
-
- m_linVibration = Math::Vector(0.0f, 0.0f, 0.0f);
- m_cirVibration = Math::Vector(0.0f, 0.0f, 0.0f);
- m_inclinaison = Math::Vector(0.0f, 0.0f, 0.0f);
-}
-
-// Object's destructor.
-
-CMotion::~CMotion()
-{
- m_iMan->DeleteInstance(CLASS_MOTION, this);
-}
-
-// Deletes the object.
-
-void CMotion::DeleteObject(bool bAll)
-{
-}
-
-
-void CMotion::SetPhysics(CPhysics* physics)
-{
- m_physics = physics;
-}
-
-void CMotion::SetBrain(CBrain* brain)
-{
- m_brain = brain;
-}
-
-
-// Creates.
-
-bool CMotion::Create(Math::Vector pos, float angle, ObjectType type, float power)
-{
- return true;
-}
-
-// Management of an event.
-
-bool CMotion::EventProcess(const Event &event)
-{
- Math::Vector pos, dir;
- float time;
-
- if ( m_object->RetType() != OBJECT_TOTO &&
- m_engine->RetPause() ) return true;
-
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_actionTime;
- if ( m_progress > 1.0f ) m_progress = 1.0f; // (*)
-
- pos = m_object->RetPosition(0);
- if ( pos.y < m_water->RetLevel(m_object) ) // underwater?
- {
- time = event.rTime*3.0f; // everything is slower
- }
- else
- {
- time = event.rTime*10.0f;
- }
-
- dir = m_object->RetLinVibration();
- dir.x = Math::Smooth(dir.x, m_linVibration.x, time);
- dir.y = Math::Smooth(dir.y, m_linVibration.y, time);
- dir.z = Math::Smooth(dir.z, m_linVibration.z, time);
- m_object->SetLinVibration(dir);
-
- dir = m_object->RetCirVibration();
- dir.x = Math::Smooth(dir.x, m_cirVibration.x, time);
- dir.y = Math::Smooth(dir.y, m_cirVibration.y, time);
- dir.z = Math::Smooth(dir.z, m_cirVibration.z, time);
- m_object->SetCirVibration(dir);
-
- dir = m_object->RetInclinaison();
- dir.x = Math::Smooth(dir.x, m_inclinaison.x, time);
- dir.y = Math::Smooth(dir.y, m_inclinaison.y, time);
- dir.z = Math::Smooth(dir.z, m_inclinaison.z, time);
- m_object->SetInclinaison(dir);
-
- return true;
-}
-
-// (*) Avoids the bug of ants returned by the thumper and
-// whose abdomen grown to infinity!
-
-
-// Start an action.
-
-Error CMotion::SetAction(int action, float time)
-{
- m_actionType = action;
- m_actionTime = 1.0f/time;
- m_progress = 0.0f;
- return ERR_OK;
-}
-
-// Returns the current action.
-
-int CMotion::RetAction()
-{
- return m_actionType;
-}
-
-
-// Specifies a special parameter.
-
-bool CMotion::SetParam(int rank, float value)
-{
- return false;
-}
-
-float CMotion::RetParam(int rank)
-{
- return 0.0f;
-}
-
-
-// Saves all parameters of the object.
-
-bool CMotion::Write(char *line)
-{
- char name[100];
-
- if ( m_actionType == -1 ) return false;
-
- sprintf(name, " mType=%d", m_actionType);
- strcat(line, name);
-
- sprintf(name, " mTime=%.2f", m_actionTime);
- strcat(line, name);
-
- sprintf(name, " mProgress=%.2f", m_progress);
- strcat(line, name);
-
- return false;
-}
-
-// Restores all parameters of the object.
-
-bool CMotion::Read(char *line)
-{
- m_actionType = OpInt(line, "mType", -1);
- m_actionTime = OpFloat(line, "mTime", 0.0f);
- m_progress = OpFloat(line, "mProgress", 0.0f);
-
- return false;
-}
-
-
-// Gives the linear vibration.
-
-void CMotion::SetLinVibration(Math::Vector dir)
-{
- m_linVibration = dir;
-}
-
-Math::Vector CMotion::RetLinVibration()
-{
- return m_linVibration;
-}
-
-// Gives the circular vibration.
-
-void CMotion::SetCirVibration(Math::Vector dir)
-{
- m_cirVibration = dir;
-}
-
-Math::Vector CMotion::RetCirVibration()
-{
- return m_cirVibration;
-}
-
-// Gives the tilt.
-
-void CMotion::SetInclinaison(Math::Vector dir)
-{
- m_inclinaison = dir;
-}
-
-Math::Vector CMotion::RetInclinaison()
-{
- return m_inclinaison;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motion.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motion.h"
+
+#include "common/iman.h"
+#include "script/cmdtoken.h"
+
+
+
+
+// Object's constructor.
+
+CMotion::CMotion(CInstanceManager* iMan, CObject* object)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_MOTION, this, 100);
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+
+ m_object = object;
+ m_physics = 0;
+ m_brain = 0;
+
+ m_actionType = -1;
+ m_actionTime = 0.0f;
+ m_progress = 0.0f;
+
+ m_linVibration = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_cirVibration = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_inclinaison = Math::Vector(0.0f, 0.0f, 0.0f);
+}
+
+// Object's destructor.
+
+CMotion::~CMotion()
+{
+ m_iMan->DeleteInstance(CLASS_MOTION, this);
+}
+
+// Deletes the object.
+
+void CMotion::DeleteObject(bool bAll)
+{
+}
+
+
+void CMotion::SetPhysics(CPhysics* physics)
+{
+ m_physics = physics;
+}
+
+void CMotion::SetBrain(CBrain* brain)
+{
+ m_brain = brain;
+}
+
+
+// Creates.
+
+bool CMotion::Create(Math::Vector pos, float angle, ObjectType type, float power)
+{
+ return true;
+}
+
+// Management of an event.
+
+bool CMotion::EventProcess(const Event &event)
+{
+ Math::Vector pos, dir;
+ float time;
+
+ if ( m_object->RetType() != OBJECT_TOTO &&
+ m_engine->RetPause() ) return true;
+
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_actionTime;
+ if ( m_progress > 1.0f ) m_progress = 1.0f; // (*)
+
+ pos = m_object->RetPosition(0);
+ if ( pos.y < m_water->RetLevel(m_object) ) // underwater?
+ {
+ time = event.rTime*3.0f; // everything is slower
+ }
+ else
+ {
+ time = event.rTime*10.0f;
+ }
+
+ dir = m_object->RetLinVibration();
+ dir.x = Math::Smooth(dir.x, m_linVibration.x, time);
+ dir.y = Math::Smooth(dir.y, m_linVibration.y, time);
+ dir.z = Math::Smooth(dir.z, m_linVibration.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir = m_object->RetCirVibration();
+ dir.x = Math::Smooth(dir.x, m_cirVibration.x, time);
+ dir.y = Math::Smooth(dir.y, m_cirVibration.y, time);
+ dir.z = Math::Smooth(dir.z, m_cirVibration.z, time);
+ m_object->SetCirVibration(dir);
+
+ dir = m_object->RetInclinaison();
+ dir.x = Math::Smooth(dir.x, m_inclinaison.x, time);
+ dir.y = Math::Smooth(dir.y, m_inclinaison.y, time);
+ dir.z = Math::Smooth(dir.z, m_inclinaison.z, time);
+ m_object->SetInclinaison(dir);
+
+ return true;
+}
+
+// (*) Avoids the bug of ants returned by the thumper and
+// whose abdomen grown to infinity!
+
+
+// Start an action.
+
+Error CMotion::SetAction(int action, float time)
+{
+ m_actionType = action;
+ m_actionTime = 1.0f/time;
+ m_progress = 0.0f;
+ return ERR_OK;
+}
+
+// Returns the current action.
+
+int CMotion::RetAction()
+{
+ return m_actionType;
+}
+
+
+// Specifies a special parameter.
+
+bool CMotion::SetParam(int rank, float value)
+{
+ return false;
+}
+
+float CMotion::RetParam(int rank)
+{
+ return 0.0f;
+}
+
+
+// Saves all parameters of the object.
+
+bool CMotion::Write(char *line)
+{
+ char name[100];
+
+ if ( m_actionType == -1 ) return false;
+
+ sprintf(name, " mType=%d", m_actionType);
+ strcat(line, name);
+
+ sprintf(name, " mTime=%.2f", m_actionTime);
+ strcat(line, name);
+
+ sprintf(name, " mProgress=%.2f", m_progress);
+ strcat(line, name);
+
+ return false;
+}
+
+// Restores all parameters of the object.
+
+bool CMotion::Read(char *line)
+{
+ m_actionType = OpInt(line, "mType", -1);
+ m_actionTime = OpFloat(line, "mTime", 0.0f);
+ m_progress = OpFloat(line, "mProgress", 0.0f);
+
+ return false;
+}
+
+
+// Gives the linear vibration.
+
+void CMotion::SetLinVibration(Math::Vector dir)
+{
+ m_linVibration = dir;
+}
+
+Math::Vector CMotion::RetLinVibration()
+{
+ return m_linVibration;
+}
+
+// Gives the circular vibration.
+
+void CMotion::SetCirVibration(Math::Vector dir)
+{
+ m_cirVibration = dir;
+}
+
+Math::Vector CMotion::RetCirVibration()
+{
+ return m_cirVibration;
+}
+
+// Gives the tilt.
+
+void CMotion::SetInclinaison(Math::Vector dir)
+{
+ m_inclinaison = dir;
+}
+
+Math::Vector CMotion::RetInclinaison()
+{
+ return m_inclinaison;
+}
+
diff --git a/src/object/motion/motion.h b/src/object/motion/motion.h
index bdb9ce0..9828283 100644
--- a/src/object/motion/motion.h
+++ b/src/object/motion/motion.h
@@ -1,93 +1,93 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motion.h
-
-#pragma once
-
-
-#include "common/event.h"
-#include "common/misc.h"
-#include "object/object.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CLight;
-class CParticule;
-class CTerrain;
-class CWater;
-class CCamera;
-class CBrain;
-class CPhysics;
-class CObject;
-class CRobotMain;
-class CSound;
-
-
-class CMotion
-{
-public:
- CMotion(CInstanceManager* iMan, CObject* object);
- virtual ~CMotion();
-
- void SetPhysics(CPhysics* physics);
- void SetBrain(CBrain* brain);
-
- virtual void DeleteObject(bool bAll=false);
- virtual bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- virtual bool EventProcess(const Event &event);
- virtual Error SetAction(int action, float time=0.2f);
- virtual int RetAction();
-
- virtual bool SetParam(int rank, float value);
- virtual float RetParam(int rank);
-
- virtual bool Write(char *line);
- virtual bool Read(char *line);
-
- virtual void SetLinVibration(Math::Vector dir);
- virtual Math::Vector RetLinVibration();
- virtual void SetCirVibration(Math::Vector dir);
- virtual Math::Vector RetCirVibration();
- virtual void SetInclinaison(Math::Vector dir);
- virtual Math::Vector RetInclinaison();
-
-protected:
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CLight* m_light;
- CParticule* m_particule;
- CTerrain* m_terrain;
- CWater* m_water;
- CCamera* m_camera;
- CObject* m_object;
- CBrain* m_brain;
- CPhysics* m_physics;
- CRobotMain* m_main;
- CSound* m_sound;
-
- int m_actionType;
- float m_actionTime;
- float m_progress;
-
- Math::Vector m_linVibration; // linear vibration
- Math::Vector m_cirVibration; // circular vibration
- Math::Vector m_inclinaison; // tilt
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motion.h
+
+#pragma once
+
+
+#include "common/event.h"
+#include "common/misc.h"
+#include "object/object.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CLight;
+class CParticule;
+class CTerrain;
+class CWater;
+class CCamera;
+class CBrain;
+class CPhysics;
+class CObject;
+class CRobotMain;
+class CSound;
+
+
+class CMotion
+{
+public:
+ CMotion(CInstanceManager* iMan, CObject* object);
+ virtual ~CMotion();
+
+ void SetPhysics(CPhysics* physics);
+ void SetBrain(CBrain* brain);
+
+ virtual void DeleteObject(bool bAll=false);
+ virtual bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ virtual bool EventProcess(const Event &event);
+ virtual Error SetAction(int action, float time=0.2f);
+ virtual int RetAction();
+
+ virtual bool SetParam(int rank, float value);
+ virtual float RetParam(int rank);
+
+ virtual bool Write(char *line);
+ virtual bool Read(char *line);
+
+ virtual void SetLinVibration(Math::Vector dir);
+ virtual Math::Vector RetLinVibration();
+ virtual void SetCirVibration(Math::Vector dir);
+ virtual Math::Vector RetCirVibration();
+ virtual void SetInclinaison(Math::Vector dir);
+ virtual Math::Vector RetInclinaison();
+
+protected:
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CLight* m_light;
+ CParticule* m_particule;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CCamera* m_camera;
+ CObject* m_object;
+ CBrain* m_brain;
+ CPhysics* m_physics;
+ CRobotMain* m_main;
+ CSound* m_sound;
+
+ int m_actionType;
+ float m_actionTime;
+ float m_progress;
+
+ Math::Vector m_linVibration; // linear vibration
+ Math::Vector m_cirVibration; // circular vibration
+ Math::Vector m_inclinaison; // tilt
+};
+
diff --git a/src/object/motion/motionant.cpp b/src/object/motion/motionant.cpp
index c85a631..c6a9357 100644
--- a/src/object/motion/motionant.cpp
+++ b/src/object/motion/motionant.cpp
@@ -1,871 +1,871 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionant.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motionant.h"
-
-#include "old/modfile.h"
-#include "old/particule.h"
-#include "physics/physics.h"
-
-
-
-#define ADJUST_ANGLE false // true -> adjusts the angles of the members
-const float START_TIME = 1000.0f; // beginning of the relative time
-
-
-
-// Object's constructor.
-
-CMotionAnt::CMotionAnt(CInstanceManager* iMan, CObject* object)
- : CMotion(iMan, object)
-{
- m_armMember = START_TIME;
- m_armTimeAbs = START_TIME;
- m_armTimeMarch = START_TIME;
- m_armTimeAction = START_TIME;
- m_armTimeIndex = 0;
- m_armPartIndex = 0;
- m_armMemberIndex = 0;
- m_armLastAction = -1;
- m_bArmStop = false;
- m_lastParticule = 0.0f;
-}
-
-// Object's destructor.
-
-CMotionAnt::~CMotionAnt()
-{
-}
-
-
-// Removes an object.
-
-void CMotionAnt::DeleteObject(bool bAll)
-{
-}
-
-
-// Creates a vehicle poses some rolling on the floor.
-
-bool CMotionAnt::Create(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 3+18 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- m_object->SetType(type);
-
- // Creates the main base.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
-
- pModFile->ReadModel("objects\\ant1.mod");
- pModFile->CreateEngineObject(rank);
-
- m_object->SetPosition(0, pos);
- m_object->SetAngleY(0, angle);
-
- // A vehicle must have necessarily a collision
- //with a sphere of center (0, y, 0) (see GetCrashSphere).
- m_object->CreateCrashSphere(Math::Vector(0.0f, -2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
- m_object->SetGlobalSphere(Math::Vector(-0.5f, 1.0f, 0.0f), 4.0f);
-
- // Creates the head.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\ant2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(2.0f, 0.0f, 0.0f));
-
- // Creates the tail.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\ant3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(-1.0f, 0.0f, 0.0f));
-
- // Creates a right-back thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(-0.4f, -0.1f, -0.3f));
-
- // Creates a right-back leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(4, rank);
- m_object->SetObjectParent(4, 3);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(4, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates a right-back foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(5, rank);
- m_object->SetObjectParent(5, 4);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(5, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates two middle-right thighs.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(0.1f, -0.1f, -0.4f));
-
- // Creates two middle-right legs.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 6);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates two middle-right foots.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 7);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates the right front thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(9, rank);
- m_object->SetObjectParent(9, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(9, Math::Vector(1.4f, -0.1f, -0.6f));
-
- // Creates the right front leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(10, rank);
- m_object->SetObjectParent(10, 9);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(10, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates the right front foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(11, rank);
- m_object->SetObjectParent(11, 10);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(11, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates a left-back thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(12, rank);
- m_object->SetObjectParent(12, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(12, Math::Vector(-0.4f, -0.1f, 0.3f));
-
- // Creates a left-back leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(13, rank);
- m_object->SetObjectParent(13, 12);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(13, Math::Vector(0.0f, 0.0f, 1.0f));
-
- // Creates a left-back foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(14, rank);
- m_object->SetObjectParent(14, 13);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(14, Math::Vector(0.0f, 0.0f, 2.0f));
-
- // Creates two middle-left thighs.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(15, rank);
- m_object->SetObjectParent(15, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(15, Math::Vector(0.1f, -0.1f, 0.4f));
-
- // Creates two middle-left legs.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(16, rank);
- m_object->SetObjectParent(16, 15);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(16, Math::Vector(0.0f, 0.0f, 1.0f));
-
- // Creates two middle-left foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(17, rank);
- m_object->SetObjectParent(17, 16);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(17, Math::Vector(0.0f, 0.0f, 2.0f));
-
- // Creates the left front thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(18, rank);
- m_object->SetObjectParent(18, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(18, Math::Vector(1.4f, -0.1f, 0.6f));
-
- // Creates the left front leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(19, rank);
- m_object->SetObjectParent(19, 18);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(19, Math::Vector(0.0f, 0.0f, 1.0f));
-
- // Creates the left front foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(20, rank);
- m_object->SetObjectParent(20, 19);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(20, Math::Vector(0.0f, 0.0f, 2.0f));
-
- m_object->CreateShadowCircle(4.0f, 0.5f);
-
- CreatePhysics();
- m_object->SetFloorHeight(0.0f);
-
- pos = m_object->RetPosition(0);
- m_object->SetPosition(0, pos); // to display the shadows immediately
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-// Creates the physics of the object.
-
-void CMotionAnt::CreatePhysics()
-{
- Character* character;
- int i;
-
- int member_march[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
- 0,45,0, 0,45,0, 0,50,0, // t0: thighs 1..3
- 30,-70,0, 20,-105,20, 25,-100,0, // t0: legs 1..3
- -70,75,0, -30,80,0, -80,80,0, // t0: feet 1..3
- // on the ground:
- 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3
- -15,-50,0, -20,-60,0, -10,-75,0, // t1: legs 1..3
- -40,50,0, -25,15,0, -50,35,0, // t1: feet 1..3
- // on the ground back:
- 0,35,0, 0,30,0, 0,20,0, // t2: thighs 1..3
- -20,-15,0, -30,-55,0, -25,-70,15, // t2: legs 1..3
- -25,25,0, -20,60,0, -30,95,0, // t2: feet 1..3
- };
-
- int member_stop[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
- 0,30,0, 0,20,0, 0,15,0, // t0: thighs 1..3
- -15,-35,0, -20,-60,0, -15,-75,0, // t0: legs 1..3
- -35,35,0, -25,40,0, -40,65,0, // t0: feet 1..3
- // on the ground:
- 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3
- -15,-35,0, -20,-60,0, -15,-75,0, // t1: legs 1..3
- -35,35,0, -25,40,0, -40,65,0, // t1: feet 1..3
- // on the ground back:
- 0,30,0, 0,20,0, 0,15,0, // t2: thighs 1..3
- -15,-35,0, -20,-60,0, -15,-75,0, // t2: legs 1..3
- -35,35,0, -25,40,0, -40,65,0, // t2: feet 1..3
- };
-
- int member_spec[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // prepares the fire:
- 0,20,0, 0,10,0, 0,50,0, // s0: thighs 1..3
- -50,-30,0, -20,-15,0, 35,-65,0, // s0: legs 1..3
- -5,-40,0, 20,-70,0, -10,-40,0, // s0: feet 1..3
- // shot:
- 0,20,0, 0,10,0, 0,50,0, // s1: thighs 1..3
- -50,-30,0, -20,-15,0, 35,-65,0, // s1: legs 1..3
- -5,-40,0, 20,-70,0, -10,-40,0, // s1: feet 1..3
- // ends the fire:
- 0,30,0, 0,20,0, 0,15,0, // s2: thighs 1..3
- -15,-50,0, -20,-60,0, -10,-75,0, // s2: legs 1..3
- -40,50,0, -25,15,0, -50,35,0, // s2: feet 1..3
- // burning:
- 0,30,0, 0,20,0, 0,15,0, // s3: thighs 1..3
- -15,-35,0, -20,-60,0, -15,-75,0, // s3: legs 1..3
- -35,35,0, -25,40,0, -40,65,0, // s3: feet 1..3
- // destroyed:
- 0,30,0, 0,20,0, 0,15,0, // s4: thighs 1..3
- -15,-35,0, -20,-60,0, -15,-75,0, // s4: legs 1..3
- -35,35,0, -25,40,0, -40,65,0, // s4: feet 1..3
- // back1 :
- 0,30,0, 0,20,0, 0,15,0, // s5: thighs 1..3
- -15,-35,0, -20,-60,0, -15,-75,0, // s5: legs 1..3
- -35,35,0, -25,40,0, -40,65,0, // s5: feet 1..3
- // back2 :
- 0,45,0, 0,45,0, 0,50,0, // s6: thighs 1..3
- -35,-70,0, -20,-85,-25, -25,-100,0, // s6: legs 1..3
- -110,75,-15, -130,80,-25, -125,40,0, // s6: feet 1..3
- // back3 :
- 0,30,0, 0,20,0, 0,15,0, // s7: thighs 1..3
- -15,-35,0, -20,-60,0, -15,-75,0, // s7: legs 1..3
- -35,35,0, -25,40,0, -40,65,0, // s7: feet 1..3
- };
-
- m_physics->SetType(TYPE_ROLLING);
-
- character = m_object->RetCharacter();
- character->wheelFront = 3.0f;
- character->wheelBack = 3.0f;
- character->wheelLeft = 5.0f;
- character->wheelRight = 5.0f;
- character->height = 1.2f;
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 12.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 12.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 15.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 10.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 20.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 40.0f);
-
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MA_MARCH+i] = member_march[i];
- }
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MA_STOP+i] = member_stop[i];
- }
- for ( i=0 ; i<3*3*3*8 ; i++ )
- {
- m_armAngles[3*3*3*3*MA_SPEC+i] = member_spec[i];
- }
-}
-
-
-// Management of an event.
-
-bool CMotionAnt::EventProcess(const Event &event)
-{
- CMotion::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
-#if ADJUST_ANGLE
- int i;
-
- if ( event.param == 'A' ) m_armTimeIndex++;
- if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
-
- if ( event.param == 'Q' ) m_armPartIndex++;
- if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
-
- if ( event.param == 'W' ) m_armMemberIndex++;
- if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
-
- i = m_armMemberIndex*3;
- i += m_armPartIndex*3*3;
- i += m_armTimeIndex*3*3*3;
-//? i += 3*3*3*3;
-
- if ( event.param == 'E' ) m_armAngles[i+0] += 5;
- if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
- if ( event.param == 'R' ) m_armAngles[i+1] += 5;
- if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
- if ( event.param == 'T' ) m_armAngles[i+2] += 5;
- if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
-
- if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
-#endif
- }
-
- return true;
-}
-
-// Management of an event.
-
-bool CMotionAnt::EventFrame(const Event &event)
-{
- Math::Vector dir, pos, speed;
- Math::Point dim;
- float s, a, prog, time;
- float tSt[9], tNd[9];
- int i, ii, st, nd, action;
- bool bStop;
-
- if ( m_engine->RetPause() ) return true;
- if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
-
- s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
- a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f);
-
- if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
-
- m_armTimeAbs += event.rTime;
- m_armTimeMarch += (s)*event.rTime*0.15f;
- m_armMember += (s+a)*event.rTime*0.15f;
-
- bStop = ( a == 0.0f && s == 0.0f ); // stopped?
-
- action = MA_MARCH; // walking
- if ( s == 0.0f && a == 0.0f )
- {
- action = MA_STOP; // stop
- }
-
- if ( bStop )
- {
- prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
- a = Math::Mod(m_armMember, 1.0f);
- a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly
- m_armMember += a;
- }
-
- if ( m_object->RetRuin() ) // destroyed?
- {
- m_actionType = MAS_RUIN;
- }
- if ( m_object->RetBurn() ) // burning?
- {
- if ( m_object->RetFixed() )
- {
- m_actionType = MAS_BURN;
- }
- else
- {
- m_actionType = -1;
- }
- }
-
- for ( i=0 ; i<6 ; i++ ) // the six legs
- {
- if ( m_actionType != -1 ) // special action in progress?
- {
- st = 3*3*3*3*MA_SPEC + 3*3*3*m_actionType + (i%3)*3;
- nd = st;
- time = event.rTime*m_actionTime;
- m_armTimeAction = 0.0f;
- }
- else
- {
- if ( i < 3 ) prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
- else prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
- if ( m_bArmStop )
- {
- prog = (float)m_armTimeIndex/3.0f;
- }
- if ( prog < 0.33f ) // t0..t1 ?
- {
- prog = prog/0.33f; // 0..1
- st = 0; // index start
- nd = 1; // index end
- }
- else if ( prog < 0.67f ) // t1..t2 ?
- {
- prog = (prog-0.33f)/0.33f; // 0..1
- st = 1; // index start
- nd = 2; // index end
- }
- else // t2..t0 ?
- {
- prog = (prog-0.67f)/0.33f; // 0..1
- st = 2; // index start
- nd = 0; // index end
- }
- st = 3*3*3*3*action + st*3*3*3 + (i%3)*3;
- nd = 3*3*3*3*action + nd*3*3*3 + (i%3)*3;
-
- // More and more soft ...
- time = event.rTime*(10.0f+Math::Min(m_armTimeAction*100.0f, 200.0f));
- }
-
- tSt[0] = m_armAngles[st+ 0]; // x
- tSt[1] = m_armAngles[st+ 1]; // y
- tSt[2] = m_armAngles[st+ 2]; // z
- tSt[3] = m_armAngles[st+ 9]; // x
- tSt[4] = m_armAngles[st+10]; // y
- tSt[5] = m_armAngles[st+11]; // z
- tSt[6] = m_armAngles[st+18]; // x
- tSt[7] = m_armAngles[st+19]; // y
- tSt[8] = m_armAngles[st+20]; // z
-
- tNd[0] = m_armAngles[nd+ 0]; // x
- tNd[1] = m_armAngles[nd+ 1]; // y
- tNd[2] = m_armAngles[nd+ 2]; // z
- tNd[3] = m_armAngles[nd+ 9]; // x
- tNd[4] = m_armAngles[nd+10]; // y
- tNd[5] = m_armAngles[nd+11]; // z
- tNd[6] = m_armAngles[nd+18]; // x
- tNd[7] = m_armAngles[nd+19]; // y
- tNd[8] = m_armAngles[nd+20]; // z
-
- if ( m_actionType == MAS_BACK2 ) // on the back?
- {
- for ( ii=0 ; ii<9 ; ii++ )
- {
- tSt[ii] += Math::Rand()*50.0f;
- tNd[ii] = tSt[ii];
- }
-//? time = 100.0f;
- time = event.rTime*10.0f;
- }
-
- if ( i < 3 ) // right leg (1..3) ?
- {
- m_object->SetAngleX(3+3*i+0, Math::Smooth(m_object->RetAngleX(3+3*i+0), Math::PropAngle(tSt[0], tNd[0], prog), time));
- m_object->SetAngleY(3+3*i+0, Math::Smooth(m_object->RetAngleY(3+3*i+0), Math::PropAngle(tSt[1], tNd[1], prog), time));
- m_object->SetAngleZ(3+3*i+0, Math::Smooth(m_object->RetAngleZ(3+3*i+0), Math::PropAngle(tSt[2], tNd[2], prog), time));
- m_object->SetAngleX(3+3*i+1, Math::Smooth(m_object->RetAngleX(3+3*i+1), Math::PropAngle(tSt[3], tNd[3], prog), time));
- m_object->SetAngleY(3+3*i+1, Math::Smooth(m_object->RetAngleY(3+3*i+1), Math::PropAngle(tSt[4], tNd[4], prog), time));
- m_object->SetAngleZ(3+3*i+1, Math::Smooth(m_object->RetAngleZ(3+3*i+1), Math::PropAngle(tSt[5], tNd[5], prog), time));
- m_object->SetAngleX(3+3*i+2, Math::Smooth(m_object->RetAngleX(3+3*i+2), Math::PropAngle(tSt[6], tNd[6], prog), time));
- m_object->SetAngleY(3+3*i+2, Math::Smooth(m_object->RetAngleY(3+3*i+2), Math::PropAngle(tSt[7], tNd[7], prog), time));
- m_object->SetAngleZ(3+3*i+2, Math::Smooth(m_object->RetAngleZ(3+3*i+2), Math::PropAngle(tSt[8], tNd[8], prog), time));
- }
- else // left leg (4..6) ?
- {
- m_object->SetAngleX(3+3*i+0, Math::Smooth(m_object->RetAngleX(3+3*i+0), Math::PropAngle(-tSt[0], -tNd[0], prog), time));
- m_object->SetAngleY(3+3*i+0, Math::Smooth(m_object->RetAngleY(3+3*i+0), Math::PropAngle(-tSt[1], -tNd[1], prog), time));
- m_object->SetAngleZ(3+3*i+0, Math::Smooth(m_object->RetAngleZ(3+3*i+0), Math::PropAngle( tSt[2], tNd[2], prog), time));
- m_object->SetAngleX(3+3*i+1, Math::Smooth(m_object->RetAngleX(3+3*i+1), Math::PropAngle(-tSt[3], -tNd[3], prog), time));
- m_object->SetAngleY(3+3*i+1, Math::Smooth(m_object->RetAngleY(3+3*i+1), Math::PropAngle(-tSt[4], -tNd[4], prog), time));
- m_object->SetAngleZ(3+3*i+1, Math::Smooth(m_object->RetAngleZ(3+3*i+1), Math::PropAngle( tSt[5], tNd[5], prog), time));
- m_object->SetAngleX(3+3*i+2, Math::Smooth(m_object->RetAngleX(3+3*i+2), Math::PropAngle(-tSt[6], -tNd[6], prog), time));
- m_object->SetAngleY(3+3*i+2, Math::Smooth(m_object->RetAngleY(3+3*i+2), Math::PropAngle(-tSt[7], -tNd[7], prog), time));
- m_object->SetAngleZ(3+3*i+2, Math::Smooth(m_object->RetAngleZ(3+3*i+2), Math::PropAngle( tSt[8], tNd[8], prog), time));
- }
- }
-
-#if ADJUST_ANGLE
- if ( m_object->RetSelect() )
- {
- char s[100];
- sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
- m_engine->SetInfoText(4, s);
- }
-#endif
-
- if ( m_actionType == MAS_PREPARE ) // prepares the shooting?
- {
- prog = m_progress;
-
- dir.x = 0.0f;
- dir.y = 0.0f;
- dir.z = Math::PropAngle(0, -50, prog);
- SetInclinaison(dir);
- m_object->SetAngleZ(1, Math::PropAngle(0, 65, prog)); // head
- m_object->SetAngleZ(2, Math::PropAngle(0, -95, prog)); // tail
- }
- else if ( m_actionType == MAS_FIRE ) // shooting?
- {
- if ( m_progress < 0.75f ) a = m_progress/0.75f;
- else a = (1.0f-m_progress)/0.25f;
- m_object->SetZoom(2, (a*0.5f)+1.0f); // tail
- m_object->SetAngleX(2, (Math::Rand()-0.5f)*0.3f*a);
- m_object->SetAngleY(2, (Math::Rand()-0.5f)*0.3f*a);
-
- dir.x = (Math::Rand()-0.5f)*0.02f*a;
- dir.y = (Math::Rand()-0.5f)*0.05f*a;
- dir.z = (Math::Rand()-0.5f)*0.03f*a;
- SetCirVibration(dir);
- }
- else if ( m_actionType == MAS_TERMINATE ) // ends the shooting?
- {
- prog = 1.0f-m_progress;
-
- dir.x = 0.0f;
- dir.y = 0.0f;
- dir.z = Math::PropAngle(0, -50, prog);
- SetInclinaison(dir);
- m_object->SetAngleZ(1, Math::PropAngle(0, 65, prog)); // head
- m_object->SetAngleZ(2, Math::PropAngle(0, -95, prog)); // tail
- }
- else if ( m_actionType == MAS_BURN ) // burning?
- {
- dir = Math::Vector(Math::PI, 0.0f, 0.0f);
- SetCirVibration(dir);
- dir = Math::Vector(0.0f, -1.5f, 0.0f);
- SetLinVibration(dir);
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetInclinaison(dir);
-
- time = event.rTime*1.0f;
- m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), 0.0f, time)); // head
- m_object->SetAngleZ(2, Math::Smooth(m_object->RetAngleZ(2), 0.0f, time)); // tail
- }
- else if ( m_actionType == MAS_RUIN ) // destroyed?
- {
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetLinVibration(dir);
- SetCirVibration(dir);
- SetInclinaison(dir);
- }
- else if ( m_actionType == MAS_BACK1 ) // starts on the back?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
- {
- m_lastParticule = m_armTimeAbs;
-
- pos = m_object->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = Math::Rand()*5.0f;
- dim.x = Math::Rand()*3.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
-
- if ( m_progress < 0.5f )
- {
- dir.x = 0.0f;
- dir.y = powf(m_progress/0.5f, 2.0f)*12.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
- else
- {
- dir.x = 0.0f;
- dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*12.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
- dir.x = m_progress*Math::PI;
- dir.y = 0.0f;
- dir.z = 0.0f;
- SetCirVibration(dir);
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetInclinaison(dir);
-
- if ( m_progress >= 1.0f )
- {
- SetAction(MAS_BACK2, 55.0f+Math::Rand()*10.0f);
- }
- }
- else if ( m_actionType == MAS_BACK2 ) // moves on the back?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
- {
- m_lastParticule = m_armTimeAbs;
-
- if ( rand()%10 == 0 )
- {
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- pos.y -= 1.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = Math::Rand()*2.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
- }
-
- dir = Math::Vector(0.0f, -1.0f, 0.0f);
- SetLinVibration(dir);
- dir.x = sinf(m_armTimeAbs* 4.0f)*0.10f+
- sinf(m_armTimeAbs* 7.0f)*0.20f+
- sinf(m_armTimeAbs*10.0f)*0.40f+
- sinf(m_armTimeAbs*21.0f)*0.50f+Math::PI;
- dir.y = sinf(m_armTimeAbs* 3.0f)*0.01f+
- sinf(m_armTimeAbs* 6.0f)*0.02f+
- sinf(m_armTimeAbs*11.0f)*0.04f+
- sinf(m_armTimeAbs*20.0f)*0.02f;
- dir.z = sinf(m_armTimeAbs* 5.0f)*0.01f+
- sinf(m_armTimeAbs* 8.0f)*0.02f+
- sinf(m_armTimeAbs* 9.0f)*0.04f+
- sinf(m_armTimeAbs*23.0f)*0.03f;
- SetCirVibration(dir);
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetInclinaison(dir);
-
- m_object->SetAngleY(1, sinf(m_armTimeAbs*8.0f)*0.7f); // head
- m_object->SetAngleY(2, cosf(m_armTimeAbs*8.0f)*0.7f); // tail
- m_object->SetAngleZ(1, 0.0f); // head
- m_object->SetAngleZ(2, 0.0f); // tail
-
- if ( m_progress >= 1.0f )
- {
- SetAction(MAS_BACK3, 0.4f);
- }
- }
- else if ( m_actionType == MAS_BACK3 ) // goes back on the legs?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
- {
- m_lastParticule = m_armTimeAbs;
-
- pos = m_object->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = Math::Rand()*5.0f;
- dim.x = Math::Rand()*3.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
-
- if ( m_progress < 0.5f )
- {
- dir.x = 0.0f;
- dir.y = powf(m_progress/0.5f, 2.0f)*5.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
- else
- {
- dir.x = 0.0f;
- dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*5.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
- dir.x = (1.0f-m_progress)*Math::PI;
- dir.y = 0.0f;
- dir.z = 0.0f;
- SetCirVibration(dir);
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetInclinaison(dir);
-
- if ( m_progress >= 1.0f )
- {
- SetAction(-1);
- m_object->SetFixed(false); // moving again
- }
- }
- else
- {
- m_object->SetZoom(2, 1.0f); // tail
- m_object->SetAngleX(2, 0.0f);
- m_object->SetAngleY(2, 0.0f);
-
- if ( bStop )
- {
- m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.7f)*0.15f); // tail
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetLinVibration(dir);
- SetInclinaison(dir);
- }
- else
- {
- a = Math::Mod(m_armTimeMarch, 1.0f);
- if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
- else a = 3.0f-4.0f*a; // 1..-1
- dir.x = sinf(a)*0.05f;
-
- s = Math::Mod(m_armTimeMarch/2.0f, 1.0f);
- if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
- else s = 3.0f-4.0f*s; // 1..-1
- dir.z = sinf(s)*0.1f;
-
- dir.y = 0.0f;
- SetInclinaison(dir);
-
- m_object->SetAngleZ(2, -sinf(a)*0.3f); // tail
-
- a = Math::Mod(m_armMember-0.1f, 1.0f);
- if ( a < 0.33f )
- {
- dir.y = -(1.0f-(a/0.33f))*0.3f;
- }
- else if ( a < 0.67f )
- {
- dir.y = 0.0f;
- }
- else
- {
- dir.y = -(a-0.67f)/0.33f*0.3f;
- }
- dir.x = 0.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetCirVibration(dir);
-
- m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.4f)*0.20f); // head
- m_object->SetAngleX(1, sinf(m_armTimeAbs*1.9f)*0.10f); // head
- m_object->SetAngleY(1, sinf(m_armTimeAbs*2.1f)*0.50f); // head
- }
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionant.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motionant.h"
+
+#include "old/modfile.h"
+#include "old/particule.h"
+#include "physics/physics.h"
+
+
+
+#define ADJUST_ANGLE false // true -> adjusts the angles of the members
+const float START_TIME = 1000.0f; // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionAnt::CMotionAnt(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeMarch = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLastAction = -1;
+ m_bArmStop = false;
+ m_lastParticule = 0.0f;
+}
+
+// Object's destructor.
+
+CMotionAnt::~CMotionAnt()
+{
+}
+
+
+// Removes an object.
+
+void CMotionAnt::DeleteObject(bool bAll)
+{
+}
+
+
+// Creates a vehicle poses some rolling on the floor.
+
+bool CMotionAnt::Create(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 3+18 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates the main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+
+ pModFile->ReadModel("objects\\ant1.mod");
+ pModFile->CreateEngineObject(rank);
+
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have necessarily a collision
+ //with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(Math::Vector(0.0f, -2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
+ m_object->SetGlobalSphere(Math::Vector(-0.5f, 1.0f, 0.0f), 4.0f);
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\ant2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(2.0f, 0.0f, 0.0f));
+
+ // Creates the tail.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\ant3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(-1.0f, 0.0f, 0.0f));
+
+ // Creates a right-back thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(-0.4f, -0.1f, -0.3f));
+
+ // Creates a right-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 3);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates a right-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 4);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates two middle-right thighs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(0.1f, -0.1f, -0.4f));
+
+ // Creates two middle-right legs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 6);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates two middle-right foots.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 7);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates the right front thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, Math::Vector(1.4f, -0.1f, -0.6f));
+
+ // Creates the right front leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10, rank);
+ m_object->SetObjectParent(10, 9);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates the right front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(11, rank);
+ m_object->SetObjectParent(11, 10);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(11, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates a left-back thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(12, rank);
+ m_object->SetObjectParent(12, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(12, Math::Vector(-0.4f, -0.1f, 0.3f));
+
+ // Creates a left-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(13, rank);
+ m_object->SetObjectParent(13, 12);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(13, Math::Vector(0.0f, 0.0f, 1.0f));
+
+ // Creates a left-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(14, rank);
+ m_object->SetObjectParent(14, 13);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(14, Math::Vector(0.0f, 0.0f, 2.0f));
+
+ // Creates two middle-left thighs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(15, rank);
+ m_object->SetObjectParent(15, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(15, Math::Vector(0.1f, -0.1f, 0.4f));
+
+ // Creates two middle-left legs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(16, rank);
+ m_object->SetObjectParent(16, 15);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(16, Math::Vector(0.0f, 0.0f, 1.0f));
+
+ // Creates two middle-left foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(17, rank);
+ m_object->SetObjectParent(17, 16);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(17, Math::Vector(0.0f, 0.0f, 2.0f));
+
+ // Creates the left front thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(18, rank);
+ m_object->SetObjectParent(18, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(18, Math::Vector(1.4f, -0.1f, 0.6f));
+
+ // Creates the left front leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(19, rank);
+ m_object->SetObjectParent(19, 18);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(19, Math::Vector(0.0f, 0.0f, 1.0f));
+
+ // Creates the left front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(20, rank);
+ m_object->SetObjectParent(20, 19);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(20, Math::Vector(0.0f, 0.0f, 2.0f));
+
+ m_object->CreateShadowCircle(4.0f, 0.5f);
+
+ CreatePhysics();
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+// Creates the physics of the object.
+
+void CMotionAnt::CreatePhysics()
+{
+ Character* character;
+ int i;
+
+ int member_march[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 0,45,0, 0,45,0, 0,50,0, // t0: thighs 1..3
+ 30,-70,0, 20,-105,20, 25,-100,0, // t0: legs 1..3
+ -70,75,0, -30,80,0, -80,80,0, // t0: feet 1..3
+ // on the ground:
+ 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3
+ -15,-50,0, -20,-60,0, -10,-75,0, // t1: legs 1..3
+ -40,50,0, -25,15,0, -50,35,0, // t1: feet 1..3
+ // on the ground back:
+ 0,35,0, 0,30,0, 0,20,0, // t2: thighs 1..3
+ -20,-15,0, -30,-55,0, -25,-70,15, // t2: legs 1..3
+ -25,25,0, -20,60,0, -30,95,0, // t2: feet 1..3
+ };
+
+ int member_stop[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 0,30,0, 0,20,0, 0,15,0, // t0: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // t0: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // t0: feet 1..3
+ // on the ground:
+ 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // t1: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // t1: feet 1..3
+ // on the ground back:
+ 0,30,0, 0,20,0, 0,15,0, // t2: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // t2: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // t2: feet 1..3
+ };
+
+ int member_spec[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // prepares the fire:
+ 0,20,0, 0,10,0, 0,50,0, // s0: thighs 1..3
+ -50,-30,0, -20,-15,0, 35,-65,0, // s0: legs 1..3
+ -5,-40,0, 20,-70,0, -10,-40,0, // s0: feet 1..3
+ // shot:
+ 0,20,0, 0,10,0, 0,50,0, // s1: thighs 1..3
+ -50,-30,0, -20,-15,0, 35,-65,0, // s1: legs 1..3
+ -5,-40,0, 20,-70,0, -10,-40,0, // s1: feet 1..3
+ // ends the fire:
+ 0,30,0, 0,20,0, 0,15,0, // s2: thighs 1..3
+ -15,-50,0, -20,-60,0, -10,-75,0, // s2: legs 1..3
+ -40,50,0, -25,15,0, -50,35,0, // s2: feet 1..3
+ // burning:
+ 0,30,0, 0,20,0, 0,15,0, // s3: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // s3: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // s3: feet 1..3
+ // destroyed:
+ 0,30,0, 0,20,0, 0,15,0, // s4: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // s4: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // s4: feet 1..3
+ // back1 :
+ 0,30,0, 0,20,0, 0,15,0, // s5: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // s5: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // s5: feet 1..3
+ // back2 :
+ 0,45,0, 0,45,0, 0,50,0, // s6: thighs 1..3
+ -35,-70,0, -20,-85,-25, -25,-100,0, // s6: legs 1..3
+ -110,75,-15, -130,80,-25, -125,40,0, // s6: feet 1..3
+ // back3 :
+ 0,30,0, 0,20,0, 0,15,0, // s7: thighs 1..3
+ -15,-35,0, -20,-60,0, -15,-75,0, // s7: legs 1..3
+ -35,35,0, -25,40,0, -40,65,0, // s7: feet 1..3
+ };
+
+ m_physics->SetType(TYPE_ROLLING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 3.0f;
+ character->wheelBack = 3.0f;
+ character->wheelLeft = 5.0f;
+ character->wheelRight = 5.0f;
+ character->height = 1.2f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 12.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 12.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 15.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 10.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 40.0f);
+
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MA_MARCH+i] = member_march[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MA_STOP+i] = member_stop[i];
+ }
+ for ( i=0 ; i<3*3*3*8 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MA_SPEC+i] = member_spec[i];
+ }
+}
+
+
+// Management of an event.
+
+bool CMotionAnt::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if ADJUST_ANGLE
+ int i;
+
+ if ( event.param == 'A' ) m_armTimeIndex++;
+ if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
+
+ if ( event.param == 'Q' ) m_armPartIndex++;
+ if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
+
+ if ( event.param == 'W' ) m_armMemberIndex++;
+ if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
+
+ i = m_armMemberIndex*3;
+ i += m_armPartIndex*3*3;
+ i += m_armTimeIndex*3*3*3;
+//? i += 3*3*3*3;
+
+ if ( event.param == 'E' ) m_armAngles[i+0] += 5;
+ if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
+ if ( event.param == 'R' ) m_armAngles[i+1] += 5;
+ if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
+ if ( event.param == 'T' ) m_armAngles[i+2] += 5;
+ if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
+
+ if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
+#endif
+ }
+
+ return true;
+}
+
+// Management of an event.
+
+bool CMotionAnt::EventFrame(const Event &event)
+{
+ Math::Vector dir, pos, speed;
+ Math::Point dim;
+ float s, a, prog, time;
+ float tSt[9], tNd[9];
+ int i, ii, st, nd, action;
+ bool bStop;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
+ a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f);
+
+ if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armTimeMarch += (s)*event.rTime*0.15f;
+ m_armMember += (s+a)*event.rTime*0.15f;
+
+ bStop = ( a == 0.0f && s == 0.0f ); // stopped?
+
+ action = MA_MARCH; // walking
+ if ( s == 0.0f && a == 0.0f )
+ {
+ action = MA_STOP; // stop
+ }
+
+ if ( bStop )
+ {
+ prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
+ a = Math::Mod(m_armMember, 1.0f);
+ a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly
+ m_armMember += a;
+ }
+
+ if ( m_object->RetRuin() ) // destroyed?
+ {
+ m_actionType = MAS_RUIN;
+ }
+ if ( m_object->RetBurn() ) // burning?
+ {
+ if ( m_object->RetFixed() )
+ {
+ m_actionType = MAS_BURN;
+ }
+ else
+ {
+ m_actionType = -1;
+ }
+ }
+
+ for ( i=0 ; i<6 ; i++ ) // the six legs
+ {
+ if ( m_actionType != -1 ) // special action in progress?
+ {
+ st = 3*3*3*3*MA_SPEC + 3*3*3*m_actionType + (i%3)*3;
+ nd = st;
+ time = event.rTime*m_actionTime;
+ m_armTimeAction = 0.0f;
+ }
+ else
+ {
+ if ( i < 3 ) prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
+ else prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
+ if ( m_bArmStop )
+ {
+ prog = (float)m_armTimeIndex/3.0f;
+ }
+ if ( prog < 0.33f ) // t0..t1 ?
+ {
+ prog = prog/0.33f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.67f ) // t1..t2 ?
+ {
+ prog = (prog-0.33f)/0.33f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.67f)/0.33f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ st = 3*3*3*3*action + st*3*3*3 + (i%3)*3;
+ nd = 3*3*3*3*action + nd*3*3*3 + (i%3)*3;
+
+ // More and more soft ...
+ time = event.rTime*(10.0f+Math::Min(m_armTimeAction*100.0f, 200.0f));
+ }
+
+ tSt[0] = m_armAngles[st+ 0]; // x
+ tSt[1] = m_armAngles[st+ 1]; // y
+ tSt[2] = m_armAngles[st+ 2]; // z
+ tSt[3] = m_armAngles[st+ 9]; // x
+ tSt[4] = m_armAngles[st+10]; // y
+ tSt[5] = m_armAngles[st+11]; // z
+ tSt[6] = m_armAngles[st+18]; // x
+ tSt[7] = m_armAngles[st+19]; // y
+ tSt[8] = m_armAngles[st+20]; // z
+
+ tNd[0] = m_armAngles[nd+ 0]; // x
+ tNd[1] = m_armAngles[nd+ 1]; // y
+ tNd[2] = m_armAngles[nd+ 2]; // z
+ tNd[3] = m_armAngles[nd+ 9]; // x
+ tNd[4] = m_armAngles[nd+10]; // y
+ tNd[5] = m_armAngles[nd+11]; // z
+ tNd[6] = m_armAngles[nd+18]; // x
+ tNd[7] = m_armAngles[nd+19]; // y
+ tNd[8] = m_armAngles[nd+20]; // z
+
+ if ( m_actionType == MAS_BACK2 ) // on the back?
+ {
+ for ( ii=0 ; ii<9 ; ii++ )
+ {
+ tSt[ii] += Math::Rand()*50.0f;
+ tNd[ii] = tSt[ii];
+ }
+//? time = 100.0f;
+ time = event.rTime*10.0f;
+ }
+
+ if ( i < 3 ) // right leg (1..3) ?
+ {
+ m_object->SetAngleX(3+3*i+0, Math::Smooth(m_object->RetAngleX(3+3*i+0), Math::PropAngle(tSt[0], tNd[0], prog), time));
+ m_object->SetAngleY(3+3*i+0, Math::Smooth(m_object->RetAngleY(3+3*i+0), Math::PropAngle(tSt[1], tNd[1], prog), time));
+ m_object->SetAngleZ(3+3*i+0, Math::Smooth(m_object->RetAngleZ(3+3*i+0), Math::PropAngle(tSt[2], tNd[2], prog), time));
+ m_object->SetAngleX(3+3*i+1, Math::Smooth(m_object->RetAngleX(3+3*i+1), Math::PropAngle(tSt[3], tNd[3], prog), time));
+ m_object->SetAngleY(3+3*i+1, Math::Smooth(m_object->RetAngleY(3+3*i+1), Math::PropAngle(tSt[4], tNd[4], prog), time));
+ m_object->SetAngleZ(3+3*i+1, Math::Smooth(m_object->RetAngleZ(3+3*i+1), Math::PropAngle(tSt[5], tNd[5], prog), time));
+ m_object->SetAngleX(3+3*i+2, Math::Smooth(m_object->RetAngleX(3+3*i+2), Math::PropAngle(tSt[6], tNd[6], prog), time));
+ m_object->SetAngleY(3+3*i+2, Math::Smooth(m_object->RetAngleY(3+3*i+2), Math::PropAngle(tSt[7], tNd[7], prog), time));
+ m_object->SetAngleZ(3+3*i+2, Math::Smooth(m_object->RetAngleZ(3+3*i+2), Math::PropAngle(tSt[8], tNd[8], prog), time));
+ }
+ else // left leg (4..6) ?
+ {
+ m_object->SetAngleX(3+3*i+0, Math::Smooth(m_object->RetAngleX(3+3*i+0), Math::PropAngle(-tSt[0], -tNd[0], prog), time));
+ m_object->SetAngleY(3+3*i+0, Math::Smooth(m_object->RetAngleY(3+3*i+0), Math::PropAngle(-tSt[1], -tNd[1], prog), time));
+ m_object->SetAngleZ(3+3*i+0, Math::Smooth(m_object->RetAngleZ(3+3*i+0), Math::PropAngle( tSt[2], tNd[2], prog), time));
+ m_object->SetAngleX(3+3*i+1, Math::Smooth(m_object->RetAngleX(3+3*i+1), Math::PropAngle(-tSt[3], -tNd[3], prog), time));
+ m_object->SetAngleY(3+3*i+1, Math::Smooth(m_object->RetAngleY(3+3*i+1), Math::PropAngle(-tSt[4], -tNd[4], prog), time));
+ m_object->SetAngleZ(3+3*i+1, Math::Smooth(m_object->RetAngleZ(3+3*i+1), Math::PropAngle( tSt[5], tNd[5], prog), time));
+ m_object->SetAngleX(3+3*i+2, Math::Smooth(m_object->RetAngleX(3+3*i+2), Math::PropAngle(-tSt[6], -tNd[6], prog), time));
+ m_object->SetAngleY(3+3*i+2, Math::Smooth(m_object->RetAngleY(3+3*i+2), Math::PropAngle(-tSt[7], -tNd[7], prog), time));
+ m_object->SetAngleZ(3+3*i+2, Math::Smooth(m_object->RetAngleZ(3+3*i+2), Math::PropAngle( tSt[8], tNd[8], prog), time));
+ }
+ }
+
+#if ADJUST_ANGLE
+ if ( m_object->RetSelect() )
+ {
+ char s[100];
+ sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
+ m_engine->SetInfoText(4, s);
+ }
+#endif
+
+ if ( m_actionType == MAS_PREPARE ) // prepares the shooting?
+ {
+ prog = m_progress;
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = Math::PropAngle(0, -50, prog);
+ SetInclinaison(dir);
+ m_object->SetAngleZ(1, Math::PropAngle(0, 65, prog)); // head
+ m_object->SetAngleZ(2, Math::PropAngle(0, -95, prog)); // tail
+ }
+ else if ( m_actionType == MAS_FIRE ) // shooting?
+ {
+ if ( m_progress < 0.75f ) a = m_progress/0.75f;
+ else a = (1.0f-m_progress)/0.25f;
+ m_object->SetZoom(2, (a*0.5f)+1.0f); // tail
+ m_object->SetAngleX(2, (Math::Rand()-0.5f)*0.3f*a);
+ m_object->SetAngleY(2, (Math::Rand()-0.5f)*0.3f*a);
+
+ dir.x = (Math::Rand()-0.5f)*0.02f*a;
+ dir.y = (Math::Rand()-0.5f)*0.05f*a;
+ dir.z = (Math::Rand()-0.5f)*0.03f*a;
+ SetCirVibration(dir);
+ }
+ else if ( m_actionType == MAS_TERMINATE ) // ends the shooting?
+ {
+ prog = 1.0f-m_progress;
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = Math::PropAngle(0, -50, prog);
+ SetInclinaison(dir);
+ m_object->SetAngleZ(1, Math::PropAngle(0, 65, prog)); // head
+ m_object->SetAngleZ(2, Math::PropAngle(0, -95, prog)); // tail
+ }
+ else if ( m_actionType == MAS_BURN ) // burning?
+ {
+ dir = Math::Vector(Math::PI, 0.0f, 0.0f);
+ SetCirVibration(dir);
+ dir = Math::Vector(0.0f, -1.5f, 0.0f);
+ SetLinVibration(dir);
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ time = event.rTime*1.0f;
+ m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), 0.0f, time)); // head
+ m_object->SetAngleZ(2, Math::Smooth(m_object->RetAngleZ(2), 0.0f, time)); // tail
+ }
+ else if ( m_actionType == MAS_RUIN ) // destroyed?
+ {
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ SetCirVibration(dir);
+ SetInclinaison(dir);
+ }
+ else if ( m_actionType == MAS_BACK1 ) // starts on the back?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = Math::Rand()*5.0f;
+ dim.x = Math::Rand()*3.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+
+ if ( m_progress < 0.5f )
+ {
+ dir.x = 0.0f;
+ dir.y = powf(m_progress/0.5f, 2.0f)*12.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*12.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ dir.x = m_progress*Math::PI;
+ dir.y = 0.0f;
+ dir.z = 0.0f;
+ SetCirVibration(dir);
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(MAS_BACK2, 55.0f+Math::Rand()*10.0f);
+ }
+ }
+ else if ( m_actionType == MAS_BACK2 ) // moves on the back?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ if ( rand()%10 == 0 )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ pos.y -= 1.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = Math::Rand()*2.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+ }
+
+ dir = Math::Vector(0.0f, -1.0f, 0.0f);
+ SetLinVibration(dir);
+ dir.x = sinf(m_armTimeAbs* 4.0f)*0.10f+
+ sinf(m_armTimeAbs* 7.0f)*0.20f+
+ sinf(m_armTimeAbs*10.0f)*0.40f+
+ sinf(m_armTimeAbs*21.0f)*0.50f+Math::PI;
+ dir.y = sinf(m_armTimeAbs* 3.0f)*0.01f+
+ sinf(m_armTimeAbs* 6.0f)*0.02f+
+ sinf(m_armTimeAbs*11.0f)*0.04f+
+ sinf(m_armTimeAbs*20.0f)*0.02f;
+ dir.z = sinf(m_armTimeAbs* 5.0f)*0.01f+
+ sinf(m_armTimeAbs* 8.0f)*0.02f+
+ sinf(m_armTimeAbs* 9.0f)*0.04f+
+ sinf(m_armTimeAbs*23.0f)*0.03f;
+ SetCirVibration(dir);
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*8.0f)*0.7f); // head
+ m_object->SetAngleY(2, cosf(m_armTimeAbs*8.0f)*0.7f); // tail
+ m_object->SetAngleZ(1, 0.0f); // head
+ m_object->SetAngleZ(2, 0.0f); // tail
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(MAS_BACK3, 0.4f);
+ }
+ }
+ else if ( m_actionType == MAS_BACK3 ) // goes back on the legs?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = Math::Rand()*5.0f;
+ dim.x = Math::Rand()*3.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+
+ if ( m_progress < 0.5f )
+ {
+ dir.x = 0.0f;
+ dir.y = powf(m_progress/0.5f, 2.0f)*5.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*5.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ dir.x = (1.0f-m_progress)*Math::PI;
+ dir.y = 0.0f;
+ dir.z = 0.0f;
+ SetCirVibration(dir);
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(-1);
+ m_object->SetFixed(false); // moving again
+ }
+ }
+ else
+ {
+ m_object->SetZoom(2, 1.0f); // tail
+ m_object->SetAngleX(2, 0.0f);
+ m_object->SetAngleY(2, 0.0f);
+
+ if ( bStop )
+ {
+ m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.7f)*0.15f); // tail
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ SetInclinaison(dir);
+ }
+ else
+ {
+ a = Math::Mod(m_armTimeMarch, 1.0f);
+ if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
+ else a = 3.0f-4.0f*a; // 1..-1
+ dir.x = sinf(a)*0.05f;
+
+ s = Math::Mod(m_armTimeMarch/2.0f, 1.0f);
+ if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
+ else s = 3.0f-4.0f*s; // 1..-1
+ dir.z = sinf(s)*0.1f;
+
+ dir.y = 0.0f;
+ SetInclinaison(dir);
+
+ m_object->SetAngleZ(2, -sinf(a)*0.3f); // tail
+
+ a = Math::Mod(m_armMember-0.1f, 1.0f);
+ if ( a < 0.33f )
+ {
+ dir.y = -(1.0f-(a/0.33f))*0.3f;
+ }
+ else if ( a < 0.67f )
+ {
+ dir.y = 0.0f;
+ }
+ else
+ {
+ dir.y = -(a-0.67f)/0.33f*0.3f;
+ }
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetCirVibration(dir);
+
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.4f)*0.20f); // head
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.9f)*0.10f); // head
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*2.1f)*0.50f); // head
+ }
+
+ return true;
+}
+
+
diff --git a/src/object/motion/motionant.h b/src/object/motion/motionant.h
index 71a11e4..8ddd789 100644
--- a/src/object/motion/motionant.h
+++ b/src/object/motion/motionant.h
@@ -1,73 +1,73 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionant.h
-
-#pragma once
-
-
-#include "object/motion/motion.h"
-
-
-
-enum MotionAntAction
-{
- MA_MARCH = 0,
- MA_STOP = 1,
- MA_SPEC = 2
-};
-
-enum MotionAntSpecialAction
-{
- MAS_PREPARE = 0,
- MAS_FIRE = 1,
- MAS_TERMINATE = 2,
- MAS_BURN = 3,
- MAS_RUIN = 4,
- MAS_BACK1 = 5,
- MAS_BACK2 = 6,
- MAS_BACK3 = 7
-};
-
-
-class CMotionAnt : public CMotion
-{
-public:
- CMotionAnt(CInstanceManager* iMan, CObject* object);
- ~CMotionAnt();
-
- void DeleteObject(bool bAll=false);
- bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- bool EventProcess(const Event &event);
-
-protected:
- void CreatePhysics();
- bool EventFrame(const Event &event);
-
-protected:
- float m_armMember;
- float m_armTimeAbs;
- float m_armTimeMarch;
- float m_armTimeAction;
- short m_armAngles[3*3*3*3*3 + 3*3*3*8];
- int m_armTimeIndex;
- int m_armPartIndex;
- int m_armMemberIndex;
- int m_armLastAction;
- bool m_bArmStop;
- float m_lastParticule;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionant.h
+
+#pragma once
+
+
+#include "object/motion/motion.h"
+
+
+
+enum MotionAntAction
+{
+ MA_MARCH = 0,
+ MA_STOP = 1,
+ MA_SPEC = 2
+};
+
+enum MotionAntSpecialAction
+{
+ MAS_PREPARE = 0,
+ MAS_FIRE = 1,
+ MAS_TERMINATE = 2,
+ MAS_BURN = 3,
+ MAS_RUIN = 4,
+ MAS_BACK1 = 5,
+ MAS_BACK2 = 6,
+ MAS_BACK3 = 7
+};
+
+
+class CMotionAnt : public CMotion
+{
+public:
+ CMotionAnt(CInstanceManager* iMan, CObject* object);
+ ~CMotionAnt();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ bool EventProcess(const Event &event);
+
+protected:
+ void CreatePhysics();
+ bool EventFrame(const Event &event);
+
+protected:
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeMarch;
+ float m_armTimeAction;
+ short m_armAngles[3*3*3*3*3 + 3*3*3*8];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ bool m_bArmStop;
+ float m_lastParticule;
+};
+
diff --git a/src/object/motion/motionbee.cpp b/src/object/motion/motionbee.cpp
index c5d9ed2..e5c6b24 100644
--- a/src/object/motion/motionbee.cpp
+++ b/src/object/motion/motionbee.cpp
@@ -1,644 +1,644 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionbee.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motionbee.h"
-
-#include "old/modfile.h"
-#include "physics/physics.h"
-
-
-
-#define ADJUST_ANGLE false // true -> adjusts the angles of the members
-const float START_TIME = 1000.0f; // beginning of the relative time
-
-
-
-// Object's constructor.
-
-CMotionBee::CMotionBee(CInstanceManager* iMan, CObject* object)
- : CMotion(iMan, object)
-{
- m_armMember = START_TIME;
- m_armTimeAbs = START_TIME;
- m_armTimeMarch = START_TIME;
- m_armTimeAction = START_TIME;
- m_armTimeIndex = 0;
- m_armPartIndex = 0;
- m_armMemberIndex = 0;
- m_armLastAction = -1;
- m_bArmStop = false;
-}
-
-// Object's destructor.
-
-CMotionBee::~CMotionBee()
-{
-}
-
-
-// Removes an object.
-
-void CMotionBee::DeleteObject(bool bAll)
-{
-}
-
-
-// Creates a vehicle traveling any lands on the ground.
-
-bool CMotionBee::Create(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 3+18+2 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- m_object->SetType(type);
-
- // Creates main base.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
-
- pModFile->ReadModel("objects\\bee1.mod");
- pModFile->CreateEngineObject(rank);
-
- m_object->SetPosition(0, pos);
- m_object->SetAngleY(0, angle);
-
- // A vehicle must have an obligatory collision
- // with a sphere of center (0, y, 0) (see GetCrashSphere).
- m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
- m_object->SetGlobalSphere(Math::Vector(-1.0f, 1.0f, 0.0f), 5.0f);
-
- // Creates the head.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\bee2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(1.6f, 0.3f, 0.0f));
-
- // Creates the tail.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\bee3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(-0.8f, 0.0f, 0.0f));
-
- // Creates a right-back thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(-0.3f, -0.1f, -0.2f));
-
- // Creates a right-back leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(4, rank);
- m_object->SetObjectParent(4, 3);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(4, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates a right-back foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(5, rank);
- m_object->SetObjectParent(5, 4);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(5, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates two middle-right thighs.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(0.3f, -0.1f, -0.4f));
-
- // Creates two middle-right legs.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 6);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates two middle-right feet.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 7);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates the right front thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(9, rank);
- m_object->SetObjectParent(9, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(9, Math::Vector(1.0f, -0.1f, -0.7f));
-
- // Creates the right front leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(10, rank);
- m_object->SetObjectParent(10, 9);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(10, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates the right front foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(11, rank);
- m_object->SetObjectParent(11, 10);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(11, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates a left-back thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(12, rank);
- m_object->SetObjectParent(12, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(12, Math::Vector(-0.3f, -0.1f, 0.2f));
- m_object->SetAngleY(12, Math::PI);
-
- // Creates a left-back leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(13, rank);
- m_object->SetObjectParent(13, 12);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(13, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates a left-back foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(14, rank);
- m_object->SetObjectParent(14, 13);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(14, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates two middle-left thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(15, rank);
- m_object->SetObjectParent(15, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(15, Math::Vector(0.3f, -0.1f, 0.4f));
- m_object->SetAngleY(15, Math::PI);
-
- // Creates two middle-left legs.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(16, rank);
- m_object->SetObjectParent(16, 15);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(16, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates two middle-left feet.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(17, rank);
- m_object->SetObjectParent(17, 16);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(17, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates front-left thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(18, rank);
- m_object->SetObjectParent(18, 0);
- pModFile->ReadModel("objects\\ant4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(18, Math::Vector(1.0f, -0.1f, 0.7f));
- m_object->SetAngleY(18, Math::PI);
-
- // Creates front-left leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(19, rank);
- m_object->SetObjectParent(19, 18);
- pModFile->ReadModel("objects\\ant5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(19, Math::Vector(0.0f, 0.0f, -1.0f));
-
- // Creates front-left foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(20, rank);
- m_object->SetObjectParent(20, 19);
- pModFile->ReadModel("objects\\ant6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(20, Math::Vector(0.0f, 0.0f, -2.0f));
-
- // Creates the right wing.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(21, rank);
- m_object->SetObjectParent(21, 0);
- pModFile->ReadModel("objects\\bee7.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(21, Math::Vector(0.8f, 0.4f, -0.5f));
-
- // Creates the left wing.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(22, rank);
- m_object->SetObjectParent(22, 0);
- pModFile->ReadModel("objects\\bee7.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(22, Math::Vector(0.8f, 0.4f, 0.5f));
-
- m_object->CreateShadowCircle(6.0f, 0.5f);
-
- CreatePhysics();
- m_object->SetFloorHeight(0.0f);
-
- pos = m_object->RetPosition(0);
- m_object->SetPosition(0, pos); // to display the shadows immediately
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-// Creates the physical object.
-
-void CMotionBee::CreatePhysics()
-{
- Character* character;
- int i;
-
- int member_march[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
- 0,45,0, 0,45,0, 0,50,0, // t0: thighs 1..3
- 30,-70,0, 20,-105,20, 25,-100,0, // t0: legs 1..3
- -70,75,0, -30,80,0, -80,80,0, // t0: feet 1..3
- // on the ground:
- 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3
- -15,-50,0, -20,-60,0, -10,-75,0, // t1: legs 1..3
- -40,50,0, -25,15,0, -50,35,0, // t1: feet 1..3
- // on the ground back:
- 0,35,0, 0,30,0, 0,20,0, // t2: thighs 1..3
- -20,-15,0, -30,-55,0, -25,-70,15, // t2: legs 1..3
- -25,25,0, -20,60,0, -30,95,0, // t2: feet 1..3
- };
-
- int member_spec[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // ball carrier:
- 0,45,0, 0,45,0, 0,50,0, // s0: thighs 1..3
- -35,-70,0, -20,-85,-25, -25,-100,0, // s0: legs 1..3
- -110,75,-15, -130,80,-25, -125,40,0, // s0: feet 1..3
- // burning:
- 0,45,0, 0,45,0, 0,50,0, // s1: thighs 1..3
- -35,-70,0, -20,-85,-25, -25,-100,0, // s1: legs 1..3
- -110,75,-15, -130,80,-25, -125,40,0, // s1: feet 1..3
- // destroyed:
- 0,45,0, 0,45,0, 0,50,0, // s2: thighs 1..3
- -35,-70,0, -20,-85,-25, -25,-100,0, // s2: legs 1..3
- -110,75,-15, -130,80,-25, -125,40,0, // s2: feet 1..3
- };
-
- m_physics->SetType(TYPE_FLYING);
-
- character = m_object->RetCharacter();
- character->wheelFront = 3.0f;
- character->wheelBack = 3.0f;
- character->wheelLeft = 5.0f;
- character->wheelRight = 5.0f;
- character->height = 2.5f;
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 50.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 10.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
- m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
- m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
- m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
- m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 20.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 40.0f);
-
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MB_MARCH+i] = member_march[i];
- }
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MB_SPEC+i] = member_spec[i];
- }
-}
-
-
-// Management of an event.
-
-bool CMotionBee::EventProcess(const Event &event)
-{
- CMotion::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
-#if ADJUST_ANGLE
- int i;
-
- if ( event.param == 'A' ) m_armTimeIndex++;
- if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
-
- if ( event.param == 'Q' ) m_armPartIndex++;
- if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
-
- if ( event.param == 'W' ) m_armMemberIndex++;
- if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
-
- i = m_armMemberIndex*3;
- i += m_armPartIndex*3*3;
- i += m_armTimeIndex*3*3*3;
-//? i += 3*3*3*3;
-
- if ( event.param == 'E' ) m_armAngles[i+0] += 5;
- if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
- if ( event.param == 'R' ) m_armAngles[i+1] += 5;
- if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
- if ( event.param == 'T' ) m_armAngles[i+2] += 5;
- if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
-
- if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
-#endif
- }
-
- return true;
-}
-
-// Management of an event.
-
-bool CMotionBee::EventFrame(const Event &event)
-{
- Math::Vector dir;
- float s, a, prog;
- int action, i, st, nd;
- bool bStop;
-
- if ( m_engine->RetPause() ) return true;
- if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
-
- s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.30f;
- a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.00f);
-
- if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
-
- m_armTimeAbs += event.rTime;
- m_armTimeMarch += (s)*event.rTime*0.15f;
- m_armMember += (s+a)*event.rTime*0.15f;
-
- bStop = ( a == 0.0f && s == 0.0f ); // stopped?
- if ( !m_physics->RetLand() ) bStop = true;
-
- if ( bStop )
- {
- prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
- a = Math::Mod(m_armMember, 1.0f);
- a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly
- m_armMember += a;
- }
-
- action = MB_MARCH; // flying
-
- m_actionType = -1;
- if ( m_object->RetFret() != 0 ) m_actionType = MBS_HOLD; // carries the ball
-
- if ( m_object->RetRuin() ) // destroyed?
- {
- m_actionType = MBS_RUIN;
- }
- if ( m_object->RetBurn() ) // burning?
- {
- m_actionType = MBS_BURN;
- }
-
- for ( i=0 ; i<6 ; i++ ) // the six legs
- {
- if ( m_actionType != -1 ) // special action in progress?
- {
- st = 3*3*3*3*MB_SPEC + 3*3*3*m_actionType + (i%3)*3;
- nd = st;
- }
- else
- {
- if ( i < 3 ) prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
- else prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
- if ( m_bArmStop )
- {
- prog = (float)m_armTimeIndex/3.0f;
- }
- if ( prog < 0.33f ) // t0..t1 ?
- {
- prog = prog/0.33f; // 0..1
- st = 0; // index start
- nd = 1; // index end
- }
- else if ( prog < 0.67f ) // t1..t2 ?
- {
- prog = (prog-0.33f)/0.33f; // 0..1
- st = 1; // index start
- nd = 2; // index end
- }
- else // t2..t0 ?
- {
- prog = (prog-0.67f)/0.33f; // 0..1
- st = 2; // index start
- nd = 0; // index end
- }
- st = 3*3*3*3*action + st*3*3*3 + (i%3)*3;
- nd = 3*3*3*3*action + nd*3*3*3 + (i%3)*3;
- }
-
- if ( i < 3 ) // right leg (1..3) ?
- {
- m_object->SetAngleX(3+3*i+0, Math::PropAngle(m_armAngles[st+ 0], m_armAngles[nd+ 0], prog));
- m_object->SetAngleY(3+3*i+0, Math::PropAngle(m_armAngles[st+ 1], m_armAngles[nd+ 1], prog));
- m_object->SetAngleZ(3+3*i+0, Math::PropAngle(m_armAngles[st+ 2], m_armAngles[nd+ 2], prog));
- m_object->SetAngleX(3+3*i+1, Math::PropAngle(m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
- m_object->SetAngleY(3+3*i+1, Math::PropAngle(m_armAngles[st+10], m_armAngles[nd+10], prog));
- m_object->SetAngleZ(3+3*i+1, Math::PropAngle(m_armAngles[st+11], m_armAngles[nd+11], prog));
- m_object->SetAngleX(3+3*i+2, Math::PropAngle(m_armAngles[st+18], m_armAngles[nd+18], prog));
- m_object->SetAngleY(3+3*i+2, Math::PropAngle(m_armAngles[st+19], m_armAngles[nd+19], prog));
- m_object->SetAngleZ(3+3*i+2, Math::PropAngle(m_armAngles[st+20], m_armAngles[nd+20], prog));
- }
- else // left leg(4..6) ?
- {
- m_object->SetAngleX(3+3*i+0, Math::PropAngle( -m_armAngles[st+ 0], -m_armAngles[nd+ 0], prog));
- m_object->SetAngleY(3+3*i+0, Math::PropAngle(180-m_armAngles[st+ 1], 180-m_armAngles[nd+ 1], prog));
- m_object->SetAngleZ(3+3*i+0, Math::PropAngle( -m_armAngles[st+ 2], -m_armAngles[nd+ 2], prog));
- m_object->SetAngleX(3+3*i+1, Math::PropAngle( m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
- m_object->SetAngleY(3+3*i+1, Math::PropAngle( -m_armAngles[st+10], -m_armAngles[nd+10], prog));
- m_object->SetAngleZ(3+3*i+1, Math::PropAngle( -m_armAngles[st+11], -m_armAngles[nd+11], prog));
- m_object->SetAngleX(3+3*i+2, Math::PropAngle( m_armAngles[st+18], m_armAngles[nd+18], prog));
- m_object->SetAngleY(3+3*i+2, Math::PropAngle( -m_armAngles[st+19], -m_armAngles[nd+19], prog));
- m_object->SetAngleZ(3+3*i+2, Math::PropAngle( -m_armAngles[st+20], -m_armAngles[nd+20], prog));
- }
- }
-
-#if ADJUST_ANGLE
- if ( m_object->RetSelect() )
- {
- char s[100];
- sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
- m_engine->SetInfoText(4, s);
- }
-#endif
-
- if ( m_physics->RetLand() ) // on the ground?
- {
- if ( m_object->RetRuin() )
- {
- }
- else if ( bStop || m_object->RetBurn() )
- {
- m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.7f)*0.15f+0.35f); // tail
- }
- else
- {
- a = Math::Mod(m_armTimeMarch, 1.0f);
- if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
- else a = 3.0f-4.0f*a; // 1..-1
- dir.x = sinf(a)*0.05f;
-
- s = Math::Mod(m_armTimeMarch/2.0f, 1.0f);
- if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
- else s = 3.0f-4.0f*s; // 1..-1
- dir.z = sinf(s)*0.1f;
-
- dir.y = 0.0f;
- m_object->SetInclinaison(dir);
-
- m_object->SetAngleZ(2, -sinf(a)*0.3f); // tail
-
- a = Math::Mod(m_armMember-0.1f, 1.0f);
- if ( a < 0.33f )
- {
- dir.y = -(1.0f-(a/0.33f))*0.3f;
- }
- else if ( a < 0.67f )
- {
- dir.y = 0.0f;
- }
- else
- {
- dir.y = -(a-0.67f)/0.33f*0.3f;
- }
- dir.x = 0.0f;
- dir.z = 0.0f;
- m_object->SetLinVibration(dir);
- }
- }
-
- if ( m_physics->RetLand() )
- {
- if ( bStop ) prog = 0.05f;
- else prog = 0.15f;
- }
- else
- {
- prog = 1.00f;
- }
-
-#if 0
- a = Math::Rand()*Math::PI/2.0f*prog;
- m_object->SetAngleX(21, a); // right wing
- a = -Math::Rand()*Math::PI/4.0f*prog;
- m_object->SetAngleY(21, a);
-
- a = -Math::Rand()*Math::PI/2.0f*prog;
- m_object->SetAngleX(22, a); // left wing
- a = Math::Rand()*Math::PI/4.0f*prog;
- m_object->SetAngleY(22, a);
-#else
- m_object->SetAngleX(21, (sinf(m_armTimeAbs*30.0f)+1.0f)*(Math::PI/4.0f)*prog);
- m_object->SetAngleY(21, -Math::Rand()*Math::PI/6.0f*prog);
-
- m_object->SetAngleX(22, -(sinf(m_armTimeAbs*30.0f)+1.0f)*(Math::PI/4.0f)*prog);
- m_object->SetAngleY(22, Math::Rand()*Math::PI/6.0f*prog);
-#endif
-
- m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.4f)*0.20f); // head
- m_object->SetAngleX(1, sinf(m_armTimeAbs*1.9f)*0.10f); // head
- m_object->SetAngleY(1, sinf(m_armTimeAbs*2.1f)*0.50f); // head
-
-#if 0
- h = m_terrain->RetFloorHeight(RetPosition(0));
- radius = 4.0f+h/4.0f;
- color.r = 0.3f+h/80.0f;
- color.g = color.r;
- color.b = color.r;
- color.a = color.r;
- m_engine->SetObjectShadowRadius(m_objectPart[0].object, radius);
- m_engine->SetObjectShadowColor(m_objectPart[0].object, color);
-#endif
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionbee.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motionbee.h"
+
+#include "old/modfile.h"
+#include "physics/physics.h"
+
+
+
+#define ADJUST_ANGLE false // true -> adjusts the angles of the members
+const float START_TIME = 1000.0f; // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionBee::CMotionBee(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeMarch = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLastAction = -1;
+ m_bArmStop = false;
+}
+
+// Object's destructor.
+
+CMotionBee::~CMotionBee()
+{
+}
+
+
+// Removes an object.
+
+void CMotionBee::DeleteObject(bool bAll)
+{
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+bool CMotionBee::Create(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 3+18+2 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+
+ pModFile->ReadModel("objects\\bee1.mod");
+ pModFile->CreateEngineObject(rank);
+
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have an obligatory collision
+ // with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
+ m_object->SetGlobalSphere(Math::Vector(-1.0f, 1.0f, 0.0f), 5.0f);
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\bee2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(1.6f, 0.3f, 0.0f));
+
+ // Creates the tail.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\bee3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(-0.8f, 0.0f, 0.0f));
+
+ // Creates a right-back thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(-0.3f, -0.1f, -0.2f));
+
+ // Creates a right-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 3);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates a right-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 4);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates two middle-right thighs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(0.3f, -0.1f, -0.4f));
+
+ // Creates two middle-right legs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 6);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates two middle-right feet.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 7);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates the right front thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, Math::Vector(1.0f, -0.1f, -0.7f));
+
+ // Creates the right front leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10, rank);
+ m_object->SetObjectParent(10, 9);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates the right front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(11, rank);
+ m_object->SetObjectParent(11, 10);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(11, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates a left-back thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(12, rank);
+ m_object->SetObjectParent(12, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(12, Math::Vector(-0.3f, -0.1f, 0.2f));
+ m_object->SetAngleY(12, Math::PI);
+
+ // Creates a left-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(13, rank);
+ m_object->SetObjectParent(13, 12);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(13, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates a left-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(14, rank);
+ m_object->SetObjectParent(14, 13);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(14, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates two middle-left thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(15, rank);
+ m_object->SetObjectParent(15, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(15, Math::Vector(0.3f, -0.1f, 0.4f));
+ m_object->SetAngleY(15, Math::PI);
+
+ // Creates two middle-left legs.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(16, rank);
+ m_object->SetObjectParent(16, 15);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(16, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates two middle-left feet.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(17, rank);
+ m_object->SetObjectParent(17, 16);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(17, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates front-left thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(18, rank);
+ m_object->SetObjectParent(18, 0);
+ pModFile->ReadModel("objects\\ant4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(18, Math::Vector(1.0f, -0.1f, 0.7f));
+ m_object->SetAngleY(18, Math::PI);
+
+ // Creates front-left leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(19, rank);
+ m_object->SetObjectParent(19, 18);
+ pModFile->ReadModel("objects\\ant5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(19, Math::Vector(0.0f, 0.0f, -1.0f));
+
+ // Creates front-left foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(20, rank);
+ m_object->SetObjectParent(20, 19);
+ pModFile->ReadModel("objects\\ant6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(20, Math::Vector(0.0f, 0.0f, -2.0f));
+
+ // Creates the right wing.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(21, rank);
+ m_object->SetObjectParent(21, 0);
+ pModFile->ReadModel("objects\\bee7.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(21, Math::Vector(0.8f, 0.4f, -0.5f));
+
+ // Creates the left wing.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(22, rank);
+ m_object->SetObjectParent(22, 0);
+ pModFile->ReadModel("objects\\bee7.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(22, Math::Vector(0.8f, 0.4f, 0.5f));
+
+ m_object->CreateShadowCircle(6.0f, 0.5f);
+
+ CreatePhysics();
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+// Creates the physical object.
+
+void CMotionBee::CreatePhysics()
+{
+ Character* character;
+ int i;
+
+ int member_march[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 0,45,0, 0,45,0, 0,50,0, // t0: thighs 1..3
+ 30,-70,0, 20,-105,20, 25,-100,0, // t0: legs 1..3
+ -70,75,0, -30,80,0, -80,80,0, // t0: feet 1..3
+ // on the ground:
+ 0,30,0, 0,20,0, 0,15,0, // t1: thighs 1..3
+ -15,-50,0, -20,-60,0, -10,-75,0, // t1: legs 1..3
+ -40,50,0, -25,15,0, -50,35,0, // t1: feet 1..3
+ // on the ground back:
+ 0,35,0, 0,30,0, 0,20,0, // t2: thighs 1..3
+ -20,-15,0, -30,-55,0, -25,-70,15, // t2: legs 1..3
+ -25,25,0, -20,60,0, -30,95,0, // t2: feet 1..3
+ };
+
+ int member_spec[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // ball carrier:
+ 0,45,0, 0,45,0, 0,50,0, // s0: thighs 1..3
+ -35,-70,0, -20,-85,-25, -25,-100,0, // s0: legs 1..3
+ -110,75,-15, -130,80,-25, -125,40,0, // s0: feet 1..3
+ // burning:
+ 0,45,0, 0,45,0, 0,50,0, // s1: thighs 1..3
+ -35,-70,0, -20,-85,-25, -25,-100,0, // s1: legs 1..3
+ -110,75,-15, -130,80,-25, -125,40,0, // s1: feet 1..3
+ // destroyed:
+ 0,45,0, 0,45,0, 0,50,0, // s2: thighs 1..3
+ -35,-70,0, -20,-85,-25, -25,-100,0, // s2: legs 1..3
+ -110,75,-15, -130,80,-25, -125,40,0, // s2: feet 1..3
+ };
+
+ m_physics->SetType(TYPE_FLYING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 3.0f;
+ character->wheelBack = 3.0f;
+ character->wheelLeft = 5.0f;
+ character->wheelRight = 5.0f;
+ character->height = 2.5f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 50.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+ m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
+ m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 40.0f);
+
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MB_MARCH+i] = member_march[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MB_SPEC+i] = member_spec[i];
+ }
+}
+
+
+// Management of an event.
+
+bool CMotionBee::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if ADJUST_ANGLE
+ int i;
+
+ if ( event.param == 'A' ) m_armTimeIndex++;
+ if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
+
+ if ( event.param == 'Q' ) m_armPartIndex++;
+ if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
+
+ if ( event.param == 'W' ) m_armMemberIndex++;
+ if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
+
+ i = m_armMemberIndex*3;
+ i += m_armPartIndex*3*3;
+ i += m_armTimeIndex*3*3*3;
+//? i += 3*3*3*3;
+
+ if ( event.param == 'E' ) m_armAngles[i+0] += 5;
+ if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
+ if ( event.param == 'R' ) m_armAngles[i+1] += 5;
+ if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
+ if ( event.param == 'T' ) m_armAngles[i+2] += 5;
+ if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
+
+ if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
+#endif
+ }
+
+ return true;
+}
+
+// Management of an event.
+
+bool CMotionBee::EventFrame(const Event &event)
+{
+ Math::Vector dir;
+ float s, a, prog;
+ int action, i, st, nd;
+ bool bStop;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.30f;
+ a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.00f);
+
+ if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armTimeMarch += (s)*event.rTime*0.15f;
+ m_armMember += (s+a)*event.rTime*0.15f;
+
+ bStop = ( a == 0.0f && s == 0.0f ); // stopped?
+ if ( !m_physics->RetLand() ) bStop = true;
+
+ if ( bStop )
+ {
+ prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
+ a = Math::Mod(m_armMember, 1.0f);
+ a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly
+ m_armMember += a;
+ }
+
+ action = MB_MARCH; // flying
+
+ m_actionType = -1;
+ if ( m_object->RetFret() != 0 ) m_actionType = MBS_HOLD; // carries the ball
+
+ if ( m_object->RetRuin() ) // destroyed?
+ {
+ m_actionType = MBS_RUIN;
+ }
+ if ( m_object->RetBurn() ) // burning?
+ {
+ m_actionType = MBS_BURN;
+ }
+
+ for ( i=0 ; i<6 ; i++ ) // the six legs
+ {
+ if ( m_actionType != -1 ) // special action in progress?
+ {
+ st = 3*3*3*3*MB_SPEC + 3*3*3*m_actionType + (i%3)*3;
+ nd = st;
+ }
+ else
+ {
+ if ( i < 3 ) prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
+ else prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
+ if ( m_bArmStop )
+ {
+ prog = (float)m_armTimeIndex/3.0f;
+ }
+ if ( prog < 0.33f ) // t0..t1 ?
+ {
+ prog = prog/0.33f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.67f ) // t1..t2 ?
+ {
+ prog = (prog-0.33f)/0.33f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.67f)/0.33f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ st = 3*3*3*3*action + st*3*3*3 + (i%3)*3;
+ nd = 3*3*3*3*action + nd*3*3*3 + (i%3)*3;
+ }
+
+ if ( i < 3 ) // right leg (1..3) ?
+ {
+ m_object->SetAngleX(3+3*i+0, Math::PropAngle(m_armAngles[st+ 0], m_armAngles[nd+ 0], prog));
+ m_object->SetAngleY(3+3*i+0, Math::PropAngle(m_armAngles[st+ 1], m_armAngles[nd+ 1], prog));
+ m_object->SetAngleZ(3+3*i+0, Math::PropAngle(m_armAngles[st+ 2], m_armAngles[nd+ 2], prog));
+ m_object->SetAngleX(3+3*i+1, Math::PropAngle(m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
+ m_object->SetAngleY(3+3*i+1, Math::PropAngle(m_armAngles[st+10], m_armAngles[nd+10], prog));
+ m_object->SetAngleZ(3+3*i+1, Math::PropAngle(m_armAngles[st+11], m_armAngles[nd+11], prog));
+ m_object->SetAngleX(3+3*i+2, Math::PropAngle(m_armAngles[st+18], m_armAngles[nd+18], prog));
+ m_object->SetAngleY(3+3*i+2, Math::PropAngle(m_armAngles[st+19], m_armAngles[nd+19], prog));
+ m_object->SetAngleZ(3+3*i+2, Math::PropAngle(m_armAngles[st+20], m_armAngles[nd+20], prog));
+ }
+ else // left leg(4..6) ?
+ {
+ m_object->SetAngleX(3+3*i+0, Math::PropAngle( -m_armAngles[st+ 0], -m_armAngles[nd+ 0], prog));
+ m_object->SetAngleY(3+3*i+0, Math::PropAngle(180-m_armAngles[st+ 1], 180-m_armAngles[nd+ 1], prog));
+ m_object->SetAngleZ(3+3*i+0, Math::PropAngle( -m_armAngles[st+ 2], -m_armAngles[nd+ 2], prog));
+ m_object->SetAngleX(3+3*i+1, Math::PropAngle( m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
+ m_object->SetAngleY(3+3*i+1, Math::PropAngle( -m_armAngles[st+10], -m_armAngles[nd+10], prog));
+ m_object->SetAngleZ(3+3*i+1, Math::PropAngle( -m_armAngles[st+11], -m_armAngles[nd+11], prog));
+ m_object->SetAngleX(3+3*i+2, Math::PropAngle( m_armAngles[st+18], m_armAngles[nd+18], prog));
+ m_object->SetAngleY(3+3*i+2, Math::PropAngle( -m_armAngles[st+19], -m_armAngles[nd+19], prog));
+ m_object->SetAngleZ(3+3*i+2, Math::PropAngle( -m_armAngles[st+20], -m_armAngles[nd+20], prog));
+ }
+ }
+
+#if ADJUST_ANGLE
+ if ( m_object->RetSelect() )
+ {
+ char s[100];
+ sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
+ m_engine->SetInfoText(4, s);
+ }
+#endif
+
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ if ( m_object->RetRuin() )
+ {
+ }
+ else if ( bStop || m_object->RetBurn() )
+ {
+ m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.7f)*0.15f+0.35f); // tail
+ }
+ else
+ {
+ a = Math::Mod(m_armTimeMarch, 1.0f);
+ if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
+ else a = 3.0f-4.0f*a; // 1..-1
+ dir.x = sinf(a)*0.05f;
+
+ s = Math::Mod(m_armTimeMarch/2.0f, 1.0f);
+ if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
+ else s = 3.0f-4.0f*s; // 1..-1
+ dir.z = sinf(s)*0.1f;
+
+ dir.y = 0.0f;
+ m_object->SetInclinaison(dir);
+
+ m_object->SetAngleZ(2, -sinf(a)*0.3f); // tail
+
+ a = Math::Mod(m_armMember-0.1f, 1.0f);
+ if ( a < 0.33f )
+ {
+ dir.y = -(1.0f-(a/0.33f))*0.3f;
+ }
+ else if ( a < 0.67f )
+ {
+ dir.y = 0.0f;
+ }
+ else
+ {
+ dir.y = -(a-0.67f)/0.33f*0.3f;
+ }
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ m_object->SetLinVibration(dir);
+ }
+ }
+
+ if ( m_physics->RetLand() )
+ {
+ if ( bStop ) prog = 0.05f;
+ else prog = 0.15f;
+ }
+ else
+ {
+ prog = 1.00f;
+ }
+
+#if 0
+ a = Math::Rand()*Math::PI/2.0f*prog;
+ m_object->SetAngleX(21, a); // right wing
+ a = -Math::Rand()*Math::PI/4.0f*prog;
+ m_object->SetAngleY(21, a);
+
+ a = -Math::Rand()*Math::PI/2.0f*prog;
+ m_object->SetAngleX(22, a); // left wing
+ a = Math::Rand()*Math::PI/4.0f*prog;
+ m_object->SetAngleY(22, a);
+#else
+ m_object->SetAngleX(21, (sinf(m_armTimeAbs*30.0f)+1.0f)*(Math::PI/4.0f)*prog);
+ m_object->SetAngleY(21, -Math::Rand()*Math::PI/6.0f*prog);
+
+ m_object->SetAngleX(22, -(sinf(m_armTimeAbs*30.0f)+1.0f)*(Math::PI/4.0f)*prog);
+ m_object->SetAngleY(22, Math::Rand()*Math::PI/6.0f*prog);
+#endif
+
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.4f)*0.20f); // head
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.9f)*0.10f); // head
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*2.1f)*0.50f); // head
+
+#if 0
+ h = m_terrain->RetFloorHeight(RetPosition(0));
+ radius = 4.0f+h/4.0f;
+ color.r = 0.3f+h/80.0f;
+ color.g = color.r;
+ color.b = color.r;
+ color.a = color.r;
+ m_engine->SetObjectShadowRadius(m_objectPart[0].object, radius);
+ m_engine->SetObjectShadowColor(m_objectPart[0].object, color);
+#endif
+
+ return true;
+}
+
+
diff --git a/src/object/motion/motionbee.h b/src/object/motion/motionbee.h
index 94ac7fa..aa8e5a6 100644
--- a/src/object/motion/motionbee.h
+++ b/src/object/motion/motionbee.h
@@ -1,66 +1,66 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionbee.h
-
-#pragma once
-
-
-#include "object/motion/motion.h"
-
-
-
-enum MotionBeeAction
-{
- MB_MARCH = 0,
- MB_SPEC = 1
-};
-
-enum MotionBeeSpecialAction
-{
- MBS_HOLD = 0,
- MBS_BURN = 1,
- MBS_RUIN = 2
-};
-
-
-class CMotionBee : public CMotion
-{
-public:
- CMotionBee(CInstanceManager* iMan, CObject* object);
- ~CMotionBee();
-
- void DeleteObject(bool bAll=false);
- bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- bool EventProcess(const Event &event);
-
-protected:
- void CreatePhysics();
- bool EventFrame(const Event &event);
-
-protected:
- float m_armMember;
- float m_armTimeAbs;
- float m_armTimeMarch;
- float m_armTimeAction;
- short m_armAngles[3*3*3*3*2];
- int m_armTimeIndex;
- int m_armPartIndex;
- int m_armMemberIndex;
- int m_armLastAction;
- bool m_bArmStop;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionbee.h
+
+#pragma once
+
+
+#include "object/motion/motion.h"
+
+
+
+enum MotionBeeAction
+{
+ MB_MARCH = 0,
+ MB_SPEC = 1
+};
+
+enum MotionBeeSpecialAction
+{
+ MBS_HOLD = 0,
+ MBS_BURN = 1,
+ MBS_RUIN = 2
+};
+
+
+class CMotionBee : public CMotion
+{
+public:
+ CMotionBee(CInstanceManager* iMan, CObject* object);
+ ~CMotionBee();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ bool EventProcess(const Event &event);
+
+protected:
+ void CreatePhysics();
+ bool EventFrame(const Event &event);
+
+protected:
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeMarch;
+ float m_armTimeAction;
+ short m_armAngles[3*3*3*3*2];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ bool m_bArmStop;
+};
+
diff --git a/src/object/motion/motionhuman.cpp b/src/object/motion/motionhuman.cpp
index 6bdcf7e..06db454 100644
--- a/src/object/motion/motionhuman.cpp
+++ b/src/object/motion/motionhuman.cpp
@@ -1,1770 +1,1770 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionhuman.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motionhuman.h"
-
-#include "old/modfile.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "math/geometry.h"
-#include "object/robotmain.h"
-#include "physics/physics.h"
-
-
-
-#define ADJUST_ANGLE false // true -> adjusts the angles of the members
-const int ADJUST_ACTION = (3*3*3*3*MH_SPEC+3*3*3*MHS_SATCOM);
-
-const float START_TIME = 1000.0f; // beginning of the relative time
-
-
-
-// Object's constructor.
-
-CMotionHuman::CMotionHuman(CInstanceManager* iMan, CObject* object)
- : CMotion(iMan, object)
-{
- m_partiReactor = -1;
- m_armMember = START_TIME;
- m_armTimeAbs = START_TIME;
- m_armTimeAction = START_TIME;
- m_armTimeSwim = START_TIME;
- m_armTimeIndex = 0;
- m_armPartIndex = 0;
- m_armMemberIndex = 0;
- m_armLastAction = -1;
- m_bArmStop = false;
- m_lastSoundMarch = 0.0f;
- m_lastSoundHhh = 0.0f;
- m_time = 0.0f;
- m_tired = 0.0f;
- m_bDisplayPerso = false;
-}
-
-// Object's constructor.
-
-CMotionHuman::~CMotionHuman()
-{
-}
-
-
-// Removes an object.
-
-void CMotionHuman::DeleteObject(bool bAll)
-{
- if ( m_partiReactor != -1 )
- {
- m_particule->DeleteParticule(m_partiReactor);
- m_partiReactor = -1;
- }
-}
-
-
-// Starts an action.
-
-Error CMotionHuman::SetAction(int action, float time)
-{
- CMotion::SetAction(action, time);
- m_time = 0.0f;
- return ERR_OK;
-}
-
-
-// Creates cosmonaut on the ground.
-
-bool CMotionHuman::Create(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- char filename[100];
- int rank, option, face, glasses;
-
- if ( m_engine->RetRestCreate() < 16 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- m_object->SetType(type);
- option = m_object->RetOption();
-
- if ( m_main->RetGamerOnlyHead() )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
- face = m_main->RetGamerFace();
- sprintf(filename, "objects\\human2h%d.mod", face+1);
- pModFile->ReadModel(filename);
- pModFile->CreateEngineObject(rank);
-
- glasses = m_main->RetGamerGlasses();
- if ( glasses != 0 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- sprintf(filename, "objects\\human2g%d.mod", glasses);
- pModFile->ReadModel(filename);
- pModFile->CreateEngineObject(rank);
- }
-
- CreatePhysics(type);
- m_object->SetFloorHeight(0.0f);
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
- }
-
- // Creates the main base.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
-
- if ( option == 0 ) // head in helmet?
- {
- pModFile->ReadModel("objects\\human1c.mod");
- }
- if ( option == 1 ) // head without helmet?
- {
- pModFile->ReadModel("objects\\human1h.mod");
- }
- if ( option == 2 ) // without a backpack?
- {
- pModFile->ReadModel("objects\\human1v.mod");
- }
- pModFile->CreateEngineObject(rank);
-
- m_object->SetPosition(0, pos);
- m_object->SetAngleY(0, angle);
-
- // A vehicle must have an obligatory collision with a sphere of center (0, y, 0) (see GetCrashSphere).
- m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 2.0f, SOUND_AIE, 0.20f);
- m_object->SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 4.0f);
-
- // Creates the head.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
-
- if ( type == OBJECT_HUMAN )
- {
- if ( option == 0 ) // head in helmet?
- {
- face = m_main->RetGamerFace();
- sprintf(filename, "objects\\human2c%d.mod", face+1);
- pModFile->ReadModel(filename);
- }
- if ( option == 1 || // head without helmet?
- option == 2 ) // without a backpack?
- {
- face = m_main->RetGamerFace();
- sprintf(filename, "objects\\human2h%d.mod", face+1);
- pModFile->ReadModel(filename);
- }
- }
- if ( type == OBJECT_TECH )
- {
- pModFile->ReadModel("objects\\human2t.mod");
- }
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(0.0f, 2.7f, 0.0f));
- if ( option == 1 || // head without helmet?
- option == 2 ) // without a backpack?
- {
- m_object->SetZoom(1, Math::Vector(1.0f, 1.05f, 1.0f));
- }
-
- // Creates the glasses.
- glasses = m_main->RetGamerGlasses();
- if ( glasses != 0 && type == OBJECT_HUMAN )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(15, rank);
- m_object->SetObjectParent(15, 1);
- sprintf(filename, "objects\\human2g%d.mod", glasses);
- pModFile->ReadModel(filename);
- pModFile->CreateEngineObject(rank);
- }
-
- // Creates the right arm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\human3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(0.0f, 2.3f, -1.2f));
- m_object->SetAngle(2, Math::Vector(90.0f*Math::PI/180.0f, 90.0f*Math::PI/180.0f, -50.0f*Math::PI/180.0f));
-
- // Creates the right forearm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\human4r.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(1.3f, 0.0f, 0.0f));
- m_object->SetAngle(3, Math::Vector(0.0f*Math::PI/180.0f, -20.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f));
-
- // Creates right hand.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(4, rank);
- m_object->SetObjectParent(4, 3);
- pModFile->ReadModel("objects\\human5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(4, Math::Vector(1.2f, 0.0f, 0.0f));
-
- // Creates the right thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(5, rank);
- m_object->SetObjectParent(5, 0);
- pModFile->ReadModel("objects\\human6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(5, Math::Vector(0.0f, 0.0f, -0.7f));
- m_object->SetAngle(5, Math::Vector(10.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f));
-
- // Creates the right leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 5);
- pModFile->ReadModel("objects\\human7.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(0.0f, -1.5f, 0.0f));
- m_object->SetAngle(6, Math::Vector(0.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f, -10.0f*Math::PI/180.0f));
-
- // Creates the right foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 6);
- pModFile->ReadModel("objects\\human8.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, -1.5f, 0.0f));
- m_object->SetAngle(7, Math::Vector(-10.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f));
-
- // Creates the left arm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 0);
- pModFile->ReadModel("objects\\human3.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(0.0f, 2.3f, 1.2f));
- m_object->SetAngle(8, Math::Vector(-90.0f*Math::PI/180.0f, -90.0f*Math::PI/180.0f, -50.0f*Math::PI/180.0f));
-
- // Creates the left forearm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(9, rank);
- m_object->SetObjectParent(9, 8);
- pModFile->ReadModel("objects\\human4l.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(9, Math::Vector(1.3f, 0.0f, 0.0f));
- m_object->SetAngle(9, Math::Vector(0.0f*Math::PI/180.0f, 20.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f));
-
- // Creates left hand.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(10, rank);
- m_object->SetObjectParent(10, 9);
- pModFile->ReadModel("objects\\human5.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(10, Math::Vector(1.2f, 0.0f, 0.0f));
-
- // Creates the left thigh.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(11, rank);
- m_object->SetObjectParent(11, 0);
- pModFile->ReadModel("objects\\human6.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(11, Math::Vector(0.0f, 0.0f, 0.7f));
- m_object->SetAngle(11, Math::Vector(-10.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f));
-
- // Creates the left leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(12, rank);
- m_object->SetObjectParent(12, 11);
- pModFile->ReadModel("objects\\human7.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(12, Math::Vector(0.0f, -1.5f, 0.0f));
- m_object->SetAngle(12, Math::Vector(0.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f, -10.0f*Math::PI/180.0f));
-
- // Creates the left foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(13, rank);
- m_object->SetObjectParent(13, 12);
- pModFile->ReadModel("objects\\human8.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(13, Math::Vector(0.0f, -1.5f, 0.0f));
- m_object->SetAngle(13, Math::Vector(10.0f*Math::PI/180.0f, -5.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f));
-
- // Creates the neutron gun.
- if ( option != 2 ) // with backpack?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(14, rank);
- m_object->SetObjectParent(14, 0);
- pModFile->ReadModel("objects\\human9.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(14, Math::Vector(-1.5f, 0.3f, -1.35f));
- m_object->SetAngleZ(14, Math::PI);
- }
-
- m_object->CreateShadowCircle(2.0f, 0.8f);
-
- CreatePhysics(type);
- m_object->SetFloorHeight(0.0f);
-
- pos = m_object->RetPosition(0);
- m_object->SetPosition(0, pos); // to display the shadows immediately
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-// Creates the physical object.
-
-void CMotionHuman::CreatePhysics(ObjectType type)
-{
- Character* character;
- int i;
-
- int member_march[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
- 90,90,-50, 10,0,55, 0,0,0, // t0: arms/thighs/-
- 0,-20,0, -5,0,-110, 0,0,0, // t0: forearm/legs/-
- 0,0,0, -5,0,40, 0,0,0, // t0: hands/feet/-
- // on the ground:
- 125,115,-45, 10,0,50, 0,0,0, // t1: arms/thighs/-
- 0,-20,0, -5,0,-15, 0,0,0, // t1: forearm/legs/-
- 0,0,0, -5,0,0, 0,0,0, // t1: hands/feet/-
- // on the ground back:
- 25,55,-40, 10,0,-15, 0,0,0, // t2: arms/thighs/-
- 30,-50,40, -5,0,-55, 0,0,0, // t2: forearm/legs/-
- 0,0,0, -5,0,25, 0,0,0, // t2: hands/feet/-
- };
-
- int member_march_take[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
- 15,50,-50, 10,0,55, 0,0,0, // t0: arms/thighs/-
- 45,-70,10, -5,0,-110, 0,0,0, // t0: forearm/legs/-
- -10,25,0, -5,0,40, 0,0,0, // t0: hands/feet/-
- // on the ground:
- 15,50,-55, 10,0,50, 0,0,0, // t1: arms/thighs/-
- 45,-70,10, -5,0,-15, 0,0,0, // t1: forearm/legs/-
- -10,25,0, -5,0,0, 0,0,0, // t1: hands/feet/-
- // on the ground back:
- 15,50,-45, 10,0,-15, 0,0,0, // t2: arms/thighs/-
- 45,-70,10, -5,0,-55, 0,0,0, // t2: forearm/legs/-
- -10,25,0, -5,0,45, 0,0,0, // t2: hands/feet/-
- };
-
- int member_turn[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
- 90,90,-50, 10,0,30, 0,0,0, // t0: arms/thighs/-
- 0,-20,0, -5,0,-60, 0,0,0, // t0: forearm/legs/-
- 0,0,0, -5,0,30, 0,0,0, // t0: hands/feet/-
- // on the ground:
- 90,110,-45, 10,0,0, 0,0,0, // t1: arms/thighs/-
- 0,-20,0, -5,5,0, 0,0,0, // t1: forearm/legs/-
- 0,0,0, -5,10,0, 0,0,0, // t1: hands/feet/-
- // on the ground back:
- 90,70,-45, 10,0,0, 0,0,0, // t2: arms/thighs/-
- 0,-20,10, -5,-5,0, 0,0,0, // t2: forearm/legs/-
- 0,0,0, -5,-10,0, 0,0,0, // t2: hands/feet/-
- };
-
- int member_stop[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3,
- 90,90,-50, 10,0,5, 0,0,0, // arms/thighs/-
- 0,-20,0, 0,0,-10, 0,0,0, // forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // hands/feet/-
- //
- 90,90,-55, 10,0,5, 0,0,0, // arms/thighs/-
- 0,-15,0, 0,0,-10, 0,0,0, // forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // hands/feet/-
- //
- 90,90,-60, 10,0,5, 0,0,0, // arms/thighs/-
- 0,-10,0, 0,0,-10, 0,0,0, // forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // hands/feet/-
- };
-
- int member_fly[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3,
- -5,90,-60, 20,5,-25, 0,0,0, // arms/thighs/-
- 85,-40,-25, 10,0,-30, 0,0,0, // forearm/legs/-
- 40,10,25, 0,15,0, 0,0,0, // hands/feet/-
- //
- -15,90,-40, 20,5,-35, 0,0,0, // arms/thighs/-
- 85,-40,-25, 10,0,-40, 0,0,0, // forearm/legs/-
- 45,5,20, 0,15,0, 0,0,0, // hands/feet/-
- //
- -25,90,-50, 20,5,-20, 0,0,0, // arms/thighs/-
- 85,-40,-25, 10,0,-10, 0,0,0, // forearm/legs/-
- 30,15,25, 0,15,0, 0,0,0, // hands/feet/-
- };
-
- int member_swim[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3,
-#if 1
- 130,-70,200, 10,20,55, 0,0,0, // arms/thighs/-
- 115,-125,0, -5,0,-110, 0,0,0, // forearm/legs/-
- 0,0,0, -5,10,-5, 0,0,0, // hands/feet/-
- //
- 130,-95,115,55,5,5, 0,0,0, // arms/thighs/-
- 75,-50,25, -5,0,-15, 0,0,0, // forearm/legs/-
- 0,0,0, -5,5,-30, 0,0,0, // hands/feet/-
- //
- 130,-100,220,5,0,0, 0,0,0, // arms/thighs/-
- 150,5,0, -5,0,-15, 0,0,0, // forearm/legs/-
- 0,0,0, -5,30,-20, 0,0,0, // hands/feet/-
-#endif
-#if 0
- 130,-70,200,5,0,0, 0,0,0, // arms/thighs/-
- 115,-125,0, -5,0,-15, 0,0,0, // forearm/legs/-
- 0,0,0, -5,30,-20, 0,0,0, // hands/feet/-
- //
- 130,-95,115, 10,20,55, 0,0,0, // arms/thighs/-
- 75,-50,25, -5,0,-110, 0,0,0, // forearm/legs/-
- 0,0,0, -5,10,-5, 0,0,0, // hands/feet/-
- //
- 130,-100,220, 55,5,5, 0,0,0, // arms/thighs/-
- 150,5,0, -5,0,-15, 0,0,0, // forearm/legs/-
- 0,0,0, -5,5,-30, 0,0,0, // hands/feet/-
-#endif
-#if 0
- 130,-70,200, 55,5,5, 0,0,0, // arms/thighs/-
- 115,-125,0, -5,0,-15, 0,0,0, // forearm/legs/-
- 0,0,0, -5,5,-30, 0,0,0, // hands/feet/-
- //
- 130,-95,115, 5,0,0, 0,0,0, // arms/thighs/-
- 75,-50,25, -5,0,-15, 0,0,0, // forearm/legs/-
- 0,0,0, -5,30,-20, 0,0,0, // hands/feet/-
- //
- 130,-100,220, 10,20,55, 0,0,0, // arms/thighs/-
- 150,5,0, -5,0,-110, 0,0,0, // forearm/legs/-
- 0,0,0, -5,10,-5, 0,0,0, // hands/feet/-
-#endif
- };
-
- int member_spec[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // shooting:
- 65,5,-20, 10,0,40, 0,0,0, // s0: arms/thighs/-
- -50,-30,50, 0,0,-70, 0,0,0, // s0: forearm/legs/-
- 0,50,0, -10,0,35, 0,0,0, // s0: hands/feet/-
- // takes weapon:
- 160,135,-20,10,0,5, 0,0,0, // s1: arms/thighs/-
- 10,-60,40, 0,0,-10, 0,0,0, // s1: forearm/legs/-
- 0,-5,-25, -10,5,5, 0,0,0, // s1: hands/feet/-
- // carries earth:
- 25,40,-40, 10,0,60, 0,0,0, // s2: arms/thighs/-
- 0,-45,0, 0,0,-120, 0,0,0, // s2: forearm/legs/-
- 0,15,5, -10,0,70, 0,0,0, // s2: hands/feet/-
- // carries in front:
- 25,20,5, 10,0,55, 0,0,0, // s3: arms/thighs/-
- -15,-30,10, 0,0,-110, 0,0,0, // s3: forearm/legs/-
- 0,0,0, -10,0,65, 0,0,0, // s3: hands/feet/-
- // carries vertically:
- -30,15,-5, 10,0,15, 0,0,0, // s4: arms/thighs/-
- 0,-15,15, 0,0,-30, 0,0,0, // s4: forearm/legs/-
- 35,0,-15, -10,0,25, 0,0,0, // s4: hands/feet/-
- // rises:
- 15,50,-50, 10,0,5, 0,0,0, // s5: arms/thighs/-
- 45,-70,10, 0,0,-10, 0,0,0, // s5: forearm/legs/-
- -10,25,0, -10,5,5, 0,0,0, // s5: hands/feet/-
- // wins:
- 90,90,-30, 20,0,5, 0,0,0, // s6: arms/thighs/-
- 0,-90,0, -10,0,-10, 0,0,0, // s6: forearm/legs/-
- 0,25,0, -10,5,5, 0,0,0, // s6: hands/feet/-
- // lose:
- -70,45,35, 10,0,40, 0,0,0, // s7: arms/thighs/-
- 15,-95,-5, 0,0,-70, 0,0,0, // s7: forearm/legs/-
- 0,0,0, -10,0,35, 0,0,0, // s7: hands/feet/-
- // shooting death (falls):
- 90,90,-50, 10,0,5, 0,0,0, // s8: arms/thighs/-
- 0,-20,0, 0,0,-10, 0,0,0, // s8: forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // s8: hands/feet/-
- // shooting death (knees):
- 110,105,-5, 10,0,25, 0,0,0, // s9: arms/thighs/-
- 0,-40,20, 0,0,-120, 0,0,0, // s9: forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // s9: hands/feet/-
- // shooting death (knees):
- 110,120,-25, 10,0,25, 0,0,0, // s10: arms/thighs/-
- 0,-40,20, 0,0,-120, 0,0,0, // s10: forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // s10: hands/feet/-
- // shooting death (face down):
- 110,100,-25, 25,0,10, 0,0,0, // s11: arms/thighs/-
- 0,-40,20, 0,0,-25, 0,0,0, // s11: forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // s11: hands/feet/-
- // shooting death (face down):
- 110,100,-25, 25,0,10, 0,0,0, // s12: arms/thighs/-
- 0,-40,20, 0,0,-25, 0,0,0, // s12: forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // s12: hands/feet/-
- // drowned:
- 110,100,-25, 25,0,10, 0,0,0, // s13: arms/thighs/-
- 0,-40,20, 0,0,-25, 0,0,0, // s13: forearm/legs/-
- 0,0,0, -10,5,5, 0,0,0, // s13: hands/feet/-
- // puts / removes flag:
- 85,45,-50, 10,0,60, 0,0,0, // s14: arms/thighs/-
- -60,15,65, 0,0,-105, 0,0,0, // s14: forearm/legs/-
- 0,10,0, -10,0,60, 0,0,0, // s14: hands/feet/-
- // reads SatCom:
- 70,30,-20, 10,0,5, 0,0,0, // s15: arms/thighs/-
- 115,-65,60, 0,0,-10, 0,0,0, // s15: forearm/legs/-
- 0,20,0, -10,5,5, 0,0,0, // s15: hands/feet/-
- };
-
- m_physics->SetType(TYPE_FLYING);
-
- character = m_object->RetCharacter();
- character->wheelFront = 4.0f;
- character->wheelBack = 4.0f;
- character->wheelLeft = 4.0f;
- character->wheelRight = 4.0f;
- character->height = 3.5f;
-
- if ( type == OBJECT_HUMAN )
- {
- m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 35.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 70.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 40.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
- m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
- m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
- m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
- m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 6.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 6.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 4.0f);
- }
- else
- {
- m_physics->SetLinMotionX(MO_ADVSPEED, 40.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 15.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 8.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 8.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 8.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 50.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
- m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
- m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
- m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
- m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.6f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.6f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 4.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 4.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 3.0f);
- }
-
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MH_MARCH+i] = member_march[i];
- }
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MH_MARCHTAKE+i] = member_march_take[i];
- }
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MH_TURN+i] = member_turn[i];
- }
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MH_STOP+i] = member_stop[i];
- }
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MH_FLY+i] = member_fly[i];
- }
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[3*3*3*3*MH_SWIM+i] = member_swim[i];
- }
- for ( i=0 ; i<3*3*3*16 ; i++ )
- {
- m_armAngles[3*3*3*3*MH_SPEC+i] = member_spec[i];
- }
-}
-
-
-// Management of an event.
-
-bool CMotionHuman::EventProcess(const Event &event)
-{
- CMotion::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
-#if ADJUST_ANGLE
- int i;
-
- if ( event.param == 'A' ) m_armTimeIndex++;
- if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
-
- if ( event.param == 'Q' ) m_armPartIndex++;
- if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
-
- if ( event.param == 'W' ) m_armMemberIndex++;
- if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
-
- i = m_armMemberIndex*3;
- i += m_armPartIndex*3*3;
- i += m_armTimeIndex*3*3*3;
- i += ADJUST_ACTION;
-
- if ( event.param == 'E' ) m_armAngles[i+0] += 5;
- if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
- if ( event.param == 'R' ) m_armAngles[i+1] += 5;
- if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
- if ( event.param == 'T' ) m_armAngles[i+2] += 5;
- if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
-
- if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
-
- if ( event.param == 'Y' )
- {
- char s[100];
- sprintf(s, "index dans table = %d %d %d\n", i, i+9, i+18);
- OutputDebugString(s);
- }
-#endif
- }
-
- return true;
-}
-
-// Management of an event.
-
-bool CMotionHuman::EventFrame(const Event &event)
-{
- Math::Matrix* mat;
- Math::Vector dir, actual, pos, speed, pf;
- Math::Point center, dim, p2;
- float s, a, prog, rTime[2], lTime[2], time, rot, hr, hl;
- float al, ar, af;
- float tSt[9], tNd[9];
- float aa, bb, shield, deadFactor, level;
- int i, ii, st, nd, action, legAction, armAction;
- bool bOnBoard, bSwim, bStop;
-
- if ( m_engine->RetPause() )
- {
- if ( m_actionType == MHS_SATCOM )
- {
- m_progress += event.rTime*m_actionTime;
- }
- else
- {
- return true;
- }
- }
-
- bOnBoard = false;
- if ( m_object->RetSelect() &&
- m_camera->RetType() == CAMERA_ONBOARD )
- {
- bOnBoard = true;
- }
-
- if ( m_bDisplayPerso && m_main->RetGamerOnlyHead() )
- {
- m_time += event.rTime;
- m_object->SetLinVibration(Math::Vector(0.0f, -0.55f, 0.0f));
- m_object->SetCirVibration(Math::Vector(0.0f, m_main->RetPersoAngle(), 0.0f));
- return true;
- }
- if ( m_bDisplayPerso )
- {
- m_object->SetCirVibration(Math::Vector(0.0f, m_main->RetPersoAngle()+0.2f, 0.0f));
- }
-
- shield = m_object->RetShield();
- shield += event.rTime*(1.0f/120.0f); // regeneration in 120 seconds
- if ( shield > 1.0f ) shield = 1.0f;
- m_object->SetShield(shield);
-
- bSwim = m_physics->RetSwim();
-
-#if 0
- rot = m_physics->RetCirMotionY(MO_MOTSPEED);
- s = m_physics->RetLinMotionX(MO_REASPEED)*2.0f;
- a = m_physics->RetLinMotionX(MO_TERSPEED);
- if ( a < 0.0f ) // rises?
- {
- if ( s > 0.0f && s < 20.0f ) s = 20.0f; // moving slowly?
-//? if ( s < 0.0f && s > -10.0f ) s = 0.0f; // falling slowly?
- }
- if ( a > 0.0f && !bSwim ) // falls?
- {
- if ( s > 0.0f && s < 10.0f ) s = 0.0f; // moving slowly?
-//? if ( s < 0.0f && s > -5.0f ) s = -5.0f; // falling slowly?
- }
- a = fabs(rot*12.0f);
-
- if ( !m_physics->RetLand() && !bSwim ) // in flight?
- {
- s = 0.0f;
- }
-
- if ( m_object->RetFret() != 0 ) // carries something?
- {
- s *= 1.3f;
- }
-#else
- rot = m_physics->RetCirMotionY(MO_MOTSPEED);
-#if 0
- s = m_physics->RetLinMotionX(MO_REASPEED);
-#else
- a = m_physics->RetLinMotionX(MO_REASPEED);
- s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.2f;
- if ( fabs(a) > fabs(s) ) s = a; // the highest value
-#endif
- a = m_physics->RetLinMotionX(MO_TERSPEED);
- if ( a < 0.0f ) // rises?
- {
- a += m_physics->RetLinMotionX(MO_TERSLIDE);
- if ( a < 0.0f ) s -= a;
- }
- if ( a > 0.0f ) // falls?
- {
- a -= m_physics->RetLinMotionX(MO_TERSLIDE);
- if ( a > 0.0f ) s -= a;
- }
- s *= 2.0f;
- a = fabs(rot*12.0f);
-
- if ( !m_physics->RetLand() && !bSwim ) // in flight?
- {
- s = 0.0f;
- }
-
- if ( m_object->RetFret() != 0 ) // carries something?
- {
- s *= 1.3f;
- }
-#endif
-
- m_time += event.rTime;
- m_armTimeAbs += event.rTime;
- m_armTimeAction += event.rTime;
- m_armMember += s*event.rTime*0.05f;
-
- // Fatigue management when short.
- if ( m_physics->RetLand() && s != 0.0f ) // on the ground?
- {
- m_tired += event.rTime*0.1f;
- if ( m_tired > 1.0f )
- {
- m_tired = 1.0f;
- if ( m_lastSoundHhh > 3.0f ) m_lastSoundHhh = 0.5f;
- }
- }
- else
- {
- m_tired -= event.rTime*0.2f;
- if ( m_tired < 0.0f ) m_tired = 0.0f;
- }
-
- if ( bSwim ) // swims?
- {
- s += fabs(m_physics->RetLinMotionY(MO_REASPEED)*2.0f);
- a *= 2.0f;
- m_armTimeSwim += Math::Min(Math::Max(s,a,3.0f),15.0f)*event.rTime*0.05f;
- }
-
- bStop = ( s == 0.0f ); // stop?
- prog = 0.0f;
-
- if ( m_physics->RetLand() ) // on the ground?
- {
- if ( s == 0.0f && a == 0.0f )
- {
- action = MH_STOP; // stop
- rTime[0] = rTime[1] = m_armTimeAbs*0.21f;
- lTime[0] = lTime[1] = m_armTimeAbs*0.25f;
- m_armMember = START_TIME;
- }
- else
- {
- if ( s == 0.0f )
- {
- action = MH_TURN; // turn
- rTime[0] = rTime[1] = m_armTimeAbs;
- lTime[0] = lTime[1] = m_armTimeAbs+0.5f;
- if ( rot < 0.0f )
- {
- rTime[1] = 1000000.0f-rTime[1];
- }
- else
- {
- lTime[1] = 1000000.0f-lTime[1];
- }
- m_armMember = START_TIME;
- }
- else
- {
- action = MH_MARCH; // walking
- if ( m_object->RetFret() != 0 ) action = MH_MARCHTAKE; // take walking
- rTime[0] = rTime[1] = m_armMember;
- lTime[0] = lTime[1] = m_armMember+0.5f;
- }
- }
- if ( bSwim )
- {
- rTime[0] *= 0.6f;
- rTime[1] *= 0.6f;
- lTime[0] = rTime[0]+0.5f;
- lTime[1] = rTime[1]+0.5f;
- }
- }
- else
- {
- if ( bSwim )
- {
- action = MH_SWIM; // swim
- rTime[0] = rTime[1] = m_armTimeSwim;
- lTime[0] = lTime[1] = m_armTimeSwim;
- }
- else
- {
- action = MH_FLY; // fly
- rTime[0] = rTime[1] = m_armTimeAbs*0.30f;
- lTime[0] = lTime[1] = m_armTimeAbs*0.31f;
- m_armMember = START_TIME;
- }
- }
-
- if ( action != m_armLastAction )
- {
- m_armLastAction = action;
- m_armTimeAction = 0.0f;
- }
-
- armAction = action;
- legAction = action;
-
- if ( m_object->RetFret() != 0 ) // carries something?
- {
- armAction = MH_MARCHTAKE; // take walking
- }
-
- if ( m_physics->RetLand() ) // on the ground?
- {
- a = m_object->RetAngleY(0);
- pos = m_object->RetPosition(0);
- m_terrain->MoveOnFloor(pos);
-
- pf.x = pos.x+cosf(a+Math::PI*1.5f)*0.7f;
- pf.y = pos.y;
- pf.z = pos.z-sinf(a+Math::PI*1.5f)*0.7f;
- m_terrain->MoveOnFloor(pf);
- al = atanf((pf.y-pos.y)/0.7f); // angle for left leg
-
- pf = pos;
- pf.x = pos.x+cosf(a+Math::PI*0.5f)*0.7f;
- pf.y = pos.y;
- pf.z = pos.z-sinf(a+Math::PI*0.5f)*0.7f;
- m_terrain->MoveOnFloor(pf);
- ar = atanf((pf.y-pos.y)/0.7f); // angle to right leg
-
- pf.x = pos.x+cosf(a+Math::PI)*0.3f;
- pf.y = pos.y;
- pf.z = pos.z-sinf(a+Math::PI)*0.3f;
- m_terrain->MoveOnFloor(pf);
- af = atanf((pf.y-pos.y)/0.3f); // angle for feet
- }
- else
- {
- al = 0.0f;
- ar = 0.0f;
- af = 0.0f;
- }
-
- for ( i=0 ; i<4 ; i++ ) // 4 members
- {
- if ( m_bArmStop ) // focus?
- {
- st = ADJUST_ACTION + (i%2)*3;
- nd = st;
- time = 100.0f;
- m_armTimeAction = 0.0f;
- }
- else if ( m_actionType != -1 ) // special action in progress?
- {
- st = 3*3*3*3*MH_SPEC + 3*3*3*m_actionType + (i%2)*3;
- nd = st;
- time = event.rTime*m_actionTime;
- m_armTimeAction = 0.0f;
- }
- else
- {
- if ( i < 2 ) prog = Math::Mod(rTime[i%2], 1.0f);
- else prog = Math::Mod(lTime[i%2], 1.0f);
- if ( prog < 0.25f ) // t0..t1 ?
- {
- prog = prog/0.25f; // 0..1
- st = 0; // index start
- nd = 1; // index end
- }
- else if ( prog < 0.75f ) // t1..t2 ?
- {
- prog = (prog-0.25f)/0.50f; // 0..1
- st = 1; // index start
- nd = 2; // index end
- }
- else // t2..t0 ?
- {
- prog = (prog-0.75f)/0.25f; // 0..1
- st = 2; // index start
- nd = 0; // index end
- }
- if ( i%2 == 0 ) // arm?
- {
- st = 3*3*3*3*armAction + st*3*3*3 + (i%2)*3;
- nd = 3*3*3*3*armAction + nd*3*3*3 + (i%2)*3;
- }
- else // leg?
- {
- st = 3*3*3*3*legAction + st*3*3*3 + (i%2)*3;
- nd = 3*3*3*3*legAction + nd*3*3*3 + (i%2)*3;
- }
-
- // Less soft ...
- time = event.rTime*(5.0f+Math::Min(m_armTimeAction*50.0f, 100.0f));
- if ( bSwim ) time *= 0.25f;
- }
-
- tSt[0] = m_armAngles[st+ 0]; // x
- tSt[1] = m_armAngles[st+ 1]; // y
- tSt[2] = m_armAngles[st+ 2]; // z
- tSt[3] = m_armAngles[st+ 9]; // x
- tSt[4] = m_armAngles[st+10]; // y
- tSt[5] = m_armAngles[st+11]; // z
- tSt[6] = m_armAngles[st+18]; // x
- tSt[7] = m_armAngles[st+19]; // y
- tSt[8] = m_armAngles[st+20]; // z
-
- tNd[0] = m_armAngles[nd+ 0]; // x
- tNd[1] = m_armAngles[nd+ 1]; // y
- tNd[2] = m_armAngles[nd+ 2]; // z
- tNd[3] = m_armAngles[nd+ 9]; // x
- tNd[4] = m_armAngles[nd+10]; // y
- tNd[5] = m_armAngles[nd+11]; // z
- tNd[6] = m_armAngles[nd+18]; // x
- tNd[7] = m_armAngles[nd+19]; // y
- tNd[8] = m_armAngles[nd+20]; // z
-
- aa = 0.5f;
- if ( i%2 == 0 ) // arm?
- {
- if ( m_object->RetFret() == 0 ) // does nothing?
- {
- aa = 2.0f; // moves a lot
- }
- else
- {
- aa = 0.0f; // immobile
- }
- }
-
- if ( i < 2 ) // left?
- {
- bb = sinf(m_time*1.1f)*aa; tSt[0] += bb; tNd[0] += bb;
- bb = sinf(m_time*1.0f)*aa; tSt[1] += bb; tNd[1] += bb;
- bb = sinf(m_time*1.2f)*aa; tSt[2] += bb; tNd[2] += bb;
- bb = sinf(m_time*2.5f)*aa; tSt[3] += bb; tNd[3] += bb;
- bb = sinf(m_time*2.0f)*aa; tSt[4] += bb; tNd[4] += bb;
- bb = sinf(m_time*3.8f)*aa; tSt[5] += bb; tNd[5] += bb;
- bb = sinf(m_time*3.0f)*aa; tSt[6] += bb; tNd[6] += bb;
- bb = sinf(m_time*2.3f)*aa; tSt[7] += bb; tNd[7] += bb;
- bb = sinf(m_time*4.0f)*aa; tSt[8] += bb; tNd[8] += bb;
- }
- else // right?
- {
- bb = sinf(m_time*0.9f)*aa; tSt[0] += bb; tNd[0] += bb;
- bb = sinf(m_time*1.2f)*aa; tSt[1] += bb; tNd[1] += bb;
- bb = sinf(m_time*1.4f)*aa; tSt[2] += bb; tNd[2] += bb;
- bb = sinf(m_time*2.9f)*aa; tSt[3] += bb; tNd[3] += bb;
- bb = sinf(m_time*1.4f)*aa; tSt[4] += bb; tNd[4] += bb;
- bb = sinf(m_time*3.1f)*aa; tSt[5] += bb; tNd[5] += bb;
- bb = sinf(m_time*3.7f)*aa; tSt[6] += bb; tNd[6] += bb;
- bb = sinf(m_time*2.0f)*aa; tSt[7] += bb; tNd[7] += bb;
- bb = sinf(m_time*3.1f)*aa; tSt[8] += bb; tNd[8] += bb;
- }
-
-#if 1
- if ( i%2 == 1 && // leg?
- m_actionType == -1 ) // no special action?
- {
- if ( i == 1 ) // right leg?
- {
- ii = 5;
- a = ar*0.25f;
- }
- else
- {
- ii = 11;
- a = al*0.25f;
- }
- if ( a < -0.2f ) a = -0.2f;
- if ( a > 0.2f ) a = 0.2f;
-
- pos = m_object->RetPosition(ii+0);
- pos.y = 0.0f+a;
- m_object->SetPosition(ii+0, pos); // lengthens / shortcuts thigh
-
- pos = m_object->RetPosition(ii+1);
- pos.y = -1.5f+a;
- m_object->SetPosition(ii+1, pos); // lengthens / shortcuts leg
-
- pos = m_object->RetPosition(ii+2);
- pos.y = -1.5f+a;
- m_object->SetPosition(ii+2, pos); // lengthens / shortcuts foot
-
- if ( i == 1 ) // right leg?
- {
- aa = (ar*180.0f/Math::PI*0.5f);
- }
- else // left leg?
- {
- aa = (al*180.0f/Math::PI*0.5f);
- }
- tSt[6] += aa;
- tNd[6] += aa; // increases the angle X of the foot
-
- if ( i == 1 ) // right leg?
- {
- aa = (ar*180.0f/Math::PI);
- }
- else // left leg?
- {
- aa = (al*180.0f/Math::PI);
- }
- if ( aa < 0.0f ) aa = 0.0f;
- if ( aa > 30.0f ) aa = 30.0f;
-
- tSt[2] += aa;
- tNd[2] += aa; // increases the angle Z of the thigh
- tSt[5] -= aa*2;
- tNd[5] -= aa*2; // increases the angle Z of the leg
- tSt[8] += aa;
- tNd[8] += aa; // increases the angle Z of the foot
-
- aa = (af*180.0f/Math::PI)*0.7f;
- if ( aa < -30.0f ) aa = -30.0f;
- if ( aa > 30.0f ) aa = 30.0f;
-
- tSt[8] -= aa;
- tNd[8] -= aa; // increases the angle Z of the foot
- }
-#endif
-
- if ( m_actionType == MHS_DEADw ) // drowned?
- {
- if ( m_progress < 0.5f )
- {
- deadFactor = m_progress/0.5f;
- }
- else
- {
- deadFactor = 1.0f-(m_progress-0.5f)/0.5f;
- }
- if ( deadFactor < 0.0f ) deadFactor = 0.0f;
- if ( deadFactor > 1.0f ) deadFactor = 1.0f;
-
- for ( ii=0 ; ii<9 ; ii++ )
- {
- tSt[ii] += Math::Rand()*20.0f*deadFactor;
- tNd[ii] = tSt[ii];
- }
- time = 100.0f;
- }
-
- if ( i < 2 ) // right member (0..1) ?
- {
- m_object->SetAngleX(2+3*i+0, Math::Smooth(m_object->RetAngleX(2+3*i+0), Math::PropAngle(tSt[0], tNd[0], prog), time));
- m_object->SetAngleY(2+3*i+0, Math::Smooth(m_object->RetAngleY(2+3*i+0), Math::PropAngle(tSt[1], tNd[1], prog), time));
- m_object->SetAngleZ(2+3*i+0, Math::Smooth(m_object->RetAngleZ(2+3*i+0), Math::PropAngle(tSt[2], tNd[2], prog), time));
- m_object->SetAngleX(2+3*i+1, Math::Smooth(m_object->RetAngleX(2+3*i+1), Math::PropAngle(tSt[3], tNd[3], prog), time));
- m_object->SetAngleY(2+3*i+1, Math::Smooth(m_object->RetAngleY(2+3*i+1), Math::PropAngle(tSt[4], tNd[4], prog), time));
- m_object->SetAngleZ(2+3*i+1, Math::Smooth(m_object->RetAngleZ(2+3*i+1), Math::PropAngle(tSt[5], tNd[5], prog), time));
- m_object->SetAngleX(2+3*i+2, Math::Smooth(m_object->RetAngleX(2+3*i+2), Math::PropAngle(tSt[6], tNd[6], prog), time));
- m_object->SetAngleY(2+3*i+2, Math::Smooth(m_object->RetAngleY(2+3*i+2), Math::PropAngle(tSt[7], tNd[7], prog), time));
- m_object->SetAngleZ(2+3*i+2, Math::Smooth(m_object->RetAngleZ(2+3*i+2), Math::PropAngle(tSt[8], tNd[8], prog), time));
- }
- else // left member (2..3) ?
- {
- m_object->SetAngleX(2+3*i+0, Math::Smooth(m_object->RetAngleX(2+3*i+0), Math::PropAngle(-tSt[0], -tNd[0], prog), time));
- m_object->SetAngleY(2+3*i+0, Math::Smooth(m_object->RetAngleY(2+3*i+0), Math::PropAngle(-tSt[1], -tNd[1], prog), time));
- m_object->SetAngleZ(2+3*i+0, Math::Smooth(m_object->RetAngleZ(2+3*i+0), Math::PropAngle( tSt[2], tNd[2], prog), time));
- m_object->SetAngleX(2+3*i+1, Math::Smooth(m_object->RetAngleX(2+3*i+1), Math::PropAngle(-tSt[3], -tNd[3], prog), time));
- m_object->SetAngleY(2+3*i+1, Math::Smooth(m_object->RetAngleY(2+3*i+1), Math::PropAngle(-tSt[4], -tNd[4], prog), time));
- m_object->SetAngleZ(2+3*i+1, Math::Smooth(m_object->RetAngleZ(2+3*i+1), Math::PropAngle( tSt[5], tNd[5], prog), time));
- m_object->SetAngleX(2+3*i+2, Math::Smooth(m_object->RetAngleX(2+3*i+2), Math::PropAngle(-tSt[6], -tNd[6], prog), time));
- m_object->SetAngleY(2+3*i+2, Math::Smooth(m_object->RetAngleY(2+3*i+2), Math::PropAngle(-tSt[7], -tNd[7], prog), time));
- m_object->SetAngleZ(2+3*i+2, Math::Smooth(m_object->RetAngleZ(2+3*i+2), Math::PropAngle( tSt[8], tNd[8], prog), time));
- }
- }
-
-#if ADJUST_ANGLE
- if ( m_object->RetSelect() )
- {
- char s[100];
- sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
- m_engine->SetInfoText(4, s);
- }
-#endif
-
- // calculates the height lowering as a function
- // of the position of the legs.
- hr = 1.5f*(1.0f-cosf(m_object->RetAngleZ(5))) +
- 1.5f*(1.0f-cosf(m_object->RetAngleZ(5)+m_object->RetAngleZ(6)));
- a = 1.0f*sinf(m_object->RetAngleZ(5)+m_object->RetAngleZ(6)+m_object->RetAngleZ(7));
- if ( a < 0.0f ) hr += a;
-
- hl = 1.5f*(1.0f-cosf(m_object->RetAngleZ(11))) +
- 1.5f*(1.0f-cosf(m_object->RetAngleZ(11)+m_object->RetAngleZ(12)));
- a = 1.0f*sinf(m_object->RetAngleZ(11)+m_object->RetAngleZ(12)+m_object->RetAngleZ(13));
- if ( a < 0.0f ) hl += a;
-
- hr = Math::Min(hr, hl);
-
- if ( m_actionType == MHS_FIRE ) // shooting?
- {
- time = event.rTime*m_actionTime;
-
- dir.x = (Math::Rand()-0.5f)/8.0f;
- dir.z = (Math::Rand()-0.5f)/8.0f;
- dir.y = -0.5f; // slightly lower
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
-//? dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.y = -hr;
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetLinVibration(dir);
-
- dir.x = 0.0f;
- dir.y = (Math::Rand()-0.5f)/3.0f;
- dir.z = -0.1f; // slightly leaning forward
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
- }
- else if ( m_actionType == MHS_TAKE || // carrying?
- m_actionType == MHS_TAKEOTHER ) // flag?
- {
- time = event.rTime*m_actionTime*2.0f;
-
- dir.x = 0.0f;
- dir.z = 0.0f;
- dir.y = -1.5f; // slightly lower
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
-//? dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.y = -hr;
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetLinVibration(dir);
-
- dir.x = 0.0f;
- dir.y = 0.0f;
- dir.z = -0.2f;
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
- }
- else if ( m_actionType == MHS_TAKEHIGH ) // carrying?
- {
- time = event.rTime*m_actionTime*2.0f;
-
- dir.x = 0.4f; // slightly forward
- dir.z = 0.0f;
- dir.y = 0.0f;
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
-//? dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.y = -hr;
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetLinVibration(dir);
-
- dir.x = 0.0f;
- dir.y = 0.0f;
- dir.z = -0.2f;
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
- }
- else if ( m_actionType == MHS_FLAG ) // flag?
- {
- time = event.rTime*m_actionTime*2.0f;
-
- dir.x = 0.0f;
- dir.z = 0.0f;
- dir.y = -2.0f; // slightly lower
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
-//? dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.y = -hr;
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetLinVibration(dir);
-
- dir.x = 0.0f;
- dir.y = 0.0f;
- dir.z = -0.4f;
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
- }
- else if ( m_actionType == MHS_DEADg ) // shooting death (falls)?
- {
- if ( m_physics->RetLand() ) // on the ground?
- {
- SetAction(MHS_DEADg1, 0.5f); // knees
- }
- }
- else if ( m_actionType == MHS_DEADg1 ) // shooting death (knees)?
- {
- prog = m_progress;
- if ( prog >= 1.0f )
- {
- prog = 1.0f;
-
- for ( i=0 ; i<10 ; i++ )
- {
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*4.0f;
- pos.z += (Math::Rand()-0.5f)*4.0f;
- m_terrain->MoveOnFloor(pos);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 1.2f+Math::Rand()*1.2f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f);
- }
- m_sound->Play(SOUND_BOUMv, m_object->RetPosition(0));
-
- SetAction(MHS_DEADg2, 1.0f); // expects knees
- }
-
- time = 100.0f;
-
- dir.x = 0.0f;
- dir.z = 0.0f;
- dir.y = -1.5f*prog;
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetLinVibration(dir);
-
- dir.x = 0.0f;
- dir.y = 0.0f;
- dir.z = -(20.0f*Math::PI/180.0f)*prog;
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
- }
- else if ( m_actionType == MHS_DEADg2 ) // shooting death (knees)?
- {
- if ( m_progress >= 1.0f )
- {
- SetAction(MHS_DEADg3, 1.0f); // face down
- }
-
- time = 100.0f;
-
- dir.x = 0.0f;
- dir.z = 0.0f;
- dir.y = -1.5f;
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetLinVibration(dir);
-
- dir.x = 0.0f;
- dir.y = 0.0f;
- dir.z = -(20.0f*Math::PI/180.0f);
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
- }
- else if ( m_actionType == MHS_DEADg3 ) // shooting death (face down)?
- {
- prog = m_progress;
- if ( prog >= 1.0f )
- {
- prog = 1.0f;
-
- for ( i=0 ; i<20 ; i++ )
- {
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*8.0f;
- pos.z += (Math::Rand()-0.5f)*8.0f;
- m_terrain->MoveOnFloor(pos);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 2.0f+Math::Rand()*1.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f);
- }
- m_sound->Play(SOUND_BOUMv, m_object->RetPosition(0));
-
- SetAction(MHS_DEADg4, 3.0f); // expects face down
- }
-
- time = 100.0f;
- prog = powf(prog, 3.0f);
-
- dir.y = -(1.5f+1.5f*prog);
- dir.x = 0.0f;
- dir.z = 0.0f;
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetLinVibration(dir);
-
- dir.z = -((20.0f*Math::PI/180.0f)+(70.0f*Math::PI/180.0f)*prog);
- dir.x = 0.0f;
- dir.y = 0.0f;
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
- }
- else if ( m_actionType == MHS_DEADg4 ) // shooting death (face down)?
- {
- if ( m_progress >= 1.0f )
- {
- m_object->SetEnable(false);
- }
-
- time = 100.0f;
-
- dir.y = -(1.5f+1.5f);
- dir.x = 0.0f;
- dir.z = 0.0f;
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetLinVibration(dir);
-
- dir.z = -((20.0f*Math::PI/180.0f)+(70.0f*Math::PI/180.0f));
- dir.x = 0.0f;
- dir.y = 0.0f;
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
- }
- else if ( m_actionType == MHS_DEADw ) // drowned?
- {
- pos = m_object->RetPosition(0);
- level = m_water->RetLevel()-0.5f;
- if ( pos.y < level )
- {
- pos.y += 4.0f*event.rTime; // back to the surface
- if ( pos.y > level ) pos.y = level;
- m_object->SetPosition(0, pos);
- }
- if ( pos.y > level )
- {
- pos.y -= 10.0f*event.rTime; // down quickly
- if ( pos.y < level ) pos.y = level;
- m_object->SetPosition(0, pos);
- }
-
- prog = m_progress;
- if ( prog >= 1.0f )
- {
- prog = 1.0f;
- if ( pos.y >= level ) m_object->SetEnable(false);
- }
-
- prog *= 2.0f;
- if ( prog > 1.0f ) prog = 1.0f;
-
- time = 100.0f;
-
- dir.z = -(90.0f*Math::PI/180.0f)*prog;
- dir.x = Math::Rand()*0.3f*deadFactor;
- dir.y = Math::Rand()*0.3f*deadFactor;
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- m_object->SetInclinaison(dir);
-
- m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- }
- else if ( m_actionType == MHS_LOST ) // lost?
- {
- time = m_time;
- if ( time < 10.0f ) time *= time/10.0f; // starts slowly
-
- dir.x = time*2.0f;
- dir.y = sinf(m_time*0.8f)*0.8f;
- dir.z = sinf(m_time*0.6f)*0.5f;
- m_object->SetInclinaison(dir);
- SetInclinaison(dir);
-
-//? dir.x = -(sinf(time*0.05f+Math::PI*1.5f)+1.0f)*100.0f;
- // original code: Math::Min(time/30.0f) (?) changed to time/30.0f
- dir.x = -(powf(time/30.0f, 4.0f))*1000.0f; // from the distance
- dir.y = 0.0f;
- dir.z = 0.0f;
- m_object->SetLinVibration(dir);
- SetLinVibration(dir);
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(0.5f, 3.7f, 0.0f);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.y += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- pos = Transform(*mat, pos);
- speed.x = (Math::Rand()-0.5f)*0.5f;
- speed.y = (Math::Rand()-0.5f)*0.5f;
- speed.z = (Math::Rand()-0.5f)*0.5f;
- dim.x = 0.5f+Math::Rand()*0.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTILENS1, 5.0f, 0.0f, 0.0f);
- }
- else if ( m_actionType == MHS_SATCOM ) // look at the SatCom?
- {
- SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- SetLinVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
- }
- else
- {
- if ( m_physics->RetLand() ) // on the ground?
- {
- time = event.rTime*8.0f;
- if ( bSwim ) time *= 0.25f;
-
- if ( action == MH_MARCH ) // walking?
- {
- dir.x = sinf(Math::Mod(rTime[0]+0.5f, 1.0f)*Math::PI*2.0f)*0.10f;
- dir.y = sinf(Math::Mod(rTime[0]+0.6f, 1.0f)*Math::PI*2.0f)*0.20f;
- s = m_physics->RetLinMotionX(MO_REASPEED)*0.03f;
- }
- else if ( action == MH_MARCHTAKE ) // takes walking?
- {
- dir.x = sinf(Math::Mod(rTime[0]+0.5f, 1.0f)*Math::PI*2.0f)*0.10f;
- dir.y = sinf(Math::Mod(rTime[0]+0.6f, 1.0f)*Math::PI*2.0f)*0.15f;
- s = m_physics->RetLinMotionX(MO_REASPEED)*0.02f;
- }
- else
- {
- dir.x = 0.0f;
- dir.y = 0.0f;
- s = m_physics->RetLinMotionX(MO_REASPEED)*0.03f;
- }
-
- if ( s < 0.0f ) s *= 0.5f;
- dir.z = -s*0.7f;
-
- actual = m_object->RetInclinaison();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- dir.y = Math::Smooth(actual.y, dir.y, time);
- dir.z = Math::Smooth(actual.z, dir.z, time);
- if ( bOnBoard ) dir *= 0.3f;
- m_object->SetInclinaison(dir);
- SetInclinaison(dir);
-
- if ( action == MH_MARCH ) // walking?
- {
- p2.x = 0.0f;
- p2.y = sinf(Math::Mod(rTime[0]+0.5f, 1.0f)*Math::PI*2.0f)*0.5f;
- p2 = Math::RotatePoint(-m_object->RetAngleY(0), p2);
- dir.x = p2.x;
- dir.z = p2.y;
- dir.y = sinf(Math::Mod(rTime[0]*2.0f, 1.0f)*Math::PI*2.0f)*0.3f;
- }
- else if ( action == MH_MARCHTAKE ) // takes walking?
- {
- p2.x = 0.0f;
- p2.y = sinf(Math::Mod(rTime[0]+0.5f, 1.0f)*Math::PI*2.0f)*0.25f;
- p2 = Math::RotatePoint(-m_object->RetAngleY(0), p2);
- dir.x = p2.x;
- dir.z = p2.y;
- dir.y = sinf(Math::Mod(rTime[0]*2.0f, 1.0f)*Math::PI*2.0f)*0.05f-0.3f;
- }
- else
- {
- dir.x = 0.0f;
- dir.z = 0.0f;
- dir.y = 0.0f;
- }
-
- actual = m_object->RetLinVibration();
- dir.x = Math::Smooth(actual.x, dir.x, time);
- if ( action == MH_MARCHTAKE ) // takes walking?
- {
- dir.y = -hr;
- }
- else
- {
- s = Math::Min(m_armTimeAction, 1.0f);
- dir.y = Math::Smooth(actual.y, dir.y, time)*s;
- dir.y += -hr*(1.0f-s);
- }
- dir.z = Math::Smooth(actual.z, dir.z, time);
- if ( bOnBoard ) dir *= 0.3f;
- m_object->SetLinVibration(dir);
-
- dir.x = 0.0f;
- dir.z = 0.0f;
- dir.y = 0.0f;
- SetCirVibration(dir);
- }
- }
-
- // Management of the head.
- if ( m_actionType == MHS_TAKE || // takes?
- m_actionType == MHS_FLAG ) // takes?
- {
- m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f-0.6f, event.rTime*5.0f));
- m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f);
- m_object->SetAngleY(1, Math::Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f));
- }
- else if ( m_actionType == MHS_TAKEOTHER || // takes?
- m_actionType == MHS_TAKEHIGH ) // takes?
- {
- m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f-0.3f, event.rTime*5.0f));
- m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f);
- m_object->SetAngleY(1, Math::Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f));
- }
- else if ( m_actionType == MHS_WIN ) // win
- {
- float factor = 0.6f+(sinf(m_armTimeAbs*0.5f)*0.40f);
- m_object->SetAngleZ(1, sinf(m_armTimeAbs*5.0f)*0.20f*factor);
- m_object->SetAngleX(1, sinf(m_armTimeAbs*0.6f)*0.10f);
- m_object->SetAngleY(1, sinf(m_armTimeAbs*1.5f)*0.15f);
- }
- else if ( m_actionType == MHS_LOST ) // lost?
- {
- float factor = 0.6f+(sinf(m_armTimeAbs*0.5f)*0.40f);
- m_object->SetAngleZ(1, sinf(m_armTimeAbs*0.6f)*0.10f);
- m_object->SetAngleX(1, sinf(m_armTimeAbs*0.7f)*0.10f);
- m_object->SetAngleY(1, sinf(m_armTimeAbs*3.0f)*0.30f*factor);
- }
- else if ( m_object->RetDead() ) // dead?
- {
- }
- else
- {
- m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f, event.rTime*5.0f));
- m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f);
- m_object->SetAngleY(1, Math::Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f));
- }
-
- if ( bOnBoard )
- {
- m_object->SetAngleZ(1, 0.0f);
- m_object->SetAngleX(1, 0.0f);
- m_object->SetAngleY(1, 0.0f);
- }
-
- // Steps sound effects.
- if ( legAction == MH_MARCH ||
- legAction == MH_MARCHTAKE )
- {
- Sound sound[2];
- float speed, synchro, volume[2], freq[2], hard, level;
-
- speed = m_physics->RetLinMotionX(MO_REASPEED);
-
- if ( m_object->RetFret() == 0 )
- {
- if ( speed > 0.0f ) synchro = 0.21f; // synchro forward
- else synchro = 0.29f; // synchro backward
- }
- else
- {
- if ( speed > 0.0f ) synchro = 0.15f; // synchro forward
- else synchro = 0.35f; // synchro backward
- }
- time = rTime[1]+synchro;
-
- if ( fabs(m_lastSoundMarch-time) > 0.4f &&
- Math::Mod(time, 0.5f) < 0.1f )
- {
- volume[0] = 0.5f;
- freq[0] = 1.0f;
- if ( m_object->RetFret() != 0 )
- {
-//? volume[0] *= 2.0f;
- freq[0] = 0.7f;
- }
- volume[1] = volume[0];
- freq[1] = freq[0];
- sound[0] = SOUND_CLICK;
- sound[1] = SOUND_CLICK;
-
- pos = m_object->RetPosition(0);
-
- level = m_water->RetLevel();
- if ( pos.y <= level+3.0f ) // underwater?
- {
- sound[0] = SOUND_STEPw;
- }
- else
- {
- hard = m_terrain->RetHardness(pos);
-
- if ( hard >= 0.875 )
- {
- sound[0] = SOUND_STEPm; // metal
- }
- else
- {
- hard /= 0.875;
- sound[0] = SOUND_STEPs; // smooth
- sound[1] = SOUND_STEPh; // hard
-
- volume[0] *= 1.0f-hard;
- volume[1] *= hard;
- if ( hard < 0.5f )
- {
- volume[0] *= 1.0f+hard*2.0f;
- volume[1] *= 1.0f+hard*2.0f;
- }
- else
- {
- volume[0] *= 3.0f-hard*2.0f;
- volume[1] *= 3.0f-hard*2.0f;
- }
- freq[0] *= 1.0f+hard;
- freq[1] *= 0.5f+hard;
- }
- }
-
- if ( sound[0] != SOUND_CLICK )
- {
- m_sound->Play(sound[0], pos, volume[0], freq[0]);
- }
- if ( sound[1] != SOUND_CLICK )
- {
- m_sound->Play(sound[1], pos, volume[1], freq[1]);
- }
- m_lastSoundMarch = time;
- }
- }
-
- if ( legAction == MH_SWIM )
- {
- time = rTime[0]+0.5f;
-
- if ( fabs(m_lastSoundMarch-time) > 0.9f &&
- Math::Mod(time, 1.0f) < 0.1f )
- {
- m_sound->Play(SOUND_SWIM, m_object->RetPosition(0), 0.5f);
- m_lastSoundMarch = time;
- }
- }
-
- m_lastSoundHhh -= event.rTime;
- if ( m_lastSoundHhh <= 0.0f &&
- m_object->RetSelect() &&
- m_object->RetOption() == 0 ) // helmet?
- {
- m_sound->Play(SOUND_HUMAN1, m_object->RetPosition(0), (0.5f+m_tired*0.2f));
- m_lastSoundHhh = (4.0f-m_tired*2.5f)+(4.0f-m_tired*2.5f)*Math::Rand();
- }
-
- return true;
-}
-
-
-// Management of the display mode when customizing the personal.
-
-void CMotionHuman::StartDisplayPerso()
-{
- m_bDisplayPerso = true;
-}
-
-void CMotionHuman::StopDisplayPerso()
-{
- m_bDisplayPerso = false;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionhuman.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motionhuman.h"
+
+#include "old/modfile.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "math/geometry.h"
+#include "object/robotmain.h"
+#include "physics/physics.h"
+
+
+
+#define ADJUST_ANGLE false // true -> adjusts the angles of the members
+const int ADJUST_ACTION = (3*3*3*3*MH_SPEC+3*3*3*MHS_SATCOM);
+
+const float START_TIME = 1000.0f; // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionHuman::CMotionHuman(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ m_partiReactor = -1;
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeSwim = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLastAction = -1;
+ m_bArmStop = false;
+ m_lastSoundMarch = 0.0f;
+ m_lastSoundHhh = 0.0f;
+ m_time = 0.0f;
+ m_tired = 0.0f;
+ m_bDisplayPerso = false;
+}
+
+// Object's constructor.
+
+CMotionHuman::~CMotionHuman()
+{
+}
+
+
+// Removes an object.
+
+void CMotionHuman::DeleteObject(bool bAll)
+{
+ if ( m_partiReactor != -1 )
+ {
+ m_particule->DeleteParticule(m_partiReactor);
+ m_partiReactor = -1;
+ }
+}
+
+
+// Starts an action.
+
+Error CMotionHuman::SetAction(int action, float time)
+{
+ CMotion::SetAction(action, time);
+ m_time = 0.0f;
+ return ERR_OK;
+}
+
+
+// Creates cosmonaut on the ground.
+
+bool CMotionHuman::Create(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ char filename[100];
+ int rank, option, face, glasses;
+
+ if ( m_engine->RetRestCreate() < 16 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+ option = m_object->RetOption();
+
+ if ( m_main->RetGamerOnlyHead() )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+ face = m_main->RetGamerFace();
+ sprintf(filename, "objects\\human2h%d.mod", face+1);
+ pModFile->ReadModel(filename);
+ pModFile->CreateEngineObject(rank);
+
+ glasses = m_main->RetGamerGlasses();
+ if ( glasses != 0 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ sprintf(filename, "objects\\human2g%d.mod", glasses);
+ pModFile->ReadModel(filename);
+ pModFile->CreateEngineObject(rank);
+ }
+
+ CreatePhysics(type);
+ m_object->SetFloorHeight(0.0f);
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+ }
+
+ // Creates the main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+
+ if ( option == 0 ) // head in helmet?
+ {
+ pModFile->ReadModel("objects\\human1c.mod");
+ }
+ if ( option == 1 ) // head without helmet?
+ {
+ pModFile->ReadModel("objects\\human1h.mod");
+ }
+ if ( option == 2 ) // without a backpack?
+ {
+ pModFile->ReadModel("objects\\human1v.mod");
+ }
+ pModFile->CreateEngineObject(rank);
+
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have an obligatory collision with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 2.0f, SOUND_AIE, 0.20f);
+ m_object->SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 4.0f);
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+
+ if ( type == OBJECT_HUMAN )
+ {
+ if ( option == 0 ) // head in helmet?
+ {
+ face = m_main->RetGamerFace();
+ sprintf(filename, "objects\\human2c%d.mod", face+1);
+ pModFile->ReadModel(filename);
+ }
+ if ( option == 1 || // head without helmet?
+ option == 2 ) // without a backpack?
+ {
+ face = m_main->RetGamerFace();
+ sprintf(filename, "objects\\human2h%d.mod", face+1);
+ pModFile->ReadModel(filename);
+ }
+ }
+ if ( type == OBJECT_TECH )
+ {
+ pModFile->ReadModel("objects\\human2t.mod");
+ }
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(0.0f, 2.7f, 0.0f));
+ if ( option == 1 || // head without helmet?
+ option == 2 ) // without a backpack?
+ {
+ m_object->SetZoom(1, Math::Vector(1.0f, 1.05f, 1.0f));
+ }
+
+ // Creates the glasses.
+ glasses = m_main->RetGamerGlasses();
+ if ( glasses != 0 && type == OBJECT_HUMAN )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(15, rank);
+ m_object->SetObjectParent(15, 1);
+ sprintf(filename, "objects\\human2g%d.mod", glasses);
+ pModFile->ReadModel(filename);
+ pModFile->CreateEngineObject(rank);
+ }
+
+ // Creates the right arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\human3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(0.0f, 2.3f, -1.2f));
+ m_object->SetAngle(2, Math::Vector(90.0f*Math::PI/180.0f, 90.0f*Math::PI/180.0f, -50.0f*Math::PI/180.0f));
+
+ // Creates the right forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\human4r.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(1.3f, 0.0f, 0.0f));
+ m_object->SetAngle(3, Math::Vector(0.0f*Math::PI/180.0f, -20.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f));
+
+ // Creates right hand.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 3);
+ pModFile->ReadModel("objects\\human5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, Math::Vector(1.2f, 0.0f, 0.0f));
+
+ // Creates the right thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 0);
+ pModFile->ReadModel("objects\\human6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, Math::Vector(0.0f, 0.0f, -0.7f));
+ m_object->SetAngle(5, Math::Vector(10.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f));
+
+ // Creates the right leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 5);
+ pModFile->ReadModel("objects\\human7.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(0.0f, -1.5f, 0.0f));
+ m_object->SetAngle(6, Math::Vector(0.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f, -10.0f*Math::PI/180.0f));
+
+ // Creates the right foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 6);
+ pModFile->ReadModel("objects\\human8.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, -1.5f, 0.0f));
+ m_object->SetAngle(7, Math::Vector(-10.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f));
+
+ // Creates the left arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\human3.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(0.0f, 2.3f, 1.2f));
+ m_object->SetAngle(8, Math::Vector(-90.0f*Math::PI/180.0f, -90.0f*Math::PI/180.0f, -50.0f*Math::PI/180.0f));
+
+ // Creates the left forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 8);
+ pModFile->ReadModel("objects\\human4l.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, Math::Vector(1.3f, 0.0f, 0.0f));
+ m_object->SetAngle(9, Math::Vector(0.0f*Math::PI/180.0f, 20.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f));
+
+ // Creates left hand.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10, rank);
+ m_object->SetObjectParent(10, 9);
+ pModFile->ReadModel("objects\\human5.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10, Math::Vector(1.2f, 0.0f, 0.0f));
+
+ // Creates the left thigh.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(11, rank);
+ m_object->SetObjectParent(11, 0);
+ pModFile->ReadModel("objects\\human6.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(11, Math::Vector(0.0f, 0.0f, 0.7f));
+ m_object->SetAngle(11, Math::Vector(-10.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f));
+
+ // Creates the left leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(12, rank);
+ m_object->SetObjectParent(12, 11);
+ pModFile->ReadModel("objects\\human7.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(12, Math::Vector(0.0f, -1.5f, 0.0f));
+ m_object->SetAngle(12, Math::Vector(0.0f*Math::PI/180.0f, 0.0f*Math::PI/180.0f, -10.0f*Math::PI/180.0f));
+
+ // Creates the left foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(13, rank);
+ m_object->SetObjectParent(13, 12);
+ pModFile->ReadModel("objects\\human8.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(13, Math::Vector(0.0f, -1.5f, 0.0f));
+ m_object->SetAngle(13, Math::Vector(10.0f*Math::PI/180.0f, -5.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f));
+
+ // Creates the neutron gun.
+ if ( option != 2 ) // with backpack?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(14, rank);
+ m_object->SetObjectParent(14, 0);
+ pModFile->ReadModel("objects\\human9.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(14, Math::Vector(-1.5f, 0.3f, -1.35f));
+ m_object->SetAngleZ(14, Math::PI);
+ }
+
+ m_object->CreateShadowCircle(2.0f, 0.8f);
+
+ CreatePhysics(type);
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+// Creates the physical object.
+
+void CMotionHuman::CreatePhysics(ObjectType type)
+{
+ Character* character;
+ int i;
+
+ int member_march[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 90,90,-50, 10,0,55, 0,0,0, // t0: arms/thighs/-
+ 0,-20,0, -5,0,-110, 0,0,0, // t0: forearm/legs/-
+ 0,0,0, -5,0,40, 0,0,0, // t0: hands/feet/-
+ // on the ground:
+ 125,115,-45, 10,0,50, 0,0,0, // t1: arms/thighs/-
+ 0,-20,0, -5,0,-15, 0,0,0, // t1: forearm/legs/-
+ 0,0,0, -5,0,0, 0,0,0, // t1: hands/feet/-
+ // on the ground back:
+ 25,55,-40, 10,0,-15, 0,0,0, // t2: arms/thighs/-
+ 30,-50,40, -5,0,-55, 0,0,0, // t2: forearm/legs/-
+ 0,0,0, -5,0,25, 0,0,0, // t2: hands/feet/-
+ };
+
+ int member_march_take[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 15,50,-50, 10,0,55, 0,0,0, // t0: arms/thighs/-
+ 45,-70,10, -5,0,-110, 0,0,0, // t0: forearm/legs/-
+ -10,25,0, -5,0,40, 0,0,0, // t0: hands/feet/-
+ // on the ground:
+ 15,50,-55, 10,0,50, 0,0,0, // t1: arms/thighs/-
+ 45,-70,10, -5,0,-15, 0,0,0, // t1: forearm/legs/-
+ -10,25,0, -5,0,0, 0,0,0, // t1: hands/feet/-
+ // on the ground back:
+ 15,50,-45, 10,0,-15, 0,0,0, // t2: arms/thighs/-
+ 45,-70,10, -5,0,-55, 0,0,0, // t2: forearm/legs/-
+ -10,25,0, -5,0,45, 0,0,0, // t2: hands/feet/-
+ };
+
+ int member_turn[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 90,90,-50, 10,0,30, 0,0,0, // t0: arms/thighs/-
+ 0,-20,0, -5,0,-60, 0,0,0, // t0: forearm/legs/-
+ 0,0,0, -5,0,30, 0,0,0, // t0: hands/feet/-
+ // on the ground:
+ 90,110,-45, 10,0,0, 0,0,0, // t1: arms/thighs/-
+ 0,-20,0, -5,5,0, 0,0,0, // t1: forearm/legs/-
+ 0,0,0, -5,10,0, 0,0,0, // t1: hands/feet/-
+ // on the ground back:
+ 90,70,-45, 10,0,0, 0,0,0, // t2: arms/thighs/-
+ 0,-20,10, -5,-5,0, 0,0,0, // t2: forearm/legs/-
+ 0,0,0, -5,-10,0, 0,0,0, // t2: hands/feet/-
+ };
+
+ int member_stop[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3,
+ 90,90,-50, 10,0,5, 0,0,0, // arms/thighs/-
+ 0,-20,0, 0,0,-10, 0,0,0, // forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // hands/feet/-
+ //
+ 90,90,-55, 10,0,5, 0,0,0, // arms/thighs/-
+ 0,-15,0, 0,0,-10, 0,0,0, // forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // hands/feet/-
+ //
+ 90,90,-60, 10,0,5, 0,0,0, // arms/thighs/-
+ 0,-10,0, 0,0,-10, 0,0,0, // forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // hands/feet/-
+ };
+
+ int member_fly[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3,
+ -5,90,-60, 20,5,-25, 0,0,0, // arms/thighs/-
+ 85,-40,-25, 10,0,-30, 0,0,0, // forearm/legs/-
+ 40,10,25, 0,15,0, 0,0,0, // hands/feet/-
+ //
+ -15,90,-40, 20,5,-35, 0,0,0, // arms/thighs/-
+ 85,-40,-25, 10,0,-40, 0,0,0, // forearm/legs/-
+ 45,5,20, 0,15,0, 0,0,0, // hands/feet/-
+ //
+ -25,90,-50, 20,5,-20, 0,0,0, // arms/thighs/-
+ 85,-40,-25, 10,0,-10, 0,0,0, // forearm/legs/-
+ 30,15,25, 0,15,0, 0,0,0, // hands/feet/-
+ };
+
+ int member_swim[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3,
+#if 1
+ 130,-70,200, 10,20,55, 0,0,0, // arms/thighs/-
+ 115,-125,0, -5,0,-110, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,10,-5, 0,0,0, // hands/feet/-
+ //
+ 130,-95,115,55,5,5, 0,0,0, // arms/thighs/-
+ 75,-50,25, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,5,-30, 0,0,0, // hands/feet/-
+ //
+ 130,-100,220,5,0,0, 0,0,0, // arms/thighs/-
+ 150,5,0, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,30,-20, 0,0,0, // hands/feet/-
+#endif
+#if 0
+ 130,-70,200,5,0,0, 0,0,0, // arms/thighs/-
+ 115,-125,0, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,30,-20, 0,0,0, // hands/feet/-
+ //
+ 130,-95,115, 10,20,55, 0,0,0, // arms/thighs/-
+ 75,-50,25, -5,0,-110, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,10,-5, 0,0,0, // hands/feet/-
+ //
+ 130,-100,220, 55,5,5, 0,0,0, // arms/thighs/-
+ 150,5,0, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,5,-30, 0,0,0, // hands/feet/-
+#endif
+#if 0
+ 130,-70,200, 55,5,5, 0,0,0, // arms/thighs/-
+ 115,-125,0, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,5,-30, 0,0,0, // hands/feet/-
+ //
+ 130,-95,115, 5,0,0, 0,0,0, // arms/thighs/-
+ 75,-50,25, -5,0,-15, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,30,-20, 0,0,0, // hands/feet/-
+ //
+ 130,-100,220, 10,20,55, 0,0,0, // arms/thighs/-
+ 150,5,0, -5,0,-110, 0,0,0, // forearm/legs/-
+ 0,0,0, -5,10,-5, 0,0,0, // hands/feet/-
+#endif
+ };
+
+ int member_spec[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // shooting:
+ 65,5,-20, 10,0,40, 0,0,0, // s0: arms/thighs/-
+ -50,-30,50, 0,0,-70, 0,0,0, // s0: forearm/legs/-
+ 0,50,0, -10,0,35, 0,0,0, // s0: hands/feet/-
+ // takes weapon:
+ 160,135,-20,10,0,5, 0,0,0, // s1: arms/thighs/-
+ 10,-60,40, 0,0,-10, 0,0,0, // s1: forearm/legs/-
+ 0,-5,-25, -10,5,5, 0,0,0, // s1: hands/feet/-
+ // carries earth:
+ 25,40,-40, 10,0,60, 0,0,0, // s2: arms/thighs/-
+ 0,-45,0, 0,0,-120, 0,0,0, // s2: forearm/legs/-
+ 0,15,5, -10,0,70, 0,0,0, // s2: hands/feet/-
+ // carries in front:
+ 25,20,5, 10,0,55, 0,0,0, // s3: arms/thighs/-
+ -15,-30,10, 0,0,-110, 0,0,0, // s3: forearm/legs/-
+ 0,0,0, -10,0,65, 0,0,0, // s3: hands/feet/-
+ // carries vertically:
+ -30,15,-5, 10,0,15, 0,0,0, // s4: arms/thighs/-
+ 0,-15,15, 0,0,-30, 0,0,0, // s4: forearm/legs/-
+ 35,0,-15, -10,0,25, 0,0,0, // s4: hands/feet/-
+ // rises:
+ 15,50,-50, 10,0,5, 0,0,0, // s5: arms/thighs/-
+ 45,-70,10, 0,0,-10, 0,0,0, // s5: forearm/legs/-
+ -10,25,0, -10,5,5, 0,0,0, // s5: hands/feet/-
+ // wins:
+ 90,90,-30, 20,0,5, 0,0,0, // s6: arms/thighs/-
+ 0,-90,0, -10,0,-10, 0,0,0, // s6: forearm/legs/-
+ 0,25,0, -10,5,5, 0,0,0, // s6: hands/feet/-
+ // lose:
+ -70,45,35, 10,0,40, 0,0,0, // s7: arms/thighs/-
+ 15,-95,-5, 0,0,-70, 0,0,0, // s7: forearm/legs/-
+ 0,0,0, -10,0,35, 0,0,0, // s7: hands/feet/-
+ // shooting death (falls):
+ 90,90,-50, 10,0,5, 0,0,0, // s8: arms/thighs/-
+ 0,-20,0, 0,0,-10, 0,0,0, // s8: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s8: hands/feet/-
+ // shooting death (knees):
+ 110,105,-5, 10,0,25, 0,0,0, // s9: arms/thighs/-
+ 0,-40,20, 0,0,-120, 0,0,0, // s9: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s9: hands/feet/-
+ // shooting death (knees):
+ 110,120,-25, 10,0,25, 0,0,0, // s10: arms/thighs/-
+ 0,-40,20, 0,0,-120, 0,0,0, // s10: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s10: hands/feet/-
+ // shooting death (face down):
+ 110,100,-25, 25,0,10, 0,0,0, // s11: arms/thighs/-
+ 0,-40,20, 0,0,-25, 0,0,0, // s11: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s11: hands/feet/-
+ // shooting death (face down):
+ 110,100,-25, 25,0,10, 0,0,0, // s12: arms/thighs/-
+ 0,-40,20, 0,0,-25, 0,0,0, // s12: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s12: hands/feet/-
+ // drowned:
+ 110,100,-25, 25,0,10, 0,0,0, // s13: arms/thighs/-
+ 0,-40,20, 0,0,-25, 0,0,0, // s13: forearm/legs/-
+ 0,0,0, -10,5,5, 0,0,0, // s13: hands/feet/-
+ // puts / removes flag:
+ 85,45,-50, 10,0,60, 0,0,0, // s14: arms/thighs/-
+ -60,15,65, 0,0,-105, 0,0,0, // s14: forearm/legs/-
+ 0,10,0, -10,0,60, 0,0,0, // s14: hands/feet/-
+ // reads SatCom:
+ 70,30,-20, 10,0,5, 0,0,0, // s15: arms/thighs/-
+ 115,-65,60, 0,0,-10, 0,0,0, // s15: forearm/legs/-
+ 0,20,0, -10,5,5, 0,0,0, // s15: hands/feet/-
+ };
+
+ m_physics->SetType(TYPE_FLYING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.0f;
+ character->wheelRight = 4.0f;
+ character->height = 3.5f;
+
+ if ( type == OBJECT_HUMAN )
+ {
+ m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 35.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 70.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 40.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+ m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
+ m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 6.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 6.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 4.0f);
+ }
+ else
+ {
+ m_physics->SetLinMotionX(MO_ADVSPEED, 40.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 8.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 8.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 8.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+ m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
+ m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.6f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.6f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 4.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 4.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 3.0f);
+ }
+
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_MARCH+i] = member_march[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_MARCHTAKE+i] = member_march_take[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_TURN+i] = member_turn[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_STOP+i] = member_stop[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_FLY+i] = member_fly[i];
+ }
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_SWIM+i] = member_swim[i];
+ }
+ for ( i=0 ; i<3*3*3*16 ; i++ )
+ {
+ m_armAngles[3*3*3*3*MH_SPEC+i] = member_spec[i];
+ }
+}
+
+
+// Management of an event.
+
+bool CMotionHuman::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if ADJUST_ANGLE
+ int i;
+
+ if ( event.param == 'A' ) m_armTimeIndex++;
+ if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
+
+ if ( event.param == 'Q' ) m_armPartIndex++;
+ if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
+
+ if ( event.param == 'W' ) m_armMemberIndex++;
+ if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
+
+ i = m_armMemberIndex*3;
+ i += m_armPartIndex*3*3;
+ i += m_armTimeIndex*3*3*3;
+ i += ADJUST_ACTION;
+
+ if ( event.param == 'E' ) m_armAngles[i+0] += 5;
+ if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
+ if ( event.param == 'R' ) m_armAngles[i+1] += 5;
+ if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
+ if ( event.param == 'T' ) m_armAngles[i+2] += 5;
+ if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
+
+ if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
+
+ if ( event.param == 'Y' )
+ {
+ char s[100];
+ sprintf(s, "index dans table = %d %d %d\n", i, i+9, i+18);
+ OutputDebugString(s);
+ }
+#endif
+ }
+
+ return true;
+}
+
+// Management of an event.
+
+bool CMotionHuman::EventFrame(const Event &event)
+{
+ Math::Matrix* mat;
+ Math::Vector dir, actual, pos, speed, pf;
+ Math::Point center, dim, p2;
+ float s, a, prog, rTime[2], lTime[2], time, rot, hr, hl;
+ float al, ar, af;
+ float tSt[9], tNd[9];
+ float aa, bb, shield, deadFactor, level;
+ int i, ii, st, nd, action, legAction, armAction;
+ bool bOnBoard, bSwim, bStop;
+
+ if ( m_engine->RetPause() )
+ {
+ if ( m_actionType == MHS_SATCOM )
+ {
+ m_progress += event.rTime*m_actionTime;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ bOnBoard = false;
+ if ( m_object->RetSelect() &&
+ m_camera->RetType() == CAMERA_ONBOARD )
+ {
+ bOnBoard = true;
+ }
+
+ if ( m_bDisplayPerso && m_main->RetGamerOnlyHead() )
+ {
+ m_time += event.rTime;
+ m_object->SetLinVibration(Math::Vector(0.0f, -0.55f, 0.0f));
+ m_object->SetCirVibration(Math::Vector(0.0f, m_main->RetPersoAngle(), 0.0f));
+ return true;
+ }
+ if ( m_bDisplayPerso )
+ {
+ m_object->SetCirVibration(Math::Vector(0.0f, m_main->RetPersoAngle()+0.2f, 0.0f));
+ }
+
+ shield = m_object->RetShield();
+ shield += event.rTime*(1.0f/120.0f); // regeneration in 120 seconds
+ if ( shield > 1.0f ) shield = 1.0f;
+ m_object->SetShield(shield);
+
+ bSwim = m_physics->RetSwim();
+
+#if 0
+ rot = m_physics->RetCirMotionY(MO_MOTSPEED);
+ s = m_physics->RetLinMotionX(MO_REASPEED)*2.0f;
+ a = m_physics->RetLinMotionX(MO_TERSPEED);
+ if ( a < 0.0f ) // rises?
+ {
+ if ( s > 0.0f && s < 20.0f ) s = 20.0f; // moving slowly?
+//? if ( s < 0.0f && s > -10.0f ) s = 0.0f; // falling slowly?
+ }
+ if ( a > 0.0f && !bSwim ) // falls?
+ {
+ if ( s > 0.0f && s < 10.0f ) s = 0.0f; // moving slowly?
+//? if ( s < 0.0f && s > -5.0f ) s = -5.0f; // falling slowly?
+ }
+ a = fabs(rot*12.0f);
+
+ if ( !m_physics->RetLand() && !bSwim ) // in flight?
+ {
+ s = 0.0f;
+ }
+
+ if ( m_object->RetFret() != 0 ) // carries something?
+ {
+ s *= 1.3f;
+ }
+#else
+ rot = m_physics->RetCirMotionY(MO_MOTSPEED);
+#if 0
+ s = m_physics->RetLinMotionX(MO_REASPEED);
+#else
+ a = m_physics->RetLinMotionX(MO_REASPEED);
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.2f;
+ if ( fabs(a) > fabs(s) ) s = a; // the highest value
+#endif
+ a = m_physics->RetLinMotionX(MO_TERSPEED);
+ if ( a < 0.0f ) // rises?
+ {
+ a += m_physics->RetLinMotionX(MO_TERSLIDE);
+ if ( a < 0.0f ) s -= a;
+ }
+ if ( a > 0.0f ) // falls?
+ {
+ a -= m_physics->RetLinMotionX(MO_TERSLIDE);
+ if ( a > 0.0f ) s -= a;
+ }
+ s *= 2.0f;
+ a = fabs(rot*12.0f);
+
+ if ( !m_physics->RetLand() && !bSwim ) // in flight?
+ {
+ s = 0.0f;
+ }
+
+ if ( m_object->RetFret() != 0 ) // carries something?
+ {
+ s *= 1.3f;
+ }
+#endif
+
+ m_time += event.rTime;
+ m_armTimeAbs += event.rTime;
+ m_armTimeAction += event.rTime;
+ m_armMember += s*event.rTime*0.05f;
+
+ // Fatigue management when short.
+ if ( m_physics->RetLand() && s != 0.0f ) // on the ground?
+ {
+ m_tired += event.rTime*0.1f;
+ if ( m_tired > 1.0f )
+ {
+ m_tired = 1.0f;
+ if ( m_lastSoundHhh > 3.0f ) m_lastSoundHhh = 0.5f;
+ }
+ }
+ else
+ {
+ m_tired -= event.rTime*0.2f;
+ if ( m_tired < 0.0f ) m_tired = 0.0f;
+ }
+
+ if ( bSwim ) // swims?
+ {
+ s += fabs(m_physics->RetLinMotionY(MO_REASPEED)*2.0f);
+ a *= 2.0f;
+ m_armTimeSwim += Math::Min(Math::Max(s,a,3.0f),15.0f)*event.rTime*0.05f;
+ }
+
+ bStop = ( s == 0.0f ); // stop?
+ prog = 0.0f;
+
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ if ( s == 0.0f && a == 0.0f )
+ {
+ action = MH_STOP; // stop
+ rTime[0] = rTime[1] = m_armTimeAbs*0.21f;
+ lTime[0] = lTime[1] = m_armTimeAbs*0.25f;
+ m_armMember = START_TIME;
+ }
+ else
+ {
+ if ( s == 0.0f )
+ {
+ action = MH_TURN; // turn
+ rTime[0] = rTime[1] = m_armTimeAbs;
+ lTime[0] = lTime[1] = m_armTimeAbs+0.5f;
+ if ( rot < 0.0f )
+ {
+ rTime[1] = 1000000.0f-rTime[1];
+ }
+ else
+ {
+ lTime[1] = 1000000.0f-lTime[1];
+ }
+ m_armMember = START_TIME;
+ }
+ else
+ {
+ action = MH_MARCH; // walking
+ if ( m_object->RetFret() != 0 ) action = MH_MARCHTAKE; // take walking
+ rTime[0] = rTime[1] = m_armMember;
+ lTime[0] = lTime[1] = m_armMember+0.5f;
+ }
+ }
+ if ( bSwim )
+ {
+ rTime[0] *= 0.6f;
+ rTime[1] *= 0.6f;
+ lTime[0] = rTime[0]+0.5f;
+ lTime[1] = rTime[1]+0.5f;
+ }
+ }
+ else
+ {
+ if ( bSwim )
+ {
+ action = MH_SWIM; // swim
+ rTime[0] = rTime[1] = m_armTimeSwim;
+ lTime[0] = lTime[1] = m_armTimeSwim;
+ }
+ else
+ {
+ action = MH_FLY; // fly
+ rTime[0] = rTime[1] = m_armTimeAbs*0.30f;
+ lTime[0] = lTime[1] = m_armTimeAbs*0.31f;
+ m_armMember = START_TIME;
+ }
+ }
+
+ if ( action != m_armLastAction )
+ {
+ m_armLastAction = action;
+ m_armTimeAction = 0.0f;
+ }
+
+ armAction = action;
+ legAction = action;
+
+ if ( m_object->RetFret() != 0 ) // carries something?
+ {
+ armAction = MH_MARCHTAKE; // take walking
+ }
+
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ a = m_object->RetAngleY(0);
+ pos = m_object->RetPosition(0);
+ m_terrain->MoveOnFloor(pos);
+
+ pf.x = pos.x+cosf(a+Math::PI*1.5f)*0.7f;
+ pf.y = pos.y;
+ pf.z = pos.z-sinf(a+Math::PI*1.5f)*0.7f;
+ m_terrain->MoveOnFloor(pf);
+ al = atanf((pf.y-pos.y)/0.7f); // angle for left leg
+
+ pf = pos;
+ pf.x = pos.x+cosf(a+Math::PI*0.5f)*0.7f;
+ pf.y = pos.y;
+ pf.z = pos.z-sinf(a+Math::PI*0.5f)*0.7f;
+ m_terrain->MoveOnFloor(pf);
+ ar = atanf((pf.y-pos.y)/0.7f); // angle to right leg
+
+ pf.x = pos.x+cosf(a+Math::PI)*0.3f;
+ pf.y = pos.y;
+ pf.z = pos.z-sinf(a+Math::PI)*0.3f;
+ m_terrain->MoveOnFloor(pf);
+ af = atanf((pf.y-pos.y)/0.3f); // angle for feet
+ }
+ else
+ {
+ al = 0.0f;
+ ar = 0.0f;
+ af = 0.0f;
+ }
+
+ for ( i=0 ; i<4 ; i++ ) // 4 members
+ {
+ if ( m_bArmStop ) // focus?
+ {
+ st = ADJUST_ACTION + (i%2)*3;
+ nd = st;
+ time = 100.0f;
+ m_armTimeAction = 0.0f;
+ }
+ else if ( m_actionType != -1 ) // special action in progress?
+ {
+ st = 3*3*3*3*MH_SPEC + 3*3*3*m_actionType + (i%2)*3;
+ nd = st;
+ time = event.rTime*m_actionTime;
+ m_armTimeAction = 0.0f;
+ }
+ else
+ {
+ if ( i < 2 ) prog = Math::Mod(rTime[i%2], 1.0f);
+ else prog = Math::Mod(lTime[i%2], 1.0f);
+ if ( prog < 0.25f ) // t0..t1 ?
+ {
+ prog = prog/0.25f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.75f ) // t1..t2 ?
+ {
+ prog = (prog-0.25f)/0.50f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.75f)/0.25f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ if ( i%2 == 0 ) // arm?
+ {
+ st = 3*3*3*3*armAction + st*3*3*3 + (i%2)*3;
+ nd = 3*3*3*3*armAction + nd*3*3*3 + (i%2)*3;
+ }
+ else // leg?
+ {
+ st = 3*3*3*3*legAction + st*3*3*3 + (i%2)*3;
+ nd = 3*3*3*3*legAction + nd*3*3*3 + (i%2)*3;
+ }
+
+ // Less soft ...
+ time = event.rTime*(5.0f+Math::Min(m_armTimeAction*50.0f, 100.0f));
+ if ( bSwim ) time *= 0.25f;
+ }
+
+ tSt[0] = m_armAngles[st+ 0]; // x
+ tSt[1] = m_armAngles[st+ 1]; // y
+ tSt[2] = m_armAngles[st+ 2]; // z
+ tSt[3] = m_armAngles[st+ 9]; // x
+ tSt[4] = m_armAngles[st+10]; // y
+ tSt[5] = m_armAngles[st+11]; // z
+ tSt[6] = m_armAngles[st+18]; // x
+ tSt[7] = m_armAngles[st+19]; // y
+ tSt[8] = m_armAngles[st+20]; // z
+
+ tNd[0] = m_armAngles[nd+ 0]; // x
+ tNd[1] = m_armAngles[nd+ 1]; // y
+ tNd[2] = m_armAngles[nd+ 2]; // z
+ tNd[3] = m_armAngles[nd+ 9]; // x
+ tNd[4] = m_armAngles[nd+10]; // y
+ tNd[5] = m_armAngles[nd+11]; // z
+ tNd[6] = m_armAngles[nd+18]; // x
+ tNd[7] = m_armAngles[nd+19]; // y
+ tNd[8] = m_armAngles[nd+20]; // z
+
+ aa = 0.5f;
+ if ( i%2 == 0 ) // arm?
+ {
+ if ( m_object->RetFret() == 0 ) // does nothing?
+ {
+ aa = 2.0f; // moves a lot
+ }
+ else
+ {
+ aa = 0.0f; // immobile
+ }
+ }
+
+ if ( i < 2 ) // left?
+ {
+ bb = sinf(m_time*1.1f)*aa; tSt[0] += bb; tNd[0] += bb;
+ bb = sinf(m_time*1.0f)*aa; tSt[1] += bb; tNd[1] += bb;
+ bb = sinf(m_time*1.2f)*aa; tSt[2] += bb; tNd[2] += bb;
+ bb = sinf(m_time*2.5f)*aa; tSt[3] += bb; tNd[3] += bb;
+ bb = sinf(m_time*2.0f)*aa; tSt[4] += bb; tNd[4] += bb;
+ bb = sinf(m_time*3.8f)*aa; tSt[5] += bb; tNd[5] += bb;
+ bb = sinf(m_time*3.0f)*aa; tSt[6] += bb; tNd[6] += bb;
+ bb = sinf(m_time*2.3f)*aa; tSt[7] += bb; tNd[7] += bb;
+ bb = sinf(m_time*4.0f)*aa; tSt[8] += bb; tNd[8] += bb;
+ }
+ else // right?
+ {
+ bb = sinf(m_time*0.9f)*aa; tSt[0] += bb; tNd[0] += bb;
+ bb = sinf(m_time*1.2f)*aa; tSt[1] += bb; tNd[1] += bb;
+ bb = sinf(m_time*1.4f)*aa; tSt[2] += bb; tNd[2] += bb;
+ bb = sinf(m_time*2.9f)*aa; tSt[3] += bb; tNd[3] += bb;
+ bb = sinf(m_time*1.4f)*aa; tSt[4] += bb; tNd[4] += bb;
+ bb = sinf(m_time*3.1f)*aa; tSt[5] += bb; tNd[5] += bb;
+ bb = sinf(m_time*3.7f)*aa; tSt[6] += bb; tNd[6] += bb;
+ bb = sinf(m_time*2.0f)*aa; tSt[7] += bb; tNd[7] += bb;
+ bb = sinf(m_time*3.1f)*aa; tSt[8] += bb; tNd[8] += bb;
+ }
+
+#if 1
+ if ( i%2 == 1 && // leg?
+ m_actionType == -1 ) // no special action?
+ {
+ if ( i == 1 ) // right leg?
+ {
+ ii = 5;
+ a = ar*0.25f;
+ }
+ else
+ {
+ ii = 11;
+ a = al*0.25f;
+ }
+ if ( a < -0.2f ) a = -0.2f;
+ if ( a > 0.2f ) a = 0.2f;
+
+ pos = m_object->RetPosition(ii+0);
+ pos.y = 0.0f+a;
+ m_object->SetPosition(ii+0, pos); // lengthens / shortcuts thigh
+
+ pos = m_object->RetPosition(ii+1);
+ pos.y = -1.5f+a;
+ m_object->SetPosition(ii+1, pos); // lengthens / shortcuts leg
+
+ pos = m_object->RetPosition(ii+2);
+ pos.y = -1.5f+a;
+ m_object->SetPosition(ii+2, pos); // lengthens / shortcuts foot
+
+ if ( i == 1 ) // right leg?
+ {
+ aa = (ar*180.0f/Math::PI*0.5f);
+ }
+ else // left leg?
+ {
+ aa = (al*180.0f/Math::PI*0.5f);
+ }
+ tSt[6] += aa;
+ tNd[6] += aa; // increases the angle X of the foot
+
+ if ( i == 1 ) // right leg?
+ {
+ aa = (ar*180.0f/Math::PI);
+ }
+ else // left leg?
+ {
+ aa = (al*180.0f/Math::PI);
+ }
+ if ( aa < 0.0f ) aa = 0.0f;
+ if ( aa > 30.0f ) aa = 30.0f;
+
+ tSt[2] += aa;
+ tNd[2] += aa; // increases the angle Z of the thigh
+ tSt[5] -= aa*2;
+ tNd[5] -= aa*2; // increases the angle Z of the leg
+ tSt[8] += aa;
+ tNd[8] += aa; // increases the angle Z of the foot
+
+ aa = (af*180.0f/Math::PI)*0.7f;
+ if ( aa < -30.0f ) aa = -30.0f;
+ if ( aa > 30.0f ) aa = 30.0f;
+
+ tSt[8] -= aa;
+ tNd[8] -= aa; // increases the angle Z of the foot
+ }
+#endif
+
+ if ( m_actionType == MHS_DEADw ) // drowned?
+ {
+ if ( m_progress < 0.5f )
+ {
+ deadFactor = m_progress/0.5f;
+ }
+ else
+ {
+ deadFactor = 1.0f-(m_progress-0.5f)/0.5f;
+ }
+ if ( deadFactor < 0.0f ) deadFactor = 0.0f;
+ if ( deadFactor > 1.0f ) deadFactor = 1.0f;
+
+ for ( ii=0 ; ii<9 ; ii++ )
+ {
+ tSt[ii] += Math::Rand()*20.0f*deadFactor;
+ tNd[ii] = tSt[ii];
+ }
+ time = 100.0f;
+ }
+
+ if ( i < 2 ) // right member (0..1) ?
+ {
+ m_object->SetAngleX(2+3*i+0, Math::Smooth(m_object->RetAngleX(2+3*i+0), Math::PropAngle(tSt[0], tNd[0], prog), time));
+ m_object->SetAngleY(2+3*i+0, Math::Smooth(m_object->RetAngleY(2+3*i+0), Math::PropAngle(tSt[1], tNd[1], prog), time));
+ m_object->SetAngleZ(2+3*i+0, Math::Smooth(m_object->RetAngleZ(2+3*i+0), Math::PropAngle(tSt[2], tNd[2], prog), time));
+ m_object->SetAngleX(2+3*i+1, Math::Smooth(m_object->RetAngleX(2+3*i+1), Math::PropAngle(tSt[3], tNd[3], prog), time));
+ m_object->SetAngleY(2+3*i+1, Math::Smooth(m_object->RetAngleY(2+3*i+1), Math::PropAngle(tSt[4], tNd[4], prog), time));
+ m_object->SetAngleZ(2+3*i+1, Math::Smooth(m_object->RetAngleZ(2+3*i+1), Math::PropAngle(tSt[5], tNd[5], prog), time));
+ m_object->SetAngleX(2+3*i+2, Math::Smooth(m_object->RetAngleX(2+3*i+2), Math::PropAngle(tSt[6], tNd[6], prog), time));
+ m_object->SetAngleY(2+3*i+2, Math::Smooth(m_object->RetAngleY(2+3*i+2), Math::PropAngle(tSt[7], tNd[7], prog), time));
+ m_object->SetAngleZ(2+3*i+2, Math::Smooth(m_object->RetAngleZ(2+3*i+2), Math::PropAngle(tSt[8], tNd[8], prog), time));
+ }
+ else // left member (2..3) ?
+ {
+ m_object->SetAngleX(2+3*i+0, Math::Smooth(m_object->RetAngleX(2+3*i+0), Math::PropAngle(-tSt[0], -tNd[0], prog), time));
+ m_object->SetAngleY(2+3*i+0, Math::Smooth(m_object->RetAngleY(2+3*i+0), Math::PropAngle(-tSt[1], -tNd[1], prog), time));
+ m_object->SetAngleZ(2+3*i+0, Math::Smooth(m_object->RetAngleZ(2+3*i+0), Math::PropAngle( tSt[2], tNd[2], prog), time));
+ m_object->SetAngleX(2+3*i+1, Math::Smooth(m_object->RetAngleX(2+3*i+1), Math::PropAngle(-tSt[3], -tNd[3], prog), time));
+ m_object->SetAngleY(2+3*i+1, Math::Smooth(m_object->RetAngleY(2+3*i+1), Math::PropAngle(-tSt[4], -tNd[4], prog), time));
+ m_object->SetAngleZ(2+3*i+1, Math::Smooth(m_object->RetAngleZ(2+3*i+1), Math::PropAngle( tSt[5], tNd[5], prog), time));
+ m_object->SetAngleX(2+3*i+2, Math::Smooth(m_object->RetAngleX(2+3*i+2), Math::PropAngle(-tSt[6], -tNd[6], prog), time));
+ m_object->SetAngleY(2+3*i+2, Math::Smooth(m_object->RetAngleY(2+3*i+2), Math::PropAngle(-tSt[7], -tNd[7], prog), time));
+ m_object->SetAngleZ(2+3*i+2, Math::Smooth(m_object->RetAngleZ(2+3*i+2), Math::PropAngle( tSt[8], tNd[8], prog), time));
+ }
+ }
+
+#if ADJUST_ANGLE
+ if ( m_object->RetSelect() )
+ {
+ char s[100];
+ sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
+ m_engine->SetInfoText(4, s);
+ }
+#endif
+
+ // calculates the height lowering as a function
+ // of the position of the legs.
+ hr = 1.5f*(1.0f-cosf(m_object->RetAngleZ(5))) +
+ 1.5f*(1.0f-cosf(m_object->RetAngleZ(5)+m_object->RetAngleZ(6)));
+ a = 1.0f*sinf(m_object->RetAngleZ(5)+m_object->RetAngleZ(6)+m_object->RetAngleZ(7));
+ if ( a < 0.0f ) hr += a;
+
+ hl = 1.5f*(1.0f-cosf(m_object->RetAngleZ(11))) +
+ 1.5f*(1.0f-cosf(m_object->RetAngleZ(11)+m_object->RetAngleZ(12)));
+ a = 1.0f*sinf(m_object->RetAngleZ(11)+m_object->RetAngleZ(12)+m_object->RetAngleZ(13));
+ if ( a < 0.0f ) hl += a;
+
+ hr = Math::Min(hr, hl);
+
+ if ( m_actionType == MHS_FIRE ) // shooting?
+ {
+ time = event.rTime*m_actionTime;
+
+ dir.x = (Math::Rand()-0.5f)/8.0f;
+ dir.z = (Math::Rand()-0.5f)/8.0f;
+ dir.y = -0.5f; // slightly lower
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+//? dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.y = -hr;
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = (Math::Rand()-0.5f)/3.0f;
+ dir.z = -0.1f; // slightly leaning forward
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_TAKE || // carrying?
+ m_actionType == MHS_TAKEOTHER ) // flag?
+ {
+ time = event.rTime*m_actionTime*2.0f;
+
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = -1.5f; // slightly lower
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+//? dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.y = -hr;
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = -0.2f;
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_TAKEHIGH ) // carrying?
+ {
+ time = event.rTime*m_actionTime*2.0f;
+
+ dir.x = 0.4f; // slightly forward
+ dir.z = 0.0f;
+ dir.y = 0.0f;
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+//? dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.y = -hr;
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = -0.2f;
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_FLAG ) // flag?
+ {
+ time = event.rTime*m_actionTime*2.0f;
+
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = -2.0f; // slightly lower
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+//? dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.y = -hr;
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = -0.4f;
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_DEADg ) // shooting death (falls)?
+ {
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ SetAction(MHS_DEADg1, 0.5f); // knees
+ }
+ }
+ else if ( m_actionType == MHS_DEADg1 ) // shooting death (knees)?
+ {
+ prog = m_progress;
+ if ( prog >= 1.0f )
+ {
+ prog = 1.0f;
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*4.0f;
+ pos.z += (Math::Rand()-0.5f)*4.0f;
+ m_terrain->MoveOnFloor(pos);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 1.2f+Math::Rand()*1.2f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f);
+ }
+ m_sound->Play(SOUND_BOUMv, m_object->RetPosition(0));
+
+ SetAction(MHS_DEADg2, 1.0f); // expects knees
+ }
+
+ time = 100.0f;
+
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = -1.5f*prog;
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = -(20.0f*Math::PI/180.0f)*prog;
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_DEADg2 ) // shooting death (knees)?
+ {
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(MHS_DEADg3, 1.0f); // face down
+ }
+
+ time = 100.0f;
+
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = -1.5f;
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = -(20.0f*Math::PI/180.0f);
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_DEADg3 ) // shooting death (face down)?
+ {
+ prog = m_progress;
+ if ( prog >= 1.0f )
+ {
+ prog = 1.0f;
+
+ for ( i=0 ; i<20 ; i++ )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*8.0f;
+ pos.z += (Math::Rand()-0.5f)*8.0f;
+ m_terrain->MoveOnFloor(pos);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 2.0f+Math::Rand()*1.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f);
+ }
+ m_sound->Play(SOUND_BOUMv, m_object->RetPosition(0));
+
+ SetAction(MHS_DEADg4, 3.0f); // expects face down
+ }
+
+ time = 100.0f;
+ prog = powf(prog, 3.0f);
+
+ dir.y = -(1.5f+1.5f*prog);
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.z = -((20.0f*Math::PI/180.0f)+(70.0f*Math::PI/180.0f)*prog);
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_DEADg4 ) // shooting death (face down)?
+ {
+ if ( m_progress >= 1.0f )
+ {
+ m_object->SetEnable(false);
+ }
+
+ time = 100.0f;
+
+ dir.y = -(1.5f+1.5f);
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetLinVibration(dir);
+
+ dir.z = -((20.0f*Math::PI/180.0f)+(70.0f*Math::PI/180.0f));
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+ }
+ else if ( m_actionType == MHS_DEADw ) // drowned?
+ {
+ pos = m_object->RetPosition(0);
+ level = m_water->RetLevel()-0.5f;
+ if ( pos.y < level )
+ {
+ pos.y += 4.0f*event.rTime; // back to the surface
+ if ( pos.y > level ) pos.y = level;
+ m_object->SetPosition(0, pos);
+ }
+ if ( pos.y > level )
+ {
+ pos.y -= 10.0f*event.rTime; // down quickly
+ if ( pos.y < level ) pos.y = level;
+ m_object->SetPosition(0, pos);
+ }
+
+ prog = m_progress;
+ if ( prog >= 1.0f )
+ {
+ prog = 1.0f;
+ if ( pos.y >= level ) m_object->SetEnable(false);
+ }
+
+ prog *= 2.0f;
+ if ( prog > 1.0f ) prog = 1.0f;
+
+ time = 100.0f;
+
+ dir.z = -(90.0f*Math::PI/180.0f)*prog;
+ dir.x = Math::Rand()*0.3f*deadFactor;
+ dir.y = Math::Rand()*0.3f*deadFactor;
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ m_object->SetInclinaison(dir);
+
+ m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ }
+ else if ( m_actionType == MHS_LOST ) // lost?
+ {
+ time = m_time;
+ if ( time < 10.0f ) time *= time/10.0f; // starts slowly
+
+ dir.x = time*2.0f;
+ dir.y = sinf(m_time*0.8f)*0.8f;
+ dir.z = sinf(m_time*0.6f)*0.5f;
+ m_object->SetInclinaison(dir);
+ SetInclinaison(dir);
+
+//? dir.x = -(sinf(time*0.05f+Math::PI*1.5f)+1.0f)*100.0f;
+ // original code: Math::Min(time/30.0f) (?) changed to time/30.0f
+ dir.x = -(powf(time/30.0f, 4.0f))*1000.0f; // from the distance
+ dir.y = 0.0f;
+ dir.z = 0.0f;
+ m_object->SetLinVibration(dir);
+ SetLinVibration(dir);
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(0.5f, 3.7f, 0.0f);
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.y += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ pos = Transform(*mat, pos);
+ speed.x = (Math::Rand()-0.5f)*0.5f;
+ speed.y = (Math::Rand()-0.5f)*0.5f;
+ speed.z = (Math::Rand()-0.5f)*0.5f;
+ dim.x = 0.5f+Math::Rand()*0.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTILENS1, 5.0f, 0.0f, 0.0f);
+ }
+ else if ( m_actionType == MHS_SATCOM ) // look at the SatCom?
+ {
+ SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ SetLinVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
+ }
+ else
+ {
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ time = event.rTime*8.0f;
+ if ( bSwim ) time *= 0.25f;
+
+ if ( action == MH_MARCH ) // walking?
+ {
+ dir.x = sinf(Math::Mod(rTime[0]+0.5f, 1.0f)*Math::PI*2.0f)*0.10f;
+ dir.y = sinf(Math::Mod(rTime[0]+0.6f, 1.0f)*Math::PI*2.0f)*0.20f;
+ s = m_physics->RetLinMotionX(MO_REASPEED)*0.03f;
+ }
+ else if ( action == MH_MARCHTAKE ) // takes walking?
+ {
+ dir.x = sinf(Math::Mod(rTime[0]+0.5f, 1.0f)*Math::PI*2.0f)*0.10f;
+ dir.y = sinf(Math::Mod(rTime[0]+0.6f, 1.0f)*Math::PI*2.0f)*0.15f;
+ s = m_physics->RetLinMotionX(MO_REASPEED)*0.02f;
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ s = m_physics->RetLinMotionX(MO_REASPEED)*0.03f;
+ }
+
+ if ( s < 0.0f ) s *= 0.5f;
+ dir.z = -s*0.7f;
+
+ actual = m_object->RetInclinaison();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ dir.y = Math::Smooth(actual.y, dir.y, time);
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ if ( bOnBoard ) dir *= 0.3f;
+ m_object->SetInclinaison(dir);
+ SetInclinaison(dir);
+
+ if ( action == MH_MARCH ) // walking?
+ {
+ p2.x = 0.0f;
+ p2.y = sinf(Math::Mod(rTime[0]+0.5f, 1.0f)*Math::PI*2.0f)*0.5f;
+ p2 = Math::RotatePoint(-m_object->RetAngleY(0), p2);
+ dir.x = p2.x;
+ dir.z = p2.y;
+ dir.y = sinf(Math::Mod(rTime[0]*2.0f, 1.0f)*Math::PI*2.0f)*0.3f;
+ }
+ else if ( action == MH_MARCHTAKE ) // takes walking?
+ {
+ p2.x = 0.0f;
+ p2.y = sinf(Math::Mod(rTime[0]+0.5f, 1.0f)*Math::PI*2.0f)*0.25f;
+ p2 = Math::RotatePoint(-m_object->RetAngleY(0), p2);
+ dir.x = p2.x;
+ dir.z = p2.y;
+ dir.y = sinf(Math::Mod(rTime[0]*2.0f, 1.0f)*Math::PI*2.0f)*0.05f-0.3f;
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = 0.0f;
+ }
+
+ actual = m_object->RetLinVibration();
+ dir.x = Math::Smooth(actual.x, dir.x, time);
+ if ( action == MH_MARCHTAKE ) // takes walking?
+ {
+ dir.y = -hr;
+ }
+ else
+ {
+ s = Math::Min(m_armTimeAction, 1.0f);
+ dir.y = Math::Smooth(actual.y, dir.y, time)*s;
+ dir.y += -hr*(1.0f-s);
+ }
+ dir.z = Math::Smooth(actual.z, dir.z, time);
+ if ( bOnBoard ) dir *= 0.3f;
+ m_object->SetLinVibration(dir);
+
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ dir.y = 0.0f;
+ SetCirVibration(dir);
+ }
+ }
+
+ // Management of the head.
+ if ( m_actionType == MHS_TAKE || // takes?
+ m_actionType == MHS_FLAG ) // takes?
+ {
+ m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f-0.6f, event.rTime*5.0f));
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f);
+ m_object->SetAngleY(1, Math::Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f));
+ }
+ else if ( m_actionType == MHS_TAKEOTHER || // takes?
+ m_actionType == MHS_TAKEHIGH ) // takes?
+ {
+ m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f-0.3f, event.rTime*5.0f));
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f);
+ m_object->SetAngleY(1, Math::Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f));
+ }
+ else if ( m_actionType == MHS_WIN ) // win
+ {
+ float factor = 0.6f+(sinf(m_armTimeAbs*0.5f)*0.40f);
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*5.0f)*0.20f*factor);
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*0.6f)*0.10f);
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*1.5f)*0.15f);
+ }
+ else if ( m_actionType == MHS_LOST ) // lost?
+ {
+ float factor = 0.6f+(sinf(m_armTimeAbs*0.5f)*0.40f);
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*0.6f)*0.10f);
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*0.7f)*0.10f);
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*3.0f)*0.30f*factor);
+ }
+ else if ( m_object->RetDead() ) // dead?
+ {
+ }
+ else
+ {
+ m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), sinf(m_armTimeAbs*1.0f)*0.2f, event.rTime*5.0f));
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.1f)*0.1f);
+ m_object->SetAngleY(1, Math::Smooth(m_object->RetAngleY(1), sinf(m_armTimeAbs*1.3f)*0.2f+rot*0.3f, event.rTime*5.0f));
+ }
+
+ if ( bOnBoard )
+ {
+ m_object->SetAngleZ(1, 0.0f);
+ m_object->SetAngleX(1, 0.0f);
+ m_object->SetAngleY(1, 0.0f);
+ }
+
+ // Steps sound effects.
+ if ( legAction == MH_MARCH ||
+ legAction == MH_MARCHTAKE )
+ {
+ Sound sound[2];
+ float speed, synchro, volume[2], freq[2], hard, level;
+
+ speed = m_physics->RetLinMotionX(MO_REASPEED);
+
+ if ( m_object->RetFret() == 0 )
+ {
+ if ( speed > 0.0f ) synchro = 0.21f; // synchro forward
+ else synchro = 0.29f; // synchro backward
+ }
+ else
+ {
+ if ( speed > 0.0f ) synchro = 0.15f; // synchro forward
+ else synchro = 0.35f; // synchro backward
+ }
+ time = rTime[1]+synchro;
+
+ if ( fabs(m_lastSoundMarch-time) > 0.4f &&
+ Math::Mod(time, 0.5f) < 0.1f )
+ {
+ volume[0] = 0.5f;
+ freq[0] = 1.0f;
+ if ( m_object->RetFret() != 0 )
+ {
+//? volume[0] *= 2.0f;
+ freq[0] = 0.7f;
+ }
+ volume[1] = volume[0];
+ freq[1] = freq[0];
+ sound[0] = SOUND_CLICK;
+ sound[1] = SOUND_CLICK;
+
+ pos = m_object->RetPosition(0);
+
+ level = m_water->RetLevel();
+ if ( pos.y <= level+3.0f ) // underwater?
+ {
+ sound[0] = SOUND_STEPw;
+ }
+ else
+ {
+ hard = m_terrain->RetHardness(pos);
+
+ if ( hard >= 0.875 )
+ {
+ sound[0] = SOUND_STEPm; // metal
+ }
+ else
+ {
+ hard /= 0.875;
+ sound[0] = SOUND_STEPs; // smooth
+ sound[1] = SOUND_STEPh; // hard
+
+ volume[0] *= 1.0f-hard;
+ volume[1] *= hard;
+ if ( hard < 0.5f )
+ {
+ volume[0] *= 1.0f+hard*2.0f;
+ volume[1] *= 1.0f+hard*2.0f;
+ }
+ else
+ {
+ volume[0] *= 3.0f-hard*2.0f;
+ volume[1] *= 3.0f-hard*2.0f;
+ }
+ freq[0] *= 1.0f+hard;
+ freq[1] *= 0.5f+hard;
+ }
+ }
+
+ if ( sound[0] != SOUND_CLICK )
+ {
+ m_sound->Play(sound[0], pos, volume[0], freq[0]);
+ }
+ if ( sound[1] != SOUND_CLICK )
+ {
+ m_sound->Play(sound[1], pos, volume[1], freq[1]);
+ }
+ m_lastSoundMarch = time;
+ }
+ }
+
+ if ( legAction == MH_SWIM )
+ {
+ time = rTime[0]+0.5f;
+
+ if ( fabs(m_lastSoundMarch-time) > 0.9f &&
+ Math::Mod(time, 1.0f) < 0.1f )
+ {
+ m_sound->Play(SOUND_SWIM, m_object->RetPosition(0), 0.5f);
+ m_lastSoundMarch = time;
+ }
+ }
+
+ m_lastSoundHhh -= event.rTime;
+ if ( m_lastSoundHhh <= 0.0f &&
+ m_object->RetSelect() &&
+ m_object->RetOption() == 0 ) // helmet?
+ {
+ m_sound->Play(SOUND_HUMAN1, m_object->RetPosition(0), (0.5f+m_tired*0.2f));
+ m_lastSoundHhh = (4.0f-m_tired*2.5f)+(4.0f-m_tired*2.5f)*Math::Rand();
+ }
+
+ return true;
+}
+
+
+// Management of the display mode when customizing the personal.
+
+void CMotionHuman::StartDisplayPerso()
+{
+ m_bDisplayPerso = true;
+}
+
+void CMotionHuman::StopDisplayPerso()
+{
+ m_bDisplayPerso = false;
+}
+
+
diff --git a/src/object/motion/motionhuman.h b/src/object/motion/motionhuman.h
index ab7b0f9..b365a77 100644
--- a/src/object/motion/motionhuman.h
+++ b/src/object/motion/motionhuman.h
@@ -1,94 +1,94 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionhuman.h
-
-#pragma once
-
-
-#include "object/motion/motion.h"
-
-
-
-enum MotionHumanAction
-{
- MH_MARCH = 0,
- MH_MARCHTAKE = 1,
- MH_TURN = 2,
- MH_STOP = 3,
- MH_FLY = 4,
- MH_SWIM = 5,
- MH_SPEC = 6
-};
-
-enum MotionHumanSpecialAction
-{
- MHS_FIRE = 0,
- MHS_GUN = 1,
- MHS_TAKE = 2,
- MHS_TAKEOTHER = 3,
- MHS_TAKEHIGH = 4,
- MHS_UPRIGHT = 5,
- MHS_WIN = 6,
- MHS_LOST = 7,
- MHS_DEADg = 8,
- MHS_DEADg1 = 9,
- MHS_DEADg2 = 10,
- MHS_DEADg3 = 11,
- MHS_DEADg4 = 12,
- MHS_DEADw = 13,
- MHS_FLAG = 14,
- MHS_SATCOM = 15
-};
-
-
-class CMotionHuman : public CMotion
-{
-public:
- CMotionHuman(CInstanceManager* iMan, CObject* object);
- ~CMotionHuman();
-
- void DeleteObject(bool bAll=false);
- bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- bool EventProcess(const Event &event);
- Error SetAction(int action, float time=0.2f);
-
- void StartDisplayPerso();
- void StopDisplayPerso();
-
-protected:
- void CreatePhysics(ObjectType type);
- bool EventFrame(const Event &event);
-
-protected:
- int m_partiReactor;
- float m_armMember;
- float m_armTimeAbs;
- float m_armTimeAction;
- float m_armTimeSwim;
- short m_armAngles[3*3*3*3*7 + 3*3*3*16];
- int m_armTimeIndex;
- int m_armPartIndex;
- int m_armMemberIndex;
- int m_armLastAction;
- bool m_bArmStop;
- float m_lastSoundMarch;
- float m_lastSoundHhh;
- float m_time;
- float m_tired;
- bool m_bDisplayPerso;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionhuman.h
+
+#pragma once
+
+
+#include "object/motion/motion.h"
+
+
+
+enum MotionHumanAction
+{
+ MH_MARCH = 0,
+ MH_MARCHTAKE = 1,
+ MH_TURN = 2,
+ MH_STOP = 3,
+ MH_FLY = 4,
+ MH_SWIM = 5,
+ MH_SPEC = 6
+};
+
+enum MotionHumanSpecialAction
+{
+ MHS_FIRE = 0,
+ MHS_GUN = 1,
+ MHS_TAKE = 2,
+ MHS_TAKEOTHER = 3,
+ MHS_TAKEHIGH = 4,
+ MHS_UPRIGHT = 5,
+ MHS_WIN = 6,
+ MHS_LOST = 7,
+ MHS_DEADg = 8,
+ MHS_DEADg1 = 9,
+ MHS_DEADg2 = 10,
+ MHS_DEADg3 = 11,
+ MHS_DEADg4 = 12,
+ MHS_DEADw = 13,
+ MHS_FLAG = 14,
+ MHS_SATCOM = 15
+};
+
+
+class CMotionHuman : public CMotion
+{
+public:
+ CMotionHuman(CInstanceManager* iMan, CObject* object);
+ ~CMotionHuman();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ bool EventProcess(const Event &event);
+ Error SetAction(int action, float time=0.2f);
+
+ void StartDisplayPerso();
+ void StopDisplayPerso();
+
+protected:
+ void CreatePhysics(ObjectType type);
+ bool EventFrame(const Event &event);
+
+protected:
+ int m_partiReactor;
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeAction;
+ float m_armTimeSwim;
+ short m_armAngles[3*3*3*3*7 + 3*3*3*16];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ bool m_bArmStop;
+ float m_lastSoundMarch;
+ float m_lastSoundHhh;
+ float m_time;
+ float m_tired;
+ bool m_bDisplayPerso;
+};
+
diff --git a/src/object/motion/motionmother.cpp b/src/object/motion/motionmother.cpp
index 26e28d5..0b783a3 100644
--- a/src/object/motion/motionmother.cpp
+++ b/src/object/motion/motionmother.cpp
@@ -1,524 +1,524 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionmother.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motionmother.h"
-
-#include "old/modfile.h"
-#include "physics/physics.h"
-
-
-
-#define ADJUST_ANGLE false // true -> adjusts the angles of the members
-const float START_TIME = 1000.0f; // beginning of the relative time
-
-
-
-// Object's constructor.
-
-CMotionMother::CMotionMother(CInstanceManager* iMan, CObject* object)
- : CMotion(iMan, object)
-{
- m_armMember = START_TIME;
- m_armTimeAbs = START_TIME;
- m_armTimeMarch = START_TIME;
- m_armTimeAction = START_TIME;
- m_armTimeIndex = 0;
- m_armPartIndex = 0;
- m_armMemberIndex = 0;
- m_armLastAction = -1;
- m_specAction = -1;
- m_bArmStop = false;
-}
-
-// Object's destructor.
-
-CMotionMother::~CMotionMother()
-{
-}
-
-
-// Removes an object.
-
-void CMotionMother::DeleteObject(bool bAll)
-{
-}
-
-
-// Creates a vehicle traveling any lands on the ground.
-
-bool CMotionMother::Create(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 2+12+6 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- m_object->SetType(type);
-
- // Creates main base.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
-
- pModFile->ReadModel("objects\\mother1.mod");
- pModFile->CreateEngineObject(rank);
-
- m_object->SetPosition(0, pos);
- m_object->SetAngleY(0, angle);
-
- // A vehicle must have a obligatory collision
- //with a sphere of center (0, y, 0) (see GetCrashSphere).
- m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 20.0f, SOUND_BOUM, 0.20f);
- m_object->SetGlobalSphere(Math::Vector(-2.0f, 10.0f, 0.0f), 25.0f);
-
- // Creates the head.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\mother2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(16.0f, 3.0f, 0.0f));
-
- // Creates a right-back leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\mother3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(-5.0f, -1.0f, -12.0f));
-
- // Creates a right-back foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\mother4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(0.0f, 0.0f, -8.5f));
-
- // Creates a middle-right leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(4, rank);
- m_object->SetObjectParent(4, 0);
- pModFile->ReadModel("objects\\mother3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(4, Math::Vector(3.5f, -1.0f, -12.0f));
-
- // Creates a middle-right foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(5, rank);
- m_object->SetObjectParent(5, 4);
- pModFile->ReadModel("objects\\mother4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(5, Math::Vector(0.0f, 0.0f, -8.5f));
-
- // Creates a right-front leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\mother3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(10.0f, -1.0f, -10.0f));
-
- // Creates a right-front foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 6);
- pModFile->ReadModel("objects\\mother4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, 0.0f, -8.5f));
-
- // Creates a left-back leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 0);
- pModFile->ReadModel("objects\\mother3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(-5.0f, -1.0f, 12.0f));
- m_object->SetAngleY(8, Math::PI);
-
- // Creates a left-back foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(9, rank);
- m_object->SetObjectParent(9, 8);
- pModFile->ReadModel("objects\\mother4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(9, Math::Vector(0.0f, 0.0f, -8.5f));
-
- // Creates a middle-left leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(10, rank);
- m_object->SetObjectParent(10, 0);
- pModFile->ReadModel("objects\\mother3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(10, Math::Vector(3.5f, -1.0f, 12.0f));
- m_object->SetAngleY(10, Math::PI);
-
- // Creates a middle-left foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(11, rank);
- m_object->SetObjectParent(11, 10);
- pModFile->ReadModel("objects\\mother4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(11, Math::Vector(0.0f, 0.0f, -8.5f));
-
- // Creates a left-front leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(12, rank);
- m_object->SetObjectParent(12, 0);
- pModFile->ReadModel("objects\\mother3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(12, Math::Vector(10.0f, -1.0f, 10.0f));
- m_object->SetAngleY(12, Math::PI);
-
- // Creates a left-front foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(13, rank);
- m_object->SetObjectParent(13, 12);
- pModFile->ReadModel("objects\\mother4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(13, Math::Vector(0.0f, 0.0f, -8.5f));
-
- // Creates the right antenna.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(14, rank);
- m_object->SetObjectParent(14, 1);
- pModFile->ReadModel("objects\\mother5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(14, Math::Vector(6.0f, 1.0f, -2.5f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(15, rank);
- m_object->SetObjectParent(15, 14);
- pModFile->ReadModel("objects\\mother6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(15, Math::Vector(8.0f, 0.0f, 0.0f));
-
- // Creates the left antenna.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(16, rank);
- m_object->SetObjectParent(16, 1);
- pModFile->ReadModel("objects\\mother5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(16, Math::Vector(6.0f, 1.0f, 2.5f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(17, rank);
- m_object->SetObjectParent(17, 16);
- pModFile->ReadModel("objects\\mother6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(17, Math::Vector(8.0f, 0.0f, 0.0f));
-
- // Creates the right claw.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(18, rank);
- m_object->SetObjectParent(18, 1);
- pModFile->ReadModel("objects\\mother7.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(18, Math::Vector(-4.0f, -3.5f, -8.0f));
- m_object->SetZoomX(18, 1.2f);
-
- // Creates the left claw.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(19, rank);
- m_object->SetObjectParent(19, 1);
- pModFile->ReadModel("objects\\mother7.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(19, Math::Vector(-4.0f, -3.5f, 8.0f));
- m_object->SetZoomX(19, 1.2f);
-
- m_object->CreateShadowCircle(18.0f, 0.8f);
-
- CreatePhysics();
- m_object->SetFloorHeight(0.0f);
-
- pos = m_object->RetPosition(0);
- m_object->SetPosition(0, pos); // to display the shadows immediately
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-// Creates the physics of the object.
-
-void CMotionMother::CreatePhysics()
-{
- Character* character;
- int i;
-
- int member[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
- 30,30,10, 35,-15,10, 35,-35,10, // t0: legs 1..3
- -80,-45,-35, -115,-40,-35, -90,10,-55, // t0: feet 1..3
- 0,0,0, 0,0,0, 0,0,0, // t0: unused
- // on the ground:
- 15,-5,10, 10,-30,10, 5,-50,10, // t1: legs 1..3
- -90,-15,-15, -110,-55,-35, -75,-75,-30, // t1: feet 1..3
- 0,0,0, 0,0,0, 0,0,0, // t1: unused
- // on the ground back:
- 0,40,10, 5,5,10, 0,-15,10, // t2: legs 1..3
- -45,0,-55, -65,10,-50, -125,-85,-45, // t2: feet 1..3
- 0,0,0, 0,0,0, 0,0,0, // t2: unused
- };
-
- m_physics->SetType(TYPE_ROLLING);
-
- character = m_object->RetCharacter();
- character->wheelFront = 10.0f;
- character->wheelBack = 10.0f;
- character->wheelLeft = 20.0f;
- character->wheelRight = 20.0f;
- character->height = 3.0f;
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 8.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 8.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 30.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 20.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.1f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.1f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 20.0f);
-
- for ( i=0 ; i<3*3*3*3 ; i++ )
- {
- m_armAngles[i] = member[i];
- }
-}
-
-
-// Management of an event.
-
-bool CMotionMother::EventProcess(const Event &event)
-{
- CMotion::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
-#if ADJUST_ANGLE
- int i;
-
- if ( event.param == 'A' ) m_armTimeIndex++;
- if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
-
- if ( event.param == 'Q' ) m_armPartIndex++;
- if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
-
- if ( event.param == 'W' ) m_armMemberIndex++;
- if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
-
- i = m_armMemberIndex*3;
- i += m_armPartIndex*3*3;
- i += m_armTimeIndex*3*3*3;
-//? i += 3*3*3*3;
-
- if ( event.param == 'E' ) m_armAngles[i+0] += 5;
- if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
- if ( event.param == 'R' ) m_armAngles[i+1] += 5;
- if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
- if ( event.param == 'T' ) m_armAngles[i+2] += 5;
- if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
-
- if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
-#endif
- }
-
- return true;
-}
-
-// Management of an event.
-
-bool CMotionMother::EventFrame(const Event &event)
-{
- Math::Vector dir;
- float s, a, prog;
- int i, st, nd;
- bool bStop;
-
- if ( m_engine->RetPause() ) return true;
- if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
-
- s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
- a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*26.0f);
-
- if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
-
- m_armTimeAbs += event.rTime;
- m_armTimeMarch += (s)*event.rTime*0.05f;
- m_armMember += (s+a)*event.rTime*0.05f;
-
- bStop = ( a == 0.0f && s == 0.0f ); // stop?
-
- if ( bStop )
- {
- prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
- a = Math::Mod(m_armMember, 1.0f);
- a = (prog-a)*event.rTime*1.0f; // stop position just pleasantly
- m_armMember += a;
- }
-
- for ( i=0 ; i<6 ; i++ ) // the six legs
- {
- if ( i < 3 ) prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
- else prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
- if ( m_bArmStop )
- {
- prog = (float)m_armTimeIndex/3.0f;
- }
- if ( prog < 0.33f ) // t0..t1 ?
- {
- prog = prog/0.33f; // 0..1
- st = 0; // index start
- nd = 1; // index end
- }
- else if ( prog < 0.67f ) // t1..t2 ?
- {
- prog = (prog-0.33f)/0.33f; // 0..1
- st = 1; // index start
- nd = 2; // index end
- }
- else // t2..t0 ?
- {
- prog = (prog-0.67f)/0.33f; // 0..1
- st = 2; // index start
- nd = 0; // index end
- }
- st = st*27+(i%3)*3;
- nd = nd*27+(i%3)*3;
- if ( i < 3 ) // right leg (1..3) ?
- {
- m_object->SetAngleX(2+2*i+0, Math::PropAngle(m_armAngles[st+ 0], m_armAngles[nd+ 0], prog));
- m_object->SetAngleY(2+2*i+0, Math::PropAngle(m_armAngles[st+ 1], m_armAngles[nd+ 1], prog));
- m_object->SetAngleZ(2+2*i+0, Math::PropAngle(m_armAngles[st+ 2], m_armAngles[nd+ 2], prog));
- m_object->SetAngleX(2+2*i+1, Math::PropAngle(m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
- m_object->SetAngleY(2+2*i+1, Math::PropAngle(m_armAngles[st+10], m_armAngles[nd+10], prog));
- m_object->SetAngleZ(2+2*i+1, Math::PropAngle(m_armAngles[st+11], m_armAngles[nd+11], prog));
- }
- else // left leg (4..6) ?
- {
- m_object->SetAngleX(2+2*i+0, Math::PropAngle( m_armAngles[st+ 0], m_armAngles[nd+ 0], prog));
- m_object->SetAngleY(2+2*i+0, Math::PropAngle(180-m_armAngles[st+ 1], 180-m_armAngles[nd+ 1], prog));
- m_object->SetAngleZ(2+2*i+0, Math::PropAngle( -m_armAngles[st+ 2], -m_armAngles[nd+ 2], prog));
- m_object->SetAngleX(2+2*i+1, Math::PropAngle( m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
- m_object->SetAngleY(2+2*i+1, Math::PropAngle( -m_armAngles[st+10], -m_armAngles[nd+10], prog));
- m_object->SetAngleZ(2+2*i+1, Math::PropAngle( -m_armAngles[st+11], -m_armAngles[nd+11], prog));
- }
- }
-
-#if ADJUST_ANGLE
- if ( m_object->RetSelect() )
- {
- char s[100];
- sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
- m_engine->SetInfoText(4, s);
- }
-#endif
-
- if ( !bStop && !m_object->RetRuin() )
- {
- a = Math::Mod(m_armTimeMarch, 1.0f);
- if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
- else a = 3.0f-4.0f*a; // 1..-1
- dir.x = sinf(a)*0.03f;
-
- s = Math::Mod(m_armTimeMarch/2.0f, 1.0f);
- if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
- else s = 3.0f-4.0f*s; // 1..-1
- dir.z = sinf(s)*0.05f;
-
- dir.y = 0.0f;
- m_object->SetInclinaison(dir);
-
- a = Math::Mod(m_armMember-0.1f, 1.0f);
- if ( a < 0.33f )
- {
- dir.y = -(1.0f-(a/0.33f))*0.3f;
- }
- else if ( a < 0.67f )
- {
- dir.y = 0.0f;
- }
- else
- {
- dir.y = -(a-0.67f)/0.33f*0.3f;
- }
- dir.x = 0.0f;
- dir.z = 0.0f;
- m_object->SetLinVibration(dir);
- }
-
- m_object->SetAngleZ(1, sinf(m_armTimeAbs*0.5f)*0.20f); // head
- m_object->SetAngleX(1, sinf(m_armTimeAbs*0.6f)*0.10f); // head
- m_object->SetAngleY(1, sinf(m_armTimeAbs*0.7f)*0.20f); // head
-
- m_object->SetAngleZ(14, 0.50f);
- m_object->SetAngleZ(16, 0.50f);
- m_object->SetAngleY(14, 0.80f+sinf(m_armTimeAbs*1.1f)*0.53f); // right antenna
- m_object->SetAngleY(15, 0.70f-sinf(m_armTimeAbs*1.7f)*0.43f);
- m_object->SetAngleY(16, -0.80f+sinf(m_armTimeAbs*0.9f)*0.53f); // left antenna
- m_object->SetAngleY(17, -0.70f-sinf(m_armTimeAbs*1.3f)*0.43f);
-
- m_object->SetAngleY(18, sinf(m_armTimeAbs*1.1f)*0.20f); // right claw
- m_object->SetAngleZ(18, -0.20f);
- m_object->SetAngleY(19, sinf(m_armTimeAbs*0.9f)*0.20f); // left claw
- m_object->SetAngleZ(19, -0.20f);
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionmother.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motionmother.h"
+
+#include "old/modfile.h"
+#include "physics/physics.h"
+
+
+
+#define ADJUST_ANGLE false // true -> adjusts the angles of the members
+const float START_TIME = 1000.0f; // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionMother::CMotionMother(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeMarch = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLastAction = -1;
+ m_specAction = -1;
+ m_bArmStop = false;
+}
+
+// Object's destructor.
+
+CMotionMother::~CMotionMother()
+{
+}
+
+
+// Removes an object.
+
+void CMotionMother::DeleteObject(bool bAll)
+{
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+bool CMotionMother::Create(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 2+12+6 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+
+ pModFile->ReadModel("objects\\mother1.mod");
+ pModFile->CreateEngineObject(rank);
+
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have a obligatory collision
+ //with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 20.0f, SOUND_BOUM, 0.20f);
+ m_object->SetGlobalSphere(Math::Vector(-2.0f, 10.0f, 0.0f), 25.0f);
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\mother2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(16.0f, 3.0f, 0.0f));
+
+ // Creates a right-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(-5.0f, -1.0f, -12.0f));
+
+ // Creates a right-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(0.0f, 0.0f, -8.5f));
+
+ // Creates a middle-right leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, Math::Vector(3.5f, -1.0f, -12.0f));
+
+ // Creates a middle-right foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 4);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, Math::Vector(0.0f, 0.0f, -8.5f));
+
+ // Creates a right-front leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(10.0f, -1.0f, -10.0f));
+
+ // Creates a right-front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 6);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, 0.0f, -8.5f));
+
+ // Creates a left-back leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(-5.0f, -1.0f, 12.0f));
+ m_object->SetAngleY(8, Math::PI);
+
+ // Creates a left-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 8);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, Math::Vector(0.0f, 0.0f, -8.5f));
+
+ // Creates a middle-left leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10, rank);
+ m_object->SetObjectParent(10, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10, Math::Vector(3.5f, -1.0f, 12.0f));
+ m_object->SetAngleY(10, Math::PI);
+
+ // Creates a middle-left foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(11, rank);
+ m_object->SetObjectParent(11, 10);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(11, Math::Vector(0.0f, 0.0f, -8.5f));
+
+ // Creates a left-front leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(12, rank);
+ m_object->SetObjectParent(12, 0);
+ pModFile->ReadModel("objects\\mother3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(12, Math::Vector(10.0f, -1.0f, 10.0f));
+ m_object->SetAngleY(12, Math::PI);
+
+ // Creates a left-front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(13, rank);
+ m_object->SetObjectParent(13, 12);
+ pModFile->ReadModel("objects\\mother4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(13, Math::Vector(0.0f, 0.0f, -8.5f));
+
+ // Creates the right antenna.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(14, rank);
+ m_object->SetObjectParent(14, 1);
+ pModFile->ReadModel("objects\\mother5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(14, Math::Vector(6.0f, 1.0f, -2.5f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(15, rank);
+ m_object->SetObjectParent(15, 14);
+ pModFile->ReadModel("objects\\mother6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(15, Math::Vector(8.0f, 0.0f, 0.0f));
+
+ // Creates the left antenna.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(16, rank);
+ m_object->SetObjectParent(16, 1);
+ pModFile->ReadModel("objects\\mother5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(16, Math::Vector(6.0f, 1.0f, 2.5f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(17, rank);
+ m_object->SetObjectParent(17, 16);
+ pModFile->ReadModel("objects\\mother6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(17, Math::Vector(8.0f, 0.0f, 0.0f));
+
+ // Creates the right claw.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(18, rank);
+ m_object->SetObjectParent(18, 1);
+ pModFile->ReadModel("objects\\mother7.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(18, Math::Vector(-4.0f, -3.5f, -8.0f));
+ m_object->SetZoomX(18, 1.2f);
+
+ // Creates the left claw.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(19, rank);
+ m_object->SetObjectParent(19, 1);
+ pModFile->ReadModel("objects\\mother7.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(19, Math::Vector(-4.0f, -3.5f, 8.0f));
+ m_object->SetZoomX(19, 1.2f);
+
+ m_object->CreateShadowCircle(18.0f, 0.8f);
+
+ CreatePhysics();
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+// Creates the physics of the object.
+
+void CMotionMother::CreatePhysics()
+{
+ Character* character;
+ int i;
+
+ int member[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 30,30,10, 35,-15,10, 35,-35,10, // t0: legs 1..3
+ -80,-45,-35, -115,-40,-35, -90,10,-55, // t0: feet 1..3
+ 0,0,0, 0,0,0, 0,0,0, // t0: unused
+ // on the ground:
+ 15,-5,10, 10,-30,10, 5,-50,10, // t1: legs 1..3
+ -90,-15,-15, -110,-55,-35, -75,-75,-30, // t1: feet 1..3
+ 0,0,0, 0,0,0, 0,0,0, // t1: unused
+ // on the ground back:
+ 0,40,10, 5,5,10, 0,-15,10, // t2: legs 1..3
+ -45,0,-55, -65,10,-50, -125,-85,-45, // t2: feet 1..3
+ 0,0,0, 0,0,0, 0,0,0, // t2: unused
+ };
+
+ m_physics->SetType(TYPE_ROLLING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 10.0f;
+ character->wheelBack = 10.0f;
+ character->wheelLeft = 20.0f;
+ character->wheelRight = 20.0f;
+ character->height = 3.0f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 8.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 8.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 30.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.1f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.1f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 20.0f);
+
+ for ( i=0 ; i<3*3*3*3 ; i++ )
+ {
+ m_armAngles[i] = member[i];
+ }
+}
+
+
+// Management of an event.
+
+bool CMotionMother::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if ADJUST_ANGLE
+ int i;
+
+ if ( event.param == 'A' ) m_armTimeIndex++;
+ if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
+
+ if ( event.param == 'Q' ) m_armPartIndex++;
+ if ( m_armPartIndex >= 3 ) m_armPartIndex = 0;
+
+ if ( event.param == 'W' ) m_armMemberIndex++;
+ if ( m_armMemberIndex >= 3 ) m_armMemberIndex = 0;
+
+ i = m_armMemberIndex*3;
+ i += m_armPartIndex*3*3;
+ i += m_armTimeIndex*3*3*3;
+//? i += 3*3*3*3;
+
+ if ( event.param == 'E' ) m_armAngles[i+0] += 5;
+ if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
+ if ( event.param == 'R' ) m_armAngles[i+1] += 5;
+ if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
+ if ( event.param == 'T' ) m_armAngles[i+2] += 5;
+ if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
+
+ if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
+#endif
+ }
+
+ return true;
+}
+
+// Management of an event.
+
+bool CMotionMother::EventFrame(const Event &event)
+{
+ Math::Vector dir;
+ float s, a, prog;
+ int i, st, nd;
+ bool bStop;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
+ a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*26.0f);
+
+ if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armTimeMarch += (s)*event.rTime*0.05f;
+ m_armMember += (s+a)*event.rTime*0.05f;
+
+ bStop = ( a == 0.0f && s == 0.0f ); // stop?
+
+ if ( bStop )
+ {
+ prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
+ a = Math::Mod(m_armMember, 1.0f);
+ a = (prog-a)*event.rTime*1.0f; // stop position just pleasantly
+ m_armMember += a;
+ }
+
+ for ( i=0 ; i<6 ; i++ ) // the six legs
+ {
+ if ( i < 3 ) prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
+ else prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
+ if ( m_bArmStop )
+ {
+ prog = (float)m_armTimeIndex/3.0f;
+ }
+ if ( prog < 0.33f ) // t0..t1 ?
+ {
+ prog = prog/0.33f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.67f ) // t1..t2 ?
+ {
+ prog = (prog-0.33f)/0.33f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.67f)/0.33f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ st = st*27+(i%3)*3;
+ nd = nd*27+(i%3)*3;
+ if ( i < 3 ) // right leg (1..3) ?
+ {
+ m_object->SetAngleX(2+2*i+0, Math::PropAngle(m_armAngles[st+ 0], m_armAngles[nd+ 0], prog));
+ m_object->SetAngleY(2+2*i+0, Math::PropAngle(m_armAngles[st+ 1], m_armAngles[nd+ 1], prog));
+ m_object->SetAngleZ(2+2*i+0, Math::PropAngle(m_armAngles[st+ 2], m_armAngles[nd+ 2], prog));
+ m_object->SetAngleX(2+2*i+1, Math::PropAngle(m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
+ m_object->SetAngleY(2+2*i+1, Math::PropAngle(m_armAngles[st+10], m_armAngles[nd+10], prog));
+ m_object->SetAngleZ(2+2*i+1, Math::PropAngle(m_armAngles[st+11], m_armAngles[nd+11], prog));
+ }
+ else // left leg (4..6) ?
+ {
+ m_object->SetAngleX(2+2*i+0, Math::PropAngle( m_armAngles[st+ 0], m_armAngles[nd+ 0], prog));
+ m_object->SetAngleY(2+2*i+0, Math::PropAngle(180-m_armAngles[st+ 1], 180-m_armAngles[nd+ 1], prog));
+ m_object->SetAngleZ(2+2*i+0, Math::PropAngle( -m_armAngles[st+ 2], -m_armAngles[nd+ 2], prog));
+ m_object->SetAngleX(2+2*i+1, Math::PropAngle( m_armAngles[st+ 9], m_armAngles[nd+ 9], prog));
+ m_object->SetAngleY(2+2*i+1, Math::PropAngle( -m_armAngles[st+10], -m_armAngles[nd+10], prog));
+ m_object->SetAngleZ(2+2*i+1, Math::PropAngle( -m_armAngles[st+11], -m_armAngles[nd+11], prog));
+ }
+ }
+
+#if ADJUST_ANGLE
+ if ( m_object->RetSelect() )
+ {
+ char s[100];
+ sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
+ m_engine->SetInfoText(4, s);
+ }
+#endif
+
+ if ( !bStop && !m_object->RetRuin() )
+ {
+ a = Math::Mod(m_armTimeMarch, 1.0f);
+ if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
+ else a = 3.0f-4.0f*a; // 1..-1
+ dir.x = sinf(a)*0.03f;
+
+ s = Math::Mod(m_armTimeMarch/2.0f, 1.0f);
+ if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
+ else s = 3.0f-4.0f*s; // 1..-1
+ dir.z = sinf(s)*0.05f;
+
+ dir.y = 0.0f;
+ m_object->SetInclinaison(dir);
+
+ a = Math::Mod(m_armMember-0.1f, 1.0f);
+ if ( a < 0.33f )
+ {
+ dir.y = -(1.0f-(a/0.33f))*0.3f;
+ }
+ else if ( a < 0.67f )
+ {
+ dir.y = 0.0f;
+ }
+ else
+ {
+ dir.y = -(a-0.67f)/0.33f*0.3f;
+ }
+ dir.x = 0.0f;
+ dir.z = 0.0f;
+ m_object->SetLinVibration(dir);
+ }
+
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*0.5f)*0.20f); // head
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*0.6f)*0.10f); // head
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*0.7f)*0.20f); // head
+
+ m_object->SetAngleZ(14, 0.50f);
+ m_object->SetAngleZ(16, 0.50f);
+ m_object->SetAngleY(14, 0.80f+sinf(m_armTimeAbs*1.1f)*0.53f); // right antenna
+ m_object->SetAngleY(15, 0.70f-sinf(m_armTimeAbs*1.7f)*0.43f);
+ m_object->SetAngleY(16, -0.80f+sinf(m_armTimeAbs*0.9f)*0.53f); // left antenna
+ m_object->SetAngleY(17, -0.70f-sinf(m_armTimeAbs*1.3f)*0.43f);
+
+ m_object->SetAngleY(18, sinf(m_armTimeAbs*1.1f)*0.20f); // right claw
+ m_object->SetAngleZ(18, -0.20f);
+ m_object->SetAngleY(19, sinf(m_armTimeAbs*0.9f)*0.20f); // left claw
+ m_object->SetAngleZ(19, -0.20f);
+
+ return true;
+}
+
+
diff --git a/src/object/motion/motionmother.h b/src/object/motion/motionmother.h
index 7d67f5b..5060315 100644
--- a/src/object/motion/motionmother.h
+++ b/src/object/motion/motionmother.h
@@ -1,54 +1,54 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionmother.h
-
-#pragma once
-
-
-#include "object/motion/motion.h"
-
-
-
-class CMotionMother : public CMotion
-{
-public:
- CMotionMother(CInstanceManager* iMan, CObject* object);
- ~CMotionMother();
-
- void DeleteObject(bool bAll=false);
- bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- bool EventProcess(const Event &event);
-
-protected:
- void CreatePhysics();
- bool EventFrame(const Event &event);
-
-protected:
- float m_armMember;
- float m_armTimeAbs;
- float m_armTimeMarch;
- float m_armTimeAction;
- short m_armAngles[3*3*3*3*10];
- int m_armTimeIndex;
- int m_armPartIndex;
- int m_armMemberIndex;
- int m_armLastAction;
- int m_specAction;
- float m_specTime;
- bool m_bArmStop;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionmother.h
+
+#pragma once
+
+
+#include "object/motion/motion.h"
+
+
+
+class CMotionMother : public CMotion
+{
+public:
+ CMotionMother(CInstanceManager* iMan, CObject* object);
+ ~CMotionMother();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ bool EventProcess(const Event &event);
+
+protected:
+ void CreatePhysics();
+ bool EventFrame(const Event &event);
+
+protected:
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeMarch;
+ float m_armTimeAction;
+ short m_armAngles[3*3*3*3*10];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ int m_specAction;
+ float m_specTime;
+ bool m_bArmStop;
+};
+
diff --git a/src/object/motion/motionspider.cpp b/src/object/motion/motionspider.cpp
index fa5d649..be16e08 100644
--- a/src/object/motion/motionspider.cpp
+++ b/src/object/motion/motionspider.cpp
@@ -1,759 +1,759 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionspider.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motionspider.h"
-
-#include "old/modfile.h"
-#include "old/particule.h"
-#include "physics/physics.h"
-
-
-
-#define ADJUST_ANGLE false // true -> adjusts the angles of the members
-const float START_TIME = 1000.0f; // beginning of the relative time
-
-
-
-// Object's constructor.
-
-CMotionSpider::CMotionSpider(CInstanceManager* iMan, CObject* object)
- : CMotion(iMan, object)
-{
- m_armMember = START_TIME;
- m_armTimeAbs = START_TIME;
- m_armTimeMarch = START_TIME;
- m_armTimeAction = START_TIME;
- m_armTimeIndex = 0;
- m_armPartIndex = 0;
- m_armMemberIndex = 0;
- m_armLastAction = -1;
- m_bArmStop = false;
- m_lastParticule = 0.0f;
-}
-
-// Object's destructor.
-
-CMotionSpider::~CMotionSpider()
-{
-}
-
-
-// Removes an object.
-
-void CMotionSpider::DeleteObject(bool bAll)
-{
-}
-
-
-// Creates a vehicle traveling any lands on the ground.
-
-bool CMotionSpider::Create(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- int rank, i, j, parent;
- char name[50];
-
- float table[] =
- {
- // x y z
- 0.6f, 0.0f, 0.0f, // back leg
- 0.0f, 0.0f, -2.0f,
- 0.0f, 0.0f, -2.0f,
- 0.0f, 0.0f, -2.0f,
-
- 0.8f, 0.0f, -0.2f, // middle-back leg
- 0.0f, 0.0f, -2.0f,
- 0.0f, 0.0f, -2.0f,
- 0.0f, 0.0f, -2.0f,
-
- 1.0f, 0.0f, -0.2f, // middle-front leg
- 0.0f, 0.0f, -2.0f,
- 0.0f, 0.0f, -2.0f,
- 0.0f, 0.0f, -2.0f,
-
- 1.2f, 0.0f, 0.0f, // front leg
- 0.0f, 0.0f, -2.0f,
- 0.0f, 0.0f, -2.0f,
- 0.0f, 0.0f, -2.0f,
- };
-
- if ( m_engine->RetRestCreate() < 3+32+2 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- m_object->SetType(type);
-
- // Creates the main base.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\spider0.mod"); // doesn't exist
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(0, pos);
- m_object->SetAngleY(0, angle);
-
- // A vehicle must have a obligatory collision
- // with a sphere of center (0, y, 0) (see GetCrashSphere).
- m_object->CreateCrashSphere(Math::Vector(0.0f, -2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
- m_object->SetGlobalSphere(Math::Vector(-0.5f, 1.0f, 0.0f), 4.0f);
-
- // Creates the abdomen.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\spider1.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(1.0f, 0.0f, 0.0f));
-
- // Creates the head.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\spider2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(1.0f, 0.0f, 0.0f));
-
- // Creates legs.
- for ( i=0 ; i<4 ; i++ )
- {
- for ( j=0 ; j<4 ; j++ )
- {
- sprintf(name, "objects\\spider%d.mod", j+3); // 3..6
-
- // Creates the right leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3+i*4+j, rank);
- if ( j == 0 ) parent = 0;
- else parent = 3+i*4+j-1;
- m_object->SetObjectParent(3+i*4+j, parent);
- pModFile->ReadModel(name);
- pModFile->CreateEngineObject(rank);
- pos.x = table[i*12+j*3+0];
- pos.y = table[i*12+j*3+1];
- pos.z = table[i*12+j*3+2];
- m_object->SetPosition(3+i*4+j, pos);
-
- // Creates the left leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(19+i*4+j, rank);
- if ( j == 0 ) parent = 0;
- else parent = 19+i*4+j-1;
- m_object->SetObjectParent(19+i*4+j, parent);
- pModFile->ReadModel(name);
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- pos.x = table[i*12+j*3+0];
- pos.y = table[i*12+j*3+1];
- pos.z = -table[i*12+j*3+2];
- m_object->SetPosition(19+i*4+j, pos);
- }
- }
-
- // Creates the right mandible.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(35, rank);
- m_object->SetObjectParent(35, 1);
- pModFile->ReadModel("objects\\spider7.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(35, Math::Vector(0.0f, 0.0f, -0.3f));
-
- // Creates the left mandible.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(36, rank);
- m_object->SetObjectParent(36, 1);
- pModFile->ReadModel("objects\\spider7.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(36, Math::Vector(0.0f, 0.0f, 0.3f));
-
- m_object->CreateShadowCircle(4.0f, 0.5f);
-
- CreatePhysics();
- m_object->SetFloorHeight(0.0f);
-
- pos = m_object->RetPosition(0);
- m_object->SetPosition(0, pos); // to display the shadows immediately
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-// Creates the physics of the object.
-
-void CMotionSpider::CreatePhysics()
-{
- Character* character;
- int i;
-
- int member_march[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // in the air:
- 60,25,0, 60,0,0, 60,-25,0, 60,-50,0, // t0: thighs 1..4
- -35,40,0, -35,0,0, -35,0,0, -35,-40,0, // t0: legs 1..4
- -65,0,-30, -65,0,0, -65,0,0, -65,0,30, // t0: feet 1..4
- 25,0,0, 25,0,0, 25,0,0, 25,0,0, // t0: fingers 1..4
- // on the ground:
- 30,15,0, 30,-10,0, 30,-35,0, 30,-60,0, // t1: thighs 1..4
- -10,40,0, -45,0,0, -45,0,0, -45,-40,0, // t1: legs 1..4
- -90,0,0, -20,0,0, -20,0,0, -20,0,0, // t1: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t1: fingers 1..4
- // on the ground back:
- 35,35,0, 40,10,0, 40,-15,0, 40,-40,0, // t2: thighs 1..4
- -35,40,0, -35,0,0, -35,0,0, -25,-40,0, // t2: legs 1..4
- -50,-25,-30, -65,0,0, -65,0,0, -90,0,30, // t2: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t2: fingers 1..4
- };
-
- int member_stop[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // in the air:
- 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t0: thighs 1..4
- -35,40,0, -45,0,0, -45,0,0, -45,-40,0, // t0: legs 1..4
- -50,-25,-30, -20,0,0, -20,0,0, -20,0,30, // t0: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t0: fingers 1..4
- // on the ground:
- 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t1: thighs 1..4
- -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // t1: legs 1..4
- -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // t1: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t1: fingers 1..4
- // on the ground back:
- 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t2: thighs 1..4
- -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // t2: legs 1..4
- -50,-25,-30, -20,0,0, -20,0,0, -20,0,30, // t2: feet 1..4
- -10,0,0, -10,0,0, -10,0,0, -10,0,0, // t2: fingers 1..4
- };
-
- int member_spec[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // burning:
- 30,25,0, 30,0,0, 30,-25,0, 30,-50,0, // s0: thighs 1..4
- -45,0,0, -45,0,0, -45,0,0, -45,0,0, // s0: legs 1..4
- -20,0,0, -20,0,0, -20,0,0, -20,0,0, // s0: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s0: fingers 1..4
- // destroyed:
- 30,25,0, 30,0,0, 30,-25,0, 30,-50,0, // s1: thighs 1..4
- -45,0,0, -45,0,0, -45,0,0, -45,0,0, // s1: legs 1..4
- -20,0,0, -20,0,0, -20,0,0, -20,0,0, // s1: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s1: fingers 1..4
- // explodes:
- 40,25,0, 40,0,0, 40,-25,0, 40,-50,0, // s2: thighs 1..4
- -55,0,0, -55,0,0, -55,0,0, -55,0,0, // s2: legs 1..4
- -30,0,0, -30,0,0, -30,0,0, -30,0,0, // s2: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s2: fingers 1..4
- // back1 :
- 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // s3: thighs 1..4
- -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // s3: legs 1..4
- -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // s3: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s3: fingers 1..4
- // back2 :
- 15,35,0, 15,0,0, 15,-25,0, 15,-50,0, // s4: thighs 1..4
- -60,40,0, -60,0,0, -60,0,0, -60,-40,0, // s4: legs 1..4
- -65,-25,-30, -65,0,0, -65,0,0, -65,0,0, // s4: feet 1..4
- -15,0,0, -15,0,0, -15,0,0, -15,0,0, // s4: fingers 1..4
- // back3 :
- 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // s5: thighs 1..4
- -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // s5: legs 1..4
- -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // s5: feet 1..4
- -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s5: fingers 1..4
- };
-
- m_physics->SetType(TYPE_ROLLING);
-
- character = m_object->RetCharacter();
- character->wheelFront = 4.0f;
- character->wheelBack = 4.0f;
- character->wheelLeft = 6.0f;
- character->wheelRight = 6.0f;
- character->height = 0.6f;
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 12.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 12.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 15.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 10.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 20.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 40.0f);
-
- for ( i=0 ; i<3*4*4*3 ; i++ )
- {
- m_armAngles[3*4*4*3*MS_MARCH+i] = member_march[i];
- }
- for ( i=0 ; i<3*4*4*3 ; i++ )
- {
- m_armAngles[3*4*4*3*MS_STOP+i] = member_stop[i];
- }
- for ( i=0 ; i<3*4*4*6 ; i++ )
- {
- m_armAngles[3*4*4*3*MS_SPEC+i] = member_spec[i];
- }
-}
-
-
-// Management of an event.
-
-bool CMotionSpider::EventProcess(const Event &event)
-{
- CMotion::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
-#if ADJUST_ANGLE
- int i;
-
- if ( event.param == 'A' ) m_armTimeIndex++;
- if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
-
- if ( event.param == 'Q' ) m_armPartIndex++;
- if ( m_armPartIndex >= 4 ) m_armPartIndex = 0;
-
- if ( event.param == 'W' ) m_armMemberIndex++;
- if ( m_armMemberIndex >= 4 ) m_armMemberIndex = 0;
-
- i = m_armMemberIndex*3;
- i += m_armPartIndex*3*4;
- i += m_armTimeIndex*3*4*4;
-
- if ( event.param == 'E' ) m_armAngles[i+0] += 5;
- if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
- if ( event.param == 'R' ) m_armAngles[i+1] += 5;
- if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
- if ( event.param == 'T' ) m_armAngles[i+2] += 5;
- if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
- if ( event.param == 'Z' ) m_armAngles[i+3] += 5;
- if ( event.param == 'H' ) m_armAngles[i+3] -= 5;
-
- if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
-#endif
- }
-
- return true;
-}
-
-// Management of an event.
-
-bool CMotionSpider::EventFrame(const Event &event)
-{
- Math::Vector dir, pos, speed;
- Math::Point dim;
- float s, a, prog, time;
- float tSt[12], tNd[12];
- int i, ii, st, nd, action;
- bool bStop;
-
- if ( m_engine->RetPause() ) return true;
- if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
-
- s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
- a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f);
-
- if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
-
- m_armTimeAbs += event.rTime;
- m_armTimeAction += event.rTime;
- m_armTimeMarch += (s)*event.rTime*0.15f;
- m_armMember += (s+a)*event.rTime*0.15f;
-
- bStop = ( a == 0.0f && s == 0.0f ); // stop?
-
- action = MS_MARCH; // waslking
- if ( s == 0.0f && a == 0.0f )
- {
- action = MS_STOP; // stop
- }
-
- if ( bStop )
- {
- prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
- a = Math::Mod(m_armMember, 1.0f);
- a = (prog-a)*event.rTime*2.0f; // stop position just pleasantly
- m_armMember += a;
- }
-
- if ( m_object->RetRuin() ) // destroyed?
- {
- m_actionType = MSS_RUIN;
- }
- if ( m_object->RetBurn() ) // burning?
- {
- if ( m_object->RetFixed() )
- {
- m_actionType = MSS_BURN;
- }
- else
- {
- m_actionType = -1;
- }
- }
-
- for ( i=0 ; i<8 ; i++ ) // the 8 legs
- {
- if ( m_actionType != -1 ) // special action in progress?
- {
- st = 3*4*4*3*MS_SPEC + 3*4*4*m_actionType + (i%4)*3;
- nd = st;
- time = event.rTime*m_actionTime;
- m_armTimeAction = 0.0f;
- }
- else
- {
-//? if ( i < 4 ) prog = Math::Mod(m_armMember+(2.0f-(i%4))*0.25f+0.0f, 1.0f);
-//? else prog = Math::Mod(m_armMember+(2.0f-(i%4))*0.25f+0.3f, 1.0f);
- if ( i < 4 ) prog = Math::Mod(m_armMember+(2.0f-(i%4))*0.25f+0.0f, 1.0f);
- else prog = Math::Mod(m_armMember+(2.0f-(i%4))*0.25f+0.5f, 1.0f);
- if ( m_bArmStop )
- {
- prog = (float)m_armTimeIndex/3.0f;
- action = MS_MARCH;
- }
- if ( prog < 0.33f ) // t0..t1 ?
- {
- prog = prog/0.33f; // 0..1
- st = 0; // index start
- nd = 1; // index end
- }
- else if ( prog < 0.67f ) // t1..t2 ?
- {
- prog = (prog-0.33f)/0.33f; // 0..1
- st = 1; // index start
- nd = 2; // index end
- }
- else // t2..t0 ?
- {
- prog = (prog-0.67f)/0.33f; // 0..1
- st = 2; // index start
- nd = 0; // index end
- }
- st = 3*4*4*3*action + st*3*4*4 + (i%4)*3;
- nd = 3*4*4*3*action + nd*3*4*4 + (i%4)*3;
-
- // Less and less soft ...
-//? time = event.rTime*(2.0f+Math::Min(m_armTimeAction*20.0f, 40.0f));
- time = event.rTime*10.0f;
- }
-
- tSt[ 0] = m_armAngles[st+ 0]; // x
- tSt[ 1] = m_armAngles[st+ 1]; // y
- tSt[ 2] = m_armAngles[st+ 2]; // z
- tSt[ 3] = m_armAngles[st+12]; // x
- tSt[ 4] = m_armAngles[st+13]; // y
- tSt[ 5] = m_armAngles[st+14]; // z
- tSt[ 6] = m_armAngles[st+24]; // x
- tSt[ 7] = m_armAngles[st+25]; // y
- tSt[ 8] = m_armAngles[st+26]; // z
- tSt[ 9] = m_armAngles[st+36]; // x
- tSt[10] = m_armAngles[st+37]; // y
- tSt[11] = m_armAngles[st+38]; // z
-
- tNd[ 0] = m_armAngles[nd+ 0]; // x
- tNd[ 1] = m_armAngles[nd+ 1]; // y
- tNd[ 2] = m_armAngles[nd+ 2]; // z
- tNd[ 3] = m_armAngles[nd+12]; // x
- tNd[ 4] = m_armAngles[nd+13]; // y
- tNd[ 5] = m_armAngles[nd+14]; // z
- tNd[ 6] = m_armAngles[nd+24]; // x
- tNd[ 7] = m_armAngles[nd+25]; // y
- tNd[ 8] = m_armAngles[nd+26]; // z
- tNd[ 9] = m_armAngles[nd+36]; // z
- tNd[10] = m_armAngles[nd+37]; // z
- tNd[11] = m_armAngles[nd+38]; // z
-
- if ( m_actionType == MSS_BACK2 ) // on the back?
- {
- for ( ii=0 ; ii<12 ; ii++ )
- {
- tSt[ii] += Math::Rand()*20.0f;
- tNd[ii] = tSt[ii];
- }
-//? time = 100.0f;
- time = event.rTime*10.0f;
- }
-
- if ( i < 4 ) // right leg (1..4) ?
- {
- m_object->SetAngleX(3+4*i+0, Math::Smooth(m_object->RetAngleX(3+4*i+0), Math::PropAngle(tSt[ 0], tNd[ 0], prog), time));
- m_object->SetAngleY(3+4*i+0, Math::Smooth(m_object->RetAngleY(3+4*i+0), Math::PropAngle(tSt[ 1], tNd[ 1], prog), time));
- m_object->SetAngleZ(3+4*i+0, Math::Smooth(m_object->RetAngleZ(3+4*i+0), Math::PropAngle(tSt[ 2], tNd[ 2], prog), time));
- m_object->SetAngleX(3+4*i+1, Math::Smooth(m_object->RetAngleX(3+4*i+1), Math::PropAngle(tSt[ 3], tNd[ 3], prog), time));
- m_object->SetAngleY(3+4*i+1, Math::Smooth(m_object->RetAngleY(3+4*i+1), Math::PropAngle(tSt[ 4], tNd[ 4], prog), time));
- m_object->SetAngleZ(3+4*i+1, Math::Smooth(m_object->RetAngleZ(3+4*i+1), Math::PropAngle(tSt[ 5], tNd[ 5], prog), time));
- m_object->SetAngleX(3+4*i+2, Math::Smooth(m_object->RetAngleX(3+4*i+2), Math::PropAngle(tSt[ 6], tNd[ 6], prog), time));
- m_object->SetAngleY(3+4*i+2, Math::Smooth(m_object->RetAngleY(3+4*i+2), Math::PropAngle(tSt[ 7], tNd[ 7], prog), time));
- m_object->SetAngleZ(3+4*i+2, Math::Smooth(m_object->RetAngleZ(3+4*i+2), Math::PropAngle(tSt[ 8], tNd[ 8], prog), time));
- m_object->SetAngleX(3+4*i+3, Math::Smooth(m_object->RetAngleX(3+4*i+3), Math::PropAngle(tSt[ 9], tNd[ 9], prog), time));
- m_object->SetAngleY(3+4*i+3, Math::Smooth(m_object->RetAngleY(3+4*i+3), Math::PropAngle(tSt[10], tNd[10], prog), time));
- m_object->SetAngleZ(3+4*i+3, Math::Smooth(m_object->RetAngleZ(3+4*i+3), Math::PropAngle(tSt[11], tNd[11], prog), time));
- }
- else // left leg (5..8) ?
- {
- m_object->SetAngleX(3+4*i+0, Math::Smooth(m_object->RetAngleX(3+4*i+0), Math::PropAngle(-tSt[ 0], -tNd[ 0], prog), time));
- m_object->SetAngleY(3+4*i+0, Math::Smooth(m_object->RetAngleY(3+4*i+0), Math::PropAngle(-tSt[ 1], -tNd[ 1], prog), time));
- m_object->SetAngleZ(3+4*i+0, Math::Smooth(m_object->RetAngleZ(3+4*i+0), Math::PropAngle( tSt[ 2], tNd[ 2], prog), time));
- m_object->SetAngleX(3+4*i+1, Math::Smooth(m_object->RetAngleX(3+4*i+1), Math::PropAngle(-tSt[ 3], -tNd[ 3], prog), time));
- m_object->SetAngleY(3+4*i+1, Math::Smooth(m_object->RetAngleY(3+4*i+1), Math::PropAngle(-tSt[ 4], -tNd[ 4], prog), time));
- m_object->SetAngleZ(3+4*i+1, Math::Smooth(m_object->RetAngleZ(3+4*i+1), Math::PropAngle( tSt[ 5], tNd[ 5], prog), time));
- m_object->SetAngleX(3+4*i+2, Math::Smooth(m_object->RetAngleX(3+4*i+2), Math::PropAngle(-tSt[ 6], -tNd[ 6], prog), time));
- m_object->SetAngleY(3+4*i+2, Math::Smooth(m_object->RetAngleY(3+4*i+2), Math::PropAngle(-tSt[ 7], -tNd[ 7], prog), time));
- m_object->SetAngleZ(3+4*i+2, Math::Smooth(m_object->RetAngleZ(3+4*i+2), Math::PropAngle( tSt[ 8], tNd[ 8], prog), time));
- m_object->SetAngleX(3+4*i+3, Math::Smooth(m_object->RetAngleX(3+4*i+3), Math::PropAngle(-tSt[ 9], -tNd[ 9], prog), time));
- m_object->SetAngleY(3+4*i+3, Math::Smooth(m_object->RetAngleY(3+4*i+3), Math::PropAngle(-tSt[10], -tNd[10], prog), time));
- m_object->SetAngleZ(3+4*i+3, Math::Smooth(m_object->RetAngleZ(3+4*i+3), Math::PropAngle( tSt[11], tNd[11], prog), time));
- }
- }
-
-#if ADJUST_ANGLE
- if ( m_object->RetSelect() )
- {
- char s[100];
- sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
- m_engine->SetInfoText(4, s);
- }
-#endif
-
- if ( m_actionType == MSS_BURN ) // burning?
- {
- dir = Math::Vector(Math::PI, 0.0f, 0.0f);
- SetCirVibration(dir);
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetLinVibration(dir);
- SetInclinaison(dir);
-
- time = event.rTime*1.0f;
- m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), 0.0f, time)); // head
- }
- else if ( m_actionType == MSS_RUIN ) // destroyed?
- {
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetLinVibration(dir);
- SetCirVibration(dir);
- SetInclinaison(dir);
- }
- else if ( m_actionType == MSS_EXPLO ) // exploded?
- {
- m_object->SetZoomY(1, 1.0f+m_progress);
- m_object->SetZoomZ(1, 1.0f+m_progress);
- m_object->SetZoomX(1, 1.0f+m_progress/2.0f);
-
- dir.x = (Math::Rand()-0.5f)*0.1f*m_progress;
- dir.y = (Math::Rand()-0.5f)*0.1f*m_progress;
- dir.z = (Math::Rand()-0.5f)*0.1f*m_progress;
- m_object->SetCirVibration(dir);
- }
- else if ( m_actionType == MSS_BACK1 ) // turns on the back?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
- {
- m_lastParticule = m_armTimeAbs;
-
- pos = m_object->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = Math::Rand()*5.0f;
- dim.x = Math::Rand()*3.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
-
- if ( m_progress < 0.5f )
- {
- dir.x = 0.0f;
- dir.y = powf(m_progress/0.5f, 2.0f)*12.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
- else
- {
- dir.x = 0.0f;
- dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*12.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
- dir.x = m_progress*Math::PI;
- dir.y = 0.0f;
- dir.z = 0.0f;
- SetCirVibration(dir);
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetInclinaison(dir);
-
- if ( m_progress >= 1.0f )
- {
- SetAction(MSS_BACK2, 55.0f+Math::Rand()*10.0f);
- }
- }
- else if ( m_actionType == MSS_BACK2 ) // moves on the back?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
- {
- m_lastParticule = m_armTimeAbs;
-
- if ( rand()%10 == 0 )
- {
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*8.0f;
- pos.z += (Math::Rand()-0.5f)*8.0f;
- pos.y -= 1.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = Math::Rand()*2.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
- }
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetLinVibration(dir);
- dir.x = sinf(m_armTimeAbs* 3.0f)*0.20f+
- sinf(m_armTimeAbs* 6.0f)*0.20f+
- sinf(m_armTimeAbs*10.0f)*0.20f+
- sinf(m_armTimeAbs*17.0f)*0.30f+Math::PI;
- dir.y = sinf(m_armTimeAbs* 4.0f)*0.02f+
- sinf(m_armTimeAbs* 5.0f)*0.02f+
- sinf(m_armTimeAbs*11.0f)*0.02f+
- sinf(m_armTimeAbs*18.0f)*0.03f;
- dir.z = sinf(m_armTimeAbs* 2.0f)*0.02f+
- sinf(m_armTimeAbs* 7.0f)*0.02f+
- sinf(m_armTimeAbs*13.0f)*0.02f+
- sinf(m_armTimeAbs*15.0f)*0.03f;
- SetCirVibration(dir);
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetInclinaison(dir);
-
- m_object->SetAngleY(1, sinf(m_armTimeAbs*5.0f)*0.05f); // tail
- m_object->SetAngleY(2, cosf(m_armTimeAbs*5.0f)*0.20f); // head
- m_object->SetAngleZ(1, 0.4f); // tail
- m_object->SetAngleZ(2, 0.0f); // head
-
- if ( m_progress >= 1.0f )
- {
- SetAction(MSS_BACK3, 0.4f);
- }
- }
- else if ( m_actionType == MSS_BACK3 ) // recovers on the legs?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
- {
- m_lastParticule = m_armTimeAbs;
-
- pos = m_object->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = Math::Rand()*5.0f;
- dim.x = Math::Rand()*3.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
-
- if ( m_progress < 0.5f )
- {
- dir.x = 0.0f;
- dir.y = powf(m_progress/0.5f, 2.0f)*5.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
- else
- {
- dir.x = 0.0f;
- dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*5.0f;
- dir.z = 0.0f;
- SetLinVibration(dir);
- }
- dir.x = (1.0f-m_progress)*Math::PI;
- dir.y = 0.0f;
- dir.z = 0.0f;
- SetCirVibration(dir);
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetInclinaison(dir);
-
- if ( m_progress >= 1.0f )
- {
- SetAction(-1);
- m_object->SetFixed(false); // moving again
- }
- }
- else
- {
- if ( bStop )
- {
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetInclinaison(dir);
- }
- else
- {
- a = Math::Mod(m_armMember, 1.0f);
- if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
- else a = 3.0f-4.0f*a; // 1..-1
- dir.x = sinf(a)*0.05f;
-
- s = Math::Mod(m_armMember/2.0f, 1.0f);
- if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
- else s = 3.0f-4.0f*s; // 1..-1
- dir.z = sinf(s)*0.1f;
-
- dir.y = 0.0f;
- SetInclinaison(dir);
- }
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- SetLinVibration(dir);
- SetCirVibration(dir);
-
- m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.7f)*0.02f); // tail
- m_object->SetAngleX(1, sinf(m_armTimeAbs*1.3f)*0.05f);
- m_object->SetAngleY(1, sinf(m_armTimeAbs*2.4f)*0.10f);
- m_object->SetZoom(1, 1.0f+sinf(m_armTimeAbs*3.3f)*0.05f);
-
- m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.4f)*0.20f); // head
- m_object->SetAngleX(2, sinf(m_armTimeAbs*1.9f)*0.10f);
- m_object->SetAngleY(2, sinf(m_armTimeAbs*2.1f)*0.10f);
-
- m_object->SetAngleY(35, sinf(m_armTimeAbs*3.1f)*0.20f); // mandible
- m_object->SetAngleY(36, -sinf(m_armTimeAbs*3.1f)*0.20f); // mandible
- }
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionspider.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motionspider.h"
+
+#include "old/modfile.h"
+#include "old/particule.h"
+#include "physics/physics.h"
+
+
+
+#define ADJUST_ANGLE false // true -> adjusts the angles of the members
+const float START_TIME = 1000.0f; // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionSpider::CMotionSpider(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeMarch = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLastAction = -1;
+ m_bArmStop = false;
+ m_lastParticule = 0.0f;
+}
+
+// Object's destructor.
+
+CMotionSpider::~CMotionSpider()
+{
+}
+
+
+// Removes an object.
+
+void CMotionSpider::DeleteObject(bool bAll)
+{
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+bool CMotionSpider::Create(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank, i, j, parent;
+ char name[50];
+
+ float table[] =
+ {
+ // x y z
+ 0.6f, 0.0f, 0.0f, // back leg
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+
+ 0.8f, 0.0f, -0.2f, // middle-back leg
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+
+ 1.0f, 0.0f, -0.2f, // middle-front leg
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+
+ 1.2f, 0.0f, 0.0f, // front leg
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+ 0.0f, 0.0f, -2.0f,
+ };
+
+ if ( m_engine->RetRestCreate() < 3+32+2 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates the main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\spider0.mod"); // doesn't exist
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have a obligatory collision
+ // with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(Math::Vector(0.0f, -2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
+ m_object->SetGlobalSphere(Math::Vector(-0.5f, 1.0f, 0.0f), 4.0f);
+
+ // Creates the abdomen.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\spider1.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(1.0f, 0.0f, 0.0f));
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\spider2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(1.0f, 0.0f, 0.0f));
+
+ // Creates legs.
+ for ( i=0 ; i<4 ; i++ )
+ {
+ for ( j=0 ; j<4 ; j++ )
+ {
+ sprintf(name, "objects\\spider%d.mod", j+3); // 3..6
+
+ // Creates the right leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3+i*4+j, rank);
+ if ( j == 0 ) parent = 0;
+ else parent = 3+i*4+j-1;
+ m_object->SetObjectParent(3+i*4+j, parent);
+ pModFile->ReadModel(name);
+ pModFile->CreateEngineObject(rank);
+ pos.x = table[i*12+j*3+0];
+ pos.y = table[i*12+j*3+1];
+ pos.z = table[i*12+j*3+2];
+ m_object->SetPosition(3+i*4+j, pos);
+
+ // Creates the left leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(19+i*4+j, rank);
+ if ( j == 0 ) parent = 0;
+ else parent = 19+i*4+j-1;
+ m_object->SetObjectParent(19+i*4+j, parent);
+ pModFile->ReadModel(name);
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ pos.x = table[i*12+j*3+0];
+ pos.y = table[i*12+j*3+1];
+ pos.z = -table[i*12+j*3+2];
+ m_object->SetPosition(19+i*4+j, pos);
+ }
+ }
+
+ // Creates the right mandible.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(35, rank);
+ m_object->SetObjectParent(35, 1);
+ pModFile->ReadModel("objects\\spider7.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(35, Math::Vector(0.0f, 0.0f, -0.3f));
+
+ // Creates the left mandible.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(36, rank);
+ m_object->SetObjectParent(36, 1);
+ pModFile->ReadModel("objects\\spider7.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(36, Math::Vector(0.0f, 0.0f, 0.3f));
+
+ m_object->CreateShadowCircle(4.0f, 0.5f);
+
+ CreatePhysics();
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+// Creates the physics of the object.
+
+void CMotionSpider::CreatePhysics()
+{
+ Character* character;
+ int i;
+
+ int member_march[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // in the air:
+ 60,25,0, 60,0,0, 60,-25,0, 60,-50,0, // t0: thighs 1..4
+ -35,40,0, -35,0,0, -35,0,0, -35,-40,0, // t0: legs 1..4
+ -65,0,-30, -65,0,0, -65,0,0, -65,0,30, // t0: feet 1..4
+ 25,0,0, 25,0,0, 25,0,0, 25,0,0, // t0: fingers 1..4
+ // on the ground:
+ 30,15,0, 30,-10,0, 30,-35,0, 30,-60,0, // t1: thighs 1..4
+ -10,40,0, -45,0,0, -45,0,0, -45,-40,0, // t1: legs 1..4
+ -90,0,0, -20,0,0, -20,0,0, -20,0,0, // t1: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t1: fingers 1..4
+ // on the ground back:
+ 35,35,0, 40,10,0, 40,-15,0, 40,-40,0, // t2: thighs 1..4
+ -35,40,0, -35,0,0, -35,0,0, -25,-40,0, // t2: legs 1..4
+ -50,-25,-30, -65,0,0, -65,0,0, -90,0,30, // t2: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t2: fingers 1..4
+ };
+
+ int member_stop[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // in the air:
+ 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t0: thighs 1..4
+ -35,40,0, -45,0,0, -45,0,0, -45,-40,0, // t0: legs 1..4
+ -50,-25,-30, -20,0,0, -20,0,0, -20,0,30, // t0: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t0: fingers 1..4
+ // on the ground:
+ 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t1: thighs 1..4
+ -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // t1: legs 1..4
+ -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // t1: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // t1: fingers 1..4
+ // on the ground back:
+ 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // t2: thighs 1..4
+ -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // t2: legs 1..4
+ -50,-25,-30, -20,0,0, -20,0,0, -20,0,30, // t2: feet 1..4
+ -10,0,0, -10,0,0, -10,0,0, -10,0,0, // t2: fingers 1..4
+ };
+
+ int member_spec[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4, // burning:
+ 30,25,0, 30,0,0, 30,-25,0, 30,-50,0, // s0: thighs 1..4
+ -45,0,0, -45,0,0, -45,0,0, -45,0,0, // s0: legs 1..4
+ -20,0,0, -20,0,0, -20,0,0, -20,0,0, // s0: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s0: fingers 1..4
+ // destroyed:
+ 30,25,0, 30,0,0, 30,-25,0, 30,-50,0, // s1: thighs 1..4
+ -45,0,0, -45,0,0, -45,0,0, -45,0,0, // s1: legs 1..4
+ -20,0,0, -20,0,0, -20,0,0, -20,0,0, // s1: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s1: fingers 1..4
+ // explodes:
+ 40,25,0, 40,0,0, 40,-25,0, 40,-50,0, // s2: thighs 1..4
+ -55,0,0, -55,0,0, -55,0,0, -55,0,0, // s2: legs 1..4
+ -30,0,0, -30,0,0, -30,0,0, -30,0,0, // s2: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s2: fingers 1..4
+ // back1 :
+ 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // s3: thighs 1..4
+ -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // s3: legs 1..4
+ -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // s3: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s3: fingers 1..4
+ // back2 :
+ 15,35,0, 15,0,0, 15,-25,0, 15,-50,0, // s4: thighs 1..4
+ -60,40,0, -60,0,0, -60,0,0, -60,-40,0, // s4: legs 1..4
+ -65,-25,-30, -65,0,0, -65,0,0, -65,0,0, // s4: feet 1..4
+ -15,0,0, -15,0,0, -15,0,0, -15,0,0, // s4: fingers 1..4
+ // back3 :
+ 35,35,0, 30,0,0, 30,-25,0, 30,-50,0, // s5: thighs 1..4
+ -30,40,0, -40,0,0, -40,0,0, -40,-40,0, // s5: legs 1..4
+ -55,-25,-30, -25,0,0, -25,0,0, -25,0,0, // s5: feet 1..4
+ -5,0,0, -5,0,0, -5,0,0, -5,0,0, // s5: fingers 1..4
+ };
+
+ m_physics->SetType(TYPE_ROLLING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 6.0f;
+ character->wheelRight = 6.0f;
+ character->height = 0.6f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 12.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 12.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 15.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 10.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 1.0f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 1.0f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 20.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 40.0f);
+
+ for ( i=0 ; i<3*4*4*3 ; i++ )
+ {
+ m_armAngles[3*4*4*3*MS_MARCH+i] = member_march[i];
+ }
+ for ( i=0 ; i<3*4*4*3 ; i++ )
+ {
+ m_armAngles[3*4*4*3*MS_STOP+i] = member_stop[i];
+ }
+ for ( i=0 ; i<3*4*4*6 ; i++ )
+ {
+ m_armAngles[3*4*4*3*MS_SPEC+i] = member_spec[i];
+ }
+}
+
+
+// Management of an event.
+
+bool CMotionSpider::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if ADJUST_ANGLE
+ int i;
+
+ if ( event.param == 'A' ) m_armTimeIndex++;
+ if ( m_armTimeIndex >= 3 ) m_armTimeIndex = 0;
+
+ if ( event.param == 'Q' ) m_armPartIndex++;
+ if ( m_armPartIndex >= 4 ) m_armPartIndex = 0;
+
+ if ( event.param == 'W' ) m_armMemberIndex++;
+ if ( m_armMemberIndex >= 4 ) m_armMemberIndex = 0;
+
+ i = m_armMemberIndex*3;
+ i += m_armPartIndex*3*4;
+ i += m_armTimeIndex*3*4*4;
+
+ if ( event.param == 'E' ) m_armAngles[i+0] += 5;
+ if ( event.param == 'D' ) m_armAngles[i+0] -= 5;
+ if ( event.param == 'R' ) m_armAngles[i+1] += 5;
+ if ( event.param == 'F' ) m_armAngles[i+1] -= 5;
+ if ( event.param == 'T' ) m_armAngles[i+2] += 5;
+ if ( event.param == 'G' ) m_armAngles[i+2] -= 5;
+ if ( event.param == 'Z' ) m_armAngles[i+3] += 5;
+ if ( event.param == 'H' ) m_armAngles[i+3] -= 5;
+
+ if ( event.param == 'Y' ) m_bArmStop = !m_bArmStop;
+#endif
+ }
+
+ return true;
+}
+
+// Management of an event.
+
+bool CMotionSpider::EventFrame(const Event &event)
+{
+ Math::Vector dir, pos, speed;
+ Math::Point dim;
+ float s, a, prog, time;
+ float tSt[12], tNd[12];
+ int i, ii, st, nd, action;
+ bool bStop;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
+ a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f);
+
+ if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armTimeAction += event.rTime;
+ m_armTimeMarch += (s)*event.rTime*0.15f;
+ m_armMember += (s+a)*event.rTime*0.15f;
+
+ bStop = ( a == 0.0f && s == 0.0f ); // stop?
+
+ action = MS_MARCH; // waslking
+ if ( s == 0.0f && a == 0.0f )
+ {
+ action = MS_STOP; // stop
+ }
+
+ if ( bStop )
+ {
+ prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
+ a = Math::Mod(m_armMember, 1.0f);
+ a = (prog-a)*event.rTime*2.0f; // stop position just pleasantly
+ m_armMember += a;
+ }
+
+ if ( m_object->RetRuin() ) // destroyed?
+ {
+ m_actionType = MSS_RUIN;
+ }
+ if ( m_object->RetBurn() ) // burning?
+ {
+ if ( m_object->RetFixed() )
+ {
+ m_actionType = MSS_BURN;
+ }
+ else
+ {
+ m_actionType = -1;
+ }
+ }
+
+ for ( i=0 ; i<8 ; i++ ) // the 8 legs
+ {
+ if ( m_actionType != -1 ) // special action in progress?
+ {
+ st = 3*4*4*3*MS_SPEC + 3*4*4*m_actionType + (i%4)*3;
+ nd = st;
+ time = event.rTime*m_actionTime;
+ m_armTimeAction = 0.0f;
+ }
+ else
+ {
+//? if ( i < 4 ) prog = Math::Mod(m_armMember+(2.0f-(i%4))*0.25f+0.0f, 1.0f);
+//? else prog = Math::Mod(m_armMember+(2.0f-(i%4))*0.25f+0.3f, 1.0f);
+ if ( i < 4 ) prog = Math::Mod(m_armMember+(2.0f-(i%4))*0.25f+0.0f, 1.0f);
+ else prog = Math::Mod(m_armMember+(2.0f-(i%4))*0.25f+0.5f, 1.0f);
+ if ( m_bArmStop )
+ {
+ prog = (float)m_armTimeIndex/3.0f;
+ action = MS_MARCH;
+ }
+ if ( prog < 0.33f ) // t0..t1 ?
+ {
+ prog = prog/0.33f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.67f ) // t1..t2 ?
+ {
+ prog = (prog-0.33f)/0.33f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.67f)/0.33f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ st = 3*4*4*3*action + st*3*4*4 + (i%4)*3;
+ nd = 3*4*4*3*action + nd*3*4*4 + (i%4)*3;
+
+ // Less and less soft ...
+//? time = event.rTime*(2.0f+Math::Min(m_armTimeAction*20.0f, 40.0f));
+ time = event.rTime*10.0f;
+ }
+
+ tSt[ 0] = m_armAngles[st+ 0]; // x
+ tSt[ 1] = m_armAngles[st+ 1]; // y
+ tSt[ 2] = m_armAngles[st+ 2]; // z
+ tSt[ 3] = m_armAngles[st+12]; // x
+ tSt[ 4] = m_armAngles[st+13]; // y
+ tSt[ 5] = m_armAngles[st+14]; // z
+ tSt[ 6] = m_armAngles[st+24]; // x
+ tSt[ 7] = m_armAngles[st+25]; // y
+ tSt[ 8] = m_armAngles[st+26]; // z
+ tSt[ 9] = m_armAngles[st+36]; // x
+ tSt[10] = m_armAngles[st+37]; // y
+ tSt[11] = m_armAngles[st+38]; // z
+
+ tNd[ 0] = m_armAngles[nd+ 0]; // x
+ tNd[ 1] = m_armAngles[nd+ 1]; // y
+ tNd[ 2] = m_armAngles[nd+ 2]; // z
+ tNd[ 3] = m_armAngles[nd+12]; // x
+ tNd[ 4] = m_armAngles[nd+13]; // y
+ tNd[ 5] = m_armAngles[nd+14]; // z
+ tNd[ 6] = m_armAngles[nd+24]; // x
+ tNd[ 7] = m_armAngles[nd+25]; // y
+ tNd[ 8] = m_armAngles[nd+26]; // z
+ tNd[ 9] = m_armAngles[nd+36]; // z
+ tNd[10] = m_armAngles[nd+37]; // z
+ tNd[11] = m_armAngles[nd+38]; // z
+
+ if ( m_actionType == MSS_BACK2 ) // on the back?
+ {
+ for ( ii=0 ; ii<12 ; ii++ )
+ {
+ tSt[ii] += Math::Rand()*20.0f;
+ tNd[ii] = tSt[ii];
+ }
+//? time = 100.0f;
+ time = event.rTime*10.0f;
+ }
+
+ if ( i < 4 ) // right leg (1..4) ?
+ {
+ m_object->SetAngleX(3+4*i+0, Math::Smooth(m_object->RetAngleX(3+4*i+0), Math::PropAngle(tSt[ 0], tNd[ 0], prog), time));
+ m_object->SetAngleY(3+4*i+0, Math::Smooth(m_object->RetAngleY(3+4*i+0), Math::PropAngle(tSt[ 1], tNd[ 1], prog), time));
+ m_object->SetAngleZ(3+4*i+0, Math::Smooth(m_object->RetAngleZ(3+4*i+0), Math::PropAngle(tSt[ 2], tNd[ 2], prog), time));
+ m_object->SetAngleX(3+4*i+1, Math::Smooth(m_object->RetAngleX(3+4*i+1), Math::PropAngle(tSt[ 3], tNd[ 3], prog), time));
+ m_object->SetAngleY(3+4*i+1, Math::Smooth(m_object->RetAngleY(3+4*i+1), Math::PropAngle(tSt[ 4], tNd[ 4], prog), time));
+ m_object->SetAngleZ(3+4*i+1, Math::Smooth(m_object->RetAngleZ(3+4*i+1), Math::PropAngle(tSt[ 5], tNd[ 5], prog), time));
+ m_object->SetAngleX(3+4*i+2, Math::Smooth(m_object->RetAngleX(3+4*i+2), Math::PropAngle(tSt[ 6], tNd[ 6], prog), time));
+ m_object->SetAngleY(3+4*i+2, Math::Smooth(m_object->RetAngleY(3+4*i+2), Math::PropAngle(tSt[ 7], tNd[ 7], prog), time));
+ m_object->SetAngleZ(3+4*i+2, Math::Smooth(m_object->RetAngleZ(3+4*i+2), Math::PropAngle(tSt[ 8], tNd[ 8], prog), time));
+ m_object->SetAngleX(3+4*i+3, Math::Smooth(m_object->RetAngleX(3+4*i+3), Math::PropAngle(tSt[ 9], tNd[ 9], prog), time));
+ m_object->SetAngleY(3+4*i+3, Math::Smooth(m_object->RetAngleY(3+4*i+3), Math::PropAngle(tSt[10], tNd[10], prog), time));
+ m_object->SetAngleZ(3+4*i+3, Math::Smooth(m_object->RetAngleZ(3+4*i+3), Math::PropAngle(tSt[11], tNd[11], prog), time));
+ }
+ else // left leg (5..8) ?
+ {
+ m_object->SetAngleX(3+4*i+0, Math::Smooth(m_object->RetAngleX(3+4*i+0), Math::PropAngle(-tSt[ 0], -tNd[ 0], prog), time));
+ m_object->SetAngleY(3+4*i+0, Math::Smooth(m_object->RetAngleY(3+4*i+0), Math::PropAngle(-tSt[ 1], -tNd[ 1], prog), time));
+ m_object->SetAngleZ(3+4*i+0, Math::Smooth(m_object->RetAngleZ(3+4*i+0), Math::PropAngle( tSt[ 2], tNd[ 2], prog), time));
+ m_object->SetAngleX(3+4*i+1, Math::Smooth(m_object->RetAngleX(3+4*i+1), Math::PropAngle(-tSt[ 3], -tNd[ 3], prog), time));
+ m_object->SetAngleY(3+4*i+1, Math::Smooth(m_object->RetAngleY(3+4*i+1), Math::PropAngle(-tSt[ 4], -tNd[ 4], prog), time));
+ m_object->SetAngleZ(3+4*i+1, Math::Smooth(m_object->RetAngleZ(3+4*i+1), Math::PropAngle( tSt[ 5], tNd[ 5], prog), time));
+ m_object->SetAngleX(3+4*i+2, Math::Smooth(m_object->RetAngleX(3+4*i+2), Math::PropAngle(-tSt[ 6], -tNd[ 6], prog), time));
+ m_object->SetAngleY(3+4*i+2, Math::Smooth(m_object->RetAngleY(3+4*i+2), Math::PropAngle(-tSt[ 7], -tNd[ 7], prog), time));
+ m_object->SetAngleZ(3+4*i+2, Math::Smooth(m_object->RetAngleZ(3+4*i+2), Math::PropAngle( tSt[ 8], tNd[ 8], prog), time));
+ m_object->SetAngleX(3+4*i+3, Math::Smooth(m_object->RetAngleX(3+4*i+3), Math::PropAngle(-tSt[ 9], -tNd[ 9], prog), time));
+ m_object->SetAngleY(3+4*i+3, Math::Smooth(m_object->RetAngleY(3+4*i+3), Math::PropAngle(-tSt[10], -tNd[10], prog), time));
+ m_object->SetAngleZ(3+4*i+3, Math::Smooth(m_object->RetAngleZ(3+4*i+3), Math::PropAngle( tSt[11], tNd[11], prog), time));
+ }
+ }
+
+#if ADJUST_ANGLE
+ if ( m_object->RetSelect() )
+ {
+ char s[100];
+ sprintf(s, "A:time=%d Q:part=%d W:member=%d", m_armTimeIndex, m_armPartIndex, m_armMemberIndex);
+ m_engine->SetInfoText(4, s);
+ }
+#endif
+
+ if ( m_actionType == MSS_BURN ) // burning?
+ {
+ dir = Math::Vector(Math::PI, 0.0f, 0.0f);
+ SetCirVibration(dir);
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ SetInclinaison(dir);
+
+ time = event.rTime*1.0f;
+ m_object->SetAngleZ(1, Math::Smooth(m_object->RetAngleZ(1), 0.0f, time)); // head
+ }
+ else if ( m_actionType == MSS_RUIN ) // destroyed?
+ {
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ SetCirVibration(dir);
+ SetInclinaison(dir);
+ }
+ else if ( m_actionType == MSS_EXPLO ) // exploded?
+ {
+ m_object->SetZoomY(1, 1.0f+m_progress);
+ m_object->SetZoomZ(1, 1.0f+m_progress);
+ m_object->SetZoomX(1, 1.0f+m_progress/2.0f);
+
+ dir.x = (Math::Rand()-0.5f)*0.1f*m_progress;
+ dir.y = (Math::Rand()-0.5f)*0.1f*m_progress;
+ dir.z = (Math::Rand()-0.5f)*0.1f*m_progress;
+ m_object->SetCirVibration(dir);
+ }
+ else if ( m_actionType == MSS_BACK1 ) // turns on the back?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = Math::Rand()*5.0f;
+ dim.x = Math::Rand()*3.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+
+ if ( m_progress < 0.5f )
+ {
+ dir.x = 0.0f;
+ dir.y = powf(m_progress/0.5f, 2.0f)*12.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*12.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ dir.x = m_progress*Math::PI;
+ dir.y = 0.0f;
+ dir.z = 0.0f;
+ SetCirVibration(dir);
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(MSS_BACK2, 55.0f+Math::Rand()*10.0f);
+ }
+ }
+ else if ( m_actionType == MSS_BACK2 ) // moves on the back?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ if ( rand()%10 == 0 )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*8.0f;
+ pos.z += (Math::Rand()-0.5f)*8.0f;
+ pos.y -= 1.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = Math::Rand()*2.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+ }
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ dir.x = sinf(m_armTimeAbs* 3.0f)*0.20f+
+ sinf(m_armTimeAbs* 6.0f)*0.20f+
+ sinf(m_armTimeAbs*10.0f)*0.20f+
+ sinf(m_armTimeAbs*17.0f)*0.30f+Math::PI;
+ dir.y = sinf(m_armTimeAbs* 4.0f)*0.02f+
+ sinf(m_armTimeAbs* 5.0f)*0.02f+
+ sinf(m_armTimeAbs*11.0f)*0.02f+
+ sinf(m_armTimeAbs*18.0f)*0.03f;
+ dir.z = sinf(m_armTimeAbs* 2.0f)*0.02f+
+ sinf(m_armTimeAbs* 7.0f)*0.02f+
+ sinf(m_armTimeAbs*13.0f)*0.02f+
+ sinf(m_armTimeAbs*15.0f)*0.03f;
+ SetCirVibration(dir);
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*5.0f)*0.05f); // tail
+ m_object->SetAngleY(2, cosf(m_armTimeAbs*5.0f)*0.20f); // head
+ m_object->SetAngleZ(1, 0.4f); // tail
+ m_object->SetAngleZ(2, 0.0f); // head
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(MSS_BACK3, 0.4f);
+ }
+ }
+ else if ( m_actionType == MSS_BACK3 ) // recovers on the legs?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_armTimeAbs )
+ {
+ m_lastParticule = m_armTimeAbs;
+
+ pos = m_object->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = Math::Rand()*5.0f;
+ dim.x = Math::Rand()*3.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+
+ if ( m_progress < 0.5f )
+ {
+ dir.x = 0.0f;
+ dir.y = powf(m_progress/0.5f, 2.0f)*5.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ else
+ {
+ dir.x = 0.0f;
+ dir.y = powf(2.0f-m_progress/0.5f, 2.0f)*5.0f;
+ dir.z = 0.0f;
+ SetLinVibration(dir);
+ }
+ dir.x = (1.0f-m_progress)*Math::PI;
+ dir.y = 0.0f;
+ dir.z = 0.0f;
+ SetCirVibration(dir);
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+
+ if ( m_progress >= 1.0f )
+ {
+ SetAction(-1);
+ m_object->SetFixed(false); // moving again
+ }
+ }
+ else
+ {
+ if ( bStop )
+ {
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetInclinaison(dir);
+ }
+ else
+ {
+ a = Math::Mod(m_armMember, 1.0f);
+ if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
+ else a = 3.0f-4.0f*a; // 1..-1
+ dir.x = sinf(a)*0.05f;
+
+ s = Math::Mod(m_armMember/2.0f, 1.0f);
+ if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
+ else s = 3.0f-4.0f*s; // 1..-1
+ dir.z = sinf(s)*0.1f;
+
+ dir.y = 0.0f;
+ SetInclinaison(dir);
+ }
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ SetLinVibration(dir);
+ SetCirVibration(dir);
+
+ m_object->SetAngleZ(1, sinf(m_armTimeAbs*1.7f)*0.02f); // tail
+ m_object->SetAngleX(1, sinf(m_armTimeAbs*1.3f)*0.05f);
+ m_object->SetAngleY(1, sinf(m_armTimeAbs*2.4f)*0.10f);
+ m_object->SetZoom(1, 1.0f+sinf(m_armTimeAbs*3.3f)*0.05f);
+
+ m_object->SetAngleZ(2, sinf(m_armTimeAbs*1.4f)*0.20f); // head
+ m_object->SetAngleX(2, sinf(m_armTimeAbs*1.9f)*0.10f);
+ m_object->SetAngleY(2, sinf(m_armTimeAbs*2.1f)*0.10f);
+
+ m_object->SetAngleY(35, sinf(m_armTimeAbs*3.1f)*0.20f); // mandible
+ m_object->SetAngleY(36, -sinf(m_armTimeAbs*3.1f)*0.20f); // mandible
+ }
+
+ return true;
+}
+
+
diff --git a/src/object/motion/motionspider.h b/src/object/motion/motionspider.h
index 6b34974..e9f052c 100644
--- a/src/object/motion/motionspider.h
+++ b/src/object/motion/motionspider.h
@@ -1,71 +1,71 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionspider.h
-
-#pragma once
-
-
-#include "object/motion/motion.h"
-
-
-
-enum MotionSpiderAction
-{
- MS_MARCH = 0,
- MS_STOP = 1,
- MS_SPEC = 2
-};
-
-enum MotionSpiderSpecialAction
-{
- MSS_BURN = 0,
- MSS_RUIN = 1,
- MSS_EXPLO = 2,
- MSS_BACK1 = 3,
- MSS_BACK2 = 4,
- MSS_BACK3 = 5
-};
-
-
-class CMotionSpider : public CMotion
-{
-public:
- CMotionSpider(CInstanceManager* iMan, CObject* object);
- ~CMotionSpider();
-
- void DeleteObject(bool bAll=false);
- bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- bool EventProcess(const Event &event);
-
-protected:
- void CreatePhysics();
- bool EventFrame(const Event &event);
-
-protected:
- float m_armMember;
- float m_armTimeAbs;
- float m_armTimeMarch;
- float m_armTimeAction;
- short m_armAngles[3*4*4*3*3 + 3*4*4*6];
- int m_armTimeIndex;
- int m_armPartIndex;
- int m_armMemberIndex;
- int m_armLastAction;
- bool m_bArmStop;
- float m_lastParticule;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionspider.h
+
+#pragma once
+
+
+#include "object/motion/motion.h"
+
+
+
+enum MotionSpiderAction
+{
+ MS_MARCH = 0,
+ MS_STOP = 1,
+ MS_SPEC = 2
+};
+
+enum MotionSpiderSpecialAction
+{
+ MSS_BURN = 0,
+ MSS_RUIN = 1,
+ MSS_EXPLO = 2,
+ MSS_BACK1 = 3,
+ MSS_BACK2 = 4,
+ MSS_BACK3 = 5
+};
+
+
+class CMotionSpider : public CMotion
+{
+public:
+ CMotionSpider(CInstanceManager* iMan, CObject* object);
+ ~CMotionSpider();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ bool EventProcess(const Event &event);
+
+protected:
+ void CreatePhysics();
+ bool EventFrame(const Event &event);
+
+protected:
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeMarch;
+ float m_armTimeAction;
+ short m_armAngles[3*4*4*3*3 + 3*4*4*6];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ bool m_bArmStop;
+ float m_lastParticule;
+};
+
diff --git a/src/object/motion/motiontoto.cpp b/src/object/motion/motiontoto.cpp
index 71e872a..f64570e 100644
--- a/src/object/motion/motiontoto.cpp
+++ b/src/object/motion/motiontoto.cpp
@@ -1,869 +1,869 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motiontoto.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motiontoto.h"
-
-#include "math/geometry.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "old/modfile.h"
-#include "object/robotmain.h"
-
-
-
-const float START_TIME = 1000.0f; // beginning of the relative time
-
-
-
-// Object's constructor.
-
-CMotionToto::CMotionToto(CInstanceManager* iMan, CObject* object)
- : CMotion(iMan, object)
-{
- m_time = 0.0f;
- m_bDisplayInfo = false;
- m_bQuickPos = false;
- m_bStartAction = false;
- m_speedAction = 20.0f;
- m_soundChannel = -1;
- m_clownRadius = 0.0f;
- m_clownDelay = 0.0f;
- m_clownTime = 0.0f;
- m_blinkTime = 0.0f;
- m_blinkProgress = -1.0f;
- m_lastMotorParticule = 0.0f;
- m_type = OBJECT_NULL;
- m_mousePos = Math::Point(0.0f, 0.0f);
-}
-
-// Object's destructor.
-
-CMotionToto::~CMotionToto()
-{
-}
-
-
-// Removes an object.
-
-void CMotionToto::DeleteObject(bool bAll)
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->Stop(m_soundChannel);
- m_soundChannel = -1;
- }
-}
-
-
-// Creates a vehicle traveling any lands on the ground.
-
-bool CMotionToto::Create(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 10 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- m_object->SetType(type);
-
- // Creates the head.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\toto1.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(0, pos);
- m_object->SetAngleY(0, angle);
-
- // Creates mouth.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\toto2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(1.00f, 0.17f, 0.00f));
-
- // Creates the left eye.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\toto3.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(0.85f, 1.04f, 0.25f));
- m_object->SetAngleY(2, -20.0f*Math::PI/180.0f);
-
- // Creates the right eye.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 0);
- pModFile->ReadModel("objects\\toto3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(0.85f, 1.04f, -0.25f));
- m_object->SetAngleY(3, 20.0f*Math::PI/180.0f);
-
- // Creates left antenna.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(4, rank);
- m_object->SetObjectParent(4, 0);
- pModFile->ReadModel("objects\\toto4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(4, Math::Vector(0.0f, 1.9f, 0.3f));
- m_object->SetAngleX(4, 30.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(5, rank);
- m_object->SetObjectParent(5, 4);
- pModFile->ReadModel("objects\\toto4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(5, Math::Vector(0.0f, 0.67f, 0.0f));
- m_object->SetAngleX(5, 30.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 5);
- pModFile->ReadModel("objects\\toto5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(0.0f, 0.70f, 0.0f));
- m_object->SetAngleX(6, 30.0f*Math::PI/180.0f);
-
- // Creates right antenna.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\toto4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, 1.9f, -0.3f));
- m_object->SetAngleX(7, -30.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 7);
- pModFile->ReadModel("objects\\toto4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(0.0f, 0.67f, 0.0f));
- m_object->SetAngleX(8, -30.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(9, rank);
- m_object->SetObjectParent(9, 8);
- pModFile->ReadModel("objects\\toto5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(9, Math::Vector(0.0f, 0.70f, 0.0f));
- m_object->SetAngleX(9, -30.0f*Math::PI/180.0f);
-
- m_object->SetZoom(0, 0.5f); // is little
- m_object->SetFloorHeight(0.0f);
-
- pos = m_object->RetPosition(0);
- m_object->SetPosition(0, pos); // to display the shadows immediately
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-
-// Beginning of the display of informations, with foo in the left margin.
-
-void CMotionToto::StartDisplayInfo()
-{
-return;
-//?
- m_bDisplayInfo = true;
-
- m_actionType = -1;
- m_actionTime = 0.0f;
- m_progress = 0.0f;
-
- m_object->SetAngleY(0, 0.0f);
- m_mousePos = Math::Point(0.5f, 0.5f);
-}
-
-// End of the display of informations.
-
-void CMotionToto::StopDisplayInfo()
-{
- m_bDisplayInfo = false;
- m_bQuickPos = true;
-}
-
-// Gives the position of the mouse.
-
-void CMotionToto::SetMousePos(Math::Point pos)
-{
- m_mousePos = pos;
-}
-
-
-// Management of an event.
-
-bool CMotionToto::EventProcess(const Event &event)
-{
- CMotion::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- return true;
-}
-
-// Management of an event.
-
-bool CMotionToto::EventFrame(const Event &event)
-{
- Math::Matrix* mat;
- Math::Vector eye, lookat, dir, perp, nPos, aPos, pos, speed;
- Math::Vector vibLin, vibCir, dirSpeed, aAntenna;
- Math::Point dim;
- POINT wDim;
- ParticuleType type;
- float progress, focus, distance, shift, verti, level, zoom;
- float aAngle, nAngle, mAngle, angle, linSpeed, cirSpeed;
- int sheet, i, r;
- bool bHidden;
-
- if ( m_engine->RetPause() &&
- !m_main->RetInfoLock() ) return true;
-
- if ( m_bDisplayInfo ) // "looks" mouse?
- {
- bHidden = false;
- }
- else
- {
- bHidden = false;
-
- if ( m_main->RetMovieLock() ) // current movie?
- {
- bHidden = true;
- }
- if ( !m_engine->RetTotoMode() )
- {
- if ( !m_main->RetEditLock() ) // current edition?
- {
- bHidden = true;
- }
- }
- }
-
- if ( bHidden )
- {
- nPos = m_object->RetPosition(0);
- m_terrain->MoveOnFloor(nPos, true);
- nPos.y -= 100.0f; // hidden under the ground!
- m_object->SetPosition(0, nPos);
- return true;
- }
-
- m_time += event.rTime;
- m_blinkTime -= event.rTime;
-
- progress = 0.0f;
- if ( m_actionType != -1 ) // current action?
- {
- if ( m_progress < 0.15f )
- {
- progress = m_progress/0.15f;
- }
- else if ( m_progress < 0.85f )
- {
- progress = 1.0f;
- }
- else
- {
- progress = (1.0f-m_progress)/0.15f;
- }
- }
-
- if ( m_progress >= 1.0f )
- {
- m_actionType = -1; // action ended
- m_actionTime = 0.0f;
- m_progress = 0.0f;
-
- m_clownTime = 0.0f;
- m_clownDelay = 0.0f;
- }
-
- focus = m_engine->RetFocus();
- eye = m_engine->RetEyePt();
- lookat = m_engine->RetLookatPt();
-
- vibLin = Math::Vector(0.0f, 0.0f, 0.0f);
- vibCir = Math::Vector(0.0f, 0.0f, 0.0f);
- aAntenna = Math::Vector(0.0f, 0.0f, 0.0f);
- aAntenna.x += 30.0f*Math::PI/180.0f;
-
- // Calculates the new position.
- if ( m_bDisplayInfo )
- {
- wDim = m_engine->RetDim();
- nPos.x = -4.0f*((float)wDim.x/(float)wDim.y)/(640.0f/480.0f);
- nPos.y = -0.5f;
- nPos.z = 7.0f; // in the left margin
-
- linSpeed = 0.0f;
- }
- else
- {
-#if 0
- distance = 30.0f-progress*24.5f; // remoteness
- shift = 18.0f-progress*15.4f; // shift is left
- verti = 10.0f-progress* 9.6f; // shift at the top
-#else
- distance = 30.0f-progress*18.0f; // remoteness
- shift = 18.0f-progress*11.0f; // shift is left
- verti = 10.0f-progress* 8.0f; // shift at the top
-#endif
-
- if ( m_actionType == -1 &&
- (m_type == OBJECT_HUMAN ||
- m_type == OBJECT_TECH ||
- m_type == OBJECT_MOBILEwa ||
- m_type == OBJECT_MOBILEta ||
- m_type == OBJECT_MOBILEfa ||
- m_type == OBJECT_MOBILEia ||
- m_type == OBJECT_MOBILEwc ||
- m_type == OBJECT_MOBILEtc ||
- m_type == OBJECT_MOBILEfc ||
- m_type == OBJECT_MOBILEic ||
- m_type == OBJECT_MOBILEwi ||
- m_type == OBJECT_MOBILEti ||
- m_type == OBJECT_MOBILEfi ||
- m_type == OBJECT_MOBILEii ||
- m_type == OBJECT_MOBILEws ||
- m_type == OBJECT_MOBILEts ||
- m_type == OBJECT_MOBILEfs ||
- m_type == OBJECT_MOBILEis ||
- m_type == OBJECT_MOBILErt ||
- m_type == OBJECT_MOBILErc ||
- m_type == OBJECT_MOBILErr ||
- m_type == OBJECT_MOBILErs ||
- m_type == OBJECT_MOBILEsa ||
- m_type == OBJECT_MOBILEwt ||
- m_type == OBJECT_MOBILEtt ||
- m_type == OBJECT_MOBILEft ||
- m_type == OBJECT_MOBILEit ||
- m_type == OBJECT_MOBILEdr ) ) // vehicle?
- {
- m_clownTime += event.rTime;
- if ( m_clownTime >= m_clownDelay )
- {
- if ( rand()%10 < 2 )
- {
- m_clownRadius = 2.0f+Math::Rand()*10.0f;
-//? m_clownDelay = m_clownRadius/(2.0f+Math::Rand()*2.0f);
- m_clownDelay = 1.5f+Math::Rand()*1.0f;
- }
- else
- {
- m_clownRadius = 0.0f;
- m_clownDelay = 2.0f+Math::Rand()*2.0f;
- }
- pos = m_object->RetPosition(0);
- if ( pos.y < m_water->RetLevel() ) // underwater?
- {
- m_clownRadius /= 1.5f;
- m_clownDelay *= 2.0f;
- }
- m_clownTime = 0.0f;
- }
- else
- {
- distance -= m_clownRadius*sinf(m_clownTime*Math::PI*2.0f/m_clownDelay);
- shift -= m_clownRadius-m_clownRadius*cosf(m_clownTime*Math::PI*2.0f/m_clownDelay);
- }
-
- verti += (18.0f-shift)*0.2f;
- }
-
- distance /= focus;
-//? shift *= focus;
- verti /= focus;
-
- dir = Normalize(lookat-eye);
- nPos = eye + dir*distance;
-
- perp.x = -dir.z;
- perp.y = dir.y;
- perp.z = dir.x;
- nPos = nPos + perp*shift;
-
- nPos.y += verti;
-
- if ( m_bQuickPos ) // immediately in place?
- {
- m_bQuickPos = false;
- linSpeed = 0.0f;
- }
- else
- {
- aPos = m_object->RetPosition(0);
- if ( m_actionType == -1 )
- {
- level = 4.0f;
- }
- else
- {
- if ( m_bStartAction )
- {
- m_bStartAction = false;
- m_speedAction = Math::Distance(nPos, aPos)/15.0f;
- if ( m_speedAction < 20.0f ) m_speedAction = 20.0f;
- }
- level = m_speedAction;
- }
- if ( level > 1.0f/event.rTime ) level = 1.0f/event.rTime;
- nPos = aPos + (nPos-aPos)*event.rTime*level; // progression aPos -> nPos
-
- linSpeed = Math::DistanceProjected(nPos, aPos)/event.rTime;
- dirSpeed = (nPos-aPos)/event.rTime;
- nPos.y -= linSpeed*0.015f*(1.0f-progress); // at ground level if moving fast
- }
- }
-
- // Calculate the new angle.
- nAngle = Math::NormAngle(Math::RotateAngle(eye.x-lookat.x, lookat.z-eye.z)-0.9f);
- if ( linSpeed == 0.0f || m_actionType != -1 )
- {
- mAngle = nAngle;
- }
- else
- {
- mAngle = Math::NormAngle(Math::RotateAngle(dirSpeed.x, -dirSpeed.z));
- }
- level = Math::Min(linSpeed*0.1f, 1.0f);
- nAngle = nAngle*(1.0f-level) + mAngle*level;
- aAngle = Math::NormAngle(m_object->RetAngleY(0));
-
- if ( nAngle < aAngle )
- {
- if ( nAngle+Math::PI*2.0f-aAngle < aAngle-nAngle ) nAngle += Math::PI*2.0f;
- }
- else
- {
- if ( aAngle+Math::PI*2.0f-nAngle < nAngle-aAngle ) aAngle += Math::PI*2.0f;
- }
- nAngle = aAngle + (nAngle-aAngle)*event.rTime*4.0f;
-
- // Leans quotes if running.
- cirSpeed = (aAngle-nAngle)/event.rTime;
- angle = cirSpeed*0.3f*(1.0f-progress);
- if ( angle > 0.7f ) angle = 0.7f;
- if ( angle < -0.7f ) angle = -0.7f;
- vibCir.x += angle*1.5f;
- aAntenna.x += fabs(angle)*0.8f; // deviates
-
- // Leans forward so quickly advance.
- angle = linSpeed*0.10f*(1.0f-progress);
- if ( angle > 1.0f ) angle = 1.0f;
- vibCir.z -= angle/2.0f; // leans forward
- aAntenna.z -= angle; // leans forward
-
- // Calculates the residual motion.
-#if 1
- vibLin.y += (sinf(m_time*2.00f)*0.5f+
- sinf(m_time*2.11f)*0.2f)*(1.0f-progress);
-
- vibCir.z += sinf(m_time*Math::PI* 2.01f)*(Math::PI/ 75.0f)+
- sinf(m_time*Math::PI* 2.51f)*(Math::PI/100.0f)+
- sinf(m_time*Math::PI*19.01f)*(Math::PI/200.0f);
-
- vibCir.x += sinf(m_time*Math::PI* 2.03f)*(Math::PI/ 75.0f)+
- sinf(m_time*Math::PI* 2.52f)*(Math::PI/100.0f)+
- sinf(m_time*Math::PI*19.53f)*(Math::PI/200.0f);
-
- vibCir.y += (sinf(m_time*Math::PI* 1.07f)*(Math::PI/ 10.0f)+
- sinf(m_time*Math::PI* 1.19f)*(Math::PI/ 17.0f)+
- sinf(m_time*Math::PI* 1.57f)*(Math::PI/ 31.0f))*(1.0f-progress);
-#endif
-
- // Calculates the animations in action.
- if ( m_actionType == MT_ERROR ) // no-no?
- {
- vibCir.y += progress*sinf(m_progress*Math::PI*11.0f)*1.0f;
- vibCir.z -= progress*0.5f; // leans forward
-
- aAntenna.x -= progress*0.4f; // narrows
- aAntenna.z += progress*1.0f; // leaning back
- }
-
- if ( m_actionType == MT_WARNING ) // warning?
- {
- vibCir.x += progress*sinf(m_progress*Math::PI*17.0f)*0.5f;
-
- aAntenna.x += progress*sinf(m_progress*Math::PI*17.0f)*0.5f; // deviates
- aAntenna.z += progress*cosf(m_progress*Math::PI*17.0f)*0.5f; // turns
- }
-
- if ( m_actionType == MT_INFO ) // yes-yes?
- {
- vibCir.z += progress*sinf(m_progress*Math::PI*19.0f)*0.7f;
-
- aAntenna.x -= progress*0.2f; // narrows
- aAntenna.z -= progress*cosf(m_progress*Math::PI*19.0f)*0.9f; // turns
- }
-
- if ( m_actionType == MT_MESSAGE ) // message?
- {
- vibCir.x += progress*sinf(m_progress*Math::PI*15.0f)*0.3f;
- vibCir.z += progress*cosf(m_progress*Math::PI*15.0f)*0.3f;
-
- aAntenna.x -= progress*0.4f; // narrows
- aAntenna.z -= progress*cosf(m_progress*Math::PI*19.0f)*0.8f;
- }
-
- // Initialize the object.
- if ( m_bDisplayInfo ) // "looks" mouse?
- {
- if ( m_mousePos.x < 0.15f )
- {
- progress = 1.0f-m_mousePos.x/0.15f;
- vibCir.y += progress*Math::PI/2.0f;
- }
- else
- {
- progress = (m_mousePos.x-0.15f)/0.85f;
- vibCir.y -= progress*Math::PI/3.0f;
- }
-
- angle = Math::RotateAngle(m_mousePos.x-0.1f, m_mousePos.y-0.5f-vibLin.y*0.2f);
- if ( angle < Math::PI )
- {
- if ( angle > Math::PI*0.5f ) angle = Math::PI-angle;
- if ( angle > Math::PI*0.3f ) angle = Math::PI*0.3f;
- vibCir.z += angle;
- }
- else
- {
- angle = Math::PI*2.0f-angle;
- if ( angle > Math::PI*0.5f ) angle = Math::PI-angle;
- if ( angle > Math::PI*0.3f ) angle = Math::PI*0.3f;
- vibCir.z -= angle;
- }
- }
- else
- {
- nPos.y += vibLin.y;
- level = m_terrain->RetFloorLevel(nPos);
- if ( nPos.y < level+2.0f )
- {
- nPos.y = level+2.0f; // just above the ground
- }
- nPos.y -= vibLin.y;
- }
- m_object->SetPosition(0, nPos);
- m_object->SetAngleY(0, nAngle);
-
- SetLinVibration(vibLin);
- SetCirVibration(vibCir);
-
- // Calculates the residual movement of the antennas.
- pos = aAntenna*0.40f;
- pos.x += sinf(m_time*Math::PI*2.07f)*(Math::PI/50.0f)+
- sinf(m_time*Math::PI*2.59f)*(Math::PI/70.0f)+
- sinf(m_time*Math::PI*2.67f)*(Math::PI/90.0f);
-
- pos.y += sinf(m_time*Math::PI*2.22f)*(Math::PI/50.0f)+
- sinf(m_time*Math::PI*2.36f)*(Math::PI/70.0f)+
- sinf(m_time*Math::PI*3.01f)*(Math::PI/90.0f);
-
- pos.z += sinf(m_time*Math::PI*2.11f)*(Math::PI/50.0f)+
- sinf(m_time*Math::PI*2.83f)*(Math::PI/70.0f)+
- sinf(m_time*Math::PI*3.09f)*(Math::PI/90.0f);
-
- m_object->SetAngle(4, pos); // left antenna
- m_object->SetAngle(5, pos); // left antenna
- m_object->SetAngle(6, pos); // left antenna
-
- pos = aAntenna*0.40f;
- pos.x = -pos.x;
- pos.x += sinf(m_time*Math::PI*2.33f)*(Math::PI/50.0f)+
- sinf(m_time*Math::PI*2.19f)*(Math::PI/70.0f)+
- sinf(m_time*Math::PI*2.07f)*(Math::PI/90.0f);
-
- pos.y += sinf(m_time*Math::PI*2.44f)*(Math::PI/50.0f)+
- sinf(m_time*Math::PI*2.77f)*(Math::PI/70.0f)+
- sinf(m_time*Math::PI*3.22f)*(Math::PI/90.0f);
-
- pos.z += sinf(m_time*Math::PI*2.05f)*(Math::PI/50.0f)+
- sinf(m_time*Math::PI*2.38f)*(Math::PI/70.0f)+
- sinf(m_time*Math::PI*2.79f)*(Math::PI/90.0f);
-
- m_object->SetAngle(7, pos); // right antenna
- m_object->SetAngle(8, pos); // right antenna
- m_object->SetAngle(9, pos); // right antenna
-
- // Movement of the mouth.
- if ( m_actionType == MT_ERROR ) // no-no?
- {
- m_object->SetAngleX(1, 0.0f);
- m_object->SetAngleZ(1, 0.2f+sinf(m_time*10.0f)*0.2f);
- m_object->SetZoomY(1, 2.0f+sinf(m_time*10.0f));
- m_object->SetZoomZ(1, 1.0f);
- }
- else if ( m_actionType == MT_WARNING ) // warning?
- {
- m_object->SetAngleX(1, 15.0f*Math::PI/180.0f);
- m_object->SetAngleZ(1, 0.0f);
- m_object->SetZoomY(1, 1.0f);
- m_object->SetZoomZ(1, 1.0f);
- }
- else if ( m_actionType == MT_INFO ) // yes-yes?
- {
- m_object->SetAngleX(1, 0.0f);
- m_object->SetAngleZ(1, 0.0f);
- m_object->SetZoomY(1, 1.0f);
- m_object->SetZoomZ(1, 0.7f+sinf(m_time*10.0f)*0.3f);
- }
- else if ( m_actionType == MT_MESSAGE ) // message?
- {
- m_object->SetAngleX(1, 0.0f);
- m_object->SetAngleZ(1, 0.0f);
- m_object->SetZoomY(1, 1.0f);
- m_object->SetZoomZ(1, 0.8f+sinf(m_time*7.0f)*0.2f);
- }
- else
- {
- m_object->SetAngleX(1, 0.0f);
- m_object->SetAngleZ(1, 0.0f);
- m_object->SetZoomY(1, 1.0f);
- m_object->SetZoomZ(1, 1.0f);
- }
-
- // Eye blinking management.
- if ( m_blinkTime <= 0.0f && m_blinkProgress == -1.0f )
- {
- m_blinkProgress = 0.0f;
- }
-
- if ( m_blinkProgress >= 0.0f )
- {
- m_blinkProgress += event.rTime*3.2f;
-
- if ( m_blinkProgress < 1.0f )
- {
- if ( m_blinkProgress < 0.5f ) zoom = m_blinkProgress/0.5f;
- else zoom = 2.0f-m_blinkProgress/0.5f;
- m_object->SetZoomY(2, 1.0f-zoom*0.9f);
- m_object->SetZoomY(3, 1.0f-zoom*0.9f);
- }
- else
- {
- m_blinkProgress = -1.0f;
- m_blinkTime = 0.1f+Math::Rand()*4.0f;
- m_object->SetZoomY(2, 1.0f);
- m_object->SetZoomY(3, 1.0f);
- }
- }
-
- if ( m_actionType == MT_ERROR ) // no-no?
- {
- m_object->SetAngleX(2, -30.0f*Math::PI/180.0f);
- m_object->SetAngleX(3, 30.0f*Math::PI/180.0f);
- }
- else if ( m_actionType == MT_WARNING ) // warning?
- {
- m_object->SetAngleX(2, -15.0f*Math::PI/180.0f);
- m_object->SetAngleX(3, 15.0f*Math::PI/180.0f);
- }
- else if ( m_actionType == MT_INFO ) // yes-yes?
- {
- m_object->SetAngleX(2, 40.0f*Math::PI/180.0f);
- m_object->SetAngleX(3, -40.0f*Math::PI/180.0f);
- }
- else if ( m_actionType == MT_MESSAGE ) // message?
- {
- m_object->SetAngleX(2, 20.0f*Math::PI/180.0f);
- m_object->SetAngleX(3, -20.0f*Math::PI/180.0f);
- }
- else
- {
- m_object->SetAngleX(2, 0.0f);
- m_object->SetAngleX(3, 0.0f);
- }
-
- mat = m_object->RetWorldMatrix(0); // must be done every time!
-
- // Generates particles.
- if ( m_time-m_lastMotorParticule >= m_engine->ParticuleAdapt(0.05f) )
- {
- m_lastMotorParticule = m_time;
-
- if ( m_bDisplayInfo ) sheet = SH_FRONT;
- else sheet = SH_WORLD;
-
- pos = m_object->RetPosition(0);
- if ( !m_bDisplayInfo &&
- pos.y < m_water->RetLevel() ) // underwater?
- {
- float t = Math::Mod(m_time, 3.5f);
- if ( t >= 2.2f || ( t >= 1.2f && t <= 1.4f ) ) // breathe?
- {
- pos = Math::Vector(1.0f, 0.2f, 0.0f);
- pos.z += (Math::Rand()-0.5f)*0.5f;
-
- speed = pos;
- speed.y += 5.0f+Math::Rand()*5.0f;
- speed.x += Math::Rand()*2.0f;
- speed.z += (Math::Rand()-0.5f)*2.0f;
-
- pos = Transform(*mat, pos);
- speed = Transform(*mat, speed)-pos;
-
- dim.x = 0.12f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBUBBLE, 3.0f, 0.0f, 0.0f);
- }
- }
- else // out of water?
- {
- pos = Math::Vector(0.0f, -0.5f, 0.0f);
- pos.z += (Math::Rand()-0.5f)*0.5f;
-
- speed = pos;
- speed.y -= (1.5f+Math::Rand()*1.5f) + vibLin.y;
- speed.x += (Math::Rand()-0.5f)*2.0f;
- speed.z += (Math::Rand()-0.5f)*2.0f;
-
-// mat = m_object->RetWorldMatrix(0);
- pos = Transform(*mat, pos);
- speed = Transform(*mat, speed)-pos;
-
- dim.x = (Math::Rand()*0.4f+0.4f)*(1.0f+Math::Min(linSpeed*0.1f, 5.0f));
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTITOTO, 1.0f+Math::Rand()*1.0f, 0.0f, 1.0f, sheet);
- }
-
- if ( m_actionType != -1 && // current action?
- m_progress <= 0.85f )
- {
- pos.x = (Math::Rand()-0.5f)*1.0f;
- pos.y = (Math::Rand()-0.5f)*1.0f+3.5f;
- pos.z = (Math::Rand()-0.5f)*1.0f;
- pos = Transform(*mat, pos);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = (Math::Rand()*0.3f+0.3f);
- dim.y = dim.x;
- if ( m_actionType == MT_ERROR ) type = PARTIERROR;
- if ( m_actionType == MT_WARNING ) type = PARTIWARNING;
- if ( m_actionType == MT_INFO ) type = PARTIINFO;
- if ( m_actionType == MT_MESSAGE ) type = PARTIWARNING;
- m_particule->CreateParticule(pos, speed, dim, type, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, sheet);
-
- pos.x = 0.50f+(Math::Rand()-0.5f)*0.80f;
- pos.y = 0.86f+(Math::Rand()-0.5f)*0.08f;
- pos.z = 0.00f;
- dim.x = (Math::Rand()*0.04f+0.04f);
- dim.y = dim.x/0.75f;
- m_particule->CreateParticule(pos, speed, dim, type, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, SH_INTERFACE);
- }
-
-//? if ( m_bDisplayInfo && m_main->RetGlint() )
- if ( false )
- {
- pos.x = (Math::Rand()-0.5f)*1.4f;
- pos.y = (Math::Rand()-0.5f)*1.4f+3.5f;
- pos.z = (Math::Rand()-0.5f)*1.4f;
- pos = Transform(*mat, pos);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = (Math::Rand()*0.5f+0.5f);
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, sheet);
-
- for ( i=0 ; i<10 ; i++ )
- {
- pos.x = 0.60f+(Math::Rand()-0.5f)*0.76f;
- pos.y = 0.47f+(Math::Rand()-0.5f)*0.90f;
- pos.z = 0.00f;
- r = rand()%4;
- if ( r == 0 ) pos.x = 0.21f; // the left edge
- else if ( r == 1 ) pos.x = 0.98f; // the right edge
- else if ( r == 2 ) pos.y = 0.02f; // on the lower edge
- else pos.y = 0.92f; // on the upper edge
- dim.x = (Math::Rand()*0.02f+0.02f);
- dim.y = dim.x/0.75f;
- m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, SH_INTERFACE);
- }
- }
- }
-
- // Move the sound.
- if ( m_soundChannel != -1 )
- {
- if ( !m_sound->Position(m_soundChannel, m_object->RetPosition(0)) )
- {
- m_soundChannel = -1;
- }
- }
-
- return true;
-}
-
-
-// Starts an action.
-
-Error CMotionToto::SetAction(int action, float time)
-{
- Sound sound;
-
- CMotion::SetAction(action, time);
-
- m_bStartAction = true;
-
- sound = SOUND_CLICK;
- if ( action == MT_ERROR ) sound = SOUND_ERROR;
- if ( action == MT_WARNING ) sound = SOUND_WARNING;
- if ( action == MT_INFO ) sound = SOUND_INFO;
- if ( action == MT_MESSAGE ) sound = SOUND_MESSAGE;
-
- if ( sound != SOUND_CLICK )
- {
- m_soundChannel = m_sound->Play(sound, m_object->RetPosition(0));
- }
-
- return ERR_OK;
-}
-
-// Specifies the type of the object is attached to toto.
-
-void CMotionToto::SetLinkType(ObjectType type)
-{
- m_type = type;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motiontoto.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motiontoto.h"
+
+#include "math/geometry.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "old/modfile.h"
+#include "object/robotmain.h"
+
+
+
+const float START_TIME = 1000.0f; // beginning of the relative time
+
+
+
+// Object's constructor.
+
+CMotionToto::CMotionToto(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ m_time = 0.0f;
+ m_bDisplayInfo = false;
+ m_bQuickPos = false;
+ m_bStartAction = false;
+ m_speedAction = 20.0f;
+ m_soundChannel = -1;
+ m_clownRadius = 0.0f;
+ m_clownDelay = 0.0f;
+ m_clownTime = 0.0f;
+ m_blinkTime = 0.0f;
+ m_blinkProgress = -1.0f;
+ m_lastMotorParticule = 0.0f;
+ m_type = OBJECT_NULL;
+ m_mousePos = Math::Point(0.0f, 0.0f);
+}
+
+// Object's destructor.
+
+CMotionToto::~CMotionToto()
+{
+}
+
+
+// Removes an object.
+
+void CMotionToto::DeleteObject(bool bAll)
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->Stop(m_soundChannel);
+ m_soundChannel = -1;
+ }
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+bool CMotionToto::Create(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 10 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\toto1.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // Creates mouth.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\toto2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(1.00f, 0.17f, 0.00f));
+
+ // Creates the left eye.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\toto3.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(0.85f, 1.04f, 0.25f));
+ m_object->SetAngleY(2, -20.0f*Math::PI/180.0f);
+
+ // Creates the right eye.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 0);
+ pModFile->ReadModel("objects\\toto3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(0.85f, 1.04f, -0.25f));
+ m_object->SetAngleY(3, 20.0f*Math::PI/180.0f);
+
+ // Creates left antenna.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 0);
+ pModFile->ReadModel("objects\\toto4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, Math::Vector(0.0f, 1.9f, 0.3f));
+ m_object->SetAngleX(4, 30.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 4);
+ pModFile->ReadModel("objects\\toto4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, Math::Vector(0.0f, 0.67f, 0.0f));
+ m_object->SetAngleX(5, 30.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 5);
+ pModFile->ReadModel("objects\\toto5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(0.0f, 0.70f, 0.0f));
+ m_object->SetAngleX(6, 30.0f*Math::PI/180.0f);
+
+ // Creates right antenna.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\toto4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, 1.9f, -0.3f));
+ m_object->SetAngleX(7, -30.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 7);
+ pModFile->ReadModel("objects\\toto4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(0.0f, 0.67f, 0.0f));
+ m_object->SetAngleX(8, -30.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 8);
+ pModFile->ReadModel("objects\\toto5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, Math::Vector(0.0f, 0.70f, 0.0f));
+ m_object->SetAngleX(9, -30.0f*Math::PI/180.0f);
+
+ m_object->SetZoom(0, 0.5f); // is little
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+
+// Beginning of the display of informations, with foo in the left margin.
+
+void CMotionToto::StartDisplayInfo()
+{
+return;
+//?
+ m_bDisplayInfo = true;
+
+ m_actionType = -1;
+ m_actionTime = 0.0f;
+ m_progress = 0.0f;
+
+ m_object->SetAngleY(0, 0.0f);
+ m_mousePos = Math::Point(0.5f, 0.5f);
+}
+
+// End of the display of informations.
+
+void CMotionToto::StopDisplayInfo()
+{
+ m_bDisplayInfo = false;
+ m_bQuickPos = true;
+}
+
+// Gives the position of the mouse.
+
+void CMotionToto::SetMousePos(Math::Point pos)
+{
+ m_mousePos = pos;
+}
+
+
+// Management of an event.
+
+bool CMotionToto::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ return true;
+}
+
+// Management of an event.
+
+bool CMotionToto::EventFrame(const Event &event)
+{
+ Math::Matrix* mat;
+ Math::Vector eye, lookat, dir, perp, nPos, aPos, pos, speed;
+ Math::Vector vibLin, vibCir, dirSpeed, aAntenna;
+ Math::Point dim;
+ POINT wDim;
+ ParticuleType type;
+ float progress, focus, distance, shift, verti, level, zoom;
+ float aAngle, nAngle, mAngle, angle, linSpeed, cirSpeed;
+ int sheet, i, r;
+ bool bHidden;
+
+ if ( m_engine->RetPause() &&
+ !m_main->RetInfoLock() ) return true;
+
+ if ( m_bDisplayInfo ) // "looks" mouse?
+ {
+ bHidden = false;
+ }
+ else
+ {
+ bHidden = false;
+
+ if ( m_main->RetMovieLock() ) // current movie?
+ {
+ bHidden = true;
+ }
+ if ( !m_engine->RetTotoMode() )
+ {
+ if ( !m_main->RetEditLock() ) // current edition?
+ {
+ bHidden = true;
+ }
+ }
+ }
+
+ if ( bHidden )
+ {
+ nPos = m_object->RetPosition(0);
+ m_terrain->MoveOnFloor(nPos, true);
+ nPos.y -= 100.0f; // hidden under the ground!
+ m_object->SetPosition(0, nPos);
+ return true;
+ }
+
+ m_time += event.rTime;
+ m_blinkTime -= event.rTime;
+
+ progress = 0.0f;
+ if ( m_actionType != -1 ) // current action?
+ {
+ if ( m_progress < 0.15f )
+ {
+ progress = m_progress/0.15f;
+ }
+ else if ( m_progress < 0.85f )
+ {
+ progress = 1.0f;
+ }
+ else
+ {
+ progress = (1.0f-m_progress)/0.15f;
+ }
+ }
+
+ if ( m_progress >= 1.0f )
+ {
+ m_actionType = -1; // action ended
+ m_actionTime = 0.0f;
+ m_progress = 0.0f;
+
+ m_clownTime = 0.0f;
+ m_clownDelay = 0.0f;
+ }
+
+ focus = m_engine->RetFocus();
+ eye = m_engine->RetEyePt();
+ lookat = m_engine->RetLookatPt();
+
+ vibLin = Math::Vector(0.0f, 0.0f, 0.0f);
+ vibCir = Math::Vector(0.0f, 0.0f, 0.0f);
+ aAntenna = Math::Vector(0.0f, 0.0f, 0.0f);
+ aAntenna.x += 30.0f*Math::PI/180.0f;
+
+ // Calculates the new position.
+ if ( m_bDisplayInfo )
+ {
+ wDim = m_engine->RetDim();
+ nPos.x = -4.0f*((float)wDim.x/(float)wDim.y)/(640.0f/480.0f);
+ nPos.y = -0.5f;
+ nPos.z = 7.0f; // in the left margin
+
+ linSpeed = 0.0f;
+ }
+ else
+ {
+#if 0
+ distance = 30.0f-progress*24.5f; // remoteness
+ shift = 18.0f-progress*15.4f; // shift is left
+ verti = 10.0f-progress* 9.6f; // shift at the top
+#else
+ distance = 30.0f-progress*18.0f; // remoteness
+ shift = 18.0f-progress*11.0f; // shift is left
+ verti = 10.0f-progress* 8.0f; // shift at the top
+#endif
+
+ if ( m_actionType == -1 &&
+ (m_type == OBJECT_HUMAN ||
+ m_type == OBJECT_TECH ||
+ m_type == OBJECT_MOBILEwa ||
+ m_type == OBJECT_MOBILEta ||
+ m_type == OBJECT_MOBILEfa ||
+ m_type == OBJECT_MOBILEia ||
+ m_type == OBJECT_MOBILEwc ||
+ m_type == OBJECT_MOBILEtc ||
+ m_type == OBJECT_MOBILEfc ||
+ m_type == OBJECT_MOBILEic ||
+ m_type == OBJECT_MOBILEwi ||
+ m_type == OBJECT_MOBILEti ||
+ m_type == OBJECT_MOBILEfi ||
+ m_type == OBJECT_MOBILEii ||
+ m_type == OBJECT_MOBILEws ||
+ m_type == OBJECT_MOBILEts ||
+ m_type == OBJECT_MOBILEfs ||
+ m_type == OBJECT_MOBILEis ||
+ m_type == OBJECT_MOBILErt ||
+ m_type == OBJECT_MOBILErc ||
+ m_type == OBJECT_MOBILErr ||
+ m_type == OBJECT_MOBILErs ||
+ m_type == OBJECT_MOBILEsa ||
+ m_type == OBJECT_MOBILEwt ||
+ m_type == OBJECT_MOBILEtt ||
+ m_type == OBJECT_MOBILEft ||
+ m_type == OBJECT_MOBILEit ||
+ m_type == OBJECT_MOBILEdr ) ) // vehicle?
+ {
+ m_clownTime += event.rTime;
+ if ( m_clownTime >= m_clownDelay )
+ {
+ if ( rand()%10 < 2 )
+ {
+ m_clownRadius = 2.0f+Math::Rand()*10.0f;
+//? m_clownDelay = m_clownRadius/(2.0f+Math::Rand()*2.0f);
+ m_clownDelay = 1.5f+Math::Rand()*1.0f;
+ }
+ else
+ {
+ m_clownRadius = 0.0f;
+ m_clownDelay = 2.0f+Math::Rand()*2.0f;
+ }
+ pos = m_object->RetPosition(0);
+ if ( pos.y < m_water->RetLevel() ) // underwater?
+ {
+ m_clownRadius /= 1.5f;
+ m_clownDelay *= 2.0f;
+ }
+ m_clownTime = 0.0f;
+ }
+ else
+ {
+ distance -= m_clownRadius*sinf(m_clownTime*Math::PI*2.0f/m_clownDelay);
+ shift -= m_clownRadius-m_clownRadius*cosf(m_clownTime*Math::PI*2.0f/m_clownDelay);
+ }
+
+ verti += (18.0f-shift)*0.2f;
+ }
+
+ distance /= focus;
+//? shift *= focus;
+ verti /= focus;
+
+ dir = Normalize(lookat-eye);
+ nPos = eye + dir*distance;
+
+ perp.x = -dir.z;
+ perp.y = dir.y;
+ perp.z = dir.x;
+ nPos = nPos + perp*shift;
+
+ nPos.y += verti;
+
+ if ( m_bQuickPos ) // immediately in place?
+ {
+ m_bQuickPos = false;
+ linSpeed = 0.0f;
+ }
+ else
+ {
+ aPos = m_object->RetPosition(0);
+ if ( m_actionType == -1 )
+ {
+ level = 4.0f;
+ }
+ else
+ {
+ if ( m_bStartAction )
+ {
+ m_bStartAction = false;
+ m_speedAction = Math::Distance(nPos, aPos)/15.0f;
+ if ( m_speedAction < 20.0f ) m_speedAction = 20.0f;
+ }
+ level = m_speedAction;
+ }
+ if ( level > 1.0f/event.rTime ) level = 1.0f/event.rTime;
+ nPos = aPos + (nPos-aPos)*event.rTime*level; // progression aPos -> nPos
+
+ linSpeed = Math::DistanceProjected(nPos, aPos)/event.rTime;
+ dirSpeed = (nPos-aPos)/event.rTime;
+ nPos.y -= linSpeed*0.015f*(1.0f-progress); // at ground level if moving fast
+ }
+ }
+
+ // Calculate the new angle.
+ nAngle = Math::NormAngle(Math::RotateAngle(eye.x-lookat.x, lookat.z-eye.z)-0.9f);
+ if ( linSpeed == 0.0f || m_actionType != -1 )
+ {
+ mAngle = nAngle;
+ }
+ else
+ {
+ mAngle = Math::NormAngle(Math::RotateAngle(dirSpeed.x, -dirSpeed.z));
+ }
+ level = Math::Min(linSpeed*0.1f, 1.0f);
+ nAngle = nAngle*(1.0f-level) + mAngle*level;
+ aAngle = Math::NormAngle(m_object->RetAngleY(0));
+
+ if ( nAngle < aAngle )
+ {
+ if ( nAngle+Math::PI*2.0f-aAngle < aAngle-nAngle ) nAngle += Math::PI*2.0f;
+ }
+ else
+ {
+ if ( aAngle+Math::PI*2.0f-nAngle < nAngle-aAngle ) aAngle += Math::PI*2.0f;
+ }
+ nAngle = aAngle + (nAngle-aAngle)*event.rTime*4.0f;
+
+ // Leans quotes if running.
+ cirSpeed = (aAngle-nAngle)/event.rTime;
+ angle = cirSpeed*0.3f*(1.0f-progress);
+ if ( angle > 0.7f ) angle = 0.7f;
+ if ( angle < -0.7f ) angle = -0.7f;
+ vibCir.x += angle*1.5f;
+ aAntenna.x += fabs(angle)*0.8f; // deviates
+
+ // Leans forward so quickly advance.
+ angle = linSpeed*0.10f*(1.0f-progress);
+ if ( angle > 1.0f ) angle = 1.0f;
+ vibCir.z -= angle/2.0f; // leans forward
+ aAntenna.z -= angle; // leans forward
+
+ // Calculates the residual motion.
+#if 1
+ vibLin.y += (sinf(m_time*2.00f)*0.5f+
+ sinf(m_time*2.11f)*0.2f)*(1.0f-progress);
+
+ vibCir.z += sinf(m_time*Math::PI* 2.01f)*(Math::PI/ 75.0f)+
+ sinf(m_time*Math::PI* 2.51f)*(Math::PI/100.0f)+
+ sinf(m_time*Math::PI*19.01f)*(Math::PI/200.0f);
+
+ vibCir.x += sinf(m_time*Math::PI* 2.03f)*(Math::PI/ 75.0f)+
+ sinf(m_time*Math::PI* 2.52f)*(Math::PI/100.0f)+
+ sinf(m_time*Math::PI*19.53f)*(Math::PI/200.0f);
+
+ vibCir.y += (sinf(m_time*Math::PI* 1.07f)*(Math::PI/ 10.0f)+
+ sinf(m_time*Math::PI* 1.19f)*(Math::PI/ 17.0f)+
+ sinf(m_time*Math::PI* 1.57f)*(Math::PI/ 31.0f))*(1.0f-progress);
+#endif
+
+ // Calculates the animations in action.
+ if ( m_actionType == MT_ERROR ) // no-no?
+ {
+ vibCir.y += progress*sinf(m_progress*Math::PI*11.0f)*1.0f;
+ vibCir.z -= progress*0.5f; // leans forward
+
+ aAntenna.x -= progress*0.4f; // narrows
+ aAntenna.z += progress*1.0f; // leaning back
+ }
+
+ if ( m_actionType == MT_WARNING ) // warning?
+ {
+ vibCir.x += progress*sinf(m_progress*Math::PI*17.0f)*0.5f;
+
+ aAntenna.x += progress*sinf(m_progress*Math::PI*17.0f)*0.5f; // deviates
+ aAntenna.z += progress*cosf(m_progress*Math::PI*17.0f)*0.5f; // turns
+ }
+
+ if ( m_actionType == MT_INFO ) // yes-yes?
+ {
+ vibCir.z += progress*sinf(m_progress*Math::PI*19.0f)*0.7f;
+
+ aAntenna.x -= progress*0.2f; // narrows
+ aAntenna.z -= progress*cosf(m_progress*Math::PI*19.0f)*0.9f; // turns
+ }
+
+ if ( m_actionType == MT_MESSAGE ) // message?
+ {
+ vibCir.x += progress*sinf(m_progress*Math::PI*15.0f)*0.3f;
+ vibCir.z += progress*cosf(m_progress*Math::PI*15.0f)*0.3f;
+
+ aAntenna.x -= progress*0.4f; // narrows
+ aAntenna.z -= progress*cosf(m_progress*Math::PI*19.0f)*0.8f;
+ }
+
+ // Initialize the object.
+ if ( m_bDisplayInfo ) // "looks" mouse?
+ {
+ if ( m_mousePos.x < 0.15f )
+ {
+ progress = 1.0f-m_mousePos.x/0.15f;
+ vibCir.y += progress*Math::PI/2.0f;
+ }
+ else
+ {
+ progress = (m_mousePos.x-0.15f)/0.85f;
+ vibCir.y -= progress*Math::PI/3.0f;
+ }
+
+ angle = Math::RotateAngle(m_mousePos.x-0.1f, m_mousePos.y-0.5f-vibLin.y*0.2f);
+ if ( angle < Math::PI )
+ {
+ if ( angle > Math::PI*0.5f ) angle = Math::PI-angle;
+ if ( angle > Math::PI*0.3f ) angle = Math::PI*0.3f;
+ vibCir.z += angle;
+ }
+ else
+ {
+ angle = Math::PI*2.0f-angle;
+ if ( angle > Math::PI*0.5f ) angle = Math::PI-angle;
+ if ( angle > Math::PI*0.3f ) angle = Math::PI*0.3f;
+ vibCir.z -= angle;
+ }
+ }
+ else
+ {
+ nPos.y += vibLin.y;
+ level = m_terrain->RetFloorLevel(nPos);
+ if ( nPos.y < level+2.0f )
+ {
+ nPos.y = level+2.0f; // just above the ground
+ }
+ nPos.y -= vibLin.y;
+ }
+ m_object->SetPosition(0, nPos);
+ m_object->SetAngleY(0, nAngle);
+
+ SetLinVibration(vibLin);
+ SetCirVibration(vibCir);
+
+ // Calculates the residual movement of the antennas.
+ pos = aAntenna*0.40f;
+ pos.x += sinf(m_time*Math::PI*2.07f)*(Math::PI/50.0f)+
+ sinf(m_time*Math::PI*2.59f)*(Math::PI/70.0f)+
+ sinf(m_time*Math::PI*2.67f)*(Math::PI/90.0f);
+
+ pos.y += sinf(m_time*Math::PI*2.22f)*(Math::PI/50.0f)+
+ sinf(m_time*Math::PI*2.36f)*(Math::PI/70.0f)+
+ sinf(m_time*Math::PI*3.01f)*(Math::PI/90.0f);
+
+ pos.z += sinf(m_time*Math::PI*2.11f)*(Math::PI/50.0f)+
+ sinf(m_time*Math::PI*2.83f)*(Math::PI/70.0f)+
+ sinf(m_time*Math::PI*3.09f)*(Math::PI/90.0f);
+
+ m_object->SetAngle(4, pos); // left antenna
+ m_object->SetAngle(5, pos); // left antenna
+ m_object->SetAngle(6, pos); // left antenna
+
+ pos = aAntenna*0.40f;
+ pos.x = -pos.x;
+ pos.x += sinf(m_time*Math::PI*2.33f)*(Math::PI/50.0f)+
+ sinf(m_time*Math::PI*2.19f)*(Math::PI/70.0f)+
+ sinf(m_time*Math::PI*2.07f)*(Math::PI/90.0f);
+
+ pos.y += sinf(m_time*Math::PI*2.44f)*(Math::PI/50.0f)+
+ sinf(m_time*Math::PI*2.77f)*(Math::PI/70.0f)+
+ sinf(m_time*Math::PI*3.22f)*(Math::PI/90.0f);
+
+ pos.z += sinf(m_time*Math::PI*2.05f)*(Math::PI/50.0f)+
+ sinf(m_time*Math::PI*2.38f)*(Math::PI/70.0f)+
+ sinf(m_time*Math::PI*2.79f)*(Math::PI/90.0f);
+
+ m_object->SetAngle(7, pos); // right antenna
+ m_object->SetAngle(8, pos); // right antenna
+ m_object->SetAngle(9, pos); // right antenna
+
+ // Movement of the mouth.
+ if ( m_actionType == MT_ERROR ) // no-no?
+ {
+ m_object->SetAngleX(1, 0.0f);
+ m_object->SetAngleZ(1, 0.2f+sinf(m_time*10.0f)*0.2f);
+ m_object->SetZoomY(1, 2.0f+sinf(m_time*10.0f));
+ m_object->SetZoomZ(1, 1.0f);
+ }
+ else if ( m_actionType == MT_WARNING ) // warning?
+ {
+ m_object->SetAngleX(1, 15.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(1, 0.0f);
+ m_object->SetZoomY(1, 1.0f);
+ m_object->SetZoomZ(1, 1.0f);
+ }
+ else if ( m_actionType == MT_INFO ) // yes-yes?
+ {
+ m_object->SetAngleX(1, 0.0f);
+ m_object->SetAngleZ(1, 0.0f);
+ m_object->SetZoomY(1, 1.0f);
+ m_object->SetZoomZ(1, 0.7f+sinf(m_time*10.0f)*0.3f);
+ }
+ else if ( m_actionType == MT_MESSAGE ) // message?
+ {
+ m_object->SetAngleX(1, 0.0f);
+ m_object->SetAngleZ(1, 0.0f);
+ m_object->SetZoomY(1, 1.0f);
+ m_object->SetZoomZ(1, 0.8f+sinf(m_time*7.0f)*0.2f);
+ }
+ else
+ {
+ m_object->SetAngleX(1, 0.0f);
+ m_object->SetAngleZ(1, 0.0f);
+ m_object->SetZoomY(1, 1.0f);
+ m_object->SetZoomZ(1, 1.0f);
+ }
+
+ // Eye blinking management.
+ if ( m_blinkTime <= 0.0f && m_blinkProgress == -1.0f )
+ {
+ m_blinkProgress = 0.0f;
+ }
+
+ if ( m_blinkProgress >= 0.0f )
+ {
+ m_blinkProgress += event.rTime*3.2f;
+
+ if ( m_blinkProgress < 1.0f )
+ {
+ if ( m_blinkProgress < 0.5f ) zoom = m_blinkProgress/0.5f;
+ else zoom = 2.0f-m_blinkProgress/0.5f;
+ m_object->SetZoomY(2, 1.0f-zoom*0.9f);
+ m_object->SetZoomY(3, 1.0f-zoom*0.9f);
+ }
+ else
+ {
+ m_blinkProgress = -1.0f;
+ m_blinkTime = 0.1f+Math::Rand()*4.0f;
+ m_object->SetZoomY(2, 1.0f);
+ m_object->SetZoomY(3, 1.0f);
+ }
+ }
+
+ if ( m_actionType == MT_ERROR ) // no-no?
+ {
+ m_object->SetAngleX(2, -30.0f*Math::PI/180.0f);
+ m_object->SetAngleX(3, 30.0f*Math::PI/180.0f);
+ }
+ else if ( m_actionType == MT_WARNING ) // warning?
+ {
+ m_object->SetAngleX(2, -15.0f*Math::PI/180.0f);
+ m_object->SetAngleX(3, 15.0f*Math::PI/180.0f);
+ }
+ else if ( m_actionType == MT_INFO ) // yes-yes?
+ {
+ m_object->SetAngleX(2, 40.0f*Math::PI/180.0f);
+ m_object->SetAngleX(3, -40.0f*Math::PI/180.0f);
+ }
+ else if ( m_actionType == MT_MESSAGE ) // message?
+ {
+ m_object->SetAngleX(2, 20.0f*Math::PI/180.0f);
+ m_object->SetAngleX(3, -20.0f*Math::PI/180.0f);
+ }
+ else
+ {
+ m_object->SetAngleX(2, 0.0f);
+ m_object->SetAngleX(3, 0.0f);
+ }
+
+ mat = m_object->RetWorldMatrix(0); // must be done every time!
+
+ // Generates particles.
+ if ( m_time-m_lastMotorParticule >= m_engine->ParticuleAdapt(0.05f) )
+ {
+ m_lastMotorParticule = m_time;
+
+ if ( m_bDisplayInfo ) sheet = SH_FRONT;
+ else sheet = SH_WORLD;
+
+ pos = m_object->RetPosition(0);
+ if ( !m_bDisplayInfo &&
+ pos.y < m_water->RetLevel() ) // underwater?
+ {
+ float t = Math::Mod(m_time, 3.5f);
+ if ( t >= 2.2f || ( t >= 1.2f && t <= 1.4f ) ) // breathe?
+ {
+ pos = Math::Vector(1.0f, 0.2f, 0.0f);
+ pos.z += (Math::Rand()-0.5f)*0.5f;
+
+ speed = pos;
+ speed.y += 5.0f+Math::Rand()*5.0f;
+ speed.x += Math::Rand()*2.0f;
+ speed.z += (Math::Rand()-0.5f)*2.0f;
+
+ pos = Transform(*mat, pos);
+ speed = Transform(*mat, speed)-pos;
+
+ dim.x = 0.12f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBUBBLE, 3.0f, 0.0f, 0.0f);
+ }
+ }
+ else // out of water?
+ {
+ pos = Math::Vector(0.0f, -0.5f, 0.0f);
+ pos.z += (Math::Rand()-0.5f)*0.5f;
+
+ speed = pos;
+ speed.y -= (1.5f+Math::Rand()*1.5f) + vibLin.y;
+ speed.x += (Math::Rand()-0.5f)*2.0f;
+ speed.z += (Math::Rand()-0.5f)*2.0f;
+
+// mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+ speed = Transform(*mat, speed)-pos;
+
+ dim.x = (Math::Rand()*0.4f+0.4f)*(1.0f+Math::Min(linSpeed*0.1f, 5.0f));
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTITOTO, 1.0f+Math::Rand()*1.0f, 0.0f, 1.0f, sheet);
+ }
+
+ if ( m_actionType != -1 && // current action?
+ m_progress <= 0.85f )
+ {
+ pos.x = (Math::Rand()-0.5f)*1.0f;
+ pos.y = (Math::Rand()-0.5f)*1.0f+3.5f;
+ pos.z = (Math::Rand()-0.5f)*1.0f;
+ pos = Transform(*mat, pos);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = (Math::Rand()*0.3f+0.3f);
+ dim.y = dim.x;
+ if ( m_actionType == MT_ERROR ) type = PARTIERROR;
+ if ( m_actionType == MT_WARNING ) type = PARTIWARNING;
+ if ( m_actionType == MT_INFO ) type = PARTIINFO;
+ if ( m_actionType == MT_MESSAGE ) type = PARTIWARNING;
+ m_particule->CreateParticule(pos, speed, dim, type, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, sheet);
+
+ pos.x = 0.50f+(Math::Rand()-0.5f)*0.80f;
+ pos.y = 0.86f+(Math::Rand()-0.5f)*0.08f;
+ pos.z = 0.00f;
+ dim.x = (Math::Rand()*0.04f+0.04f);
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim, type, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, SH_INTERFACE);
+ }
+
+//? if ( m_bDisplayInfo && m_main->RetGlint() )
+ if ( false )
+ {
+ pos.x = (Math::Rand()-0.5f)*1.4f;
+ pos.y = (Math::Rand()-0.5f)*1.4f+3.5f;
+ pos.z = (Math::Rand()-0.5f)*1.4f;
+ pos = Transform(*mat, pos);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = (Math::Rand()*0.5f+0.5f);
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, sheet);
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ pos.x = 0.60f+(Math::Rand()-0.5f)*0.76f;
+ pos.y = 0.47f+(Math::Rand()-0.5f)*0.90f;
+ pos.z = 0.00f;
+ r = rand()%4;
+ if ( r == 0 ) pos.x = 0.21f; // the left edge
+ else if ( r == 1 ) pos.x = 0.98f; // the right edge
+ else if ( r == 2 ) pos.y = 0.02f; // on the lower edge
+ else pos.y = 0.92f; // on the upper edge
+ dim.x = (Math::Rand()*0.02f+0.02f);
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 0.5f+Math::Rand()*0.5f, 0.0f, 1.0f, SH_INTERFACE);
+ }
+ }
+ }
+
+ // Move the sound.
+ if ( m_soundChannel != -1 )
+ {
+ if ( !m_sound->Position(m_soundChannel, m_object->RetPosition(0)) )
+ {
+ m_soundChannel = -1;
+ }
+ }
+
+ return true;
+}
+
+
+// Starts an action.
+
+Error CMotionToto::SetAction(int action, float time)
+{
+ Sound sound;
+
+ CMotion::SetAction(action, time);
+
+ m_bStartAction = true;
+
+ sound = SOUND_CLICK;
+ if ( action == MT_ERROR ) sound = SOUND_ERROR;
+ if ( action == MT_WARNING ) sound = SOUND_WARNING;
+ if ( action == MT_INFO ) sound = SOUND_INFO;
+ if ( action == MT_MESSAGE ) sound = SOUND_MESSAGE;
+
+ if ( sound != SOUND_CLICK )
+ {
+ m_soundChannel = m_sound->Play(sound, m_object->RetPosition(0));
+ }
+
+ return ERR_OK;
+}
+
+// Specifies the type of the object is attached to toto.
+
+void CMotionToto::SetLinkType(ObjectType type)
+{
+ m_type = type;
+}
+
+
diff --git a/src/object/motion/motiontoto.h b/src/object/motion/motiontoto.h
index 8edeec0..9df2d99 100644
--- a/src/object/motion/motiontoto.h
+++ b/src/object/motion/motiontoto.h
@@ -1,70 +1,70 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motiontoto.h
-
-#pragma once
-
-
-#include "object/motion/motion.h"
-
-
-
-enum MotionTotoAction
-{
- MT_ERROR = 0,
- MT_WARNING = 1,
- MT_INFO = 2,
- MT_MESSAGE = 3
-};
-
-
-class CMotionToto : public CMotion
-{
-public:
- CMotionToto(CInstanceManager* iMan, CObject* object);
- ~CMotionToto();
-
- void DeleteObject(bool bAll=false);
- bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- bool EventProcess(const Event &event);
- Error SetAction(int action, float time=0.2f);
- void SetLinkType(ObjectType type);
-
- void StartDisplayInfo();
- void StopDisplayInfo();
- void SetMousePos(Math::Point pos);
-
-protected:
- bool EventFrame(const Event &event);
-
-protected:
- float m_time;
- float m_lastMotorParticule;
- bool m_bDisplayInfo;
- bool m_bQuickPos;
- bool m_bStartAction;
- float m_speedAction;
- float m_clownRadius;
- float m_clownDelay;
- float m_clownTime;
- float m_blinkTime;
- float m_blinkProgress;
- int m_soundChannel;
- ObjectType m_type;
- Math::Point m_mousePos;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motiontoto.h
+
+#pragma once
+
+
+#include "object/motion/motion.h"
+
+
+
+enum MotionTotoAction
+{
+ MT_ERROR = 0,
+ MT_WARNING = 1,
+ MT_INFO = 2,
+ MT_MESSAGE = 3
+};
+
+
+class CMotionToto : public CMotion
+{
+public:
+ CMotionToto(CInstanceManager* iMan, CObject* object);
+ ~CMotionToto();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ bool EventProcess(const Event &event);
+ Error SetAction(int action, float time=0.2f);
+ void SetLinkType(ObjectType type);
+
+ void StartDisplayInfo();
+ void StopDisplayInfo();
+ void SetMousePos(Math::Point pos);
+
+protected:
+ bool EventFrame(const Event &event);
+
+protected:
+ float m_time;
+ float m_lastMotorParticule;
+ bool m_bDisplayInfo;
+ bool m_bQuickPos;
+ bool m_bStartAction;
+ float m_speedAction;
+ float m_clownRadius;
+ float m_clownDelay;
+ float m_clownTime;
+ float m_blinkTime;
+ float m_blinkProgress;
+ int m_soundChannel;
+ ObjectType m_type;
+ Math::Point m_mousePos;
+};
+
diff --git a/src/object/motion/motionvehicle.cpp b/src/object/motion/motionvehicle.cpp
index 6f96991..ff05695 100644
--- a/src/object/motion/motionvehicle.cpp
+++ b/src/object/motion/motionvehicle.cpp
@@ -1,2073 +1,2073 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionvehicle.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motionvehicle.h"
-
-#include "old/modfile.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "math/geometry.h"
-#include "object/brain.h"
-#include "physics/physics.h"
-
-
-
-
-
-
-// Object's constructor.
-
-CMotionVehicle::CMotionVehicle(CInstanceManager* iMan, CObject* object)
- : CMotion(iMan, object)
-{
- int i;
-
- for ( i=0 ; i<4 ; i++ )
- {
- m_wheelTurn[i] = 0.0f;
- }
- for ( i=0 ; i<3 ; i++ )
- {
- m_flyPaw[i] = 0.0f;
- }
- m_posTrackLeft = 0.0f;
- m_posTrackRight = 0.0f;
- m_partiReactor = -1;
- m_armTimeAbs = 1000.0f;
- m_armMember = 1000.0f;
- m_canonTime = 0.0f;
- m_lastTimeCanon = 0.0f;
- m_wheelLastPos = Math::Vector(0.0f, 0.0f, 0.0f);
- m_wheelLastAngle = Math::Vector(0.0f, 0.0f, 0.0f);
- m_posKey = Math::Vector(0.0f, 0.0f, 0.0f);
- m_bFlyFix = false;
-
- m_bTraceDown = false;
- m_traceColor = 1; // black
- m_traceWidth = 0.5f;
-}
-
-// Object's destructor.
-
-CMotionVehicle::~CMotionVehicle()
-{
-}
-
-
-// Removes an object.
-
-void CMotionVehicle::DeleteObject(bool bAll)
-{
- if ( m_partiReactor != -1 )
- {
- m_particule->DeleteParticule(m_partiReactor);
- m_partiReactor = -1;
- }
-}
-
-
-// Creates a vehicle traveling any lands on the ground.
-
-bool CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- CObject* pPower;
- int rank, i, j, parent;
- D3DCOLORVALUE color;
- char name[50];
-
- if ( m_engine->RetRestCreate() < 1+5+18+1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- m_object->SetType(type);
-
- // Creates the main base.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEfs )
- {
- pModFile->ReadModel("objects\\lem1f.mod");
- }
- if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts )
- {
- pModFile->ReadModel("objects\\lem1t.mod");
- }
- if ( type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEws )
- {
- if ( m_object->RetTrainer() )
- {
- pModFile->ReadModel("objects\\lem1wt.mod");
- }
- else
- {
- pModFile->ReadModel("objects\\lem1w.mod");
- }
- }
- if ( type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEis )
- {
- pModFile->ReadModel("objects\\lem1i.mod");
- }
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs )
- {
- pModFile->ReadModel("objects\\roller1.mod");
- }
- if ( type == OBJECT_MOBILEsa )
- {
- pModFile->ReadModel("objects\\subm1.mod");
- }
- if ( type == OBJECT_MOBILEtg )
- {
- pModFile->ReadModel("objects\\target.mod");
- }
- if ( type == OBJECT_MOBILEwt )
- {
- pModFile->ReadModel("objects\\trainerw.mod");
- }
- if ( type == OBJECT_MOBILEft )
- {
- pModFile->ReadModel("objects\\trainerf.mod");
- }
- if ( type == OBJECT_MOBILEtt )
- {
- pModFile->ReadModel("objects\\trainert.mod");
- }
- if ( type == OBJECT_MOBILEit )
- {
- pModFile->ReadModel("objects\\traineri.mod");
- }
- if ( type == OBJECT_MOBILEdr )
- {
- pModFile->ReadModel("objects\\drawer1.mod");
- }
- if ( type == OBJECT_APOLLO2 )
- {
- pModFile->ReadModel("objects\\apolloj1.mod");
- }
- pModFile->CreateEngineObject(rank);
-
- m_object->SetPosition(0, pos);
- m_object->SetAngleY(0, angle);
-
- // A vehicle must have a obligatory collision
- // with a sphere of center (0, y, 0) (see GetCrashSphere).
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs )
- {
- m_object->CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 6.5f, SOUND_BOUMm, 0.45f);
- m_object->SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 7.0f);
- }
- else if ( type == OBJECT_MOBILEsa )
- {
- m_object->CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 4.5f, SOUND_BOUMm, 0.45f);
- m_object->SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f);
- }
- else if ( type == OBJECT_MOBILEdr )
- {
- m_object->CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- m_object->SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 7.0f);
- }
- else if ( type == OBJECT_APOLLO2 )
- {
- m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 8.0f, SOUND_BOUMm, 0.45f);
- }
- else
- {
- m_object->CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 4.5f, SOUND_BOUMm, 0.45f);
- m_object->SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 6.0f);
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia )
- {
- // Creates the arm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\lem2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
- m_object->SetAngleZ(1, ARM_NEUTRAL_ANGLE1);
-
- // Creates the forearm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\lem3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(5.0f, 0.0f, 0.0f));
- m_object->SetAngleZ(2, ARM_NEUTRAL_ANGLE2);
-
- // Creates the hand.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\lem4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(3.5f, 0.0f, 0.0f));
- m_object->SetAngleZ(3, ARM_NEUTRAL_ANGLE3);
- m_object->SetAngleX(3, Math::PI/2.0f);
-
- // Creates the close clamp.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(4, rank);
- m_object->SetObjectParent(4, 3);
- pModFile->ReadModel("objects\\lem5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(4, Math::Vector(1.5f, 0.0f, 0.0f));
- m_object->SetAngleZ(4, -Math::PI*0.10f);
-
- // Creates the remote clamp.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(5, rank);
- m_object->SetObjectParent(5, 3);
- pModFile->ReadModel("objects\\lem6.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(5, Math::Vector(1.5f, 0.0f, 0.0f));
- m_object->SetAngleZ(5, Math::PI*0.10f);
- }
-
- if ( type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis )
- {
- // Creates the arm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\lem2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
- m_object->SetAngleZ(1, 110.0f*Math::PI/180.0f);
-
- // Creates the forearm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\lem3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(5.0f, 0.0f, 0.0f));
- m_object->SetAngleZ(2, -110.0f*Math::PI/180.0f);
-
- // Creates the sensor.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\lem4s.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(3.5f, 0.0f, 0.0f));
- m_object->SetAngleZ(3, -65.0f*Math::PI/180.0f);
- }
-
- if ( type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic )
- {
- // Creates the cannon.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\canon.mod");
- pModFile->CreateEngineObject(rank);
-//? m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
- m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
- m_object->SetAngleZ(1, 0.0f);
- }
-
- if ( type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii )
- {
- // Creates the insect cannon.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\canoni1.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
- m_object->SetAngleZ(1, 0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\canoni2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(0.0f, 2.5f, 0.0f));
- m_object->SetAngleZ(2, 0.0f);
- }
-
- if ( type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEwt )
- {
- // Creates the right-back wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\lem2w.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(-3.0f, 1.0f, -3.0f));
-
- // Creates the left-back wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\lem2w.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(-3.0f, 1.0f, 3.0f));
- m_object->SetAngleY(7, Math::PI);
-
- // Creates the right-front wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 0);
- pModFile->ReadModel("objects\\lem2w.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(2.0f, 1.0f, -3.0f));
-
- // Creates the left-front wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(9, rank);
- m_object->SetObjectParent(9, 0);
- pModFile->ReadModel("objects\\lem2w.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(9, Math::Vector(2.0f, 1.0f, 3.0f));
- m_object->SetAngleY(9, Math::PI);
- }
-
- if ( type == OBJECT_MOBILEtg )
- {
- // Creates the right-back wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\lem2w.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(-2.0f, 1.0f, -3.0f));
-
- // Creates the left-back wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\lem2w.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(-2.0f, 1.0f, 3.0f));
- m_object->SetAngleY(7, Math::PI);
-
- // Creates the right-front wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 0);
- pModFile->ReadModel("objects\\lem2w.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(3.0f, 1.0f, -3.0f));
-
- // Creates the left-front wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(9, rank);
- m_object->SetObjectParent(9, 0);
- pModFile->ReadModel("objects\\lem2w.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(9, Math::Vector(3.0f, 1.0f, 3.0f));
- m_object->SetAngleY(9, Math::PI);
- }
-
- if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts ) // caterpillars?
- {
- // Creates the right caterpillar.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\lem2t.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(0.0f, 2.0f, -3.0f));
-
- // Creates the left caterpillar.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\lem3t.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, 2.0f, 3.0f));
- }
-
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ) // large caterpillars?
- {
- // Creates the right caterpillar.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\roller2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(0.0f, 2.0f, -3.0f));
-
- // Creates the left caterpillar.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\roller3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, 2.0f, 3.0f));
- }
-
- if ( type == OBJECT_MOBILEsa ) // underwater caterpillars?
- {
- // Creates the right caterpillar.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\subm4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(0.0f, 1.0f, -3.0f));
-
- // Creates the left caterpillar.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\subm5.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, 1.0f, 3.0f));
- }
-
- if ( type == OBJECT_MOBILEdr ) // caterpillars?
- {
- // Creates the right caterpillar.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\drawer2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(0.0f, 1.0f, -3.0f));
-
- // Creates the left caterpillar.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\drawer3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(0.0f, 1.0f, 3.0f));
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEft ) // flying?
- {
- // Creates the front foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\lem2f.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(1.7f, 3.0f, 0.0f));
-
- // Creates the right-back foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\lem2f.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(-1.8f, 3.0f, -1.5f));
- m_object->SetAngleY(7, 120.0f*Math::PI/180.0f);
-
- // Creates the left-back foot.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 0);
- pModFile->ReadModel("objects\\lem2f.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(-1.8f, 3.0f, 1.5f));
- m_object->SetAngleY(8, -120.0f*Math::PI/180.0f);
- }
-
- if ( type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILEii ) // insect legs?
- {
- float table[] =
- {
- // x y z
- -1.5f, 1.2f, -0.7f, // back leg
- 0.0f, 0.0f, -1.0f,
- 0.0f, 0.0f, -2.0f,
-
- 0.0f, 1.2f, -0.9f, // middle leg
- 0.0f, 0.0f, -1.0f,
- 0.0f, 0.0f, -2.0f,
-
- 1.5f, 1.2f, -0.7f, // front leg
- 0.0f, 0.0f, -1.0f,
- 0.0f, 0.0f, -2.0f,
- };
-
- for ( i=0 ; i<3 ; i++ )
- {
- for ( j=0 ; j<3 ; j++ )
- {
- sprintf(name, "objects\\ant%d.mod", j+4); // 4..6
-
- // Creates the right leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6+i*3+j, rank);
- if ( j == 0 ) parent = 0;
- else parent = 6+i*3+j-1;
- m_object->SetObjectParent(6+i*3+j, parent);
- pModFile->ReadModel(name);
- pModFile->CreateEngineObject(rank);
- pos.x = table[i*9+j*3+0];
- pos.y = table[i*9+j*3+1];
- pos.z = table[i*9+j*3+2];
- m_object->SetPosition(6+i*3+j, pos);
-
- // Creates the left leg.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(15+i*3+j, rank);
- if ( j == 0 ) parent = 0;
- else parent = 15+i*3+j-1;
- m_object->SetObjectParent(15+i*3+j, parent);
- pModFile->ReadModel(name);
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- pos.x = table[i*9+j*3+0];
- pos.y = table[i*9+j*3+1];
- pos.z = -table[i*9+j*3+2];
- m_object->SetPosition(15+i*3+j, pos);
- }
- }
- }
-
- if ( type == OBJECT_MOBILErt )
- {
- // Creates the holder.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\roller2t.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetAngleZ(1, 0.0f);
-
- // Creates the pestle.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\roller3t.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(9.0f, 4.0f, 0.0f));
- m_object->SetAngleZ(2, 0.0f);
- }
-
- if ( type == OBJECT_MOBILErc )
- {
- // Creates the holder.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\roller2c.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(3.0f, 4.6f, 0.0f));
- m_object->SetAngleZ(1, Math::PI/8.0f);
-
- // Creates the cannon.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\roller3p.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(7.0f, 6.5f, 0.0f));
- m_object->SetAngleZ(2, 0.0f);
- }
-
- if ( type == OBJECT_MOBILErr )
- {
- // Creates the holder.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\recover1.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(2.0f, 5.0f, 0.0f));
-
- // Creates the right arm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\recover2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(0.1f, 0.0f, -5.0f));
- m_object->SetAngleZ(2, 126.0f*Math::PI/180.0f);
-
- // Creates the right forearm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\recover3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(5.0f, 0.0f, -0.5f));
- m_object->SetAngleZ(3, -144.0f*Math::PI/180.0f);
-
- // Creates the left arm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(4, rank);
- m_object->SetObjectParent(4, 1);
- pModFile->ReadModel("objects\\recover2.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(4, Math::Vector(0.1f, 0.0f, 5.0f));
- m_object->SetAngleZ(4, 126.0f*Math::PI/180.0f);
-
- // Creates the left forearm.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(5, rank);
- m_object->SetObjectParent(5, 4);
- pModFile->ReadModel("objects\\recover3.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(5, Math::Vector(5.0f, 0.0f, 0.5f));
- m_object->SetAngleZ(5, -144.0f*Math::PI/180.0f);
- }
-
- if ( type == OBJECT_MOBILErs )
- {
- // Creates the holder.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\roller2s.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetAngleZ(1, 0.0f);
-
- // Creates the intermediate piston.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\roller3s.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(7.0f, 4.5f, 0.0f));
- m_object->SetAngleZ(2, 0.0f);
-
- // Creates the piston with the sphere.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\roller4s.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(0.0f, 1.0f, 0.0f));
- m_object->SetAngleZ(3, 0.0f);
- }
-
- if ( type == OBJECT_MOBILEsa )
- {
- // Creates the holder.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\subm2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(4.2f, 3.0f, 0.0f));
-
- // Creates the right tong.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\subm3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(0.5f, 0.0f, -1.5f));
-
- // Creates the left tong.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(3, rank);
- m_object->SetObjectParent(3, 1);
- pModFile->ReadModel("objects\\subm3.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(3, Math::Vector(0.5f, 0.0f, 1.5f));
- }
-
- if ( type == OBJECT_MOBILEdr )
- {
- // Creates the carousel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\drawer4.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(-3.0f, 3.0f, 0.0f));
-
- // Creates the key.
- if ( m_object->RetToy() )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\drawer5.mod");
- pModFile->CreateEngineObject(rank);
- m_posKey = Math::Vector(3.0f, 5.7f, 0.0f);
- m_object->SetPosition(2, m_posKey);
- m_object->SetAngleY(2, 90.0f*Math::PI/180.0f);
- }
-
- // Creates pencils.
- for ( i=0 ; i<8 ; i++ )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(10+i, rank);
- m_object->SetObjectParent(10+i, 1);
- sprintf(name, "objects\\drawer%d.mod", 10+i);
- pModFile->ReadModel(name);
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(10+i, Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetAngleY(10+i, 45.0f*Math::PI/180.0f*i);
- }
- }
-
- if ( type == OBJECT_MOBILEwt )
- {
- // Creates the key.
- if ( m_object->RetToy() )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\drawer5.mod");
- pModFile->CreateEngineObject(rank);
- m_posKey = Math::Vector(0.2f, 4.1f, 0.0f);
- m_object->SetPosition(2, m_posKey);
- m_object->SetAngleY(2, 90.0f*Math::PI/180.0f);
- }
- }
-
- if ( type == OBJECT_APOLLO2 )
- {
- // Creates the accessories.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\apolloj2.mod"); // antenna
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(5.5f, 8.8f, 2.0f));
- m_object->SetAngleY(1, -120.0f*Math::PI/180.0f);
- m_object->SetAngleZ(1, 45.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2, rank);
- m_object->SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\apolloj3.mod"); // camera
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2, Math::Vector(5.5f, 2.8f, -2.0f));
- m_object->SetAngleY(2, 30.0f*Math::PI/180.0f);
-
- // Creates the wheels.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(6, rank);
- m_object->SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(6, Math::Vector(-5.75f, 1.65f, -5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(7, rank);
- m_object->SetObjectParent(7, 0);
- pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(7, Math::Vector(-5.75f, 1.65f, 5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(8, rank);
- m_object->SetObjectParent(8, 0);
- pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(8, Math::Vector(5.75f, 1.65f, -5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(9, rank);
- m_object->SetObjectParent(9, 0);
- pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(9, Math::Vector(5.75f, 1.65f, 5.00f));
-
- // Creates mud guards.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(10, rank);
- m_object->SetObjectParent(10, 0);
- pModFile->ReadModel("objects\\apolloj6.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(10, Math::Vector(-5.75f, 1.65f, -5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(11, rank);
- m_object->SetObjectParent(11, 0);
- pModFile->ReadModel("objects\\apolloj6.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(11, Math::Vector(-5.75f, 1.65f, 5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(12, rank);
- m_object->SetObjectParent(12, 0);
- pModFile->ReadModel("objects\\apolloj5.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(12, Math::Vector(5.75f, 1.65f, -5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(13, rank);
- m_object->SetObjectParent(13, 0);
- pModFile->ReadModel("objects\\apolloj5.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(13, Math::Vector(5.75f, 1.65f, 5.00f));
- }
-
-#if 1
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs )
- {
- m_object->CreateShadowCircle(6.0f, 1.0f);
- }
- else if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEsa )
- {
- m_object->CreateShadowCircle(5.0f, 1.0f);
- }
- else if ( type == OBJECT_MOBILEdr )
- {
- m_object->CreateShadowCircle(4.5f, 1.0f);
- }
- else if ( type == OBJECT_APOLLO2 )
- {
- m_object->CreateShadowCircle(7.0f, 0.8f);
- }
- else
- {
- m_object->CreateShadowCircle(4.0f, 1.0f);
- }
-#else
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs )
- {
- m_object->CreateShadowCircle(6.0f, 1.0f, D3DSHADOWTANK);
- }
- else if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts )
- {
- m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWTANK);
- }
- else if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEfs )
- {
- m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWFLY);
- }
- else if ( type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEws )
- {
- m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWWHEEL);
- }
- else if ( type == OBJECT_APOLLO2 )
- {
- m_object->CreateShadowCircle(6.0f, 0.8f);
- }
- else
- {
- m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWNORM);
- }
-#endif
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEft ) // flying?
- {
-//? color.r = 0.5f-1.0f;
-//? color.g = 0.2f-1.0f;
-//? color.b = 0.0f-1.0f; // orange
-//? color.r = 0.8f;
-//? color.g = 0.6f;
-//? color.b = 0.0f; // yellow-orange
- color.r = 0.0f;
- color.g = 0.4f;
- color.b = 0.8f; // blue
- color.a = 0.0f;
- m_object->CreateShadowLight(50.0f, color);
- }
-
- CreatePhysics(type);
- m_object->SetFloorHeight(0.0f);
-
- if ( power > 0.0f &&
- type != OBJECT_MOBILEdr &&
- type != OBJECT_APOLLO2 )
- {
- color.r = 1.0f;
- color.g = 1.0f;
- color.b = 0.0f; // yellow
- color.a = 0.0f;
- m_object->CreateEffectLight(20.0f, color);
-
- // Creates the battery.
- pPower = new CObject(m_iMan);
- pPower->SetType(power<=1.0f?OBJECT_POWER:OBJECT_ATOMIC);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- pPower->SetObjectRank(0, rank);
-
- if ( power <= 1.0f ) pModFile->ReadModel("objects\\power.mod");
- else pModFile->ReadModel("objects\\atomic.mod");
- pModFile->CreateEngineObject(rank);
-
- pPower->SetPosition(0, m_object->RetCharacter()->posPower);
- pPower->CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- pPower->SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.5f);
-
- pPower->SetTruck(m_object);
- m_object->SetPower(pPower);
-
- if ( power <= 1.0f ) pPower->SetEnergy(power);
- else pPower->SetEnergy(power/100.0f);
- }
-
- pos = m_object->RetPosition(0);
- m_object->SetPosition(0, pos); //to display the shadows immediately
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-// Creates the physics of the object.
-
-void CMotionVehicle::CreatePhysics(ObjectType type)
-{
- Character* character;
-
- character = m_object->RetCharacter();
-
- if ( type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEwt ) // wheels?
- {
- m_physics->SetType(TYPE_ROLLING);
-
- character->wheelFront = 3.0f;
- character->wheelBack = 4.0f;
- character->wheelLeft = 4.0f;
- character->wheelRight = 4.0f;
- character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 20.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 30.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 8.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 8.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 12.0f);
- }
-
- if ( type == OBJECT_MOBILEtg )
- {
- m_physics->SetType(TYPE_ROLLING);
-
- character->wheelFront = 4.0f;
- character->wheelBack = 3.0f;
- character->wheelLeft = 4.0f;
- character->wheelRight = 4.0f;
- character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 20.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 20.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 15.0f);
- }
-
- if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts ) // caterpillars?
- {
- m_physics->SetType(TYPE_ROLLING);
-
- character->wheelFront = 4.0f;
- character->wheelBack = 4.0f;
- character->wheelLeft = 4.8f;
- character->wheelRight = 4.8f;
- character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 8.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 8.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 6.0f);
- }
-
- if ( type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEis ) // legs?
- {
- m_physics->SetType(TYPE_ROLLING);
-
- character->wheelFront = 4.0f;
- character->wheelBack = 4.0f;
- character->wheelLeft = 5.0f;
- character->wheelRight = 5.0f;
- character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 8.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 10.0f);
-//? m_physics->SetLinMotionX(MO_TERFORCE, 15.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 15.0f);
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEft ) // flying?
- {
- m_physics->SetType(TYPE_FLYING);
-
- character->wheelFront = 5.0f;
- character->wheelBack = 4.0f;
- character->wheelLeft = 4.5f;
- character->wheelRight = 4.5f;
- character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 50.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 50.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
- m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
- m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
- m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
- m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.4f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.4f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 2.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 2.0f);
- }
-
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ) // large caterpillars?
- {
- m_physics->SetType(TYPE_ROLLING);
-
- character->wheelFront = 5.0f;
- character->wheelBack = 5.0f;
- character->wheelLeft = 6.0f;
- character->wheelRight = 6.0f;
- character->posPower = Math::Vector(-5.8f, 4.0f, 0.0f);
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 10.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 5.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 5.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.3f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.3f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 2.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 4.0f);
- }
-
- if ( type == OBJECT_MOBILEsa )
- {
- m_physics->SetType(TYPE_ROLLING);
-
- character->wheelFront = 4.0f;
- character->wheelBack = 4.0f;
- character->wheelLeft = 4.0f;
- character->wheelRight = 4.0f;
- character->posPower = Math::Vector(-5.0f, 3.0f, 0.0f);
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 5.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 5.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 10.0f);
- }
-
- if ( type == OBJECT_MOBILEdr )
- {
- m_physics->SetType(TYPE_ROLLING);
-
- character->wheelFront = 4.0f;
- character->wheelBack = 4.0f;
- character->wheelLeft = 4.0f;
- character->wheelRight = 4.0f;
- character->posPower = Math::Vector(-5.0f, 3.0f, 0.0f);
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 5.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 5.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 10.0f);
- }
-
- if ( type == OBJECT_APOLLO2 ) // jeep?
- {
- m_physics->SetType(TYPE_ROLLING);
-
- character->wheelFront = 6.0f;
- character->wheelBack = 6.0f;
- character->wheelLeft = 5.0f;
- character->wheelRight = 5.0f;
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 2.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 2.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 30.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.4f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.4f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 2.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 4.0f);
- }
-}
-
-
-// Management of an event.
-
-bool CMotionVehicle::EventProcess(const Event &event)
-{
- CMotion::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
- }
-
- return true;
-}
-
-// Management of an event.
-
-bool CMotionVehicle::EventFrame(const Event &event)
-{
- Math::Matrix* mat;
- Character* character;
- Math::Vector pos, angle, floor;
- ObjectType type;
- float s, a, speedBL, speedBR, speedFL, speedFR, h, a1, a2;
- float back, front, dist, radius, limit[2];
-
- if ( m_engine->RetPause() ) return true;
- if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
-
- type = m_object->RetType();
-
- if ( type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_APOLLO2 ) // wheels?
- {
- s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.0f;
- a = m_physics->RetCirMotionY(MO_MOTSPEED)*3.0f;
-
- if ( type == OBJECT_APOLLO2 ) s *= 0.5f;
-
- speedBR = -s+a;
- speedBL = s+a;
- speedFR = -s+a;
- speedFL = s+a;
-
- m_object->SetAngleZ(6, m_object->RetAngleZ(6)+event.rTime*speedBR); // turning the wheels
- m_object->SetAngleZ(7, m_object->RetAngleZ(7)+event.rTime*speedBL);
- m_object->SetAngleZ(8, m_object->RetAngleZ(8)+event.rTime*speedFR);
- m_object->SetAngleZ(9, m_object->RetAngleZ(9)+event.rTime*speedFL);
-
- if ( s > 0.0f )
- {
- m_wheelTurn[0] = -a*0.05f;
- m_wheelTurn[1] = -a*0.05f+Math::PI;
- m_wheelTurn[2] = a*0.05f;
- m_wheelTurn[3] = a*0.05f+Math::PI;
- }
- else if ( s < 0.0f )
- {
- m_wheelTurn[0] = a*0.05f;
- m_wheelTurn[1] = a*0.05f+Math::PI;
- m_wheelTurn[2] = -a*0.05f;
- m_wheelTurn[3] = -a*0.05f+Math::PI;
- }
- else
- {
- m_wheelTurn[0] = fabs(a)*0.05f;
- m_wheelTurn[1] = -fabs(a)*0.05f+Math::PI;
- m_wheelTurn[2] = -fabs(a)*0.05f;
- m_wheelTurn[3] = fabs(a)*0.05f+Math::PI;
- }
- m_object->SetAngleY(6, m_object->RetAngleY(6)+(m_wheelTurn[0]-m_object->RetAngleY(6))*event.rTime*8.0f);
- m_object->SetAngleY(7, m_object->RetAngleY(7)+(m_wheelTurn[1]-m_object->RetAngleY(7))*event.rTime*8.0f);
- m_object->SetAngleY(8, m_object->RetAngleY(8)+(m_wheelTurn[2]-m_object->RetAngleY(8))*event.rTime*8.0f);
- m_object->SetAngleY(9, m_object->RetAngleY(9)+(m_wheelTurn[3]-m_object->RetAngleY(9))*event.rTime*8.0f);
-
- if ( type == OBJECT_APOLLO2 )
- {
- m_object->SetAngleY(10, m_object->RetAngleY(6)+(m_wheelTurn[0]-m_object->RetAngleY(6))*event.rTime*8.0f);
- m_object->SetAngleY(11, m_object->RetAngleY(7)+(m_wheelTurn[1]-m_object->RetAngleY(7))*event.rTime*8.0f+Math::PI);
- m_object->SetAngleY(12, m_object->RetAngleY(8)+(m_wheelTurn[2]-m_object->RetAngleY(8))*event.rTime*8.0f);
- m_object->SetAngleY(13, m_object->RetAngleY(9)+(m_wheelTurn[3]-m_object->RetAngleY(9))*event.rTime*8.0f+Math::PI);
- }
-
- pos = m_object->RetPosition(0);
- angle = m_object->RetAngle(0);
- if ( pos.x != m_wheelLastPos.x ||
- pos.y != m_wheelLastPos.y ||
- pos.z != m_wheelLastPos.z ||
- angle.x != m_wheelLastAngle.x ||
- angle.y != m_wheelLastAngle.y ||
- angle.z != m_wheelLastAngle.z )
- {
- m_wheelLastPos = pos;
- m_wheelLastAngle = angle;
-
- if ( type == OBJECT_MOBILEtg )
- {
- back = -2.0f; // back wheels position
- front = 3.0f; // front wheels position
- dist = 3.0f; // distancing wheels Z
- radius = 1.0f;
- }
- else if ( type == OBJECT_APOLLO2 )
- {
- back = -5.75f; // back wheels position
- front = 5.75f; // front wheels position
- dist = 5.00f; // distancing wheels Z
- radius = 1.65f;
- }
- else
- {
- back = -3.0f; // back wheels position
- front = 2.0f; // front wheels position
- dist = 3.0f; // distancing wheels Z
- radius = 1.0f;
- }
-
- if ( Math::Distance(pos, m_engine->RetEyePt()) < 50.0f ) // suspension?
- {
- character = m_object->RetCharacter();
- mat = m_object->RetWorldMatrix(0);
-
- pos.x = -character->wheelBack; // right back wheel
- pos.z = -character->wheelRight;
- pos.y = 0.0f;
- pos = Math::Transform(*mat, pos);
- h = m_terrain->RetFloorHeight(pos);
- if ( h > 0.5f ) h = 0.5f;
- if ( h < -0.5f ) h = -0.5f;
- pos.x = back;
- pos.y = radius-h;
- pos.z = -dist;
- m_object->SetPosition(6, pos);
- if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(10, pos);
-
- pos.x = -character->wheelBack; // left back wheel
- pos.z = character->wheelLeft;
- pos.y = 0.0f;
- pos = Math::Transform(*mat, pos);
- h = m_terrain->RetFloorHeight(pos);
- if ( h > 0.5f ) h = 0.5f;
- if ( h < -0.5f ) h = -0.5f;
- pos.x = back;
- pos.y = radius-h;
- pos.z = dist;
- m_object->SetPosition(7, pos);
- if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(11, pos);
-
- pos.x = character->wheelFront; // right front wheel
- pos.z = -character->wheelRight;
- pos.y = 0.0f;
- pos = Math::Transform(*mat, pos);
- h = m_terrain->RetFloorHeight(pos);
- if ( h > 0.5f ) h = 0.5f;
- if ( h < -0.5f ) h = -0.5f;
- pos.x = front;
- pos.y = radius-h;
- pos.z = -dist;
- m_object->SetPosition(8, pos);
- if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(12, pos);
-
- pos.x = character->wheelFront; // left front wheel
- pos.z = character->wheelLeft;
- pos.y = 0.0f;
- pos = Math::Transform(*mat, pos);
- h = m_terrain->RetFloorHeight(pos);
- if ( h > 0.5f ) h = 0.5f;
- if ( h < -0.5f ) h = -0.5f;
- pos.x = front;
- pos.y = radius-h;
- pos.z = dist;
- m_object->SetPosition(9, pos);
- if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(13, pos);
- }
- else
- {
- m_object->SetPosition(6, Math::Vector(back, radius, -dist));
- m_object->SetPosition(7, Math::Vector(back, radius, dist));
- m_object->SetPosition(8, Math::Vector(front, radius, -dist));
- m_object->SetPosition(9, Math::Vector(front, radius, dist));
-
- if ( type == OBJECT_APOLLO2 )
- {
- m_object->SetPosition(10, Math::Vector(back, radius, -dist));
- m_object->SetPosition(11, Math::Vector(back, radius, dist));
- m_object->SetPosition(12, Math::Vector(front, radius, -dist));
- m_object->SetPosition(13, Math::Vector(front, radius, dist));
- }
- }
- }
- }
-
- if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEdr ) // caterpillars?
- {
- s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.7f;
- a = m_physics->RetCirMotionY(MO_MOTSPEED)*2.5f;
-
- m_posTrackLeft += event.rTime*(s+a);
- m_posTrackRight += event.rTime*(s-a);
-
- UpdateTrackMapping(m_posTrackLeft, m_posTrackRight, type);
-
- pos = m_object->RetPosition(0);
- angle = m_object->RetAngle(0);
- if ( pos.x != m_wheelLastPos.x ||
- pos.y != m_wheelLastPos.y ||
- pos.z != m_wheelLastPos.z ||
- angle.x != m_wheelLastAngle.x ||
- angle.y != m_wheelLastAngle.y ||
- angle.z != m_wheelLastAngle.z )
- {
- m_wheelLastPos = pos;
- m_wheelLastAngle = angle;
-
- if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts )
- {
- limit[0] = 8.0f*Math::PI/180.0f;
- limit[1] = -12.0f*Math::PI/180.0f;
- }
- else if ( type == OBJECT_MOBILEsa )
- {
- limit[0] = 15.0f*Math::PI/180.0f;
- limit[1] = -15.0f*Math::PI/180.0f;
- }
- else if ( type == OBJECT_MOBILEdr )
- {
- limit[0] = 10.0f*Math::PI/180.0f;
- limit[1] = -10.0f*Math::PI/180.0f;
- }
- else
- {
- limit[0] = 15.0f*Math::PI/180.0f;
- limit[1] = -10.0f*Math::PI/180.0f;
- }
-
- if ( Math::Distance(pos, m_engine->RetEyePt()) < 50.0f ) // suspension?
- {
- character = m_object->RetCharacter();
- mat = m_object->RetWorldMatrix(0);
-
- pos.x = character->wheelFront; // right front wheel
- pos.z = -character->wheelRight;
- pos.y = 0.0f;
- pos = Transform(*mat, pos);
- a1 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelFront);
-
- pos.x = -character->wheelBack; // right back wheel
- pos.z = -character->wheelRight;
- pos.y = 0.0f;
- pos = Transform(*mat, pos);
- a2 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelBack);
-
- a = (a2-a1)/2.0f;
- if ( a > limit[0] ) a = limit[0];
- if ( a < limit[1] ) a = limit[1];
- m_object->SetAngleZ(6, a);
-
- pos.x = character->wheelFront; // left front wheel
- pos.z = character->wheelLeft;
- pos.y = 0.0f;
- pos = Transform(*mat, pos);
- a1 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelFront);
-
- pos.x = -character->wheelBack; // left back wheel
- pos.z = character->wheelLeft;
- pos.y = 0.0f;
- pos = Transform(*mat, pos);
- a2 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelBack);
-
- a = (a2-a1)/2.0f;
- if ( a > limit[0] ) a = limit[0];
- if ( a < limit[1] ) a = limit[1];
- m_object->SetAngleZ(7, a);
- }
- else
- {
- m_object->SetAngleZ(6, 0.0f);
- m_object->SetAngleZ(7, 0.0f);
- }
- }
- }
-
- if ( type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEdr ) // toy is key?
- {
- pos = m_posKey;
- if ( m_object->RetSelect() &&
- m_camera->RetType() == CAMERA_ONBOARD )
- {
- pos.y += 10.0f; // out of sight!
- }
- m_object->SetPosition(2, pos);
-
- s = -fabs(m_physics->RetLinMotionX(MO_MOTSPEED)*0.1f);
- s += -fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*1.5f);
- m_object->SetAngleY(2, m_object->RetAngleY(2)+event.rTime*s); // turns the key
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEft ) // flying?
- {
- EventFrameFly(event);
- }
-
- if ( type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEis ) // legs?
- {
- EventFrameInsect(event);
- }
-
- if ( type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEii ) // insect cannon?
- {
- EventFrameCanoni(event);
- }
-
- return true;
-}
-
-// Managing an event for a flying robot.
-
-bool CMotionVehicle::EventFrameFly(const Event &event)
-{
- Math::Matrix* mat;
- Math::Vector pos, angle, paw[3];
- float hope[3], actual, final, h, a;
- int i;
-
- pos = m_object->RetPosition(0);
- angle = m_object->RetAngle(0);
- if ( m_bFlyFix &&
- pos.x == m_wheelLastPos.x &&
- pos.y == m_wheelLastPos.y &&
- pos.z == m_wheelLastPos.z &&
- angle.x == m_wheelLastAngle.x &&
- angle.y == m_wheelLastAngle.y &&
- angle.z == m_wheelLastAngle.z ) return true;
-
- m_wheelLastPos = pos;
- m_wheelLastAngle = angle;
-
- if ( m_physics->RetLand() ) // on the ground?
- {
- mat = m_object->RetWorldMatrix(0);
- paw[0] = Transform(*mat, Math::Vector( 4.2f, 0.0f, 0.0f)); // front
- paw[1] = Transform(*mat, Math::Vector(-3.0f, 0.0f, -3.7f)); // right back
- paw[2] = Transform(*mat, Math::Vector(-3.0f, 0.0f, 3.7f)); // left back
-
- for ( i=0 ; i<3 ; i++ )
- {
- h = m_terrain->RetFloorHeight(paw[i]);
- a = -atanf(h*0.5f);
- if ( a > Math::PI*0.2f ) a = Math::PI*0.2f;
- if ( a < -Math::PI*0.2f ) a = -Math::PI*0.2f;
- hope[i] = a;
- }
- }
- else // in flight?
- {
- hope[0] = 0.0f; // front
- hope[1] = 0.0f; // right back
- hope[2] = 0.0f; // left back
- }
-
- m_bFlyFix = true;
- for ( i=0 ; i<3 ; i++ )
- {
- actual = m_object->RetAngleZ(6+i);
- final = Math::Smooth(actual, hope[i], event.rTime*5.0f);
- if ( final != actual )
- {
- m_bFlyFix = false; // it is moving
- m_object->SetAngleZ(6+i, final);
- }
- }
-
- return true;
-}
-
-// Event management for insect legs.
-
-bool CMotionVehicle::EventFrameInsect(const Event &event)
-{
- Math::Vector dir;
- float s, a, prog, time;
- int i, st, nd, action;
- bool bStop, bOnBoard;
-
- static int table[] =
- {
- // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
- 60,25,0, 60,0,0, 60,-25,0, // t0: thighs 1..4
- -35,0,0, -35,0,0, -35,0,0, // t0: legs 1..4
- -65,0,0, -65,0,0, -65,0,0, // t0: feet 1..4
- // on the ground:
- 30,10,0, 30,-15,0, 30,-40,0, // t1: thighs 1..4
- -45,0,0, -45,0,0, -45,0,0, // t1: legs 1..4
- -20,0,0, -20,0,0, -20,0,0, // t1: feet 1..4
- // on the ground back:
- 35,40,0, 40,15,0, 40,-10,0, // t2: thighs 1..4
- -35,0,0, -35,0,0, -35,0,0, // t2: legs 1..4
- -50,0,0, -65,0,0, -65,0,0, // t2: feet 1..4
- // stop:
- 35,35,0, 40,10,0, 40,-15,0, // s0: thighs 1..4
- -35,0,0, -35,0,0, -35,0,0, // s0: legs 1..4
- -50,0,0, -65,0,0, -65,0,0, // s0: feet 1..4
- };
-
- bOnBoard = false;
- if ( m_object->RetSelect() &&
- m_camera->RetType() == CAMERA_ONBOARD )
- {
- bOnBoard = true;
- }
-
- s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
- a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f);
-
- if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
-
- m_armTimeAbs += event.rTime;
- m_armMember += (s+a)*event.rTime*0.15f;
-
- bStop = ( a == 0.0f && s == 0.0f ); // stop?
-
- action = 0; // walking
- if ( s == 0.0f && a == 0.0f )
- {
- action = 3; // stop
- }
-
- if ( bStop )
- {
- prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
- a = Math::Mod(m_armMember, 1.0f);
- a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly
- m_armMember += a;
- }
-
- if ( m_object->RetRuin() ) // burn or explode?
- {
- action = 3;
- }
-
- for ( i=0 ; i<6 ; i++ ) // the six legs
- {
- if ( action != 0 ) // special action in progress?
- {
- st = 3*3*3*action + (i%3)*3;
- nd = st;
- time = event.rTime*5.0f;
- }
- else
- {
- if ( i < 3 ) prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
- else prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
- if ( prog < 0.33f ) // t0..t1 ?
- {
- prog = prog/0.33f; // 0..1
- st = 0; // index start
- nd = 1; // index end
- }
- else if ( prog < 0.67f ) // t1..t2 ?
- {
- prog = (prog-0.33f)/0.33f; // 0..1
- st = 1; // index start
- nd = 2; // index end
- }
- else // t2..t0 ?
- {
- prog = (prog-0.67f)/0.33f; // 0..1
- st = 2; // index start
- nd = 0; // index end
- }
- st = 3*3*3*action + st*3*3*3 + (i%3)*3;
- nd = 3*3*3*action + nd*3*3*3 + (i%3)*3;
-
- // Less and less soft ...
- time = event.rTime*20.0f;
- }
-
- if ( i < 3 ) // right leg (1..3) ?
- {
- m_object->SetAngleX(6+3*i+0, Math::Smooth(m_object->RetAngleX(6+3*i+0), Math::PropAngle(table[st+ 0], table[nd+ 0], prog), time));
- m_object->SetAngleY(6+3*i+0, Math::Smooth(m_object->RetAngleY(6+3*i+0), Math::PropAngle(table[st+ 1], table[nd+ 1], prog), time));
- m_object->SetAngleZ(6+3*i+0, Math::Smooth(m_object->RetAngleZ(6+3*i+0), Math::PropAngle(table[st+ 2], table[nd+ 2], prog), time));
- m_object->SetAngleX(6+3*i+1, Math::Smooth(m_object->RetAngleX(6+3*i+1), Math::PropAngle(table[st+ 9], table[nd+ 9], prog), time));
- m_object->SetAngleY(6+3*i+1, Math::Smooth(m_object->RetAngleY(6+3*i+1), Math::PropAngle(table[st+10], table[nd+10], prog), time));
- m_object->SetAngleZ(6+3*i+1, Math::Smooth(m_object->RetAngleZ(6+3*i+1), Math::PropAngle(table[st+11], table[nd+11], prog), time));
- m_object->SetAngleX(6+3*i+2, Math::Smooth(m_object->RetAngleX(6+3*i+2), Math::PropAngle(table[st+18], table[nd+18], prog), time));
- m_object->SetAngleY(6+3*i+2, Math::Smooth(m_object->RetAngleY(6+3*i+2), Math::PropAngle(table[st+19], table[nd+19], prog), time));
- m_object->SetAngleZ(6+3*i+2, Math::Smooth(m_object->RetAngleZ(6+3*i+2), Math::PropAngle(table[st+20], table[nd+20], prog), time));
- }
- else // left leg (4..6) ?
- {
- m_object->SetAngleX(6+3*i+0, Math::Smooth(m_object->RetAngleX(6+3*i+0), Math::PropAngle(-table[st+ 0], -table[nd+ 0], prog), time));
- m_object->SetAngleY(6+3*i+0, Math::Smooth(m_object->RetAngleY(6+3*i+0), Math::PropAngle(-table[st+ 1], -table[nd+ 1], prog), time));
- m_object->SetAngleZ(6+3*i+0, Math::Smooth(m_object->RetAngleZ(6+3*i+0), Math::PropAngle( table[st+ 2], table[nd+ 2], prog), time));
- m_object->SetAngleX(6+3*i+1, Math::Smooth(m_object->RetAngleX(6+3*i+1), Math::PropAngle(-table[st+ 9], -table[nd+ 9], prog), time));
- m_object->SetAngleY(6+3*i+1, Math::Smooth(m_object->RetAngleY(6+3*i+1), Math::PropAngle(-table[st+10], -table[nd+10], prog), time));
- m_object->SetAngleZ(6+3*i+1, Math::Smooth(m_object->RetAngleZ(6+3*i+1), Math::PropAngle( table[st+11], table[nd+11], prog), time));
- m_object->SetAngleX(6+3*i+2, Math::Smooth(m_object->RetAngleX(6+3*i+2), Math::PropAngle(-table[st+18], -table[nd+18], prog), time));
- m_object->SetAngleY(6+3*i+2, Math::Smooth(m_object->RetAngleY(6+3*i+2), Math::PropAngle(-table[st+19], -table[nd+19], prog), time));
- m_object->SetAngleZ(6+3*i+2, Math::Smooth(m_object->RetAngleZ(6+3*i+2), Math::PropAngle( table[st+20], table[nd+20], prog), time));
- }
- }
-
- if ( bStop )
- {
- }
- else
- {
- a = Math::Mod(m_armMember, 1.0f);
- if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
- else a = 3.0f-4.0f*a; // 1..-1
- dir.x = sinf(a)*0.05f;
-
- s = Math::Mod(m_armMember/2.0f, 1.0f);
- if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
- else s = 3.0f-4.0f*s; // 1..-1
- dir.z = sinf(s)*0.1f;
-
- dir.y = 0.0f;
-
- if ( bOnBoard ) dir *= 0.6f;
- SetInclinaison(dir);
- }
-
- return true;
-}
-
-// Event management for a insect cannon.
-
-bool CMotionVehicle::EventFrameCanoni(const Event &event)
-{
- CObject* power;
- Math::Vector pos, speed;
- Math::Point dim;
- float zoom, angle, energy, factor;
- bool bOnBoard = false;
-
- m_canonTime += event.rTime;
-
- if ( m_object->RetSelect() &&
- m_camera->RetType() == CAMERA_ONBOARD )
- {
- bOnBoard = true;
- }
-
- power = m_object->RetPower();
- if ( power == 0 )
- {
- energy = 0.0f;
- }
- else
- {
- energy = power->RetEnergy();
- }
- if ( energy == 0.0f ) return true;
-
- factor = 0.5f+energy*0.5f;
- if ( bOnBoard ) factor *= 0.8f;
-
- zoom = 1.3f+
- sinf(m_canonTime*Math::PI*0.31f)*0.10f+
- sinf(m_canonTime*Math::PI*0.52f)*0.08f+
- sinf(m_canonTime*Math::PI*1.53f)*0.05f;
- zoom *= factor;
- m_object->SetZoomY(2, zoom);
-
- zoom = 1.0f+
- sinf(m_canonTime*Math::PI*0.27f)*0.07f+
- sinf(m_canonTime*Math::PI*0.62f)*0.06f+
- sinf(m_canonTime*Math::PI*1.73f)*0.03f;
- zoom *= factor;
- m_object->SetZoomZ(2, zoom);
-
- angle = sinf(m_canonTime*1.0f)*0.10f+
- sinf(m_canonTime*1.3f)*0.15f+
- sinf(m_canonTime*2.7f)*0.05f;
- m_object->SetAngleX(2, angle);
-
-#if 0
- m_lastTimeCanon -= event.rTime;
- if ( m_lastTimeCanon <= 0.0f )
- {
- m_lastTimeCanon = m_engine->ParticuleAdapt(0.5f+Math::Rand()*0.5f);
-
- pos = m_object->RetPosition(0);
- pos.y += 8.0f;
- speed.y = 7.0f+Math::Rand()*3.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = 2.0f+Math::Rand()*2.0f;
- if ( Math::Rand() < 0.5f ) speed.z = -speed.z;
- mat = m_object->RetRotateMatrix(0);
- speed = Transform(*mat, speed);
- dim.x = Math::Rand()*0.1f+0.1f;
- if ( bOnBoard ) dim.x *= 0.4f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIORGANIC2, 2.0f, 10.0f);
- }
-#endif
-
- return true;
-}
-
-
-// Updates the mapping of the texture of the caterpillars.
-
-void CMotionVehicle::UpdateTrackMapping(float left, float right, ObjectType type)
-{
- D3DMATERIAL7 mat;
- float limit[4];
- int rRank, lRank, i;
-
- ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
- 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;
-
- rRank = m_object->RetObjectRank(6);
- lRank = m_object->RetObjectRank(7);
-
-
- if ( type == OBJECT_MOBILEdr )
- {
- limit[0] = 0.0f;
- limit[1] = 1000000.0f;
- limit[2] = limit[1];
- limit[3] = m_engine->RetLimitLOD(1);
-
- m_engine->TrackTextureMapping(rRank, mat, D3DSTATEPART1, "drawer.tga", "",
- limit[0], limit[1], D3DMAPPINGX,
- right, 1.0f, 8.0f, 192.0f, 256.0f);
-
- m_engine->TrackTextureMapping(lRank, mat, D3DSTATEPART2, "drawer.tga", "",
- limit[0], limit[1], D3DMAPPINGX,
- left, 1.0f, 8.0f, 192.0f, 256.0f);
- }
- else
- {
- limit[0] = 0.0f;
- limit[1] = m_engine->RetLimitLOD(0);
- limit[2] = limit[1];
- limit[3] = m_engine->RetLimitLOD(1);
-
- for ( i=0 ; i<2 ; i++ )
- {
- m_engine->TrackTextureMapping(rRank, mat, D3DSTATEPART1, "lemt.tga", "",
- limit[i*2+0], limit[i*2+1], D3DMAPPINGX,
- right, 1.0f, 8.0f, 192.0f, 256.0f);
-
- m_engine->TrackTextureMapping(lRank, mat, D3DSTATEPART2, "lemt.tga", "",
- limit[i*2+0], limit[i*2+1], D3DMAPPINGX,
- left, 1.0f, 8.0f, 192.0f, 256.0f);
- }
- }
-
-}
-
-
-
-// State management of the pencil drawing robot.
-
-bool CMotionVehicle::RetTraceDown()
-{
- return m_bTraceDown;
-}
-
-void CMotionVehicle::SetTraceDown(bool bDown)
-{
- m_bTraceDown = bDown;
-}
-
-int CMotionVehicle::RetTraceColor()
-{
- return m_traceColor;
-}
-
-void CMotionVehicle::SetTraceColor(int color)
-{
- m_traceColor = color;
-}
-
-float CMotionVehicle::RetTraceWidth()
-{
- return m_traceWidth;
-}
-
-void CMotionVehicle::SetTraceWidth(float width)
-{
- m_traceWidth = width;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionvehicle.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motionvehicle.h"
+
+#include "old/modfile.h"
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "math/geometry.h"
+#include "object/brain.h"
+#include "physics/physics.h"
+
+
+
+
+
+
+// Object's constructor.
+
+CMotionVehicle::CMotionVehicle(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ int i;
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ m_wheelTurn[i] = 0.0f;
+ }
+ for ( i=0 ; i<3 ; i++ )
+ {
+ m_flyPaw[i] = 0.0f;
+ }
+ m_posTrackLeft = 0.0f;
+ m_posTrackRight = 0.0f;
+ m_partiReactor = -1;
+ m_armTimeAbs = 1000.0f;
+ m_armMember = 1000.0f;
+ m_canonTime = 0.0f;
+ m_lastTimeCanon = 0.0f;
+ m_wheelLastPos = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_wheelLastAngle = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_posKey = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_bFlyFix = false;
+
+ m_bTraceDown = false;
+ m_traceColor = 1; // black
+ m_traceWidth = 0.5f;
+}
+
+// Object's destructor.
+
+CMotionVehicle::~CMotionVehicle()
+{
+}
+
+
+// Removes an object.
+
+void CMotionVehicle::DeleteObject(bool bAll)
+{
+ if ( m_partiReactor != -1 )
+ {
+ m_particule->DeleteParticule(m_partiReactor);
+ m_partiReactor = -1;
+ }
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+bool CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ CObject* pPower;
+ int rank, i, j, parent;
+ D3DCOLORVALUE color;
+ char name[50];
+
+ if ( m_engine->RetRestCreate() < 1+5+18+1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates the main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs )
+ {
+ pModFile->ReadModel("objects\\lem1f.mod");
+ }
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts )
+ {
+ pModFile->ReadModel("objects\\lem1t.mod");
+ }
+ if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEws )
+ {
+ if ( m_object->RetTrainer() )
+ {
+ pModFile->ReadModel("objects\\lem1wt.mod");
+ }
+ else
+ {
+ pModFile->ReadModel("objects\\lem1w.mod");
+ }
+ }
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEis )
+ {
+ pModFile->ReadModel("objects\\lem1i.mod");
+ }
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ pModFile->ReadModel("objects\\roller1.mod");
+ }
+ if ( type == OBJECT_MOBILEsa )
+ {
+ pModFile->ReadModel("objects\\subm1.mod");
+ }
+ if ( type == OBJECT_MOBILEtg )
+ {
+ pModFile->ReadModel("objects\\target.mod");
+ }
+ if ( type == OBJECT_MOBILEwt )
+ {
+ pModFile->ReadModel("objects\\trainerw.mod");
+ }
+ if ( type == OBJECT_MOBILEft )
+ {
+ pModFile->ReadModel("objects\\trainerf.mod");
+ }
+ if ( type == OBJECT_MOBILEtt )
+ {
+ pModFile->ReadModel("objects\\trainert.mod");
+ }
+ if ( type == OBJECT_MOBILEit )
+ {
+ pModFile->ReadModel("objects\\traineri.mod");
+ }
+ if ( type == OBJECT_MOBILEdr )
+ {
+ pModFile->ReadModel("objects\\drawer1.mod");
+ }
+ if ( type == OBJECT_APOLLO2 )
+ {
+ pModFile->ReadModel("objects\\apolloj1.mod");
+ }
+ pModFile->CreateEngineObject(rank);
+
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have a obligatory collision
+ // with a sphere of center (0, y, 0) (see GetCrashSphere).
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 6.5f, SOUND_BOUMm, 0.45f);
+ m_object->SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 7.0f);
+ }
+ else if ( type == OBJECT_MOBILEsa )
+ {
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 4.5f, SOUND_BOUMm, 0.45f);
+ m_object->SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f);
+ }
+ else if ( type == OBJECT_MOBILEdr )
+ {
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ m_object->SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 7.0f);
+ }
+ else if ( type == OBJECT_APOLLO2 )
+ {
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ }
+ else
+ {
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 4.5f, SOUND_BOUMm, 0.45f);
+ m_object->SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 6.0f);
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia )
+ {
+ // Creates the arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\lem2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
+ m_object->SetAngleZ(1, ARM_NEUTRAL_ANGLE1);
+
+ // Creates the forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\lem3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(5.0f, 0.0f, 0.0f));
+ m_object->SetAngleZ(2, ARM_NEUTRAL_ANGLE2);
+
+ // Creates the hand.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\lem4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(3.5f, 0.0f, 0.0f));
+ m_object->SetAngleZ(3, ARM_NEUTRAL_ANGLE3);
+ m_object->SetAngleX(3, Math::PI/2.0f);
+
+ // Creates the close clamp.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 3);
+ pModFile->ReadModel("objects\\lem5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, Math::Vector(1.5f, 0.0f, 0.0f));
+ m_object->SetAngleZ(4, -Math::PI*0.10f);
+
+ // Creates the remote clamp.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 3);
+ pModFile->ReadModel("objects\\lem6.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, Math::Vector(1.5f, 0.0f, 0.0f));
+ m_object->SetAngleZ(5, Math::PI*0.10f);
+ }
+
+ if ( type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis )
+ {
+ // Creates the arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\lem2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
+ m_object->SetAngleZ(1, 110.0f*Math::PI/180.0f);
+
+ // Creates the forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\lem3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(5.0f, 0.0f, 0.0f));
+ m_object->SetAngleZ(2, -110.0f*Math::PI/180.0f);
+
+ // Creates the sensor.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\lem4s.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(3.5f, 0.0f, 0.0f));
+ m_object->SetAngleZ(3, -65.0f*Math::PI/180.0f);
+ }
+
+ if ( type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic )
+ {
+ // Creates the cannon.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\canon.mod");
+ pModFile->CreateEngineObject(rank);
+//? m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
+ m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
+ m_object->SetAngleZ(1, 0.0f);
+ }
+
+ if ( type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii )
+ {
+ // Creates the insect cannon.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\canoni1.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(0.0f, 5.3f, 0.0f));
+ m_object->SetAngleZ(1, 0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\canoni2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(0.0f, 2.5f, 0.0f));
+ m_object->SetAngleZ(2, 0.0f);
+ }
+
+ if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEwt )
+ {
+ // Creates the right-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(-3.0f, 1.0f, -3.0f));
+
+ // Creates the left-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(-3.0f, 1.0f, 3.0f));
+ m_object->SetAngleY(7, Math::PI);
+
+ // Creates the right-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(2.0f, 1.0f, -3.0f));
+
+ // Creates the left-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, Math::Vector(2.0f, 1.0f, 3.0f));
+ m_object->SetAngleY(9, Math::PI);
+ }
+
+ if ( type == OBJECT_MOBILEtg )
+ {
+ // Creates the right-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(-2.0f, 1.0f, -3.0f));
+
+ // Creates the left-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(-2.0f, 1.0f, 3.0f));
+ m_object->SetAngleY(7, Math::PI);
+
+ // Creates the right-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(3.0f, 1.0f, -3.0f));
+
+ // Creates the left-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 0);
+ pModFile->ReadModel("objects\\lem2w.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, Math::Vector(3.0f, 1.0f, 3.0f));
+ m_object->SetAngleY(9, Math::PI);
+ }
+
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts ) // caterpillars?
+ {
+ // Creates the right caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\lem2t.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(0.0f, 2.0f, -3.0f));
+
+ // Creates the left caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\lem3t.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, 2.0f, 3.0f));
+ }
+
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ) // large caterpillars?
+ {
+ // Creates the right caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\roller2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(0.0f, 2.0f, -3.0f));
+
+ // Creates the left caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\roller3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, 2.0f, 3.0f));
+ }
+
+ if ( type == OBJECT_MOBILEsa ) // underwater caterpillars?
+ {
+ // Creates the right caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\subm4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(0.0f, 1.0f, -3.0f));
+
+ // Creates the left caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\subm5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, 1.0f, 3.0f));
+ }
+
+ if ( type == OBJECT_MOBILEdr ) // caterpillars?
+ {
+ // Creates the right caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\drawer2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(0.0f, 1.0f, -3.0f));
+
+ // Creates the left caterpillar.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\drawer3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(0.0f, 1.0f, 3.0f));
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEft ) // flying?
+ {
+ // Creates the front foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\lem2f.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(1.7f, 3.0f, 0.0f));
+
+ // Creates the right-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\lem2f.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(-1.8f, 3.0f, -1.5f));
+ m_object->SetAngleY(7, 120.0f*Math::PI/180.0f);
+
+ // Creates the left-back foot.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\lem2f.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(-1.8f, 3.0f, 1.5f));
+ m_object->SetAngleY(8, -120.0f*Math::PI/180.0f);
+ }
+
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILEii ) // insect legs?
+ {
+ float table[] =
+ {
+ // x y z
+ -1.5f, 1.2f, -0.7f, // back leg
+ 0.0f, 0.0f, -1.0f,
+ 0.0f, 0.0f, -2.0f,
+
+ 0.0f, 1.2f, -0.9f, // middle leg
+ 0.0f, 0.0f, -1.0f,
+ 0.0f, 0.0f, -2.0f,
+
+ 1.5f, 1.2f, -0.7f, // front leg
+ 0.0f, 0.0f, -1.0f,
+ 0.0f, 0.0f, -2.0f,
+ };
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ for ( j=0 ; j<3 ; j++ )
+ {
+ sprintf(name, "objects\\ant%d.mod", j+4); // 4..6
+
+ // Creates the right leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6+i*3+j, rank);
+ if ( j == 0 ) parent = 0;
+ else parent = 6+i*3+j-1;
+ m_object->SetObjectParent(6+i*3+j, parent);
+ pModFile->ReadModel(name);
+ pModFile->CreateEngineObject(rank);
+ pos.x = table[i*9+j*3+0];
+ pos.y = table[i*9+j*3+1];
+ pos.z = table[i*9+j*3+2];
+ m_object->SetPosition(6+i*3+j, pos);
+
+ // Creates the left leg.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(15+i*3+j, rank);
+ if ( j == 0 ) parent = 0;
+ else parent = 15+i*3+j-1;
+ m_object->SetObjectParent(15+i*3+j, parent);
+ pModFile->ReadModel(name);
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ pos.x = table[i*9+j*3+0];
+ pos.y = table[i*9+j*3+1];
+ pos.z = -table[i*9+j*3+2];
+ m_object->SetPosition(15+i*3+j, pos);
+ }
+ }
+ }
+
+ if ( type == OBJECT_MOBILErt )
+ {
+ // Creates the holder.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\roller2t.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(0.0f, 0.0f, 0.0f));
+ m_object->SetAngleZ(1, 0.0f);
+
+ // Creates the pestle.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\roller3t.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(9.0f, 4.0f, 0.0f));
+ m_object->SetAngleZ(2, 0.0f);
+ }
+
+ if ( type == OBJECT_MOBILErc )
+ {
+ // Creates the holder.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\roller2c.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(3.0f, 4.6f, 0.0f));
+ m_object->SetAngleZ(1, Math::PI/8.0f);
+
+ // Creates the cannon.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\roller3p.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(7.0f, 6.5f, 0.0f));
+ m_object->SetAngleZ(2, 0.0f);
+ }
+
+ if ( type == OBJECT_MOBILErr )
+ {
+ // Creates the holder.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\recover1.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(2.0f, 5.0f, 0.0f));
+
+ // Creates the right arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\recover2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(0.1f, 0.0f, -5.0f));
+ m_object->SetAngleZ(2, 126.0f*Math::PI/180.0f);
+
+ // Creates the right forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\recover3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(5.0f, 0.0f, -0.5f));
+ m_object->SetAngleZ(3, -144.0f*Math::PI/180.0f);
+
+ // Creates the left arm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(4, rank);
+ m_object->SetObjectParent(4, 1);
+ pModFile->ReadModel("objects\\recover2.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(4, Math::Vector(0.1f, 0.0f, 5.0f));
+ m_object->SetAngleZ(4, 126.0f*Math::PI/180.0f);
+
+ // Creates the left forearm.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(5, rank);
+ m_object->SetObjectParent(5, 4);
+ pModFile->ReadModel("objects\\recover3.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(5, Math::Vector(5.0f, 0.0f, 0.5f));
+ m_object->SetAngleZ(5, -144.0f*Math::PI/180.0f);
+ }
+
+ if ( type == OBJECT_MOBILErs )
+ {
+ // Creates the holder.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\roller2s.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(0.0f, 0.0f, 0.0f));
+ m_object->SetAngleZ(1, 0.0f);
+
+ // Creates the intermediate piston.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\roller3s.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(7.0f, 4.5f, 0.0f));
+ m_object->SetAngleZ(2, 0.0f);
+
+ // Creates the piston with the sphere.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\roller4s.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(0.0f, 1.0f, 0.0f));
+ m_object->SetAngleZ(3, 0.0f);
+ }
+
+ if ( type == OBJECT_MOBILEsa )
+ {
+ // Creates the holder.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\subm2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(4.2f, 3.0f, 0.0f));
+
+ // Creates the right tong.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\subm3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(0.5f, 0.0f, -1.5f));
+
+ // Creates the left tong.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(3, rank);
+ m_object->SetObjectParent(3, 1);
+ pModFile->ReadModel("objects\\subm3.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(3, Math::Vector(0.5f, 0.0f, 1.5f));
+ }
+
+ if ( type == OBJECT_MOBILEdr )
+ {
+ // Creates the carousel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\drawer4.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(-3.0f, 3.0f, 0.0f));
+
+ // Creates the key.
+ if ( m_object->RetToy() )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\drawer5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_posKey = Math::Vector(3.0f, 5.7f, 0.0f);
+ m_object->SetPosition(2, m_posKey);
+ m_object->SetAngleY(2, 90.0f*Math::PI/180.0f);
+ }
+
+ // Creates pencils.
+ for ( i=0 ; i<8 ; i++ )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10+i, rank);
+ m_object->SetObjectParent(10+i, 1);
+ sprintf(name, "objects\\drawer%d.mod", 10+i);
+ pModFile->ReadModel(name);
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10+i, Math::Vector(0.0f, 0.0f, 0.0f));
+ m_object->SetAngleY(10+i, 45.0f*Math::PI/180.0f*i);
+ }
+ }
+
+ if ( type == OBJECT_MOBILEwt )
+ {
+ // Creates the key.
+ if ( m_object->RetToy() )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\drawer5.mod");
+ pModFile->CreateEngineObject(rank);
+ m_posKey = Math::Vector(0.2f, 4.1f, 0.0f);
+ m_object->SetPosition(2, m_posKey);
+ m_object->SetAngleY(2, 90.0f*Math::PI/180.0f);
+ }
+ }
+
+ if ( type == OBJECT_APOLLO2 )
+ {
+ // Creates the accessories.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\apolloj2.mod"); // antenna
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(5.5f, 8.8f, 2.0f));
+ m_object->SetAngleY(1, -120.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(1, 45.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2, rank);
+ m_object->SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\apolloj3.mod"); // camera
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2, Math::Vector(5.5f, 2.8f, -2.0f));
+ m_object->SetAngleY(2, 30.0f*Math::PI/180.0f);
+
+ // Creates the wheels.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(6, rank);
+ m_object->SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(6, Math::Vector(-5.75f, 1.65f, -5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(7, rank);
+ m_object->SetObjectParent(7, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(7, Math::Vector(-5.75f, 1.65f, 5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(8, rank);
+ m_object->SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(8, Math::Vector(5.75f, 1.65f, -5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(9, rank);
+ m_object->SetObjectParent(9, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(9, Math::Vector(5.75f, 1.65f, 5.00f));
+
+ // Creates mud guards.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(10, rank);
+ m_object->SetObjectParent(10, 0);
+ pModFile->ReadModel("objects\\apolloj6.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(10, Math::Vector(-5.75f, 1.65f, -5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(11, rank);
+ m_object->SetObjectParent(11, 0);
+ pModFile->ReadModel("objects\\apolloj6.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(11, Math::Vector(-5.75f, 1.65f, 5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(12, rank);
+ m_object->SetObjectParent(12, 0);
+ pModFile->ReadModel("objects\\apolloj5.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(12, Math::Vector(5.75f, 1.65f, -5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(13, rank);
+ m_object->SetObjectParent(13, 0);
+ pModFile->ReadModel("objects\\apolloj5.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(13, Math::Vector(5.75f, 1.65f, 5.00f));
+ }
+
+#if 1
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ m_object->CreateShadowCircle(6.0f, 1.0f);
+ }
+ else if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEsa )
+ {
+ m_object->CreateShadowCircle(5.0f, 1.0f);
+ }
+ else if ( type == OBJECT_MOBILEdr )
+ {
+ m_object->CreateShadowCircle(4.5f, 1.0f);
+ }
+ else if ( type == OBJECT_APOLLO2 )
+ {
+ m_object->CreateShadowCircle(7.0f, 0.8f);
+ }
+ else
+ {
+ m_object->CreateShadowCircle(4.0f, 1.0f);
+ }
+#else
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ m_object->CreateShadowCircle(6.0f, 1.0f, D3DSHADOWTANK);
+ }
+ else if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts )
+ {
+ m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWTANK);
+ }
+ else if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs )
+ {
+ m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWFLY);
+ }
+ else if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEws )
+ {
+ m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWWHEEL);
+ }
+ else if ( type == OBJECT_APOLLO2 )
+ {
+ m_object->CreateShadowCircle(6.0f, 0.8f);
+ }
+ else
+ {
+ m_object->CreateShadowCircle(4.0f, 1.0f, D3DSHADOWNORM);
+ }
+#endif
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEft ) // flying?
+ {
+//? color.r = 0.5f-1.0f;
+//? color.g = 0.2f-1.0f;
+//? color.b = 0.0f-1.0f; // orange
+//? color.r = 0.8f;
+//? color.g = 0.6f;
+//? color.b = 0.0f; // yellow-orange
+ color.r = 0.0f;
+ color.g = 0.4f;
+ color.b = 0.8f; // blue
+ color.a = 0.0f;
+ m_object->CreateShadowLight(50.0f, color);
+ }
+
+ CreatePhysics(type);
+ m_object->SetFloorHeight(0.0f);
+
+ if ( power > 0.0f &&
+ type != OBJECT_MOBILEdr &&
+ type != OBJECT_APOLLO2 )
+ {
+ color.r = 1.0f;
+ color.g = 1.0f;
+ color.b = 0.0f; // yellow
+ color.a = 0.0f;
+ m_object->CreateEffectLight(20.0f, color);
+
+ // Creates the battery.
+ pPower = new CObject(m_iMan);
+ pPower->SetType(power<=1.0f?OBJECT_POWER:OBJECT_ATOMIC);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ pPower->SetObjectRank(0, rank);
+
+ if ( power <= 1.0f ) pModFile->ReadModel("objects\\power.mod");
+ else pModFile->ReadModel("objects\\atomic.mod");
+ pModFile->CreateEngineObject(rank);
+
+ pPower->SetPosition(0, m_object->RetCharacter()->posPower);
+ pPower->CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ pPower->SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.5f);
+
+ pPower->SetTruck(m_object);
+ m_object->SetPower(pPower);
+
+ if ( power <= 1.0f ) pPower->SetEnergy(power);
+ else pPower->SetEnergy(power/100.0f);
+ }
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); //to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+// Creates the physics of the object.
+
+void CMotionVehicle::CreatePhysics(ObjectType type)
+{
+ Character* character;
+
+ character = m_object->RetCharacter();
+
+ if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEwt ) // wheels?
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 3.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.0f;
+ character->wheelRight = 4.0f;
+ character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 20.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 30.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 8.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 8.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 12.0f);
+ }
+
+ if ( type == OBJECT_MOBILEtg )
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 4.0f;
+ character->wheelBack = 3.0f;
+ character->wheelLeft = 4.0f;
+ character->wheelRight = 4.0f;
+ character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 20.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.8f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.8f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 15.0f);
+ }
+
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts ) // caterpillars?
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.8f;
+ character->wheelRight = 4.8f;
+ character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 8.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 15.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 8.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 6.0f);
+ }
+
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEis ) // legs?
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 5.0f;
+ character->wheelRight = 5.0f;
+ character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 8.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 10.0f);
+//? m_physics->SetLinMotionX(MO_TERFORCE, 15.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 15.0f);
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEft ) // flying?
+ {
+ m_physics->SetType(TYPE_FLYING);
+
+ character->wheelFront = 5.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.5f;
+ character->wheelRight = 4.5f;
+ character->posPower = Math::Vector(-3.2f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 50.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 50.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 50.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+ m_physics->SetLinMotionY(MO_ADVSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_RECSPEED, 60.0f);
+ m_physics->SetLinMotionY(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionY(MO_RECACCEL, 50.0f);
+ m_physics->SetLinMotionY(MO_STOACCEL, 50.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.4f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.4f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 2.0f);
+ }
+
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ) // large caterpillars?
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 5.0f;
+ character->wheelBack = 5.0f;
+ character->wheelLeft = 6.0f;
+ character->wheelRight = 6.0f;
+ character->posPower = Math::Vector(-5.8f, 4.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 5.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 5.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.3f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.3f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 4.0f);
+ }
+
+ if ( type == OBJECT_MOBILEsa )
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.0f;
+ character->wheelRight = 4.0f;
+ character->posPower = Math::Vector(-5.0f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 5.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 5.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 10.0f);
+ }
+
+ if ( type == OBJECT_MOBILEdr )
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 4.0f;
+ character->wheelBack = 4.0f;
+ character->wheelLeft = 4.0f;
+ character->wheelRight = 4.0f;
+ character->posPower = Math::Vector(-5.0f, 3.0f, 0.0f);
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 20.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.5f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.5f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 5.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 5.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 10.0f);
+ }
+
+ if ( type == OBJECT_APOLLO2 ) // jeep?
+ {
+ m_physics->SetType(TYPE_ROLLING);
+
+ character->wheelFront = 6.0f;
+ character->wheelBack = 6.0f;
+ character->wheelLeft = 5.0f;
+ character->wheelRight = 5.0f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 15.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 10.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 20.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 2.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 2.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 30.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 10.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 20.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.4f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.4f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 2.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 4.0f);
+ }
+}
+
+
+// Management of an event.
+
+bool CMotionVehicle::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+ }
+
+ return true;
+}
+
+// Management of an event.
+
+bool CMotionVehicle::EventFrame(const Event &event)
+{
+ Math::Matrix* mat;
+ Character* character;
+ Math::Vector pos, angle, floor;
+ ObjectType type;
+ float s, a, speedBL, speedBR, speedFL, speedFR, h, a1, a2;
+ float back, front, dist, radius, limit[2];
+
+ if ( m_engine->RetPause() ) return true;
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
+
+ type = m_object->RetType();
+
+ if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_APOLLO2 ) // wheels?
+ {
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.0f;
+ a = m_physics->RetCirMotionY(MO_MOTSPEED)*3.0f;
+
+ if ( type == OBJECT_APOLLO2 ) s *= 0.5f;
+
+ speedBR = -s+a;
+ speedBL = s+a;
+ speedFR = -s+a;
+ speedFL = s+a;
+
+ m_object->SetAngleZ(6, m_object->RetAngleZ(6)+event.rTime*speedBR); // turning the wheels
+ m_object->SetAngleZ(7, m_object->RetAngleZ(7)+event.rTime*speedBL);
+ m_object->SetAngleZ(8, m_object->RetAngleZ(8)+event.rTime*speedFR);
+ m_object->SetAngleZ(9, m_object->RetAngleZ(9)+event.rTime*speedFL);
+
+ if ( s > 0.0f )
+ {
+ m_wheelTurn[0] = -a*0.05f;
+ m_wheelTurn[1] = -a*0.05f+Math::PI;
+ m_wheelTurn[2] = a*0.05f;
+ m_wheelTurn[3] = a*0.05f+Math::PI;
+ }
+ else if ( s < 0.0f )
+ {
+ m_wheelTurn[0] = a*0.05f;
+ m_wheelTurn[1] = a*0.05f+Math::PI;
+ m_wheelTurn[2] = -a*0.05f;
+ m_wheelTurn[3] = -a*0.05f+Math::PI;
+ }
+ else
+ {
+ m_wheelTurn[0] = fabs(a)*0.05f;
+ m_wheelTurn[1] = -fabs(a)*0.05f+Math::PI;
+ m_wheelTurn[2] = -fabs(a)*0.05f;
+ m_wheelTurn[3] = fabs(a)*0.05f+Math::PI;
+ }
+ m_object->SetAngleY(6, m_object->RetAngleY(6)+(m_wheelTurn[0]-m_object->RetAngleY(6))*event.rTime*8.0f);
+ m_object->SetAngleY(7, m_object->RetAngleY(7)+(m_wheelTurn[1]-m_object->RetAngleY(7))*event.rTime*8.0f);
+ m_object->SetAngleY(8, m_object->RetAngleY(8)+(m_wheelTurn[2]-m_object->RetAngleY(8))*event.rTime*8.0f);
+ m_object->SetAngleY(9, m_object->RetAngleY(9)+(m_wheelTurn[3]-m_object->RetAngleY(9))*event.rTime*8.0f);
+
+ if ( type == OBJECT_APOLLO2 )
+ {
+ m_object->SetAngleY(10, m_object->RetAngleY(6)+(m_wheelTurn[0]-m_object->RetAngleY(6))*event.rTime*8.0f);
+ m_object->SetAngleY(11, m_object->RetAngleY(7)+(m_wheelTurn[1]-m_object->RetAngleY(7))*event.rTime*8.0f+Math::PI);
+ m_object->SetAngleY(12, m_object->RetAngleY(8)+(m_wheelTurn[2]-m_object->RetAngleY(8))*event.rTime*8.0f);
+ m_object->SetAngleY(13, m_object->RetAngleY(9)+(m_wheelTurn[3]-m_object->RetAngleY(9))*event.rTime*8.0f+Math::PI);
+ }
+
+ pos = m_object->RetPosition(0);
+ angle = m_object->RetAngle(0);
+ if ( pos.x != m_wheelLastPos.x ||
+ pos.y != m_wheelLastPos.y ||
+ pos.z != m_wheelLastPos.z ||
+ angle.x != m_wheelLastAngle.x ||
+ angle.y != m_wheelLastAngle.y ||
+ angle.z != m_wheelLastAngle.z )
+ {
+ m_wheelLastPos = pos;
+ m_wheelLastAngle = angle;
+
+ if ( type == OBJECT_MOBILEtg )
+ {
+ back = -2.0f; // back wheels position
+ front = 3.0f; // front wheels position
+ dist = 3.0f; // distancing wheels Z
+ radius = 1.0f;
+ }
+ else if ( type == OBJECT_APOLLO2 )
+ {
+ back = -5.75f; // back wheels position
+ front = 5.75f; // front wheels position
+ dist = 5.00f; // distancing wheels Z
+ radius = 1.65f;
+ }
+ else
+ {
+ back = -3.0f; // back wheels position
+ front = 2.0f; // front wheels position
+ dist = 3.0f; // distancing wheels Z
+ radius = 1.0f;
+ }
+
+ if ( Math::Distance(pos, m_engine->RetEyePt()) < 50.0f ) // suspension?
+ {
+ character = m_object->RetCharacter();
+ mat = m_object->RetWorldMatrix(0);
+
+ pos.x = -character->wheelBack; // right back wheel
+ pos.z = -character->wheelRight;
+ pos.y = 0.0f;
+ pos = Math::Transform(*mat, pos);
+ h = m_terrain->RetFloorHeight(pos);
+ if ( h > 0.5f ) h = 0.5f;
+ if ( h < -0.5f ) h = -0.5f;
+ pos.x = back;
+ pos.y = radius-h;
+ pos.z = -dist;
+ m_object->SetPosition(6, pos);
+ if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(10, pos);
+
+ pos.x = -character->wheelBack; // left back wheel
+ pos.z = character->wheelLeft;
+ pos.y = 0.0f;
+ pos = Math::Transform(*mat, pos);
+ h = m_terrain->RetFloorHeight(pos);
+ if ( h > 0.5f ) h = 0.5f;
+ if ( h < -0.5f ) h = -0.5f;
+ pos.x = back;
+ pos.y = radius-h;
+ pos.z = dist;
+ m_object->SetPosition(7, pos);
+ if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(11, pos);
+
+ pos.x = character->wheelFront; // right front wheel
+ pos.z = -character->wheelRight;
+ pos.y = 0.0f;
+ pos = Math::Transform(*mat, pos);
+ h = m_terrain->RetFloorHeight(pos);
+ if ( h > 0.5f ) h = 0.5f;
+ if ( h < -0.5f ) h = -0.5f;
+ pos.x = front;
+ pos.y = radius-h;
+ pos.z = -dist;
+ m_object->SetPosition(8, pos);
+ if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(12, pos);
+
+ pos.x = character->wheelFront; // left front wheel
+ pos.z = character->wheelLeft;
+ pos.y = 0.0f;
+ pos = Math::Transform(*mat, pos);
+ h = m_terrain->RetFloorHeight(pos);
+ if ( h > 0.5f ) h = 0.5f;
+ if ( h < -0.5f ) h = -0.5f;
+ pos.x = front;
+ pos.y = radius-h;
+ pos.z = dist;
+ m_object->SetPosition(9, pos);
+ if ( type == OBJECT_APOLLO2 ) m_object->SetPosition(13, pos);
+ }
+ else
+ {
+ m_object->SetPosition(6, Math::Vector(back, radius, -dist));
+ m_object->SetPosition(7, Math::Vector(back, radius, dist));
+ m_object->SetPosition(8, Math::Vector(front, radius, -dist));
+ m_object->SetPosition(9, Math::Vector(front, radius, dist));
+
+ if ( type == OBJECT_APOLLO2 )
+ {
+ m_object->SetPosition(10, Math::Vector(back, radius, -dist));
+ m_object->SetPosition(11, Math::Vector(back, radius, dist));
+ m_object->SetPosition(12, Math::Vector(front, radius, -dist));
+ m_object->SetPosition(13, Math::Vector(front, radius, dist));
+ }
+ }
+ }
+ }
+
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEdr ) // caterpillars?
+ {
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*0.7f;
+ a = m_physics->RetCirMotionY(MO_MOTSPEED)*2.5f;
+
+ m_posTrackLeft += event.rTime*(s+a);
+ m_posTrackRight += event.rTime*(s-a);
+
+ UpdateTrackMapping(m_posTrackLeft, m_posTrackRight, type);
+
+ pos = m_object->RetPosition(0);
+ angle = m_object->RetAngle(0);
+ if ( pos.x != m_wheelLastPos.x ||
+ pos.y != m_wheelLastPos.y ||
+ pos.z != m_wheelLastPos.z ||
+ angle.x != m_wheelLastAngle.x ||
+ angle.y != m_wheelLastAngle.y ||
+ angle.z != m_wheelLastAngle.z )
+ {
+ m_wheelLastPos = pos;
+ m_wheelLastAngle = angle;
+
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts )
+ {
+ limit[0] = 8.0f*Math::PI/180.0f;
+ limit[1] = -12.0f*Math::PI/180.0f;
+ }
+ else if ( type == OBJECT_MOBILEsa )
+ {
+ limit[0] = 15.0f*Math::PI/180.0f;
+ limit[1] = -15.0f*Math::PI/180.0f;
+ }
+ else if ( type == OBJECT_MOBILEdr )
+ {
+ limit[0] = 10.0f*Math::PI/180.0f;
+ limit[1] = -10.0f*Math::PI/180.0f;
+ }
+ else
+ {
+ limit[0] = 15.0f*Math::PI/180.0f;
+ limit[1] = -10.0f*Math::PI/180.0f;
+ }
+
+ if ( Math::Distance(pos, m_engine->RetEyePt()) < 50.0f ) // suspension?
+ {
+ character = m_object->RetCharacter();
+ mat = m_object->RetWorldMatrix(0);
+
+ pos.x = character->wheelFront; // right front wheel
+ pos.z = -character->wheelRight;
+ pos.y = 0.0f;
+ pos = Transform(*mat, pos);
+ a1 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelFront);
+
+ pos.x = -character->wheelBack; // right back wheel
+ pos.z = -character->wheelRight;
+ pos.y = 0.0f;
+ pos = Transform(*mat, pos);
+ a2 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelBack);
+
+ a = (a2-a1)/2.0f;
+ if ( a > limit[0] ) a = limit[0];
+ if ( a < limit[1] ) a = limit[1];
+ m_object->SetAngleZ(6, a);
+
+ pos.x = character->wheelFront; // left front wheel
+ pos.z = character->wheelLeft;
+ pos.y = 0.0f;
+ pos = Transform(*mat, pos);
+ a1 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelFront);
+
+ pos.x = -character->wheelBack; // left back wheel
+ pos.z = character->wheelLeft;
+ pos.y = 0.0f;
+ pos = Transform(*mat, pos);
+ a2 = atanf(m_terrain->RetFloorHeight(pos)/character->wheelBack);
+
+ a = (a2-a1)/2.0f;
+ if ( a > limit[0] ) a = limit[0];
+ if ( a < limit[1] ) a = limit[1];
+ m_object->SetAngleZ(7, a);
+ }
+ else
+ {
+ m_object->SetAngleZ(6, 0.0f);
+ m_object->SetAngleZ(7, 0.0f);
+ }
+ }
+ }
+
+ if ( type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEdr ) // toy is key?
+ {
+ pos = m_posKey;
+ if ( m_object->RetSelect() &&
+ m_camera->RetType() == CAMERA_ONBOARD )
+ {
+ pos.y += 10.0f; // out of sight!
+ }
+ m_object->SetPosition(2, pos);
+
+ s = -fabs(m_physics->RetLinMotionX(MO_MOTSPEED)*0.1f);
+ s += -fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*1.5f);
+ m_object->SetAngleY(2, m_object->RetAngleY(2)+event.rTime*s); // turns the key
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEft ) // flying?
+ {
+ EventFrameFly(event);
+ }
+
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEis ) // legs?
+ {
+ EventFrameInsect(event);
+ }
+
+ if ( type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEii ) // insect cannon?
+ {
+ EventFrameCanoni(event);
+ }
+
+ return true;
+}
+
+// Managing an event for a flying robot.
+
+bool CMotionVehicle::EventFrameFly(const Event &event)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, angle, paw[3];
+ float hope[3], actual, final, h, a;
+ int i;
+
+ pos = m_object->RetPosition(0);
+ angle = m_object->RetAngle(0);
+ if ( m_bFlyFix &&
+ pos.x == m_wheelLastPos.x &&
+ pos.y == m_wheelLastPos.y &&
+ pos.z == m_wheelLastPos.z &&
+ angle.x == m_wheelLastAngle.x &&
+ angle.y == m_wheelLastAngle.y &&
+ angle.z == m_wheelLastAngle.z ) return true;
+
+ m_wheelLastPos = pos;
+ m_wheelLastAngle = angle;
+
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ mat = m_object->RetWorldMatrix(0);
+ paw[0] = Transform(*mat, Math::Vector( 4.2f, 0.0f, 0.0f)); // front
+ paw[1] = Transform(*mat, Math::Vector(-3.0f, 0.0f, -3.7f)); // right back
+ paw[2] = Transform(*mat, Math::Vector(-3.0f, 0.0f, 3.7f)); // left back
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ h = m_terrain->RetFloorHeight(paw[i]);
+ a = -atanf(h*0.5f);
+ if ( a > Math::PI*0.2f ) a = Math::PI*0.2f;
+ if ( a < -Math::PI*0.2f ) a = -Math::PI*0.2f;
+ hope[i] = a;
+ }
+ }
+ else // in flight?
+ {
+ hope[0] = 0.0f; // front
+ hope[1] = 0.0f; // right back
+ hope[2] = 0.0f; // left back
+ }
+
+ m_bFlyFix = true;
+ for ( i=0 ; i<3 ; i++ )
+ {
+ actual = m_object->RetAngleZ(6+i);
+ final = Math::Smooth(actual, hope[i], event.rTime*5.0f);
+ if ( final != actual )
+ {
+ m_bFlyFix = false; // it is moving
+ m_object->SetAngleZ(6+i, final);
+ }
+ }
+
+ return true;
+}
+
+// Event management for insect legs.
+
+bool CMotionVehicle::EventFrameInsect(const Event &event)
+{
+ Math::Vector dir;
+ float s, a, prog, time;
+ int i, st, nd, action;
+ bool bStop, bOnBoard;
+
+ static int table[] =
+ {
+ // x1,y1,z1, x2,y2,z2, x3,y3,z3, // in the air:
+ 60,25,0, 60,0,0, 60,-25,0, // t0: thighs 1..4
+ -35,0,0, -35,0,0, -35,0,0, // t0: legs 1..4
+ -65,0,0, -65,0,0, -65,0,0, // t0: feet 1..4
+ // on the ground:
+ 30,10,0, 30,-15,0, 30,-40,0, // t1: thighs 1..4
+ -45,0,0, -45,0,0, -45,0,0, // t1: legs 1..4
+ -20,0,0, -20,0,0, -20,0,0, // t1: feet 1..4
+ // on the ground back:
+ 35,40,0, 40,15,0, 40,-10,0, // t2: thighs 1..4
+ -35,0,0, -35,0,0, -35,0,0, // t2: legs 1..4
+ -50,0,0, -65,0,0, -65,0,0, // t2: feet 1..4
+ // stop:
+ 35,35,0, 40,10,0, 40,-15,0, // s0: thighs 1..4
+ -35,0,0, -35,0,0, -35,0,0, // s0: legs 1..4
+ -50,0,0, -65,0,0, -65,0,0, // s0: feet 1..4
+ };
+
+ bOnBoard = false;
+ if ( m_object->RetSelect() &&
+ m_camera->RetType() == CAMERA_ONBOARD )
+ {
+ bOnBoard = true;
+ }
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)*1.5f;
+ a = fabs(m_physics->RetCirMotionY(MO_MOTSPEED)*2.0f);
+
+ if ( s == 0.0f && a != 0.0f ) a *= 1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armMember += (s+a)*event.rTime*0.15f;
+
+ bStop = ( a == 0.0f && s == 0.0f ); // stop?
+
+ action = 0; // walking
+ if ( s == 0.0f && a == 0.0f )
+ {
+ action = 3; // stop
+ }
+
+ if ( bStop )
+ {
+ prog = Math::Mod(m_armTimeAbs, 2.0f)/10.0f;
+ a = Math::Mod(m_armMember, 1.0f);
+ a = (prog-a)*event.rTime*2.0f; // stop position is pleasantly
+ m_armMember += a;
+ }
+
+ if ( m_object->RetRuin() ) // burn or explode?
+ {
+ action = 3;
+ }
+
+ for ( i=0 ; i<6 ; i++ ) // the six legs
+ {
+ if ( action != 0 ) // special action in progress?
+ {
+ st = 3*3*3*action + (i%3)*3;
+ nd = st;
+ time = event.rTime*5.0f;
+ }
+ else
+ {
+ if ( i < 3 ) prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.0f, 1.0f);
+ else prog = Math::Mod(m_armMember+(2.0f-(i%3))*0.33f+0.3f, 1.0f);
+ if ( prog < 0.33f ) // t0..t1 ?
+ {
+ prog = prog/0.33f; // 0..1
+ st = 0; // index start
+ nd = 1; // index end
+ }
+ else if ( prog < 0.67f ) // t1..t2 ?
+ {
+ prog = (prog-0.33f)/0.33f; // 0..1
+ st = 1; // index start
+ nd = 2; // index end
+ }
+ else // t2..t0 ?
+ {
+ prog = (prog-0.67f)/0.33f; // 0..1
+ st = 2; // index start
+ nd = 0; // index end
+ }
+ st = 3*3*3*action + st*3*3*3 + (i%3)*3;
+ nd = 3*3*3*action + nd*3*3*3 + (i%3)*3;
+
+ // Less and less soft ...
+ time = event.rTime*20.0f;
+ }
+
+ if ( i < 3 ) // right leg (1..3) ?
+ {
+ m_object->SetAngleX(6+3*i+0, Math::Smooth(m_object->RetAngleX(6+3*i+0), Math::PropAngle(table[st+ 0], table[nd+ 0], prog), time));
+ m_object->SetAngleY(6+3*i+0, Math::Smooth(m_object->RetAngleY(6+3*i+0), Math::PropAngle(table[st+ 1], table[nd+ 1], prog), time));
+ m_object->SetAngleZ(6+3*i+0, Math::Smooth(m_object->RetAngleZ(6+3*i+0), Math::PropAngle(table[st+ 2], table[nd+ 2], prog), time));
+ m_object->SetAngleX(6+3*i+1, Math::Smooth(m_object->RetAngleX(6+3*i+1), Math::PropAngle(table[st+ 9], table[nd+ 9], prog), time));
+ m_object->SetAngleY(6+3*i+1, Math::Smooth(m_object->RetAngleY(6+3*i+1), Math::PropAngle(table[st+10], table[nd+10], prog), time));
+ m_object->SetAngleZ(6+3*i+1, Math::Smooth(m_object->RetAngleZ(6+3*i+1), Math::PropAngle(table[st+11], table[nd+11], prog), time));
+ m_object->SetAngleX(6+3*i+2, Math::Smooth(m_object->RetAngleX(6+3*i+2), Math::PropAngle(table[st+18], table[nd+18], prog), time));
+ m_object->SetAngleY(6+3*i+2, Math::Smooth(m_object->RetAngleY(6+3*i+2), Math::PropAngle(table[st+19], table[nd+19], prog), time));
+ m_object->SetAngleZ(6+3*i+2, Math::Smooth(m_object->RetAngleZ(6+3*i+2), Math::PropAngle(table[st+20], table[nd+20], prog), time));
+ }
+ else // left leg (4..6) ?
+ {
+ m_object->SetAngleX(6+3*i+0, Math::Smooth(m_object->RetAngleX(6+3*i+0), Math::PropAngle(-table[st+ 0], -table[nd+ 0], prog), time));
+ m_object->SetAngleY(6+3*i+0, Math::Smooth(m_object->RetAngleY(6+3*i+0), Math::PropAngle(-table[st+ 1], -table[nd+ 1], prog), time));
+ m_object->SetAngleZ(6+3*i+0, Math::Smooth(m_object->RetAngleZ(6+3*i+0), Math::PropAngle( table[st+ 2], table[nd+ 2], prog), time));
+ m_object->SetAngleX(6+3*i+1, Math::Smooth(m_object->RetAngleX(6+3*i+1), Math::PropAngle(-table[st+ 9], -table[nd+ 9], prog), time));
+ m_object->SetAngleY(6+3*i+1, Math::Smooth(m_object->RetAngleY(6+3*i+1), Math::PropAngle(-table[st+10], -table[nd+10], prog), time));
+ m_object->SetAngleZ(6+3*i+1, Math::Smooth(m_object->RetAngleZ(6+3*i+1), Math::PropAngle( table[st+11], table[nd+11], prog), time));
+ m_object->SetAngleX(6+3*i+2, Math::Smooth(m_object->RetAngleX(6+3*i+2), Math::PropAngle(-table[st+18], -table[nd+18], prog), time));
+ m_object->SetAngleY(6+3*i+2, Math::Smooth(m_object->RetAngleY(6+3*i+2), Math::PropAngle(-table[st+19], -table[nd+19], prog), time));
+ m_object->SetAngleZ(6+3*i+2, Math::Smooth(m_object->RetAngleZ(6+3*i+2), Math::PropAngle( table[st+20], table[nd+20], prog), time));
+ }
+ }
+
+ if ( bStop )
+ {
+ }
+ else
+ {
+ a = Math::Mod(m_armMember, 1.0f);
+ if ( a < 0.5f ) a = -1.0f+4.0f*a; // -1..1
+ else a = 3.0f-4.0f*a; // 1..-1
+ dir.x = sinf(a)*0.05f;
+
+ s = Math::Mod(m_armMember/2.0f, 1.0f);
+ if ( s < 0.5f ) s = -1.0f+4.0f*s; // -1..1
+ else s = 3.0f-4.0f*s; // 1..-1
+ dir.z = sinf(s)*0.1f;
+
+ dir.y = 0.0f;
+
+ if ( bOnBoard ) dir *= 0.6f;
+ SetInclinaison(dir);
+ }
+
+ return true;
+}
+
+// Event management for a insect cannon.
+
+bool CMotionVehicle::EventFrameCanoni(const Event &event)
+{
+ CObject* power;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float zoom, angle, energy, factor;
+ bool bOnBoard = false;
+
+ m_canonTime += event.rTime;
+
+ if ( m_object->RetSelect() &&
+ m_camera->RetType() == CAMERA_ONBOARD )
+ {
+ bOnBoard = true;
+ }
+
+ power = m_object->RetPower();
+ if ( power == 0 )
+ {
+ energy = 0.0f;
+ }
+ else
+ {
+ energy = power->RetEnergy();
+ }
+ if ( energy == 0.0f ) return true;
+
+ factor = 0.5f+energy*0.5f;
+ if ( bOnBoard ) factor *= 0.8f;
+
+ zoom = 1.3f+
+ sinf(m_canonTime*Math::PI*0.31f)*0.10f+
+ sinf(m_canonTime*Math::PI*0.52f)*0.08f+
+ sinf(m_canonTime*Math::PI*1.53f)*0.05f;
+ zoom *= factor;
+ m_object->SetZoomY(2, zoom);
+
+ zoom = 1.0f+
+ sinf(m_canonTime*Math::PI*0.27f)*0.07f+
+ sinf(m_canonTime*Math::PI*0.62f)*0.06f+
+ sinf(m_canonTime*Math::PI*1.73f)*0.03f;
+ zoom *= factor;
+ m_object->SetZoomZ(2, zoom);
+
+ angle = sinf(m_canonTime*1.0f)*0.10f+
+ sinf(m_canonTime*1.3f)*0.15f+
+ sinf(m_canonTime*2.7f)*0.05f;
+ m_object->SetAngleX(2, angle);
+
+#if 0
+ m_lastTimeCanon -= event.rTime;
+ if ( m_lastTimeCanon <= 0.0f )
+ {
+ m_lastTimeCanon = m_engine->ParticuleAdapt(0.5f+Math::Rand()*0.5f);
+
+ pos = m_object->RetPosition(0);
+ pos.y += 8.0f;
+ speed.y = 7.0f+Math::Rand()*3.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = 2.0f+Math::Rand()*2.0f;
+ if ( Math::Rand() < 0.5f ) speed.z = -speed.z;
+ mat = m_object->RetRotateMatrix(0);
+ speed = Transform(*mat, speed);
+ dim.x = Math::Rand()*0.1f+0.1f;
+ if ( bOnBoard ) dim.x *= 0.4f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIORGANIC2, 2.0f, 10.0f);
+ }
+#endif
+
+ return true;
+}
+
+
+// Updates the mapping of the texture of the caterpillars.
+
+void CMotionVehicle::UpdateTrackMapping(float left, float right, ObjectType type)
+{
+ D3DMATERIAL7 mat;
+ float limit[4];
+ int rRank, lRank, i;
+
+ ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
+ 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;
+
+ rRank = m_object->RetObjectRank(6);
+ lRank = m_object->RetObjectRank(7);
+
+
+ if ( type == OBJECT_MOBILEdr )
+ {
+ limit[0] = 0.0f;
+ limit[1] = 1000000.0f;
+ limit[2] = limit[1];
+ limit[3] = m_engine->RetLimitLOD(1);
+
+ m_engine->TrackTextureMapping(rRank, mat, D3DSTATEPART1, "drawer.tga", "",
+ limit[0], limit[1], D3DMAPPINGX,
+ right, 1.0f, 8.0f, 192.0f, 256.0f);
+
+ m_engine->TrackTextureMapping(lRank, mat, D3DSTATEPART2, "drawer.tga", "",
+ limit[0], limit[1], D3DMAPPINGX,
+ left, 1.0f, 8.0f, 192.0f, 256.0f);
+ }
+ else
+ {
+ limit[0] = 0.0f;
+ limit[1] = m_engine->RetLimitLOD(0);
+ limit[2] = limit[1];
+ limit[3] = m_engine->RetLimitLOD(1);
+
+ for ( i=0 ; i<2 ; i++ )
+ {
+ m_engine->TrackTextureMapping(rRank, mat, D3DSTATEPART1, "lemt.tga", "",
+ limit[i*2+0], limit[i*2+1], D3DMAPPINGX,
+ right, 1.0f, 8.0f, 192.0f, 256.0f);
+
+ m_engine->TrackTextureMapping(lRank, mat, D3DSTATEPART2, "lemt.tga", "",
+ limit[i*2+0], limit[i*2+1], D3DMAPPINGX,
+ left, 1.0f, 8.0f, 192.0f, 256.0f);
+ }
+ }
+
+}
+
+
+
+// State management of the pencil drawing robot.
+
+bool CMotionVehicle::RetTraceDown()
+{
+ return m_bTraceDown;
+}
+
+void CMotionVehicle::SetTraceDown(bool bDown)
+{
+ m_bTraceDown = bDown;
+}
+
+int CMotionVehicle::RetTraceColor()
+{
+ return m_traceColor;
+}
+
+void CMotionVehicle::SetTraceColor(int color)
+{
+ m_traceColor = color;
+}
+
+float CMotionVehicle::RetTraceWidth()
+{
+ return m_traceWidth;
+}
+
+void CMotionVehicle::SetTraceWidth(float width)
+{
+ m_traceWidth = width;
+}
+
+
diff --git a/src/object/motion/motionvehicle.h b/src/object/motion/motionvehicle.h
index d3e00f9..5ca97cd 100644
--- a/src/object/motion/motionvehicle.h
+++ b/src/object/motion/motionvehicle.h
@@ -1,69 +1,69 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionvehicle.h
-
-#pragma once
-
-
-#include "object/motion/motion.h"
-
-
-
-class CMotionVehicle : public CMotion
-{
-public:
- CMotionVehicle(CInstanceManager* iMan, CObject* object);
- ~CMotionVehicle();
-
- void DeleteObject(bool bAll=false);
- bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- bool EventProcess(const Event &event);
-
- bool RetTraceDown();
- void SetTraceDown(bool bDown);
- int RetTraceColor();
- void SetTraceColor(int color);
- float RetTraceWidth();
- void SetTraceWidth(float width);
-
-protected:
- void CreatePhysics(ObjectType type);
- bool EventFrame(const Event &event);
- bool EventFrameFly(const Event &event);
- bool EventFrameInsect(const Event &event);
- bool EventFrameCanoni(const Event &event);
- void UpdateTrackMapping(float left, float right, ObjectType type);
-
-protected:
- float m_wheelTurn[4];
- float m_flyPaw[3];
- float m_posTrackLeft;
- float m_posTrackRight;
- int m_partiReactor;
- float m_armTimeAbs;
- float m_armMember;
- float m_canonTime;
- float m_lastTimeCanon;
- Math::Vector m_wheelLastPos;
- Math::Vector m_wheelLastAngle;
- Math::Vector m_posKey;
- bool m_bFlyFix;
- bool m_bTraceDown;
- int m_traceColor;
- float m_traceWidth;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionvehicle.h
+
+#pragma once
+
+
+#include "object/motion/motion.h"
+
+
+
+class CMotionVehicle : public CMotion
+{
+public:
+ CMotionVehicle(CInstanceManager* iMan, CObject* object);
+ ~CMotionVehicle();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ bool EventProcess(const Event &event);
+
+ bool RetTraceDown();
+ void SetTraceDown(bool bDown);
+ int RetTraceColor();
+ void SetTraceColor(int color);
+ float RetTraceWidth();
+ void SetTraceWidth(float width);
+
+protected:
+ void CreatePhysics(ObjectType type);
+ bool EventFrame(const Event &event);
+ bool EventFrameFly(const Event &event);
+ bool EventFrameInsect(const Event &event);
+ bool EventFrameCanoni(const Event &event);
+ void UpdateTrackMapping(float left, float right, ObjectType type);
+
+protected:
+ float m_wheelTurn[4];
+ float m_flyPaw[3];
+ float m_posTrackLeft;
+ float m_posTrackRight;
+ int m_partiReactor;
+ float m_armTimeAbs;
+ float m_armMember;
+ float m_canonTime;
+ float m_lastTimeCanon;
+ Math::Vector m_wheelLastPos;
+ Math::Vector m_wheelLastAngle;
+ Math::Vector m_posKey;
+ bool m_bFlyFix;
+ bool m_bTraceDown;
+ int m_traceColor;
+ float m_traceWidth;
+};
+
diff --git a/src/object/motion/motionworm.cpp b/src/object/motion/motionworm.cpp
index a18b7c4..daf74ff 100644
--- a/src/object/motion/motionworm.cpp
+++ b/src/object/motion/motionworm.cpp
@@ -1,365 +1,365 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionworm.cpp
-
-
-#include <stdio.h>
-
-#include "object/motion/motionworm.h"
-
-#include "old/modfile.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "math/geometry.h"
-#include "physics/physics.h"
-
-
-
-
-const float START_TIME = 1000.0f; // beginning of the relative time
-const float TIME_UPDOWN = 2.0f; // time for up / down
-const float DOWN_ALTITUDE = 3.0f; // underground distance
-const int WORM_PART = 7; // number of parts of a worm
-
-
-
-// Object's constructor.
-
-CMotionWorm::CMotionWorm(CInstanceManager* iMan, CObject* object)
- : CMotion(iMan, object)
-{
- m_timeUp = 18.0f;
- m_timeDown = 18.0f;
- m_armMember = START_TIME;
- m_armTimeAbs = START_TIME;
- m_armTimeMarch = START_TIME;
- m_armTimeAction = START_TIME;
- m_armTimeIndex = 0;
- m_armPartIndex = 0;
- m_armMemberIndex = 0;
- m_armLinSpeed = 0.0f;
- m_armCirSpeed = 0.0f;
- m_armLastAction = -1;
- m_specAction = -1;
- m_lastParticule = 0.0f;
- m_bArmStop = false;
-}
-
-// Object's destructor.
-
-CMotionWorm::~CMotionWorm()
-{
-}
-
-
-// Removes an object.
-
-void CMotionWorm::DeleteObject(bool bAll)
-{
-}
-
-
-// Creates a vehicle traveling any lands on the ground.
-
-bool CMotionWorm::Create(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- int rank, i;
- float px;
-
- if ( m_engine->RetRestCreate() < 2+WORM_PART+1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- m_object->SetType(type);
-
- // Creates the main base.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
- m_object->SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\worm0.mod"); // there is no purpose!
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(0, pos);
- m_object->SetAngleY(0, angle);
-
- // A vehicle must have a obligatory collision with a sphere of center (0, y, 0) (see GetCrashSphere).
- m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
- m_object->SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 5.0f);
-
- px = 1.0f+WORM_PART/2;
-
- // Creates the head.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(1, rank);
- m_object->SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\worm1.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(1, Math::Vector(px, 0.0f, 0.0f));
- px -= 1.0f;
-
- // Creates the body.
- for ( i=0 ; i<WORM_PART ; i++ )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2+i, rank);
- m_object->SetObjectParent(2+i, 0);
- pModFile->ReadModel("objects\\worm2.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2+i, Math::Vector(px, 0.0f, 0.0f));
- px -= 1.0f;
- }
-
- // Creates the tail.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- m_object->SetObjectRank(2+WORM_PART, rank);
- m_object->SetObjectParent(2+WORM_PART, 0);
- pModFile->ReadModel("objects\\worm3.mod");
- pModFile->CreateEngineObject(rank);
- m_object->SetPosition(2+WORM_PART, Math::Vector(px, 0.0f, 0.0f));
-
- m_object->CreateShadowCircle(0.0f, 1.0f, D3DSHADOWWORM);
-
- CreatePhysics();
- m_object->SetFloorHeight(0.0f);
-
- pos = m_object->RetPosition(0);
- m_object->SetPosition(0, pos); // to display the shadows immediately
-
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-// Creates the physics of the object.
-
-void CMotionWorm::CreatePhysics()
-{
- Character* character;
-
- m_physics->SetType(TYPE_ROLLING);
-
- character = m_object->RetCharacter();
- character->wheelFront = 10.0f;
- character->wheelBack = 10.0f;
- character->wheelLeft = 2.0f;
- character->wheelRight = 2.0f;
- character->height = -0.2f;
-
- m_physics->SetLinMotionX(MO_ADVSPEED, 3.0f);
- m_physics->SetLinMotionX(MO_RECSPEED, 3.0f);
- m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f);
- m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
- m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
- m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
- m_physics->SetLinMotionX(MO_TERFORCE, 5.0f);
- m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f);
- m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
-
- m_physics->SetCirMotionY(MO_ADVSPEED, 0.2f*Math::PI);
- m_physics->SetCirMotionY(MO_RECSPEED, 0.2f*Math::PI);
- m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
- m_physics->SetCirMotionY(MO_STOACCEL, 20.0f);
-}
-
-
-
-// Specifies a special parameter.
-
-bool CMotionWorm::SetParam(int rank, float value)
-{
- if ( rank == 0 )
- {
- m_timeDown = value;
- return true;
- }
-
- if ( rank == 1 )
- {
- m_timeUp = value;
- return true;
- }
-
- return false;
-}
-
-float CMotionWorm::RetParam(int rank)
-{
- if ( rank == 0 ) return m_timeDown;
- if ( rank == 1 ) return m_timeUp;
- return 0.0f;
-}
-
-
-
-// Management of an event.
-
-bool CMotionWorm::EventProcess(const Event &event)
-{
- CMotion::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
- }
-
- return true;
-}
-
-// Management of an event.
-
-bool CMotionWorm::EventFrame(const Event &event)
-{
- Math::Matrix* mat;
- Math::Vector pos, p, angle, speed;
- Math::Point center, pp, dim;
- float height[WORM_PART+2];
- float floor, a, s, px, curve, phase, h, zoom, radius;
- int i, under;
-
- if ( m_engine->RetPause() ) return true;
-
- s = m_physics->RetLinMotionX(MO_MOTSPEED)/m_physics->RetLinMotionX(MO_ADVSPEED);
- a = m_physics->RetCirMotionY(MO_MOTSPEED)/m_physics->RetCirMotionY(MO_ADVSPEED);
-
- if ( s == 0.0f && a != 0.0f ) s = a;
-
- m_armLinSpeed += (s-m_armLinSpeed)*event.rTime*3.0f;
- m_armCirSpeed += (a-m_armCirSpeed)*event.rTime*1.5f;
-
- m_armTimeAbs += event.rTime;
- m_armTimeMarch += event.rTime*m_armLinSpeed;
-
- under = 0; // no piece under the ground
- for ( i=0 ; i<WORM_PART+2 ; i++ )
- {
- phase = Math::Mod(m_armTimeMarch-START_TIME-i*0.3f, TIME_UPDOWN+m_timeDown+TIME_UPDOWN+m_timeUp);
- if ( phase < TIME_UPDOWN ) // descends?
- {
- h = -(phase/TIME_UPDOWN)*DOWN_ALTITUDE;
- }
- else if ( phase < TIME_UPDOWN+m_timeDown ) // advance underground?
- {
- h = -DOWN_ALTITUDE;
- under ++; // the most of a piece entirely under ground
- }
- else if ( phase < TIME_UPDOWN+m_timeDown+TIME_UPDOWN ) // up?
- {
- h = -(1.0f-(phase-TIME_UPDOWN-m_timeDown)/TIME_UPDOWN)*DOWN_ALTITUDE;
- }
- else // advance on earth?
- {
- h = 0.0f;
- }
- if ( m_object->RetBurn() ) // is burning?
- {
- h = 0.0f; // remains on earth
- }
- h += 0.3f;
- height[i] = h;
- }
- m_object->SetVisible(under!=WORM_PART+2);
-
- if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
-
- pos = m_object->RetPosition(0);
- floor = m_terrain->RetFloorLevel(pos, true);
-
- mat = m_object->RetWorldMatrix(0);
-
- px = 1.0f+WORM_PART/2;
- for ( i=0 ; i<WORM_PART+2 ; i++ )
- {
- radius = 1.0f+(height[i]-0.3f)/DOWN_ALTITUDE; // 0 = underground, 1 = surface
- radius = radius*1.3f-0.3f;
- if ( radius < 0.0f ) radius = 0.0f;
- radius *= 5.0f;
- m_engine->SetObjectShadowRadius(m_object->RetObjectRank(0), radius);
-
- pos.x = px+ sinf(m_armTimeMarch*4.0f+0.5f*i)*0.6f;
- pos.y = height[i]+sinf(m_armTimeMarch*4.0f+0.5f*i)*0.2f*m_armLinSpeed;
- pos.y += sinf(m_armTimeAbs *1.3f+0.2f*i)*0.1f;
- pos.z = sinf(m_armTimeAbs *2.0f+0.7f*i)*0.2f;
-
- curve = ((float)i-(WORM_PART+2)/2)*m_armCirSpeed*0.1f;
- center.x = 0.0f;
- center.y = 0.0f;
- pp.x = pos.x;
- pp.y = pos.z;
- pp = Math::RotatePoint(center, curve, pp);
- pos.x = pp.x;
- pos.z = pp.y;
-
- p = Transform(*mat, pos);
- pos.y += m_terrain->RetFloorLevel(p, true)-floor;
- m_object->SetPosition(i+1, pos);
-
- zoom = Math::Mod(m_armTimeAbs*0.5f+100.0f-i*0.1f, 2.0f);
- if ( zoom > 1.0f ) zoom = 2.0f-zoom;
- zoom *= 1.6f;
- if ( zoom < 1.0f ) zoom = 1.0f;
- m_object->SetZoomY(i+1, 0.2f+zoom*0.8f);
- m_object->SetZoomZ(i+1, zoom);
-
- if ( height[i] >= -1.0f && height[i] < -0.2f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.2f) <= m_armTimeMarch )
- {
- m_lastParticule = m_armTimeMarch;
-
- pos = p;
- pos.y += -height[i];
- pos.x += (Math::Rand()-0.5f)*4.0f;
- pos.z += (Math::Rand()-0.5f)*4.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*2.0f+1.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
-
- px -= 1.0f;
- }
-
- for ( i=0 ; i<WORM_PART+1 ; i++ )
- {
- pos = m_object->RetPosition(i+2);
- pos -= m_object->RetPosition(i+1);
-
- angle.z = -Math::RotateAngle(Math::Point(pos.x, pos.z).Length(), pos.y);
- angle.y = Math::PI-Math::RotateAngle(pos.x, pos.z);
- angle.x = 0.0f;
- m_object->SetAngle(i+1, angle);
-
- if ( i == WORM_PART )
- {
- m_object->SetAngle(i+2, angle);
- }
- }
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionworm.cpp
+
+
+#include <stdio.h>
+
+#include "object/motion/motionworm.h"
+
+#include "old/modfile.h"
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "math/geometry.h"
+#include "physics/physics.h"
+
+
+
+
+const float START_TIME = 1000.0f; // beginning of the relative time
+const float TIME_UPDOWN = 2.0f; // time for up / down
+const float DOWN_ALTITUDE = 3.0f; // underground distance
+const int WORM_PART = 7; // number of parts of a worm
+
+
+
+// Object's constructor.
+
+CMotionWorm::CMotionWorm(CInstanceManager* iMan, CObject* object)
+ : CMotion(iMan, object)
+{
+ m_timeUp = 18.0f;
+ m_timeDown = 18.0f;
+ m_armMember = START_TIME;
+ m_armTimeAbs = START_TIME;
+ m_armTimeMarch = START_TIME;
+ m_armTimeAction = START_TIME;
+ m_armTimeIndex = 0;
+ m_armPartIndex = 0;
+ m_armMemberIndex = 0;
+ m_armLinSpeed = 0.0f;
+ m_armCirSpeed = 0.0f;
+ m_armLastAction = -1;
+ m_specAction = -1;
+ m_lastParticule = 0.0f;
+ m_bArmStop = false;
+}
+
+// Object's destructor.
+
+CMotionWorm::~CMotionWorm()
+{
+}
+
+
+// Removes an object.
+
+void CMotionWorm::DeleteObject(bool bAll)
+{
+}
+
+
+// Creates a vehicle traveling any lands on the ground.
+
+bool CMotionWorm::Create(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ int rank, i;
+ float px;
+
+ if ( m_engine->RetRestCreate() < 2+WORM_PART+1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ m_object->SetType(type);
+
+ // Creates the main base.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEVEHICULE); // this is a moving object
+ m_object->SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\worm0.mod"); // there is no purpose!
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(0, pos);
+ m_object->SetAngleY(0, angle);
+
+ // A vehicle must have a obligatory collision with a sphere of center (0, y, 0) (see GetCrashSphere).
+ m_object->CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.20f);
+ m_object->SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 5.0f);
+
+ px = 1.0f+WORM_PART/2;
+
+ // Creates the head.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(1, rank);
+ m_object->SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\worm1.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(1, Math::Vector(px, 0.0f, 0.0f));
+ px -= 1.0f;
+
+ // Creates the body.
+ for ( i=0 ; i<WORM_PART ; i++ )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2+i, rank);
+ m_object->SetObjectParent(2+i, 0);
+ pModFile->ReadModel("objects\\worm2.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2+i, Math::Vector(px, 0.0f, 0.0f));
+ px -= 1.0f;
+ }
+
+ // Creates the tail.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ m_object->SetObjectRank(2+WORM_PART, rank);
+ m_object->SetObjectParent(2+WORM_PART, 0);
+ pModFile->ReadModel("objects\\worm3.mod");
+ pModFile->CreateEngineObject(rank);
+ m_object->SetPosition(2+WORM_PART, Math::Vector(px, 0.0f, 0.0f));
+
+ m_object->CreateShadowCircle(0.0f, 1.0f, D3DSHADOWWORM);
+
+ CreatePhysics();
+ m_object->SetFloorHeight(0.0f);
+
+ pos = m_object->RetPosition(0);
+ m_object->SetPosition(0, pos); // to display the shadows immediately
+
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+// Creates the physics of the object.
+
+void CMotionWorm::CreatePhysics()
+{
+ Character* character;
+
+ m_physics->SetType(TYPE_ROLLING);
+
+ character = m_object->RetCharacter();
+ character->wheelFront = 10.0f;
+ character->wheelBack = 10.0f;
+ character->wheelLeft = 2.0f;
+ character->wheelRight = 2.0f;
+ character->height = -0.2f;
+
+ m_physics->SetLinMotionX(MO_ADVSPEED, 3.0f);
+ m_physics->SetLinMotionX(MO_RECSPEED, 3.0f);
+ m_physics->SetLinMotionX(MO_ADVACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_RECACCEL, 10.0f);
+ m_physics->SetLinMotionX(MO_STOACCEL, 40.0f);
+ m_physics->SetLinMotionX(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERSLIDE, 5.0f);
+ m_physics->SetLinMotionX(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_TERFORCE, 5.0f);
+ m_physics->SetLinMotionZ(MO_MOTACCEL, 40.0f);
+
+ m_physics->SetCirMotionY(MO_ADVSPEED, 0.2f*Math::PI);
+ m_physics->SetCirMotionY(MO_RECSPEED, 0.2f*Math::PI);
+ m_physics->SetCirMotionY(MO_ADVACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_RECACCEL, 10.0f);
+ m_physics->SetCirMotionY(MO_STOACCEL, 20.0f);
+}
+
+
+
+// Specifies a special parameter.
+
+bool CMotionWorm::SetParam(int rank, float value)
+{
+ if ( rank == 0 )
+ {
+ m_timeDown = value;
+ return true;
+ }
+
+ if ( rank == 1 )
+ {
+ m_timeUp = value;
+ return true;
+ }
+
+ return false;
+}
+
+float CMotionWorm::RetParam(int rank)
+{
+ if ( rank == 0 ) return m_timeDown;
+ if ( rank == 1 ) return m_timeUp;
+ return 0.0f;
+}
+
+
+
+// Management of an event.
+
+bool CMotionWorm::EventProcess(const Event &event)
+{
+ CMotion::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+ }
+
+ return true;
+}
+
+// Management of an event.
+
+bool CMotionWorm::EventFrame(const Event &event)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, p, angle, speed;
+ Math::Point center, pp, dim;
+ float height[WORM_PART+2];
+ float floor, a, s, px, curve, phase, h, zoom, radius;
+ int i, under;
+
+ if ( m_engine->RetPause() ) return true;
+
+ s = m_physics->RetLinMotionX(MO_MOTSPEED)/m_physics->RetLinMotionX(MO_ADVSPEED);
+ a = m_physics->RetCirMotionY(MO_MOTSPEED)/m_physics->RetCirMotionY(MO_ADVSPEED);
+
+ if ( s == 0.0f && a != 0.0f ) s = a;
+
+ m_armLinSpeed += (s-m_armLinSpeed)*event.rTime*3.0f;
+ m_armCirSpeed += (a-m_armCirSpeed)*event.rTime*1.5f;
+
+ m_armTimeAbs += event.rTime;
+ m_armTimeMarch += event.rTime*m_armLinSpeed;
+
+ under = 0; // no piece under the ground
+ for ( i=0 ; i<WORM_PART+2 ; i++ )
+ {
+ phase = Math::Mod(m_armTimeMarch-START_TIME-i*0.3f, TIME_UPDOWN+m_timeDown+TIME_UPDOWN+m_timeUp);
+ if ( phase < TIME_UPDOWN ) // descends?
+ {
+ h = -(phase/TIME_UPDOWN)*DOWN_ALTITUDE;
+ }
+ else if ( phase < TIME_UPDOWN+m_timeDown ) // advance underground?
+ {
+ h = -DOWN_ALTITUDE;
+ under ++; // the most of a piece entirely under ground
+ }
+ else if ( phase < TIME_UPDOWN+m_timeDown+TIME_UPDOWN ) // up?
+ {
+ h = -(1.0f-(phase-TIME_UPDOWN-m_timeDown)/TIME_UPDOWN)*DOWN_ALTITUDE;
+ }
+ else // advance on earth?
+ {
+ h = 0.0f;
+ }
+ if ( m_object->RetBurn() ) // is burning?
+ {
+ h = 0.0f; // remains on earth
+ }
+ h += 0.3f;
+ height[i] = h;
+ }
+ m_object->SetVisible(under!=WORM_PART+2);
+
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return true;
+
+ pos = m_object->RetPosition(0);
+ floor = m_terrain->RetFloorLevel(pos, true);
+
+ mat = m_object->RetWorldMatrix(0);
+
+ px = 1.0f+WORM_PART/2;
+ for ( i=0 ; i<WORM_PART+2 ; i++ )
+ {
+ radius = 1.0f+(height[i]-0.3f)/DOWN_ALTITUDE; // 0 = underground, 1 = surface
+ radius = radius*1.3f-0.3f;
+ if ( radius < 0.0f ) radius = 0.0f;
+ radius *= 5.0f;
+ m_engine->SetObjectShadowRadius(m_object->RetObjectRank(0), radius);
+
+ pos.x = px+ sinf(m_armTimeMarch*4.0f+0.5f*i)*0.6f;
+ pos.y = height[i]+sinf(m_armTimeMarch*4.0f+0.5f*i)*0.2f*m_armLinSpeed;
+ pos.y += sinf(m_armTimeAbs *1.3f+0.2f*i)*0.1f;
+ pos.z = sinf(m_armTimeAbs *2.0f+0.7f*i)*0.2f;
+
+ curve = ((float)i-(WORM_PART+2)/2)*m_armCirSpeed*0.1f;
+ center.x = 0.0f;
+ center.y = 0.0f;
+ pp.x = pos.x;
+ pp.y = pos.z;
+ pp = Math::RotatePoint(center, curve, pp);
+ pos.x = pp.x;
+ pos.z = pp.y;
+
+ p = Transform(*mat, pos);
+ pos.y += m_terrain->RetFloorLevel(p, true)-floor;
+ m_object->SetPosition(i+1, pos);
+
+ zoom = Math::Mod(m_armTimeAbs*0.5f+100.0f-i*0.1f, 2.0f);
+ if ( zoom > 1.0f ) zoom = 2.0f-zoom;
+ zoom *= 1.6f;
+ if ( zoom < 1.0f ) zoom = 1.0f;
+ m_object->SetZoomY(i+1, 0.2f+zoom*0.8f);
+ m_object->SetZoomZ(i+1, zoom);
+
+ if ( height[i] >= -1.0f && height[i] < -0.2f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.2f) <= m_armTimeMarch )
+ {
+ m_lastParticule = m_armTimeMarch;
+
+ pos = p;
+ pos.y += -height[i];
+ pos.x += (Math::Rand()-0.5f)*4.0f;
+ pos.z += (Math::Rand()-0.5f)*4.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*2.0f+1.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+
+ px -= 1.0f;
+ }
+
+ for ( i=0 ; i<WORM_PART+1 ; i++ )
+ {
+ pos = m_object->RetPosition(i+2);
+ pos -= m_object->RetPosition(i+1);
+
+ angle.z = -Math::RotateAngle(Math::Point(pos.x, pos.z).Length(), pos.y);
+ angle.y = Math::PI-Math::RotateAngle(pos.x, pos.z);
+ angle.x = 0.0f;
+ m_object->SetAngle(i+1, angle);
+
+ if ( i == WORM_PART )
+ {
+ m_object->SetAngle(i+2, angle);
+ }
+ }
+
+ return true;
+}
+
+
diff --git a/src/object/motion/motionworm.h b/src/object/motion/motionworm.h
index f159e5c..1b2abf9 100644
--- a/src/object/motion/motionworm.h
+++ b/src/object/motion/motionworm.h
@@ -1,62 +1,62 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// motionworm.h
-
-#pragma once
-
-
-#include "object/motion/motion.h"
-
-
-
-class CMotionWorm : public CMotion
-{
-public:
- CMotionWorm(CInstanceManager* iMan, CObject* object);
- ~CMotionWorm();
-
- void DeleteObject(bool bAll=false);
- bool Create(Math::Vector pos, float angle, ObjectType type, float power);
- bool EventProcess(const Event &event);
-
- bool SetParam(int rank, float value);
- float RetParam(int rank);
-
-protected:
- void CreatePhysics();
- bool EventFrame(const Event &event);
-
-protected:
- float m_timeUp;
- float m_timeDown;
- float m_armMember;
- float m_armTimeAbs;
- float m_armTimeMarch;
- float m_armTimeAction;
- short m_armAngles[3*3*3*3*10];
- int m_armTimeIndex;
- int m_armPartIndex;
- int m_armMemberIndex;
- int m_armLastAction;
- float m_armLinSpeed;
- float m_armCirSpeed;
- int m_specAction;
- float m_specTime;
- bool m_bArmStop;
- float m_lastParticule;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// motionworm.h
+
+#pragma once
+
+
+#include "object/motion/motion.h"
+
+
+
+class CMotionWorm : public CMotion
+{
+public:
+ CMotionWorm(CInstanceManager* iMan, CObject* object);
+ ~CMotionWorm();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(Math::Vector pos, float angle, ObjectType type, float power);
+ bool EventProcess(const Event &event);
+
+ bool SetParam(int rank, float value);
+ float RetParam(int rank);
+
+protected:
+ void CreatePhysics();
+ bool EventFrame(const Event &event);
+
+protected:
+ float m_timeUp;
+ float m_timeDown;
+ float m_armMember;
+ float m_armTimeAbs;
+ float m_armTimeMarch;
+ float m_armTimeAction;
+ short m_armAngles[3*3*3*3*10];
+ int m_armTimeIndex;
+ int m_armPartIndex;
+ int m_armMemberIndex;
+ int m_armLastAction;
+ float m_armLinSpeed;
+ float m_armCirSpeed;
+ int m_specAction;
+ float m_specTime;
+ bool m_bArmStop;
+ float m_lastParticule;
+};
+
diff --git a/src/object/object.cpp b/src/object/object.cpp
index 6931bd2..692a9c9 100644
--- a/src/object/object.cpp
+++ b/src/object/object.cpp
@@ -1,7606 +1,7606 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// object.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "CBot/CBotDll.h"
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "old/d3dutil.h"
-#include "common/global.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "old/math3d.h"
-#include "object/mainmovie.h"
-#include "object/robotmain.h"
-#include "old/light.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "old/blitz.h"
-#include "old/camera.h"
-#include "old/particule.h"
-#include "physics/physics.h"
-#include "object/brain.h"
-#include "object/motion/motion.h"
-#include "object/motion/motionhuman.h"
-#include "object/motion/motiontoto.h"
-#include "object/motion/motionvehicle.h"
-#include "object/motion/motionmother.h"
-#include "object/motion/motionant.h"
-#include "object/motion/motionspider.h"
-#include "object/motion/motionbee.h"
-#include "object/motion/motionworm.h"
-#include "old/modfile.h"
-#include "object/auto/auto.h"
-#include "object/auto/autobase.h"
-#include "object/auto/autoportico.h"
-#include "object/auto/autoderrick.h"
-#include "object/auto/autofactory.h"
-#include "object/auto/autorepair.h"
-#include "object/auto/autodestroyer.h"
-#include "object/auto/autostation.h"
-#include "object/auto/autoenergy.h"
-#include "object/auto/autoconvert.h"
-#include "object/auto/autotower.h"
-#include "object/auto/autoresearch.h"
-#include "object/auto/autolabo.h"
-#include "object/auto/autonuclear.h"
-#include "object/auto/autoradar.h"
-#include "object/auto/autoegg.h"
-#include "object/auto/autonest.h"
-#include "object/auto/autoroot.h"
-#include "object/auto/autoflag.h"
-#include "object/auto/autoinfo.h"
-#include "object/auto/autojostle.h"
-#include "object/auto/autopara.h"
-#include "object/auto/autosafe.h"
-#include "object/auto/autohuston.h"
-#include "object/auto/automush.h"
-#include "object/auto/autokid.h"
-#include "object/task/task.h"
-#include "old/pyro.h"
-#include "ui/displaytext.h"
-#include "script/cmdtoken.h"
-#include "script/cbottoken.h"
-#include "old/sound.h"
-#include "object/object.h"
-
-
-
-#define ADJUST_ONBOARD false // true -> adjusts the camera ONBOARD
-#define ADJUST_ARM false // true -> adjusts the manipulator arm
-const float VIRUS_DELAY = 60.0f; // duration of virus infection
-const float LOSS_SHIELD = 0.24f; // loss of the shield by shot
-const float LOSS_SHIELD_H = 0.10f; // loss of the shield for humans
-const float LOSS_SHIELD_M = 0.02f; // loss of the shield for the laying
-
-#if ADJUST_ONBOARD
-static float debug_x = 0.0f;
-static float debug_y = 0.0f;
-static float debug_z = 0.0f;
-#endif
-
-#if ADJUST_ARM
-static float debug_arm1 = 0.0f;
-static float debug_arm2 = 0.0f;
-static float debug_arm3 = 0.0f;
-#endif
-
-
-
-
-// Updates the class Object.
-
-void uObject(CBotVar* botThis, void* user)
-{
- CObject* object = (CObject*)user;
- CObject* power;
- CObject* fret;
- CPhysics* physics;
- CBotVar *pVar, *pSub;
- ObjectType type;
- Math::Vector pos;
- float value;
- int iValue;
-
- if ( object == 0 ) return;
-
- physics = object->RetPhysics();
-
- // Updates the object's type.
- pVar = botThis->GivItemList(); // "category"
- type = object->RetType();
- pVar->SetValInt(type, object->RetName());
-
- // Updates the position of the object.
- pVar = pVar->GivNext(); // "position"
- if ( object->RetTruck() == 0 )
- {
- pos = object->RetPosition(0);
- pos.y -= object->RetWaterLevel(); // relative to sea level!
- pSub = pVar->GivItemList(); // "x"
- pSub->SetValFloat(pos.x/g_unit);
- pSub = pSub->GivNext(); // "y"
- pSub->SetValFloat(pos.z/g_unit);
- pSub = pSub->GivNext(); // "z"
- pSub->SetValFloat(pos.y/g_unit);
- }
- else // object transported?
- {
- pSub = pVar->GivItemList(); // "x"
- pSub->SetInit(IS_NAN);
- pSub = pSub->GivNext(); // "y"
- pSub->SetInit(IS_NAN);
- pSub = pSub->GivNext(); // "z"
- pSub->SetInit(IS_NAN);
- }
-
- // Updates the angle.
- pos = object->RetAngle(0);
- pos += object->RetInclinaison();
- pVar = pVar->GivNext(); // "orientation"
- pVar->SetValFloat(360.0f-Math::Mod(pos.y*180.0f/Math::PI, 360.0f));
- pVar = pVar->GivNext(); // "pitch"
- pVar->SetValFloat(pos.z*180.0f/Math::PI);
- pVar = pVar->GivNext(); // "roll"
- pVar->SetValFloat(pos.x*180.0f/Math::PI);
-
- // Updates the energy level of the object.
- pVar = pVar->GivNext(); // "energyLevel"
- value = object->RetEnergy();
- pVar->SetValFloat(value);
-
- // Updates the shield level of the object.
- pVar = pVar->GivNext(); // "shieldLevel"
- value = object->RetShield();
- pVar->SetValFloat(value);
-
- // Updates the temperature of the reactor.
- pVar = pVar->GivNext(); // "temperature"
- if ( physics == 0 ) value = 0.0f;
- else value = 1.0f-physics->RetReactorRange();
- pVar->SetValFloat(value);
-
- // Updates the height above the ground.
- pVar = pVar->GivNext(); // "altitude"
- if ( physics == 0 ) value = 0.0f;
- else value = physics->RetFloorHeight();
- pVar->SetValFloat(value/g_unit);
-
- // Updates the lifetime of the object.
- pVar = pVar->GivNext(); // "lifeTime"
- value = object->RetAbsTime();
- pVar->SetValFloat(value);
-
- // Updates the material of the object.
- pVar = pVar->GivNext(); // "material"
- iValue = object->RetMaterial();
- pVar->SetValInt(iValue);
-
- // Updates the type of battery.
- pVar = pVar->GivNext(); // "energyCell"
- power = object->RetPower();
- if ( power == 0 ) pVar->SetPointer(0);
- else pVar->SetPointer(power->RetBotVar());
-
- // Updates the transported object's type.
- pVar = pVar->GivNext(); // "load"
- fret = object->RetFret();
- if ( fret == 0 ) pVar->SetPointer(0);
- else pVar->SetPointer(fret->RetBotVar());
-}
-
-
-
-
-// Object's constructor.
-
-CObject::CObject(CInstanceManager* iMan)
-{
- int i;
-
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_OBJECT, this, 500);
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- m_physics = 0;
- m_brain = 0;
- m_motion = 0;
- m_auto = 0;
- m_runScript = 0;
-
- m_type = OBJECT_FIX;
- m_id = ++g_id;
- m_option = 0;
- m_name[0] = 0;
- m_partiReactor = -1;
- m_shadowLight = -1;
- m_effectLight = -1;
- m_linVibration = Math::Vector(0.0f, 0.0f, 0.0f);
- m_cirVibration = Math::Vector(0.0f, 0.0f, 0.0f);
- m_inclinaison = Math::Vector(0.0f, 0.0f, 0.0f);
- m_lastParticule = 0.0f;
-
- m_power = 0;
- m_fret = 0;
- m_truck = 0;
- m_truckLink = 0;
- m_energy = 1.0f;
- m_capacity = 1.0f;
- m_shield = 1.0f;
- m_range = 0.0f;
- m_transparency = 0.0f;
- m_lastEnergy = 999.9f;
- m_bHilite = false;
- m_bSelect = false;
- m_bSelectable = true;
- m_bCheckToken = true;
- m_bVisible = true;
- m_bEnable = true;
- m_bGadget = false;
- m_bProxyActivate = false;
- m_bTrainer = false;
- m_bToy = false;
- m_bManual = false;
- m_bFixed = false;
- m_bClip = true;
- m_bShowLimit = false;
- m_showLimitRadius = 0.0f;
- m_aTime = 0.0f;
- m_shotTime = 0.0f;
- m_bVirusMode = false;
- m_virusTime = 0.0f;
- m_lastVirusParticule = 0.0f;
- m_totalDesectList = 0;
- m_bLock = false;
- m_bExplo = false;
- m_bCargo = false;
- m_bBurn = false;
- m_bDead = false;
- m_bFlat = false;
- m_gunGoalV = 0.0f;
- m_gunGoalH = 0.0f;
- m_shieldRadius = 0.0f;
- m_defRank = -1;
- m_magnifyDamage = 1.0f;
- m_proxyDistance = 60.0f;
- m_param = 0.0f;
-
- ZeroMemory(&m_character, sizeof(Character));
- m_character.wheelFront = 1.0f;
- m_character.wheelBack = 1.0f;
- m_character.wheelLeft = 1.0f;
- m_character.wheelRight = 1.0f;
-
- m_resetCap = RESET_NONE;
- m_bResetBusy = false;
- m_resetPosition = Math::Vector(0.0f, 0.0f, 0.0f);
- m_resetAngle = Math::Vector(0.0f, 0.0f, 0.0f);
- m_resetRun = -1;
-
- m_cameraType = CAMERA_BACK;
- m_cameraDist = 50.0f;
- m_bCameraLock = false;
-
- m_infoTotal = 0;
- m_infoReturn = NAN;
- m_bInfoUpdate = false;
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- m_objectPart[i].bUsed = false;
- }
- m_totalPart = 0;
-
- for ( i=0 ; i<4 ; i++ )
- {
- m_partiSel[i] = -1;
- }
-
- for ( i=0 ; i<OBJECTMAXCMDLINE ; i++ )
- {
- m_cmdLine[i] = NAN;
- }
-
- FlushCrashShere();
- m_globalSpherePos = Math::Vector(0.0f, 0.0f, 0.0f);
- m_globalSphereRadius = 0.0f;
- m_jotlerSpherePos = Math::Vector(0.0f, 0.0f, 0.0f);
- m_jotlerSphereRadius = 0.0f;
-
- CBotClass* bc = CBotClass::Find("object");
- if ( bc != 0 )
- {
- bc->AddUpdateFunc(uObject);
- }
-
- m_botVar = CBotVar::Create("", CBotTypResult(CBotTypClass, "object"));
- m_botVar->SetUserPtr(this);
- m_botVar->SetIdent(m_id);
-}
-
-// Object's destructor.
-
-CObject::~CObject()
-{
- if ( m_botVar != 0 )
- {
- m_botVar->SetUserPtr(OBJECTDELETED);
- delete m_botVar;
- }
-
- delete m_physics;
- delete m_brain;
- delete m_motion;
- delete m_auto;
-
- m_iMan->DeleteInstance(CLASS_OBJECT, this);
-}
-
-
-// Removes an object.
-// If bAll = true, it does not help,
-// because all objects in the scene are quickly destroyed!
-
-void CObject::DeleteObject(bool bAll)
-{
- CObject* pObj;
- CPyro* pPyro;
- int i;
-
- if ( m_botVar != 0 )
- {
- m_botVar->SetUserPtr(OBJECTDELETED);
- }
-
- if ( m_camera->RetObject() == this )
- {
- m_camera->SetObject(0);
- }
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- pObj->DeleteDeselList(this);
- }
-
- if ( !bAll )
- {
-#if 0
- type = m_camera->RetType();
- if ( (type == CAMERA_BACK ||
- type == CAMERA_FIX ||
- type == CAMERA_EXPLO ||
- type == CAMERA_ONBOARD) &&
- m_camera->RetObject() == this )
- {
- pObj = m_main->SearchNearest(RetPosition(0), this);
- if ( pObj == 0 )
- {
- m_camera->SetObject(0);
- m_camera->SetType(CAMERA_FREE);
- }
- else
- {
- m_camera->SetObject(pObj);
- m_camera->SetType(CAMERA_BACK);
- }
- }
-#endif
- for ( i=0 ; i<1000000 ; i++ )
- {
- pPyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, i);
- if ( pPyro == 0 ) break;
-
- pPyro->CutObjectLink(this); // the object no longer exists
- }
-
- if ( m_bSelect )
- {
- SetSelect(false);
- }
-
- if ( m_type == OBJECT_BASE ||
- m_type == OBJECT_FACTORY ||
- m_type == OBJECT_REPAIR ||
- m_type == OBJECT_DESTROYER||
- m_type == OBJECT_DERRICK ||
- m_type == OBJECT_STATION ||
- m_type == OBJECT_CONVERT ||
- m_type == OBJECT_TOWER ||
- m_type == OBJECT_RESEARCH ||
- m_type == OBJECT_RADAR ||
- m_type == OBJECT_INFO ||
- m_type == OBJECT_ENERGY ||
- m_type == OBJECT_LABO ||
- m_type == OBJECT_NUCLEAR ||
- m_type == OBJECT_PARA ||
- m_type == OBJECT_SAFE ||
- m_type == OBJECT_HUSTON ||
- m_type == OBJECT_START ||
- m_type == OBJECT_END ) // building?
- {
- m_terrain->DeleteBuildingLevel(RetPosition(0)); // flattens the field
- }
- }
-
- m_type = OBJECT_NULL; // invalid object until complete destruction
-
- if ( m_partiReactor != -1 )
- {
- m_particule->DeleteParticule(m_partiReactor);
- m_partiReactor = -1;
- }
-
- if ( m_shadowLight != -1 )
- {
- m_light->DeleteLight(m_shadowLight);
- m_shadowLight = -1;
- }
-
- if ( m_effectLight != -1 )
- {
- m_light->DeleteLight(m_effectLight);
- m_effectLight = -1;
- }
-
- if ( m_physics != 0 )
- {
- m_physics->DeleteObject(bAll);
- }
-
- if ( m_brain != 0 )
- {
- m_brain->DeleteObject(bAll);
- }
-
- if ( m_motion != 0 )
- {
- m_motion->DeleteObject(bAll);
- }
-
- if ( m_auto != 0 )
- {
- m_auto->DeleteObject(bAll);
- }
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- if ( m_objectPart[i].bUsed )
- {
- m_objectPart[i].bUsed = false;
- m_engine->DeleteObject(m_objectPart[i].object);
-
- if ( m_objectPart[i].masterParti != -1 )
- {
- m_particule->DeleteParticule(m_objectPart[i].masterParti);
- m_objectPart[i].masterParti = -1;
- }
- }
- }
-
- if ( m_bShowLimit )
- {
- m_main->FlushShowLimit(0);
- m_bShowLimit = false;
- }
-
- if ( !bAll ) m_main->CreateShortcuts();
-}
-
-// Simplifies a object (he was the brain, among others).
-
-void CObject::Simplify()
-{
- if ( m_brain != 0 )
- {
- m_brain->StopProgram();
- }
- m_main->SaveOneScript(this);
-
- if ( m_physics != 0 )
- {
- m_physics->DeleteObject();
- delete m_physics;
- m_physics = 0;
- }
-
- if ( m_brain != 0 )
- {
- m_brain->DeleteObject();
- delete m_brain;
- m_brain = 0;
- }
-
- if ( m_motion != 0 )
- {
- m_motion->DeleteObject();
- delete m_motion;
- m_motion = 0;
- }
-
- if ( m_auto != 0 )
- {
- m_auto->DeleteObject();
- delete m_auto;
- m_auto = 0;
- }
-
- m_main->CreateShortcuts();
-}
-
-
-// Detonates an object, when struck by a shot.
-// If false is returned, the object is still screwed.
-// If true is returned, the object is destroyed.
-
-bool CObject::ExploObject(ExploType type, float force, float decay)
-{
- PyroType pyroType;
- CPyro* pyro;
- float loss, shield;
-
- if ( type == EXPLO_BURN )
- {
- if ( m_type == OBJECT_MOBILEtg ||
- m_type == OBJECT_TEEN28 || // cylinder?
- m_type == OBJECT_METAL ||
- m_type == OBJECT_POWER ||
- m_type == OBJECT_ATOMIC ||
- m_type == OBJECT_TNT ||
- m_type == OBJECT_SCRAP1 ||
- m_type == OBJECT_SCRAP2 ||
- m_type == OBJECT_SCRAP3 ||
- m_type == OBJECT_SCRAP4 ||
- m_type == OBJECT_SCRAP5 ||
- m_type == OBJECT_BULLET ||
- m_type == OBJECT_EGG ) // object that isn't burning?
- {
- type = EXPLO_BOUM;
- force = 1.0f;
- decay = 1.0f;
- }
- }
-
- if ( EXPLO_BOUM )
- {
- if ( m_shotTime < 0.5f ) return false;
- m_shotTime = 0.0f;
- }
-
- if ( m_type == OBJECT_HUMAN && m_bDead ) return false;
-
- // Calculate the power lost by the explosion.
- if ( force == 0.0f )
- {
- if ( m_type == OBJECT_HUMAN )
- {
- loss = LOSS_SHIELD_H;
- }
- else if ( m_type == OBJECT_MOTHER )
- {
- loss = LOSS_SHIELD_M;
- }
- else
- {
- loss = LOSS_SHIELD;
- }
- }
- else
- {
- loss = force;
- }
- loss *= m_magnifyDamage;
- loss *= decay;
-
- // Decreases the power of the shield.
- shield = RetShield();
- shield -= loss;
- if ( shield < 0.0f ) shield = 0.0f;
- SetShield(shield);
-
- if ( shield > 0.0f ) // not dead yet?
- {
- if ( type == EXPLO_WATER )
- {
- if ( m_type == OBJECT_HUMAN )
- {
- pyroType = PT_SHOTH;
- }
- else
- {
- pyroType = PT_SHOTW;
- }
- }
- else
- {
- if ( m_type == OBJECT_HUMAN )
- {
- pyroType = PT_SHOTH;
- }
- else if ( m_type == OBJECT_MOTHER )
- {
- pyroType = PT_SHOTM;
- }
- else
- {
- pyroType = PT_SHOTT;
- }
- }
- }
- else // completely dead?
- {
- if ( type == EXPLO_BURN ) // burning?
- {
- if ( m_type == OBJECT_MOTHER ||
- m_type == OBJECT_ANT ||
- m_type == OBJECT_SPIDER ||
- m_type == OBJECT_BEE ||
- m_type == OBJECT_WORM ||
- m_type == OBJECT_BULLET )
- {
- pyroType = PT_BURNO;
- SetBurn(true);
- }
- else if ( m_type == OBJECT_HUMAN )
- {
- pyroType = PT_DEADG;
- }
- else
- {
- pyroType = PT_BURNT;
- SetBurn(true);
- }
- SetVirusMode(false);
- }
- else if ( type == EXPLO_WATER )
- {
- if ( m_type == OBJECT_HUMAN )
- {
- pyroType = PT_DEADW;
- }
- else
- {
- pyroType = PT_FRAGW;
- }
- }
- else // explosion?
- {
- if ( m_type == OBJECT_ANT ||
- m_type == OBJECT_SPIDER ||
- m_type == OBJECT_BEE ||
- m_type == OBJECT_WORM )
- {
- pyroType = PT_EXPLOO;
- }
- else if ( m_type == OBJECT_MOTHER ||
- m_type == OBJECT_NEST ||
- m_type == OBJECT_BULLET )
- {
- pyroType = PT_FRAGO;
- }
- else if ( m_type == OBJECT_HUMAN )
- {
- pyroType = PT_DEADG;
- }
- else if ( m_type == OBJECT_BASE ||
- m_type == OBJECT_DERRICK ||
- m_type == OBJECT_FACTORY ||
- m_type == OBJECT_STATION ||
- m_type == OBJECT_CONVERT ||
- m_type == OBJECT_REPAIR ||
- m_type == OBJECT_DESTROYER||
- m_type == OBJECT_TOWER ||
- m_type == OBJECT_NEST ||
- m_type == OBJECT_RESEARCH ||
- m_type == OBJECT_RADAR ||
- m_type == OBJECT_INFO ||
- m_type == OBJECT_ENERGY ||
- m_type == OBJECT_LABO ||
- m_type == OBJECT_NUCLEAR ||
- m_type == OBJECT_PARA ||
- m_type == OBJECT_SAFE ||
- m_type == OBJECT_HUSTON ||
- m_type == OBJECT_START ||
- m_type == OBJECT_END ) // building?
- {
- pyroType = PT_FRAGT;
- }
- else if ( m_type == OBJECT_MOBILEtg ||
- m_type == OBJECT_TEEN28 || // cylinder?
- m_type == OBJECT_TEEN31 ) // basket?
- {
- pyroType = PT_FRAGT;
- }
- else
- {
- pyroType = PT_EXPLOT;
- }
- }
-
- loss = 1.0f;
- }
-
- pyro = new CPyro(m_iMan);
- pyro->Create(pyroType, this, loss);
-
- if ( shield == 0.0f ) // dead?
- {
- if ( m_brain != 0 )
- {
- m_brain->StopProgram();
- }
- m_main->SaveOneScript(this);
- }
-
- if ( shield > 0.0f ) return false; // not dead yet
-
- if ( RetSelect() )
- {
- SetSelect(false); // deselects the object
- m_camera->SetType(CAMERA_EXPLO);
- m_main->DeselectAll();
- }
- DeleteDeselList(this);
-
- if ( m_botVar != 0 )
- {
- if ( m_type == OBJECT_STONE ||
- m_type == OBJECT_URANIUM ||
- m_type == OBJECT_METAL ||
- m_type == OBJECT_POWER ||
- m_type == OBJECT_ATOMIC ||
- m_type == OBJECT_BULLET ||
- m_type == OBJECT_BBOX ||
- m_type == OBJECT_TNT ||
- m_type == OBJECT_SCRAP1 ||
- m_type == OBJECT_SCRAP2 ||
- m_type == OBJECT_SCRAP3 ||
- m_type == OBJECT_SCRAP4 ||
- m_type == OBJECT_SCRAP5 ) // (*)
- {
- m_botVar->SetUserPtr(OBJECTDELETED);
- }
- }
-
- return true;
-}
-
-// (*) If a robot or cosmonaut dies, the subject must continue to exist,
-// so that programs of the ants continue to operate as usual.
-
-
-// Initializes a new part.
-
-void CObject::InitPart(int part)
-{
- m_objectPart[part].bUsed = true;
- m_objectPart[part].object = -1;
- m_objectPart[part].parentPart = -1;
-
- m_objectPart[part].position = Math::Vector(0.0f, 0.0f, 0.0f);
- m_objectPart[part].angle.y = 0.0f;
- m_objectPart[part].angle.x = 0.0f;
- m_objectPart[part].angle.z = 0.0f;
- m_objectPart[part].zoom = Math::Vector(1.0f, 1.0f, 1.0f);
-
- m_objectPart[part].bTranslate = true;
- m_objectPart[part].bRotate = true;
- m_objectPart[part].bZoom = false;
-
- m_objectPart[part].matTranslate.LoadIdentity();
- m_objectPart[part].matRotate.LoadIdentity();
- m_objectPart[part].matTransform.LoadIdentity();
- m_objectPart[part].matWorld.LoadIdentity();;
-
- m_objectPart[part].masterParti = -1;
-}
-
-// Creates a new part, and returns its number.
-// Returns -1 on error.
-
-int CObject::CreatePart()
-{
- int i;
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- if ( m_objectPart[i].bUsed ) continue;
-
- InitPart(i);
- UpdateTotalPart();
- return i;
- }
- return -1;
-}
-
-// Removes part.
-
-void CObject::DeletePart(int part)
-{
- if ( !m_objectPart[part].bUsed ) return;
-
- if ( m_objectPart[part].masterParti != -1 )
- {
- m_particule->DeleteParticule(m_objectPart[part].masterParti);
- m_objectPart[part].masterParti = -1;
- }
-
- m_objectPart[part].bUsed = false;
- m_engine->DeleteObject(m_objectPart[part].object);
- UpdateTotalPart();
-}
-
-void CObject::UpdateTotalPart()
-{
- int i;
-
- m_totalPart = 0;
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- if ( m_objectPart[i].bUsed )
- {
- m_totalPart = i+1;
- }
- }
-}
-
-
-// Specifies the number of the object of a part.
-
-void CObject::SetObjectRank(int part, int objRank)
-{
- if ( !m_objectPart[part].bUsed ) // object not created?
- {
- InitPart(part);
- UpdateTotalPart();
- }
- m_objectPart[part].object = objRank;
-}
-
-// Returns the number of part.
-
-int CObject::RetObjectRank(int part)
-{
- if ( !m_objectPart[part].bUsed ) return -1;
- return m_objectPart[part].object;
-}
-
-// Specifies what is the parent of a part.
-// Reminder: Part 0 is always the father of all
-// and therefore the main part (eg the chassis of a car).
-
-void CObject::SetObjectParent(int part, int parent)
-{
- m_objectPart[part].parentPart = parent;
-}
-
-
-// Specifies the type of the object.
-
-void CObject::SetType(ObjectType type)
-{
- m_type = type;
- strcpy(m_name, RetObjectName(m_type));
-
- if ( m_type == OBJECT_MOBILErs )
- {
- m_param = 1.0f; // shield up to default
- }
-
- if ( m_type == OBJECT_ATOMIC )
- {
- m_capacity = 10.0f;
- }
- else
- {
- m_capacity = 1.0f;
- }
-
- if ( m_type == OBJECT_MOBILEwc ||
- m_type == OBJECT_MOBILEtc ||
- m_type == OBJECT_MOBILEfc ||
- m_type == OBJECT_MOBILEic ||
- m_type == OBJECT_MOBILEwi ||
- m_type == OBJECT_MOBILEti ||
- m_type == OBJECT_MOBILEfi ||
- m_type == OBJECT_MOBILEii ||
- m_type == OBJECT_MOBILErc ) // cannon vehicle?
- {
- m_cameraType = CAMERA_ONBOARD;
- }
-}
-
-ObjectType CObject::RetType()
-{
- return m_type;
-}
-
-char* CObject::RetName()
-{
- return m_name;
-}
-
-
-// Choosing the option to use.
-
-void CObject::SetOption(int option)
-{
- m_option = option;
-}
-
-int CObject::RetOption()
-{
- return m_option;
-}
-
-
-// Management of the unique identifier of an object.
-
-void CObject::SetID(int id)
-{
- m_id = id;
-
- if ( m_botVar != 0 )
- {
- m_botVar->SetIdent(m_id);
- }
-}
-
-int CObject::RetID()
-{
- return m_id;
-}
-
-
-// Saves all the parameters of the object.
-
-bool CObject::Write(char *line)
-{
- Math::Vector pos;
- Info info;
- char name[100];
- float value;
- int i;
-
- sprintf(name, " camera=%s", GetCamera(RetCameraType()));
- strcat(line, name);
-
- if ( RetCameraLock() != 0 )
- {
- sprintf(name, " cameraLock=%d", RetCameraLock());
- strcat(line, name);
- }
-
- if ( RetEnergy() != 0.0f )
- {
- sprintf(name, " energy=%.2f", RetEnergy());
- strcat(line, name);
- }
-
- if ( RetCapacity() != 1.0f )
- {
- sprintf(name, " capacity=%.2f", RetCapacity());
- strcat(line, name);
- }
-
- if ( RetShield() != 1.0f )
- {
- sprintf(name, " shield=%.2f", RetShield());
- strcat(line, name);
- }
-
- if ( RetRange() != 1.0f )
- {
- sprintf(name, " range=%.2f", RetRange());
- strcat(line, name);
- }
-
- if ( RetSelectable() != 1 )
- {
- sprintf(name, " selectable=%d", RetSelectable());
- strcat(line, name);
- }
-
- if ( RetEnable() != 1 )
- {
- sprintf(name, " enable=%d", RetEnable());
- strcat(line, name);
- }
-
- if ( RetFixed() != 0 )
- {
- sprintf(name, " fixed=%d", RetFixed());
- strcat(line, name);
- }
-
- if ( RetClip() != 1 )
- {
- sprintf(name, " clip=%d", RetClip());
- strcat(line, name);
- }
-
- if ( RetLock() != 0 )
- {
- sprintf(name, " lock=%d", RetLock());
- strcat(line, name);
- }
-
- if ( RetProxyActivate() != 0 )
- {
- sprintf(name, " proxyActivate=%d", RetProxyActivate());
- strcat(line, name);
-
- sprintf(name, " proxyDistance=%.2f", RetProxyDistance()/g_unit);
- strcat(line, name);
- }
-
- if ( RetMagnifyDamage() != 1.0f )
- {
- sprintf(name, " magnifyDamage=%.2f", RetMagnifyDamage());
- strcat(line, name);
- }
-
- if ( RetGunGoalV() != 0.0f )
- {
- sprintf(name, " aimV=%.2f", RetGunGoalV());
- strcat(line, name);
- }
- if ( RetGunGoalH() != 0.0f )
- {
- sprintf(name, " aimH=%.2f", RetGunGoalH());
- strcat(line, name);
- }
-
- if ( RetParam() != 0.0f )
- {
- sprintf(name, " param=%.2f", RetParam());
- strcat(line, name);
- }
-
- if ( RetResetCap() != 0 )
- {
- sprintf(name, " resetCap=%d", RetResetCap());
- strcat(line, name);
-
- pos = RetResetPosition()/g_unit;
- sprintf(name, " resetPos=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
- strcat(line, name);
-
- pos = RetResetAngle()/(Math::PI/180.0f);
- sprintf(name, " resetAngle=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
- strcat(line, name);
-
- sprintf(name, " resetRun=%d", RetResetRun());
- strcat(line, name);
- }
-
- if ( m_bVirusMode != 0 )
- {
- sprintf(name, " virusMode=%d", m_bVirusMode);
- strcat(line, name);
- }
-
- if ( m_virusTime != 0.0f )
- {
- sprintf(name, " virusTime=%.2f", m_virusTime);
- strcat(line, name);
- }
-
- // Puts information in terminal (OBJECT_INFO).
- for ( i=0 ; i<m_infoTotal ; i++ )
- {
- info = RetInfo(i);
- if ( info.name[0] == 0 ) break;
-
- sprintf(name, " info%d=\"%s=%.2f\"", i+1, info.name, info.value);
- strcat(line, name);
- }
-
- // Sets the parameters of the command line.
- for ( i=0 ; i<OBJECTMAXCMDLINE ; i++ )
- {
- value = RetCmdLine(i);
- if ( value == NAN ) break;
-
- if ( i == 0 ) sprintf(name, " cmdline=%.2f", value);
- else sprintf(name, ";%.2f", value);
- strcat(line, name);
- }
-
- if ( m_motion != 0 )
- {
- m_motion->Write(line);
- }
-
- if ( m_brain != 0 )
- {
- m_brain->Write(line);
- }
-
- if ( m_physics != 0 )
- {
- m_physics->Write(line);
- }
-
- if ( m_auto != 0 )
- {
- m_auto->Write(line);
- }
-
- return true;
-}
-
-// Returns all parameters of the object.
-
-bool CObject::Read(char *line)
-{
- Math::Vector pos, dir;
- Info info;
- CameraType cType;
- char op[20];
- char text[100];
- char* p;
- float value;
- int i;
-
- cType = OpCamera(line, "camera");
- if ( cType != CAMERA_NULL )
- {
- SetCameraType(cType);
- }
-
- SetCameraLock(OpInt(line, "cameraLock", 0));
- SetEnergy(OpFloat(line, "energy", 0.0f));
- SetCapacity(OpFloat(line, "capacity", 1.0f));
- SetShield(OpFloat(line, "shield", 1.0f));
- SetRange(OpFloat(line, "range", 1.0f));
- SetSelectable(OpInt(line, "selectable", 1));
- SetEnable(OpInt(line, "enable", 1));
- SetFixed(OpInt(line, "fixed", 0));
- SetClip(OpInt(line, "clip", 1));
- SetLock(OpInt(line, "lock", 0));
- SetProxyActivate(OpInt(line, "proxyActivate", 0));
- SetProxyDistance(OpFloat(line, "proxyDistance", 15.0f)*g_unit);
- SetRange(OpFloat(line, "range", 30.0f));
- SetMagnifyDamage(OpFloat(line, "magnifyDamage", 1.0f));
- SetGunGoalV(OpFloat(line, "aimV", 0.0f));
- SetGunGoalH(OpFloat(line, "aimH", 0.0f));
- SetParam(OpFloat(line, "param", 0.0f));
- SetResetCap((ResetCap)OpInt(line, "resetCap", 0));
- SetResetPosition(OpDir(line, "resetPos")*g_unit);
- SetResetAngle(OpDir(line, "resetAngle")*(Math::PI/180.0f));
- SetResetRun(OpInt(line, "resetRun", 0));
- m_bBurn = OpInt(line, "burnMode", 0);
- m_bVirusMode = OpInt(line, "virusMode", 0);
- m_virusTime = OpFloat(line, "virusTime", 0.0f);
-
- // Puts information in terminal (OBJECT_INFO).
- for ( i=0 ; i<OBJECTMAXINFO ; i++ )
- {
- sprintf(op, "info%d", i+1);
- OpString(line, op, text);
- if ( text[0] == 0 ) break;
- p = strchr(text, '=');
- if ( p == 0 ) break;
- *p = 0;
- strcpy(info.name, text);
- sscanf(p+1, "%f", &info.value);
- SetInfo(i, info);
- }
-
- // Sets the parameters of the command line.
- p = SearchOp(line, "cmdline");
- for ( i=0 ; i<OBJECTMAXCMDLINE ; i++ )
- {
- value = GetFloat(p, i, NAN);
- if ( value == NAN ) break;
- SetCmdLine(i, value);
- }
-
- if ( m_motion != 0 )
- {
- m_motion->Read(line);
- }
-
- if ( m_brain != 0 )
- {
- m_brain->Read(line);
- }
-
- if ( m_physics != 0 )
- {
- m_physics->Read(line);
- }
-
- if ( m_auto != 0 )
- {
- m_auto->Read(line);
- }
-
- return true;
-}
-
-
-
-// Seeking the nth son of a father.
-
-int CObject::SearchDescendant(int parent, int n)
-{
- int i;
-
- for ( i=0 ; i<m_totalPart ; i++ )
- {
- if ( !m_objectPart[i].bUsed ) continue;
-
- if ( parent == m_objectPart[i].parentPart )
- {
- if ( n-- == 0 ) return i;
- }
- }
- return -1;
-}
-
-
-// Removes all spheres used for collisions.
-
-void CObject::FlushCrashShere()
-{
- m_crashSphereUsed = 0;
-}
-
-// Adds a new sphere.
-
-int CObject::CreateCrashSphere(Math::Vector pos, float radius, Sound sound,
- float hardness)
-{
- float zoom;
-
- if ( m_crashSphereUsed >= MAXCRASHSPHERE ) return -1;
-
- zoom = RetZoomX(0);
- m_crashSpherePos[m_crashSphereUsed] = pos;
- m_crashSphereRadius[m_crashSphereUsed] = radius*zoom;
- m_crashSphereHardness[m_crashSphereUsed] = hardness;
- m_crashSphereSound[m_crashSphereUsed] = sound;
- return m_crashSphereUsed++;
-}
-
-// Returns the number of spheres.
-
-int CObject::RetCrashSphereTotal()
-{
- return m_crashSphereUsed;
-}
-
-// Returns a sphere for collisions.
-// The position is absolute in the world.
-
-bool CObject::GetCrashSphere(int rank, Math::Vector &pos, float &radius)
-{
- if ( rank < 0 || rank >= m_crashSphereUsed )
- {
- pos = m_objectPart[0].position;
- radius = 0.0f;
- return false;
- }
-
- // Returns to the sphere collisions,
- // which ignores the inclination of the vehicle.
- // This is necessary to collisions with vehicles,
- // so as not to reflect SetInclinaison, for example.
- // The sphere must necessarily have a center (0, y, 0).
- if ( rank == 0 && m_crashSphereUsed == 1 &&
- m_crashSpherePos[0].x == 0.0f &&
- m_crashSpherePos[0].z == 0.0f )
- {
- pos = m_objectPart[0].position + m_crashSpherePos[0];
- radius = m_crashSphereRadius[0];
- return true;
- }
-
- if ( m_objectPart[0].bTranslate ||
- m_objectPart[0].bRotate )
- {
- UpdateTransformObject();
- }
- pos = Math::Transform(m_objectPart[0].matWorld, m_crashSpherePos[rank]);
- radius = m_crashSphereRadius[rank];
- return true;
-}
-
-// Returns the hardness of a sphere.
-
-Sound CObject::RetCrashSphereSound(int rank)
-{
- return m_crashSphereSound[rank];
-}
-
-// Returns the hardness of a sphere.
-
-float CObject::RetCrashSphereHardness(int rank)
-{
- return m_crashSphereHardness[rank];
-}
-
-// Deletes a sphere.
-
-void CObject::DeleteCrashSphere(int rank)
-{
- int i;
-
- if ( rank < 0 || rank >= m_crashSphereUsed ) return;
-
- for ( i=rank+1 ; i<MAXCRASHSPHERE ; i++ )
- {
- m_crashSpherePos[i-1] = m_crashSpherePos[i];
- m_crashSphereRadius[i-1] = m_crashSphereRadius[i];
- }
- m_crashSphereUsed --;
-}
-
-// Specifies the global sphere, relative to the object.
-
-void CObject::SetGlobalSphere(Math::Vector pos, float radius)
-{
- float zoom;
-
- zoom = RetZoomX(0);
- m_globalSpherePos = pos;
- m_globalSphereRadius = radius*zoom;
-}
-
-// Returns the global sphere, in the world.
-
-void CObject::GetGlobalSphere(Math::Vector &pos, float &radius)
-{
- pos = Math::Transform(m_objectPart[0].matWorld, m_globalSpherePos);
- radius = m_globalSphereRadius;
-}
-
-
-// Specifies the sphere of jostling, relative to the object.
-
-void CObject::SetJotlerSphere(Math::Vector pos, float radius)
-{
- m_jotlerSpherePos = pos;
- m_jotlerSphereRadius = radius;
-}
-
-// Specifies the sphere of jostling, in the world.
-
-void CObject::GetJotlerSphere(Math::Vector &pos, float &radius)
-{
- pos = Math::Transform(m_objectPart[0].matWorld, m_jotlerSpherePos);
- radius = m_jotlerSphereRadius;
-}
-
-
-// Specifies the radius of the shield.
-
-void CObject::SetShieldRadius(float radius)
-{
- m_shieldRadius = radius;
-}
-
-// Returns the radius of the shield.
-
-float CObject::RetShieldRadius()
-{
- return m_shieldRadius;
-}
-
-
-// Positioning an object on a certain height, above the ground.
-
-void CObject::SetFloorHeight(float height)
-{
- Math::Vector pos;
-
- pos = m_objectPart[0].position;
- m_terrain->MoveOnFloor(pos);
-
- if ( m_physics != 0 )
- {
- m_physics->SetLand(height == 0.0f);
- m_physics->SetMotor(height != 0.0f);
- }
-
- m_objectPart[0].position.y = pos.y+height+m_character.height;
- m_objectPart[0].bTranslate = true; // it will recalculate the matrices
-}
-
-// Adjust the inclination of an object laying on the ground.
-
-void CObject::FloorAdjust()
-{
- Math::Vector pos, n;
- Math::Point nn;
- float a;
-
- pos = RetPosition(0);
- if ( m_terrain->GetNormal(n, pos) )
- {
-#if 0
- SetAngleX(0, sinf(n.z));
- SetAngleZ(0, -sinf(n.x));
- SetAngleY(0, 0.0f);
-#else
- a = RetAngleY(0);
- nn = Math::RotatePoint(-a, Math::Point(n.z, n.x));
- SetAngleX(0, sinf(nn.x));
- SetAngleZ(0, -sinf(nn.y));
-#endif
- }
-}
-
-
-// Gives the linear vibration.
-
-void CObject::SetLinVibration(Math::Vector dir)
-{
- if ( m_linVibration.x != dir.x ||
- m_linVibration.y != dir.y ||
- m_linVibration.z != dir.z )
- {
- m_linVibration = dir;
- m_objectPart[0].bTranslate = true;
- }
-}
-
-Math::Vector CObject::RetLinVibration()
-{
- return m_linVibration;
-}
-
-// Gives the circular vibration.
-
-void CObject::SetCirVibration(Math::Vector dir)
-{
- if ( m_cirVibration.x != dir.x ||
- m_cirVibration.y != dir.y ||
- m_cirVibration.z != dir.z )
- {
- m_cirVibration = dir;
- m_objectPart[0].bRotate = true;
- }
-}
-
-Math::Vector CObject::RetCirVibration()
-{
- return m_cirVibration;
-}
-
-// Gives the inclination.
-
-void CObject::SetInclinaison(Math::Vector dir)
-{
- if ( m_inclinaison.x != dir.x ||
- m_inclinaison.y != dir.y ||
- m_inclinaison.z != dir.z )
- {
- m_inclinaison = dir;
- m_objectPart[0].bRotate = true;
- }
-}
-
-Math::Vector CObject::RetInclinaison()
-{
- return m_inclinaison;
-}
-
-
-// Gives the position of center of the object.
-
-void CObject::SetPosition(int part, const Math::Vector &pos)
-{
- Math::Vector shPos, n[20], norm;
- float height, radius;
- int rank, i, j;
-
- m_objectPart[part].position = pos;
- m_objectPart[part].bTranslate = true; // it will recalculate the matrices
-
- if ( part == 0 && !m_bFlat ) // main part?
- {
- rank = m_objectPart[0].object;
-
- shPos = pos;
- m_terrain->MoveOnFloor(shPos, true);
- m_engine->SetObjectShadowPos(rank, shPos);
-
- if ( m_physics != 0 && m_physics->RetType() == TYPE_FLYING )
- {
- height = pos.y-shPos.y;
- }
- else
- {
- height = 0.0f;
- }
- m_engine->SetObjectShadowHeight(rank, height);
-
- // Calculating the normal to the ground in nine strategic locations,
- // then perform a weighted average (the dots in the center are more important).
- radius = m_engine->RetObjectShadowRadius(rank);
- i = 0;
-
- m_terrain->GetNormal(norm, pos);
- n[i++] = norm;
- n[i++] = norm;
- n[i++] = norm;
-
- shPos = pos;
- shPos.x += radius*0.6f;
- shPos.z += radius*0.6f;
- m_terrain->GetNormal(norm, shPos);
- n[i++] = norm;
- n[i++] = norm;
-
- shPos = pos;
- shPos.x -= radius*0.6f;
- shPos.z += radius*0.6f;
- m_terrain->GetNormal(norm, shPos);
- n[i++] = norm;
- n[i++] = norm;
-
- shPos = pos;
- shPos.x += radius*0.6f;
- shPos.z -= radius*0.6f;
- m_terrain->GetNormal(norm, shPos);
- n[i++] = norm;
- n[i++] = norm;
-
- shPos = pos;
- shPos.x -= radius*0.6f;
- shPos.z -= radius*0.6f;
- m_terrain->GetNormal(norm, shPos);
- n[i++] = norm;
- n[i++] = norm;
-
- shPos = pos;
- shPos.x += radius;
- shPos.z += radius;
- m_terrain->GetNormal(norm, shPos);
- n[i++] = norm;
-
- shPos = pos;
- shPos.x -= radius;
- shPos.z += radius;
- m_terrain->GetNormal(norm, shPos);
- n[i++] = norm;
-
- shPos = pos;
- shPos.x += radius;
- shPos.z -= radius;
- m_terrain->GetNormal(norm, shPos);
- n[i++] = norm;
-
- shPos = pos;
- shPos.x -= radius;
- shPos.z -= radius;
- m_terrain->GetNormal(norm, shPos);
- n[i++] = norm;
-
- norm.LoadZero();
- for ( j=0 ; j<i ; j++ )
- {
- norm += n[j];
- }
- norm /= (float)i; // average vector
-
- m_engine->SetObjectShadowNormal(rank, norm);
-
- if ( m_shadowLight != -1 )
- {
- shPos = pos;
- shPos.y += m_shadowHeight;
- m_light->SetLightPos(m_shadowLight, shPos);
- }
-
- if ( m_effectLight != -1 )
- {
- shPos = pos;
- shPos.y += m_effectHeight;
- m_light->SetLightPos(m_effectLight, shPos);
- }
-
- if ( m_bShowLimit )
- {
- m_main->AdjustShowLimit(0, pos);
- }
- }
-}
-
-Math::Vector CObject::RetPosition(int part)
-{
- return m_objectPart[part].position;
-}
-
-// Gives the rotation around three axis.
-
-void CObject::SetAngle(int part, const Math::Vector &angle)
-{
- m_objectPart[part].angle = angle;
- m_objectPart[part].bRotate = true; // it will recalculate the matrices
-
- if ( part == 0 && !m_bFlat ) // main part?
- {
- m_engine->SetObjectShadowAngle(m_objectPart[0].object, m_objectPart[0].angle.y);
- }
-}
-
-Math::Vector CObject::RetAngle(int part)
-{
- return m_objectPart[part].angle;
-}
-
-// Gives the rotation about the axis Y.
-
-void CObject::SetAngleY(int part, float angle)
-{
- m_objectPart[part].angle.y = angle;
- m_objectPart[part].bRotate = true; // it will recalculate the matrices
-
- if ( part == 0 && !m_bFlat ) // main part?
- {
- m_engine->SetObjectShadowAngle(m_objectPart[0].object, m_objectPart[0].angle.y);
- }
-}
-
-// Gives the rotation about the axis X.
-
-void CObject::SetAngleX(int part, float angle)
-{
- m_objectPart[part].angle.x = angle;
- m_objectPart[part].bRotate = true; // it will recalculate the matrices
-}
-
-// Gives the rotation about the axis Z.
-
-void CObject::SetAngleZ(int part, float angle)
-{
- m_objectPart[part].angle.z = angle;
- m_objectPart[part].bRotate = true; //it will recalculate the matrices
-}
-
-float CObject::RetAngleY(int part)
-{
- return m_objectPart[part].angle.y;
-}
-
-float CObject::RetAngleX(int part)
-{
- return m_objectPart[part].angle.x;
-}
-
-float CObject::RetAngleZ(int part)
-{
- return m_objectPart[part].angle.z;
-}
-
-
-// Gives the global zoom.
-
-void CObject::SetZoom(int part, float zoom)
-{
- m_objectPart[part].bTranslate = true; // it will recalculate the matrices
- m_objectPart[part].zoom.x = zoom;
- m_objectPart[part].zoom.y = zoom;
- m_objectPart[part].zoom.z = zoom;
-
- m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
- m_objectPart[part].zoom.y != 1.0f ||
- m_objectPart[part].zoom.z != 1.0f );
-}
-
-void CObject::SetZoom(int part, Math::Vector zoom)
-{
- m_objectPart[part].bTranslate = true; // it will recalculate the matrices
- m_objectPart[part].zoom = zoom;
-
- m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
- m_objectPart[part].zoom.y != 1.0f ||
- m_objectPart[part].zoom.z != 1.0f );
-}
-
-Math::Vector CObject::RetZoom(int part)
-{
- return m_objectPart[part].zoom;
-}
-
-void CObject::SetZoomX(int part, float zoom)
-{
- m_objectPart[part].bTranslate = true; // it will recalculate the matrices
- m_objectPart[part].zoom.x = zoom;
-
- m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
- m_objectPart[part].zoom.y != 1.0f ||
- m_objectPart[part].zoom.z != 1.0f );
-}
-
-void CObject::SetZoomY(int part, float zoom)
-{
- m_objectPart[part].bTranslate = true; // it will recalculate the matrices
- m_objectPart[part].zoom.y = zoom;
-
- m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
- m_objectPart[part].zoom.y != 1.0f ||
- m_objectPart[part].zoom.z != 1.0f );
-}
-
-void CObject::SetZoomZ(int part, float zoom)
-{
- m_objectPart[part].bTranslate = true; // it will recalculate the matrices
- m_objectPart[part].zoom.z = zoom;
-
- m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
- m_objectPart[part].zoom.y != 1.0f ||
- m_objectPart[part].zoom.z != 1.0f );
-}
-
-float CObject::RetZoomX(int part)
-{
- return m_objectPart[part].zoom.x;
-}
-
-float CObject::RetZoomY(int part)
-{
- return m_objectPart[part].zoom.y;
-}
-
-float CObject::RetZoomZ(int part)
-{
- return m_objectPart[part].zoom.z;
-}
-
-
-// Returns the water level.
-
-float CObject::RetWaterLevel()
-{
- return m_water->RetLevel();
-}
-
-
-void CObject::SetTrainer(bool bEnable)
-{
- m_bTrainer = bEnable;
-
- if ( m_bTrainer ) // training?
- {
- m_cameraType = CAMERA_FIX;
- }
-}
-
-bool CObject::RetTrainer()
-{
- return m_bTrainer;
-}
-
-void CObject::SetToy(bool bEnable)
-{
- m_bToy = bEnable;
-}
-
-bool CObject::RetToy()
-{
- return m_bToy;
-}
-
-void CObject::SetManual(bool bManual)
-{
- m_bManual = bManual;
-}
-
-bool CObject::RetManual()
-{
- return m_bManual;
-}
-
-void CObject::SetResetCap(ResetCap cap)
-{
- m_resetCap = cap;
-}
-
-ResetCap CObject::RetResetCap()
-{
- return m_resetCap;
-}
-
-void CObject::SetResetBusy(bool bBusy)
-{
- m_bResetBusy = bBusy;
-}
-
-bool CObject::RetResetBusy()
-{
- return m_bResetBusy;
-}
-
-void CObject::SetResetPosition(const Math::Vector &pos)
-{
- m_resetPosition = pos;
-}
-
-Math::Vector CObject::RetResetPosition()
-{
- return m_resetPosition;
-}
-
-void CObject::SetResetAngle(const Math::Vector &angle)
-{
- m_resetAngle = angle;
-}
-
-Math::Vector CObject::RetResetAngle()
-{
- return m_resetAngle;
-}
-
-int CObject::RetResetRun()
-{
- return m_resetRun;
-}
-
-void CObject::SetResetRun(int run)
-{
- m_resetRun = run;
-}
-
-
-// Management of the particle master.
-
-void CObject::SetMasterParticule(int part, int parti)
-{
- m_objectPart[part].masterParti = parti;
-}
-
-int CObject::RetMasterParticule(int part)
-{
- return m_objectPart[part].masterParti;
-}
-
-
-// Management of the stack transport.
-
-void CObject::SetPower(CObject* power)
-{
- m_power = power;
-}
-
-CObject* CObject::RetPower()
-{
- return m_power;
-}
-
-// Management of the object transport.
-
-void CObject::SetFret(CObject* fret)
-{
- m_fret = fret;
-}
-
-CObject* CObject::RetFret()
-{
- return m_fret;
-}
-
-// Management of the object "truck" that transports it.
-
-void CObject::SetTruck(CObject* truck)
-{
- m_truck = truck;
-
- // Invisible shadow if the object is transported.
- m_engine->SetObjectShadowHide(m_objectPart[0].object, (m_truck != 0));
-}
-
-CObject* CObject::RetTruck()
-{
- return m_truck;
-}
-
-// Management of the conveying portion.
-
-void CObject::SetTruckPart(int part)
-{
- m_truckLink = part;
-}
-
-int CObject::RetTruckPart()
-{
- return m_truckLink;
-}
-
-
-// Management of user information.
-
-void CObject::InfoFlush()
-{
- m_infoTotal = 0;
- m_bInfoUpdate = true;
-}
-
-void CObject::DeleteInfo(int rank)
-{
- int i;
-
- if ( rank < 0 || rank >= m_infoTotal ) return;
-
- for ( i=rank ; i<m_infoTotal-1 ; i++ )
- {
- m_info[i] = m_info[i+1];
- }
- m_infoTotal --;
- m_bInfoUpdate = true;
-}
-
-void CObject::SetInfo(int rank, Info info)
-{
- if ( rank < 0 || rank >= OBJECTMAXINFO ) return;
- m_info[rank] = info;
-
- if ( rank+1 > m_infoTotal ) m_infoTotal = rank+1;
- m_bInfoUpdate = true;
-}
-
-Info CObject::RetInfo(int rank)
-{
- if ( rank < 0 || rank >= OBJECTMAXINFO ) rank = 0;
- return m_info[rank];
-}
-
-int CObject::RetInfoTotal()
-{
- return m_infoTotal;
-}
-
-void CObject::SetInfoReturn(float value)
-{
- m_infoReturn = value;
-}
-
-float CObject::RetInfoReturn()
-{
- return m_infoReturn;
-}
-
-void CObject::SetInfoUpdate(bool bUpdate)
-{
- m_bInfoUpdate = bUpdate;
-}
-
-bool CObject::RetInfoUpdate()
-{
- return m_bInfoUpdate;
-}
-
-
-bool CObject::SetCmdLine(int rank, float value)
-{
- if ( rank < 0 || rank >= OBJECTMAXCMDLINE ) return false;
- m_cmdLine[rank] = value;
- return true;
-}
-
-float CObject::RetCmdLine(int rank)
-{
- if ( rank < 0 || rank >= OBJECTMAXCMDLINE ) return 0.0f;
- return m_cmdLine[rank];
-}
-
-
-// Returns matrices of an object portion.
-
-Math::Matrix* CObject::RetRotateMatrix(int part)
-{
- return &m_objectPart[part].matRotate;
-}
-
-Math::Matrix* CObject::RetTranslateMatrix(int part)
-{
- return &m_objectPart[part].matTranslate;
-}
-
-Math::Matrix* CObject::RetTransformMatrix(int part)
-{
- return &m_objectPart[part].matTransform;
-}
-
-Math::Matrix* CObject::RetWorldMatrix(int part)
-{
- if ( m_objectPart[0].bTranslate ||
- m_objectPart[0].bRotate )
- {
- UpdateTransformObject();
- }
-
- return &m_objectPart[part].matWorld;
-}
-
-
-// Indicates whether the object should be drawn below the interface.
-
-void CObject::SetDrawWorld(bool bDraw)
-{
- int i;
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- if ( m_objectPart[i].bUsed )
- {
- m_engine->SetDrawWorld(m_objectPart[i].object, bDraw);
- }
- }
-}
-
-// Indicates whether the object should be drawn over the interface.
-
-void CObject::SetDrawFront(bool bDraw)
-{
- int i;
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- if ( m_objectPart[i].bUsed )
- {
- m_engine->SetDrawFront(m_objectPart[i].object, bDraw);
- }
- }
-}
-
-
-// Creates a vehicle traveling any pose on the floor.
-
-bool CObject::CreateVehicle(Math::Vector pos, float angle, ObjectType type,
- float power, bool bTrainer, bool bToy)
-{
- m_type = type;
-
- if ( type == OBJECT_TOTO )
- {
- m_motion = new CMotionToto(m_iMan, this);
- m_motion->Create(pos, angle, type, 1.0f);
- return true;
- }
-
- SetTrainer(bTrainer);
- SetToy(bToy);
-
- m_physics = new CPhysics(m_iMan, this);
- m_brain = new CBrain(m_iMan, this);
-
- m_physics->SetBrain(m_brain);
- m_brain->SetPhysics(m_physics);
-
-#if 0
- if ( type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ) // fireball cannon?
- {
- m_showLimitRadius = 160.0f;
- }
- if ( type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ) // orgaball cannon?
- {
- m_showLimitRadius = 160.0f;
- }
- if ( type == OBJECT_MOBILErc ) // phazer cannon?
- {
- m_showLimitRadius = 160.0f;
- }
- if ( type == OBJECT_MOBILErs ) // robot shield?
- {
- m_showLimitRadius = 50.0f;
- }
-#endif
- if ( type == OBJECT_MOBILErt ) // robot thumper?
- {
- m_showLimitRadius = 400.0f;
- }
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH )
- {
- m_motion = new CMotionHuman(m_iMan, this);
- }
- else
- {
- m_motion = new CMotionVehicle(m_iMan, this);
- }
- if ( m_motion == 0 ) return false;
-
- m_physics->SetMotion(m_motion);
- m_brain->SetMotion(m_motion);
- m_motion->SetPhysics(m_physics);
- m_motion->SetBrain(m_brain);
- if ( !m_motion->Create(pos, angle, type, power) )
- {
- if ( m_physics != 0 )
- {
- m_physics->DeleteObject();
- delete m_physics;
- m_physics = 0;
- }
- if ( m_brain != 0 )
- {
- m_brain->DeleteObject();
- delete m_brain;
- m_brain = 0;
- }
- if ( m_motion != 0 )
- {
- m_motion->DeleteObject();
- delete m_motion;
- m_motion = 0;
- }
- return false;
- }
-
- return true;
-}
-
-// Creates an insect lands on any ground.
-
-bool CObject::CreateInsect(Math::Vector pos, float angle, ObjectType type)
-{
- m_type = type;
-
- m_physics = new CPhysics(m_iMan, this);
- m_brain = new CBrain(m_iMan, this);
-
- m_physics->SetBrain(m_brain);
- m_brain->SetPhysics(m_physics);
-
- if ( type == OBJECT_MOTHER )
- {
- m_motion = new CMotionMother(m_iMan, this);
- }
- if ( type == OBJECT_ANT )
- {
- m_motion = new CMotionAnt(m_iMan, this);
- }
- if ( type == OBJECT_SPIDER )
- {
- m_motion = new CMotionSpider(m_iMan, this);
- }
- if ( type == OBJECT_BEE )
- {
- m_motion = new CMotionBee(m_iMan, this);
- }
- if ( type == OBJECT_WORM )
- {
- m_motion = new CMotionWorm(m_iMan, this);
- }
- if ( m_motion == 0 ) return false;
-
- m_physics->SetMotion(m_motion);
- m_brain->SetMotion(m_motion);
- m_motion->SetPhysics(m_physics);
- m_motion->SetBrain(m_brain);
- if ( !m_motion->Create(pos, angle, type, 0.0f) )
- {
- if ( m_physics != 0 )
- {
- m_physics->DeleteObject();
- delete m_physics;
- m_physics = 0;
- }
- if ( m_brain != 0 )
- {
- m_brain->DeleteObject();
- delete m_brain;
- m_brain = 0;
- }
- if ( m_motion != 0 )
- {
- m_motion->DeleteObject();
- delete m_motion;
- m_motion = 0;
- }
- return false;
- }
-
- return true;
-}
-
-// Creates shade under a vehicle as a negative light.
-
-bool CObject::CreateShadowLight(float height, D3DCOLORVALUE color)
-{
- D3DLIGHT7 light;
- Math::Vector pos;
-
- if ( !m_engine->RetLightMode() ) return true;
-
- pos = RetPosition(0);
- m_shadowHeight = height;
-
- ZeroMemory( &light, sizeof(light) );
- light.dltType = D3DLIGHT_SPOT;
- light.dcvDiffuse.r = color.r;
- light.dcvDiffuse.g = color.g;
- light.dcvDiffuse.b = color.b;
- light.dvPosition.x = pos.x;
- light.dvPosition.y = pos.y+height;
- light.dvPosition.z = pos.z;
- light.dvDirection.x = 0.0f;
- light.dvDirection.y = -1.0f; // against the bottom
- light.dvDirection.z = 0.0f;
- light.dvRange = D3DLIGHT_RANGE_MAX;
- light.dvFalloff = 1.0f;
- light.dvAttenuation0 = 1.0f;
- light.dvAttenuation1 = 0.0f;
- light.dvAttenuation2 = 0.0f;
- light.dvTheta = 0.0f;
- light.dvPhi = Math::PI/4.0f;
-
- m_shadowLight = m_light->CreateLight();
- if ( m_shadowLight == -1 ) return false;
-
- m_light->SetLight(m_shadowLight, light);
-
- // Only illuminates the objects on the ground.
- m_light->SetLightIncluType(m_shadowLight, TYPETERRAIN);
-
- return true;
-}
-
-// Returns the number of negative light shade.
-
-int CObject::RetShadowLight()
-{
- return m_shadowLight;
-}
-
-// Creates light for the effects of a vehicle.
-
-bool CObject::CreateEffectLight(float height, D3DCOLORVALUE color)
-{
- D3DLIGHT7 light;
-
- if ( !m_engine->RetLightMode() ) return true;
-
- m_effectHeight = height;
-
- ZeroMemory( &light, sizeof(light) );
- light.dltType = D3DLIGHT_SPOT;
- light.dcvDiffuse.r = color.r;
- light.dcvDiffuse.g = color.g;
- light.dcvDiffuse.b = color.b;
- light.dvPosition.x = 0.0f;
- light.dvPosition.y = 0.0f+height;
- light.dvPosition.z = 0.0f;
- light.dvDirection.x = 0.0f;
- light.dvDirection.y = -1.0f; // against the bottom
- light.dvDirection.z = 0.0f;
- light.dvRange = D3DLIGHT_RANGE_MAX;
- light.dvFalloff = 1.0f;
- light.dvAttenuation0 = 1.0f;
- light.dvAttenuation1 = 0.0f;
- light.dvAttenuation2 = 0.0f;
- light.dvTheta = 0.0f;
- light.dvPhi = Math::PI/4.0f;
-
- m_effectLight = m_light->CreateLight();
- if ( m_effectLight == -1 ) return false;
-
- m_light->SetLight(m_effectLight, light);
- m_light->SetLightIntensity(m_effectLight, 0.0f);
-
- return true;
-}
-
-// Returns the number of light effects.
-
-int CObject::RetEffectLight()
-{
- return m_effectLight;
-}
-
-// Creates the circular shadow underneath a vehicle.
-
-bool CObject::CreateShadowCircle(float radius, float intensity,
- D3DShadowType type)
-{
- float zoom;
-
- if ( intensity == 0.0f ) return true;
-
- zoom = RetZoomX(0);
-
- m_engine->ShadowCreate(m_objectPart[0].object);
-
- m_engine->SetObjectShadowRadius(m_objectPart[0].object, radius*zoom);
- m_engine->SetObjectShadowIntensity(m_objectPart[0].object, intensity);
- m_engine->SetObjectShadowHeight(m_objectPart[0].object, 0.0f);
- m_engine->SetObjectShadowAngle(m_objectPart[0].object, m_objectPart[0].angle.y);
- m_engine->SetObjectShadowType(m_objectPart[0].object, type);
-
- return true;
-}
-
-// Creates a building laying on the ground.
-
-bool CObject::CreateBuilding(Math::Vector pos, float angle, float height,
- ObjectType type, float power)
-{
- CModFile* pModFile;
- Math::Point p;
- int rank, i;
-
- if ( m_engine->RetRestCreate() < 20 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
- SetObjectRank(0, rank);
-
- if ( m_type == OBJECT_PORTICO )
- {
- pModFile->ReadModel("objects\\portico1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\portico2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 67.0f, 0.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\portico3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(0.0f, 0.0f, -33.0f));
- SetAngleY(2, 45.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(3, rank);
- SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\portico4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(3, Math::Vector(50.0f, 0.0f, 0.0f));
- SetAngleY(3, -60.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(4, rank);
- SetObjectParent(4, 3);
- pModFile->ReadModel("objects\\portico5.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(4, Math::Vector(35.0f, 0.0f, 0.0f));
- SetAngleY(4, -55.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(5, rank);
- SetObjectParent(5, 1);
- pModFile->ReadModel("objects\\portico3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(5, Math::Vector(0.0f, 0.0f, 33.0f));
- SetAngleY(5, -45.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(6, rank);
- SetObjectParent(6, 5);
- pModFile->ReadModel("objects\\portico4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(6, Math::Vector(50.0f, 0.0f, 0.0f));
- SetAngleY(6, 60.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(7, rank);
- SetObjectParent(7, 6);
- pModFile->ReadModel("objects\\portico5.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(7, Math::Vector(35.0f, 0.0f, 0.0f));
- SetAngleY(7, 55.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(8, rank);
- SetObjectParent(8, 0);
- pModFile->ReadModel("objects\\portico6.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(8, Math::Vector(-35.0f, 50.0f, -35.0f));
- SetAngleY(8, -Math::PI/2.0f);
- SetZoom(8, 2.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(9, rank);
- SetObjectParent(9, 8);
- pModFile->ReadModel("objects\\portico7.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(9, Math::Vector(0.0f, 4.5f, 1.9f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(10, rank);
- SetObjectParent(10, 0);
- pModFile->ReadModel("objects\\portico6.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(10, Math::Vector(-35.0f, 50.0f, 35.0f));
- SetAngleY(10, -Math::PI/2.0f);
- SetZoom(10, 2.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(11, rank);
- SetObjectParent(11, 10);
- pModFile->ReadModel("objects\\portico7.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(11, Math::Vector(0.0f, 4.5f, 1.9f));
-
- CreateCrashSphere(Math::Vector( 0.0f, 28.0f, 0.0f), 45.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 27.0f, 10.0f, -42.0f), 15.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 10.0f, -42.0f), 15.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-27.0f, 10.0f, -42.0f), 15.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 27.0f, 10.0f, 42.0f), 15.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 10.0f, 42.0f), 15.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-27.0f, 10.0f, 42.0f), 15.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-32.0f, 45.0f, -32.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-32.0f, 45.0f, 32.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 32.0f, 45.0f, -32.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 32.0f, 45.0f, 32.0f), 10.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 35.0f, 0.0f), 50.0f);
-
- CreateShadowCircle(50.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_BASE )
- {
- pModFile->ReadModel("objects\\base1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- for ( i=0 ; i<8 ; i++ )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1+i, rank);
- SetObjectParent(1+i, 0);
- pModFile->ReadModel("objects\\base2.mod");
- pModFile->CreateEngineObject(rank);
- p = Math::RotatePoint(-Math::PI/4.0f*i, 27.8f);
- SetPosition(1+i, Math::Vector(p.x, 30.0f, p.y));
- SetAngleY(1+i, Math::PI/4.0f*i);
- SetAngleZ(1+i, Math::PI/2.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(10+i, rank);
- SetObjectParent(10+i, 1+i);
- pModFile->ReadModel("objects\\base4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(10+i, Math::Vector(23.5f, 0.0f, 7.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(18+i, rank);
- SetObjectParent(18+i, 1+i);
- pModFile->ReadModel("objects\\base4.mod");
- pModFile->Mirror();
- pModFile->CreateEngineObject(rank);
- SetPosition(18+i, Math::Vector(23.5f, 0.0f, -7.0f));
- }
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(9, rank);
- SetObjectParent(9, 0);
- pModFile->ReadModel("objects\\base3.mod"); // central pillar
- pModFile->CreateEngineObject(rank);
-
- CreateCrashSphere(Math::Vector( 0.0f, 33.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 39.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 45.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 51.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 57.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 63.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 69.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 82.0f, 0.0f), 8.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 18.0f, 94.0f, 0.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-18.0f, 94.0f, 0.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 94.0f, 18.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 94.0f, -18.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 13.0f, 94.0f, 13.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-13.0f, 94.0f, 13.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 13.0f, 94.0f, -13.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-13.0f, 94.0f, -13.0f), 10.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f,104.0f, 0.0f), 14.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 45.0f, 0.0f), 10.0f);
-
- CreateShadowCircle(60.0f, 1.0f);
- m_showLimitRadius = 200.0f;
-
- m_terrain->AddBuildingLevel(pos, 28.6f, 73.4f, 30.0f, 0.4f);
- }
-
- if ( m_type == OBJECT_DERRICK )
- {
- pModFile->ReadModel("objects\\derrick1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\derrick2.mod");
- pModFile->CreateEngineObject(rank);
-
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 17.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 26.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(7.0f, 17.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 10.0f);
-
- CreateShadowCircle(10.0f, 0.4f);
- }
-
- if ( m_type == OBJECT_RESEARCH )
- {
- pModFile->ReadModel("objects\\search1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\search2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 13.0f, 0.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\search3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(0.0f, 4.0f, 0.0f));
- SetAngleZ(2, 35.0f*Math::PI/180.0f);
-
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 6.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 14.0f, 0.0f), 7.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 8.0f, 0.0f), 12.0f);
-
- m_character.posPower = Math::Vector(7.5f, 3.0f, 0.0f);
-
- CreateShadowCircle(12.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_RADAR )
- {
- pModFile->ReadModel("objects\\radar1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\radar2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 5.0f, 0.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\radar3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(0.0f, 11.0f, 0.0f));
- SetAngleY(2, -Math::PI/2.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(3, rank);
- SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\radar4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(3, Math::Vector(0.0f, 4.5f, 1.9f));
-
- CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 11.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 7.0f, 0.0f), 7.0f);
-
- CreateShadowCircle(8.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_INFO )
- {
- pModFile->ReadModel("objects\\info1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\info2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 5.0f, 0.0f));
-
- for ( i=0 ; i<3 ; i++ )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2+i*2, rank);
- SetObjectParent(2+i*2, 1);
- pModFile->ReadModel("objects\\info3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(2+i*2, Math::Vector(0.0f, 4.5f, 0.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(3+i*2, rank);
- SetObjectParent(3+i*2, 2+i*2);
- pModFile->ReadModel("objects\\radar4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(3+i*2, Math::Vector(0.0f, 0.0f, -4.0f));
-
- SetAngleY(2+i*2, 2.0f*Math::PI/3.0f*i);
- }
-
- CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 11.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 6.0f);
-
- CreateShadowCircle(8.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_ENERGY )
- {
- pModFile->ReadModel("objects\\energy.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- CreateCrashSphere(Math::Vector(-2.0f, 13.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-7.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(-7.0f, 5.0f, 0.0f), 5.0f);
-
- m_character.posPower = Math::Vector(0.0f, 3.0f, 0.0f);
- m_energy = power; // initializes the energy level
-
- CreateShadowCircle(6.0f, 0.5f);
- }
-
- if ( m_type == OBJECT_LABO )
- {
- pModFile->ReadModel("objects\\labo1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\labo2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(-9.0f, 3.0f, 0.0f));
- SetAngleZ(1, Math::PI/2.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\labo3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(9.0f, -1.0f, 0.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(3, rank);
- SetObjectParent(3, 2);
- pModFile->ReadModel("objects\\labo4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(3, Math::Vector(0.0f, 0.0f, 0.0f));
- SetAngleZ(3, 80.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(4, rank);
- SetObjectParent(4, 2);
- pModFile->ReadModel("objects\\labo4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(4, Math::Vector(0.0f, 0.0f, 0.0f));
- SetAngleZ(4, 80.0f*Math::PI/180.0f);
- SetAngleY(4, Math::PI*2.0f/3.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(5, rank);
- SetObjectParent(5, 2);
- pModFile->ReadModel("objects\\labo4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(5, Math::Vector(0.0f, 0.0f, 0.0f));
- SetAngleZ(5, 80.0f*Math::PI/180.0f);
- SetAngleY(5, -Math::PI*2.0f/3.0f);
-
- CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 11.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 10.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-12.0f, 3.0f, 3.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-12.0f, 3.0f, -3.0f), 4.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(-10.0f, 5.0f, 0.0f), 7.0f);
-
- m_character.posPower = Math::Vector(0.0f, 3.0f, 0.0f);
-
- CreateShadowCircle(7.0f, 0.5f);
- }
-
- if ( m_type == OBJECT_FACTORY )
- {
- pModFile->ReadModel("objects\\factory1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- for ( i=0 ; i<9 ; i++ )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1+i, rank);
- SetObjectParent(1+i, 0);
- pModFile->ReadModel("objects\\factory2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1+i, Math::Vector(10.0f, 2.0f*i, 10.0f));
- SetAngleZ(1+i, Math::PI/2.0f);
- SetZoomZ(1+i, 0.30f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(10+i, rank);
- SetObjectParent(10+i, 0);
- pModFile->ReadModel("objects\\factory2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(10+i, Math::Vector(10.0f, 2.0f*i, -10.0f));
- SetAngleZ(10+i, -Math::PI/2.0f);
- SetAngleY(10+i, Math::PI);
- SetZoomZ(10+i, 0.30f);
- }
-
- for ( i=0 ; i<2 ; i++ )
- {
- float s = (float)(i*2-1);
- CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -3.0f, 2.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.0f, 2.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 2.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 9.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -3.0f, 9.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.0f, 9.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 9.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 16.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -3.0f, 16.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.0f, 16.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 16.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 16.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -3.0f, 16.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.0f, 16.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 16.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 9.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
- }
- CreateCrashSphere(Math::Vector(-10.0f, 21.0f, -4.0f), 3.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 18.0f);
-
- CreateShadowCircle(24.0f, 0.3f);
- }
-
- if ( m_type == OBJECT_REPAIR )
- {
- pModFile->ReadModel("objects\\repair1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\repair2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(-11.0f, 13.5f, 0.0f));
- SetAngleZ(1, Math::PI/2.0f);
-
- m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
-
- CreateCrashSphere(Math::Vector(-11.0f, 0.0f, 4.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 0.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 0.0f, -4.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 10.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(-11.0f, 13.0f, 0.0f), 15.0f);
- }
-
- if ( m_type == OBJECT_DESTROYER )
- {
- pModFile->ReadModel("objects\\destroy1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\destroy2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 0.0f, 0.0f));
-
- m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
-
- CreateCrashSphere(Math::Vector(-3.5f, 0.0f, -13.5f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.5f, 0.0f, -13.5f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-3.5f, 0.0f, 13.5f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.5f, 0.0f, 13.5f), 4.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(19.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_STATION )
- {
- pModFile->ReadModel("objects\\station.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
-
- CreateCrashSphere(Math::Vector(-15.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-15.0f, 6.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(-15.0f, 5.0f, 0.0f), 6.0f);
-
- m_energy = power; // initialise le niveau d'�nergie
- }
-
- if ( m_type == OBJECT_CONVERT )
- {
- pModFile->ReadModel("objects\\convert1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\convert2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 14.0f, 0.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\convert3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(0.0f, 11.5f, 0.0f));
- SetAngleX(2, -Math::PI*0.35f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(3, rank);
- SetObjectParent(3, 0);
- pModFile->ReadModel("objects\\convert3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(3, Math::Vector(0.0f, 11.5f, 0.0f));
- SetAngleY(3, Math::PI);
- SetAngleX(3, -Math::PI*0.35f);
-
- m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
-
- CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 4.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 2.0f, -4.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 9.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 14.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(-3.0f, 8.0f, 0.0f), 14.0f);
- }
-
- if ( m_type == OBJECT_TOWER )
- {
- pModFile->ReadModel("objects\\tower.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\roller2c.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 20.0f, 0.0f));
- SetAngleZ(1, Math::PI/2.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\roller3c.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(4.5f, 0.0f, 0.0f));
- SetAngleZ(2, 0.0f);
-
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 6.5f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 8.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 15.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 24.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 7.0f);
-
- m_character.posPower = Math::Vector(5.0f, 3.0f, 0.0f);
-
- CreateShadowCircle(6.0f, 1.0f);
- m_showLimitRadius = BLITZPARA;
- }
-
- if ( m_type == OBJECT_NUCLEAR )
- {
- pModFile->ReadModel("objects\\nuclear1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\nuclear2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(20.0f, 10.0f, 0.0f));
- SetAngleZ(1, 135.0f*Math::PI/180.0f);
-
- CreateCrashSphere(Math::Vector( 0.0f, 0.0f, 0.0f), 19.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 24.0f, 0.0f), 15.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(22.0f, 1.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 17.0f, 0.0f), 26.0f);
-
- m_character.posPower = Math::Vector(22.0f, 3.0f, 0.0f);
-
- CreateShadowCircle(21.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_PARA )
- {
- pModFile->ReadModel("objects\\para.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- m_terrain->AddBuildingLevel(pos, 16.0f, 18.0f, 1.0f, 0.5f);
-
- CreateCrashSphere(Math::Vector( 13.0f, 3.0f, 13.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 11.0f, 15.0f, 11.0f), 2.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-13.0f, 3.0f, 13.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 15.0f, -11.0f), 2.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 13.0f, 3.0f, -13.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 11.0f, 15.0f, -11.0f), 2.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-13.0f, 3.0f, -13.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 15.0f, -11.0f), 2.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 26.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 54.0f, 0.0f), 14.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 20.0f);
-
- CreateShadowCircle(21.0f, 1.0f);
- m_showLimitRadius = BLITZPARA;
- }
-
- if ( m_type == OBJECT_SAFE )
- {
- pModFile->ReadModel("objects\\safe1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\safe2.mod");
- pModFile->CreateEngineObject(rank);
- SetZoom(1, 1.05f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\safe3.mod");
- pModFile->CreateEngineObject(rank);
- SetZoom(2, 1.05f);
-
- m_terrain->AddBuildingLevel(pos, 18.0f, 20.0f, 1.0f, 0.5f);
-
- CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 13.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 13.0f);
-
- CreateShadowCircle(23.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_HUSTON )
- {
- pModFile->ReadModel("objects\\huston1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\huston2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 39.0f, 30.0f));
- SetAngleY(1, -Math::PI/2.0f);
- SetZoom(1, 3.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\huston3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(0.0f, 4.5f, 1.9f));
-
- CreateCrashSphere(Math::Vector( 15.0f, 6.0f, -53.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-15.0f, 6.0f, -53.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 15.0f, 6.0f, -26.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-15.0f, 6.0f, -26.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 15.0f, 6.0f, 0.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-15.0f, 6.0f, 0.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 15.0f, 6.0f, 26.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-15.0f, 6.0f, 26.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 15.0f, 6.0f, 53.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-15.0f, 6.0f, 53.0f), 16.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 27.0f, 30.0f), 12.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 45.0f, 30.0f), 14.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 26.0f, 4.0f, -61.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-26.0f, 4.0f, -61.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 26.0f, 4.0f, 61.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-26.0f, 4.0f, 61.0f), 5.0f, SOUND_BOUMm, 0.45f);
- }
-
- if ( m_type == OBJECT_TARGET1 )
- {
- pModFile->ReadModel("objects\\target1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 1.5f);
- SetFloorHeight(0.0f);
-
- CreateCrashSphere(Math::Vector( 0.0f, 50.0f+14.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -7.0f, 50.0f+12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 7.0f, 50.0f+12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-12.0f, 50.0f+ 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 12.0f, 50.0f+ 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-14.0f, 50.0f+ 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 14.0f, 50.0f+ 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-12.0f, 50.0f- 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 12.0f, 50.0f- 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -7.0f, 50.0f-12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 7.0f, 50.0f-12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 50.0f-14.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
-
- CreateCrashSphere(Math::Vector(0.0f, 30.0f, 0.0f), 2.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 24.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 16.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 8.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(15.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_TARGET2 )
- {
- pModFile->ReadModel("objects\\target2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- height += 50.0f*1.5f;
- }
-
- if ( m_type == OBJECT_NEST )
- {
- pModFile->ReadModel("objects\\nest.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- m_terrain->AddBuildingLevel(pos, 3.0f, 5.0f, 1.0f, 0.5f);
-
- CreateShadowCircle(4.0f, 1.0f);
- }
-
- if ( m_type == OBJECT_START )
- {
- pModFile->ReadModel("objects\\start.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
- }
-
- if ( m_type == OBJECT_END )
- {
- pModFile->ReadModel("objects\\end.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
- }
-
-#if 0
- if ( power > 0.0f ) // creates a battery?
- {
- CObject* pPower;
-
- pPower = new CObject(m_iMan);
- pPower->SetType(power<=1.0f?OBJECT_POWER:OBJECT_ATOMIC);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- pPower->SetObjectRank(0, rank);
-
- if ( power <= 1.0f ) pModFile->ReadModel("objects\\power.mod");
- else pModFile->ReadModel("objects\\atomic.mod");
- pModFile->CreateEngineObject(rank);
-
- pPower->SetPosition(0, RetCharacter()->posPower);
- pPower->CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- pPower->SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.5f);
-
- pPower->SetTruck(this);
- SetPower(pPower);
-
- if ( power <= 1.0f ) pPower->SetEnergy(power);
- else pPower->SetEnergy(power/100.0f);
- }
-#endif
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos); // to display the shadows immediately
-
- CreateOtherObject(type);
- m_engine->LoadAllTexture();
-
- delete pModFile;
- return true;
-}
-
-// Creates a small resource set on the ground.
-
-bool CObject::CreateResource(Math::Vector pos, float angle, ObjectType type,
- float power)
-{
- CModFile* pModFile;
- char name[50];
- int rank;
- float radius, height;
-
- if ( type != OBJECT_SHOW )
- {
- if ( m_engine->RetRestCreate() < 1 ) return false;
- }
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
- SetObjectRank(0, rank);
- SetEnergy(power);
-
- name[0] = 0;
- if ( type == OBJECT_STONE ) strcpy(name, "objects\\stone.mod");
- if ( type == OBJECT_URANIUM ) strcpy(name, "objects\\uranium.mod");
- if ( type == OBJECT_METAL ) strcpy(name, "objects\\metal.mod");
- if ( type == OBJECT_POWER ) strcpy(name, "objects\\power.mod");
- if ( type == OBJECT_ATOMIC ) strcpy(name, "objects\\atomic.mod");
- if ( type == OBJECT_BULLET ) strcpy(name, "objects\\bullet.mod");
- if ( type == OBJECT_BBOX ) strcpy(name, "objects\\bbox.mod");
- if ( type == OBJECT_KEYa ) strcpy(name, "objects\\keya.mod");
- if ( type == OBJECT_KEYb ) strcpy(name, "objects\\keyb.mod");
- if ( type == OBJECT_KEYc ) strcpy(name, "objects\\keyc.mod");
- if ( type == OBJECT_KEYd ) strcpy(name, "objects\\keyd.mod");
- if ( type == OBJECT_TNT ) strcpy(name, "objects\\tnt.mod");
- if ( type == OBJECT_SCRAP1 ) strcpy(name, "objects\\scrap1.mod");
- if ( type == OBJECT_SCRAP2 ) strcpy(name, "objects\\scrap2.mod");
- if ( type == OBJECT_SCRAP3 ) strcpy(name, "objects\\scrap3.mod");
- if ( type == OBJECT_SCRAP4 ) strcpy(name, "objects\\scrap4.mod");
- if ( type == OBJECT_SCRAP5 ) strcpy(name, "objects\\scrap5.mod");
- if ( type == OBJECT_BOMB ) strcpy(name, "objects\\bomb.mod");
- if ( type == OBJECT_WAYPOINT ) strcpy(name, "objects\\waypoint.mod");
- if ( type == OBJECT_SHOW ) strcpy(name, "objects\\show.mod");
- if ( type == OBJECT_WINFIRE ) strcpy(name, "objects\\winfire.mod");
- if ( type == OBJECT_BAG ) strcpy(name, "objects\\bag.mod");
- if ( type == OBJECT_MARKSTONE ) strcpy(name, "objects\\cross1.mod");
- if ( type == OBJECT_MARKURANIUM ) strcpy(name, "objects\\cross3.mod");
- if ( type == OBJECT_MARKPOWER ) strcpy(name, "objects\\cross2.mod");
- if ( type == OBJECT_MARKKEYa ) strcpy(name, "objects\\crossa.mod");
- if ( type == OBJECT_MARKKEYb ) strcpy(name, "objects\\crossb.mod");
- if ( type == OBJECT_MARKKEYc ) strcpy(name, "objects\\crossc.mod");
- if ( type == OBJECT_MARKKEYd ) strcpy(name, "objects\\crossd.mod");
- if ( type == OBJECT_EGG ) strcpy(name, "objects\\egg.mod");
-
- pModFile->ReadModel(name);
- pModFile->CreateEngineObject(rank);
-
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- if ( type == OBJECT_SHOW ) // remains in the air?
- {
- delete pModFile;
- return true;
- }
-
- radius = 1.5f;
- height = 0.0f;
-
- if ( type == OBJECT_MARKSTONE ||
- type == OBJECT_MARKURANIUM ||
- type == OBJECT_MARKKEYa ||
- type == OBJECT_MARKKEYb ||
- type == OBJECT_MARKKEYc ||
- type == OBJECT_MARKKEYd ||
- type == OBJECT_MARKPOWER ||
- type == OBJECT_WAYPOINT )
- {
- }
- else if ( type == OBJECT_EGG )
- {
- CreateCrashSphere(Math::Vector(-1.0f, 2.8f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
- radius = 3.0f;
- }
- else if ( type == OBJECT_BOMB )
- {
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 3.0f);
- radius = 3.0f;
- }
- else if ( type == OBJECT_BAG )
- {
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f);
- SetZoom(0, 1.5f);
- radius = 5.0f;
- height = -1.4f;
- }
- else
- {
- CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.5f);
- }
- CreateShadowCircle(radius, 1.0f);
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
- m_engine->LoadAllTexture();
- FloorAdjust();
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos); // to display the shadows immediately
-
- delete pModFile;
- return true;
-}
-
-// Creates a flag placed on the ground.
-
-bool CObject::CreateFlag(Math::Vector pos, float angle, ObjectType type)
-{
- CModFile* pModFile;
- char name[50];
- int rank, i;
-
- if ( m_engine->RetRestCreate() < 1+4 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- name[0] = 0;
- if ( type == OBJECT_FLAGb ) strcpy(name, "objects\\flag1b.mod");
- if ( type == OBJECT_FLAGr ) strcpy(name, "objects\\flag1r.mod");
- if ( type == OBJECT_FLAGg ) strcpy(name, "objects\\flag1g.mod");
- if ( type == OBJECT_FLAGy ) strcpy(name, "objects\\flag1y.mod");
- if ( type == OBJECT_FLAGv ) strcpy(name, "objects\\flag1v.mod");
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
- SetObjectRank(0, rank);
- pModFile->ReadModel(name);
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- name[0] = 0;
- if ( type == OBJECT_FLAGb ) strcpy(name, "objects\\flag2b.mod");
- if ( type == OBJECT_FLAGr ) strcpy(name, "objects\\flag2r.mod");
- if ( type == OBJECT_FLAGg ) strcpy(name, "objects\\flag2g.mod");
- if ( type == OBJECT_FLAGy ) strcpy(name, "objects\\flag2y.mod");
- if ( type == OBJECT_FLAGv ) strcpy(name, "objects\\flag2v.mod");
-
- for ( i=0 ; i<4 ; i++ )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1+i, rank);
- SetObjectParent(1+i, i);
- pModFile->ReadModel(name);
- pModFile->CreateEngineObject(rank);
- if ( i == 0 ) SetPosition(1+i, Math::Vector(0.15f, 5.0f, 0.0f));
- else SetPosition(1+i, Math::Vector(0.79f, 0.0f, 0.0f));
- }
-
- SetJotlerSphere(Math::Vector(0.0f, 4.0f, 0.0f), 1.0f);
- CreateShadowCircle(2.0f, 0.3f);
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
- m_engine->LoadAllTexture();
- FloorAdjust();
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- delete pModFile;
- return true;
-}
-
-// Creates a barrier placed on the ground.
-
-bool CObject::CreateBarrier(Math::Vector pos, float angle, float height,
- ObjectType type)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- if ( type == OBJECT_BARRIER0 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\barrier0.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(6.0f, 0.5f, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_BARRIER1 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\barrier1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector( 8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(12.0f, 0.5f, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_BARRIER2 ) // cardboard?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\barrier2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector( 8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(12.0f, 0.8f, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_BARRIER3 ) // match + straw?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\barrier3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector( 8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(10.0f, 0.5f, D3DSHADOWWORM);
- }
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
- FloorAdjust();
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos);
-
- delete pModFile;
- return true;
-}
-
-// Creates a plant placed on the ground.
-
-bool CObject::CreatePlant(Math::Vector pos, float angle, float height,
- ObjectType type)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- if ( type == OBJECT_PLANT0 ||
- type == OBJECT_PLANT1 ||
- type == OBJECT_PLANT2 ||
- type == OBJECT_PLANT3 ||
- type == OBJECT_PLANT4 ) // standard?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- if ( type == OBJECT_PLANT0 ) pModFile->ReadModel("objects\\plant0.mod");
- if ( type == OBJECT_PLANT1 ) pModFile->ReadModel("objects\\plant1.mod");
- if ( type == OBJECT_PLANT2 ) pModFile->ReadModel("objects\\plant2.mod");
- if ( type == OBJECT_PLANT3 ) pModFile->ReadModel("objects\\plant3.mod");
- if ( type == OBJECT_PLANT4 ) pModFile->ReadModel("objects\\plant4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- height -= 2.0f;
-
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f);
- SetJotlerSphere(Math::Vector(0.0f, 0.0f, 0.0f), 8.0f);
-
- CreateShadowCircle(8.0f, 0.5f);
- }
-
- if ( type == OBJECT_PLANT5 ||
- type == OBJECT_PLANT6 ||
- type == OBJECT_PLANT7 ) // clover?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- if ( type == OBJECT_PLANT5 ) pModFile->ReadModel("objects\\plant5.mod");
- if ( type == OBJECT_PLANT6 ) pModFile->ReadModel("objects\\plant6.mod");
- if ( type == OBJECT_PLANT7 ) pModFile->ReadModel("objects\\plant7.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
-//? CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 3.0f, SOUND_BOUM, 0.10f);
- SetJotlerSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f);
-
- CreateShadowCircle(5.0f, 0.3f);
- }
-
- if ( type == OBJECT_PLANT8 ||
- type == OBJECT_PLANT9 ) // squash?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- if ( type == OBJECT_PLANT8 ) pModFile->ReadModel("objects\\plant8.mod");
- if ( type == OBJECT_PLANT9 ) pModFile->ReadModel("objects\\plant9.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
-
- CreateShadowCircle(10.0f, 0.5f);
- }
-
- if ( type == OBJECT_PLANT10 ||
- type == OBJECT_PLANT11 ||
- type == OBJECT_PLANT12 ||
- type == OBJECT_PLANT13 ||
- type == OBJECT_PLANT14 ) // succulent?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- if ( type == OBJECT_PLANT10 ) pModFile->ReadModel("objects\\plant10.mod");
- if ( type == OBJECT_PLANT11 ) pModFile->ReadModel("objects\\plant11.mod");
- if ( type == OBJECT_PLANT12 ) pModFile->ReadModel("objects\\plant12.mod");
- if ( type == OBJECT_PLANT13 ) pModFile->ReadModel("objects\\plant13.mod");
- if ( type == OBJECT_PLANT14 ) pModFile->ReadModel("objects\\plant14.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 12.0f, 0.0f), 5.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 6.0f);
- SetJotlerSphere(Math::Vector(0.0f, 4.0f, 0.0f), 8.0f);
-
- CreateShadowCircle(8.0f, 0.3f);
- }
-
- if ( type == OBJECT_PLANT15 ||
- type == OBJECT_PLANT16 ||
- type == OBJECT_PLANT17 ||
- type == OBJECT_PLANT18 ||
- type == OBJECT_PLANT19 ) // fern?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- if ( type == OBJECT_PLANT15 ) pModFile->ReadModel("objects\\plant15.mod");
- if ( type == OBJECT_PLANT16 ) pModFile->ReadModel("objects\\plant16.mod");
- if ( type == OBJECT_PLANT17 ) pModFile->ReadModel("objects\\plant17.mod");
- if ( type == OBJECT_PLANT18 ) pModFile->ReadModel("objects\\plant18.mod");
- if ( type == OBJECT_PLANT19 ) pModFile->ReadModel("objects\\plant19.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- if ( type != OBJECT_PLANT19 )
- {
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f);
- }
- SetJotlerSphere(Math::Vector(0.0f, 0.0f, 0.0f), 8.0f);
-
- CreateShadowCircle(8.0f, 0.5f);
- }
-
- if ( type == OBJECT_TREE0 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\tree0.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 2.0f), 3.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(-1.0f, 10.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 0.0f, 17.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 1.0f, 27.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
-
- CreateShadowCircle(8.0f, 0.5f);
- }
-
- if ( type == OBJECT_TREE1 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\tree1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 2.0f), 3.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(-2.0f, 11.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(-2.0f, 19.0f, 2.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 2.0f, 26.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 2.0f, 34.0f,-2.0f), 2.0f, SOUND_BOUMs, 0.20f);
-
- CreateShadowCircle(8.0f, 0.5f);
- }
-
- if ( type == OBJECT_TREE2 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\tree2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 1.0f), 3.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(-2.0f, 10.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(-2.0f, 19.0f, 2.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 2.0f, 25.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 3.0f, 32.0f,-2.0f), 2.0f, SOUND_BOUMs, 0.20f);
-
- CreateShadowCircle(8.0f, 0.5f);
- }
-
- if ( type == OBJECT_TREE3 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\tree3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(-2.0f, 3.0f, 2.0f), 3.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(-3.0f, 9.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 0.0f, 18.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 0.0f, 27.0f, 7.0f), 2.0f, SOUND_BOUMs, 0.20f);
-
- CreateShadowCircle(8.0f, 0.5f);
- }
-
- if ( type == OBJECT_TREE4 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\tree4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 10.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(0.0f, 21.0f, 0.0f), 8.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(0.0f, 32.0f, 0.0f), 7.0f, SOUND_BOUMs, 0.20f);
-
- CreateShadowCircle(8.0f, 0.5f);
- }
-
- if ( type == OBJECT_TREE5 ) // giant tree (for the world "teen")
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\tree5.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector( 0.0f, 5.0f,-10.0f), 25.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector(-65.0f, 5.0f, 65.0f), 20.0f, SOUND_BOUMs, 0.20f);
- CreateCrashSphere(Math::Vector( 38.0f, 5.0f, 21.0f), 18.0f, SOUND_BOUMs, 0.20f);
-
- CreateShadowCircle(50.0f, 0.5f);
- }
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos);
-
- delete pModFile;
- return true;
-}
-
-// Creates a mushroom placed on the ground.
-
-bool CObject::CreateMushroom(Math::Vector pos, float angle, float height,
- ObjectType type)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- if ( type == OBJECT_MUSHROOM1 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\mush1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 3.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 5.5f);
- SetJotlerSphere(Math::Vector(0.0f, 3.0f, 0.0f), 5.5f);
-
- CreateShadowCircle(6.0f, 0.5f);
- }
-
- if ( type == OBJECT_MUSHROOM2 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\mush2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 5.0f, 0.0f), 3.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 5.5f);
- SetJotlerSphere(Math::Vector(0.0f, 4.0f, 0.0f), 5.5f);
-
- CreateShadowCircle(5.0f, 0.5f);
- }
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos);
-
- delete pModFile;
- return true;
-}
-
-// Creates a toy placed on the ground.
-
-bool CObject::CreateTeen(Math::Vector pos, float angle, float zoom, float height,
- ObjectType type)
-{
- CModFile* pModFile;
- Math::Matrix* mat;
- D3DCOLORVALUE color;
- int rank;
- float fShadow;
- bool bFloorAdjust = true;
-
- if ( m_engine->RetRestCreate() < 1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- fShadow = Math::Norm(1.0f-height/10.0f);
-
- if ( type == OBJECT_TEEN0 ) // orange pencil lg=10
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen0.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 5.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 2.5f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-2.5f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(5.0f, 0.8f*fShadow, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_TEEN1 ) // blue pencil lg=14
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 6.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 2.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-2.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-4.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-6.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(6.0f, 0.8f*fShadow, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_TEEN2 ) // red pencil lg=16
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 7.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.7f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 2.3f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-2.3f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-4.7f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-7.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(6.0f, 0.8f*fShadow, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_TEEN3 ) // jar with pencils
- {
- rank = m_engine->CreateObject();
-//? m_engine->SetObjectType(rank, TYPEFIX);
- m_engine->SetObjectType(rank, TYPEMETAL);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 4.0f);
- CreateShadowCircle(6.0f, 0.5f*fShadow);
- }
-
- if ( type == OBJECT_TEEN4 ) // scissors
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-9.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-6.0f, 1.0f, 0.0f), 1.1f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-3.0f, 1.0f, 0.0f), 1.2f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.3f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 5.1f, 1.0f,-1.3f), 2.6f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 8.0f, 1.0f, 2.2f), 2.3f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 9.4f, 1.0f,-2.0f), 2.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(10.0f, 0.5f*fShadow, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_TEEN5 ) // CD
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen5.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
- SetFloorHeight(0.0f);
- bFloorAdjust = false;
-
- m_terrain->AddBuildingLevel(pos, 5.9f, 6.1f, 0.2f, 0.5f);
- CreateShadowCircle(8.0f, 0.2f*fShadow);
- }
-
- if ( type == OBJECT_TEEN6 ) // book 1
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen6.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(20.0f, 0.2f*fShadow);
- }
-
- if ( type == OBJECT_TEEN7 ) // book 2
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen7.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(20.0f, 0.2f*fShadow);
- }
-
- if ( type == OBJECT_TEEN8 ) // a stack of books 1
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen8.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 12.0f);
- CreateShadowCircle(20.0f, 0.2f*fShadow);
- }
-
- if ( type == OBJECT_TEEN9 ) // a stack of books 2
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen9.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 12.0f);
- CreateShadowCircle(20.0f, 0.2f*fShadow);
- }
-
- if ( type == OBJECT_TEEN10 ) // bookcase
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen10.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-26.0f, 3.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-15.0f, 3.0f,-4.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-15.0f, 3.0f, 5.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -4.0f, 3.0f,-4.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -4.0f, 3.0f, 5.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 6.0f, 3.0f,-4.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 6.0f, 3.0f, 4.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 14.0f, 3.0f,-3.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 14.0f, 3.0f, 2.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 24.0f, 3.0f, 5.0f), 6.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 20.0f);
- CreateShadowCircle(40.0f, 0.2f*fShadow);
- }
-
- if ( type == OBJECT_TEEN11 ) // lamp
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen11.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
- SetZoom(0, zoom);
-
- mat = RetWorldMatrix(0);
- pos = Math::Transform(*mat, Math::Vector(-56.0f, 22.0f, 0.0f));
- m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(20.0f, 20.0f), PARTISELY, 1.0f, 0.0f, 0.0f);
-
- pos = Math::Transform(*mat, Math::Vector(-65.0f, 40.0f, 0.0f));
- color.r = 4.0f;
- color.g = 2.0f;
- color.b = 0.0f; // yellow-orange
- color.a = 0.0f;
- m_main->CreateSpot(pos, color);
- }
-
- if ( type == OBJECT_TEEN12 ) // coke
- {
- rank = m_engine->CreateObject();
-//? m_engine->SetObjectType(rank, TYPEFIX);
- m_engine->SetObjectType(rank, TYPEMETAL);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen12.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 9.0f, 0.0f), 5.0f);
- CreateShadowCircle(4.5f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN13 ) // cardboard farm
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen13.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 15.0f);
- CreateShadowCircle(20.0f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN14 ) // open box
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen14.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 15.0f);
- CreateShadowCircle(20.0f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN15 ) // stack of cartons
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen15.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 15.0f);
- CreateShadowCircle(20.0f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN16 ) // watering can
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen16.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-8.0f, 4.0f, 0.0f), 12.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 8.0f, 4.0f, 0.0f), 12.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 13.0f, 0.0f), 20.0f);
- CreateShadowCircle(18.0f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN17 ) // wheel |
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen17.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 0.0f, 31.0f, 0.0f), 31.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 31.0f, 0.0f), 31.0f);
- CreateShadowCircle(24.0f, 0.5f*fShadow);
- }
-
- if ( type == OBJECT_TEEN18 ) // wheel /
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen18.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 0.0f, 31.0f, 0.0f), 31.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 31.0f, 0.0f), 31.0f);
- CreateShadowCircle(24.0f, 0.5f*fShadow);
- }
-
- if ( type == OBJECT_TEEN19 ) // wheel =
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen19.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 0.0f, 10.0f, 0.0f), 32.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 32.0f);
- CreateShadowCircle(33.0f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN20 ) // wall with shelf
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen20.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-175.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-175.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -55.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -55.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -37.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -37.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 83.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 83.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
- }
-
- if ( type == OBJECT_TEEN21 ) // wall with window
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen21.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
- }
-
- if ( type == OBJECT_TEEN22 ) // wall with door and shelf
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen22.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-135.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-135.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -15.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -15.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
- }
-
- if ( type == OBJECT_TEEN23 ) // skateboard on wheels
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen23.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- if ( m_option == 1 ) // passage under the prohibited skateboard?
- {
- CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 0.0f), 11.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 10.0f, 2.0f, 0.0f), 11.0f, SOUND_BOUMm, 0.45f);
- }
-
- CreateCrashSphere(Math::Vector(-23.0f, 2.0f, 7.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-23.0f, 2.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-23.0f, 2.0f,-7.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 23.0f, 2.0f, 7.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 23.0f, 2.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 23.0f, 2.0f,-7.0f), 3.0f, SOUND_BOUMm, 0.45f);
-
- CreateShadowCircle(35.0f, 0.8f*fShadow, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_TEEN24 ) // skate /
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen24.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-12.0f, 0.0f, -3.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-12.0f, 0.0f, 3.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateShadowCircle(20.0f, 0.2f*fShadow);
- }
-
- if ( type == OBJECT_TEEN25 ) // skate /
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen25.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-12.0f, 0.0f, -3.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-12.0f, 0.0f, 3.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateShadowCircle(20.0f, 0.2f*fShadow);
- }
-
- if ( type == OBJECT_TEEN26 ) // ceiling lamp
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen26.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
- SetFloorHeight(0.0f);
-
- mat = RetWorldMatrix(0);
- pos = Math::Transform(*mat, Math::Vector(0.0f, 50.0f, 0.0f));
- m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(100.0f, 100.0f), PARTISELY, 1.0f, 0.0f, 0.0f);
-
- pos = Math::Transform(*mat, Math::Vector(0.0f, 50.0f, 0.0f));
- color.r = 4.0f;
- color.g = 2.0f;
- color.b = 0.0f; // yellow-orange
- color.a = 0.0f;
- m_main->CreateSpot(pos, color);
- }
-
- if ( type == OBJECT_TEEN27 ) // large plant?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen27.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
- CreateShadowCircle(40.0f, 0.5f);
- }
-
- if ( type == OBJECT_TEEN28 ) // bottle?
- {
- rank = m_engine->CreateObject();
-//? m_engine->SetObjectType(rank, TYPEFIX);
- m_engine->SetObjectType(rank, TYPEMETAL);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen28.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUM, 0.10f);
- CreateShadowCircle(7.0f, 0.6f*fShadow);
- }
-
- if ( type == OBJECT_TEEN29 ) // bridge?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen29.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
- bFloorAdjust = false;
- }
-
- if ( type == OBJECT_TEEN30 ) // jump?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen30.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 15.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 15.0f, 0.0f), 17.0f);
- CreateShadowCircle(20.0f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN31 ) // basket?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen31.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector( 0.0f, 2.0f, 0.0f), 6.0f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector( 9.0f, 4.0f, 1.0f), 6.0f, SOUND_BOUM, 0.10f);
-
- SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 10.0f);
- CreateShadowCircle(16.0f, 0.6f*fShadow);
- }
-
- if ( type == OBJECT_TEEN32 ) // chair?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen32.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector( 17.5f, 1.0f, 17.5f), 3.5f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector( 17.5f, 1.0f, -17.5f), 3.5f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector(-17.5f, 1.0f, 17.5f), 3.5f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector(-17.5f, 1.0f, -17.5f), 3.5f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 26.0f);
- CreateShadowCircle(35.0f, 0.3f*fShadow);
- }
-
- if ( type == OBJECT_TEEN33 ) // panel?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen33.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
- CreateShadowCircle(10.0f, 0.3f*fShadow);
- }
-
- if ( type == OBJECT_TEEN34 ) // stone?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen34.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
- CreateShadowCircle(3.0f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN35 ) // pipe?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen35.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(-40.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector(-20.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector( 0.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector( 20.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
- CreateCrashSphere(Math::Vector( 40.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
- CreateShadowCircle(40.0f, 0.8f*fShadow, D3DSHADOWWORM);
- }
-
- if ( type == OBJECT_TEEN36 ) // trunk?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen36.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
- bFloorAdjust = false;
- }
-
- if ( type == OBJECT_TEEN37 ) // boat?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen37.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
- bFloorAdjust = false;
- }
-
- if ( type == OBJECT_TEEN38 ) // fan?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen38a.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\teen38b.mod"); // engine
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 30.0f, 0.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 1);
- pModFile->ReadModel("objects\\teen38c.mod"); // propeller
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(0.0f, 0.0f, 0.0f));
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 2.0f, 0.0f), 10.0f);
- CreateShadowCircle(15.0f, 0.5f*fShadow);
- }
-
- if ( type == OBJECT_TEEN39 ) // potted plant?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen39.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 8.5f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 2.0f, 0.0f), 8.5f);
- CreateShadowCircle(10.0f, 1.0f*fShadow);
- }
-
- if ( type == OBJECT_TEEN40 ) // balloon?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen40.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 5.0f, 0.0f), 11.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 14.0f, 0.0f), 15.0f);
- CreateShadowCircle(15.0f, 0.7f*fShadow);
- }
-
- if ( type == OBJECT_TEEN41 ) // fence?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen41.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
- }
-
- if ( type == OBJECT_TEEN42 ) // clover?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen42.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 2.0f, SOUND_BOUM, 0.10f);
- CreateShadowCircle(15.0f, 0.4f*fShadow);
- }
-
- if ( type == OBJECT_TEEN43 ) // clover?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen43.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 2.0f, SOUND_BOUM, 0.10f);
- CreateShadowCircle(15.0f, 0.4f*fShadow);
- }
-
- if ( type == OBJECT_TEEN44 ) // car?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\teen44.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, zoom);
-
- CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 55.0f, SOUND_BOUM, 0.10f);
- SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 55.0f);
- CreateShadowCircle(55.0f, 1.0f*fShadow);
- }
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- if ( bFloorAdjust )
- {
- SetFloorHeight(0.0f);
- FloorAdjust();
- }
-
- CreateOtherObject(type);
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos);
-
- delete pModFile;
- return true;
-}
-
-// Creates a crystal placed on the ground.
-
-bool CObject::CreateQuartz(Math::Vector pos, float angle, float height,
- ObjectType type)
-{
- CModFile* pModFile;
- float radius;
- int rank;
-
- if ( m_engine->RetRestCreate() < 1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- if ( type == OBJECT_QUARTZ0 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEQUARTZ);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\quartz0.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 3.5f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 2.0f, 0.0f), 3.5f);
-
- CreateShadowCircle(4.0f, 0.5f);
- }
- if ( type == OBJECT_QUARTZ1 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEQUARTZ);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\quartz1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 5.0f);
-
- CreateShadowCircle(5.0f, 0.5f);
- }
- if ( type == OBJECT_QUARTZ2 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEQUARTZ);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\quartz2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 6.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 6.0f);
-
- CreateShadowCircle(6.0f, 0.5f);
- }
- if ( type == OBJECT_QUARTZ3 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEQUARTZ);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\quartz3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 10.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 10.0f);
-
- CreateShadowCircle(10.0f, 0.5f);
- }
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos);
-
- if ( type == OBJECT_QUARTZ0 )
- {
- pos.y += 4.0f;
- radius = 2.0f;
- }
- if ( type == OBJECT_QUARTZ1 )
- {
- pos.y += 6.0f;
- radius = 4.0f;
- }
- if ( type == OBJECT_QUARTZ2 )
- {
- pos.y += 10.0f;
- radius = 5.0f;
- }
- if ( type == OBJECT_QUARTZ3 )
- {
- pos.y += 16.0f;
- radius = 8.0f;
- }
- m_particule->CreateParticule(pos, pos, Math::Point(2.0f, 2.0f), PARTIQUARTZ, 0.7f+Math::Rand()*0.7f, radius, 0.0f);
- m_particule->CreateParticule(pos, pos, Math::Point(2.0f, 2.0f), PARTIQUARTZ, 0.7f+Math::Rand()*0.7f, radius, 0.0f);
-
- delete pModFile;
- return true;
-}
-
-// Creates a root placed on the ground.
-
-bool CObject::CreateRoot(Math::Vector pos, float angle, float height,
- ObjectType type)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- if ( type == OBJECT_ROOT0 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\root0.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 2.0f);
-
- CreateCrashSphere(Math::Vector(-5.0f, 1.0f, 0.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 4.0f, 1.0f, 2.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 4.0f, 1.0f, -3.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 2.0f, 5.0f, -1.0f), 1.5f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector(-4.0f, 5.0f, -1.0f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector(-2.0f, 8.0f, -0.5f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 0.0f, 10.0f, -0.5f), 1.0f, SOUND_BOUMv, 0.15f);
-//? SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 11.0f);
-
- CreateShadowCircle(16.0f, 0.5f);
- }
- if ( type == OBJECT_ROOT1 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\root1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 2.0f);
-
- CreateCrashSphere(Math::Vector(-4.0f, 1.0f, 1.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 2.0f), 1.5f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 3.0f, 1.0f, -2.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector(-2.0f, 5.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 2.0f, 5.0f, 0.0f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 0.0f, 8.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 0.0f, 12.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
-//? SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 12.0f);
-
- CreateShadowCircle(16.0f, 0.5f);
- }
- if ( type == OBJECT_ROOT2 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\root2.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 2.0f);
-
- CreateCrashSphere(Math::Vector(-3.0f, 1.0f, 0.5f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 3.0f, 1.0f, -1.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector(-1.0f, 4.5f, 0.0f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 3.0f, 7.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 0.0f, 7.0f, -1.0f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 4.0f, 11.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
-//? SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 10.0f);
-
- CreateShadowCircle(16.0f, 0.5f);
- }
- if ( type == OBJECT_ROOT3 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\root3.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 2.0f);
-
- CreateCrashSphere(Math::Vector(-4.0f, 1.0f, 1.0f), 3.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 4.0f, 1.0f, -3.0f), 3.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 6.0f, 1.0f, 4.0f), 3.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector(-2.5f, 7.0f, 2.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 4.0f, 7.0f, 2.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 3.0f, 6.0f, -1.0f), 1.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 0.0f, 12.0f, 0.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 1.0f, 16.0f, 0.0f), 1.0f, SOUND_BOUMv, 0.15f);
-//? SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 14.0f);
-
- CreateShadowCircle(22.0f, 0.5f);
- }
- if ( type == OBJECT_ROOT4 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\root4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 2.0f);
-
- CreateCrashSphere(Math::Vector( -7.0f, 2.0f, 3.0f), 4.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 5.0f, 2.0f, -6.0f), 4.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 6.0f, 2.0f, 6.0f), 3.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector(-11.0f, 1.0f, -2.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 1.0f, 1.0f, -7.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( -4.0f, 10.0f, 3.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 1.0f, 11.0f, 7.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 3.0f, 11.0f, -3.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( -3.0f, 17.0f, 1.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( -3.0f, 23.0f, -1.0f), 2.0f, SOUND_BOUMv, 0.15f);
-//? SetGlobalSphere(Math::Vector(0.0f, 12.0f, 0.0f), 20.0f);
-
- CreateShadowCircle(30.0f, 0.5f);
- }
- if ( type == OBJECT_ROOT5 ) // gravity root ?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\root4.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 2.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\root5.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(-5.0f, 28.0f, -4.0f));
- SetAngleX(1, -30.0f*Math::PI/180.0f);
- SetAngleZ(1, 20.0f*Math::PI/180.0f);
-
- CreateCrashSphere(Math::Vector( -7.0f, 2.0f, 3.0f), 4.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 5.0f, 2.0f, -6.0f), 4.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 6.0f, 2.0f, 6.0f), 3.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector(-11.0f, 1.0f, -2.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 1.0f, 1.0f, -7.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( -4.0f, 10.0f, 3.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 1.0f, 11.0f, 7.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( 3.0f, 11.0f, -3.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( -3.0f, 17.0f, 1.0f), 2.0f, SOUND_BOUMv, 0.15f);
- CreateCrashSphere(Math::Vector( -3.0f, 23.0f, -1.0f), 2.0f, SOUND_BOUMv, 0.15f);
-//? SetGlobalSphere(Math::Vector(0.0f, 12.0f, 0.0f), 20.0f);
-
- CreateShadowCircle(30.0f, 0.5f);
- }
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos);
-
- delete pModFile;
- return true;
-}
-
-// Creates a small home.
-
-bool CObject::CreateHome(Math::Vector pos, float angle, float height,
- ObjectType type)
-{
- CModFile* pModFile;
- int rank;
-
- if ( m_engine->RetRestCreate() < 1 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- if ( type == OBJECT_HOME1 )
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX);
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\home1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 1.3f);
-
- CreateCrashSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUMs, 0.25f);
-//? SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 11.0f);
- CreateShadowCircle(16.0f, 0.5f);
- }
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos);
-
- delete pModFile;
- return true;
-}
-
-// Creates ruin placed on the ground.
-
-bool CObject::CreateRuin(Math::Vector pos, float angle, float height,
- ObjectType type)
-{
- CModFile* pModFile;
- char name[50];
- int rank;
-
- if ( m_engine->RetRestCreate() < 1+4 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
- SetObjectRank(0, rank);
-
- name[0] = 0;
- if ( type == OBJECT_RUINmobilew1 ) strcpy(name, "objects\\ruin1.mod");
- if ( type == OBJECT_RUINmobilew2 ) strcpy(name, "objects\\ruin1.mod");
- if ( type == OBJECT_RUINmobilet1 ) strcpy(name, "objects\\ruin2.mod");
- if ( type == OBJECT_RUINmobilet2 ) strcpy(name, "objects\\ruin2.mod");
- if ( type == OBJECT_RUINmobiler1 ) strcpy(name, "objects\\ruin3.mod");
- if ( type == OBJECT_RUINmobiler2 ) strcpy(name, "objects\\ruin3.mod");
- if ( type == OBJECT_RUINfactory ) strcpy(name, "objects\\ruin4.mod");
- if ( type == OBJECT_RUINdoor ) strcpy(name, "objects\\ruin5.mod");
- if ( type == OBJECT_RUINsupport ) strcpy(name, "objects\\ruin6.mod");
- if ( type == OBJECT_RUINradar ) strcpy(name, "objects\\ruin7.mod");
- if ( type == OBJECT_RUINconvert ) strcpy(name, "objects\\ruin8.mod");
- if ( type == OBJECT_RUINbase ) strcpy(name, "objects\\ruin9.mod");
- if ( type == OBJECT_RUINhead ) strcpy(name, "objects\\ruin10.mod");
-
- pModFile->ReadModel(name);
- pModFile->CreateEngineObject(rank);
-
- SetPosition(0, pos);
- SetAngleY(0, angle);
-
- if ( type == OBJECT_RUINmobilew1 ) // vehicle had wheels?
- {
- // Creates the right-back wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(6, rank);
- SetObjectParent(6, 0);
-
- pModFile->ReadModel("objects\\ruin1w.mod");
- pModFile->CreateEngineObject(rank);
-
- SetPosition(6, Math::Vector(-3.0f, 1.8f, -4.0f));
- SetAngleX(6, -Math::PI/2.0f);
-
- // Creates the left-back wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(7, rank);
- SetObjectParent(7, 0);
-
- pModFile->ReadModel("objects\\ruin1w.mod");
- pModFile->CreateEngineObject(rank);
-
- SetPosition(7, Math::Vector(-3.0f, 1.0f, 3.0f));
- SetAngleY(7, Math::PI-0.3f);
- SetAngleX(7, -0.3f);
-
- // Creates the right-front wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(8, rank);
- SetObjectParent(8, 0);
-
- pModFile->ReadModel("objects\\ruin1w.mod");
- pModFile->CreateEngineObject(rank);
-
- SetPosition(8, Math::Vector(2.0f, 1.6f, -3.0f));
- SetAngleY(8, 0.3f);
-
- // Creates the left-front wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(9, rank);
- SetObjectParent(9, 0);
-
- pModFile->ReadModel("objects\\ruin1w.mod");
- pModFile->CreateEngineObject(rank);
-
- SetPosition(9, Math::Vector(2.0f, 1.0f, 3.0f));
- SetAngleY(9, Math::PI-0.2f);
- SetAngleX(9, 0.2f);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.8f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
-//? SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
-
- CreateShadowCircle(4.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINmobilew2 ) // vehicle has wheels?
- {
- // Creates the left-back wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(7, rank);
- SetObjectParent(7, 0);
-
- pModFile->ReadModel("objects\\ruin1w.mod");
- pModFile->CreateEngineObject(rank);
-
- SetPosition(7, Math::Vector(-3.0f, 1.0f, 3.0f));
- SetAngleY(7, Math::PI+0.3f);
- SetAngleX(7, 0.4f);
-
- // Creates the left-front wheel.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(9, rank);
- SetObjectParent(9, 0);
-
- pModFile->ReadModel("objects\\ruin1w.mod");
- pModFile->CreateEngineObject(rank);
-
- SetPosition(9, Math::Vector(2.0f, 1.0f, 3.0f));
- SetAngleY(9, Math::PI+0.3f);
- SetAngleX(9, -0.3f);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.8f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
-//? SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
-
- CreateShadowCircle(4.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINmobilet1 ) // vehicle have caterpillars?
- {
- // Creates the cannon.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
-
- pModFile->ReadModel("objects\\ruin2c.mod");
- pModFile->CreateEngineObject(rank);
-
- SetPosition(1, Math::Vector(3.0f, 5.0f, -2.5f));
- SetAngleX(1, -Math::PI*0.85f);
- SetAngleY(1, -0.4f);
- SetAngleZ(1, -0.1f);
-
- CreateCrashSphere(Math::Vector(1.0f, 2.8f, -1.0f), 5.0f, SOUND_BOUMm, 0.45f);
-//? SetGlobalSphere(Math::Vector(1.0f, 5.0f, -1.0f), 10.0f);
-
- CreateShadowCircle(5.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINmobilet2 ) // vehicle have caterpillars?
- {
- CreateCrashSphere(Math::Vector(0.0f, 2.8f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
-//? SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
-
- CreateShadowCircle(5.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINmobiler1 ) // vehicle skating?
- {
- CreateCrashSphere(Math::Vector(1.0f, 2.8f, -1.0f), 5.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(1.0f, 5.0f, -1.0f), 10.0f);
-
- CreateShadowCircle(5.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINmobiler2 ) // vehicle skating?
- {
- CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
-
- CreateShadowCircle(6.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINfactory ) // factory ?
- {
- CreateCrashSphere(Math::Vector( 9.0f, 1.0f, -11.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 2.0f, -11.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f, -10.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-12.0f, 11.0f, -4.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 4.0f, -2.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 8.0f, 3.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 2.0f, 4.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 2.0f, 10.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -4.0f, 0.0f, 10.0f), 3.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 18.0f);
-
- CreateShadowCircle(20.0f, 0.7f);
- }
-
- if ( type == OBJECT_RUINdoor ) // converter holder?
- {
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
-//? SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 6.0f);
-
- CreateShadowCircle(6.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINsupport ) // radar holder?
- {
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
-//? SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f);
-
- CreateShadowCircle(3.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINradar ) // radar base?
- {
- CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
-//? SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 6.0f);
-
- CreateShadowCircle(6.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINconvert ) // converter?
- {
- m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
-
- CreateCrashSphere(Math::Vector(-10.0f, 0.0f, 4.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-10.0f, 0.0f, -4.0f), 5.0f, SOUND_BOUMm, 0.45f);
-//? SetGlobalSphere(Math::Vector(-3.0f, 0.0f, 0.0f), 14.0f);
- }
-
- if ( type == OBJECT_RUINbase ) // base?
- {
- CreateCrashSphere(Math::Vector( 0.0f, 15.0f, 0.0f),28.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 17.0f, 6.0f, 42.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 17.0f, 17.0f, 42.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-17.0f, 6.0f, 42.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-17.0f, 17.0f, 42.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-42.0f, 6.0f, 17.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-42.0f, 17.0f, 17.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-42.0f, 6.0f, -17.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-42.0f, 17.0f, -17.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-17.0f, 6.0f, -42.0f), 6.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-17.0f, 10.0f, -42.0f), 4.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 15.0f, 13.0f, -34.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 31.0f, 15.0f, -13.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 21.0f, 8.0f, -39.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 26.0f, 8.0f, -33.0f), 5.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 48.0f);
-
- CreateShadowCircle(40.0f, 1.0f);
- }
-
- if ( type == OBJECT_RUINhead ) // base cap?
- {
- CreateCrashSphere(Math::Vector( 0.0f, 13.0f, 0.0f),20.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, -8.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f,-16.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f,-22.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-21.0f, 7.0f, 9.0f), 8.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -9.0f, 7.0f, 21.0f), 8.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 21.0f, 7.0f, 9.0f), 8.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 9.0f, 7.0f, 21.0f), 8.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-21.0f, 7.0f, -9.0f), 8.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( -9.0f, 7.0f, -21.0f), 8.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 21.0f, 7.0f, -9.0f), 8.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 9.0f, 7.0f, -21.0f), 8.0f, SOUND_BOUMm, 0.45f);
- SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 35.0f);
-
- CreateShadowCircle(30.0f, 1.0f);
- }
-
- pos = RetPosition(0);
- SetPosition(0, pos); //to display the shadows immediately
-
- SetFloorHeight(0.0f);
- CreateOtherObject(type);
-
- if ( type != OBJECT_RUINfactory &&
- type != OBJECT_RUINconvert &&
- type != OBJECT_RUINbase )
- {
- FloorAdjust();
- }
-
- pos = RetPosition(0);
- pos.y += height;
- SetPosition(0, pos); //to display the shadows immediately
-
- if ( type == OBJECT_RUINmobilew1 )
- {
- pos = RetPosition(0);
- pos.y -= 0.5f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)-0.1f;
- SetAngleX(0, angle);
- }
-
- if ( type == OBJECT_RUINmobilew2 )
- {
- pos = RetPosition(0);
- pos.y -= 1.5f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)-0.9f;
- SetAngleX(0, angle);
-
- angle = RetAngleZ(0)-0.1f;
- SetAngleZ(0, angle);
- }
-
- if ( type == OBJECT_RUINmobilet1 )
- {
- pos = RetPosition(0);
- pos.y -= 0.9f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)-0.3f;
- SetAngleX(0, angle);
- }
-
- if ( type == OBJECT_RUINmobilet2 )
- {
- pos = RetPosition(0);
- pos.y -= 1.5f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)-0.3f;
- SetAngleX(0, angle);
-
- angle = RetAngleZ(0)+0.8f;
- SetAngleZ(0, angle);
- }
-
- if ( type == OBJECT_RUINmobiler1 )
- {
- pos = RetPosition(0);
- pos.y += 4.0f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)-Math::PI*0.6f;
- SetAngleX(0, angle);
-
- angle = RetAngleZ(0)-0.2f;
- SetAngleZ(0, angle);
- }
-
- if ( type == OBJECT_RUINmobiler2 )
- {
- pos = RetPosition(0);
- pos.y += 2.0f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)-0.1f;
- SetAngleX(0, angle);
-
- angle = RetAngleZ(0)-0.3f;
- SetAngleZ(0, angle);
- }
-
- if ( type == OBJECT_RUINdoor )
- {
- pos = RetPosition(0);
- pos.y -= 0.5f;
- SetPosition(0, pos);
-
- angle = RetAngleZ(0)-0.1f;
- SetAngleZ(0, angle);
- }
-
- if ( type == OBJECT_RUINsupport )
- {
- pos = RetPosition(0);
- pos.y += 0.5f;
- SetPosition(0, pos);
-
-//? angle = RetAngleY(0)+0.1f;
-//? SetAngleY(0, angle);
-
- angle = RetAngleX(0)+0.1f;
- SetAngleX(0, angle);
-
- angle = RetAngleZ(0)+0.1f;
- SetAngleZ(0, angle);
- }
-
- if ( type == OBJECT_RUINradar )
- {
- pos = RetPosition(0);
- pos.y -= 0.5f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)+0.15f;
- SetAngleX(0, angle);
-
- angle = RetAngleZ(0)+0.1f;
- SetAngleZ(0, angle);
- }
-
- if ( type == OBJECT_RUINconvert )
- {
- pos = RetPosition(0);
- pos.y -= 1.0f;
- SetPosition(0, pos);
- }
-
- if ( type == OBJECT_RUINbase )
- {
- pos = RetPosition(0);
- pos.y -= 1.0f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)+0.15f;
- SetAngleX(0, angle);
- }
-
- if ( type == OBJECT_RUINhead )
- {
- pos = RetPosition(0);
- pos.y += 8.0f;
- SetPosition(0, pos);
-
- angle = RetAngleX(0)+Math::PI*0.4f;
- SetAngleX(0, angle);
- }
-
- delete pModFile;
- return true;
-}
-
-// Creates a gadget apollo.
-
-bool CObject::CreateApollo(Math::Vector pos, float angle, ObjectType type)
-{
- CModFile* pModFile;
- int rank, i;
-
- if ( m_engine->RetRestCreate() < 6 ) return false;
-
- pModFile = new CModFile(m_iMan);
-
- SetType(type);
-
- if ( type == OBJECT_APOLLO1 ) // LEM ?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\apollol1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetZoom(0, 1.2f);
- SetFloorHeight(0.0f);
-
- for ( i=0 ; i<4 ; i++ ) // creates feet
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(i+1, rank);
- SetObjectParent(i+1, 0);
- pModFile->ReadModel("objects\\apollol2.mod");
- pModFile->CreateEngineObject(rank);
- SetAngleY(i+1, Math::PI/2.0f*i);
- }
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(5, rank);
- SetObjectParent(5, 0);
- pModFile->ReadModel("objects\\apollol3.mod"); // ladder
- pModFile->CreateEngineObject(rank);
-
-//? m_terrain->AddBuildingLevel(pos, 10.0f, 13.0f, 12.0f, 0.0f);
-
- CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 11.0f, 5.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-11.0f, 5.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 5.0f, -11.0f), 3.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 0.0f, 5.0f, 11.0f), 3.0f, SOUND_BOUMm, 0.45f);
-
- SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 9.0f);
-
- CreateShadowCircle(16.0f, 0.5f);
- }
-
- if ( type == OBJECT_APOLLO2 ) // jeep
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); //it is a stationary object
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\apolloj1.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- // Wheels.
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(-5.75f, 1.65f, -5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(2, rank);
- SetObjectParent(2, 0);
- pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- SetPosition(2, Math::Vector(-5.75f, 1.65f, 5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(3, rank);
- SetObjectParent(3, 0);
- pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- SetPosition(3, Math::Vector(5.75f, 1.65f, -5.0f));
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(4, rank);
- SetObjectParent(4, 0);
- pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
- pModFile->CreateEngineObject(rank);
- SetPosition(4, Math::Vector(5.75f, 1.65f, 5.0f));
-
- // Accessories:
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(5, rank);
- SetObjectParent(5, 0);
- pModFile->ReadModel("objects\\apolloj2.mod"); // antenna
- pModFile->CreateEngineObject(rank);
- SetPosition(5, Math::Vector(5.5f, 8.8f, 2.0f));
- SetAngleY(5, -120.0f*Math::PI/180.0f);
- SetAngleZ(5, 45.0f*Math::PI/180.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(6, rank);
- SetObjectParent(6, 0);
- pModFile->ReadModel("objects\\apolloj3.mod"); // camera
- pModFile->CreateEngineObject(rank);
- SetPosition(6, Math::Vector(5.5f, 2.8f, -2.0f));
- SetAngleY(6, 30.0f*Math::PI/180.0f);
-
- CreateCrashSphere(Math::Vector( 3.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector(-3.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
- CreateCrashSphere(Math::Vector( 7.0f, 9.0f, 2.0f), 2.0f, SOUND_BOUMm, 0.20f);
-
- CreateShadowCircle(7.0f, 0.8f);
-
- FloorAdjust();
- }
-
- if ( type == OBJECT_APOLLO3 ) // flag?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\apollof.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- SetJotlerSphere(Math::Vector(0.0f, 4.0f, 0.0f), 1.0f);
- CreateShadowCircle(2.0f, 0.3f);
- }
-
- if ( type == OBJECT_APOLLO4 ) // module?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\apollom.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 2.0f, SOUND_BOUMm, 0.45f);
- CreateShadowCircle(5.0f, 0.8f);
-
- FloorAdjust();
- }
-
- if ( type == OBJECT_APOLLO5 ) // antenna?
- {
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
- SetObjectRank(0, rank);
- pModFile->ReadModel("objects\\apolloa.mod");
- pModFile->CreateEngineObject(rank);
- SetPosition(0, pos);
- SetAngleY(0, angle);
- SetFloorHeight(0.0f);
-
- rank = m_engine->CreateObject();
- m_engine->SetObjectType(rank, TYPEDESCENDANT);
- SetObjectRank(1, rank);
- SetObjectParent(1, 0);
- pModFile->ReadModel("objects\\apolloj2.mod"); // antenna
- pModFile->CreateEngineObject(rank);
- SetPosition(1, Math::Vector(0.0f, 5.0f, 0.0f));
- SetAngleY(1, -120.0f*Math::PI/180.0f);
- SetAngleZ(1, 45.0f*Math::PI/180.0f);
-
- CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.35f);
- CreateShadowCircle(3.0f, 0.7f);
- }
-
- CreateOtherObject(type);
-
- pos = RetPosition(0);
- SetPosition(0, pos); // to display the shadows immediately
-
- delete pModFile;
- return true;
-}
-
-// Creates all sub-objects for managing the object.
-
-void CObject::CreateOtherObject(ObjectType type)
-{
- if ( type == OBJECT_BASE )
- {
- m_auto = new CAutoBase(m_iMan, this);
- }
- if ( type == OBJECT_PORTICO )
- {
- m_auto = new CAutoPortico(m_iMan, this);
- }
- if ( type == OBJECT_DERRICK )
- {
- m_auto = new CAutoDerrick(m_iMan, this);
- }
- if ( type == OBJECT_FACTORY )
- {
- m_auto = new CAutoFactory(m_iMan, this);
- }
- if ( type == OBJECT_REPAIR )
- {
- m_auto = new CAutoRepair(m_iMan, this);
- }
- if ( type == OBJECT_DESTROYER )
- {
- m_auto = new CAutoDestroyer(m_iMan, this);
- }
- if ( type == OBJECT_STATION )
- {
- m_auto = new CAutoStation(m_iMan, this);
- }
- if ( type == OBJECT_CONVERT )
- {
- m_auto = new CAutoConvert(m_iMan, this);
- }
- if ( type == OBJECT_TOWER )
- {
- m_auto = new CAutoTower(m_iMan, this);
- }
- if ( type == OBJECT_RESEARCH )
- {
- m_auto = new CAutoResearch(m_iMan, this);
- }
- if ( type == OBJECT_RADAR )
- {
- m_auto = new CAutoRadar(m_iMan, this);
- }
- if ( type == OBJECT_INFO )
- {
- m_auto = new CAutoInfo(m_iMan, this);
- }
- if ( type == OBJECT_ENERGY )
- {
- m_auto = new CAutoEnergy(m_iMan, this);
- }
- if ( type == OBJECT_LABO )
- {
- m_auto = new CAutoLabo(m_iMan, this);
- }
- if ( type == OBJECT_NUCLEAR )
- {
- m_auto = new CAutoNuclear(m_iMan, this);
- }
- if ( type == OBJECT_PARA )
- {
- m_auto = new CAutoPara(m_iMan, this);
- }
- if ( type == OBJECT_SAFE )
- {
- m_auto = new CAutoSafe(m_iMan, this);
- }
- if ( type == OBJECT_HUSTON )
- {
- m_auto = new CAutoHuston(m_iMan, this);
- }
- if ( type == OBJECT_EGG )
- {
- m_auto = new CAutoEgg(m_iMan, this);
- }
- if ( type == OBJECT_NEST )
- {
- m_auto = new CAutoNest(m_iMan, this);
- }
- if ( type == OBJECT_ROOT5 )
- {
- m_auto = new CAutoRoot(m_iMan, this);
- }
- if ( type == OBJECT_MUSHROOM2 )
- {
- m_auto = new CAutoMush(m_iMan, this);
- }
- if ( type == OBJECT_FLAGb ||
- type == OBJECT_FLAGr ||
- type == OBJECT_FLAGg ||
- type == OBJECT_FLAGy ||
- type == OBJECT_FLAGv )
- {
- m_auto = new CAutoFlag(m_iMan, this);
- }
- if ( type == OBJECT_TEEN36 || // trunk?
- type == OBJECT_TEEN37 || // boat?
- type == OBJECT_TEEN38 ) // fan?
- {
- m_auto = new CAutoKid(m_iMan, this);
- }
-}
-
-
-// Reads a program.
-
-bool CObject::ReadProgram(int rank, char* filename)
-{
- if ( m_brain != 0 )
- {
- return m_brain->ReadProgram(rank, filename);
- }
- return false;
-}
-
-// Writes a program.
-
-bool CObject::WriteProgram(int rank, char* filename)
-{
- if ( m_brain != 0 )
- {
- return m_brain->WriteProgram(rank, filename);
- }
- return false;
-}
-
-// Starts a program.
-
-bool CObject::RunProgram(int rank)
-{
- if ( m_brain != 0 )
- {
- m_brain->RunProgram(rank);
- return true;
- }
- if ( m_auto != 0 )
- {
- m_auto->Start(rank);
- return true;
- }
- return false;
-}
-
-
-
-
-// Calculates the matrix for transforming the object.
-// Returns true if the matrix has changed.
-// The rotations occur in the order Y, Z and X.
-
-bool CObject::UpdateTransformObject(int part, bool bForceUpdate)
-{
- Math::Vector position, angle, eye;
- bool bModif = false;
- int parent;
-
- if ( m_truck != 0 ) // transported by truck?
- {
- m_objectPart[part].bTranslate = true;
- m_objectPart[part].bRotate = true;
- }
-
- if ( !bForceUpdate &&
- !m_objectPart[part].bTranslate &&
- !m_objectPart[part].bRotate ) return false;
-
- position = m_objectPart[part].position;
- angle = m_objectPart[part].angle;
-
- if ( part == 0 ) // main part?
- {
- position += m_linVibration;
- angle += m_cirVibration+m_inclinaison;
- }
-
- if ( m_objectPart[part].bTranslate ||
- m_objectPart[part].bRotate )
- {
- if ( m_objectPart[part].bTranslate )
- {
- m_objectPart[part].matTranslate.LoadIdentity();
- m_objectPart[part].matTranslate.Set(1, 4, position.x);
- m_objectPart[part].matTranslate.Set(2, 4, position.y);
- m_objectPart[part].matTranslate.Set(3, 4, position.z);
- }
-
- if ( m_objectPart[part].bRotate )
- {
- Math::LoadRotationZXYMatrix(m_objectPart[part].matRotate, angle);
- }
-
- if ( m_objectPart[part].bZoom )
- {
- Math::Matrix mz;
- mz.LoadIdentity();
- mz.Set(1, 1, m_objectPart[part].zoom.x);
- mz.Set(2, 2, m_objectPart[part].zoom.y);
- mz.Set(3, 3, m_objectPart[part].zoom.z);
- m_objectPart[part].matTransform = Math::MultiplyMatrices(m_objectPart[part].matTranslate,
- Math::MultiplyMatrices(m_objectPart[part].matRotate, mz));
- }
- else
- {
- m_objectPart[part].matTransform = Math::MultiplyMatrices(m_objectPart[part].matTranslate,
- m_objectPart[part].matRotate);
- }
- bModif = true;
- }
-
- if ( bForceUpdate ||
- m_objectPart[part].bTranslate ||
- m_objectPart[part].bRotate )
- {
- parent = m_objectPart[part].parentPart;
-
- if ( part == 0 && m_truck != 0 ) // transported by a truck?
- {
- Math::Matrix* matWorldTruck;
- matWorldTruck = m_truck->RetWorldMatrix(m_truckLink);
- m_objectPart[part].matWorld = Math::MultiplyMatrices(*matWorldTruck,
- m_objectPart[part].matTransform);
- }
- else
- {
- if ( parent == -1 ) // no parent?
- {
- m_objectPart[part].matWorld = m_objectPart[part].matTransform;
- }
- else
- {
- m_objectPart[part].matWorld = Math::MultiplyMatrices(m_objectPart[parent].matWorld,
- m_objectPart[part].matTransform);
- }
- }
- bModif = true;
- }
-
- if ( bModif )
- {
- m_engine->SetObjectTransform(m_objectPart[part].object,
- m_objectPart[part].matWorld);
- }
-
- m_objectPart[part].bTranslate = false;
- m_objectPart[part].bRotate = false;
-
- return bModif;
-}
-
-// Updates all matrices to transform the object father and all his sons.
-// Assume a maximum of 4 degrees of freedom.
-// Appropriate, for example, to a body, an arm, forearm, hand and fingers.
-
-bool CObject::UpdateTransformObject()
-{
- bool bUpdate1, bUpdate2, bUpdate3, bUpdate4;
- int level1, level2, level3, level4, rank;
- int parent1, parent2, parent3, parent4;
-
- if ( m_bFlat )
- {
- for ( level1=0 ; level1<m_totalPart ; level1++ )
- {
- if ( !m_objectPart[level1].bUsed ) continue;
- UpdateTransformObject(level1, false);
- }
- }
- else
- {
- parent1 = 0;
- bUpdate1 = UpdateTransformObject(parent1, false);
-
- for ( level1=0 ; level1<m_totalPart ; level1++ )
- {
- rank = SearchDescendant(parent1, level1);
- if ( rank == -1 ) break;
-
- parent2 = rank;
- bUpdate2 = UpdateTransformObject(rank, bUpdate1);
-
- for ( level2=0 ; level2<m_totalPart ; level2++ )
- {
- rank = SearchDescendant(parent2, level2);
- if ( rank == -1 ) break;
-
- parent3 = rank;
- bUpdate3 = UpdateTransformObject(rank, bUpdate2);
-
- for ( level3=0 ; level3<m_totalPart ; level3++ )
- {
- rank = SearchDescendant(parent3, level3);
- if ( rank == -1 ) break;
-
- parent4 = rank;
- bUpdate4 = UpdateTransformObject(rank, bUpdate3);
-
- for ( level4=0 ; level4<m_totalPart ; level4++ )
- {
- rank = SearchDescendant(parent4, level4);
- if ( rank == -1 ) break;
-
- UpdateTransformObject(rank, bUpdate4);
- }
- }
- }
- }
- }
-
- return true;
-}
-
-
-// Puts all the progeny flat (there is more than fathers).
-// This allows for debris independently from each other in all directions.
-
-void CObject::FlatParent()
-{
- int i;
-
- for ( i=0 ; i<m_totalPart ; i++ )
- {
- m_objectPart[i].position.x = m_objectPart[i].matWorld.Get(1, 4);
- m_objectPart[i].position.y = m_objectPart[i].matWorld.Get(2, 4);
- m_objectPart[i].position.z = m_objectPart[i].matWorld.Get(3, 4);
-
- m_objectPart[i].matWorld.Set(1, 4, 0.0f);
- m_objectPart[i].matWorld.Set(2, 4, 0.0f);
- m_objectPart[i].matWorld.Set(3, 4, 0.0f);
-
- m_objectPart[i].matTranslate.Set(1, 4, 0.0f);
- m_objectPart[i].matTranslate.Set(2, 4, 0.0f);
- m_objectPart[i].matTranslate.Set(3, 4, 0.0f);
-
- m_objectPart[i].parentPart = -1; // more parents
- }
-
- m_bFlat = true;
-}
-
-
-
-// Updates the mapping of the texture of the pile.
-
-void CObject::UpdateEnergyMapping()
-{
- D3DMATERIAL7 mat;
- float a, b, i, s, au, bu;
- float limit[6];
- int j;
-
- if ( fabs(m_energy-m_lastEnergy) < 0.01f ) return;
- m_lastEnergy = m_energy;
-
- ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
- 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;
-
- if ( m_type == OBJECT_POWER ||
- m_type == OBJECT_ATOMIC )
- {
- a = 2.0f;
- b = 0.0f; // dimensions of the battery (according to y)
- }
- if ( m_type == OBJECT_STATION )
- {
- a = 10.0f;
- b = 4.0f; // dimensions of the battery (according to y)
- }
- if ( m_type == OBJECT_ENERGY )
- {
- a = 9.0f;
- b = 3.0f; // dimensions of the battery (according to y)
- }
-
- i = 0.50f+0.25f*m_energy; // origin
- s = i+0.25f; // width
-
- au = (s-i)/(b-a);
- bu = s-b*(s-i)/(b-a);
-
- limit[0] = 0.0f;
- limit[1] = m_engine->RetLimitLOD(0);
- limit[2] = limit[1];
- limit[3] = m_engine->RetLimitLOD(1);
- limit[4] = limit[3];
- limit[5] = 1000000.0f;
-
- for ( j=0 ; j<3 ; j++ )
- {
- m_engine->ChangeTextureMapping(m_objectPart[0].object,
- mat, D3DSTATEPART3, "lemt.tga", "",
- limit[j*2+0], limit[j*2+1], D3DMAPPING1Y,
- au, bu, 1.0f, 0.0f);
- }
-}
-
-
-// Manual action.
-
-bool CObject::EventProcess(const Event &event)
-{
- if ( event.event == EVENT_KEYDOWN )
- {
-#if ADJUST_ONBOARD
- if ( m_bSelect )
- {
- if ( event.param == 'E' ) debug_x += 0.1f;
- if ( event.param == 'D' ) debug_x -= 0.1f;
- if ( event.param == 'R' ) debug_y += 0.1f;
- if ( event.param == 'F' ) debug_y -= 0.1f;
- if ( event.param == 'T' ) debug_z += 0.1f;
- if ( event.param == 'G' ) debug_z -= 0.1f;
- }
-#endif
-#if ADJUST_ARM
- if ( m_bSelect )
- {
- if ( event.param == 'X' ) debug_arm1 += 5.0f*Math::PI/180.0f;
- if ( event.param == 'C' ) debug_arm1 -= 5.0f*Math::PI/180.0f;
- if ( event.param == 'V' ) debug_arm2 += 5.0f*Math::PI/180.0f;
- if ( event.param == 'B' ) debug_arm2 -= 5.0f*Math::PI/180.0f;
- if ( event.param == 'N' ) debug_arm3 += 5.0f*Math::PI/180.0f;
- if ( event.param == 'M' ) debug_arm3 -= 5.0f*Math::PI/180.0f;
- if ( event.param == 'X' ||
- event.param == 'C' ||
- event.param == 'V' ||
- event.param == 'B' ||
- event.param == 'N' ||
- event.param == 'M' )
- {
- SetAngleZ(1, debug_arm1);
- SetAngleZ(2, debug_arm2);
- SetAngleZ(3, debug_arm3);
- char s[100];
- sprintf(s, "a=%.2f b=%.2f c=%.2f", debug_arm1*180.0f/Math::PI, debug_arm2*180.0f/Math::PI, debug_arm3*180.0f/Math::PI);
- m_engine->SetInfoText(5, s);
- }
- }
-#endif
- }
-
- if ( m_physics != 0 )
- {
- if ( !m_physics->EventProcess(event) ) // object destroyed?
- {
- if ( RetSelect() &&
- m_type != OBJECT_ANT &&
- m_type != OBJECT_SPIDER &&
- m_type != OBJECT_BEE )
- {
- if ( !m_bDead ) m_camera->SetType(CAMERA_EXPLO);
- m_main->DeselectAll();
- }
- return false;
- }
- }
-
- if ( m_auto != 0 )
- {
- m_auto->EventProcess(event);
-
- if ( event.event == EVENT_FRAME &&
- m_auto->IsEnded() != ERR_CONTINUE )
- {
- m_auto->DeleteObject();
- delete m_auto;
- m_auto = 0;
- }
- }
-
- if ( m_motion != 0 )
- {
- m_motion->EventProcess(event);
- }
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- return true;
-}
-
-
-// Animates the object.
-
-bool CObject::EventFrame(const Event &event)
-{
- if ( m_type == OBJECT_HUMAN && m_main->RetMainMovie() == MM_SATCOMopen )
- {
- UpdateTransformObject();
- return true;
- }
-
- if ( m_type != OBJECT_SHOW && m_engine->RetPause() ) return true;
-
- m_aTime += event.rTime;
- m_shotTime += event.rTime;
-
- VirusFrame(event.rTime);
- PartiFrame(event.rTime);
-
- UpdateMapping();
- UpdateTransformObject();
- UpdateSelectParticule();
-
- if ( m_bProxyActivate ) // active if it is near?
- {
- CPyro* pyro;
- Math::Vector eye;
- float dist;
-
- eye = m_engine->RetLookatPt();
- dist = Math::Distance(eye, RetPosition(0));
- if ( dist < m_proxyDistance )
- {
- m_bProxyActivate = false;
- m_main->CreateShortcuts();
- m_sound->Play(SOUND_FINDING);
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FINDING, this, 0.0f);
- m_displayText->DisplayError(INFO_FINDING, this);
- }
- }
-
- return true;
-}
-
-// Updates the mapping of the object.
-
-void CObject::UpdateMapping()
-{
- if ( m_type == OBJECT_POWER ||
- m_type == OBJECT_ATOMIC ||
- m_type == OBJECT_STATION ||
- m_type == OBJECT_ENERGY )
- {
- UpdateEnergyMapping();
- }
-}
-
-
-// Management of viruses.
-
-void CObject::VirusFrame(float rTime)
-{
- ParticuleType type;
- Math::Vector pos, speed;
- Math::Point dim;
- int r;
-
- if ( !m_bVirusMode ) return; // healthy object?
-
- m_virusTime += rTime;
- if ( m_virusTime >= VIRUS_DELAY )
- {
- m_bVirusMode = false; // the virus is no longer active
- }
-
- if ( m_lastVirusParticule+m_engine->ParticuleAdapt(0.2f) <= m_aTime )
- {
- m_lastVirusParticule = m_aTime;
-
- r = rand()%10;
- if ( r == 0 ) type = PARTIVIRUS1;
- if ( r == 1 ) type = PARTIVIRUS2;
- if ( r == 2 ) type = PARTIVIRUS3;
- if ( r == 3 ) type = PARTIVIRUS4;
- if ( r == 4 ) type = PARTIVIRUS5;
- if ( r == 5 ) type = PARTIVIRUS6;
- if ( r == 6 ) type = PARTIVIRUS7;
- if ( r == 7 ) type = PARTIVIRUS8;
- if ( r == 8 ) type = PARTIVIRUS9;
- if ( r == 9 ) type = PARTIVIRUS10;
-
- pos = RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = Math::Rand()*4.0f+4.0f;
- dim.x = Math::Rand()*0.3f+0.3f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, type, 3.0f);
- }
-}
-
-// Management particles mistresses.
-
-void CObject::PartiFrame(float rTime)
-{
- Math::Vector pos, angle, factor;
- int i, channel;
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- if ( !m_objectPart[i].bUsed ) continue;
-
- channel = m_objectPart[i].masterParti;
- if ( channel == -1 ) continue;
-
- if ( !m_particule->GetPosition(channel, pos) )
- {
- m_objectPart[i].masterParti = -1; // particle no longer exists!
- continue;
- }
-
- SetPosition(i, pos);
-
- // Each song spins differently.
- switch( i%5 )
- {
- case 0: factor = Math::Vector( 0.5f, 0.3f, 0.6f); break;
- case 1: factor = Math::Vector(-0.3f, 0.4f,-0.2f); break;
- case 2: factor = Math::Vector( 0.4f,-0.6f,-0.3f); break;
- case 3: factor = Math::Vector(-0.6f,-0.2f, 0.0f); break;
- case 4: factor = Math::Vector( 0.4f, 0.1f,-0.7f); break;
- }
-
- angle = RetAngle(i);
- angle += rTime*Math::PI*factor;
- SetAngle(i, angle);
- }
-}
-
-
-// Changes the perspective to view if it was like in the vehicle,
-// or behind the vehicle.
-
-void CObject::SetViewFromHere(Math::Vector &eye, float &dirH, float &dirV,
- Math::Vector &lookat, Math::Vector &upVec,
- CameraType type)
-{
- float speed;
- int part;
-
- UpdateTransformObject();
-
- part = 0;
- if ( m_type == OBJECT_HUMAN ||
- m_type == OBJECT_TECH )
- {
- eye.x = -0.2f;
- eye.y = 3.3f;
- eye.z = 0.0f;
-//? eye.x = 1.0f;
-//? eye.y = 3.3f;
-//? eye.z = 0.0f;
- }
- else if ( m_type == OBJECT_MOBILErt ||
- m_type == OBJECT_MOBILErr ||
- m_type == OBJECT_MOBILErs )
- {
- eye.x = -1.1f; // on the cap
- eye.y = 7.9f;
- eye.z = 0.0f;
- }
- else if ( m_type == OBJECT_MOBILEwc ||
- m_type == OBJECT_MOBILEtc ||
- m_type == OBJECT_MOBILEfc ||
- m_type == OBJECT_MOBILEic ) // fireball?
- {
-//? eye.x = -0.9f; // on the cannon
-//? eye.y = 3.0f;
-//? eye.z = 0.0f;
-//? part = 1;
- eye.x = -0.9f; // on the cannon
- eye.y = 8.3f;
- eye.z = 0.0f;
- }
- else if ( m_type == OBJECT_MOBILEwi ||
- m_type == OBJECT_MOBILEti ||
- m_type == OBJECT_MOBILEfi ||
- m_type == OBJECT_MOBILEii ) // orgaball ?
- {
-//? eye.x = -3.5f; // on the cannon
-//? eye.y = 5.1f;
-//? eye.z = 0.0f;
-//? part = 1;
- eye.x = -2.5f; // on the cannon
- eye.y = 10.4f;
- eye.z = 0.0f;
- }
- else if ( m_type == OBJECT_MOBILErc )
- {
-//? eye.x = 2.0f; // in the cannon
-//? eye.y = 0.0f;
-//? eye.z = 0.0f;
-//? part = 2;
- eye.x = 4.0f; // on the cannon
- eye.y = 11.0f;
- eye.z = 0.0f;
- }
- else if ( m_type == OBJECT_MOBILEsa )
- {
- eye.x = 3.0f;
- eye.y = 4.5f;
- eye.z = 0.0f;
- }
- else if ( m_type == OBJECT_MOBILEdr )
- {
- eye.x = 1.0f;
- eye.y = 6.5f;
- eye.z = 0.0f;
- }
- else if ( m_type == OBJECT_APOLLO2 )
- {
- eye.x = -3.0f;
- eye.y = 6.0f;
- eye.z = -2.0f;
- }
- else
- {
- eye.x = 0.7f; // between the brackets
- eye.y = 4.8f;
- eye.z = 0.0f;
- }
-#if ADJUST_ONBOARD
- eye.x += debug_x;
- eye.y += debug_y;
- eye.z += debug_z;
- char s[100];
- sprintf(s, "x=%.2f y=%.2f z=%.2f", eye.x, eye.y, eye.z);
- m_engine->SetInfoText(4, s);
-#endif
-
- if ( type == CAMERA_BACK )
- {
- eye.x -= 20.0f;
- eye.y += 1.0f;
- }
-
- lookat.x = eye.x+1.0f;
- lookat.y = eye.y+0.0f;
- lookat.z = eye.z+0.0f;
-
- eye = Math::Transform(m_objectPart[part].matWorld, eye);
- lookat = Math::Transform(m_objectPart[part].matWorld, lookat);
-
- // Camera tilts when turning.
- upVec = Math::Vector(0.0f, 1.0f, 0.0f);
- if ( m_physics != 0 )
- {
- if ( m_physics->RetLand() ) // on ground?
- {
- speed = m_physics->RetLinMotionX(MO_REASPEED);
- lookat.y -= speed*0.002f;
-
- speed = m_physics->RetCirMotionY(MO_REASPEED);
- upVec.z -= speed*0.04f;
- }
- else // in flight?
- {
- speed = m_physics->RetLinMotionX(MO_REASPEED);
- lookat.y += speed*0.002f;
-
- speed = m_physics->RetCirMotionY(MO_REASPEED);
- upVec.z += speed*0.08f;
- }
- }
- upVec = Math::Transform(m_objectPart[0].matRotate, upVec);
-
- dirH = -(m_objectPart[part].angle.y+Math::PI/2.0f);
- dirV = 0.0f;
-
-}
-
-
-// Management of features.
-
-void CObject::SetCharacter(Character* character)
-{
- CopyMemory(&m_character, character, sizeof(Character));
-}
-
-void CObject::GetCharacter(Character* character)
-{
- CopyMemory(character, &m_character, sizeof(Character));
-}
-
-Character* CObject::RetCharacter()
-{
- return &m_character;
-}
-
-
-// Returns the absolute time.
-
-float CObject::RetAbsTime()
-{
- return m_aTime;
-}
-
-
-// Management of energy contained in a battery.
-// Single subject possesses the battery energy, but not the vehicle that carries the battery!
-
-void CObject::SetEnergy(float level)
-{
- if ( level < 0.0f ) level = 0.0f;
- if ( level > 1.0f ) level = 1.0f;
- m_energy = level;
-}
-
-float CObject::RetEnergy()
-{
- if ( m_type != OBJECT_POWER &&
- m_type != OBJECT_ATOMIC &&
- m_type != OBJECT_STATION &&
- m_type != OBJECT_ENERGY ) return 0.0f;
- return m_energy;
-}
-
-
-// Management of the capacity of a battery.
-// Single subject possesses a battery capacity,
-// but not the vehicle that carries the battery!
-
-void CObject::SetCapacity(float capacity)
-{
- m_capacity = capacity;
-}
-
-float CObject::RetCapacity()
-{
- return m_capacity;
-}
-
-
-// Management of the shield.
-
-void CObject::SetShield(float level)
-{
- m_shield = level;
-}
-
-float CObject::RetShield()
-{
- if ( m_type == OBJECT_FRET ||
- m_type == OBJECT_STONE ||
- m_type == OBJECT_URANIUM ||
- m_type == OBJECT_BULLET ||
- m_type == OBJECT_METAL ||
- m_type == OBJECT_BBOX ||
- m_type == OBJECT_KEYa ||
- m_type == OBJECT_KEYb ||
- m_type == OBJECT_KEYc ||
- m_type == OBJECT_KEYd ||
- m_type == OBJECT_TNT ||
- m_type == OBJECT_TEEN31 || // basket?
- m_type == OBJECT_SCRAP1 ||
- m_type == OBJECT_SCRAP2 ||
- m_type == OBJECT_SCRAP3 ||
- m_type == OBJECT_SCRAP4 ||
- m_type == OBJECT_SCRAP5 ||
- m_type == OBJECT_BOMB ||
- m_type == OBJECT_WAYPOINT ||
- m_type == OBJECT_FLAGb ||
- m_type == OBJECT_FLAGr ||
- m_type == OBJECT_FLAGg ||
- m_type == OBJECT_FLAGy ||
- m_type == OBJECT_FLAGv ||
- m_type == OBJECT_POWER ||
- m_type == OBJECT_ATOMIC ||
- m_type == OBJECT_ANT ||
- m_type == OBJECT_SPIDER ||
- m_type == OBJECT_BEE ||
- m_type == OBJECT_WORM ) return 0.0f;
- return m_shield;
-}
-
-
-// Management of flight range (zero = infinity).
-
-void CObject::SetRange(float delay)
-{
- m_range = delay;
-}
-
-float CObject::RetRange()
-{
- return m_range;
-}
-
-
-// Management of transparency of the object.
-
-void CObject::SetTransparency(float value)
-{
- int i;
-
- m_transparency = value;
-
- for ( i=0 ; i<m_totalPart ; i++ )
- {
- if ( m_objectPart[i].bUsed )
- {
- if ( m_type == OBJECT_BASE )
- {
- if ( i != 9 ) continue; // no central pillar?
- }
-
- m_engine->SetObjectTransparency(m_objectPart[i].object, value);
- }
- }
-}
-
-float CObject::RetTransparency()
-{
- return m_transparency;
-}
-
-
-// Management of the object matter.
-
-ObjectMaterial CObject::RetMaterial()
-{
- if ( m_type == OBJECT_HUMAN )
- {
- return OM_HUMAN;
- }
-
- if ( m_type == OBJECT_SCRAP4 ||
- m_type == OBJECT_SCRAP5 )
- {
- return OM_HUMAN;
- }
-
- return OM_METAL;
-}
-
-
-// Indicates whether the gadget is a nonessential.
-
-void CObject::SetGadget(bool bMode)
-{
- m_bGadget = bMode;
-}
-
-bool CObject::RetGadget()
-{
- return m_bGadget;
-}
-
-
-// Indicates whether an object is stationary (ant on the back).
-
-void CObject::SetFixed(bool bFixed)
-{
- m_bFixed = bFixed;
-}
-
-bool CObject::RetFixed()
-{
- return m_bFixed;
-}
-
-
-// Indicates whether an object is subjected to clipping (obstacles).
-
-void CObject::SetClip(bool bClip)
-{
- m_bClip = bClip;
-}
-
-bool CObject::RetClip()
-{
- return m_bClip;
-}
-
-
-
-// Pushes an object.
-
-bool CObject::JostleObject(float force)
-{
- CAutoJostle* pa;
-
- if ( m_type == OBJECT_FLAGb ||
- m_type == OBJECT_FLAGr ||
- m_type == OBJECT_FLAGg ||
- m_type == OBJECT_FLAGy ||
- m_type == OBJECT_FLAGv ) // flag?
- {
- if ( m_auto == 0 ) return false;
-
- m_auto->Start(1);
- }
- else
- {
- if ( m_auto != 0 ) return false;
-
- m_auto = new CAutoJostle(m_iMan, this);
- pa = (CAutoJostle*)m_auto;
- pa->Start(0, force);
- }
-
- return true;
-}
-
-
-// Beginning of the effect when the instruction "detect" is used.
-
-void CObject::StartDetectEffect(CObject *target, bool bFound)
-{
- Math::Matrix* mat;
- Math::Vector pos, goal;
- Math::Point dim;
-
- mat = RetWorldMatrix(0);
- pos = Math::Transform(*mat, Math::Vector(2.0f, 3.0f, 0.0f));
-
- if ( target == 0 )
- {
- goal = Math::Transform(*mat, Math::Vector(50.0f, 3.0f, 0.0f));
- }
- else
- {
- goal = target->RetPosition(0);
- goal.y += 3.0f;
- goal = Math::SegmentPoint(pos, goal, Math::Distance(pos, goal)-3.0f);
- }
-
- dim.x = 3.0f;
- dim.y = dim.x;
- m_particule->CreateRay(pos, goal, PARTIRAY2, dim, 0.2f);
-
- if ( target != 0 )
- {
- goal = target->RetPosition(0);
- goal.y += 3.0f;
- goal = Math::SegmentPoint(pos, goal, Math::Distance(pos, goal)-1.0f);
- dim.x = 6.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(goal, Math::Vector(0.0f, 0.0f, 0.0f), dim,
- bFound?PARTIGLINT:PARTIGLINTr, 0.5f);
- }
-
- m_sound->Play(bFound?SOUND_BUILD:SOUND_RECOVER);
-}
-
-
-// Management of time from which a virus is active.
-
-void CObject::SetVirusMode(bool bEnable)
-{
- m_bVirusMode = bEnable;
- m_virusTime = 0.0f;
-
- if ( m_bVirusMode && m_brain != 0 )
- {
- if ( !m_brain->IntroduceVirus() ) // tries to infect
- {
- m_bVirusMode = false; // program was not contaminated!
- }
- }
-}
-
-bool CObject::RetVirusMode()
-{
- return m_bVirusMode;
-}
-
-float CObject::RetVirusTime()
-{
- return m_virusTime;
-}
-
-
-// Management mode of the camera.
-
-void CObject::SetCameraType(CameraType type)
-{
- m_cameraType = type;
-}
-
-CameraType CObject::RetCameraType()
-{
- return m_cameraType;
-}
-
-void CObject::SetCameraDist(float dist)
-{
- m_cameraDist = dist;
-}
-
-float CObject::RetCameraDist()
-{
- return m_cameraDist;
-}
-
-void CObject::SetCameraLock(bool bLock)
-{
- m_bCameraLock = bLock;
-}
-
-bool CObject::RetCameraLock()
-{
- return m_bCameraLock;
-}
-
-
-
-// Management of the demonstration of the object.
-
-void CObject::SetHilite(bool bMode)
-{
- int list[OBJECTMAXPART+1];
- int i, j;
-
- m_bHilite = bMode;
-
- if ( m_bHilite )
- {
- j = 0;
- for ( i=0 ; i<m_totalPart ; i++ )
- {
- if ( m_objectPart[i].bUsed )
- {
- list[j++] = m_objectPart[i].object;
- }
- }
- list[j] = -1; // terminate
-
- m_engine->SetHiliteRank(list); // gives the list of selected parts
- }
-}
-
-bool CObject::RetHilite()
-{
- return m_bHilite;
-}
-
-
-// Indicates whether the object is selected or not.
-
-void CObject::SetSelect(bool bMode, bool bDisplayError)
-{
- Error err;
-
- m_bSelect = bMode;
-
- if ( m_physics != 0 )
- {
- m_physics->CreateInterface(m_bSelect);
- }
-
- if ( m_auto != 0 )
- {
- m_auto->CreateInterface(m_bSelect);
- }
-
- CreateSelectParticule(); // creates / removes particles
-
- if ( !m_bSelect )
- {
- SetGunGoalH(0.0f); // puts the cannon right
- return; // selects if not finished
- }
-
- err = ERR_OK;
- if ( m_physics != 0 )
- {
- err = m_physics->RetError();
- }
- if ( m_auto != 0 )
- {
- err = m_auto->RetError();
- }
- if ( err != ERR_OK && bDisplayError )
- {
- m_displayText->DisplayError(err, this);
- }
-}
-
-// Indicates whether the object is selected or not.
-
-bool CObject::RetSelect(bool bReal)
-{
- if ( !bReal && m_main->RetFixScene() ) return false;
- return m_bSelect;
-}
-
-
-// Indicates whether the object is selectable or not.
-
-void CObject::SetSelectable(bool bMode)
-{
- m_bSelectable = bMode;
-}
-
-// Indicates whether the object is selecionnable or not.
-
-bool CObject::RetSelectable()
-{
- return m_bSelectable;
-}
-
-
-// Management of the activities of an object.
-
-void CObject::SetActivity(bool bMode)
-{
- if ( m_brain != 0 )
- {
- m_brain->SetActivity(bMode);
- }
-}
-
-bool CObject::RetActivity()
-{
- if ( m_brain != 0 )
- {
- return m_brain->RetActivity();
- }
- return false;
-}
-
-
-// Indicates if necessary to check the tokens of the object.
-
-void CObject::SetCheckToken(bool bMode)
-{
- m_bCheckToken = bMode;
-}
-
-// Indicates if necessary to check the tokens of the object.
-
-bool CObject::RetCheckToken()
-{
- return m_bCheckToken;
-}
-
-
-// Management of the visibility of an object.
-// The object is not hidden or visually disabled, but ignores detections!
-// For example: underground worm.
-
-void CObject::SetVisible(bool bVisible)
-{
- m_bVisible = bVisible;
-}
-
-bool CObject::RetVisible()
-{
- return m_bVisible;
-}
-
-
-// Management mode of operation of an object.
-// An inactive object is an object destroyed, nonexistent.
-// This mode is used for objects "resetables"
-// during training to simulate destruction.
-
-void CObject::SetEnable(bool bEnable)
-{
- m_bEnable = bEnable;
-}
-
-bool CObject::RetEnable()
-{
- return m_bEnable;
-}
-
-
-// Management mode or an object is only active when you're close.
-
-void CObject::SetProxyActivate(bool bActivate)
-{
- m_bProxyActivate = bActivate;
-}
-
-bool CObject::RetProxyActivate()
-{
- return m_bProxyActivate;
-}
-
-void CObject::SetProxyDistance(float distance)
-{
- m_proxyDistance = distance;
-}
-
-float CObject::RetProxyDistance()
-{
- return m_proxyDistance;
-}
-
-
-// Management of the method of increasing damage.
-
-void CObject::SetMagnifyDamage(float factor)
-{
- m_magnifyDamage = factor;
-}
-
-float CObject::RetMagnifyDamage()
-{
- return m_magnifyDamage;
-}
-
-
-// Management of free parameter.
-
-void CObject::SetParam(float value)
-{
- m_param = value;
-}
-
-float CObject::RetParam()
-{
- return m_param;
-}
-
-
-// Management of the mode "blocked" of an object.
-// For example, a cube of titanium is blocked while it is used to make something,
-//or a vehicle is blocked as its construction is not finished.
-
-void CObject::SetLock(bool bLock)
-{
- m_bLock = bLock;
-}
-
-bool CObject::RetLock()
-{
- return m_bLock;
-}
-
-// Management of the mode "current explosion" of an object.
-// An object in this mode is not saving.
-
-void CObject::SetExplo(bool bExplo)
-{
- m_bExplo = bExplo;
-}
-
-bool CObject::RetExplo()
-{
- return m_bExplo;
-}
-
-
-// Mode management "cargo ship" during movies.
-
-void CObject::SetCargo(bool bCargo)
-{
- m_bCargo = bCargo;
-}
-
-bool CObject::RetCargo()
-{
- return m_bCargo;
-}
-
-
-// Management of the HS mode of an object.
-
-void CObject::SetBurn(bool bBurn)
-{
- m_bBurn = bBurn;
-
-//? if ( m_botVar != 0 )
-//? {
-//? if ( m_bBurn ) m_botVar->SetUserPtr(OBJECTDELETED);
-//? else m_botVar->SetUserPtr(this);
-//? }
-}
-
-bool CObject::RetBurn()
-{
- return m_bBurn;
-}
-
-void CObject::SetDead(bool bDead)
-{
- m_bDead = bDead;
-
- if ( bDead && m_brain != 0 )
- {
- m_brain->StopProgram(); // stops the current task
- }
-
-//? if ( m_botVar != 0 )
-//? {
-//? if ( m_bDead ) m_botVar->SetUserPtr(OBJECTDELETED);
-//? else m_botVar->SetUserPtr(this);
-//? }
-}
-
-bool CObject::RetDead()
-{
- return m_bDead;
-}
-
-bool CObject::RetRuin()
-{
- return m_bBurn|m_bFlat;
-}
-
-bool CObject::RetActif()
-{
- return !m_bLock && !m_bBurn && !m_bFlat && m_bVisible && m_bEnable;
-}
-
-
-// Management of the point of aim.
-
-void CObject::SetGunGoalV(float gunGoal)
-{
- if ( m_type == OBJECT_MOBILEfc ||
- m_type == OBJECT_MOBILEtc ||
- m_type == OBJECT_MOBILEwc ||
- m_type == OBJECT_MOBILEic ) // fireball?
- {
- if ( gunGoal > 10.0f*Math::PI/180.0f ) gunGoal = 10.0f*Math::PI/180.0f;
- if ( gunGoal < -20.0f*Math::PI/180.0f ) gunGoal = -20.0f*Math::PI/180.0f;
- SetAngleZ(1, gunGoal);
- }
- else if ( m_type == OBJECT_MOBILEfi ||
- m_type == OBJECT_MOBILEti ||
- m_type == OBJECT_MOBILEwi ||
- m_type == OBJECT_MOBILEii ) // orgaball?
- {
- if ( gunGoal > 20.0f*Math::PI/180.0f ) gunGoal = 20.0f*Math::PI/180.0f;
- if ( gunGoal < -20.0f*Math::PI/180.0f ) gunGoal = -20.0f*Math::PI/180.0f;
- SetAngleZ(1, gunGoal);
- }
- else if ( m_type == OBJECT_MOBILErc ) // phazer?
- {
- if ( gunGoal > 45.0f*Math::PI/180.0f ) gunGoal = 45.0f*Math::PI/180.0f;
- if ( gunGoal < -20.0f*Math::PI/180.0f ) gunGoal = -20.0f*Math::PI/180.0f;
- SetAngleZ(2, gunGoal);
- }
- else
- {
- gunGoal = 0.0f;
- }
-
- m_gunGoalV = gunGoal;
-}
-
-void CObject::SetGunGoalH(float gunGoal)
-{
- if ( m_type == OBJECT_MOBILEfc ||
- m_type == OBJECT_MOBILEtc ||
- m_type == OBJECT_MOBILEwc ||
- m_type == OBJECT_MOBILEic ) // fireball?
- {
- if ( gunGoal > 40.0f*Math::PI/180.0f ) gunGoal = 40.0f*Math::PI/180.0f;
- if ( gunGoal < -40.0f*Math::PI/180.0f ) gunGoal = -40.0f*Math::PI/180.0f;
- SetAngleY(1, gunGoal);
- }
- else if ( m_type == OBJECT_MOBILEfi ||
- m_type == OBJECT_MOBILEti ||
- m_type == OBJECT_MOBILEwi ||
- m_type == OBJECT_MOBILEii ) // orgaball?
- {
- if ( gunGoal > 40.0f*Math::PI/180.0f ) gunGoal = 40.0f*Math::PI/180.0f;
- if ( gunGoal < -40.0f*Math::PI/180.0f ) gunGoal = -40.0f*Math::PI/180.0f;
- SetAngleY(1, gunGoal);
- }
- else if ( m_type == OBJECT_MOBILErc ) // phazer?
- {
- if ( gunGoal > 40.0f*Math::PI/180.0f ) gunGoal = 40.0f*Math::PI/180.0f;
- if ( gunGoal < -40.0f*Math::PI/180.0f ) gunGoal = -40.0f*Math::PI/180.0f;
- SetAngleY(2, gunGoal);
- }
- else
- {
- gunGoal = 0.0f;
- }
-
- m_gunGoalH = gunGoal;
-}
-
-float CObject::RetGunGoalV()
-{
- return m_gunGoalV;
-}
-
-float CObject::RetGunGoalH()
-{
- return m_gunGoalH;
-}
-
-
-
-// Shows the limits of the object.
-
-bool CObject::StartShowLimit()
-{
- if ( m_showLimitRadius == 0.0f ) return false;
-
- m_main->SetShowLimit(0, PARTILIMIT1, this, RetPosition(0), m_showLimitRadius);
- m_bShowLimit = true;
- return true;
-}
-
-void CObject::StopShowLimit()
-{
- m_bShowLimit = false;
-}
-
-
-
-// Indicates whether a program is under execution.
-
-bool CObject::IsProgram()
-{
- if ( m_brain == 0 ) return false;
- return m_brain->IsProgram();
-}
-
-
-// Creates or removes particles associated to the object.
-
-void CObject::CreateSelectParticule()
-{
- Math::Vector pos, speed;
- Math::Point dim;
- int i;
-
- // Removes particles preceding.
- for ( i=0 ; i<4 ; i++ )
- {
- if ( m_partiSel[i] != -1 )
- {
- m_particule->DeleteParticule(m_partiSel[i]);
- m_partiSel[i] = -1;
- }
- }
-
- if ( m_bSelect || IsProgram() )
- {
- // Creates particles lens for the headlights.
- if ( m_type == OBJECT_MOBILEfa ||
- m_type == OBJECT_MOBILEta ||
- m_type == OBJECT_MOBILEwa ||
- m_type == OBJECT_MOBILEia ||
- m_type == OBJECT_MOBILEfc ||
- m_type == OBJECT_MOBILEtc ||
- m_type == OBJECT_MOBILEwc ||
- m_type == OBJECT_MOBILEic ||
- m_type == OBJECT_MOBILEfi ||
- m_type == OBJECT_MOBILEti ||
- m_type == OBJECT_MOBILEwi ||
- m_type == OBJECT_MOBILEii ||
- m_type == OBJECT_MOBILEfs ||
- m_type == OBJECT_MOBILEts ||
- m_type == OBJECT_MOBILEws ||
- m_type == OBJECT_MOBILEis ||
- m_type == OBJECT_MOBILErt ||
- m_type == OBJECT_MOBILErc ||
- m_type == OBJECT_MOBILErr ||
- m_type == OBJECT_MOBILErs ||
- m_type == OBJECT_MOBILEsa ||
- m_type == OBJECT_MOBILEtg ||
- m_type == OBJECT_MOBILEft ||
- m_type == OBJECT_MOBILEtt ||
- m_type == OBJECT_MOBILEwt ||
- m_type == OBJECT_MOBILEit ||
- m_type == OBJECT_MOBILEdr ) // vehicle?
- {
- pos = Math::Vector(0.0f, 0.0f, 0.0f);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 0.0f;
- dim.y = 0.0f;
- m_partiSel[0] = m_particule->CreateParticule(pos, speed, dim, PARTISELY, 1.0f, 0.0f, 0.0f);
- m_partiSel[1] = m_particule->CreateParticule(pos, speed, dim, PARTISELY, 1.0f, 0.0f, 0.0f);
- m_partiSel[2] = m_particule->CreateParticule(pos, speed, dim, PARTISELR, 1.0f, 0.0f, 0.0f);
- m_partiSel[3] = m_particule->CreateParticule(pos, speed, dim, PARTISELR, 1.0f, 0.0f, 0.0f);
- UpdateSelectParticule();
- }
- }
-}
-
-// Updates the particles associated to the object.
-
-void CObject::UpdateSelectParticule()
-{
- Math::Vector pos[4];
- Math::Point dim[4];
- float zoom[4];
- float angle;
- int i;
-
- if ( !m_bSelect && !IsProgram() ) return;
-
- dim[0].x = 1.0f;
- dim[1].x = 1.0f;
- dim[2].x = 1.2f;
- dim[3].x = 1.2f;
-
- // Lens front yellow.
- if ( m_type == OBJECT_MOBILErt ||
- m_type == OBJECT_MOBILErc ||
- m_type == OBJECT_MOBILErr ||
- m_type == OBJECT_MOBILErs ) // large caterpillars?
- {
- pos[0] = Math::Vector(4.2f, 2.8f, 1.5f);
- pos[1] = Math::Vector(4.2f, 2.8f, -1.5f);
- dim[0].x = 1.5f;
- dim[1].x = 1.5f;
- }
- else if ( m_type == OBJECT_MOBILEwt ||
- m_type == OBJECT_MOBILEtt ||
- m_type == OBJECT_MOBILEft ||
- m_type == OBJECT_MOBILEit ) // trainer ?
- {
- pos[0] = Math::Vector(4.2f, 2.5f, 1.2f);
- pos[1] = Math::Vector(4.2f, 2.5f, -1.2f);
- dim[0].x = 1.5f;
- dim[1].x = 1.5f;
- }
- else if ( m_type == OBJECT_MOBILEsa ) // submarine?
- {
- pos[0] = Math::Vector(3.6f, 4.0f, 2.0f);
- pos[1] = Math::Vector(3.6f, 4.0f, -2.0f);
- }
- else if ( m_type == OBJECT_MOBILEtg ) // target?
- {
- pos[0] = Math::Vector(3.4f, 6.5f, 2.0f);
- pos[1] = Math::Vector(3.4f, 6.5f, -2.0f);
- }
- else if ( m_type == OBJECT_MOBILEdr ) // designer?
- {
- pos[0] = Math::Vector(4.9f, 3.5f, 2.5f);
- pos[1] = Math::Vector(4.9f, 3.5f, -2.5f);
- }
- else
- {
- pos[0] = Math::Vector(4.2f, 2.5f, 1.5f);
- pos[1] = Math::Vector(4.2f, 2.5f, -1.5f);
- }
-
- // Red back lens
- if ( m_type == OBJECT_MOBILEfa ||
- m_type == OBJECT_MOBILEfc ||
- m_type == OBJECT_MOBILEfi ||
- m_type == OBJECT_MOBILEfs ||
- m_type == OBJECT_MOBILEft ) // flying?
- {
- pos[2] = Math::Vector(-4.0f, 3.1f, 4.5f);
- pos[3] = Math::Vector(-4.0f, 3.1f, -4.5f);
- dim[2].x = 0.6f;
- dim[3].x = 0.6f;
- }
- if ( m_type == OBJECT_MOBILEwa ||
- m_type == OBJECT_MOBILEwc ||
- m_type == OBJECT_MOBILEwi ||
- m_type == OBJECT_MOBILEws ) // wheels?
- {
- pos[2] = Math::Vector(-4.5f, 2.7f, 2.8f);
- pos[3] = Math::Vector(-4.5f, 2.7f, -2.8f);
- }
- if ( m_type == OBJECT_MOBILEwt ) // wheels?
- {
- pos[2] = Math::Vector(-4.0f, 2.5f, 2.2f);
- pos[3] = Math::Vector(-4.0f, 2.5f, -2.2f);
- }
- if ( m_type == OBJECT_MOBILEia ||
- m_type == OBJECT_MOBILEic ||
- m_type == OBJECT_MOBILEii ||
- m_type == OBJECT_MOBILEis ||
- m_type == OBJECT_MOBILEit ) // legs?
- {
- pos[2] = Math::Vector(-4.5f, 2.7f, 2.8f);
- pos[3] = Math::Vector(-4.5f, 2.7f, -2.8f);
- }
- if ( m_type == OBJECT_MOBILEta ||
- m_type == OBJECT_MOBILEtc ||
- m_type == OBJECT_MOBILEti ||
- m_type == OBJECT_MOBILEts ||
- m_type == OBJECT_MOBILEtt ) // caterpillars?
- {
- pos[2] = Math::Vector(-3.6f, 4.2f, 3.0f);
- pos[3] = Math::Vector(-3.6f, 4.2f, -3.0f);
- }
- if ( m_type == OBJECT_MOBILErt ||
- m_type == OBJECT_MOBILErc ||
- m_type == OBJECT_MOBILErr ||
- m_type == OBJECT_MOBILErs ) // large caterpillars?
- {
- pos[2] = Math::Vector(-5.0f, 5.2f, 2.5f);
- pos[3] = Math::Vector(-5.0f, 5.2f, -2.5f);
- }
- if ( m_type == OBJECT_MOBILEsa ) // submarine?
- {
- pos[2] = Math::Vector(-3.6f, 4.0f, 2.0f);
- pos[3] = Math::Vector(-3.6f, 4.0f, -2.0f);
- }
- if ( m_type == OBJECT_MOBILEtg ) // target?
- {
- pos[2] = Math::Vector(-2.4f, 6.5f, 2.0f);
- pos[3] = Math::Vector(-2.4f, 6.5f, -2.0f);
- }
- if ( m_type == OBJECT_MOBILEdr ) // designer?
- {
- pos[2] = Math::Vector(-5.3f, 2.7f, 1.8f);
- pos[3] = Math::Vector(-5.3f, 2.7f, -1.8f);
- }
-
- angle = RetAngleY(0)/Math::PI;
-
- zoom[0] = 1.0f;
- zoom[1] = 1.0f;
- zoom[2] = 1.0f;
- zoom[3] = 1.0f;
-
- if ( IsProgram() && // current program?
- Math::Mod(m_aTime, 0.7f) < 0.3f )
- {
- zoom[0] = 0.0f; // blinks
- zoom[1] = 0.0f;
- zoom[2] = 0.0f;
- zoom[3] = 0.0f;
- }
-
- // Updates lens.
- for ( i=0 ; i<4 ; i++ )
- {
- pos[i] = Math::Transform(m_objectPart[0].matWorld, pos[i]);
- dim[i].y = dim[i].x;
- m_particule->SetParam(m_partiSel[i], pos[i], dim[i], zoom[i], angle, 1.0f);
- }
-}
-
-
-// Gives the pointer to the current script execution.
-
-void CObject::SetRunScript(CScript* script)
-{
- m_runScript = script;
-}
-
-CScript* CObject::RetRunScript()
-{
- return m_runScript;
-}
-
-// Returns the variables of "this" for CBOT.
-
-CBotVar* CObject::RetBotVar()
-{
- return m_botVar;
-}
-
-// Returns the physics associated to the object.
-
-CPhysics* CObject::RetPhysics()
-{
- return m_physics;
-}
-
-// Returns the brain associated to the object.
-
-CBrain* CObject::RetBrain()
-{
- return m_brain;
-}
-
-// Returns the movement associated to the object.
-
-CMotion* CObject::RetMotion()
-{
- return m_motion;
-}
-
-// Returns the controller associated to the object.
-
-CAuto* CObject::RetAuto()
-{
- return m_auto;
-}
-
-void CObject::SetAuto(CAuto* automat)
-{
- m_auto = automat;
-}
-
-
-
-// Management of the position in the file definition.
-
-void CObject::SetDefRank(int rank)
-{
- m_defRank = rank;
-}
-
-int CObject::RetDefRank()
-{
- return m_defRank;
-}
-
-
-// Gives the object name for the tooltip.
-
-bool CObject::GetTooltipName(char* name)
-{
- GetResource(RES_OBJECT, m_type, name);
- return ( name[0] != 0 );
-}
-
-
-// Adds the object previously selected in the list.
-
-void CObject::AddDeselList(CObject* pObj)
-{
- int i;
-
- if ( m_totalDesectList >= OBJECTMAXDESELLIST )
- {
- for ( i=0 ; i<OBJECTMAXDESELLIST-1 ; i++ )
- {
- m_objectDeselectList[i] = m_objectDeselectList[i+1];
- }
- m_totalDesectList --;
- }
-
- m_objectDeselectList[m_totalDesectList++] = pObj;
-}
-
-// Removes the previously selected object in the list.
-
-CObject* CObject::SubDeselList()
-{
- if ( m_totalDesectList == 0 ) return 0;
-
- return m_objectDeselectList[--m_totalDesectList];
-}
-
-// Removes an object reference if it is in the list.
-
-void CObject::DeleteDeselList(CObject* pObj)
-{
- int i, j;
-
- j = 0;
- for ( i=0 ; i<m_totalDesectList ; i++ )
- {
- if ( m_objectDeselectList[i] != pObj )
- {
- m_objectDeselectList[j++] = m_objectDeselectList[i];
- }
- }
- m_totalDesectList = j;
-}
-
-
-
-// Management of the state of the pencil drawing robot.
-
-bool CObject::RetTraceDown()
-{
- CMotionVehicle* mv;
- if ( m_motion == 0 ) return false;
- mv = (CMotionVehicle*)m_motion;
- return mv->RetTraceDown();
-}
-
-void CObject::SetTraceDown(bool bDown)
-{
- CMotionVehicle* mv;
- if ( m_motion == 0 ) return;
- mv = (CMotionVehicle*)m_motion;
- mv->SetTraceDown(bDown);
-}
-
-int CObject::RetTraceColor()
-{
- CMotionVehicle* mv;
- if ( m_motion == 0 ) return 0;
- mv = (CMotionVehicle*)m_motion;
- return mv->RetTraceColor();
-}
-
-void CObject::SetTraceColor(int color)
-{
- CMotionVehicle* mv;
- if ( m_motion == 0 ) return;
- mv = (CMotionVehicle*)m_motion;
- mv->SetTraceColor(color);
-}
-
-float CObject::RetTraceWidth()
-{
- CMotionVehicle* mv;
- if ( m_motion == 0 ) return 0.0f;
- mv = (CMotionVehicle*)m_motion;
- return mv->RetTraceWidth();
-}
-
-void CObject::SetTraceWidth(float width)
-{
- CMotionVehicle* mv;
- if ( m_motion == 0 ) return;
- mv = (CMotionVehicle*)m_motion;
- mv->SetTraceWidth(width);
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// object.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "CBot/CBotDll.h"
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "old/d3dutil.h"
+#include "common/global.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "old/math3d.h"
+#include "object/mainmovie.h"
+#include "object/robotmain.h"
+#include "old/light.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "old/blitz.h"
+#include "old/camera.h"
+#include "old/particule.h"
+#include "physics/physics.h"
+#include "object/brain.h"
+#include "object/motion/motion.h"
+#include "object/motion/motionhuman.h"
+#include "object/motion/motiontoto.h"
+#include "object/motion/motionvehicle.h"
+#include "object/motion/motionmother.h"
+#include "object/motion/motionant.h"
+#include "object/motion/motionspider.h"
+#include "object/motion/motionbee.h"
+#include "object/motion/motionworm.h"
+#include "old/modfile.h"
+#include "object/auto/auto.h"
+#include "object/auto/autobase.h"
+#include "object/auto/autoportico.h"
+#include "object/auto/autoderrick.h"
+#include "object/auto/autofactory.h"
+#include "object/auto/autorepair.h"
+#include "object/auto/autodestroyer.h"
+#include "object/auto/autostation.h"
+#include "object/auto/autoenergy.h"
+#include "object/auto/autoconvert.h"
+#include "object/auto/autotower.h"
+#include "object/auto/autoresearch.h"
+#include "object/auto/autolabo.h"
+#include "object/auto/autonuclear.h"
+#include "object/auto/autoradar.h"
+#include "object/auto/autoegg.h"
+#include "object/auto/autonest.h"
+#include "object/auto/autoroot.h"
+#include "object/auto/autoflag.h"
+#include "object/auto/autoinfo.h"
+#include "object/auto/autojostle.h"
+#include "object/auto/autopara.h"
+#include "object/auto/autosafe.h"
+#include "object/auto/autohuston.h"
+#include "object/auto/automush.h"
+#include "object/auto/autokid.h"
+#include "object/task/task.h"
+#include "old/pyro.h"
+#include "ui/displaytext.h"
+#include "script/cmdtoken.h"
+#include "script/cbottoken.h"
+#include "old/sound.h"
+#include "object/object.h"
+
+
+
+#define ADJUST_ONBOARD false // true -> adjusts the camera ONBOARD
+#define ADJUST_ARM false // true -> adjusts the manipulator arm
+const float VIRUS_DELAY = 60.0f; // duration of virus infection
+const float LOSS_SHIELD = 0.24f; // loss of the shield by shot
+const float LOSS_SHIELD_H = 0.10f; // loss of the shield for humans
+const float LOSS_SHIELD_M = 0.02f; // loss of the shield for the laying
+
+#if ADJUST_ONBOARD
+static float debug_x = 0.0f;
+static float debug_y = 0.0f;
+static float debug_z = 0.0f;
+#endif
+
+#if ADJUST_ARM
+static float debug_arm1 = 0.0f;
+static float debug_arm2 = 0.0f;
+static float debug_arm3 = 0.0f;
+#endif
+
+
+
+
+// Updates the class Object.
+
+void uObject(CBotVar* botThis, void* user)
+{
+ CObject* object = (CObject*)user;
+ CObject* power;
+ CObject* fret;
+ CPhysics* physics;
+ CBotVar *pVar, *pSub;
+ ObjectType type;
+ Math::Vector pos;
+ float value;
+ int iValue;
+
+ if ( object == 0 ) return;
+
+ physics = object->RetPhysics();
+
+ // Updates the object's type.
+ pVar = botThis->GivItemList(); // "category"
+ type = object->RetType();
+ pVar->SetValInt(type, object->RetName());
+
+ // Updates the position of the object.
+ pVar = pVar->GivNext(); // "position"
+ if ( object->RetTruck() == 0 )
+ {
+ pos = object->RetPosition(0);
+ pos.y -= object->RetWaterLevel(); // relative to sea level!
+ pSub = pVar->GivItemList(); // "x"
+ pSub->SetValFloat(pos.x/g_unit);
+ pSub = pSub->GivNext(); // "y"
+ pSub->SetValFloat(pos.z/g_unit);
+ pSub = pSub->GivNext(); // "z"
+ pSub->SetValFloat(pos.y/g_unit);
+ }
+ else // object transported?
+ {
+ pSub = pVar->GivItemList(); // "x"
+ pSub->SetInit(IS_NAN);
+ pSub = pSub->GivNext(); // "y"
+ pSub->SetInit(IS_NAN);
+ pSub = pSub->GivNext(); // "z"
+ pSub->SetInit(IS_NAN);
+ }
+
+ // Updates the angle.
+ pos = object->RetAngle(0);
+ pos += object->RetInclinaison();
+ pVar = pVar->GivNext(); // "orientation"
+ pVar->SetValFloat(360.0f-Math::Mod(pos.y*180.0f/Math::PI, 360.0f));
+ pVar = pVar->GivNext(); // "pitch"
+ pVar->SetValFloat(pos.z*180.0f/Math::PI);
+ pVar = pVar->GivNext(); // "roll"
+ pVar->SetValFloat(pos.x*180.0f/Math::PI);
+
+ // Updates the energy level of the object.
+ pVar = pVar->GivNext(); // "energyLevel"
+ value = object->RetEnergy();
+ pVar->SetValFloat(value);
+
+ // Updates the shield level of the object.
+ pVar = pVar->GivNext(); // "shieldLevel"
+ value = object->RetShield();
+ pVar->SetValFloat(value);
+
+ // Updates the temperature of the reactor.
+ pVar = pVar->GivNext(); // "temperature"
+ if ( physics == 0 ) value = 0.0f;
+ else value = 1.0f-physics->RetReactorRange();
+ pVar->SetValFloat(value);
+
+ // Updates the height above the ground.
+ pVar = pVar->GivNext(); // "altitude"
+ if ( physics == 0 ) value = 0.0f;
+ else value = physics->RetFloorHeight();
+ pVar->SetValFloat(value/g_unit);
+
+ // Updates the lifetime of the object.
+ pVar = pVar->GivNext(); // "lifeTime"
+ value = object->RetAbsTime();
+ pVar->SetValFloat(value);
+
+ // Updates the material of the object.
+ pVar = pVar->GivNext(); // "material"
+ iValue = object->RetMaterial();
+ pVar->SetValInt(iValue);
+
+ // Updates the type of battery.
+ pVar = pVar->GivNext(); // "energyCell"
+ power = object->RetPower();
+ if ( power == 0 ) pVar->SetPointer(0);
+ else pVar->SetPointer(power->RetBotVar());
+
+ // Updates the transported object's type.
+ pVar = pVar->GivNext(); // "load"
+ fret = object->RetFret();
+ if ( fret == 0 ) pVar->SetPointer(0);
+ else pVar->SetPointer(fret->RetBotVar());
+}
+
+
+
+
+// Object's constructor.
+
+CObject::CObject(CInstanceManager* iMan)
+{
+ int i;
+
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_OBJECT, this, 500);
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ m_physics = 0;
+ m_brain = 0;
+ m_motion = 0;
+ m_auto = 0;
+ m_runScript = 0;
+
+ m_type = OBJECT_FIX;
+ m_id = ++g_id;
+ m_option = 0;
+ m_name[0] = 0;
+ m_partiReactor = -1;
+ m_shadowLight = -1;
+ m_effectLight = -1;
+ m_linVibration = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_cirVibration = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_inclinaison = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_lastParticule = 0.0f;
+
+ m_power = 0;
+ m_fret = 0;
+ m_truck = 0;
+ m_truckLink = 0;
+ m_energy = 1.0f;
+ m_capacity = 1.0f;
+ m_shield = 1.0f;
+ m_range = 0.0f;
+ m_transparency = 0.0f;
+ m_lastEnergy = 999.9f;
+ m_bHilite = false;
+ m_bSelect = false;
+ m_bSelectable = true;
+ m_bCheckToken = true;
+ m_bVisible = true;
+ m_bEnable = true;
+ m_bGadget = false;
+ m_bProxyActivate = false;
+ m_bTrainer = false;
+ m_bToy = false;
+ m_bManual = false;
+ m_bFixed = false;
+ m_bClip = true;
+ m_bShowLimit = false;
+ m_showLimitRadius = 0.0f;
+ m_aTime = 0.0f;
+ m_shotTime = 0.0f;
+ m_bVirusMode = false;
+ m_virusTime = 0.0f;
+ m_lastVirusParticule = 0.0f;
+ m_totalDesectList = 0;
+ m_bLock = false;
+ m_bExplo = false;
+ m_bCargo = false;
+ m_bBurn = false;
+ m_bDead = false;
+ m_bFlat = false;
+ m_gunGoalV = 0.0f;
+ m_gunGoalH = 0.0f;
+ m_shieldRadius = 0.0f;
+ m_defRank = -1;
+ m_magnifyDamage = 1.0f;
+ m_proxyDistance = 60.0f;
+ m_param = 0.0f;
+
+ ZeroMemory(&m_character, sizeof(Character));
+ m_character.wheelFront = 1.0f;
+ m_character.wheelBack = 1.0f;
+ m_character.wheelLeft = 1.0f;
+ m_character.wheelRight = 1.0f;
+
+ m_resetCap = RESET_NONE;
+ m_bResetBusy = false;
+ m_resetPosition = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_resetAngle = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_resetRun = -1;
+
+ m_cameraType = CAMERA_BACK;
+ m_cameraDist = 50.0f;
+ m_bCameraLock = false;
+
+ m_infoTotal = 0;
+ m_infoReturn = NAN;
+ m_bInfoUpdate = false;
+
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ m_objectPart[i].bUsed = false;
+ }
+ m_totalPart = 0;
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ m_partiSel[i] = -1;
+ }
+
+ for ( i=0 ; i<OBJECTMAXCMDLINE ; i++ )
+ {
+ m_cmdLine[i] = NAN;
+ }
+
+ FlushCrashShere();
+ m_globalSpherePos = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_globalSphereRadius = 0.0f;
+ m_jotlerSpherePos = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_jotlerSphereRadius = 0.0f;
+
+ CBotClass* bc = CBotClass::Find("object");
+ if ( bc != 0 )
+ {
+ bc->AddUpdateFunc(uObject);
+ }
+
+ m_botVar = CBotVar::Create("", CBotTypResult(CBotTypClass, "object"));
+ m_botVar->SetUserPtr(this);
+ m_botVar->SetIdent(m_id);
+}
+
+// Object's destructor.
+
+CObject::~CObject()
+{
+ if ( m_botVar != 0 )
+ {
+ m_botVar->SetUserPtr(OBJECTDELETED);
+ delete m_botVar;
+ }
+
+ delete m_physics;
+ delete m_brain;
+ delete m_motion;
+ delete m_auto;
+
+ m_iMan->DeleteInstance(CLASS_OBJECT, this);
+}
+
+
+// Removes an object.
+// If bAll = true, it does not help,
+// because all objects in the scene are quickly destroyed!
+
+void CObject::DeleteObject(bool bAll)
+{
+ CObject* pObj;
+ CPyro* pPyro;
+ int i;
+
+ if ( m_botVar != 0 )
+ {
+ m_botVar->SetUserPtr(OBJECTDELETED);
+ }
+
+ if ( m_camera->RetObject() == this )
+ {
+ m_camera->SetObject(0);
+ }
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ pObj->DeleteDeselList(this);
+ }
+
+ if ( !bAll )
+ {
+#if 0
+ type = m_camera->RetType();
+ if ( (type == CAMERA_BACK ||
+ type == CAMERA_FIX ||
+ type == CAMERA_EXPLO ||
+ type == CAMERA_ONBOARD) &&
+ m_camera->RetObject() == this )
+ {
+ pObj = m_main->SearchNearest(RetPosition(0), this);
+ if ( pObj == 0 )
+ {
+ m_camera->SetObject(0);
+ m_camera->SetType(CAMERA_FREE);
+ }
+ else
+ {
+ m_camera->SetObject(pObj);
+ m_camera->SetType(CAMERA_BACK);
+ }
+ }
+#endif
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pPyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, i);
+ if ( pPyro == 0 ) break;
+
+ pPyro->CutObjectLink(this); // the object no longer exists
+ }
+
+ if ( m_bSelect )
+ {
+ SetSelect(false);
+ }
+
+ if ( m_type == OBJECT_BASE ||
+ m_type == OBJECT_FACTORY ||
+ m_type == OBJECT_REPAIR ||
+ m_type == OBJECT_DESTROYER||
+ m_type == OBJECT_DERRICK ||
+ m_type == OBJECT_STATION ||
+ m_type == OBJECT_CONVERT ||
+ m_type == OBJECT_TOWER ||
+ m_type == OBJECT_RESEARCH ||
+ m_type == OBJECT_RADAR ||
+ m_type == OBJECT_INFO ||
+ m_type == OBJECT_ENERGY ||
+ m_type == OBJECT_LABO ||
+ m_type == OBJECT_NUCLEAR ||
+ m_type == OBJECT_PARA ||
+ m_type == OBJECT_SAFE ||
+ m_type == OBJECT_HUSTON ||
+ m_type == OBJECT_START ||
+ m_type == OBJECT_END ) // building?
+ {
+ m_terrain->DeleteBuildingLevel(RetPosition(0)); // flattens the field
+ }
+ }
+
+ m_type = OBJECT_NULL; // invalid object until complete destruction
+
+ if ( m_partiReactor != -1 )
+ {
+ m_particule->DeleteParticule(m_partiReactor);
+ m_partiReactor = -1;
+ }
+
+ if ( m_shadowLight != -1 )
+ {
+ m_light->DeleteLight(m_shadowLight);
+ m_shadowLight = -1;
+ }
+
+ if ( m_effectLight != -1 )
+ {
+ m_light->DeleteLight(m_effectLight);
+ m_effectLight = -1;
+ }
+
+ if ( m_physics != 0 )
+ {
+ m_physics->DeleteObject(bAll);
+ }
+
+ if ( m_brain != 0 )
+ {
+ m_brain->DeleteObject(bAll);
+ }
+
+ if ( m_motion != 0 )
+ {
+ m_motion->DeleteObject(bAll);
+ }
+
+ if ( m_auto != 0 )
+ {
+ m_auto->DeleteObject(bAll);
+ }
+
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ if ( m_objectPart[i].bUsed )
+ {
+ m_objectPart[i].bUsed = false;
+ m_engine->DeleteObject(m_objectPart[i].object);
+
+ if ( m_objectPart[i].masterParti != -1 )
+ {
+ m_particule->DeleteParticule(m_objectPart[i].masterParti);
+ m_objectPart[i].masterParti = -1;
+ }
+ }
+ }
+
+ if ( m_bShowLimit )
+ {
+ m_main->FlushShowLimit(0);
+ m_bShowLimit = false;
+ }
+
+ if ( !bAll ) m_main->CreateShortcuts();
+}
+
+// Simplifies a object (he was the brain, among others).
+
+void CObject::Simplify()
+{
+ if ( m_brain != 0 )
+ {
+ m_brain->StopProgram();
+ }
+ m_main->SaveOneScript(this);
+
+ if ( m_physics != 0 )
+ {
+ m_physics->DeleteObject();
+ delete m_physics;
+ m_physics = 0;
+ }
+
+ if ( m_brain != 0 )
+ {
+ m_brain->DeleteObject();
+ delete m_brain;
+ m_brain = 0;
+ }
+
+ if ( m_motion != 0 )
+ {
+ m_motion->DeleteObject();
+ delete m_motion;
+ m_motion = 0;
+ }
+
+ if ( m_auto != 0 )
+ {
+ m_auto->DeleteObject();
+ delete m_auto;
+ m_auto = 0;
+ }
+
+ m_main->CreateShortcuts();
+}
+
+
+// Detonates an object, when struck by a shot.
+// If false is returned, the object is still screwed.
+// If true is returned, the object is destroyed.
+
+bool CObject::ExploObject(ExploType type, float force, float decay)
+{
+ PyroType pyroType;
+ CPyro* pyro;
+ float loss, shield;
+
+ if ( type == EXPLO_BURN )
+ {
+ if ( m_type == OBJECT_MOBILEtg ||
+ m_type == OBJECT_TEEN28 || // cylinder?
+ m_type == OBJECT_METAL ||
+ m_type == OBJECT_POWER ||
+ m_type == OBJECT_ATOMIC ||
+ m_type == OBJECT_TNT ||
+ m_type == OBJECT_SCRAP1 ||
+ m_type == OBJECT_SCRAP2 ||
+ m_type == OBJECT_SCRAP3 ||
+ m_type == OBJECT_SCRAP4 ||
+ m_type == OBJECT_SCRAP5 ||
+ m_type == OBJECT_BULLET ||
+ m_type == OBJECT_EGG ) // object that isn't burning?
+ {
+ type = EXPLO_BOUM;
+ force = 1.0f;
+ decay = 1.0f;
+ }
+ }
+
+ if ( EXPLO_BOUM )
+ {
+ if ( m_shotTime < 0.5f ) return false;
+ m_shotTime = 0.0f;
+ }
+
+ if ( m_type == OBJECT_HUMAN && m_bDead ) return false;
+
+ // Calculate the power lost by the explosion.
+ if ( force == 0.0f )
+ {
+ if ( m_type == OBJECT_HUMAN )
+ {
+ loss = LOSS_SHIELD_H;
+ }
+ else if ( m_type == OBJECT_MOTHER )
+ {
+ loss = LOSS_SHIELD_M;
+ }
+ else
+ {
+ loss = LOSS_SHIELD;
+ }
+ }
+ else
+ {
+ loss = force;
+ }
+ loss *= m_magnifyDamage;
+ loss *= decay;
+
+ // Decreases the power of the shield.
+ shield = RetShield();
+ shield -= loss;
+ if ( shield < 0.0f ) shield = 0.0f;
+ SetShield(shield);
+
+ if ( shield > 0.0f ) // not dead yet?
+ {
+ if ( type == EXPLO_WATER )
+ {
+ if ( m_type == OBJECT_HUMAN )
+ {
+ pyroType = PT_SHOTH;
+ }
+ else
+ {
+ pyroType = PT_SHOTW;
+ }
+ }
+ else
+ {
+ if ( m_type == OBJECT_HUMAN )
+ {
+ pyroType = PT_SHOTH;
+ }
+ else if ( m_type == OBJECT_MOTHER )
+ {
+ pyroType = PT_SHOTM;
+ }
+ else
+ {
+ pyroType = PT_SHOTT;
+ }
+ }
+ }
+ else // completely dead?
+ {
+ if ( type == EXPLO_BURN ) // burning?
+ {
+ if ( m_type == OBJECT_MOTHER ||
+ m_type == OBJECT_ANT ||
+ m_type == OBJECT_SPIDER ||
+ m_type == OBJECT_BEE ||
+ m_type == OBJECT_WORM ||
+ m_type == OBJECT_BULLET )
+ {
+ pyroType = PT_BURNO;
+ SetBurn(true);
+ }
+ else if ( m_type == OBJECT_HUMAN )
+ {
+ pyroType = PT_DEADG;
+ }
+ else
+ {
+ pyroType = PT_BURNT;
+ SetBurn(true);
+ }
+ SetVirusMode(false);
+ }
+ else if ( type == EXPLO_WATER )
+ {
+ if ( m_type == OBJECT_HUMAN )
+ {
+ pyroType = PT_DEADW;
+ }
+ else
+ {
+ pyroType = PT_FRAGW;
+ }
+ }
+ else // explosion?
+ {
+ if ( m_type == OBJECT_ANT ||
+ m_type == OBJECT_SPIDER ||
+ m_type == OBJECT_BEE ||
+ m_type == OBJECT_WORM )
+ {
+ pyroType = PT_EXPLOO;
+ }
+ else if ( m_type == OBJECT_MOTHER ||
+ m_type == OBJECT_NEST ||
+ m_type == OBJECT_BULLET )
+ {
+ pyroType = PT_FRAGO;
+ }
+ else if ( m_type == OBJECT_HUMAN )
+ {
+ pyroType = PT_DEADG;
+ }
+ else if ( m_type == OBJECT_BASE ||
+ m_type == OBJECT_DERRICK ||
+ m_type == OBJECT_FACTORY ||
+ m_type == OBJECT_STATION ||
+ m_type == OBJECT_CONVERT ||
+ m_type == OBJECT_REPAIR ||
+ m_type == OBJECT_DESTROYER||
+ m_type == OBJECT_TOWER ||
+ m_type == OBJECT_NEST ||
+ m_type == OBJECT_RESEARCH ||
+ m_type == OBJECT_RADAR ||
+ m_type == OBJECT_INFO ||
+ m_type == OBJECT_ENERGY ||
+ m_type == OBJECT_LABO ||
+ m_type == OBJECT_NUCLEAR ||
+ m_type == OBJECT_PARA ||
+ m_type == OBJECT_SAFE ||
+ m_type == OBJECT_HUSTON ||
+ m_type == OBJECT_START ||
+ m_type == OBJECT_END ) // building?
+ {
+ pyroType = PT_FRAGT;
+ }
+ else if ( m_type == OBJECT_MOBILEtg ||
+ m_type == OBJECT_TEEN28 || // cylinder?
+ m_type == OBJECT_TEEN31 ) // basket?
+ {
+ pyroType = PT_FRAGT;
+ }
+ else
+ {
+ pyroType = PT_EXPLOT;
+ }
+ }
+
+ loss = 1.0f;
+ }
+
+ pyro = new CPyro(m_iMan);
+ pyro->Create(pyroType, this, loss);
+
+ if ( shield == 0.0f ) // dead?
+ {
+ if ( m_brain != 0 )
+ {
+ m_brain->StopProgram();
+ }
+ m_main->SaveOneScript(this);
+ }
+
+ if ( shield > 0.0f ) return false; // not dead yet
+
+ if ( RetSelect() )
+ {
+ SetSelect(false); // deselects the object
+ m_camera->SetType(CAMERA_EXPLO);
+ m_main->DeselectAll();
+ }
+ DeleteDeselList(this);
+
+ if ( m_botVar != 0 )
+ {
+ if ( m_type == OBJECT_STONE ||
+ m_type == OBJECT_URANIUM ||
+ m_type == OBJECT_METAL ||
+ m_type == OBJECT_POWER ||
+ m_type == OBJECT_ATOMIC ||
+ m_type == OBJECT_BULLET ||
+ m_type == OBJECT_BBOX ||
+ m_type == OBJECT_TNT ||
+ m_type == OBJECT_SCRAP1 ||
+ m_type == OBJECT_SCRAP2 ||
+ m_type == OBJECT_SCRAP3 ||
+ m_type == OBJECT_SCRAP4 ||
+ m_type == OBJECT_SCRAP5 ) // (*)
+ {
+ m_botVar->SetUserPtr(OBJECTDELETED);
+ }
+ }
+
+ return true;
+}
+
+// (*) If a robot or cosmonaut dies, the subject must continue to exist,
+// so that programs of the ants continue to operate as usual.
+
+
+// Initializes a new part.
+
+void CObject::InitPart(int part)
+{
+ m_objectPart[part].bUsed = true;
+ m_objectPart[part].object = -1;
+ m_objectPart[part].parentPart = -1;
+
+ m_objectPart[part].position = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_objectPart[part].angle.y = 0.0f;
+ m_objectPart[part].angle.x = 0.0f;
+ m_objectPart[part].angle.z = 0.0f;
+ m_objectPart[part].zoom = Math::Vector(1.0f, 1.0f, 1.0f);
+
+ m_objectPart[part].bTranslate = true;
+ m_objectPart[part].bRotate = true;
+ m_objectPart[part].bZoom = false;
+
+ m_objectPart[part].matTranslate.LoadIdentity();
+ m_objectPart[part].matRotate.LoadIdentity();
+ m_objectPart[part].matTransform.LoadIdentity();
+ m_objectPart[part].matWorld.LoadIdentity();;
+
+ m_objectPart[part].masterParti = -1;
+}
+
+// Creates a new part, and returns its number.
+// Returns -1 on error.
+
+int CObject::CreatePart()
+{
+ int i;
+
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ if ( m_objectPart[i].bUsed ) continue;
+
+ InitPart(i);
+ UpdateTotalPart();
+ return i;
+ }
+ return -1;
+}
+
+// Removes part.
+
+void CObject::DeletePart(int part)
+{
+ if ( !m_objectPart[part].bUsed ) return;
+
+ if ( m_objectPart[part].masterParti != -1 )
+ {
+ m_particule->DeleteParticule(m_objectPart[part].masterParti);
+ m_objectPart[part].masterParti = -1;
+ }
+
+ m_objectPart[part].bUsed = false;
+ m_engine->DeleteObject(m_objectPart[part].object);
+ UpdateTotalPart();
+}
+
+void CObject::UpdateTotalPart()
+{
+ int i;
+
+ m_totalPart = 0;
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ if ( m_objectPart[i].bUsed )
+ {
+ m_totalPart = i+1;
+ }
+ }
+}
+
+
+// Specifies the number of the object of a part.
+
+void CObject::SetObjectRank(int part, int objRank)
+{
+ if ( !m_objectPart[part].bUsed ) // object not created?
+ {
+ InitPart(part);
+ UpdateTotalPart();
+ }
+ m_objectPart[part].object = objRank;
+}
+
+// Returns the number of part.
+
+int CObject::RetObjectRank(int part)
+{
+ if ( !m_objectPart[part].bUsed ) return -1;
+ return m_objectPart[part].object;
+}
+
+// Specifies what is the parent of a part.
+// Reminder: Part 0 is always the father of all
+// and therefore the main part (eg the chassis of a car).
+
+void CObject::SetObjectParent(int part, int parent)
+{
+ m_objectPart[part].parentPart = parent;
+}
+
+
+// Specifies the type of the object.
+
+void CObject::SetType(ObjectType type)
+{
+ m_type = type;
+ strcpy(m_name, RetObjectName(m_type));
+
+ if ( m_type == OBJECT_MOBILErs )
+ {
+ m_param = 1.0f; // shield up to default
+ }
+
+ if ( m_type == OBJECT_ATOMIC )
+ {
+ m_capacity = 10.0f;
+ }
+ else
+ {
+ m_capacity = 1.0f;
+ }
+
+ if ( m_type == OBJECT_MOBILEwc ||
+ m_type == OBJECT_MOBILEtc ||
+ m_type == OBJECT_MOBILEfc ||
+ m_type == OBJECT_MOBILEic ||
+ m_type == OBJECT_MOBILEwi ||
+ m_type == OBJECT_MOBILEti ||
+ m_type == OBJECT_MOBILEfi ||
+ m_type == OBJECT_MOBILEii ||
+ m_type == OBJECT_MOBILErc ) // cannon vehicle?
+ {
+ m_cameraType = CAMERA_ONBOARD;
+ }
+}
+
+ObjectType CObject::RetType()
+{
+ return m_type;
+}
+
+char* CObject::RetName()
+{
+ return m_name;
+}
+
+
+// Choosing the option to use.
+
+void CObject::SetOption(int option)
+{
+ m_option = option;
+}
+
+int CObject::RetOption()
+{
+ return m_option;
+}
+
+
+// Management of the unique identifier of an object.
+
+void CObject::SetID(int id)
+{
+ m_id = id;
+
+ if ( m_botVar != 0 )
+ {
+ m_botVar->SetIdent(m_id);
+ }
+}
+
+int CObject::RetID()
+{
+ return m_id;
+}
+
+
+// Saves all the parameters of the object.
+
+bool CObject::Write(char *line)
+{
+ Math::Vector pos;
+ Info info;
+ char name[100];
+ float value;
+ int i;
+
+ sprintf(name, " camera=%s", GetCamera(RetCameraType()));
+ strcat(line, name);
+
+ if ( RetCameraLock() != 0 )
+ {
+ sprintf(name, " cameraLock=%d", RetCameraLock());
+ strcat(line, name);
+ }
+
+ if ( RetEnergy() != 0.0f )
+ {
+ sprintf(name, " energy=%.2f", RetEnergy());
+ strcat(line, name);
+ }
+
+ if ( RetCapacity() != 1.0f )
+ {
+ sprintf(name, " capacity=%.2f", RetCapacity());
+ strcat(line, name);
+ }
+
+ if ( RetShield() != 1.0f )
+ {
+ sprintf(name, " shield=%.2f", RetShield());
+ strcat(line, name);
+ }
+
+ if ( RetRange() != 1.0f )
+ {
+ sprintf(name, " range=%.2f", RetRange());
+ strcat(line, name);
+ }
+
+ if ( RetSelectable() != 1 )
+ {
+ sprintf(name, " selectable=%d", RetSelectable());
+ strcat(line, name);
+ }
+
+ if ( RetEnable() != 1 )
+ {
+ sprintf(name, " enable=%d", RetEnable());
+ strcat(line, name);
+ }
+
+ if ( RetFixed() != 0 )
+ {
+ sprintf(name, " fixed=%d", RetFixed());
+ strcat(line, name);
+ }
+
+ if ( RetClip() != 1 )
+ {
+ sprintf(name, " clip=%d", RetClip());
+ strcat(line, name);
+ }
+
+ if ( RetLock() != 0 )
+ {
+ sprintf(name, " lock=%d", RetLock());
+ strcat(line, name);
+ }
+
+ if ( RetProxyActivate() != 0 )
+ {
+ sprintf(name, " proxyActivate=%d", RetProxyActivate());
+ strcat(line, name);
+
+ sprintf(name, " proxyDistance=%.2f", RetProxyDistance()/g_unit);
+ strcat(line, name);
+ }
+
+ if ( RetMagnifyDamage() != 1.0f )
+ {
+ sprintf(name, " magnifyDamage=%.2f", RetMagnifyDamage());
+ strcat(line, name);
+ }
+
+ if ( RetGunGoalV() != 0.0f )
+ {
+ sprintf(name, " aimV=%.2f", RetGunGoalV());
+ strcat(line, name);
+ }
+ if ( RetGunGoalH() != 0.0f )
+ {
+ sprintf(name, " aimH=%.2f", RetGunGoalH());
+ strcat(line, name);
+ }
+
+ if ( RetParam() != 0.0f )
+ {
+ sprintf(name, " param=%.2f", RetParam());
+ strcat(line, name);
+ }
+
+ if ( RetResetCap() != 0 )
+ {
+ sprintf(name, " resetCap=%d", RetResetCap());
+ strcat(line, name);
+
+ pos = RetResetPosition()/g_unit;
+ sprintf(name, " resetPos=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
+ strcat(line, name);
+
+ pos = RetResetAngle()/(Math::PI/180.0f);
+ sprintf(name, " resetAngle=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
+ strcat(line, name);
+
+ sprintf(name, " resetRun=%d", RetResetRun());
+ strcat(line, name);
+ }
+
+ if ( m_bVirusMode != 0 )
+ {
+ sprintf(name, " virusMode=%d", m_bVirusMode);
+ strcat(line, name);
+ }
+
+ if ( m_virusTime != 0.0f )
+ {
+ sprintf(name, " virusTime=%.2f", m_virusTime);
+ strcat(line, name);
+ }
+
+ // Puts information in terminal (OBJECT_INFO).
+ for ( i=0 ; i<m_infoTotal ; i++ )
+ {
+ info = RetInfo(i);
+ if ( info.name[0] == 0 ) break;
+
+ sprintf(name, " info%d=\"%s=%.2f\"", i+1, info.name, info.value);
+ strcat(line, name);
+ }
+
+ // Sets the parameters of the command line.
+ for ( i=0 ; i<OBJECTMAXCMDLINE ; i++ )
+ {
+ value = RetCmdLine(i);
+ if ( value == NAN ) break;
+
+ if ( i == 0 ) sprintf(name, " cmdline=%.2f", value);
+ else sprintf(name, ";%.2f", value);
+ strcat(line, name);
+ }
+
+ if ( m_motion != 0 )
+ {
+ m_motion->Write(line);
+ }
+
+ if ( m_brain != 0 )
+ {
+ m_brain->Write(line);
+ }
+
+ if ( m_physics != 0 )
+ {
+ m_physics->Write(line);
+ }
+
+ if ( m_auto != 0 )
+ {
+ m_auto->Write(line);
+ }
+
+ return true;
+}
+
+// Returns all parameters of the object.
+
+bool CObject::Read(char *line)
+{
+ Math::Vector pos, dir;
+ Info info;
+ CameraType cType;
+ char op[20];
+ char text[100];
+ char* p;
+ float value;
+ int i;
+
+ cType = OpCamera(line, "camera");
+ if ( cType != CAMERA_NULL )
+ {
+ SetCameraType(cType);
+ }
+
+ SetCameraLock(OpInt(line, "cameraLock", 0));
+ SetEnergy(OpFloat(line, "energy", 0.0f));
+ SetCapacity(OpFloat(line, "capacity", 1.0f));
+ SetShield(OpFloat(line, "shield", 1.0f));
+ SetRange(OpFloat(line, "range", 1.0f));
+ SetSelectable(OpInt(line, "selectable", 1));
+ SetEnable(OpInt(line, "enable", 1));
+ SetFixed(OpInt(line, "fixed", 0));
+ SetClip(OpInt(line, "clip", 1));
+ SetLock(OpInt(line, "lock", 0));
+ SetProxyActivate(OpInt(line, "proxyActivate", 0));
+ SetProxyDistance(OpFloat(line, "proxyDistance", 15.0f)*g_unit);
+ SetRange(OpFloat(line, "range", 30.0f));
+ SetMagnifyDamage(OpFloat(line, "magnifyDamage", 1.0f));
+ SetGunGoalV(OpFloat(line, "aimV", 0.0f));
+ SetGunGoalH(OpFloat(line, "aimH", 0.0f));
+ SetParam(OpFloat(line, "param", 0.0f));
+ SetResetCap((ResetCap)OpInt(line, "resetCap", 0));
+ SetResetPosition(OpDir(line, "resetPos")*g_unit);
+ SetResetAngle(OpDir(line, "resetAngle")*(Math::PI/180.0f));
+ SetResetRun(OpInt(line, "resetRun", 0));
+ m_bBurn = OpInt(line, "burnMode", 0);
+ m_bVirusMode = OpInt(line, "virusMode", 0);
+ m_virusTime = OpFloat(line, "virusTime", 0.0f);
+
+ // Puts information in terminal (OBJECT_INFO).
+ for ( i=0 ; i<OBJECTMAXINFO ; i++ )
+ {
+ sprintf(op, "info%d", i+1);
+ OpString(line, op, text);
+ if ( text[0] == 0 ) break;
+ p = strchr(text, '=');
+ if ( p == 0 ) break;
+ *p = 0;
+ strcpy(info.name, text);
+ sscanf(p+1, "%f", &info.value);
+ SetInfo(i, info);
+ }
+
+ // Sets the parameters of the command line.
+ p = SearchOp(line, "cmdline");
+ for ( i=0 ; i<OBJECTMAXCMDLINE ; i++ )
+ {
+ value = GetFloat(p, i, NAN);
+ if ( value == NAN ) break;
+ SetCmdLine(i, value);
+ }
+
+ if ( m_motion != 0 )
+ {
+ m_motion->Read(line);
+ }
+
+ if ( m_brain != 0 )
+ {
+ m_brain->Read(line);
+ }
+
+ if ( m_physics != 0 )
+ {
+ m_physics->Read(line);
+ }
+
+ if ( m_auto != 0 )
+ {
+ m_auto->Read(line);
+ }
+
+ return true;
+}
+
+
+
+// Seeking the nth son of a father.
+
+int CObject::SearchDescendant(int parent, int n)
+{
+ int i;
+
+ for ( i=0 ; i<m_totalPart ; i++ )
+ {
+ if ( !m_objectPart[i].bUsed ) continue;
+
+ if ( parent == m_objectPart[i].parentPart )
+ {
+ if ( n-- == 0 ) return i;
+ }
+ }
+ return -1;
+}
+
+
+// Removes all spheres used for collisions.
+
+void CObject::FlushCrashShere()
+{
+ m_crashSphereUsed = 0;
+}
+
+// Adds a new sphere.
+
+int CObject::CreateCrashSphere(Math::Vector pos, float radius, Sound sound,
+ float hardness)
+{
+ float zoom;
+
+ if ( m_crashSphereUsed >= MAXCRASHSPHERE ) return -1;
+
+ zoom = RetZoomX(0);
+ m_crashSpherePos[m_crashSphereUsed] = pos;
+ m_crashSphereRadius[m_crashSphereUsed] = radius*zoom;
+ m_crashSphereHardness[m_crashSphereUsed] = hardness;
+ m_crashSphereSound[m_crashSphereUsed] = sound;
+ return m_crashSphereUsed++;
+}
+
+// Returns the number of spheres.
+
+int CObject::RetCrashSphereTotal()
+{
+ return m_crashSphereUsed;
+}
+
+// Returns a sphere for collisions.
+// The position is absolute in the world.
+
+bool CObject::GetCrashSphere(int rank, Math::Vector &pos, float &radius)
+{
+ if ( rank < 0 || rank >= m_crashSphereUsed )
+ {
+ pos = m_objectPart[0].position;
+ radius = 0.0f;
+ return false;
+ }
+
+ // Returns to the sphere collisions,
+ // which ignores the inclination of the vehicle.
+ // This is necessary to collisions with vehicles,
+ // so as not to reflect SetInclinaison, for example.
+ // The sphere must necessarily have a center (0, y, 0).
+ if ( rank == 0 && m_crashSphereUsed == 1 &&
+ m_crashSpherePos[0].x == 0.0f &&
+ m_crashSpherePos[0].z == 0.0f )
+ {
+ pos = m_objectPart[0].position + m_crashSpherePos[0];
+ radius = m_crashSphereRadius[0];
+ return true;
+ }
+
+ if ( m_objectPart[0].bTranslate ||
+ m_objectPart[0].bRotate )
+ {
+ UpdateTransformObject();
+ }
+ pos = Math::Transform(m_objectPart[0].matWorld, m_crashSpherePos[rank]);
+ radius = m_crashSphereRadius[rank];
+ return true;
+}
+
+// Returns the hardness of a sphere.
+
+Sound CObject::RetCrashSphereSound(int rank)
+{
+ return m_crashSphereSound[rank];
+}
+
+// Returns the hardness of a sphere.
+
+float CObject::RetCrashSphereHardness(int rank)
+{
+ return m_crashSphereHardness[rank];
+}
+
+// Deletes a sphere.
+
+void CObject::DeleteCrashSphere(int rank)
+{
+ int i;
+
+ if ( rank < 0 || rank >= m_crashSphereUsed ) return;
+
+ for ( i=rank+1 ; i<MAXCRASHSPHERE ; i++ )
+ {
+ m_crashSpherePos[i-1] = m_crashSpherePos[i];
+ m_crashSphereRadius[i-1] = m_crashSphereRadius[i];
+ }
+ m_crashSphereUsed --;
+}
+
+// Specifies the global sphere, relative to the object.
+
+void CObject::SetGlobalSphere(Math::Vector pos, float radius)
+{
+ float zoom;
+
+ zoom = RetZoomX(0);
+ m_globalSpherePos = pos;
+ m_globalSphereRadius = radius*zoom;
+}
+
+// Returns the global sphere, in the world.
+
+void CObject::GetGlobalSphere(Math::Vector &pos, float &radius)
+{
+ pos = Math::Transform(m_objectPart[0].matWorld, m_globalSpherePos);
+ radius = m_globalSphereRadius;
+}
+
+
+// Specifies the sphere of jostling, relative to the object.
+
+void CObject::SetJotlerSphere(Math::Vector pos, float radius)
+{
+ m_jotlerSpherePos = pos;
+ m_jotlerSphereRadius = radius;
+}
+
+// Specifies the sphere of jostling, in the world.
+
+void CObject::GetJotlerSphere(Math::Vector &pos, float &radius)
+{
+ pos = Math::Transform(m_objectPart[0].matWorld, m_jotlerSpherePos);
+ radius = m_jotlerSphereRadius;
+}
+
+
+// Specifies the radius of the shield.
+
+void CObject::SetShieldRadius(float radius)
+{
+ m_shieldRadius = radius;
+}
+
+// Returns the radius of the shield.
+
+float CObject::RetShieldRadius()
+{
+ return m_shieldRadius;
+}
+
+
+// Positioning an object on a certain height, above the ground.
+
+void CObject::SetFloorHeight(float height)
+{
+ Math::Vector pos;
+
+ pos = m_objectPart[0].position;
+ m_terrain->MoveOnFloor(pos);
+
+ if ( m_physics != 0 )
+ {
+ m_physics->SetLand(height == 0.0f);
+ m_physics->SetMotor(height != 0.0f);
+ }
+
+ m_objectPart[0].position.y = pos.y+height+m_character.height;
+ m_objectPart[0].bTranslate = true; // it will recalculate the matrices
+}
+
+// Adjust the inclination of an object laying on the ground.
+
+void CObject::FloorAdjust()
+{
+ Math::Vector pos, n;
+ Math::Point nn;
+ float a;
+
+ pos = RetPosition(0);
+ if ( m_terrain->GetNormal(n, pos) )
+ {
+#if 0
+ SetAngleX(0, sinf(n.z));
+ SetAngleZ(0, -sinf(n.x));
+ SetAngleY(0, 0.0f);
+#else
+ a = RetAngleY(0);
+ nn = Math::RotatePoint(-a, Math::Point(n.z, n.x));
+ SetAngleX(0, sinf(nn.x));
+ SetAngleZ(0, -sinf(nn.y));
+#endif
+ }
+}
+
+
+// Gives the linear vibration.
+
+void CObject::SetLinVibration(Math::Vector dir)
+{
+ if ( m_linVibration.x != dir.x ||
+ m_linVibration.y != dir.y ||
+ m_linVibration.z != dir.z )
+ {
+ m_linVibration = dir;
+ m_objectPart[0].bTranslate = true;
+ }
+}
+
+Math::Vector CObject::RetLinVibration()
+{
+ return m_linVibration;
+}
+
+// Gives the circular vibration.
+
+void CObject::SetCirVibration(Math::Vector dir)
+{
+ if ( m_cirVibration.x != dir.x ||
+ m_cirVibration.y != dir.y ||
+ m_cirVibration.z != dir.z )
+ {
+ m_cirVibration = dir;
+ m_objectPart[0].bRotate = true;
+ }
+}
+
+Math::Vector CObject::RetCirVibration()
+{
+ return m_cirVibration;
+}
+
+// Gives the inclination.
+
+void CObject::SetInclinaison(Math::Vector dir)
+{
+ if ( m_inclinaison.x != dir.x ||
+ m_inclinaison.y != dir.y ||
+ m_inclinaison.z != dir.z )
+ {
+ m_inclinaison = dir;
+ m_objectPart[0].bRotate = true;
+ }
+}
+
+Math::Vector CObject::RetInclinaison()
+{
+ return m_inclinaison;
+}
+
+
+// Gives the position of center of the object.
+
+void CObject::SetPosition(int part, const Math::Vector &pos)
+{
+ Math::Vector shPos, n[20], norm;
+ float height, radius;
+ int rank, i, j;
+
+ m_objectPart[part].position = pos;
+ m_objectPart[part].bTranslate = true; // it will recalculate the matrices
+
+ if ( part == 0 && !m_bFlat ) // main part?
+ {
+ rank = m_objectPart[0].object;
+
+ shPos = pos;
+ m_terrain->MoveOnFloor(shPos, true);
+ m_engine->SetObjectShadowPos(rank, shPos);
+
+ if ( m_physics != 0 && m_physics->RetType() == TYPE_FLYING )
+ {
+ height = pos.y-shPos.y;
+ }
+ else
+ {
+ height = 0.0f;
+ }
+ m_engine->SetObjectShadowHeight(rank, height);
+
+ // Calculating the normal to the ground in nine strategic locations,
+ // then perform a weighted average (the dots in the center are more important).
+ radius = m_engine->RetObjectShadowRadius(rank);
+ i = 0;
+
+ m_terrain->GetNormal(norm, pos);
+ n[i++] = norm;
+ n[i++] = norm;
+ n[i++] = norm;
+
+ shPos = pos;
+ shPos.x += radius*0.6f;
+ shPos.z += radius*0.6f;
+ m_terrain->GetNormal(norm, shPos);
+ n[i++] = norm;
+ n[i++] = norm;
+
+ shPos = pos;
+ shPos.x -= radius*0.6f;
+ shPos.z += radius*0.6f;
+ m_terrain->GetNormal(norm, shPos);
+ n[i++] = norm;
+ n[i++] = norm;
+
+ shPos = pos;
+ shPos.x += radius*0.6f;
+ shPos.z -= radius*0.6f;
+ m_terrain->GetNormal(norm, shPos);
+ n[i++] = norm;
+ n[i++] = norm;
+
+ shPos = pos;
+ shPos.x -= radius*0.6f;
+ shPos.z -= radius*0.6f;
+ m_terrain->GetNormal(norm, shPos);
+ n[i++] = norm;
+ n[i++] = norm;
+
+ shPos = pos;
+ shPos.x += radius;
+ shPos.z += radius;
+ m_terrain->GetNormal(norm, shPos);
+ n[i++] = norm;
+
+ shPos = pos;
+ shPos.x -= radius;
+ shPos.z += radius;
+ m_terrain->GetNormal(norm, shPos);
+ n[i++] = norm;
+
+ shPos = pos;
+ shPos.x += radius;
+ shPos.z -= radius;
+ m_terrain->GetNormal(norm, shPos);
+ n[i++] = norm;
+
+ shPos = pos;
+ shPos.x -= radius;
+ shPos.z -= radius;
+ m_terrain->GetNormal(norm, shPos);
+ n[i++] = norm;
+
+ norm.LoadZero();
+ for ( j=0 ; j<i ; j++ )
+ {
+ norm += n[j];
+ }
+ norm /= (float)i; // average vector
+
+ m_engine->SetObjectShadowNormal(rank, norm);
+
+ if ( m_shadowLight != -1 )
+ {
+ shPos = pos;
+ shPos.y += m_shadowHeight;
+ m_light->SetLightPos(m_shadowLight, shPos);
+ }
+
+ if ( m_effectLight != -1 )
+ {
+ shPos = pos;
+ shPos.y += m_effectHeight;
+ m_light->SetLightPos(m_effectLight, shPos);
+ }
+
+ if ( m_bShowLimit )
+ {
+ m_main->AdjustShowLimit(0, pos);
+ }
+ }
+}
+
+Math::Vector CObject::RetPosition(int part)
+{
+ return m_objectPart[part].position;
+}
+
+// Gives the rotation around three axis.
+
+void CObject::SetAngle(int part, const Math::Vector &angle)
+{
+ m_objectPart[part].angle = angle;
+ m_objectPart[part].bRotate = true; // it will recalculate the matrices
+
+ if ( part == 0 && !m_bFlat ) // main part?
+ {
+ m_engine->SetObjectShadowAngle(m_objectPart[0].object, m_objectPart[0].angle.y);
+ }
+}
+
+Math::Vector CObject::RetAngle(int part)
+{
+ return m_objectPart[part].angle;
+}
+
+// Gives the rotation about the axis Y.
+
+void CObject::SetAngleY(int part, float angle)
+{
+ m_objectPart[part].angle.y = angle;
+ m_objectPart[part].bRotate = true; // it will recalculate the matrices
+
+ if ( part == 0 && !m_bFlat ) // main part?
+ {
+ m_engine->SetObjectShadowAngle(m_objectPart[0].object, m_objectPart[0].angle.y);
+ }
+}
+
+// Gives the rotation about the axis X.
+
+void CObject::SetAngleX(int part, float angle)
+{
+ m_objectPart[part].angle.x = angle;
+ m_objectPart[part].bRotate = true; // it will recalculate the matrices
+}
+
+// Gives the rotation about the axis Z.
+
+void CObject::SetAngleZ(int part, float angle)
+{
+ m_objectPart[part].angle.z = angle;
+ m_objectPart[part].bRotate = true; //it will recalculate the matrices
+}
+
+float CObject::RetAngleY(int part)
+{
+ return m_objectPart[part].angle.y;
+}
+
+float CObject::RetAngleX(int part)
+{
+ return m_objectPart[part].angle.x;
+}
+
+float CObject::RetAngleZ(int part)
+{
+ return m_objectPart[part].angle.z;
+}
+
+
+// Gives the global zoom.
+
+void CObject::SetZoom(int part, float zoom)
+{
+ m_objectPart[part].bTranslate = true; // it will recalculate the matrices
+ m_objectPart[part].zoom.x = zoom;
+ m_objectPart[part].zoom.y = zoom;
+ m_objectPart[part].zoom.z = zoom;
+
+ m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
+ m_objectPart[part].zoom.y != 1.0f ||
+ m_objectPart[part].zoom.z != 1.0f );
+}
+
+void CObject::SetZoom(int part, Math::Vector zoom)
+{
+ m_objectPart[part].bTranslate = true; // it will recalculate the matrices
+ m_objectPart[part].zoom = zoom;
+
+ m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
+ m_objectPart[part].zoom.y != 1.0f ||
+ m_objectPart[part].zoom.z != 1.0f );
+}
+
+Math::Vector CObject::RetZoom(int part)
+{
+ return m_objectPart[part].zoom;
+}
+
+void CObject::SetZoomX(int part, float zoom)
+{
+ m_objectPart[part].bTranslate = true; // it will recalculate the matrices
+ m_objectPart[part].zoom.x = zoom;
+
+ m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
+ m_objectPart[part].zoom.y != 1.0f ||
+ m_objectPart[part].zoom.z != 1.0f );
+}
+
+void CObject::SetZoomY(int part, float zoom)
+{
+ m_objectPart[part].bTranslate = true; // it will recalculate the matrices
+ m_objectPart[part].zoom.y = zoom;
+
+ m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
+ m_objectPart[part].zoom.y != 1.0f ||
+ m_objectPart[part].zoom.z != 1.0f );
+}
+
+void CObject::SetZoomZ(int part, float zoom)
+{
+ m_objectPart[part].bTranslate = true; // it will recalculate the matrices
+ m_objectPart[part].zoom.z = zoom;
+
+ m_objectPart[part].bZoom = ( m_objectPart[part].zoom.x != 1.0f ||
+ m_objectPart[part].zoom.y != 1.0f ||
+ m_objectPart[part].zoom.z != 1.0f );
+}
+
+float CObject::RetZoomX(int part)
+{
+ return m_objectPart[part].zoom.x;
+}
+
+float CObject::RetZoomY(int part)
+{
+ return m_objectPart[part].zoom.y;
+}
+
+float CObject::RetZoomZ(int part)
+{
+ return m_objectPart[part].zoom.z;
+}
+
+
+// Returns the water level.
+
+float CObject::RetWaterLevel()
+{
+ return m_water->RetLevel();
+}
+
+
+void CObject::SetTrainer(bool bEnable)
+{
+ m_bTrainer = bEnable;
+
+ if ( m_bTrainer ) // training?
+ {
+ m_cameraType = CAMERA_FIX;
+ }
+}
+
+bool CObject::RetTrainer()
+{
+ return m_bTrainer;
+}
+
+void CObject::SetToy(bool bEnable)
+{
+ m_bToy = bEnable;
+}
+
+bool CObject::RetToy()
+{
+ return m_bToy;
+}
+
+void CObject::SetManual(bool bManual)
+{
+ m_bManual = bManual;
+}
+
+bool CObject::RetManual()
+{
+ return m_bManual;
+}
+
+void CObject::SetResetCap(ResetCap cap)
+{
+ m_resetCap = cap;
+}
+
+ResetCap CObject::RetResetCap()
+{
+ return m_resetCap;
+}
+
+void CObject::SetResetBusy(bool bBusy)
+{
+ m_bResetBusy = bBusy;
+}
+
+bool CObject::RetResetBusy()
+{
+ return m_bResetBusy;
+}
+
+void CObject::SetResetPosition(const Math::Vector &pos)
+{
+ m_resetPosition = pos;
+}
+
+Math::Vector CObject::RetResetPosition()
+{
+ return m_resetPosition;
+}
+
+void CObject::SetResetAngle(const Math::Vector &angle)
+{
+ m_resetAngle = angle;
+}
+
+Math::Vector CObject::RetResetAngle()
+{
+ return m_resetAngle;
+}
+
+int CObject::RetResetRun()
+{
+ return m_resetRun;
+}
+
+void CObject::SetResetRun(int run)
+{
+ m_resetRun = run;
+}
+
+
+// Management of the particle master.
+
+void CObject::SetMasterParticule(int part, int parti)
+{
+ m_objectPart[part].masterParti = parti;
+}
+
+int CObject::RetMasterParticule(int part)
+{
+ return m_objectPart[part].masterParti;
+}
+
+
+// Management of the stack transport.
+
+void CObject::SetPower(CObject* power)
+{
+ m_power = power;
+}
+
+CObject* CObject::RetPower()
+{
+ return m_power;
+}
+
+// Management of the object transport.
+
+void CObject::SetFret(CObject* fret)
+{
+ m_fret = fret;
+}
+
+CObject* CObject::RetFret()
+{
+ return m_fret;
+}
+
+// Management of the object "truck" that transports it.
+
+void CObject::SetTruck(CObject* truck)
+{
+ m_truck = truck;
+
+ // Invisible shadow if the object is transported.
+ m_engine->SetObjectShadowHide(m_objectPart[0].object, (m_truck != 0));
+}
+
+CObject* CObject::RetTruck()
+{
+ return m_truck;
+}
+
+// Management of the conveying portion.
+
+void CObject::SetTruckPart(int part)
+{
+ m_truckLink = part;
+}
+
+int CObject::RetTruckPart()
+{
+ return m_truckLink;
+}
+
+
+// Management of user information.
+
+void CObject::InfoFlush()
+{
+ m_infoTotal = 0;
+ m_bInfoUpdate = true;
+}
+
+void CObject::DeleteInfo(int rank)
+{
+ int i;
+
+ if ( rank < 0 || rank >= m_infoTotal ) return;
+
+ for ( i=rank ; i<m_infoTotal-1 ; i++ )
+ {
+ m_info[i] = m_info[i+1];
+ }
+ m_infoTotal --;
+ m_bInfoUpdate = true;
+}
+
+void CObject::SetInfo(int rank, Info info)
+{
+ if ( rank < 0 || rank >= OBJECTMAXINFO ) return;
+ m_info[rank] = info;
+
+ if ( rank+1 > m_infoTotal ) m_infoTotal = rank+1;
+ m_bInfoUpdate = true;
+}
+
+Info CObject::RetInfo(int rank)
+{
+ if ( rank < 0 || rank >= OBJECTMAXINFO ) rank = 0;
+ return m_info[rank];
+}
+
+int CObject::RetInfoTotal()
+{
+ return m_infoTotal;
+}
+
+void CObject::SetInfoReturn(float value)
+{
+ m_infoReturn = value;
+}
+
+float CObject::RetInfoReturn()
+{
+ return m_infoReturn;
+}
+
+void CObject::SetInfoUpdate(bool bUpdate)
+{
+ m_bInfoUpdate = bUpdate;
+}
+
+bool CObject::RetInfoUpdate()
+{
+ return m_bInfoUpdate;
+}
+
+
+bool CObject::SetCmdLine(int rank, float value)
+{
+ if ( rank < 0 || rank >= OBJECTMAXCMDLINE ) return false;
+ m_cmdLine[rank] = value;
+ return true;
+}
+
+float CObject::RetCmdLine(int rank)
+{
+ if ( rank < 0 || rank >= OBJECTMAXCMDLINE ) return 0.0f;
+ return m_cmdLine[rank];
+}
+
+
+// Returns matrices of an object portion.
+
+Math::Matrix* CObject::RetRotateMatrix(int part)
+{
+ return &m_objectPart[part].matRotate;
+}
+
+Math::Matrix* CObject::RetTranslateMatrix(int part)
+{
+ return &m_objectPart[part].matTranslate;
+}
+
+Math::Matrix* CObject::RetTransformMatrix(int part)
+{
+ return &m_objectPart[part].matTransform;
+}
+
+Math::Matrix* CObject::RetWorldMatrix(int part)
+{
+ if ( m_objectPart[0].bTranslate ||
+ m_objectPart[0].bRotate )
+ {
+ UpdateTransformObject();
+ }
+
+ return &m_objectPart[part].matWorld;
+}
+
+
+// Indicates whether the object should be drawn below the interface.
+
+void CObject::SetDrawWorld(bool bDraw)
+{
+ int i;
+
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ if ( m_objectPart[i].bUsed )
+ {
+ m_engine->SetDrawWorld(m_objectPart[i].object, bDraw);
+ }
+ }
+}
+
+// Indicates whether the object should be drawn over the interface.
+
+void CObject::SetDrawFront(bool bDraw)
+{
+ int i;
+
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ if ( m_objectPart[i].bUsed )
+ {
+ m_engine->SetDrawFront(m_objectPart[i].object, bDraw);
+ }
+ }
+}
+
+
+// Creates a vehicle traveling any pose on the floor.
+
+bool CObject::CreateVehicle(Math::Vector pos, float angle, ObjectType type,
+ float power, bool bTrainer, bool bToy)
+{
+ m_type = type;
+
+ if ( type == OBJECT_TOTO )
+ {
+ m_motion = new CMotionToto(m_iMan, this);
+ m_motion->Create(pos, angle, type, 1.0f);
+ return true;
+ }
+
+ SetTrainer(bTrainer);
+ SetToy(bToy);
+
+ m_physics = new CPhysics(m_iMan, this);
+ m_brain = new CBrain(m_iMan, this);
+
+ m_physics->SetBrain(m_brain);
+ m_brain->SetPhysics(m_physics);
+
+#if 0
+ if ( type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ) // fireball cannon?
+ {
+ m_showLimitRadius = 160.0f;
+ }
+ if ( type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ) // orgaball cannon?
+ {
+ m_showLimitRadius = 160.0f;
+ }
+ if ( type == OBJECT_MOBILErc ) // phazer cannon?
+ {
+ m_showLimitRadius = 160.0f;
+ }
+ if ( type == OBJECT_MOBILErs ) // robot shield?
+ {
+ m_showLimitRadius = 50.0f;
+ }
+#endif
+ if ( type == OBJECT_MOBILErt ) // robot thumper?
+ {
+ m_showLimitRadius = 400.0f;
+ }
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH )
+ {
+ m_motion = new CMotionHuman(m_iMan, this);
+ }
+ else
+ {
+ m_motion = new CMotionVehicle(m_iMan, this);
+ }
+ if ( m_motion == 0 ) return false;
+
+ m_physics->SetMotion(m_motion);
+ m_brain->SetMotion(m_motion);
+ m_motion->SetPhysics(m_physics);
+ m_motion->SetBrain(m_brain);
+ if ( !m_motion->Create(pos, angle, type, power) )
+ {
+ if ( m_physics != 0 )
+ {
+ m_physics->DeleteObject();
+ delete m_physics;
+ m_physics = 0;
+ }
+ if ( m_brain != 0 )
+ {
+ m_brain->DeleteObject();
+ delete m_brain;
+ m_brain = 0;
+ }
+ if ( m_motion != 0 )
+ {
+ m_motion->DeleteObject();
+ delete m_motion;
+ m_motion = 0;
+ }
+ return false;
+ }
+
+ return true;
+}
+
+// Creates an insect lands on any ground.
+
+bool CObject::CreateInsect(Math::Vector pos, float angle, ObjectType type)
+{
+ m_type = type;
+
+ m_physics = new CPhysics(m_iMan, this);
+ m_brain = new CBrain(m_iMan, this);
+
+ m_physics->SetBrain(m_brain);
+ m_brain->SetPhysics(m_physics);
+
+ if ( type == OBJECT_MOTHER )
+ {
+ m_motion = new CMotionMother(m_iMan, this);
+ }
+ if ( type == OBJECT_ANT )
+ {
+ m_motion = new CMotionAnt(m_iMan, this);
+ }
+ if ( type == OBJECT_SPIDER )
+ {
+ m_motion = new CMotionSpider(m_iMan, this);
+ }
+ if ( type == OBJECT_BEE )
+ {
+ m_motion = new CMotionBee(m_iMan, this);
+ }
+ if ( type == OBJECT_WORM )
+ {
+ m_motion = new CMotionWorm(m_iMan, this);
+ }
+ if ( m_motion == 0 ) return false;
+
+ m_physics->SetMotion(m_motion);
+ m_brain->SetMotion(m_motion);
+ m_motion->SetPhysics(m_physics);
+ m_motion->SetBrain(m_brain);
+ if ( !m_motion->Create(pos, angle, type, 0.0f) )
+ {
+ if ( m_physics != 0 )
+ {
+ m_physics->DeleteObject();
+ delete m_physics;
+ m_physics = 0;
+ }
+ if ( m_brain != 0 )
+ {
+ m_brain->DeleteObject();
+ delete m_brain;
+ m_brain = 0;
+ }
+ if ( m_motion != 0 )
+ {
+ m_motion->DeleteObject();
+ delete m_motion;
+ m_motion = 0;
+ }
+ return false;
+ }
+
+ return true;
+}
+
+// Creates shade under a vehicle as a negative light.
+
+bool CObject::CreateShadowLight(float height, D3DCOLORVALUE color)
+{
+ D3DLIGHT7 light;
+ Math::Vector pos;
+
+ if ( !m_engine->RetLightMode() ) return true;
+
+ pos = RetPosition(0);
+ m_shadowHeight = height;
+
+ ZeroMemory( &light, sizeof(light) );
+ light.dltType = D3DLIGHT_SPOT;
+ light.dcvDiffuse.r = color.r;
+ light.dcvDiffuse.g = color.g;
+ light.dcvDiffuse.b = color.b;
+ light.dvPosition.x = pos.x;
+ light.dvPosition.y = pos.y+height;
+ light.dvPosition.z = pos.z;
+ light.dvDirection.x = 0.0f;
+ light.dvDirection.y = -1.0f; // against the bottom
+ light.dvDirection.z = 0.0f;
+ light.dvRange = D3DLIGHT_RANGE_MAX;
+ light.dvFalloff = 1.0f;
+ light.dvAttenuation0 = 1.0f;
+ light.dvAttenuation1 = 0.0f;
+ light.dvAttenuation2 = 0.0f;
+ light.dvTheta = 0.0f;
+ light.dvPhi = Math::PI/4.0f;
+
+ m_shadowLight = m_light->CreateLight();
+ if ( m_shadowLight == -1 ) return false;
+
+ m_light->SetLight(m_shadowLight, light);
+
+ // Only illuminates the objects on the ground.
+ m_light->SetLightIncluType(m_shadowLight, TYPETERRAIN);
+
+ return true;
+}
+
+// Returns the number of negative light shade.
+
+int CObject::RetShadowLight()
+{
+ return m_shadowLight;
+}
+
+// Creates light for the effects of a vehicle.
+
+bool CObject::CreateEffectLight(float height, D3DCOLORVALUE color)
+{
+ D3DLIGHT7 light;
+
+ if ( !m_engine->RetLightMode() ) return true;
+
+ m_effectHeight = height;
+
+ ZeroMemory( &light, sizeof(light) );
+ light.dltType = D3DLIGHT_SPOT;
+ light.dcvDiffuse.r = color.r;
+ light.dcvDiffuse.g = color.g;
+ light.dcvDiffuse.b = color.b;
+ light.dvPosition.x = 0.0f;
+ light.dvPosition.y = 0.0f+height;
+ light.dvPosition.z = 0.0f;
+ light.dvDirection.x = 0.0f;
+ light.dvDirection.y = -1.0f; // against the bottom
+ light.dvDirection.z = 0.0f;
+ light.dvRange = D3DLIGHT_RANGE_MAX;
+ light.dvFalloff = 1.0f;
+ light.dvAttenuation0 = 1.0f;
+ light.dvAttenuation1 = 0.0f;
+ light.dvAttenuation2 = 0.0f;
+ light.dvTheta = 0.0f;
+ light.dvPhi = Math::PI/4.0f;
+
+ m_effectLight = m_light->CreateLight();
+ if ( m_effectLight == -1 ) return false;
+
+ m_light->SetLight(m_effectLight, light);
+ m_light->SetLightIntensity(m_effectLight, 0.0f);
+
+ return true;
+}
+
+// Returns the number of light effects.
+
+int CObject::RetEffectLight()
+{
+ return m_effectLight;
+}
+
+// Creates the circular shadow underneath a vehicle.
+
+bool CObject::CreateShadowCircle(float radius, float intensity,
+ D3DShadowType type)
+{
+ float zoom;
+
+ if ( intensity == 0.0f ) return true;
+
+ zoom = RetZoomX(0);
+
+ m_engine->ShadowCreate(m_objectPart[0].object);
+
+ m_engine->SetObjectShadowRadius(m_objectPart[0].object, radius*zoom);
+ m_engine->SetObjectShadowIntensity(m_objectPart[0].object, intensity);
+ m_engine->SetObjectShadowHeight(m_objectPart[0].object, 0.0f);
+ m_engine->SetObjectShadowAngle(m_objectPart[0].object, m_objectPart[0].angle.y);
+ m_engine->SetObjectShadowType(m_objectPart[0].object, type);
+
+ return true;
+}
+
+// Creates a building laying on the ground.
+
+bool CObject::CreateBuilding(Math::Vector pos, float angle, float height,
+ ObjectType type, float power)
+{
+ CModFile* pModFile;
+ Math::Point p;
+ int rank, i;
+
+ if ( m_engine->RetRestCreate() < 20 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
+ SetObjectRank(0, rank);
+
+ if ( m_type == OBJECT_PORTICO )
+ {
+ pModFile->ReadModel("objects\\portico1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\portico2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 67.0f, 0.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\portico3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(0.0f, 0.0f, -33.0f));
+ SetAngleY(2, 45.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(3, rank);
+ SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\portico4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(3, Math::Vector(50.0f, 0.0f, 0.0f));
+ SetAngleY(3, -60.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(4, rank);
+ SetObjectParent(4, 3);
+ pModFile->ReadModel("objects\\portico5.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(4, Math::Vector(35.0f, 0.0f, 0.0f));
+ SetAngleY(4, -55.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(5, rank);
+ SetObjectParent(5, 1);
+ pModFile->ReadModel("objects\\portico3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(5, Math::Vector(0.0f, 0.0f, 33.0f));
+ SetAngleY(5, -45.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(6, rank);
+ SetObjectParent(6, 5);
+ pModFile->ReadModel("objects\\portico4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(6, Math::Vector(50.0f, 0.0f, 0.0f));
+ SetAngleY(6, 60.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(7, rank);
+ SetObjectParent(7, 6);
+ pModFile->ReadModel("objects\\portico5.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(7, Math::Vector(35.0f, 0.0f, 0.0f));
+ SetAngleY(7, 55.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(8, rank);
+ SetObjectParent(8, 0);
+ pModFile->ReadModel("objects\\portico6.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(8, Math::Vector(-35.0f, 50.0f, -35.0f));
+ SetAngleY(8, -Math::PI/2.0f);
+ SetZoom(8, 2.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(9, rank);
+ SetObjectParent(9, 8);
+ pModFile->ReadModel("objects\\portico7.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(9, Math::Vector(0.0f, 4.5f, 1.9f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(10, rank);
+ SetObjectParent(10, 0);
+ pModFile->ReadModel("objects\\portico6.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(10, Math::Vector(-35.0f, 50.0f, 35.0f));
+ SetAngleY(10, -Math::PI/2.0f);
+ SetZoom(10, 2.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(11, rank);
+ SetObjectParent(11, 10);
+ pModFile->ReadModel("objects\\portico7.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(11, Math::Vector(0.0f, 4.5f, 1.9f));
+
+ CreateCrashSphere(Math::Vector( 0.0f, 28.0f, 0.0f), 45.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 27.0f, 10.0f, -42.0f), 15.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 10.0f, -42.0f), 15.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-27.0f, 10.0f, -42.0f), 15.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 27.0f, 10.0f, 42.0f), 15.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 10.0f, 42.0f), 15.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-27.0f, 10.0f, 42.0f), 15.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-32.0f, 45.0f, -32.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-32.0f, 45.0f, 32.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 32.0f, 45.0f, -32.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 32.0f, 45.0f, 32.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 35.0f, 0.0f), 50.0f);
+
+ CreateShadowCircle(50.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_BASE )
+ {
+ pModFile->ReadModel("objects\\base1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ for ( i=0 ; i<8 ; i++ )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1+i, rank);
+ SetObjectParent(1+i, 0);
+ pModFile->ReadModel("objects\\base2.mod");
+ pModFile->CreateEngineObject(rank);
+ p = Math::RotatePoint(-Math::PI/4.0f*i, 27.8f);
+ SetPosition(1+i, Math::Vector(p.x, 30.0f, p.y));
+ SetAngleY(1+i, Math::PI/4.0f*i);
+ SetAngleZ(1+i, Math::PI/2.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(10+i, rank);
+ SetObjectParent(10+i, 1+i);
+ pModFile->ReadModel("objects\\base4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(10+i, Math::Vector(23.5f, 0.0f, 7.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(18+i, rank);
+ SetObjectParent(18+i, 1+i);
+ pModFile->ReadModel("objects\\base4.mod");
+ pModFile->Mirror();
+ pModFile->CreateEngineObject(rank);
+ SetPosition(18+i, Math::Vector(23.5f, 0.0f, -7.0f));
+ }
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(9, rank);
+ SetObjectParent(9, 0);
+ pModFile->ReadModel("objects\\base3.mod"); // central pillar
+ pModFile->CreateEngineObject(rank);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 33.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 39.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 45.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 51.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 57.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 63.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 69.0f, 0.0f), 2.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 82.0f, 0.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 18.0f, 94.0f, 0.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-18.0f, 94.0f, 0.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 94.0f, 18.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 94.0f, -18.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 13.0f, 94.0f, 13.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-13.0f, 94.0f, 13.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 13.0f, 94.0f, -13.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-13.0f, 94.0f, -13.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f,104.0f, 0.0f), 14.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 45.0f, 0.0f), 10.0f);
+
+ CreateShadowCircle(60.0f, 1.0f);
+ m_showLimitRadius = 200.0f;
+
+ m_terrain->AddBuildingLevel(pos, 28.6f, 73.4f, 30.0f, 0.4f);
+ }
+
+ if ( m_type == OBJECT_DERRICK )
+ {
+ pModFile->ReadModel("objects\\derrick1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\derrick2.mod");
+ pModFile->CreateEngineObject(rank);
+
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 17.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 26.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(7.0f, 17.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 10.0f);
+
+ CreateShadowCircle(10.0f, 0.4f);
+ }
+
+ if ( m_type == OBJECT_RESEARCH )
+ {
+ pModFile->ReadModel("objects\\search1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\search2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 13.0f, 0.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\search3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(0.0f, 4.0f, 0.0f));
+ SetAngleZ(2, 35.0f*Math::PI/180.0f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 6.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 14.0f, 0.0f), 7.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 8.0f, 0.0f), 12.0f);
+
+ m_character.posPower = Math::Vector(7.5f, 3.0f, 0.0f);
+
+ CreateShadowCircle(12.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_RADAR )
+ {
+ pModFile->ReadModel("objects\\radar1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\radar2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 5.0f, 0.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\radar3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(0.0f, 11.0f, 0.0f));
+ SetAngleY(2, -Math::PI/2.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(3, rank);
+ SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\radar4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(3, Math::Vector(0.0f, 4.5f, 1.9f));
+
+ CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 11.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 7.0f, 0.0f), 7.0f);
+
+ CreateShadowCircle(8.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_INFO )
+ {
+ pModFile->ReadModel("objects\\info1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\info2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 5.0f, 0.0f));
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2+i*2, rank);
+ SetObjectParent(2+i*2, 1);
+ pModFile->ReadModel("objects\\info3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2+i*2, Math::Vector(0.0f, 4.5f, 0.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(3+i*2, rank);
+ SetObjectParent(3+i*2, 2+i*2);
+ pModFile->ReadModel("objects\\radar4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(3+i*2, Math::Vector(0.0f, 0.0f, -4.0f));
+
+ SetAngleY(2+i*2, 2.0f*Math::PI/3.0f*i);
+ }
+
+ CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 11.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 6.0f);
+
+ CreateShadowCircle(8.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_ENERGY )
+ {
+ pModFile->ReadModel("objects\\energy.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ CreateCrashSphere(Math::Vector(-2.0f, 13.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-7.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(-7.0f, 5.0f, 0.0f), 5.0f);
+
+ m_character.posPower = Math::Vector(0.0f, 3.0f, 0.0f);
+ m_energy = power; // initializes the energy level
+
+ CreateShadowCircle(6.0f, 0.5f);
+ }
+
+ if ( m_type == OBJECT_LABO )
+ {
+ pModFile->ReadModel("objects\\labo1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\labo2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(-9.0f, 3.0f, 0.0f));
+ SetAngleZ(1, Math::PI/2.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\labo3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(9.0f, -1.0f, 0.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(3, rank);
+ SetObjectParent(3, 2);
+ pModFile->ReadModel("objects\\labo4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(3, Math::Vector(0.0f, 0.0f, 0.0f));
+ SetAngleZ(3, 80.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(4, rank);
+ SetObjectParent(4, 2);
+ pModFile->ReadModel("objects\\labo4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(4, Math::Vector(0.0f, 0.0f, 0.0f));
+ SetAngleZ(4, 80.0f*Math::PI/180.0f);
+ SetAngleY(4, Math::PI*2.0f/3.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(5, rank);
+ SetObjectParent(5, 2);
+ pModFile->ReadModel("objects\\labo4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(5, Math::Vector(0.0f, 0.0f, 0.0f));
+ SetAngleZ(5, 80.0f*Math::PI/180.0f);
+ SetAngleY(5, -Math::PI*2.0f/3.0f);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 11.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 10.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-12.0f, 3.0f, 3.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-12.0f, 3.0f, -3.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(-10.0f, 5.0f, 0.0f), 7.0f);
+
+ m_character.posPower = Math::Vector(0.0f, 3.0f, 0.0f);
+
+ CreateShadowCircle(7.0f, 0.5f);
+ }
+
+ if ( m_type == OBJECT_FACTORY )
+ {
+ pModFile->ReadModel("objects\\factory1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ for ( i=0 ; i<9 ; i++ )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1+i, rank);
+ SetObjectParent(1+i, 0);
+ pModFile->ReadModel("objects\\factory2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1+i, Math::Vector(10.0f, 2.0f*i, 10.0f));
+ SetAngleZ(1+i, Math::PI/2.0f);
+ SetZoomZ(1+i, 0.30f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(10+i, rank);
+ SetObjectParent(10+i, 0);
+ pModFile->ReadModel("objects\\factory2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(10+i, Math::Vector(10.0f, 2.0f*i, -10.0f));
+ SetAngleZ(10+i, -Math::PI/2.0f);
+ SetAngleY(10+i, Math::PI);
+ SetZoomZ(10+i, 0.30f);
+ }
+
+ for ( i=0 ; i<2 ; i++ )
+ {
+ float s = (float)(i*2-1);
+ CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -3.0f, 2.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.0f, 2.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 2.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 9.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -3.0f, 9.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.0f, 9.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 9.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 16.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -3.0f, 16.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.0f, 16.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 16.0f, 11.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 16.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -3.0f, 16.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.0f, 16.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 16.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 9.0f, 4.0f*s), 4.0f, SOUND_BOUMm, 0.45f);
+ }
+ CreateCrashSphere(Math::Vector(-10.0f, 21.0f, -4.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 18.0f);
+
+ CreateShadowCircle(24.0f, 0.3f);
+ }
+
+ if ( m_type == OBJECT_REPAIR )
+ {
+ pModFile->ReadModel("objects\\repair1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\repair2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(-11.0f, 13.5f, 0.0f));
+ SetAngleZ(1, Math::PI/2.0f);
+
+ m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
+
+ CreateCrashSphere(Math::Vector(-11.0f, 0.0f, 4.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 0.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 0.0f, -4.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 10.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(-11.0f, 13.0f, 0.0f), 15.0f);
+ }
+
+ if ( m_type == OBJECT_DESTROYER )
+ {
+ pModFile->ReadModel("objects\\destroy1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\destroy2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 0.0f, 0.0f));
+
+ m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
+
+ CreateCrashSphere(Math::Vector(-3.5f, 0.0f, -13.5f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.5f, 0.0f, -13.5f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-3.5f, 0.0f, 13.5f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.5f, 0.0f, 13.5f), 4.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(19.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_STATION )
+ {
+ pModFile->ReadModel("objects\\station.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
+
+ CreateCrashSphere(Math::Vector(-15.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-15.0f, 6.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(-15.0f, 5.0f, 0.0f), 6.0f);
+
+ m_energy = power; // initialise le niveau d'�nergie
+ }
+
+ if ( m_type == OBJECT_CONVERT )
+ {
+ pModFile->ReadModel("objects\\convert1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\convert2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 14.0f, 0.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\convert3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(0.0f, 11.5f, 0.0f));
+ SetAngleX(2, -Math::PI*0.35f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(3, rank);
+ SetObjectParent(3, 0);
+ pModFile->ReadModel("objects\\convert3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(3, Math::Vector(0.0f, 11.5f, 0.0f));
+ SetAngleY(3, Math::PI);
+ SetAngleX(3, -Math::PI*0.35f);
+
+ m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
+
+ CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 4.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 2.0f, -4.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 9.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 14.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(-3.0f, 8.0f, 0.0f), 14.0f);
+ }
+
+ if ( m_type == OBJECT_TOWER )
+ {
+ pModFile->ReadModel("objects\\tower.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\roller2c.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 20.0f, 0.0f));
+ SetAngleZ(1, Math::PI/2.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\roller3c.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(4.5f, 0.0f, 0.0f));
+ SetAngleZ(2, 0.0f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 6.5f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 8.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 15.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 24.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 7.0f);
+
+ m_character.posPower = Math::Vector(5.0f, 3.0f, 0.0f);
+
+ CreateShadowCircle(6.0f, 1.0f);
+ m_showLimitRadius = BLITZPARA;
+ }
+
+ if ( m_type == OBJECT_NUCLEAR )
+ {
+ pModFile->ReadModel("objects\\nuclear1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\nuclear2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(20.0f, 10.0f, 0.0f));
+ SetAngleZ(1, 135.0f*Math::PI/180.0f);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 0.0f, 0.0f), 19.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 24.0f, 0.0f), 15.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(22.0f, 1.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 17.0f, 0.0f), 26.0f);
+
+ m_character.posPower = Math::Vector(22.0f, 3.0f, 0.0f);
+
+ CreateShadowCircle(21.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_PARA )
+ {
+ pModFile->ReadModel("objects\\para.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ m_terrain->AddBuildingLevel(pos, 16.0f, 18.0f, 1.0f, 0.5f);
+
+ CreateCrashSphere(Math::Vector( 13.0f, 3.0f, 13.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 11.0f, 15.0f, 11.0f), 2.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-13.0f, 3.0f, 13.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 15.0f, -11.0f), 2.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 13.0f, 3.0f, -13.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 11.0f, 15.0f, -11.0f), 2.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-13.0f, 3.0f, -13.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 15.0f, -11.0f), 2.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 26.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 54.0f, 0.0f), 14.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 20.0f);
+
+ CreateShadowCircle(21.0f, 1.0f);
+ m_showLimitRadius = BLITZPARA;
+ }
+
+ if ( m_type == OBJECT_SAFE )
+ {
+ pModFile->ReadModel("objects\\safe1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\safe2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetZoom(1, 1.05f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\safe3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetZoom(2, 1.05f);
+
+ m_terrain->AddBuildingLevel(pos, 18.0f, 20.0f, 1.0f, 0.5f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 13.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 13.0f);
+
+ CreateShadowCircle(23.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_HUSTON )
+ {
+ pModFile->ReadModel("objects\\huston1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\huston2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 39.0f, 30.0f));
+ SetAngleY(1, -Math::PI/2.0f);
+ SetZoom(1, 3.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\huston3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(0.0f, 4.5f, 1.9f));
+
+ CreateCrashSphere(Math::Vector( 15.0f, 6.0f, -53.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-15.0f, 6.0f, -53.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 15.0f, 6.0f, -26.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-15.0f, 6.0f, -26.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 15.0f, 6.0f, 0.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-15.0f, 6.0f, 0.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 15.0f, 6.0f, 26.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-15.0f, 6.0f, 26.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 15.0f, 6.0f, 53.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-15.0f, 6.0f, 53.0f), 16.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 27.0f, 30.0f), 12.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 45.0f, 30.0f), 14.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 26.0f, 4.0f, -61.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-26.0f, 4.0f, -61.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 26.0f, 4.0f, 61.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-26.0f, 4.0f, 61.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ }
+
+ if ( m_type == OBJECT_TARGET1 )
+ {
+ pModFile->ReadModel("objects\\target1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 1.5f);
+ SetFloorHeight(0.0f);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 50.0f+14.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -7.0f, 50.0f+12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 7.0f, 50.0f+12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-12.0f, 50.0f+ 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 12.0f, 50.0f+ 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-14.0f, 50.0f+ 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 14.0f, 50.0f+ 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-12.0f, 50.0f- 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 12.0f, 50.0f- 7.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -7.0f, 50.0f-12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 7.0f, 50.0f-12.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 50.0f-14.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 30.0f, 0.0f), 2.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 24.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 16.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 8.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(15.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_TARGET2 )
+ {
+ pModFile->ReadModel("objects\\target2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ height += 50.0f*1.5f;
+ }
+
+ if ( m_type == OBJECT_NEST )
+ {
+ pModFile->ReadModel("objects\\nest.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ m_terrain->AddBuildingLevel(pos, 3.0f, 5.0f, 1.0f, 0.5f);
+
+ CreateShadowCircle(4.0f, 1.0f);
+ }
+
+ if ( m_type == OBJECT_START )
+ {
+ pModFile->ReadModel("objects\\start.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
+ }
+
+ if ( m_type == OBJECT_END )
+ {
+ pModFile->ReadModel("objects\\end.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
+ }
+
+#if 0
+ if ( power > 0.0f ) // creates a battery?
+ {
+ CObject* pPower;
+
+ pPower = new CObject(m_iMan);
+ pPower->SetType(power<=1.0f?OBJECT_POWER:OBJECT_ATOMIC);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ pPower->SetObjectRank(0, rank);
+
+ if ( power <= 1.0f ) pModFile->ReadModel("objects\\power.mod");
+ else pModFile->ReadModel("objects\\atomic.mod");
+ pModFile->CreateEngineObject(rank);
+
+ pPower->SetPosition(0, RetCharacter()->posPower);
+ pPower->CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ pPower->SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.5f);
+
+ pPower->SetTruck(this);
+ SetPower(pPower);
+
+ if ( power <= 1.0f ) pPower->SetEnergy(power);
+ else pPower->SetEnergy(power/100.0f);
+ }
+#endif
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos); // to display the shadows immediately
+
+ CreateOtherObject(type);
+ m_engine->LoadAllTexture();
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a small resource set on the ground.
+
+bool CObject::CreateResource(Math::Vector pos, float angle, ObjectType type,
+ float power)
+{
+ CModFile* pModFile;
+ char name[50];
+ int rank;
+ float radius, height;
+
+ if ( type != OBJECT_SHOW )
+ {
+ if ( m_engine->RetRestCreate() < 1 ) return false;
+ }
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
+ SetObjectRank(0, rank);
+ SetEnergy(power);
+
+ name[0] = 0;
+ if ( type == OBJECT_STONE ) strcpy(name, "objects\\stone.mod");
+ if ( type == OBJECT_URANIUM ) strcpy(name, "objects\\uranium.mod");
+ if ( type == OBJECT_METAL ) strcpy(name, "objects\\metal.mod");
+ if ( type == OBJECT_POWER ) strcpy(name, "objects\\power.mod");
+ if ( type == OBJECT_ATOMIC ) strcpy(name, "objects\\atomic.mod");
+ if ( type == OBJECT_BULLET ) strcpy(name, "objects\\bullet.mod");
+ if ( type == OBJECT_BBOX ) strcpy(name, "objects\\bbox.mod");
+ if ( type == OBJECT_KEYa ) strcpy(name, "objects\\keya.mod");
+ if ( type == OBJECT_KEYb ) strcpy(name, "objects\\keyb.mod");
+ if ( type == OBJECT_KEYc ) strcpy(name, "objects\\keyc.mod");
+ if ( type == OBJECT_KEYd ) strcpy(name, "objects\\keyd.mod");
+ if ( type == OBJECT_TNT ) strcpy(name, "objects\\tnt.mod");
+ if ( type == OBJECT_SCRAP1 ) strcpy(name, "objects\\scrap1.mod");
+ if ( type == OBJECT_SCRAP2 ) strcpy(name, "objects\\scrap2.mod");
+ if ( type == OBJECT_SCRAP3 ) strcpy(name, "objects\\scrap3.mod");
+ if ( type == OBJECT_SCRAP4 ) strcpy(name, "objects\\scrap4.mod");
+ if ( type == OBJECT_SCRAP5 ) strcpy(name, "objects\\scrap5.mod");
+ if ( type == OBJECT_BOMB ) strcpy(name, "objects\\bomb.mod");
+ if ( type == OBJECT_WAYPOINT ) strcpy(name, "objects\\waypoint.mod");
+ if ( type == OBJECT_SHOW ) strcpy(name, "objects\\show.mod");
+ if ( type == OBJECT_WINFIRE ) strcpy(name, "objects\\winfire.mod");
+ if ( type == OBJECT_BAG ) strcpy(name, "objects\\bag.mod");
+ if ( type == OBJECT_MARKSTONE ) strcpy(name, "objects\\cross1.mod");
+ if ( type == OBJECT_MARKURANIUM ) strcpy(name, "objects\\cross3.mod");
+ if ( type == OBJECT_MARKPOWER ) strcpy(name, "objects\\cross2.mod");
+ if ( type == OBJECT_MARKKEYa ) strcpy(name, "objects\\crossa.mod");
+ if ( type == OBJECT_MARKKEYb ) strcpy(name, "objects\\crossb.mod");
+ if ( type == OBJECT_MARKKEYc ) strcpy(name, "objects\\crossc.mod");
+ if ( type == OBJECT_MARKKEYd ) strcpy(name, "objects\\crossd.mod");
+ if ( type == OBJECT_EGG ) strcpy(name, "objects\\egg.mod");
+
+ pModFile->ReadModel(name);
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ if ( type == OBJECT_SHOW ) // remains in the air?
+ {
+ delete pModFile;
+ return true;
+ }
+
+ radius = 1.5f;
+ height = 0.0f;
+
+ if ( type == OBJECT_MARKSTONE ||
+ type == OBJECT_MARKURANIUM ||
+ type == OBJECT_MARKKEYa ||
+ type == OBJECT_MARKKEYb ||
+ type == OBJECT_MARKKEYc ||
+ type == OBJECT_MARKKEYd ||
+ type == OBJECT_MARKPOWER ||
+ type == OBJECT_WAYPOINT )
+ {
+ }
+ else if ( type == OBJECT_EGG )
+ {
+ CreateCrashSphere(Math::Vector(-1.0f, 2.8f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
+ radius = 3.0f;
+ }
+ else if ( type == OBJECT_BOMB )
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 3.0f);
+ radius = 3.0f;
+ }
+ else if ( type == OBJECT_BAG )
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f);
+ SetZoom(0, 1.5f);
+ radius = 5.0f;
+ height = -1.4f;
+ }
+ else
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.5f);
+ }
+ CreateShadowCircle(radius, 1.0f);
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+ m_engine->LoadAllTexture();
+ FloorAdjust();
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos); // to display the shadows immediately
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a flag placed on the ground.
+
+bool CObject::CreateFlag(Math::Vector pos, float angle, ObjectType type)
+{
+ CModFile* pModFile;
+ char name[50];
+ int rank, i;
+
+ if ( m_engine->RetRestCreate() < 1+4 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ name[0] = 0;
+ if ( type == OBJECT_FLAGb ) strcpy(name, "objects\\flag1b.mod");
+ if ( type == OBJECT_FLAGr ) strcpy(name, "objects\\flag1r.mod");
+ if ( type == OBJECT_FLAGg ) strcpy(name, "objects\\flag1g.mod");
+ if ( type == OBJECT_FLAGy ) strcpy(name, "objects\\flag1y.mod");
+ if ( type == OBJECT_FLAGv ) strcpy(name, "objects\\flag1v.mod");
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
+ SetObjectRank(0, rank);
+ pModFile->ReadModel(name);
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ name[0] = 0;
+ if ( type == OBJECT_FLAGb ) strcpy(name, "objects\\flag2b.mod");
+ if ( type == OBJECT_FLAGr ) strcpy(name, "objects\\flag2r.mod");
+ if ( type == OBJECT_FLAGg ) strcpy(name, "objects\\flag2g.mod");
+ if ( type == OBJECT_FLAGy ) strcpy(name, "objects\\flag2y.mod");
+ if ( type == OBJECT_FLAGv ) strcpy(name, "objects\\flag2v.mod");
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1+i, rank);
+ SetObjectParent(1+i, i);
+ pModFile->ReadModel(name);
+ pModFile->CreateEngineObject(rank);
+ if ( i == 0 ) SetPosition(1+i, Math::Vector(0.15f, 5.0f, 0.0f));
+ else SetPosition(1+i, Math::Vector(0.79f, 0.0f, 0.0f));
+ }
+
+ SetJotlerSphere(Math::Vector(0.0f, 4.0f, 0.0f), 1.0f);
+ CreateShadowCircle(2.0f, 0.3f);
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+ m_engine->LoadAllTexture();
+ FloorAdjust();
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a barrier placed on the ground.
+
+bool CObject::CreateBarrier(Math::Vector pos, float angle, float height,
+ ObjectType type)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ if ( type == OBJECT_BARRIER0 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\barrier0.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(6.0f, 0.5f, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_BARRIER1 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\barrier1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector( 8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(12.0f, 0.5f, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_BARRIER2 ) // cardboard?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\barrier2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector( 8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(12.0f, 0.8f, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_BARRIER3 ) // match + straw?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\barrier3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector( 8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-3.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-8.5f, 3.0f, 0.0f), 0.7f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(10.0f, 0.5f, D3DSHADOWWORM);
+ }
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+ FloorAdjust();
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos);
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a plant placed on the ground.
+
+bool CObject::CreatePlant(Math::Vector pos, float angle, float height,
+ ObjectType type)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ if ( type == OBJECT_PLANT0 ||
+ type == OBJECT_PLANT1 ||
+ type == OBJECT_PLANT2 ||
+ type == OBJECT_PLANT3 ||
+ type == OBJECT_PLANT4 ) // standard?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ if ( type == OBJECT_PLANT0 ) pModFile->ReadModel("objects\\plant0.mod");
+ if ( type == OBJECT_PLANT1 ) pModFile->ReadModel("objects\\plant1.mod");
+ if ( type == OBJECT_PLANT2 ) pModFile->ReadModel("objects\\plant2.mod");
+ if ( type == OBJECT_PLANT3 ) pModFile->ReadModel("objects\\plant3.mod");
+ if ( type == OBJECT_PLANT4 ) pModFile->ReadModel("objects\\plant4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ height -= 2.0f;
+
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f);
+ SetJotlerSphere(Math::Vector(0.0f, 0.0f, 0.0f), 8.0f);
+
+ CreateShadowCircle(8.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_PLANT5 ||
+ type == OBJECT_PLANT6 ||
+ type == OBJECT_PLANT7 ) // clover?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ if ( type == OBJECT_PLANT5 ) pModFile->ReadModel("objects\\plant5.mod");
+ if ( type == OBJECT_PLANT6 ) pModFile->ReadModel("objects\\plant6.mod");
+ if ( type == OBJECT_PLANT7 ) pModFile->ReadModel("objects\\plant7.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+//? CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 3.0f, SOUND_BOUM, 0.10f);
+ SetJotlerSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f);
+
+ CreateShadowCircle(5.0f, 0.3f);
+ }
+
+ if ( type == OBJECT_PLANT8 ||
+ type == OBJECT_PLANT9 ) // squash?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ if ( type == OBJECT_PLANT8 ) pModFile->ReadModel("objects\\plant8.mod");
+ if ( type == OBJECT_PLANT9 ) pModFile->ReadModel("objects\\plant9.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
+
+ CreateShadowCircle(10.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_PLANT10 ||
+ type == OBJECT_PLANT11 ||
+ type == OBJECT_PLANT12 ||
+ type == OBJECT_PLANT13 ||
+ type == OBJECT_PLANT14 ) // succulent?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ if ( type == OBJECT_PLANT10 ) pModFile->ReadModel("objects\\plant10.mod");
+ if ( type == OBJECT_PLANT11 ) pModFile->ReadModel("objects\\plant11.mod");
+ if ( type == OBJECT_PLANT12 ) pModFile->ReadModel("objects\\plant12.mod");
+ if ( type == OBJECT_PLANT13 ) pModFile->ReadModel("objects\\plant13.mod");
+ if ( type == OBJECT_PLANT14 ) pModFile->ReadModel("objects\\plant14.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 12.0f, 0.0f), 5.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 6.0f);
+ SetJotlerSphere(Math::Vector(0.0f, 4.0f, 0.0f), 8.0f);
+
+ CreateShadowCircle(8.0f, 0.3f);
+ }
+
+ if ( type == OBJECT_PLANT15 ||
+ type == OBJECT_PLANT16 ||
+ type == OBJECT_PLANT17 ||
+ type == OBJECT_PLANT18 ||
+ type == OBJECT_PLANT19 ) // fern?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ if ( type == OBJECT_PLANT15 ) pModFile->ReadModel("objects\\plant15.mod");
+ if ( type == OBJECT_PLANT16 ) pModFile->ReadModel("objects\\plant16.mod");
+ if ( type == OBJECT_PLANT17 ) pModFile->ReadModel("objects\\plant17.mod");
+ if ( type == OBJECT_PLANT18 ) pModFile->ReadModel("objects\\plant18.mod");
+ if ( type == OBJECT_PLANT19 ) pModFile->ReadModel("objects\\plant19.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ if ( type != OBJECT_PLANT19 )
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f);
+ }
+ SetJotlerSphere(Math::Vector(0.0f, 0.0f, 0.0f), 8.0f);
+
+ CreateShadowCircle(8.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_TREE0 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\tree0.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 2.0f), 3.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(-1.0f, 10.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 0.0f, 17.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 1.0f, 27.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
+
+ CreateShadowCircle(8.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_TREE1 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\tree1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 2.0f), 3.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(-2.0f, 11.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(-2.0f, 19.0f, 2.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 2.0f, 26.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 2.0f, 34.0f,-2.0f), 2.0f, SOUND_BOUMs, 0.20f);
+
+ CreateShadowCircle(8.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_TREE2 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\tree2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 3.0f, 1.0f), 3.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(-2.0f, 10.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(-2.0f, 19.0f, 2.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 2.0f, 25.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 3.0f, 32.0f,-2.0f), 2.0f, SOUND_BOUMs, 0.20f);
+
+ CreateShadowCircle(8.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_TREE3 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\tree3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(-2.0f, 3.0f, 2.0f), 3.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(-3.0f, 9.0f, 1.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 0.0f, 18.0f, 0.0f), 2.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 0.0f, 27.0f, 7.0f), 2.0f, SOUND_BOUMs, 0.20f);
+
+ CreateShadowCircle(8.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_TREE4 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\tree4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 10.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(0.0f, 21.0f, 0.0f), 8.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(0.0f, 32.0f, 0.0f), 7.0f, SOUND_BOUMs, 0.20f);
+
+ CreateShadowCircle(8.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_TREE5 ) // giant tree (for the world "teen")
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\tree5.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 5.0f,-10.0f), 25.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector(-65.0f, 5.0f, 65.0f), 20.0f, SOUND_BOUMs, 0.20f);
+ CreateCrashSphere(Math::Vector( 38.0f, 5.0f, 21.0f), 18.0f, SOUND_BOUMs, 0.20f);
+
+ CreateShadowCircle(50.0f, 0.5f);
+ }
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos);
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a mushroom placed on the ground.
+
+bool CObject::CreateMushroom(Math::Vector pos, float angle, float height,
+ ObjectType type)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ if ( type == OBJECT_MUSHROOM1 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\mush1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 3.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 3.0f, 0.0f), 5.5f);
+ SetJotlerSphere(Math::Vector(0.0f, 3.0f, 0.0f), 5.5f);
+
+ CreateShadowCircle(6.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_MUSHROOM2 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\mush2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 5.0f, 0.0f), 3.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 5.5f);
+ SetJotlerSphere(Math::Vector(0.0f, 4.0f, 0.0f), 5.5f);
+
+ CreateShadowCircle(5.0f, 0.5f);
+ }
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos);
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a toy placed on the ground.
+
+bool CObject::CreateTeen(Math::Vector pos, float angle, float zoom, float height,
+ ObjectType type)
+{
+ CModFile* pModFile;
+ Math::Matrix* mat;
+ D3DCOLORVALUE color;
+ int rank;
+ float fShadow;
+ bool bFloorAdjust = true;
+
+ if ( m_engine->RetRestCreate() < 1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ fShadow = Math::Norm(1.0f-height/10.0f);
+
+ if ( type == OBJECT_TEEN0 ) // orange pencil lg=10
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen0.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 5.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 2.5f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-2.5f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(5.0f, 0.8f*fShadow, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_TEEN1 ) // blue pencil lg=14
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 6.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 2.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-2.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-4.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-6.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(6.0f, 0.8f*fShadow, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_TEEN2 ) // red pencil lg=16
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 7.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.7f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 2.3f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-2.3f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-4.7f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-7.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(6.0f, 0.8f*fShadow, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_TEEN3 ) // jar with pencils
+ {
+ rank = m_engine->CreateObject();
+//? m_engine->SetObjectType(rank, TYPEFIX);
+ m_engine->SetObjectType(rank, TYPEMETAL);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 4.0f);
+ CreateShadowCircle(6.0f, 0.5f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN4 ) // scissors
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-9.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-6.0f, 1.0f, 0.0f), 1.1f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-3.0f, 1.0f, 0.0f), 1.2f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 0.0f), 1.3f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 5.1f, 1.0f,-1.3f), 2.6f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 8.0f, 1.0f, 2.2f), 2.3f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 9.4f, 1.0f,-2.0f), 2.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(10.0f, 0.5f*fShadow, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_TEEN5 ) // CD
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen5.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+ SetFloorHeight(0.0f);
+ bFloorAdjust = false;
+
+ m_terrain->AddBuildingLevel(pos, 5.9f, 6.1f, 0.2f, 0.5f);
+ CreateShadowCircle(8.0f, 0.2f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN6 ) // book 1
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen6.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(20.0f, 0.2f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN7 ) // book 2
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen7.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(20.0f, 0.2f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN8 ) // a stack of books 1
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen8.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 12.0f);
+ CreateShadowCircle(20.0f, 0.2f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN9 ) // a stack of books 2
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen9.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-5.0f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 4.5f, 3.0f,-7.5f), 5.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 12.0f);
+ CreateShadowCircle(20.0f, 0.2f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN10 ) // bookcase
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen10.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-26.0f, 3.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-15.0f, 3.0f,-4.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-15.0f, 3.0f, 5.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -4.0f, 3.0f,-4.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -4.0f, 3.0f, 5.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 6.0f, 3.0f,-4.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 6.0f, 3.0f, 4.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 14.0f, 3.0f,-3.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 14.0f, 3.0f, 2.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 24.0f, 3.0f, 5.0f), 6.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 20.0f);
+ CreateShadowCircle(40.0f, 0.2f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN11 ) // lamp
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen11.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+ SetZoom(0, zoom);
+
+ mat = RetWorldMatrix(0);
+ pos = Math::Transform(*mat, Math::Vector(-56.0f, 22.0f, 0.0f));
+ m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(20.0f, 20.0f), PARTISELY, 1.0f, 0.0f, 0.0f);
+
+ pos = Math::Transform(*mat, Math::Vector(-65.0f, 40.0f, 0.0f));
+ color.r = 4.0f;
+ color.g = 2.0f;
+ color.b = 0.0f; // yellow-orange
+ color.a = 0.0f;
+ m_main->CreateSpot(pos, color);
+ }
+
+ if ( type == OBJECT_TEEN12 ) // coke
+ {
+ rank = m_engine->CreateObject();
+//? m_engine->SetObjectType(rank, TYPEFIX);
+ m_engine->SetObjectType(rank, TYPEMETAL);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen12.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 9.0f, 0.0f), 5.0f);
+ CreateShadowCircle(4.5f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN13 ) // cardboard farm
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen13.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 15.0f);
+ CreateShadowCircle(20.0f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN14 ) // open box
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen14.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 15.0f);
+ CreateShadowCircle(20.0f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN15 ) // stack of cartons
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen15.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f,-7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 4.0f, 7.0f), 5.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 15.0f);
+ CreateShadowCircle(20.0f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN16 ) // watering can
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen16.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-8.0f, 4.0f, 0.0f), 12.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 8.0f, 4.0f, 0.0f), 12.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 13.0f, 0.0f), 20.0f);
+ CreateShadowCircle(18.0f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN17 ) // wheel |
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen17.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 31.0f, 0.0f), 31.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 31.0f, 0.0f), 31.0f);
+ CreateShadowCircle(24.0f, 0.5f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN18 ) // wheel /
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen18.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 31.0f, 0.0f), 31.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 31.0f, 0.0f), 31.0f);
+ CreateShadowCircle(24.0f, 0.5f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN19 ) // wheel =
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen19.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 10.0f, 0.0f), 32.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 32.0f);
+ CreateShadowCircle(33.0f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN20 ) // wall with shelf
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen20.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-175.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-175.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -55.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -55.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -37.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -37.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 83.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 83.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ }
+
+ if ( type == OBJECT_TEEN21 ) // wall with window
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen21.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+ }
+
+ if ( type == OBJECT_TEEN22 ) // wall with door and shelf
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen22.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-135.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-135.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -15.0f, 0.0f, -5.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -15.0f, 0.0f, -35.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ }
+
+ if ( type == OBJECT_TEEN23 ) // skateboard on wheels
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen23.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ if ( m_option == 1 ) // passage under the prohibited skateboard?
+ {
+ CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 0.0f), 11.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 10.0f, 2.0f, 0.0f), 11.0f, SOUND_BOUMm, 0.45f);
+ }
+
+ CreateCrashSphere(Math::Vector(-23.0f, 2.0f, 7.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-23.0f, 2.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-23.0f, 2.0f,-7.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 23.0f, 2.0f, 7.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 23.0f, 2.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 23.0f, 2.0f,-7.0f), 3.0f, SOUND_BOUMm, 0.45f);
+
+ CreateShadowCircle(35.0f, 0.8f*fShadow, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_TEEN24 ) // skate /
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen24.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-12.0f, 0.0f, -3.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-12.0f, 0.0f, 3.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateShadowCircle(20.0f, 0.2f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN25 ) // skate /
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen25.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-12.0f, 0.0f, -3.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-12.0f, 0.0f, 3.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateShadowCircle(20.0f, 0.2f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN26 ) // ceiling lamp
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen26.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+ SetFloorHeight(0.0f);
+
+ mat = RetWorldMatrix(0);
+ pos = Math::Transform(*mat, Math::Vector(0.0f, 50.0f, 0.0f));
+ m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(100.0f, 100.0f), PARTISELY, 1.0f, 0.0f, 0.0f);
+
+ pos = Math::Transform(*mat, Math::Vector(0.0f, 50.0f, 0.0f));
+ color.r = 4.0f;
+ color.g = 2.0f;
+ color.b = 0.0f; // yellow-orange
+ color.a = 0.0f;
+ m_main->CreateSpot(pos, color);
+ }
+
+ if ( type == OBJECT_TEEN27 ) // large plant?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen27.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
+ CreateShadowCircle(40.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_TEEN28 ) // bottle?
+ {
+ rank = m_engine->CreateObject();
+//? m_engine->SetObjectType(rank, TYPEFIX);
+ m_engine->SetObjectType(rank, TYPEMETAL);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen28.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUM, 0.10f);
+ CreateShadowCircle(7.0f, 0.6f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN29 ) // bridge?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen29.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+ bFloorAdjust = false;
+ }
+
+ if ( type == OBJECT_TEEN30 ) // jump?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen30.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 15.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 15.0f, 0.0f), 17.0f);
+ CreateShadowCircle(20.0f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN31 ) // basket?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen31.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-10.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector( 0.0f, 2.0f, 0.0f), 6.0f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector( 9.0f, 4.0f, 1.0f), 6.0f, SOUND_BOUM, 0.10f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 10.0f);
+ CreateShadowCircle(16.0f, 0.6f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN32 ) // chair?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen32.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector( 17.5f, 1.0f, 17.5f), 3.5f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector( 17.5f, 1.0f, -17.5f), 3.5f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector(-17.5f, 1.0f, 17.5f), 3.5f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector(-17.5f, 1.0f, -17.5f), 3.5f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 26.0f);
+ CreateShadowCircle(35.0f, 0.3f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN33 ) // panel?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen33.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
+ CreateShadowCircle(10.0f, 0.3f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN34 ) // stone?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen34.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 4.0f, SOUND_BOUM, 0.10f);
+ CreateShadowCircle(3.0f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN35 ) // pipe?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen35.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(-40.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector(-20.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector( 0.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector( 20.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
+ CreateCrashSphere(Math::Vector( 40.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
+ CreateShadowCircle(40.0f, 0.8f*fShadow, D3DSHADOWWORM);
+ }
+
+ if ( type == OBJECT_TEEN36 ) // trunk?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen36.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+ bFloorAdjust = false;
+ }
+
+ if ( type == OBJECT_TEEN37 ) // boat?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen37.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+ bFloorAdjust = false;
+ }
+
+ if ( type == OBJECT_TEEN38 ) // fan?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen38a.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\teen38b.mod"); // engine
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 30.0f, 0.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 1);
+ pModFile->ReadModel("objects\\teen38c.mod"); // propeller
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(0.0f, 0.0f, 0.0f));
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 10.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 2.0f, 0.0f), 10.0f);
+ CreateShadowCircle(15.0f, 0.5f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN39 ) // potted plant?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen39.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 8.5f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 2.0f, 0.0f), 8.5f);
+ CreateShadowCircle(10.0f, 1.0f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN40 ) // balloon?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen40.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 5.0f, 0.0f), 11.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 14.0f, 0.0f), 15.0f);
+ CreateShadowCircle(15.0f, 0.7f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN41 ) // fence?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen41.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+ }
+
+ if ( type == OBJECT_TEEN42 ) // clover?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen42.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 2.0f, SOUND_BOUM, 0.10f);
+ CreateShadowCircle(15.0f, 0.4f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN43 ) // clover?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen43.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 2.0f, SOUND_BOUM, 0.10f);
+ CreateShadowCircle(15.0f, 0.4f*fShadow);
+ }
+
+ if ( type == OBJECT_TEEN44 ) // car?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\teen44.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, zoom);
+
+ CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 55.0f, SOUND_BOUM, 0.10f);
+ SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 55.0f);
+ CreateShadowCircle(55.0f, 1.0f*fShadow);
+ }
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ if ( bFloorAdjust )
+ {
+ SetFloorHeight(0.0f);
+ FloorAdjust();
+ }
+
+ CreateOtherObject(type);
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos);
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a crystal placed on the ground.
+
+bool CObject::CreateQuartz(Math::Vector pos, float angle, float height,
+ ObjectType type)
+{
+ CModFile* pModFile;
+ float radius;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ if ( type == OBJECT_QUARTZ0 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEQUARTZ);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\quartz0.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 3.5f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 2.0f, 0.0f), 3.5f);
+
+ CreateShadowCircle(4.0f, 0.5f);
+ }
+ if ( type == OBJECT_QUARTZ1 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEQUARTZ);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\quartz1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 5.0f);
+
+ CreateShadowCircle(5.0f, 0.5f);
+ }
+ if ( type == OBJECT_QUARTZ2 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEQUARTZ);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\quartz2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 6.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 6.0f);
+
+ CreateShadowCircle(6.0f, 0.5f);
+ }
+ if ( type == OBJECT_QUARTZ3 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEQUARTZ);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\quartz3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ CreateCrashSphere(Math::Vector(0.0f, 10.0f, 0.0f), 10.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 10.0f);
+
+ CreateShadowCircle(10.0f, 0.5f);
+ }
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos);
+
+ if ( type == OBJECT_QUARTZ0 )
+ {
+ pos.y += 4.0f;
+ radius = 2.0f;
+ }
+ if ( type == OBJECT_QUARTZ1 )
+ {
+ pos.y += 6.0f;
+ radius = 4.0f;
+ }
+ if ( type == OBJECT_QUARTZ2 )
+ {
+ pos.y += 10.0f;
+ radius = 5.0f;
+ }
+ if ( type == OBJECT_QUARTZ3 )
+ {
+ pos.y += 16.0f;
+ radius = 8.0f;
+ }
+ m_particule->CreateParticule(pos, pos, Math::Point(2.0f, 2.0f), PARTIQUARTZ, 0.7f+Math::Rand()*0.7f, radius, 0.0f);
+ m_particule->CreateParticule(pos, pos, Math::Point(2.0f, 2.0f), PARTIQUARTZ, 0.7f+Math::Rand()*0.7f, radius, 0.0f);
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a root placed on the ground.
+
+bool CObject::CreateRoot(Math::Vector pos, float angle, float height,
+ ObjectType type)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ if ( type == OBJECT_ROOT0 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\root0.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 2.0f);
+
+ CreateCrashSphere(Math::Vector(-5.0f, 1.0f, 0.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 4.0f, 1.0f, 2.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 4.0f, 1.0f, -3.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 2.0f, 5.0f, -1.0f), 1.5f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector(-4.0f, 5.0f, -1.0f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector(-2.0f, 8.0f, -0.5f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 0.0f, 10.0f, -0.5f), 1.0f, SOUND_BOUMv, 0.15f);
+//? SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 11.0f);
+
+ CreateShadowCircle(16.0f, 0.5f);
+ }
+ if ( type == OBJECT_ROOT1 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\root1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 2.0f);
+
+ CreateCrashSphere(Math::Vector(-4.0f, 1.0f, 1.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 0.0f, 1.0f, 2.0f), 1.5f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 3.0f, 1.0f, -2.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector(-2.0f, 5.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 2.0f, 5.0f, 0.0f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 0.0f, 8.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 0.0f, 12.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
+//? SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 12.0f);
+
+ CreateShadowCircle(16.0f, 0.5f);
+ }
+ if ( type == OBJECT_ROOT2 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\root2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 2.0f);
+
+ CreateCrashSphere(Math::Vector(-3.0f, 1.0f, 0.5f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 3.0f, 1.0f, -1.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector(-1.0f, 4.5f, 0.0f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 3.0f, 7.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 0.0f, 7.0f, -1.0f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 4.0f, 11.0f, 1.0f), 1.0f, SOUND_BOUMv, 0.15f);
+//? SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 10.0f);
+
+ CreateShadowCircle(16.0f, 0.5f);
+ }
+ if ( type == OBJECT_ROOT3 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\root3.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 2.0f);
+
+ CreateCrashSphere(Math::Vector(-4.0f, 1.0f, 1.0f), 3.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 4.0f, 1.0f, -3.0f), 3.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 6.0f, 1.0f, 4.0f), 3.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector(-2.5f, 7.0f, 2.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 4.0f, 7.0f, 2.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 3.0f, 6.0f, -1.0f), 1.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 0.0f, 12.0f, 0.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 1.0f, 16.0f, 0.0f), 1.0f, SOUND_BOUMv, 0.15f);
+//? SetGlobalSphere(Math::Vector(0.0f, 10.0f, 0.0f), 14.0f);
+
+ CreateShadowCircle(22.0f, 0.5f);
+ }
+ if ( type == OBJECT_ROOT4 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\root4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 2.0f);
+
+ CreateCrashSphere(Math::Vector( -7.0f, 2.0f, 3.0f), 4.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 5.0f, 2.0f, -6.0f), 4.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 6.0f, 2.0f, 6.0f), 3.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector(-11.0f, 1.0f, -2.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 1.0f, 1.0f, -7.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( -4.0f, 10.0f, 3.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 1.0f, 11.0f, 7.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 3.0f, 11.0f, -3.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( -3.0f, 17.0f, 1.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( -3.0f, 23.0f, -1.0f), 2.0f, SOUND_BOUMv, 0.15f);
+//? SetGlobalSphere(Math::Vector(0.0f, 12.0f, 0.0f), 20.0f);
+
+ CreateShadowCircle(30.0f, 0.5f);
+ }
+ if ( type == OBJECT_ROOT5 ) // gravity root ?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\root4.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 2.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\root5.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(-5.0f, 28.0f, -4.0f));
+ SetAngleX(1, -30.0f*Math::PI/180.0f);
+ SetAngleZ(1, 20.0f*Math::PI/180.0f);
+
+ CreateCrashSphere(Math::Vector( -7.0f, 2.0f, 3.0f), 4.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 5.0f, 2.0f, -6.0f), 4.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 6.0f, 2.0f, 6.0f), 3.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector(-11.0f, 1.0f, -2.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 1.0f, 1.0f, -7.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( -4.0f, 10.0f, 3.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 1.0f, 11.0f, 7.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( 3.0f, 11.0f, -3.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( -3.0f, 17.0f, 1.0f), 2.0f, SOUND_BOUMv, 0.15f);
+ CreateCrashSphere(Math::Vector( -3.0f, 23.0f, -1.0f), 2.0f, SOUND_BOUMv, 0.15f);
+//? SetGlobalSphere(Math::Vector(0.0f, 12.0f, 0.0f), 20.0f);
+
+ CreateShadowCircle(30.0f, 0.5f);
+ }
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos);
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a small home.
+
+bool CObject::CreateHome(Math::Vector pos, float angle, float height,
+ ObjectType type)
+{
+ CModFile* pModFile;
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 1 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ if ( type == OBJECT_HOME1 )
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX);
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\home1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 1.3f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f, SOUND_BOUMs, 0.25f);
+//? SetGlobalSphere(Math::Vector(0.0f, 6.0f, 0.0f), 11.0f);
+ CreateShadowCircle(16.0f, 0.5f);
+ }
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos);
+
+ delete pModFile;
+ return true;
+}
+
+// Creates ruin placed on the ground.
+
+bool CObject::CreateRuin(Math::Vector pos, float angle, float height,
+ ObjectType type)
+{
+ CModFile* pModFile;
+ char name[50];
+ int rank;
+
+ if ( m_engine->RetRestCreate() < 1+4 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
+ SetObjectRank(0, rank);
+
+ name[0] = 0;
+ if ( type == OBJECT_RUINmobilew1 ) strcpy(name, "objects\\ruin1.mod");
+ if ( type == OBJECT_RUINmobilew2 ) strcpy(name, "objects\\ruin1.mod");
+ if ( type == OBJECT_RUINmobilet1 ) strcpy(name, "objects\\ruin2.mod");
+ if ( type == OBJECT_RUINmobilet2 ) strcpy(name, "objects\\ruin2.mod");
+ if ( type == OBJECT_RUINmobiler1 ) strcpy(name, "objects\\ruin3.mod");
+ if ( type == OBJECT_RUINmobiler2 ) strcpy(name, "objects\\ruin3.mod");
+ if ( type == OBJECT_RUINfactory ) strcpy(name, "objects\\ruin4.mod");
+ if ( type == OBJECT_RUINdoor ) strcpy(name, "objects\\ruin5.mod");
+ if ( type == OBJECT_RUINsupport ) strcpy(name, "objects\\ruin6.mod");
+ if ( type == OBJECT_RUINradar ) strcpy(name, "objects\\ruin7.mod");
+ if ( type == OBJECT_RUINconvert ) strcpy(name, "objects\\ruin8.mod");
+ if ( type == OBJECT_RUINbase ) strcpy(name, "objects\\ruin9.mod");
+ if ( type == OBJECT_RUINhead ) strcpy(name, "objects\\ruin10.mod");
+
+ pModFile->ReadModel(name);
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+
+ if ( type == OBJECT_RUINmobilew1 ) // vehicle had wheels?
+ {
+ // Creates the right-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(6, rank);
+ SetObjectParent(6, 0);
+
+ pModFile->ReadModel("objects\\ruin1w.mod");
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(6, Math::Vector(-3.0f, 1.8f, -4.0f));
+ SetAngleX(6, -Math::PI/2.0f);
+
+ // Creates the left-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(7, rank);
+ SetObjectParent(7, 0);
+
+ pModFile->ReadModel("objects\\ruin1w.mod");
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(7, Math::Vector(-3.0f, 1.0f, 3.0f));
+ SetAngleY(7, Math::PI-0.3f);
+ SetAngleX(7, -0.3f);
+
+ // Creates the right-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(8, rank);
+ SetObjectParent(8, 0);
+
+ pModFile->ReadModel("objects\\ruin1w.mod");
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(8, Math::Vector(2.0f, 1.6f, -3.0f));
+ SetAngleY(8, 0.3f);
+
+ // Creates the left-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(9, rank);
+ SetObjectParent(9, 0);
+
+ pModFile->ReadModel("objects\\ruin1w.mod");
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(9, Math::Vector(2.0f, 1.0f, 3.0f));
+ SetAngleY(9, Math::PI-0.2f);
+ SetAngleX(9, 0.2f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.8f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+//? SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
+
+ CreateShadowCircle(4.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINmobilew2 ) // vehicle has wheels?
+ {
+ // Creates the left-back wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(7, rank);
+ SetObjectParent(7, 0);
+
+ pModFile->ReadModel("objects\\ruin1w.mod");
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(7, Math::Vector(-3.0f, 1.0f, 3.0f));
+ SetAngleY(7, Math::PI+0.3f);
+ SetAngleX(7, 0.4f);
+
+ // Creates the left-front wheel.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(9, rank);
+ SetObjectParent(9, 0);
+
+ pModFile->ReadModel("objects\\ruin1w.mod");
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(9, Math::Vector(2.0f, 1.0f, 3.0f));
+ SetAngleY(9, Math::PI+0.3f);
+ SetAngleX(9, -0.3f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.8f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+//? SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
+
+ CreateShadowCircle(4.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINmobilet1 ) // vehicle have caterpillars?
+ {
+ // Creates the cannon.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+
+ pModFile->ReadModel("objects\\ruin2c.mod");
+ pModFile->CreateEngineObject(rank);
+
+ SetPosition(1, Math::Vector(3.0f, 5.0f, -2.5f));
+ SetAngleX(1, -Math::PI*0.85f);
+ SetAngleY(1, -0.4f);
+ SetAngleZ(1, -0.1f);
+
+ CreateCrashSphere(Math::Vector(1.0f, 2.8f, -1.0f), 5.0f, SOUND_BOUMm, 0.45f);
+//? SetGlobalSphere(Math::Vector(1.0f, 5.0f, -1.0f), 10.0f);
+
+ CreateShadowCircle(5.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINmobilet2 ) // vehicle have caterpillars?
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 2.8f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+//? SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
+
+ CreateShadowCircle(5.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINmobiler1 ) // vehicle skating?
+ {
+ CreateCrashSphere(Math::Vector(1.0f, 2.8f, -1.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(1.0f, 5.0f, -1.0f), 10.0f);
+
+ CreateShadowCircle(5.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINmobiler2 ) // vehicle skating?
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 10.0f);
+
+ CreateShadowCircle(6.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINfactory ) // factory ?
+ {
+ CreateCrashSphere(Math::Vector( 9.0f, 1.0f, -11.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 2.0f, -11.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f, -10.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-12.0f, 11.0f, -4.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 4.0f, -2.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 8.0f, 3.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 2.0f, 4.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 2.0f, 10.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -4.0f, 0.0f, 10.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 18.0f);
+
+ CreateShadowCircle(20.0f, 0.7f);
+ }
+
+ if ( type == OBJECT_RUINdoor ) // converter holder?
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+//? SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 6.0f);
+
+ CreateShadowCircle(6.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINsupport ) // radar holder?
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+//? SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 4.0f);
+
+ CreateShadowCircle(3.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINradar ) // radar base?
+ {
+ CreateCrashSphere(Math::Vector(0.0f, 0.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+//? SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 6.0f);
+
+ CreateShadowCircle(6.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINconvert ) // converter?
+ {
+ m_terrain->AddBuildingLevel(pos, 7.0f, 9.0f, 1.0f, 0.5f);
+
+ CreateCrashSphere(Math::Vector(-10.0f, 0.0f, 4.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-10.0f, 0.0f, -4.0f), 5.0f, SOUND_BOUMm, 0.45f);
+//? SetGlobalSphere(Math::Vector(-3.0f, 0.0f, 0.0f), 14.0f);
+ }
+
+ if ( type == OBJECT_RUINbase ) // base?
+ {
+ CreateCrashSphere(Math::Vector( 0.0f, 15.0f, 0.0f),28.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 17.0f, 6.0f, 42.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 17.0f, 17.0f, 42.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-17.0f, 6.0f, 42.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-17.0f, 17.0f, 42.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-42.0f, 6.0f, 17.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-42.0f, 17.0f, 17.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-42.0f, 6.0f, -17.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-42.0f, 17.0f, -17.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-17.0f, 6.0f, -42.0f), 6.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-17.0f, 10.0f, -42.0f), 4.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 15.0f, 13.0f, -34.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 31.0f, 15.0f, -13.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 21.0f, 8.0f, -39.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 26.0f, 8.0f, -33.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 48.0f);
+
+ CreateShadowCircle(40.0f, 1.0f);
+ }
+
+ if ( type == OBJECT_RUINhead ) // base cap?
+ {
+ CreateCrashSphere(Math::Vector( 0.0f, 13.0f, 0.0f),20.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, -8.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f,-16.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f,-22.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-21.0f, 7.0f, 9.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -9.0f, 7.0f, 21.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 21.0f, 7.0f, 9.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 9.0f, 7.0f, 21.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-21.0f, 7.0f, -9.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( -9.0f, 7.0f, -21.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 21.0f, 7.0f, -9.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 9.0f, 7.0f, -21.0f), 8.0f, SOUND_BOUMm, 0.45f);
+ SetGlobalSphere(Math::Vector(0.0f, 0.0f, 0.0f), 35.0f);
+
+ CreateShadowCircle(30.0f, 1.0f);
+ }
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); //to display the shadows immediately
+
+ SetFloorHeight(0.0f);
+ CreateOtherObject(type);
+
+ if ( type != OBJECT_RUINfactory &&
+ type != OBJECT_RUINconvert &&
+ type != OBJECT_RUINbase )
+ {
+ FloorAdjust();
+ }
+
+ pos = RetPosition(0);
+ pos.y += height;
+ SetPosition(0, pos); //to display the shadows immediately
+
+ if ( type == OBJECT_RUINmobilew1 )
+ {
+ pos = RetPosition(0);
+ pos.y -= 0.5f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)-0.1f;
+ SetAngleX(0, angle);
+ }
+
+ if ( type == OBJECT_RUINmobilew2 )
+ {
+ pos = RetPosition(0);
+ pos.y -= 1.5f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)-0.9f;
+ SetAngleX(0, angle);
+
+ angle = RetAngleZ(0)-0.1f;
+ SetAngleZ(0, angle);
+ }
+
+ if ( type == OBJECT_RUINmobilet1 )
+ {
+ pos = RetPosition(0);
+ pos.y -= 0.9f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)-0.3f;
+ SetAngleX(0, angle);
+ }
+
+ if ( type == OBJECT_RUINmobilet2 )
+ {
+ pos = RetPosition(0);
+ pos.y -= 1.5f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)-0.3f;
+ SetAngleX(0, angle);
+
+ angle = RetAngleZ(0)+0.8f;
+ SetAngleZ(0, angle);
+ }
+
+ if ( type == OBJECT_RUINmobiler1 )
+ {
+ pos = RetPosition(0);
+ pos.y += 4.0f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)-Math::PI*0.6f;
+ SetAngleX(0, angle);
+
+ angle = RetAngleZ(0)-0.2f;
+ SetAngleZ(0, angle);
+ }
+
+ if ( type == OBJECT_RUINmobiler2 )
+ {
+ pos = RetPosition(0);
+ pos.y += 2.0f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)-0.1f;
+ SetAngleX(0, angle);
+
+ angle = RetAngleZ(0)-0.3f;
+ SetAngleZ(0, angle);
+ }
+
+ if ( type == OBJECT_RUINdoor )
+ {
+ pos = RetPosition(0);
+ pos.y -= 0.5f;
+ SetPosition(0, pos);
+
+ angle = RetAngleZ(0)-0.1f;
+ SetAngleZ(0, angle);
+ }
+
+ if ( type == OBJECT_RUINsupport )
+ {
+ pos = RetPosition(0);
+ pos.y += 0.5f;
+ SetPosition(0, pos);
+
+//? angle = RetAngleY(0)+0.1f;
+//? SetAngleY(0, angle);
+
+ angle = RetAngleX(0)+0.1f;
+ SetAngleX(0, angle);
+
+ angle = RetAngleZ(0)+0.1f;
+ SetAngleZ(0, angle);
+ }
+
+ if ( type == OBJECT_RUINradar )
+ {
+ pos = RetPosition(0);
+ pos.y -= 0.5f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)+0.15f;
+ SetAngleX(0, angle);
+
+ angle = RetAngleZ(0)+0.1f;
+ SetAngleZ(0, angle);
+ }
+
+ if ( type == OBJECT_RUINconvert )
+ {
+ pos = RetPosition(0);
+ pos.y -= 1.0f;
+ SetPosition(0, pos);
+ }
+
+ if ( type == OBJECT_RUINbase )
+ {
+ pos = RetPosition(0);
+ pos.y -= 1.0f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)+0.15f;
+ SetAngleX(0, angle);
+ }
+
+ if ( type == OBJECT_RUINhead )
+ {
+ pos = RetPosition(0);
+ pos.y += 8.0f;
+ SetPosition(0, pos);
+
+ angle = RetAngleX(0)+Math::PI*0.4f;
+ SetAngleX(0, angle);
+ }
+
+ delete pModFile;
+ return true;
+}
+
+// Creates a gadget apollo.
+
+bool CObject::CreateApollo(Math::Vector pos, float angle, ObjectType type)
+{
+ CModFile* pModFile;
+ int rank, i;
+
+ if ( m_engine->RetRestCreate() < 6 ) return false;
+
+ pModFile = new CModFile(m_iMan);
+
+ SetType(type);
+
+ if ( type == OBJECT_APOLLO1 ) // LEM ?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\apollol1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetZoom(0, 1.2f);
+ SetFloorHeight(0.0f);
+
+ for ( i=0 ; i<4 ; i++ ) // creates feet
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(i+1, rank);
+ SetObjectParent(i+1, 0);
+ pModFile->ReadModel("objects\\apollol2.mod");
+ pModFile->CreateEngineObject(rank);
+ SetAngleY(i+1, Math::PI/2.0f*i);
+ }
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(5, rank);
+ SetObjectParent(5, 0);
+ pModFile->ReadModel("objects\\apollol3.mod"); // ladder
+ pModFile->CreateEngineObject(rank);
+
+//? m_terrain->AddBuildingLevel(pos, 10.0f, 13.0f, 12.0f, 0.0f);
+
+ CreateCrashSphere(Math::Vector( 0.0f, 4.0f, 0.0f), 9.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 11.0f, 5.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-11.0f, 5.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 5.0f, -11.0f), 3.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 0.0f, 5.0f, 11.0f), 3.0f, SOUND_BOUMm, 0.45f);
+
+ SetGlobalSphere(Math::Vector(0.0f, 4.0f, 0.0f), 9.0f);
+
+ CreateShadowCircle(16.0f, 0.5f);
+ }
+
+ if ( type == OBJECT_APOLLO2 ) // jeep
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); //it is a stationary object
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\apolloj1.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ // Wheels.
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(-5.75f, 1.65f, -5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(2, rank);
+ SetObjectParent(2, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ SetPosition(2, Math::Vector(-5.75f, 1.65f, 5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(3, rank);
+ SetObjectParent(3, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ SetPosition(3, Math::Vector(5.75f, 1.65f, -5.0f));
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(4, rank);
+ SetObjectParent(4, 0);
+ pModFile->ReadModel("objects\\apolloj4.mod"); // wheel
+ pModFile->CreateEngineObject(rank);
+ SetPosition(4, Math::Vector(5.75f, 1.65f, 5.0f));
+
+ // Accessories:
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(5, rank);
+ SetObjectParent(5, 0);
+ pModFile->ReadModel("objects\\apolloj2.mod"); // antenna
+ pModFile->CreateEngineObject(rank);
+ SetPosition(5, Math::Vector(5.5f, 8.8f, 2.0f));
+ SetAngleY(5, -120.0f*Math::PI/180.0f);
+ SetAngleZ(5, 45.0f*Math::PI/180.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(6, rank);
+ SetObjectParent(6, 0);
+ pModFile->ReadModel("objects\\apolloj3.mod"); // camera
+ pModFile->CreateEngineObject(rank);
+ SetPosition(6, Math::Vector(5.5f, 2.8f, -2.0f));
+ SetAngleY(6, 30.0f*Math::PI/180.0f);
+
+ CreateCrashSphere(Math::Vector( 3.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector(-3.0f, 2.0f, 0.0f), 5.0f, SOUND_BOUMm, 0.45f);
+ CreateCrashSphere(Math::Vector( 7.0f, 9.0f, 2.0f), 2.0f, SOUND_BOUMm, 0.20f);
+
+ CreateShadowCircle(7.0f, 0.8f);
+
+ FloorAdjust();
+ }
+
+ if ( type == OBJECT_APOLLO3 ) // flag?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\apollof.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ SetJotlerSphere(Math::Vector(0.0f, 4.0f, 0.0f), 1.0f);
+ CreateShadowCircle(2.0f, 0.3f);
+ }
+
+ if ( type == OBJECT_APOLLO4 ) // module?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\apollom.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 2.0f, 0.0f), 2.0f, SOUND_BOUMm, 0.45f);
+ CreateShadowCircle(5.0f, 0.8f);
+
+ FloorAdjust();
+ }
+
+ if ( type == OBJECT_APOLLO5 ) // antenna?
+ {
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEFIX); // it is a stationary object
+ SetObjectRank(0, rank);
+ pModFile->ReadModel("objects\\apolloa.mod");
+ pModFile->CreateEngineObject(rank);
+ SetPosition(0, pos);
+ SetAngleY(0, angle);
+ SetFloorHeight(0.0f);
+
+ rank = m_engine->CreateObject();
+ m_engine->SetObjectType(rank, TYPEDESCENDANT);
+ SetObjectRank(1, rank);
+ SetObjectParent(1, 0);
+ pModFile->ReadModel("objects\\apolloj2.mod"); // antenna
+ pModFile->CreateEngineObject(rank);
+ SetPosition(1, Math::Vector(0.0f, 5.0f, 0.0f));
+ SetAngleY(1, -120.0f*Math::PI/180.0f);
+ SetAngleZ(1, 45.0f*Math::PI/180.0f);
+
+ CreateCrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 3.0f, SOUND_BOUMm, 0.35f);
+ CreateShadowCircle(3.0f, 0.7f);
+ }
+
+ CreateOtherObject(type);
+
+ pos = RetPosition(0);
+ SetPosition(0, pos); // to display the shadows immediately
+
+ delete pModFile;
+ return true;
+}
+
+// Creates all sub-objects for managing the object.
+
+void CObject::CreateOtherObject(ObjectType type)
+{
+ if ( type == OBJECT_BASE )
+ {
+ m_auto = new CAutoBase(m_iMan, this);
+ }
+ if ( type == OBJECT_PORTICO )
+ {
+ m_auto = new CAutoPortico(m_iMan, this);
+ }
+ if ( type == OBJECT_DERRICK )
+ {
+ m_auto = new CAutoDerrick(m_iMan, this);
+ }
+ if ( type == OBJECT_FACTORY )
+ {
+ m_auto = new CAutoFactory(m_iMan, this);
+ }
+ if ( type == OBJECT_REPAIR )
+ {
+ m_auto = new CAutoRepair(m_iMan, this);
+ }
+ if ( type == OBJECT_DESTROYER )
+ {
+ m_auto = new CAutoDestroyer(m_iMan, this);
+ }
+ if ( type == OBJECT_STATION )
+ {
+ m_auto = new CAutoStation(m_iMan, this);
+ }
+ if ( type == OBJECT_CONVERT )
+ {
+ m_auto = new CAutoConvert(m_iMan, this);
+ }
+ if ( type == OBJECT_TOWER )
+ {
+ m_auto = new CAutoTower(m_iMan, this);
+ }
+ if ( type == OBJECT_RESEARCH )
+ {
+ m_auto = new CAutoResearch(m_iMan, this);
+ }
+ if ( type == OBJECT_RADAR )
+ {
+ m_auto = new CAutoRadar(m_iMan, this);
+ }
+ if ( type == OBJECT_INFO )
+ {
+ m_auto = new CAutoInfo(m_iMan, this);
+ }
+ if ( type == OBJECT_ENERGY )
+ {
+ m_auto = new CAutoEnergy(m_iMan, this);
+ }
+ if ( type == OBJECT_LABO )
+ {
+ m_auto = new CAutoLabo(m_iMan, this);
+ }
+ if ( type == OBJECT_NUCLEAR )
+ {
+ m_auto = new CAutoNuclear(m_iMan, this);
+ }
+ if ( type == OBJECT_PARA )
+ {
+ m_auto = new CAutoPara(m_iMan, this);
+ }
+ if ( type == OBJECT_SAFE )
+ {
+ m_auto = new CAutoSafe(m_iMan, this);
+ }
+ if ( type == OBJECT_HUSTON )
+ {
+ m_auto = new CAutoHuston(m_iMan, this);
+ }
+ if ( type == OBJECT_EGG )
+ {
+ m_auto = new CAutoEgg(m_iMan, this);
+ }
+ if ( type == OBJECT_NEST )
+ {
+ m_auto = new CAutoNest(m_iMan, this);
+ }
+ if ( type == OBJECT_ROOT5 )
+ {
+ m_auto = new CAutoRoot(m_iMan, this);
+ }
+ if ( type == OBJECT_MUSHROOM2 )
+ {
+ m_auto = new CAutoMush(m_iMan, this);
+ }
+ if ( type == OBJECT_FLAGb ||
+ type == OBJECT_FLAGr ||
+ type == OBJECT_FLAGg ||
+ type == OBJECT_FLAGy ||
+ type == OBJECT_FLAGv )
+ {
+ m_auto = new CAutoFlag(m_iMan, this);
+ }
+ if ( type == OBJECT_TEEN36 || // trunk?
+ type == OBJECT_TEEN37 || // boat?
+ type == OBJECT_TEEN38 ) // fan?
+ {
+ m_auto = new CAutoKid(m_iMan, this);
+ }
+}
+
+
+// Reads a program.
+
+bool CObject::ReadProgram(int rank, char* filename)
+{
+ if ( m_brain != 0 )
+ {
+ return m_brain->ReadProgram(rank, filename);
+ }
+ return false;
+}
+
+// Writes a program.
+
+bool CObject::WriteProgram(int rank, char* filename)
+{
+ if ( m_brain != 0 )
+ {
+ return m_brain->WriteProgram(rank, filename);
+ }
+ return false;
+}
+
+// Starts a program.
+
+bool CObject::RunProgram(int rank)
+{
+ if ( m_brain != 0 )
+ {
+ m_brain->RunProgram(rank);
+ return true;
+ }
+ if ( m_auto != 0 )
+ {
+ m_auto->Start(rank);
+ return true;
+ }
+ return false;
+}
+
+
+
+
+// Calculates the matrix for transforming the object.
+// Returns true if the matrix has changed.
+// The rotations occur in the order Y, Z and X.
+
+bool CObject::UpdateTransformObject(int part, bool bForceUpdate)
+{
+ Math::Vector position, angle, eye;
+ bool bModif = false;
+ int parent;
+
+ if ( m_truck != 0 ) // transported by truck?
+ {
+ m_objectPart[part].bTranslate = true;
+ m_objectPart[part].bRotate = true;
+ }
+
+ if ( !bForceUpdate &&
+ !m_objectPart[part].bTranslate &&
+ !m_objectPart[part].bRotate ) return false;
+
+ position = m_objectPart[part].position;
+ angle = m_objectPart[part].angle;
+
+ if ( part == 0 ) // main part?
+ {
+ position += m_linVibration;
+ angle += m_cirVibration+m_inclinaison;
+ }
+
+ if ( m_objectPart[part].bTranslate ||
+ m_objectPart[part].bRotate )
+ {
+ if ( m_objectPart[part].bTranslate )
+ {
+ m_objectPart[part].matTranslate.LoadIdentity();
+ m_objectPart[part].matTranslate.Set(1, 4, position.x);
+ m_objectPart[part].matTranslate.Set(2, 4, position.y);
+ m_objectPart[part].matTranslate.Set(3, 4, position.z);
+ }
+
+ if ( m_objectPart[part].bRotate )
+ {
+ Math::LoadRotationZXYMatrix(m_objectPart[part].matRotate, angle);
+ }
+
+ if ( m_objectPart[part].bZoom )
+ {
+ Math::Matrix mz;
+ mz.LoadIdentity();
+ mz.Set(1, 1, m_objectPart[part].zoom.x);
+ mz.Set(2, 2, m_objectPart[part].zoom.y);
+ mz.Set(3, 3, m_objectPart[part].zoom.z);
+ m_objectPart[part].matTransform = Math::MultiplyMatrices(m_objectPart[part].matTranslate,
+ Math::MultiplyMatrices(m_objectPart[part].matRotate, mz));
+ }
+ else
+ {
+ m_objectPart[part].matTransform = Math::MultiplyMatrices(m_objectPart[part].matTranslate,
+ m_objectPart[part].matRotate);
+ }
+ bModif = true;
+ }
+
+ if ( bForceUpdate ||
+ m_objectPart[part].bTranslate ||
+ m_objectPart[part].bRotate )
+ {
+ parent = m_objectPart[part].parentPart;
+
+ if ( part == 0 && m_truck != 0 ) // transported by a truck?
+ {
+ Math::Matrix* matWorldTruck;
+ matWorldTruck = m_truck->RetWorldMatrix(m_truckLink);
+ m_objectPart[part].matWorld = Math::MultiplyMatrices(*matWorldTruck,
+ m_objectPart[part].matTransform);
+ }
+ else
+ {
+ if ( parent == -1 ) // no parent?
+ {
+ m_objectPart[part].matWorld = m_objectPart[part].matTransform;
+ }
+ else
+ {
+ m_objectPart[part].matWorld = Math::MultiplyMatrices(m_objectPart[parent].matWorld,
+ m_objectPart[part].matTransform);
+ }
+ }
+ bModif = true;
+ }
+
+ if ( bModif )
+ {
+ m_engine->SetObjectTransform(m_objectPart[part].object,
+ m_objectPart[part].matWorld);
+ }
+
+ m_objectPart[part].bTranslate = false;
+ m_objectPart[part].bRotate = false;
+
+ return bModif;
+}
+
+// Updates all matrices to transform the object father and all his sons.
+// Assume a maximum of 4 degrees of freedom.
+// Appropriate, for example, to a body, an arm, forearm, hand and fingers.
+
+bool CObject::UpdateTransformObject()
+{
+ bool bUpdate1, bUpdate2, bUpdate3, bUpdate4;
+ int level1, level2, level3, level4, rank;
+ int parent1, parent2, parent3, parent4;
+
+ if ( m_bFlat )
+ {
+ for ( level1=0 ; level1<m_totalPart ; level1++ )
+ {
+ if ( !m_objectPart[level1].bUsed ) continue;
+ UpdateTransformObject(level1, false);
+ }
+ }
+ else
+ {
+ parent1 = 0;
+ bUpdate1 = UpdateTransformObject(parent1, false);
+
+ for ( level1=0 ; level1<m_totalPart ; level1++ )
+ {
+ rank = SearchDescendant(parent1, level1);
+ if ( rank == -1 ) break;
+
+ parent2 = rank;
+ bUpdate2 = UpdateTransformObject(rank, bUpdate1);
+
+ for ( level2=0 ; level2<m_totalPart ; level2++ )
+ {
+ rank = SearchDescendant(parent2, level2);
+ if ( rank == -1 ) break;
+
+ parent3 = rank;
+ bUpdate3 = UpdateTransformObject(rank, bUpdate2);
+
+ for ( level3=0 ; level3<m_totalPart ; level3++ )
+ {
+ rank = SearchDescendant(parent3, level3);
+ if ( rank == -1 ) break;
+
+ parent4 = rank;
+ bUpdate4 = UpdateTransformObject(rank, bUpdate3);
+
+ for ( level4=0 ; level4<m_totalPart ; level4++ )
+ {
+ rank = SearchDescendant(parent4, level4);
+ if ( rank == -1 ) break;
+
+ UpdateTransformObject(rank, bUpdate4);
+ }
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+
+// Puts all the progeny flat (there is more than fathers).
+// This allows for debris independently from each other in all directions.
+
+void CObject::FlatParent()
+{
+ int i;
+
+ for ( i=0 ; i<m_totalPart ; i++ )
+ {
+ m_objectPart[i].position.x = m_objectPart[i].matWorld.Get(1, 4);
+ m_objectPart[i].position.y = m_objectPart[i].matWorld.Get(2, 4);
+ m_objectPart[i].position.z = m_objectPart[i].matWorld.Get(3, 4);
+
+ m_objectPart[i].matWorld.Set(1, 4, 0.0f);
+ m_objectPart[i].matWorld.Set(2, 4, 0.0f);
+ m_objectPart[i].matWorld.Set(3, 4, 0.0f);
+
+ m_objectPart[i].matTranslate.Set(1, 4, 0.0f);
+ m_objectPart[i].matTranslate.Set(2, 4, 0.0f);
+ m_objectPart[i].matTranslate.Set(3, 4, 0.0f);
+
+ m_objectPart[i].parentPart = -1; // more parents
+ }
+
+ m_bFlat = true;
+}
+
+
+
+// Updates the mapping of the texture of the pile.
+
+void CObject::UpdateEnergyMapping()
+{
+ D3DMATERIAL7 mat;
+ float a, b, i, s, au, bu;
+ float limit[6];
+ int j;
+
+ if ( fabs(m_energy-m_lastEnergy) < 0.01f ) return;
+ m_lastEnergy = m_energy;
+
+ ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
+ 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;
+
+ if ( m_type == OBJECT_POWER ||
+ m_type == OBJECT_ATOMIC )
+ {
+ a = 2.0f;
+ b = 0.0f; // dimensions of the battery (according to y)
+ }
+ if ( m_type == OBJECT_STATION )
+ {
+ a = 10.0f;
+ b = 4.0f; // dimensions of the battery (according to y)
+ }
+ if ( m_type == OBJECT_ENERGY )
+ {
+ a = 9.0f;
+ b = 3.0f; // dimensions of the battery (according to y)
+ }
+
+ i = 0.50f+0.25f*m_energy; // origin
+ s = i+0.25f; // width
+
+ au = (s-i)/(b-a);
+ bu = s-b*(s-i)/(b-a);
+
+ limit[0] = 0.0f;
+ limit[1] = m_engine->RetLimitLOD(0);
+ limit[2] = limit[1];
+ limit[3] = m_engine->RetLimitLOD(1);
+ limit[4] = limit[3];
+ limit[5] = 1000000.0f;
+
+ for ( j=0 ; j<3 ; j++ )
+ {
+ m_engine->ChangeTextureMapping(m_objectPart[0].object,
+ mat, D3DSTATEPART3, "lemt.tga", "",
+ limit[j*2+0], limit[j*2+1], D3DMAPPING1Y,
+ au, bu, 1.0f, 0.0f);
+ }
+}
+
+
+// Manual action.
+
+bool CObject::EventProcess(const Event &event)
+{
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if ADJUST_ONBOARD
+ if ( m_bSelect )
+ {
+ if ( event.param == 'E' ) debug_x += 0.1f;
+ if ( event.param == 'D' ) debug_x -= 0.1f;
+ if ( event.param == 'R' ) debug_y += 0.1f;
+ if ( event.param == 'F' ) debug_y -= 0.1f;
+ if ( event.param == 'T' ) debug_z += 0.1f;
+ if ( event.param == 'G' ) debug_z -= 0.1f;
+ }
+#endif
+#if ADJUST_ARM
+ if ( m_bSelect )
+ {
+ if ( event.param == 'X' ) debug_arm1 += 5.0f*Math::PI/180.0f;
+ if ( event.param == 'C' ) debug_arm1 -= 5.0f*Math::PI/180.0f;
+ if ( event.param == 'V' ) debug_arm2 += 5.0f*Math::PI/180.0f;
+ if ( event.param == 'B' ) debug_arm2 -= 5.0f*Math::PI/180.0f;
+ if ( event.param == 'N' ) debug_arm3 += 5.0f*Math::PI/180.0f;
+ if ( event.param == 'M' ) debug_arm3 -= 5.0f*Math::PI/180.0f;
+ if ( event.param == 'X' ||
+ event.param == 'C' ||
+ event.param == 'V' ||
+ event.param == 'B' ||
+ event.param == 'N' ||
+ event.param == 'M' )
+ {
+ SetAngleZ(1, debug_arm1);
+ SetAngleZ(2, debug_arm2);
+ SetAngleZ(3, debug_arm3);
+ char s[100];
+ sprintf(s, "a=%.2f b=%.2f c=%.2f", debug_arm1*180.0f/Math::PI, debug_arm2*180.0f/Math::PI, debug_arm3*180.0f/Math::PI);
+ m_engine->SetInfoText(5, s);
+ }
+ }
+#endif
+ }
+
+ if ( m_physics != 0 )
+ {
+ if ( !m_physics->EventProcess(event) ) // object destroyed?
+ {
+ if ( RetSelect() &&
+ m_type != OBJECT_ANT &&
+ m_type != OBJECT_SPIDER &&
+ m_type != OBJECT_BEE )
+ {
+ if ( !m_bDead ) m_camera->SetType(CAMERA_EXPLO);
+ m_main->DeselectAll();
+ }
+ return false;
+ }
+ }
+
+ if ( m_auto != 0 )
+ {
+ m_auto->EventProcess(event);
+
+ if ( event.event == EVENT_FRAME &&
+ m_auto->IsEnded() != ERR_CONTINUE )
+ {
+ m_auto->DeleteObject();
+ delete m_auto;
+ m_auto = 0;
+ }
+ }
+
+ if ( m_motion != 0 )
+ {
+ m_motion->EventProcess(event);
+ }
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ return true;
+}
+
+
+// Animates the object.
+
+bool CObject::EventFrame(const Event &event)
+{
+ if ( m_type == OBJECT_HUMAN && m_main->RetMainMovie() == MM_SATCOMopen )
+ {
+ UpdateTransformObject();
+ return true;
+ }
+
+ if ( m_type != OBJECT_SHOW && m_engine->RetPause() ) return true;
+
+ m_aTime += event.rTime;
+ m_shotTime += event.rTime;
+
+ VirusFrame(event.rTime);
+ PartiFrame(event.rTime);
+
+ UpdateMapping();
+ UpdateTransformObject();
+ UpdateSelectParticule();
+
+ if ( m_bProxyActivate ) // active if it is near?
+ {
+ CPyro* pyro;
+ Math::Vector eye;
+ float dist;
+
+ eye = m_engine->RetLookatPt();
+ dist = Math::Distance(eye, RetPosition(0));
+ if ( dist < m_proxyDistance )
+ {
+ m_bProxyActivate = false;
+ m_main->CreateShortcuts();
+ m_sound->Play(SOUND_FINDING);
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FINDING, this, 0.0f);
+ m_displayText->DisplayError(INFO_FINDING, this);
+ }
+ }
+
+ return true;
+}
+
+// Updates the mapping of the object.
+
+void CObject::UpdateMapping()
+{
+ if ( m_type == OBJECT_POWER ||
+ m_type == OBJECT_ATOMIC ||
+ m_type == OBJECT_STATION ||
+ m_type == OBJECT_ENERGY )
+ {
+ UpdateEnergyMapping();
+ }
+}
+
+
+// Management of viruses.
+
+void CObject::VirusFrame(float rTime)
+{
+ ParticuleType type;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ int r;
+
+ if ( !m_bVirusMode ) return; // healthy object?
+
+ m_virusTime += rTime;
+ if ( m_virusTime >= VIRUS_DELAY )
+ {
+ m_bVirusMode = false; // the virus is no longer active
+ }
+
+ if ( m_lastVirusParticule+m_engine->ParticuleAdapt(0.2f) <= m_aTime )
+ {
+ m_lastVirusParticule = m_aTime;
+
+ r = rand()%10;
+ if ( r == 0 ) type = PARTIVIRUS1;
+ if ( r == 1 ) type = PARTIVIRUS2;
+ if ( r == 2 ) type = PARTIVIRUS3;
+ if ( r == 3 ) type = PARTIVIRUS4;
+ if ( r == 4 ) type = PARTIVIRUS5;
+ if ( r == 5 ) type = PARTIVIRUS6;
+ if ( r == 6 ) type = PARTIVIRUS7;
+ if ( r == 7 ) type = PARTIVIRUS8;
+ if ( r == 8 ) type = PARTIVIRUS9;
+ if ( r == 9 ) type = PARTIVIRUS10;
+
+ pos = RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = Math::Rand()*4.0f+4.0f;
+ dim.x = Math::Rand()*0.3f+0.3f;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, type, 3.0f);
+ }
+}
+
+// Management particles mistresses.
+
+void CObject::PartiFrame(float rTime)
+{
+ Math::Vector pos, angle, factor;
+ int i, channel;
+
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ if ( !m_objectPart[i].bUsed ) continue;
+
+ channel = m_objectPart[i].masterParti;
+ if ( channel == -1 ) continue;
+
+ if ( !m_particule->GetPosition(channel, pos) )
+ {
+ m_objectPart[i].masterParti = -1; // particle no longer exists!
+ continue;
+ }
+
+ SetPosition(i, pos);
+
+ // Each song spins differently.
+ switch( i%5 )
+ {
+ case 0: factor = Math::Vector( 0.5f, 0.3f, 0.6f); break;
+ case 1: factor = Math::Vector(-0.3f, 0.4f,-0.2f); break;
+ case 2: factor = Math::Vector( 0.4f,-0.6f,-0.3f); break;
+ case 3: factor = Math::Vector(-0.6f,-0.2f, 0.0f); break;
+ case 4: factor = Math::Vector( 0.4f, 0.1f,-0.7f); break;
+ }
+
+ angle = RetAngle(i);
+ angle += rTime*Math::PI*factor;
+ SetAngle(i, angle);
+ }
+}
+
+
+// Changes the perspective to view if it was like in the vehicle,
+// or behind the vehicle.
+
+void CObject::SetViewFromHere(Math::Vector &eye, float &dirH, float &dirV,
+ Math::Vector &lookat, Math::Vector &upVec,
+ CameraType type)
+{
+ float speed;
+ int part;
+
+ UpdateTransformObject();
+
+ part = 0;
+ if ( m_type == OBJECT_HUMAN ||
+ m_type == OBJECT_TECH )
+ {
+ eye.x = -0.2f;
+ eye.y = 3.3f;
+ eye.z = 0.0f;
+//? eye.x = 1.0f;
+//? eye.y = 3.3f;
+//? eye.z = 0.0f;
+ }
+ else if ( m_type == OBJECT_MOBILErt ||
+ m_type == OBJECT_MOBILErr ||
+ m_type == OBJECT_MOBILErs )
+ {
+ eye.x = -1.1f; // on the cap
+ eye.y = 7.9f;
+ eye.z = 0.0f;
+ }
+ else if ( m_type == OBJECT_MOBILEwc ||
+ m_type == OBJECT_MOBILEtc ||
+ m_type == OBJECT_MOBILEfc ||
+ m_type == OBJECT_MOBILEic ) // fireball?
+ {
+//? eye.x = -0.9f; // on the cannon
+//? eye.y = 3.0f;
+//? eye.z = 0.0f;
+//? part = 1;
+ eye.x = -0.9f; // on the cannon
+ eye.y = 8.3f;
+ eye.z = 0.0f;
+ }
+ else if ( m_type == OBJECT_MOBILEwi ||
+ m_type == OBJECT_MOBILEti ||
+ m_type == OBJECT_MOBILEfi ||
+ m_type == OBJECT_MOBILEii ) // orgaball ?
+ {
+//? eye.x = -3.5f; // on the cannon
+//? eye.y = 5.1f;
+//? eye.z = 0.0f;
+//? part = 1;
+ eye.x = -2.5f; // on the cannon
+ eye.y = 10.4f;
+ eye.z = 0.0f;
+ }
+ else if ( m_type == OBJECT_MOBILErc )
+ {
+//? eye.x = 2.0f; // in the cannon
+//? eye.y = 0.0f;
+//? eye.z = 0.0f;
+//? part = 2;
+ eye.x = 4.0f; // on the cannon
+ eye.y = 11.0f;
+ eye.z = 0.0f;
+ }
+ else if ( m_type == OBJECT_MOBILEsa )
+ {
+ eye.x = 3.0f;
+ eye.y = 4.5f;
+ eye.z = 0.0f;
+ }
+ else if ( m_type == OBJECT_MOBILEdr )
+ {
+ eye.x = 1.0f;
+ eye.y = 6.5f;
+ eye.z = 0.0f;
+ }
+ else if ( m_type == OBJECT_APOLLO2 )
+ {
+ eye.x = -3.0f;
+ eye.y = 6.0f;
+ eye.z = -2.0f;
+ }
+ else
+ {
+ eye.x = 0.7f; // between the brackets
+ eye.y = 4.8f;
+ eye.z = 0.0f;
+ }
+#if ADJUST_ONBOARD
+ eye.x += debug_x;
+ eye.y += debug_y;
+ eye.z += debug_z;
+ char s[100];
+ sprintf(s, "x=%.2f y=%.2f z=%.2f", eye.x, eye.y, eye.z);
+ m_engine->SetInfoText(4, s);
+#endif
+
+ if ( type == CAMERA_BACK )
+ {
+ eye.x -= 20.0f;
+ eye.y += 1.0f;
+ }
+
+ lookat.x = eye.x+1.0f;
+ lookat.y = eye.y+0.0f;
+ lookat.z = eye.z+0.0f;
+
+ eye = Math::Transform(m_objectPart[part].matWorld, eye);
+ lookat = Math::Transform(m_objectPart[part].matWorld, lookat);
+
+ // Camera tilts when turning.
+ upVec = Math::Vector(0.0f, 1.0f, 0.0f);
+ if ( m_physics != 0 )
+ {
+ if ( m_physics->RetLand() ) // on ground?
+ {
+ speed = m_physics->RetLinMotionX(MO_REASPEED);
+ lookat.y -= speed*0.002f;
+
+ speed = m_physics->RetCirMotionY(MO_REASPEED);
+ upVec.z -= speed*0.04f;
+ }
+ else // in flight?
+ {
+ speed = m_physics->RetLinMotionX(MO_REASPEED);
+ lookat.y += speed*0.002f;
+
+ speed = m_physics->RetCirMotionY(MO_REASPEED);
+ upVec.z += speed*0.08f;
+ }
+ }
+ upVec = Math::Transform(m_objectPart[0].matRotate, upVec);
+
+ dirH = -(m_objectPart[part].angle.y+Math::PI/2.0f);
+ dirV = 0.0f;
+
+}
+
+
+// Management of features.
+
+void CObject::SetCharacter(Character* character)
+{
+ CopyMemory(&m_character, character, sizeof(Character));
+}
+
+void CObject::GetCharacter(Character* character)
+{
+ CopyMemory(character, &m_character, sizeof(Character));
+}
+
+Character* CObject::RetCharacter()
+{
+ return &m_character;
+}
+
+
+// Returns the absolute time.
+
+float CObject::RetAbsTime()
+{
+ return m_aTime;
+}
+
+
+// Management of energy contained in a battery.
+// Single subject possesses the battery energy, but not the vehicle that carries the battery!
+
+void CObject::SetEnergy(float level)
+{
+ if ( level < 0.0f ) level = 0.0f;
+ if ( level > 1.0f ) level = 1.0f;
+ m_energy = level;
+}
+
+float CObject::RetEnergy()
+{
+ if ( m_type != OBJECT_POWER &&
+ m_type != OBJECT_ATOMIC &&
+ m_type != OBJECT_STATION &&
+ m_type != OBJECT_ENERGY ) return 0.0f;
+ return m_energy;
+}
+
+
+// Management of the capacity of a battery.
+// Single subject possesses a battery capacity,
+// but not the vehicle that carries the battery!
+
+void CObject::SetCapacity(float capacity)
+{
+ m_capacity = capacity;
+}
+
+float CObject::RetCapacity()
+{
+ return m_capacity;
+}
+
+
+// Management of the shield.
+
+void CObject::SetShield(float level)
+{
+ m_shield = level;
+}
+
+float CObject::RetShield()
+{
+ if ( m_type == OBJECT_FRET ||
+ m_type == OBJECT_STONE ||
+ m_type == OBJECT_URANIUM ||
+ m_type == OBJECT_BULLET ||
+ m_type == OBJECT_METAL ||
+ m_type == OBJECT_BBOX ||
+ m_type == OBJECT_KEYa ||
+ m_type == OBJECT_KEYb ||
+ m_type == OBJECT_KEYc ||
+ m_type == OBJECT_KEYd ||
+ m_type == OBJECT_TNT ||
+ m_type == OBJECT_TEEN31 || // basket?
+ m_type == OBJECT_SCRAP1 ||
+ m_type == OBJECT_SCRAP2 ||
+ m_type == OBJECT_SCRAP3 ||
+ m_type == OBJECT_SCRAP4 ||
+ m_type == OBJECT_SCRAP5 ||
+ m_type == OBJECT_BOMB ||
+ m_type == OBJECT_WAYPOINT ||
+ m_type == OBJECT_FLAGb ||
+ m_type == OBJECT_FLAGr ||
+ m_type == OBJECT_FLAGg ||
+ m_type == OBJECT_FLAGy ||
+ m_type == OBJECT_FLAGv ||
+ m_type == OBJECT_POWER ||
+ m_type == OBJECT_ATOMIC ||
+ m_type == OBJECT_ANT ||
+ m_type == OBJECT_SPIDER ||
+ m_type == OBJECT_BEE ||
+ m_type == OBJECT_WORM ) return 0.0f;
+ return m_shield;
+}
+
+
+// Management of flight range (zero = infinity).
+
+void CObject::SetRange(float delay)
+{
+ m_range = delay;
+}
+
+float CObject::RetRange()
+{
+ return m_range;
+}
+
+
+// Management of transparency of the object.
+
+void CObject::SetTransparency(float value)
+{
+ int i;
+
+ m_transparency = value;
+
+ for ( i=0 ; i<m_totalPart ; i++ )
+ {
+ if ( m_objectPart[i].bUsed )
+ {
+ if ( m_type == OBJECT_BASE )
+ {
+ if ( i != 9 ) continue; // no central pillar?
+ }
+
+ m_engine->SetObjectTransparency(m_objectPart[i].object, value);
+ }
+ }
+}
+
+float CObject::RetTransparency()
+{
+ return m_transparency;
+}
+
+
+// Management of the object matter.
+
+ObjectMaterial CObject::RetMaterial()
+{
+ if ( m_type == OBJECT_HUMAN )
+ {
+ return OM_HUMAN;
+ }
+
+ if ( m_type == OBJECT_SCRAP4 ||
+ m_type == OBJECT_SCRAP5 )
+ {
+ return OM_HUMAN;
+ }
+
+ return OM_METAL;
+}
+
+
+// Indicates whether the gadget is a nonessential.
+
+void CObject::SetGadget(bool bMode)
+{
+ m_bGadget = bMode;
+}
+
+bool CObject::RetGadget()
+{
+ return m_bGadget;
+}
+
+
+// Indicates whether an object is stationary (ant on the back).
+
+void CObject::SetFixed(bool bFixed)
+{
+ m_bFixed = bFixed;
+}
+
+bool CObject::RetFixed()
+{
+ return m_bFixed;
+}
+
+
+// Indicates whether an object is subjected to clipping (obstacles).
+
+void CObject::SetClip(bool bClip)
+{
+ m_bClip = bClip;
+}
+
+bool CObject::RetClip()
+{
+ return m_bClip;
+}
+
+
+
+// Pushes an object.
+
+bool CObject::JostleObject(float force)
+{
+ CAutoJostle* pa;
+
+ if ( m_type == OBJECT_FLAGb ||
+ m_type == OBJECT_FLAGr ||
+ m_type == OBJECT_FLAGg ||
+ m_type == OBJECT_FLAGy ||
+ m_type == OBJECT_FLAGv ) // flag?
+ {
+ if ( m_auto == 0 ) return false;
+
+ m_auto->Start(1);
+ }
+ else
+ {
+ if ( m_auto != 0 ) return false;
+
+ m_auto = new CAutoJostle(m_iMan, this);
+ pa = (CAutoJostle*)m_auto;
+ pa->Start(0, force);
+ }
+
+ return true;
+}
+
+
+// Beginning of the effect when the instruction "detect" is used.
+
+void CObject::StartDetectEffect(CObject *target, bool bFound)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, goal;
+ Math::Point dim;
+
+ mat = RetWorldMatrix(0);
+ pos = Math::Transform(*mat, Math::Vector(2.0f, 3.0f, 0.0f));
+
+ if ( target == 0 )
+ {
+ goal = Math::Transform(*mat, Math::Vector(50.0f, 3.0f, 0.0f));
+ }
+ else
+ {
+ goal = target->RetPosition(0);
+ goal.y += 3.0f;
+ goal = Math::SegmentPoint(pos, goal, Math::Distance(pos, goal)-3.0f);
+ }
+
+ dim.x = 3.0f;
+ dim.y = dim.x;
+ m_particule->CreateRay(pos, goal, PARTIRAY2, dim, 0.2f);
+
+ if ( target != 0 )
+ {
+ goal = target->RetPosition(0);
+ goal.y += 3.0f;
+ goal = Math::SegmentPoint(pos, goal, Math::Distance(pos, goal)-1.0f);
+ dim.x = 6.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(goal, Math::Vector(0.0f, 0.0f, 0.0f), dim,
+ bFound?PARTIGLINT:PARTIGLINTr, 0.5f);
+ }
+
+ m_sound->Play(bFound?SOUND_BUILD:SOUND_RECOVER);
+}
+
+
+// Management of time from which a virus is active.
+
+void CObject::SetVirusMode(bool bEnable)
+{
+ m_bVirusMode = bEnable;
+ m_virusTime = 0.0f;
+
+ if ( m_bVirusMode && m_brain != 0 )
+ {
+ if ( !m_brain->IntroduceVirus() ) // tries to infect
+ {
+ m_bVirusMode = false; // program was not contaminated!
+ }
+ }
+}
+
+bool CObject::RetVirusMode()
+{
+ return m_bVirusMode;
+}
+
+float CObject::RetVirusTime()
+{
+ return m_virusTime;
+}
+
+
+// Management mode of the camera.
+
+void CObject::SetCameraType(CameraType type)
+{
+ m_cameraType = type;
+}
+
+CameraType CObject::RetCameraType()
+{
+ return m_cameraType;
+}
+
+void CObject::SetCameraDist(float dist)
+{
+ m_cameraDist = dist;
+}
+
+float CObject::RetCameraDist()
+{
+ return m_cameraDist;
+}
+
+void CObject::SetCameraLock(bool bLock)
+{
+ m_bCameraLock = bLock;
+}
+
+bool CObject::RetCameraLock()
+{
+ return m_bCameraLock;
+}
+
+
+
+// Management of the demonstration of the object.
+
+void CObject::SetHilite(bool bMode)
+{
+ int list[OBJECTMAXPART+1];
+ int i, j;
+
+ m_bHilite = bMode;
+
+ if ( m_bHilite )
+ {
+ j = 0;
+ for ( i=0 ; i<m_totalPart ; i++ )
+ {
+ if ( m_objectPart[i].bUsed )
+ {
+ list[j++] = m_objectPart[i].object;
+ }
+ }
+ list[j] = -1; // terminate
+
+ m_engine->SetHiliteRank(list); // gives the list of selected parts
+ }
+}
+
+bool CObject::RetHilite()
+{
+ return m_bHilite;
+}
+
+
+// Indicates whether the object is selected or not.
+
+void CObject::SetSelect(bool bMode, bool bDisplayError)
+{
+ Error err;
+
+ m_bSelect = bMode;
+
+ if ( m_physics != 0 )
+ {
+ m_physics->CreateInterface(m_bSelect);
+ }
+
+ if ( m_auto != 0 )
+ {
+ m_auto->CreateInterface(m_bSelect);
+ }
+
+ CreateSelectParticule(); // creates / removes particles
+
+ if ( !m_bSelect )
+ {
+ SetGunGoalH(0.0f); // puts the cannon right
+ return; // selects if not finished
+ }
+
+ err = ERR_OK;
+ if ( m_physics != 0 )
+ {
+ err = m_physics->RetError();
+ }
+ if ( m_auto != 0 )
+ {
+ err = m_auto->RetError();
+ }
+ if ( err != ERR_OK && bDisplayError )
+ {
+ m_displayText->DisplayError(err, this);
+ }
+}
+
+// Indicates whether the object is selected or not.
+
+bool CObject::RetSelect(bool bReal)
+{
+ if ( !bReal && m_main->RetFixScene() ) return false;
+ return m_bSelect;
+}
+
+
+// Indicates whether the object is selectable or not.
+
+void CObject::SetSelectable(bool bMode)
+{
+ m_bSelectable = bMode;
+}
+
+// Indicates whether the object is selecionnable or not.
+
+bool CObject::RetSelectable()
+{
+ return m_bSelectable;
+}
+
+
+// Management of the activities of an object.
+
+void CObject::SetActivity(bool bMode)
+{
+ if ( m_brain != 0 )
+ {
+ m_brain->SetActivity(bMode);
+ }
+}
+
+bool CObject::RetActivity()
+{
+ if ( m_brain != 0 )
+ {
+ return m_brain->RetActivity();
+ }
+ return false;
+}
+
+
+// Indicates if necessary to check the tokens of the object.
+
+void CObject::SetCheckToken(bool bMode)
+{
+ m_bCheckToken = bMode;
+}
+
+// Indicates if necessary to check the tokens of the object.
+
+bool CObject::RetCheckToken()
+{
+ return m_bCheckToken;
+}
+
+
+// Management of the visibility of an object.
+// The object is not hidden or visually disabled, but ignores detections!
+// For example: underground worm.
+
+void CObject::SetVisible(bool bVisible)
+{
+ m_bVisible = bVisible;
+}
+
+bool CObject::RetVisible()
+{
+ return m_bVisible;
+}
+
+
+// Management mode of operation of an object.
+// An inactive object is an object destroyed, nonexistent.
+// This mode is used for objects "resetables"
+// during training to simulate destruction.
+
+void CObject::SetEnable(bool bEnable)
+{
+ m_bEnable = bEnable;
+}
+
+bool CObject::RetEnable()
+{
+ return m_bEnable;
+}
+
+
+// Management mode or an object is only active when you're close.
+
+void CObject::SetProxyActivate(bool bActivate)
+{
+ m_bProxyActivate = bActivate;
+}
+
+bool CObject::RetProxyActivate()
+{
+ return m_bProxyActivate;
+}
+
+void CObject::SetProxyDistance(float distance)
+{
+ m_proxyDistance = distance;
+}
+
+float CObject::RetProxyDistance()
+{
+ return m_proxyDistance;
+}
+
+
+// Management of the method of increasing damage.
+
+void CObject::SetMagnifyDamage(float factor)
+{
+ m_magnifyDamage = factor;
+}
+
+float CObject::RetMagnifyDamage()
+{
+ return m_magnifyDamage;
+}
+
+
+// Management of free parameter.
+
+void CObject::SetParam(float value)
+{
+ m_param = value;
+}
+
+float CObject::RetParam()
+{
+ return m_param;
+}
+
+
+// Management of the mode "blocked" of an object.
+// For example, a cube of titanium is blocked while it is used to make something,
+//or a vehicle is blocked as its construction is not finished.
+
+void CObject::SetLock(bool bLock)
+{
+ m_bLock = bLock;
+}
+
+bool CObject::RetLock()
+{
+ return m_bLock;
+}
+
+// Management of the mode "current explosion" of an object.
+// An object in this mode is not saving.
+
+void CObject::SetExplo(bool bExplo)
+{
+ m_bExplo = bExplo;
+}
+
+bool CObject::RetExplo()
+{
+ return m_bExplo;
+}
+
+
+// Mode management "cargo ship" during movies.
+
+void CObject::SetCargo(bool bCargo)
+{
+ m_bCargo = bCargo;
+}
+
+bool CObject::RetCargo()
+{
+ return m_bCargo;
+}
+
+
+// Management of the HS mode of an object.
+
+void CObject::SetBurn(bool bBurn)
+{
+ m_bBurn = bBurn;
+
+//? if ( m_botVar != 0 )
+//? {
+//? if ( m_bBurn ) m_botVar->SetUserPtr(OBJECTDELETED);
+//? else m_botVar->SetUserPtr(this);
+//? }
+}
+
+bool CObject::RetBurn()
+{
+ return m_bBurn;
+}
+
+void CObject::SetDead(bool bDead)
+{
+ m_bDead = bDead;
+
+ if ( bDead && m_brain != 0 )
+ {
+ m_brain->StopProgram(); // stops the current task
+ }
+
+//? if ( m_botVar != 0 )
+//? {
+//? if ( m_bDead ) m_botVar->SetUserPtr(OBJECTDELETED);
+//? else m_botVar->SetUserPtr(this);
+//? }
+}
+
+bool CObject::RetDead()
+{
+ return m_bDead;
+}
+
+bool CObject::RetRuin()
+{
+ return m_bBurn|m_bFlat;
+}
+
+bool CObject::RetActif()
+{
+ return !m_bLock && !m_bBurn && !m_bFlat && m_bVisible && m_bEnable;
+}
+
+
+// Management of the point of aim.
+
+void CObject::SetGunGoalV(float gunGoal)
+{
+ if ( m_type == OBJECT_MOBILEfc ||
+ m_type == OBJECT_MOBILEtc ||
+ m_type == OBJECT_MOBILEwc ||
+ m_type == OBJECT_MOBILEic ) // fireball?
+ {
+ if ( gunGoal > 10.0f*Math::PI/180.0f ) gunGoal = 10.0f*Math::PI/180.0f;
+ if ( gunGoal < -20.0f*Math::PI/180.0f ) gunGoal = -20.0f*Math::PI/180.0f;
+ SetAngleZ(1, gunGoal);
+ }
+ else if ( m_type == OBJECT_MOBILEfi ||
+ m_type == OBJECT_MOBILEti ||
+ m_type == OBJECT_MOBILEwi ||
+ m_type == OBJECT_MOBILEii ) // orgaball?
+ {
+ if ( gunGoal > 20.0f*Math::PI/180.0f ) gunGoal = 20.0f*Math::PI/180.0f;
+ if ( gunGoal < -20.0f*Math::PI/180.0f ) gunGoal = -20.0f*Math::PI/180.0f;
+ SetAngleZ(1, gunGoal);
+ }
+ else if ( m_type == OBJECT_MOBILErc ) // phazer?
+ {
+ if ( gunGoal > 45.0f*Math::PI/180.0f ) gunGoal = 45.0f*Math::PI/180.0f;
+ if ( gunGoal < -20.0f*Math::PI/180.0f ) gunGoal = -20.0f*Math::PI/180.0f;
+ SetAngleZ(2, gunGoal);
+ }
+ else
+ {
+ gunGoal = 0.0f;
+ }
+
+ m_gunGoalV = gunGoal;
+}
+
+void CObject::SetGunGoalH(float gunGoal)
+{
+ if ( m_type == OBJECT_MOBILEfc ||
+ m_type == OBJECT_MOBILEtc ||
+ m_type == OBJECT_MOBILEwc ||
+ m_type == OBJECT_MOBILEic ) // fireball?
+ {
+ if ( gunGoal > 40.0f*Math::PI/180.0f ) gunGoal = 40.0f*Math::PI/180.0f;
+ if ( gunGoal < -40.0f*Math::PI/180.0f ) gunGoal = -40.0f*Math::PI/180.0f;
+ SetAngleY(1, gunGoal);
+ }
+ else if ( m_type == OBJECT_MOBILEfi ||
+ m_type == OBJECT_MOBILEti ||
+ m_type == OBJECT_MOBILEwi ||
+ m_type == OBJECT_MOBILEii ) // orgaball?
+ {
+ if ( gunGoal > 40.0f*Math::PI/180.0f ) gunGoal = 40.0f*Math::PI/180.0f;
+ if ( gunGoal < -40.0f*Math::PI/180.0f ) gunGoal = -40.0f*Math::PI/180.0f;
+ SetAngleY(1, gunGoal);
+ }
+ else if ( m_type == OBJECT_MOBILErc ) // phazer?
+ {
+ if ( gunGoal > 40.0f*Math::PI/180.0f ) gunGoal = 40.0f*Math::PI/180.0f;
+ if ( gunGoal < -40.0f*Math::PI/180.0f ) gunGoal = -40.0f*Math::PI/180.0f;
+ SetAngleY(2, gunGoal);
+ }
+ else
+ {
+ gunGoal = 0.0f;
+ }
+
+ m_gunGoalH = gunGoal;
+}
+
+float CObject::RetGunGoalV()
+{
+ return m_gunGoalV;
+}
+
+float CObject::RetGunGoalH()
+{
+ return m_gunGoalH;
+}
+
+
+
+// Shows the limits of the object.
+
+bool CObject::StartShowLimit()
+{
+ if ( m_showLimitRadius == 0.0f ) return false;
+
+ m_main->SetShowLimit(0, PARTILIMIT1, this, RetPosition(0), m_showLimitRadius);
+ m_bShowLimit = true;
+ return true;
+}
+
+void CObject::StopShowLimit()
+{
+ m_bShowLimit = false;
+}
+
+
+
+// Indicates whether a program is under execution.
+
+bool CObject::IsProgram()
+{
+ if ( m_brain == 0 ) return false;
+ return m_brain->IsProgram();
+}
+
+
+// Creates or removes particles associated to the object.
+
+void CObject::CreateSelectParticule()
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+ int i;
+
+ // Removes particles preceding.
+ for ( i=0 ; i<4 ; i++ )
+ {
+ if ( m_partiSel[i] != -1 )
+ {
+ m_particule->DeleteParticule(m_partiSel[i]);
+ m_partiSel[i] = -1;
+ }
+ }
+
+ if ( m_bSelect || IsProgram() )
+ {
+ // Creates particles lens for the headlights.
+ if ( m_type == OBJECT_MOBILEfa ||
+ m_type == OBJECT_MOBILEta ||
+ m_type == OBJECT_MOBILEwa ||
+ m_type == OBJECT_MOBILEia ||
+ m_type == OBJECT_MOBILEfc ||
+ m_type == OBJECT_MOBILEtc ||
+ m_type == OBJECT_MOBILEwc ||
+ m_type == OBJECT_MOBILEic ||
+ m_type == OBJECT_MOBILEfi ||
+ m_type == OBJECT_MOBILEti ||
+ m_type == OBJECT_MOBILEwi ||
+ m_type == OBJECT_MOBILEii ||
+ m_type == OBJECT_MOBILEfs ||
+ m_type == OBJECT_MOBILEts ||
+ m_type == OBJECT_MOBILEws ||
+ m_type == OBJECT_MOBILEis ||
+ m_type == OBJECT_MOBILErt ||
+ m_type == OBJECT_MOBILErc ||
+ m_type == OBJECT_MOBILErr ||
+ m_type == OBJECT_MOBILErs ||
+ m_type == OBJECT_MOBILEsa ||
+ m_type == OBJECT_MOBILEtg ||
+ m_type == OBJECT_MOBILEft ||
+ m_type == OBJECT_MOBILEtt ||
+ m_type == OBJECT_MOBILEwt ||
+ m_type == OBJECT_MOBILEit ||
+ m_type == OBJECT_MOBILEdr ) // vehicle?
+ {
+ pos = Math::Vector(0.0f, 0.0f, 0.0f);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 0.0f;
+ dim.y = 0.0f;
+ m_partiSel[0] = m_particule->CreateParticule(pos, speed, dim, PARTISELY, 1.0f, 0.0f, 0.0f);
+ m_partiSel[1] = m_particule->CreateParticule(pos, speed, dim, PARTISELY, 1.0f, 0.0f, 0.0f);
+ m_partiSel[2] = m_particule->CreateParticule(pos, speed, dim, PARTISELR, 1.0f, 0.0f, 0.0f);
+ m_partiSel[3] = m_particule->CreateParticule(pos, speed, dim, PARTISELR, 1.0f, 0.0f, 0.0f);
+ UpdateSelectParticule();
+ }
+ }
+}
+
+// Updates the particles associated to the object.
+
+void CObject::UpdateSelectParticule()
+{
+ Math::Vector pos[4];
+ Math::Point dim[4];
+ float zoom[4];
+ float angle;
+ int i;
+
+ if ( !m_bSelect && !IsProgram() ) return;
+
+ dim[0].x = 1.0f;
+ dim[1].x = 1.0f;
+ dim[2].x = 1.2f;
+ dim[3].x = 1.2f;
+
+ // Lens front yellow.
+ if ( m_type == OBJECT_MOBILErt ||
+ m_type == OBJECT_MOBILErc ||
+ m_type == OBJECT_MOBILErr ||
+ m_type == OBJECT_MOBILErs ) // large caterpillars?
+ {
+ pos[0] = Math::Vector(4.2f, 2.8f, 1.5f);
+ pos[1] = Math::Vector(4.2f, 2.8f, -1.5f);
+ dim[0].x = 1.5f;
+ dim[1].x = 1.5f;
+ }
+ else if ( m_type == OBJECT_MOBILEwt ||
+ m_type == OBJECT_MOBILEtt ||
+ m_type == OBJECT_MOBILEft ||
+ m_type == OBJECT_MOBILEit ) // trainer ?
+ {
+ pos[0] = Math::Vector(4.2f, 2.5f, 1.2f);
+ pos[1] = Math::Vector(4.2f, 2.5f, -1.2f);
+ dim[0].x = 1.5f;
+ dim[1].x = 1.5f;
+ }
+ else if ( m_type == OBJECT_MOBILEsa ) // submarine?
+ {
+ pos[0] = Math::Vector(3.6f, 4.0f, 2.0f);
+ pos[1] = Math::Vector(3.6f, 4.0f, -2.0f);
+ }
+ else if ( m_type == OBJECT_MOBILEtg ) // target?
+ {
+ pos[0] = Math::Vector(3.4f, 6.5f, 2.0f);
+ pos[1] = Math::Vector(3.4f, 6.5f, -2.0f);
+ }
+ else if ( m_type == OBJECT_MOBILEdr ) // designer?
+ {
+ pos[0] = Math::Vector(4.9f, 3.5f, 2.5f);
+ pos[1] = Math::Vector(4.9f, 3.5f, -2.5f);
+ }
+ else
+ {
+ pos[0] = Math::Vector(4.2f, 2.5f, 1.5f);
+ pos[1] = Math::Vector(4.2f, 2.5f, -1.5f);
+ }
+
+ // Red back lens
+ if ( m_type == OBJECT_MOBILEfa ||
+ m_type == OBJECT_MOBILEfc ||
+ m_type == OBJECT_MOBILEfi ||
+ m_type == OBJECT_MOBILEfs ||
+ m_type == OBJECT_MOBILEft ) // flying?
+ {
+ pos[2] = Math::Vector(-4.0f, 3.1f, 4.5f);
+ pos[3] = Math::Vector(-4.0f, 3.1f, -4.5f);
+ dim[2].x = 0.6f;
+ dim[3].x = 0.6f;
+ }
+ if ( m_type == OBJECT_MOBILEwa ||
+ m_type == OBJECT_MOBILEwc ||
+ m_type == OBJECT_MOBILEwi ||
+ m_type == OBJECT_MOBILEws ) // wheels?
+ {
+ pos[2] = Math::Vector(-4.5f, 2.7f, 2.8f);
+ pos[3] = Math::Vector(-4.5f, 2.7f, -2.8f);
+ }
+ if ( m_type == OBJECT_MOBILEwt ) // wheels?
+ {
+ pos[2] = Math::Vector(-4.0f, 2.5f, 2.2f);
+ pos[3] = Math::Vector(-4.0f, 2.5f, -2.2f);
+ }
+ if ( m_type == OBJECT_MOBILEia ||
+ m_type == OBJECT_MOBILEic ||
+ m_type == OBJECT_MOBILEii ||
+ m_type == OBJECT_MOBILEis ||
+ m_type == OBJECT_MOBILEit ) // legs?
+ {
+ pos[2] = Math::Vector(-4.5f, 2.7f, 2.8f);
+ pos[3] = Math::Vector(-4.5f, 2.7f, -2.8f);
+ }
+ if ( m_type == OBJECT_MOBILEta ||
+ m_type == OBJECT_MOBILEtc ||
+ m_type == OBJECT_MOBILEti ||
+ m_type == OBJECT_MOBILEts ||
+ m_type == OBJECT_MOBILEtt ) // caterpillars?
+ {
+ pos[2] = Math::Vector(-3.6f, 4.2f, 3.0f);
+ pos[3] = Math::Vector(-3.6f, 4.2f, -3.0f);
+ }
+ if ( m_type == OBJECT_MOBILErt ||
+ m_type == OBJECT_MOBILErc ||
+ m_type == OBJECT_MOBILErr ||
+ m_type == OBJECT_MOBILErs ) // large caterpillars?
+ {
+ pos[2] = Math::Vector(-5.0f, 5.2f, 2.5f);
+ pos[3] = Math::Vector(-5.0f, 5.2f, -2.5f);
+ }
+ if ( m_type == OBJECT_MOBILEsa ) // submarine?
+ {
+ pos[2] = Math::Vector(-3.6f, 4.0f, 2.0f);
+ pos[3] = Math::Vector(-3.6f, 4.0f, -2.0f);
+ }
+ if ( m_type == OBJECT_MOBILEtg ) // target?
+ {
+ pos[2] = Math::Vector(-2.4f, 6.5f, 2.0f);
+ pos[3] = Math::Vector(-2.4f, 6.5f, -2.0f);
+ }
+ if ( m_type == OBJECT_MOBILEdr ) // designer?
+ {
+ pos[2] = Math::Vector(-5.3f, 2.7f, 1.8f);
+ pos[3] = Math::Vector(-5.3f, 2.7f, -1.8f);
+ }
+
+ angle = RetAngleY(0)/Math::PI;
+
+ zoom[0] = 1.0f;
+ zoom[1] = 1.0f;
+ zoom[2] = 1.0f;
+ zoom[3] = 1.0f;
+
+ if ( IsProgram() && // current program?
+ Math::Mod(m_aTime, 0.7f) < 0.3f )
+ {
+ zoom[0] = 0.0f; // blinks
+ zoom[1] = 0.0f;
+ zoom[2] = 0.0f;
+ zoom[3] = 0.0f;
+ }
+
+ // Updates lens.
+ for ( i=0 ; i<4 ; i++ )
+ {
+ pos[i] = Math::Transform(m_objectPart[0].matWorld, pos[i]);
+ dim[i].y = dim[i].x;
+ m_particule->SetParam(m_partiSel[i], pos[i], dim[i], zoom[i], angle, 1.0f);
+ }
+}
+
+
+// Gives the pointer to the current script execution.
+
+void CObject::SetRunScript(CScript* script)
+{
+ m_runScript = script;
+}
+
+CScript* CObject::RetRunScript()
+{
+ return m_runScript;
+}
+
+// Returns the variables of "this" for CBOT.
+
+CBotVar* CObject::RetBotVar()
+{
+ return m_botVar;
+}
+
+// Returns the physics associated to the object.
+
+CPhysics* CObject::RetPhysics()
+{
+ return m_physics;
+}
+
+// Returns the brain associated to the object.
+
+CBrain* CObject::RetBrain()
+{
+ return m_brain;
+}
+
+// Returns the movement associated to the object.
+
+CMotion* CObject::RetMotion()
+{
+ return m_motion;
+}
+
+// Returns the controller associated to the object.
+
+CAuto* CObject::RetAuto()
+{
+ return m_auto;
+}
+
+void CObject::SetAuto(CAuto* automat)
+{
+ m_auto = automat;
+}
+
+
+
+// Management of the position in the file definition.
+
+void CObject::SetDefRank(int rank)
+{
+ m_defRank = rank;
+}
+
+int CObject::RetDefRank()
+{
+ return m_defRank;
+}
+
+
+// Gives the object name for the tooltip.
+
+bool CObject::GetTooltipName(char* name)
+{
+ GetResource(RES_OBJECT, m_type, name);
+ return ( name[0] != 0 );
+}
+
+
+// Adds the object previously selected in the list.
+
+void CObject::AddDeselList(CObject* pObj)
+{
+ int i;
+
+ if ( m_totalDesectList >= OBJECTMAXDESELLIST )
+ {
+ for ( i=0 ; i<OBJECTMAXDESELLIST-1 ; i++ )
+ {
+ m_objectDeselectList[i] = m_objectDeselectList[i+1];
+ }
+ m_totalDesectList --;
+ }
+
+ m_objectDeselectList[m_totalDesectList++] = pObj;
+}
+
+// Removes the previously selected object in the list.
+
+CObject* CObject::SubDeselList()
+{
+ if ( m_totalDesectList == 0 ) return 0;
+
+ return m_objectDeselectList[--m_totalDesectList];
+}
+
+// Removes an object reference if it is in the list.
+
+void CObject::DeleteDeselList(CObject* pObj)
+{
+ int i, j;
+
+ j = 0;
+ for ( i=0 ; i<m_totalDesectList ; i++ )
+ {
+ if ( m_objectDeselectList[i] != pObj )
+ {
+ m_objectDeselectList[j++] = m_objectDeselectList[i];
+ }
+ }
+ m_totalDesectList = j;
+}
+
+
+
+// Management of the state of the pencil drawing robot.
+
+bool CObject::RetTraceDown()
+{
+ CMotionVehicle* mv;
+ if ( m_motion == 0 ) return false;
+ mv = (CMotionVehicle*)m_motion;
+ return mv->RetTraceDown();
+}
+
+void CObject::SetTraceDown(bool bDown)
+{
+ CMotionVehicle* mv;
+ if ( m_motion == 0 ) return;
+ mv = (CMotionVehicle*)m_motion;
+ mv->SetTraceDown(bDown);
+}
+
+int CObject::RetTraceColor()
+{
+ CMotionVehicle* mv;
+ if ( m_motion == 0 ) return 0;
+ mv = (CMotionVehicle*)m_motion;
+ return mv->RetTraceColor();
+}
+
+void CObject::SetTraceColor(int color)
+{
+ CMotionVehicle* mv;
+ if ( m_motion == 0 ) return;
+ mv = (CMotionVehicle*)m_motion;
+ mv->SetTraceColor(color);
+}
+
+float CObject::RetTraceWidth()
+{
+ CMotionVehicle* mv;
+ if ( m_motion == 0 ) return 0.0f;
+ mv = (CMotionVehicle*)m_motion;
+ return mv->RetTraceWidth();
+}
+
+void CObject::SetTraceWidth(float width)
+{
+ CMotionVehicle* mv;
+ if ( m_motion == 0 ) return;
+ mv = (CMotionVehicle*)m_motion;
+ mv->SetTraceWidth(width);
+}
+
+
diff --git a/src/object/object.h b/src/object/object.h
index 735da8a..75283d6 100644
--- a/src/object/object.h
+++ b/src/object/object.h
@@ -1,775 +1,775 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// object.h
-
-#pragma once
-
-
-#include "old/d3dengine.h"
-#include "old/camera.h"
-#include "old/sound.h"
-
-
-class CInstanceManager;
-class CLight;
-class CTerrain;
-class CWater;
-class CParticule;
-class CPhysics;
-class CBrain;
-class CMotion;
-class CAuto;
-class CDisplayText;
-class CRobotMain;
-class CBotVar;
-class CScript;
-
-
-
-// The father of all parts must always be the part number zero!
-
-const int OBJECTMAXPART = 40;
-const int MAXCRASHSPHERE = 40;
-const int OBJECTMAXDESELLIST = 10;
-const int OBJECTMAXINFO = 10;
-const int OBJECTMAXCMDLINE = 20;
-
-enum ObjectType
-{
- OBJECT_NULL = 0, // object destroyed
- OBJECT_FIX = 1, // stationary scenery
- OBJECT_PORTICO = 2, // gantry
- OBJECT_BASE = 3, // great main base
- OBJECT_DERRICK = 4, // derrick set
- OBJECT_FACTORY = 5, // factory set
- OBJECT_STATION = 6, // recharging station
- OBJECT_CONVERT = 7, // converter station
- OBJECT_REPAIR = 8, // reparation
- OBJECT_TOWER = 9, // defense tower
- OBJECT_NEST = 10, // nest
- OBJECT_RESEARCH = 11, // research center
- OBJECT_RADAR = 12, // radar
- OBJECT_ENERGY = 13, // energy factory
- OBJECT_LABO = 14, // analytical laboratory for insect
- OBJECT_NUCLEAR = 15, // nuclear power plant
- OBJECT_START = 16, // starting
- OBJECT_END = 17, // finish
- OBJECT_INFO = 18, // information terminal
- OBJECT_PARA = 19, // lightning conductor
- OBJECT_TARGET1 = 20, // gate target
- OBJECT_TARGET2 = 21, // center target
- OBJECT_SAFE = 22, // safe
- OBJECT_HUSTON = 23, // control centre
- OBJECT_DESTROYER = 24, // destroyer
- OBJECT_FRET = 30, // transportable
- OBJECT_STONE = 31, // stone
- OBJECT_URANIUM = 32, // uranium
- OBJECT_METAL = 33, // metal
- OBJECT_POWER = 34, // normal battery
- OBJECT_ATOMIC = 35, // atomic battery
- OBJECT_BULLET = 36, // bullet
- OBJECT_BBOX = 37, // black-box
- OBJECT_TNT = 38, // box of TNT
- OBJECT_SCRAP1 = 40, // metal waste
- OBJECT_SCRAP2 = 41, // metal waste
- OBJECT_SCRAP3 = 42, // metal waste
- OBJECT_SCRAP4 = 43, // plastic waste
- OBJECT_SCRAP5 = 44, // plastic waste
- OBJECT_MARKPOWER = 50, // mark underground energy source
- OBJECT_MARKSTONE = 51, // mark underground ore
- OBJECT_MARKURANIUM = 52, // mark underground uranium
- OBJECT_MARKKEYa = 53, // mark underground key
- OBJECT_MARKKEYb = 54, // mark underground key
- OBJECT_MARKKEYc = 55, // mark underground key
- OBJECT_MARKKEYd = 56, // mark underground key
- OBJECT_BOMB = 60, // bomb
- OBJECT_WINFIRE = 61, // fireworks
- OBJECT_SHOW = 62, // shows a place
- OBJECT_BAG = 63, // survival bag
- OBJECT_PLANT0 = 70, // plant 0
- OBJECT_PLANT1 = 71, // plant 1
- OBJECT_PLANT2 = 72, // plant 2
- OBJECT_PLANT3 = 73, // plant 3
- OBJECT_PLANT4 = 74, // plant 4
- OBJECT_PLANT5 = 75, // plant 5
- OBJECT_PLANT6 = 76, // plant 6
- OBJECT_PLANT7 = 77, // plant 7
- OBJECT_PLANT8 = 78, // plant 8
- OBJECT_PLANT9 = 79, // plant 9
- OBJECT_PLANT10 = 80, // plant 10
- OBJECT_PLANT11 = 81, // plant 11
- OBJECT_PLANT12 = 82, // plant 12
- OBJECT_PLANT13 = 83, // plant 13
- OBJECT_PLANT14 = 84, // plant 14
- OBJECT_PLANT15 = 85, // plant 15
- OBJECT_PLANT16 = 86, // plant 16
- OBJECT_PLANT17 = 87, // plant 17
- OBJECT_PLANT18 = 88, // plant 18
- OBJECT_PLANT19 = 89, // plant 19
- OBJECT_TREE0 = 90, // tree 0
- OBJECT_TREE1 = 91, // tree 1
- OBJECT_TREE2 = 92, // tree 2
- OBJECT_TREE3 = 93, // tree 3
- OBJECT_TREE4 = 94, // tree 4
- OBJECT_TREE5 = 95, // tree 5
- OBJECT_TREE6 = 96, // tree 6
- OBJECT_TREE7 = 97, // tree 7
- OBJECT_TREE8 = 98, // tree 8
- OBJECT_TREE9 = 99, // tree 9
- OBJECT_MOBILEwt = 100, // wheel-trainer
- OBJECT_MOBILEtt = 101, // track-trainer
- OBJECT_MOBILEft = 102, // fly-trainer
- OBJECT_MOBILEit = 103, // insect-trainer
- OBJECT_MOBILEwa = 110, // wheel-arm
- OBJECT_MOBILEta = 111, // track-arm
- OBJECT_MOBILEfa = 112, // fly-arm
- OBJECT_MOBILEia = 113, // insect-arm
- OBJECT_MOBILEwc = 120, // wheel-cannon
- OBJECT_MOBILEtc = 121, // track-cannon
- OBJECT_MOBILEfc = 122, // fly-cannon
- OBJECT_MOBILEic = 123, // insect-cannon
- OBJECT_MOBILEwi = 130, // wheel-insect-cannon
- OBJECT_MOBILEti = 131, // track-insect-cannon
- OBJECT_MOBILEfi = 132, // fly-insect-cannon
- OBJECT_MOBILEii = 133, // insect-insect-cannon
- OBJECT_MOBILEws = 140, // wheel-search
- OBJECT_MOBILEts = 141, // track-search
- OBJECT_MOBILEfs = 142, // fly-search
- OBJECT_MOBILEis = 143, // insect-search
- OBJECT_MOBILErt = 200, // roller-terraform
- OBJECT_MOBILErc = 201, // roller-canon
- OBJECT_MOBILErr = 202, // roller-recover
- OBJECT_MOBILErs = 203, // roller-shield
- OBJECT_MOBILEsa = 210, // submarine
- OBJECT_MOBILEtg = 211, // training target
- OBJECT_MOBILEdr = 212, // robot drawing
- OBJECT_WAYPOINT = 250, // waypoint
- OBJECT_FLAGb = 260, // blue flag
- OBJECT_FLAGr = 261, // red flag
- OBJECT_FLAGg = 262, // green flag
- OBJECT_FLAGy = 263, // yellow flag
- OBJECT_FLAGv = 264, // violet flag
- OBJECT_KEYa = 270, // key a
- OBJECT_KEYb = 271, // key b
- OBJECT_KEYc = 272, // key c
- OBJECT_KEYd = 273, // key d
- OBJECT_HUMAN = 300, // human
- OBJECT_TOTO = 301, // toto
- OBJECT_TECH = 302, // technician
- OBJECT_BARRIER0 = 400, // barrier
- OBJECT_BARRIER1 = 401, // barrier
- OBJECT_BARRIER2 = 402, // barrier
- OBJECT_BARRIER3 = 403, // barrier
- OBJECT_BARRIER4 = 404, // barrier
- OBJECT_MOTHER = 500, // insect queen
- OBJECT_EGG = 501, // egg
- OBJECT_ANT = 502, // ant
- OBJECT_SPIDER = 503, // spider
- OBJECT_BEE = 504, // bee
- OBJECT_WORM = 505, // worm
- OBJECT_RUINmobilew1 = 600, // ruin 1
- OBJECT_RUINmobilew2 = 601, // ruin 1
- OBJECT_RUINmobilet1 = 602, // ruin 2
- OBJECT_RUINmobilet2 = 603, // ruin 2
- OBJECT_RUINmobiler1 = 604, // ruin 3
- OBJECT_RUINmobiler2 = 605, // ruin 3
- OBJECT_RUINfactory = 606, // ruin 4
- OBJECT_RUINdoor = 607, // ruin 5
- OBJECT_RUINsupport = 608, // ruin 6
- OBJECT_RUINradar = 609, // ruin 7
- OBJECT_RUINconvert = 610, // ruin 8
- OBJECT_RUINbase = 611, // ruin 9
- OBJECT_RUINhead = 612, // ruin 10
- OBJECT_TEEN0 = 620, // toy
- OBJECT_TEEN1 = 621, // toy
- OBJECT_TEEN2 = 622, // toy
- OBJECT_TEEN3 = 623, // toy
- OBJECT_TEEN4 = 624, // toy
- OBJECT_TEEN5 = 625, // toy
- OBJECT_TEEN6 = 626, // toy
- OBJECT_TEEN7 = 627, // toy
- OBJECT_TEEN8 = 628, // toy
- OBJECT_TEEN9 = 629, // toy
- OBJECT_TEEN10 = 630, // toy
- OBJECT_TEEN11 = 631, // toy
- OBJECT_TEEN12 = 632, // toy
- OBJECT_TEEN13 = 633, // toy
- OBJECT_TEEN14 = 634, // toy
- OBJECT_TEEN15 = 635, // toy
- OBJECT_TEEN16 = 636, // toy
- OBJECT_TEEN17 = 637, // toy
- OBJECT_TEEN18 = 638, // toy
- OBJECT_TEEN19 = 639, // toy
- OBJECT_TEEN20 = 640, // toy
- OBJECT_TEEN21 = 641, // toy
- OBJECT_TEEN22 = 642, // toy
- OBJECT_TEEN23 = 643, // toy
- OBJECT_TEEN24 = 644, // toy
- OBJECT_TEEN25 = 645, // toy
- OBJECT_TEEN26 = 646, // toy
- OBJECT_TEEN27 = 647, // toy
- OBJECT_TEEN28 = 648, // toy
- OBJECT_TEEN29 = 649, // toy
- OBJECT_TEEN30 = 650, // toy
- OBJECT_TEEN31 = 651, // toy
- OBJECT_TEEN32 = 652, // toy
- OBJECT_TEEN33 = 653, // toy
- OBJECT_TEEN34 = 654, // toy
- OBJECT_TEEN35 = 655, // toy
- OBJECT_TEEN36 = 656, // toy
- OBJECT_TEEN37 = 657, // toy
- OBJECT_TEEN38 = 658, // toy
- OBJECT_TEEN39 = 659, // toy
- OBJECT_TEEN40 = 660, // toy
- OBJECT_TEEN41 = 661, // toy
- OBJECT_TEEN42 = 662, // toy
- OBJECT_TEEN43 = 663, // toy
- OBJECT_TEEN44 = 664, // toy
- OBJECT_TEEN45 = 665, // toy
- OBJECT_TEEN46 = 666, // toy
- OBJECT_TEEN47 = 667, // toy
- OBJECT_TEEN48 = 668, // toy
- OBJECT_TEEN49 = 669, // toy
- OBJECT_QUARTZ0 = 700, // crystal 0
- OBJECT_QUARTZ1 = 701, // crystal 1
- OBJECT_QUARTZ2 = 702, // crystal 2
- OBJECT_QUARTZ3 = 703, // crystal 3
- OBJECT_QUARTZ4 = 704, // crystal 4
- OBJECT_QUARTZ5 = 705, // crystal 5
- OBJECT_QUARTZ6 = 706, // crystal 6
- OBJECT_QUARTZ7 = 707, // crystal 7
- OBJECT_QUARTZ8 = 708, // crystal 8
- OBJECT_QUARTZ9 = 709, // crystal 9
- OBJECT_ROOT0 = 710, // root 0
- OBJECT_ROOT1 = 711, // root 1
- OBJECT_ROOT2 = 712, // root 2
- OBJECT_ROOT3 = 713, // root 3
- OBJECT_ROOT4 = 714, // root 4
- OBJECT_ROOT5 = 715, // root 5
- OBJECT_ROOT6 = 716, // root 6
- OBJECT_ROOT7 = 717, // root 7
- OBJECT_ROOT8 = 718, // root 8
- OBJECT_ROOT9 = 719, // root 9
- OBJECT_SEAWEED0 = 720, // seaweed 0
- OBJECT_SEAWEED1 = 721, // seaweed 1
- OBJECT_SEAWEED2 = 722, // seaweed 2
- OBJECT_SEAWEED3 = 723, // seaweed 3
- OBJECT_SEAWEED4 = 724, // seaweed 4
- OBJECT_SEAWEED5 = 725, // seaweed 5
- OBJECT_SEAWEED6 = 726, // seaweed 6
- OBJECT_SEAWEED7 = 727, // seaweed 7
- OBJECT_SEAWEED8 = 728, // seaweed 8
- OBJECT_SEAWEED9 = 729, // seaweed 9
- OBJECT_MUSHROOM0 = 730, // mushroom 0
- OBJECT_MUSHROOM1 = 731, // mushroom 1
- OBJECT_MUSHROOM2 = 732, // mushroom 2
- OBJECT_MUSHROOM3 = 733, // mushroom 3
- OBJECT_MUSHROOM4 = 734, // mushroom 4
- OBJECT_MUSHROOM5 = 735, // mushroom 5
- OBJECT_MUSHROOM6 = 736, // mushroom 6
- OBJECT_MUSHROOM7 = 737, // mushroom 7
- OBJECT_MUSHROOM8 = 738, // mushroom 8
- OBJECT_MUSHROOM9 = 739, // mushroom 9
- OBJECT_APOLLO1 = 900, // apollo lem
- OBJECT_APOLLO2 = 901, // apollo jeep
- OBJECT_APOLLO3 = 902, // apollo flag
- OBJECT_APOLLO4 = 903, // apollo module
- OBJECT_APOLLO5 = 904, // apollo antenna
- OBJECT_HOME1 = 910, // home 1
- OBJECT_MAX = 1000,
-};
-
-enum ObjectMaterial
-{
- OM_METAL = 0, // metal
- OM_PLASTIC = 1, // plastic
- OM_HUMAN = 2, // cosmonaut
- OM_ANIMAL = 3, // insect
- OM_VEGETAL = 4, // plant
- OM_MINERAL = 5, // stone
-};
-
-struct ObjectPart
-{
- char bUsed;
- int object; // number of the object in CD3DEngine
- int parentPart; // number of father part
- int masterParti; // master canal of the particle
- Math::Vector position;
- Math::Vector angle;
- Math::Vector zoom;
- char bTranslate;
- char bRotate;
- char bZoom;
- Math::Matrix matTranslate;
- Math::Matrix matRotate;
- Math::Matrix matTransform;
- Math::Matrix matWorld;
-};
-
-struct Character
-{
- float wheelFront; // position X of the front wheels
- float wheelBack; // position X of the back wheels
- float wheelLeft; // position Z of the left wheels
- float wheelRight; // position Z of the right wheels
- float height; // normal height on top of ground
- Math::Vector posPower; // position of the battery
-};
-
-struct Info
-{
- char name[20]; // name of the information
- float value; // value of the information
-};
-
-enum ExploType
-{
- EXPLO_BOUM = 1,
- EXPLO_BURN = 2,
- EXPLO_WATER = 3,
-};
-
-enum ResetCap
-{
- RESET_NONE = 0,
- RESET_MOVE = 1,
- RESET_DELETE = 2,
-};
-
-enum RadarFilter
-{
- FILTER_NONE = 0,
- FILTER_ONLYLANDING = 1,
- FILTER_ONLYFLYING = 2,
-};
-
-
-
-
-class CObject
-{
-public:
- CObject(CInstanceManager* iMan);
- ~CObject();
-
- void DeleteObject(bool bAll=false);
- void Simplify();
- bool ExploObject(ExploType type, float force, float decay=1.0f);
-
- bool EventProcess(const Event &event);
- void UpdateMapping();
-
- int CreatePart();
- void DeletePart(int part);
- void SetObjectRank(int part, int objRank);
- int RetObjectRank(int part);
- void SetObjectParent(int part, int parent);
- void SetType(ObjectType type);
- ObjectType RetType();
- char* RetName();
- void SetOption(int option);
- int RetOption();
-
- void SetID(int id);
- int RetID();
-
- bool Write(char *line);
- bool Read(char *line);
-
- void SetDrawWorld(bool bDraw);
- void SetDrawFront(bool bDraw);
-
- bool CreateVehicle(Math::Vector pos, float angle, ObjectType type, float power, bool bTrainer, bool bToy);
- bool CreateInsect(Math::Vector pos, float angle, ObjectType type);
- bool CreateBuilding(Math::Vector pos, float angle, float height, ObjectType type, float power=1.0f);
- bool CreateResource(Math::Vector pos, float angle, ObjectType type, float power=1.0f);
- bool CreateFlag(Math::Vector pos, float angle, ObjectType type);
- bool CreateBarrier(Math::Vector pos, float angle, float height, ObjectType type);
- bool CreatePlant(Math::Vector pos, float angle, float height, ObjectType type);
- bool CreateMushroom(Math::Vector pos, float angle, float height, ObjectType type);
- bool CreateTeen(Math::Vector pos, float angle, float zoom, float height, ObjectType type);
- bool CreateQuartz(Math::Vector pos, float angle, float height, ObjectType type);
- bool CreateRoot(Math::Vector pos, float angle, float height, ObjectType type);
- bool CreateHome(Math::Vector pos, float angle, float height, ObjectType type);
- bool CreateRuin(Math::Vector pos, float angle, float height, ObjectType type);
- bool CreateApollo(Math::Vector pos, float angle, ObjectType type);
-
- bool ReadProgram(int rank, char* filename);
- bool WriteProgram(int rank, char* filename);
- bool RunProgram(int rank);
-
- int RetShadowLight();
- int RetEffectLight();
-
- void FlushCrashShere();
- int CreateCrashSphere(Math::Vector pos, float radius, Sound sound, float hardness=0.45f);
- int RetCrashSphereTotal();
- bool GetCrashSphere(int rank, Math::Vector &pos, float &radius);
- float RetCrashSphereHardness(int rank);
- Sound RetCrashSphereSound(int rank);
- void DeleteCrashSphere(int rank);
- void SetGlobalSphere(Math::Vector pos, float radius);
- void GetGlobalSphere(Math::Vector &pos, float &radius);
- void SetJotlerSphere(Math::Vector pos, float radius);
- void GetJotlerSphere(Math::Vector &pos, float &radius);
- void SetShieldRadius(float radius);
- float RetShieldRadius();
-
- void SetFloorHeight(float height);
- void FloorAdjust();
-
- void SetLinVibration(Math::Vector dir);
- Math::Vector RetLinVibration();
- void SetCirVibration(Math::Vector dir);
- Math::Vector RetCirVibration();
- void SetInclinaison(Math::Vector dir);
- Math::Vector RetInclinaison();
-
- void SetPosition(int part, const Math::Vector &pos);
- Math::Vector RetPosition(int part);
- void SetAngle(int part, const Math::Vector &angle);
- Math::Vector RetAngle(int part);
- void SetAngleY(int part, float angle);
- void SetAngleX(int part, float angle);
- void SetAngleZ(int part, float angle);
- float RetAngleY(int part);
- float RetAngleX(int part);
- float RetAngleZ(int part);
- void SetZoom(int part, float zoom);
- void SetZoom(int part, Math::Vector zoom);
- Math::Vector RetZoom(int part);
- void SetZoomX(int part, float zoom);
- float RetZoomX(int part);
- void SetZoomY(int part, float zoom);
- float RetZoomY(int part);
- void SetZoomZ(int part, float zoom);
- float RetZoomZ(int part);
-
- float RetWaterLevel();
-
- void SetTrainer(bool bEnable);
- bool RetTrainer();
-
- void SetToy(bool bEnable);
- bool RetToy();
-
- void SetManual(bool bManual);
- bool RetManual();
-
- void SetResetCap(ResetCap cap);
- ResetCap RetResetCap();
- void SetResetBusy(bool bBusy);
- bool RetResetBusy();
- void SetResetPosition(const Math::Vector &pos);
- Math::Vector RetResetPosition();
- void SetResetAngle(const Math::Vector &angle);
- Math::Vector RetResetAngle();
- void SetResetRun(int run);
- int RetResetRun();
-
- void SetMasterParticule(int part, int parti);
- int RetMasterParticule(int part);
-
- void SetPower(CObject* power);
- CObject* RetPower();
- void SetFret(CObject* fret);
- CObject* RetFret();
- void SetTruck(CObject* truck);
- CObject* RetTruck();
- void SetTruckPart(int part);
- int RetTruckPart();
-
- void InfoFlush();
- void DeleteInfo(int rank);
- void SetInfo(int rank, Info info);
- Info RetInfo(int rank);
- int RetInfoTotal();
- void SetInfoReturn(float value);
- float RetInfoReturn();
- void SetInfoUpdate(bool bUpdate);
- bool RetInfoUpdate();
-
- bool SetCmdLine(int rank, float value);
- float RetCmdLine(int rank);
-
- Math::Matrix* RetRotateMatrix(int part);
- Math::Matrix* RetTranslateMatrix(int part);
- Math::Matrix* RetTransformMatrix(int part);
- Math::Matrix* RetWorldMatrix(int part);
-
- void SetViewFromHere(Math::Vector &eye, float &dirH, float &dirV, Math::Vector &lookat, Math::Vector &upVec, CameraType type);
-
- void SetCharacter(Character* character);
- void GetCharacter(Character* character);
- Character* RetCharacter();
-
- float RetAbsTime();
-
- void SetEnergy(float level);
- float RetEnergy();
-
- void SetCapacity(float capacity);
- float RetCapacity();
-
- void SetShield(float level);
- float RetShield();
-
- void SetRange(float delay);
- float RetRange();
-
- void SetTransparency(float value);
- float RetTransparency();
-
- ObjectMaterial RetMaterial();
-
- void SetGadget(bool bMode);
- bool RetGadget();
-
- void SetFixed(bool bFixed);
- bool RetFixed();
-
- void SetClip(bool bClip);
- bool RetClip();
-
- bool JostleObject(float force);
-
- void StartDetectEffect(CObject *target, bool bFound);
-
- void SetVirusMode(bool bEnable);
- bool RetVirusMode();
- float RetVirusTime();
-
- void SetCameraType(CameraType type);
- CameraType RetCameraType();
- void SetCameraDist(float dist);
- float RetCameraDist();
- void SetCameraLock(bool bLock);
- bool RetCameraLock();
-
- void SetHilite(bool bMode);
- bool RetHilite();
-
- void SetSelect(bool bMode, bool bDisplayError=true);
- bool RetSelect(bool bReal=false);
-
- void SetSelectable(bool bMode);
- bool RetSelectable();
-
- void SetActivity(bool bMode);
- bool RetActivity();
-
- void SetVisible(bool bVisible);
- bool RetVisible();
-
- void SetEnable(bool bEnable);
- bool RetEnable();
-
- void SetCheckToken(bool bMode);
- bool RetCheckToken();
-
- void SetProxyActivate(bool bActivate);
- bool RetProxyActivate();
- void SetProxyDistance(float distance);
- float RetProxyDistance();
-
- void SetMagnifyDamage(float factor);
- float RetMagnifyDamage();
-
- void SetParam(float value);
- float RetParam();
-
- void SetExplo(bool bExplo);
- bool RetExplo();
- void SetLock(bool bLock);
- bool RetLock();
- void SetCargo(bool bCargo);
- bool RetCargo();
- void SetBurn(bool bBurn);
- bool RetBurn();
- void SetDead(bool bDead);
- bool RetDead();
- bool RetRuin();
- bool RetActif();
-
- void SetGunGoalV(float gunGoal);
- void SetGunGoalH(float gunGoal);
- float RetGunGoalV();
- float RetGunGoalH();
-
- bool StartShowLimit();
- void StopShowLimit();
-
- bool IsProgram();
- void CreateSelectParticule();
-
- void SetRunScript(CScript* script);
- CScript* RetRunScript();
- CBotVar* RetBotVar();
- CPhysics* RetPhysics();
- CBrain* RetBrain();
- CMotion* RetMotion();
- CAuto* RetAuto();
- void SetAuto(CAuto* automat);
-
- void SetDefRank(int rank);
- int RetDefRank();
-
- bool GetTooltipName(char* name);
-
- void AddDeselList(CObject* pObj);
- CObject* SubDeselList();
- void DeleteDeselList(CObject* pObj);
-
- bool CreateShadowCircle(float radius, float intensity, D3DShadowType type=D3DSHADOWNORM);
- bool CreateShadowLight(float height, D3DCOLORVALUE color);
- bool CreateEffectLight(float height, D3DCOLORVALUE color);
-
- void FlatParent();
-
- bool RetTraceDown();
- void SetTraceDown(bool bDown);
- int RetTraceColor();
- void SetTraceColor(int color);
- float RetTraceWidth();
- void SetTraceWidth(float width);
-
-protected:
- bool EventFrame(const Event &event);
- void VirusFrame(float rTime);
- void PartiFrame(float rTime);
- void CreateOtherObject(ObjectType type);
- void InitPart(int part);
- void UpdateTotalPart();
- int SearchDescendant(int parent, int n);
- void UpdateEnergyMapping();
- bool UpdateTransformObject(int part, bool bForceUpdate);
- bool UpdateTransformObject();
- void UpdateSelectParticule();
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CLight* m_light;
- CTerrain* m_terrain;
- CWater* m_water;
- CCamera* m_camera;
- CParticule* m_particule;
- CPhysics* m_physics;
- CBrain* m_brain;
- CMotion* m_motion;
- CAuto* m_auto;
- CDisplayText* m_displayText;
- CRobotMain* m_main;
- CSound* m_sound;
- CBotVar* m_botVar;
- CScript* m_runScript;
-
- ObjectType m_type; // OBJECT_*
- int m_id; // unique identifier
- char m_name[50]; // name of the object
- Character m_character; // characteristic
- int m_option; // option
- int m_partiReactor; // number of the particle of the reactor
- int m_shadowLight; // number of light from the shadows
- float m_shadowHeight; // height of light from the shadows
- int m_effectLight; // number of light effects
- float m_effectHeight; // height of light effects
- Math::Vector m_linVibration; // linear vibration
- Math::Vector m_cirVibration; // circular vibration
- Math::Vector m_inclinaison; // tilt
- CObject* m_power; // battery used by the vehicle
- CObject* m_fret; // object transported
- CObject* m_truck; // object with the latter
- int m_truckLink; // part
- float m_energy; // energy contained (if battery)
- float m_lastEnergy;
- float m_capacity; // capacity (if battery)
- float m_shield; // shield
- float m_range; // flight range
- float m_transparency; // transparency (0..1)
- int m_material; // matter(0..n)
- float m_aTime;
- float m_shotTime; // time since last shot
- bool m_bVirusMode; // virus activated/triggered
- float m_virusTime; // lifetime of the virus
- float m_lastVirusParticule;
- float m_lastParticule;
- bool m_bHilite;
- bool m_bSelect; // object selected
- bool m_bSelectable; // selectable object
- bool m_bCheckToken; // object with audited tokens
- bool m_bVisible; // object active but undetectable
- bool m_bEnable; // dead object
- bool m_bProxyActivate; // active object so close
- bool m_bGadget; // object nonessential
- bool m_bLock;
- bool m_bExplo;
- bool m_bCargo;
- bool m_bBurn;
- bool m_bDead;
- bool m_bFlat;
- bool m_bTrainer; // drive vehicle (without remote)
- bool m_bToy; // toy key
- bool m_bManual; // manual control (Scribbler)
- bool m_bFixed;
- bool m_bClip;
- bool m_bShowLimit;
- float m_showLimitRadius;
- float m_gunGoalV;
- float m_gunGoalH;
- CameraType m_cameraType;
- float m_cameraDist;
- bool m_bCameraLock;
- int m_defRank;
- float m_magnifyDamage;
- float m_proxyDistance;
- float m_param;
-
- int m_crashSphereUsed; // number of spheres used
- Math::Vector m_crashSpherePos[MAXCRASHSPHERE];
- float m_crashSphereRadius[MAXCRASHSPHERE];
- float m_crashSphereHardness[MAXCRASHSPHERE];
- Sound m_crashSphereSound[MAXCRASHSPHERE];
- Math::Vector m_globalSpherePos;
- float m_globalSphereRadius;
- Math::Vector m_jotlerSpherePos;
- float m_jotlerSphereRadius;
- float m_shieldRadius;
-
- int m_totalPart;
- ObjectPart m_objectPart[OBJECTMAXPART];
-
- int m_totalDesectList;
- CObject* m_objectDeselectList[OBJECTMAXDESELLIST];
-
- int m_partiSel[4];
-
- ResetCap m_resetCap;
- bool m_bResetBusy;
- Math::Vector m_resetPosition;
- Math::Vector m_resetAngle;
- int m_resetRun;
-
- int m_infoTotal;
- Info m_info[OBJECTMAXINFO];
- float m_infoReturn;
- bool m_bInfoUpdate;
-
- float m_cmdLine[OBJECTMAXCMDLINE];
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// object.h
+
+#pragma once
+
+
+#include "old/d3dengine.h"
+#include "old/camera.h"
+#include "old/sound.h"
+
+
+class CInstanceManager;
+class CLight;
+class CTerrain;
+class CWater;
+class CParticule;
+class CPhysics;
+class CBrain;
+class CMotion;
+class CAuto;
+class CDisplayText;
+class CRobotMain;
+class CBotVar;
+class CScript;
+
+
+
+// The father of all parts must always be the part number zero!
+
+const int OBJECTMAXPART = 40;
+const int MAXCRASHSPHERE = 40;
+const int OBJECTMAXDESELLIST = 10;
+const int OBJECTMAXINFO = 10;
+const int OBJECTMAXCMDLINE = 20;
+
+enum ObjectType
+{
+ OBJECT_NULL = 0, // object destroyed
+ OBJECT_FIX = 1, // stationary scenery
+ OBJECT_PORTICO = 2, // gantry
+ OBJECT_BASE = 3, // great main base
+ OBJECT_DERRICK = 4, // derrick set
+ OBJECT_FACTORY = 5, // factory set
+ OBJECT_STATION = 6, // recharging station
+ OBJECT_CONVERT = 7, // converter station
+ OBJECT_REPAIR = 8, // reparation
+ OBJECT_TOWER = 9, // defense tower
+ OBJECT_NEST = 10, // nest
+ OBJECT_RESEARCH = 11, // research center
+ OBJECT_RADAR = 12, // radar
+ OBJECT_ENERGY = 13, // energy factory
+ OBJECT_LABO = 14, // analytical laboratory for insect
+ OBJECT_NUCLEAR = 15, // nuclear power plant
+ OBJECT_START = 16, // starting
+ OBJECT_END = 17, // finish
+ OBJECT_INFO = 18, // information terminal
+ OBJECT_PARA = 19, // lightning conductor
+ OBJECT_TARGET1 = 20, // gate target
+ OBJECT_TARGET2 = 21, // center target
+ OBJECT_SAFE = 22, // safe
+ OBJECT_HUSTON = 23, // control centre
+ OBJECT_DESTROYER = 24, // destroyer
+ OBJECT_FRET = 30, // transportable
+ OBJECT_STONE = 31, // stone
+ OBJECT_URANIUM = 32, // uranium
+ OBJECT_METAL = 33, // metal
+ OBJECT_POWER = 34, // normal battery
+ OBJECT_ATOMIC = 35, // atomic battery
+ OBJECT_BULLET = 36, // bullet
+ OBJECT_BBOX = 37, // black-box
+ OBJECT_TNT = 38, // box of TNT
+ OBJECT_SCRAP1 = 40, // metal waste
+ OBJECT_SCRAP2 = 41, // metal waste
+ OBJECT_SCRAP3 = 42, // metal waste
+ OBJECT_SCRAP4 = 43, // plastic waste
+ OBJECT_SCRAP5 = 44, // plastic waste
+ OBJECT_MARKPOWER = 50, // mark underground energy source
+ OBJECT_MARKSTONE = 51, // mark underground ore
+ OBJECT_MARKURANIUM = 52, // mark underground uranium
+ OBJECT_MARKKEYa = 53, // mark underground key
+ OBJECT_MARKKEYb = 54, // mark underground key
+ OBJECT_MARKKEYc = 55, // mark underground key
+ OBJECT_MARKKEYd = 56, // mark underground key
+ OBJECT_BOMB = 60, // bomb
+ OBJECT_WINFIRE = 61, // fireworks
+ OBJECT_SHOW = 62, // shows a place
+ OBJECT_BAG = 63, // survival bag
+ OBJECT_PLANT0 = 70, // plant 0
+ OBJECT_PLANT1 = 71, // plant 1
+ OBJECT_PLANT2 = 72, // plant 2
+ OBJECT_PLANT3 = 73, // plant 3
+ OBJECT_PLANT4 = 74, // plant 4
+ OBJECT_PLANT5 = 75, // plant 5
+ OBJECT_PLANT6 = 76, // plant 6
+ OBJECT_PLANT7 = 77, // plant 7
+ OBJECT_PLANT8 = 78, // plant 8
+ OBJECT_PLANT9 = 79, // plant 9
+ OBJECT_PLANT10 = 80, // plant 10
+ OBJECT_PLANT11 = 81, // plant 11
+ OBJECT_PLANT12 = 82, // plant 12
+ OBJECT_PLANT13 = 83, // plant 13
+ OBJECT_PLANT14 = 84, // plant 14
+ OBJECT_PLANT15 = 85, // plant 15
+ OBJECT_PLANT16 = 86, // plant 16
+ OBJECT_PLANT17 = 87, // plant 17
+ OBJECT_PLANT18 = 88, // plant 18
+ OBJECT_PLANT19 = 89, // plant 19
+ OBJECT_TREE0 = 90, // tree 0
+ OBJECT_TREE1 = 91, // tree 1
+ OBJECT_TREE2 = 92, // tree 2
+ OBJECT_TREE3 = 93, // tree 3
+ OBJECT_TREE4 = 94, // tree 4
+ OBJECT_TREE5 = 95, // tree 5
+ OBJECT_TREE6 = 96, // tree 6
+ OBJECT_TREE7 = 97, // tree 7
+ OBJECT_TREE8 = 98, // tree 8
+ OBJECT_TREE9 = 99, // tree 9
+ OBJECT_MOBILEwt = 100, // wheel-trainer
+ OBJECT_MOBILEtt = 101, // track-trainer
+ OBJECT_MOBILEft = 102, // fly-trainer
+ OBJECT_MOBILEit = 103, // insect-trainer
+ OBJECT_MOBILEwa = 110, // wheel-arm
+ OBJECT_MOBILEta = 111, // track-arm
+ OBJECT_MOBILEfa = 112, // fly-arm
+ OBJECT_MOBILEia = 113, // insect-arm
+ OBJECT_MOBILEwc = 120, // wheel-cannon
+ OBJECT_MOBILEtc = 121, // track-cannon
+ OBJECT_MOBILEfc = 122, // fly-cannon
+ OBJECT_MOBILEic = 123, // insect-cannon
+ OBJECT_MOBILEwi = 130, // wheel-insect-cannon
+ OBJECT_MOBILEti = 131, // track-insect-cannon
+ OBJECT_MOBILEfi = 132, // fly-insect-cannon
+ OBJECT_MOBILEii = 133, // insect-insect-cannon
+ OBJECT_MOBILEws = 140, // wheel-search
+ OBJECT_MOBILEts = 141, // track-search
+ OBJECT_MOBILEfs = 142, // fly-search
+ OBJECT_MOBILEis = 143, // insect-search
+ OBJECT_MOBILErt = 200, // roller-terraform
+ OBJECT_MOBILErc = 201, // roller-canon
+ OBJECT_MOBILErr = 202, // roller-recover
+ OBJECT_MOBILErs = 203, // roller-shield
+ OBJECT_MOBILEsa = 210, // submarine
+ OBJECT_MOBILEtg = 211, // training target
+ OBJECT_MOBILEdr = 212, // robot drawing
+ OBJECT_WAYPOINT = 250, // waypoint
+ OBJECT_FLAGb = 260, // blue flag
+ OBJECT_FLAGr = 261, // red flag
+ OBJECT_FLAGg = 262, // green flag
+ OBJECT_FLAGy = 263, // yellow flag
+ OBJECT_FLAGv = 264, // violet flag
+ OBJECT_KEYa = 270, // key a
+ OBJECT_KEYb = 271, // key b
+ OBJECT_KEYc = 272, // key c
+ OBJECT_KEYd = 273, // key d
+ OBJECT_HUMAN = 300, // human
+ OBJECT_TOTO = 301, // toto
+ OBJECT_TECH = 302, // technician
+ OBJECT_BARRIER0 = 400, // barrier
+ OBJECT_BARRIER1 = 401, // barrier
+ OBJECT_BARRIER2 = 402, // barrier
+ OBJECT_BARRIER3 = 403, // barrier
+ OBJECT_BARRIER4 = 404, // barrier
+ OBJECT_MOTHER = 500, // insect queen
+ OBJECT_EGG = 501, // egg
+ OBJECT_ANT = 502, // ant
+ OBJECT_SPIDER = 503, // spider
+ OBJECT_BEE = 504, // bee
+ OBJECT_WORM = 505, // worm
+ OBJECT_RUINmobilew1 = 600, // ruin 1
+ OBJECT_RUINmobilew2 = 601, // ruin 1
+ OBJECT_RUINmobilet1 = 602, // ruin 2
+ OBJECT_RUINmobilet2 = 603, // ruin 2
+ OBJECT_RUINmobiler1 = 604, // ruin 3
+ OBJECT_RUINmobiler2 = 605, // ruin 3
+ OBJECT_RUINfactory = 606, // ruin 4
+ OBJECT_RUINdoor = 607, // ruin 5
+ OBJECT_RUINsupport = 608, // ruin 6
+ OBJECT_RUINradar = 609, // ruin 7
+ OBJECT_RUINconvert = 610, // ruin 8
+ OBJECT_RUINbase = 611, // ruin 9
+ OBJECT_RUINhead = 612, // ruin 10
+ OBJECT_TEEN0 = 620, // toy
+ OBJECT_TEEN1 = 621, // toy
+ OBJECT_TEEN2 = 622, // toy
+ OBJECT_TEEN3 = 623, // toy
+ OBJECT_TEEN4 = 624, // toy
+ OBJECT_TEEN5 = 625, // toy
+ OBJECT_TEEN6 = 626, // toy
+ OBJECT_TEEN7 = 627, // toy
+ OBJECT_TEEN8 = 628, // toy
+ OBJECT_TEEN9 = 629, // toy
+ OBJECT_TEEN10 = 630, // toy
+ OBJECT_TEEN11 = 631, // toy
+ OBJECT_TEEN12 = 632, // toy
+ OBJECT_TEEN13 = 633, // toy
+ OBJECT_TEEN14 = 634, // toy
+ OBJECT_TEEN15 = 635, // toy
+ OBJECT_TEEN16 = 636, // toy
+ OBJECT_TEEN17 = 637, // toy
+ OBJECT_TEEN18 = 638, // toy
+ OBJECT_TEEN19 = 639, // toy
+ OBJECT_TEEN20 = 640, // toy
+ OBJECT_TEEN21 = 641, // toy
+ OBJECT_TEEN22 = 642, // toy
+ OBJECT_TEEN23 = 643, // toy
+ OBJECT_TEEN24 = 644, // toy
+ OBJECT_TEEN25 = 645, // toy
+ OBJECT_TEEN26 = 646, // toy
+ OBJECT_TEEN27 = 647, // toy
+ OBJECT_TEEN28 = 648, // toy
+ OBJECT_TEEN29 = 649, // toy
+ OBJECT_TEEN30 = 650, // toy
+ OBJECT_TEEN31 = 651, // toy
+ OBJECT_TEEN32 = 652, // toy
+ OBJECT_TEEN33 = 653, // toy
+ OBJECT_TEEN34 = 654, // toy
+ OBJECT_TEEN35 = 655, // toy
+ OBJECT_TEEN36 = 656, // toy
+ OBJECT_TEEN37 = 657, // toy
+ OBJECT_TEEN38 = 658, // toy
+ OBJECT_TEEN39 = 659, // toy
+ OBJECT_TEEN40 = 660, // toy
+ OBJECT_TEEN41 = 661, // toy
+ OBJECT_TEEN42 = 662, // toy
+ OBJECT_TEEN43 = 663, // toy
+ OBJECT_TEEN44 = 664, // toy
+ OBJECT_TEEN45 = 665, // toy
+ OBJECT_TEEN46 = 666, // toy
+ OBJECT_TEEN47 = 667, // toy
+ OBJECT_TEEN48 = 668, // toy
+ OBJECT_TEEN49 = 669, // toy
+ OBJECT_QUARTZ0 = 700, // crystal 0
+ OBJECT_QUARTZ1 = 701, // crystal 1
+ OBJECT_QUARTZ2 = 702, // crystal 2
+ OBJECT_QUARTZ3 = 703, // crystal 3
+ OBJECT_QUARTZ4 = 704, // crystal 4
+ OBJECT_QUARTZ5 = 705, // crystal 5
+ OBJECT_QUARTZ6 = 706, // crystal 6
+ OBJECT_QUARTZ7 = 707, // crystal 7
+ OBJECT_QUARTZ8 = 708, // crystal 8
+ OBJECT_QUARTZ9 = 709, // crystal 9
+ OBJECT_ROOT0 = 710, // root 0
+ OBJECT_ROOT1 = 711, // root 1
+ OBJECT_ROOT2 = 712, // root 2
+ OBJECT_ROOT3 = 713, // root 3
+ OBJECT_ROOT4 = 714, // root 4
+ OBJECT_ROOT5 = 715, // root 5
+ OBJECT_ROOT6 = 716, // root 6
+ OBJECT_ROOT7 = 717, // root 7
+ OBJECT_ROOT8 = 718, // root 8
+ OBJECT_ROOT9 = 719, // root 9
+ OBJECT_SEAWEED0 = 720, // seaweed 0
+ OBJECT_SEAWEED1 = 721, // seaweed 1
+ OBJECT_SEAWEED2 = 722, // seaweed 2
+ OBJECT_SEAWEED3 = 723, // seaweed 3
+ OBJECT_SEAWEED4 = 724, // seaweed 4
+ OBJECT_SEAWEED5 = 725, // seaweed 5
+ OBJECT_SEAWEED6 = 726, // seaweed 6
+ OBJECT_SEAWEED7 = 727, // seaweed 7
+ OBJECT_SEAWEED8 = 728, // seaweed 8
+ OBJECT_SEAWEED9 = 729, // seaweed 9
+ OBJECT_MUSHROOM0 = 730, // mushroom 0
+ OBJECT_MUSHROOM1 = 731, // mushroom 1
+ OBJECT_MUSHROOM2 = 732, // mushroom 2
+ OBJECT_MUSHROOM3 = 733, // mushroom 3
+ OBJECT_MUSHROOM4 = 734, // mushroom 4
+ OBJECT_MUSHROOM5 = 735, // mushroom 5
+ OBJECT_MUSHROOM6 = 736, // mushroom 6
+ OBJECT_MUSHROOM7 = 737, // mushroom 7
+ OBJECT_MUSHROOM8 = 738, // mushroom 8
+ OBJECT_MUSHROOM9 = 739, // mushroom 9
+ OBJECT_APOLLO1 = 900, // apollo lem
+ OBJECT_APOLLO2 = 901, // apollo jeep
+ OBJECT_APOLLO3 = 902, // apollo flag
+ OBJECT_APOLLO4 = 903, // apollo module
+ OBJECT_APOLLO5 = 904, // apollo antenna
+ OBJECT_HOME1 = 910, // home 1
+ OBJECT_MAX = 1000,
+};
+
+enum ObjectMaterial
+{
+ OM_METAL = 0, // metal
+ OM_PLASTIC = 1, // plastic
+ OM_HUMAN = 2, // cosmonaut
+ OM_ANIMAL = 3, // insect
+ OM_VEGETAL = 4, // plant
+ OM_MINERAL = 5, // stone
+};
+
+struct ObjectPart
+{
+ char bUsed;
+ int object; // number of the object in CD3DEngine
+ int parentPart; // number of father part
+ int masterParti; // master canal of the particle
+ Math::Vector position;
+ Math::Vector angle;
+ Math::Vector zoom;
+ char bTranslate;
+ char bRotate;
+ char bZoom;
+ Math::Matrix matTranslate;
+ Math::Matrix matRotate;
+ Math::Matrix matTransform;
+ Math::Matrix matWorld;
+};
+
+struct Character
+{
+ float wheelFront; // position X of the front wheels
+ float wheelBack; // position X of the back wheels
+ float wheelLeft; // position Z of the left wheels
+ float wheelRight; // position Z of the right wheels
+ float height; // normal height on top of ground
+ Math::Vector posPower; // position of the battery
+};
+
+struct Info
+{
+ char name[20]; // name of the information
+ float value; // value of the information
+};
+
+enum ExploType
+{
+ EXPLO_BOUM = 1,
+ EXPLO_BURN = 2,
+ EXPLO_WATER = 3,
+};
+
+enum ResetCap
+{
+ RESET_NONE = 0,
+ RESET_MOVE = 1,
+ RESET_DELETE = 2,
+};
+
+enum RadarFilter
+{
+ FILTER_NONE = 0,
+ FILTER_ONLYLANDING = 1,
+ FILTER_ONLYFLYING = 2,
+};
+
+
+
+
+class CObject
+{
+public:
+ CObject(CInstanceManager* iMan);
+ ~CObject();
+
+ void DeleteObject(bool bAll=false);
+ void Simplify();
+ bool ExploObject(ExploType type, float force, float decay=1.0f);
+
+ bool EventProcess(const Event &event);
+ void UpdateMapping();
+
+ int CreatePart();
+ void DeletePart(int part);
+ void SetObjectRank(int part, int objRank);
+ int RetObjectRank(int part);
+ void SetObjectParent(int part, int parent);
+ void SetType(ObjectType type);
+ ObjectType RetType();
+ char* RetName();
+ void SetOption(int option);
+ int RetOption();
+
+ void SetID(int id);
+ int RetID();
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+ void SetDrawWorld(bool bDraw);
+ void SetDrawFront(bool bDraw);
+
+ bool CreateVehicle(Math::Vector pos, float angle, ObjectType type, float power, bool bTrainer, bool bToy);
+ bool CreateInsect(Math::Vector pos, float angle, ObjectType type);
+ bool CreateBuilding(Math::Vector pos, float angle, float height, ObjectType type, float power=1.0f);
+ bool CreateResource(Math::Vector pos, float angle, ObjectType type, float power=1.0f);
+ bool CreateFlag(Math::Vector pos, float angle, ObjectType type);
+ bool CreateBarrier(Math::Vector pos, float angle, float height, ObjectType type);
+ bool CreatePlant(Math::Vector pos, float angle, float height, ObjectType type);
+ bool CreateMushroom(Math::Vector pos, float angle, float height, ObjectType type);
+ bool CreateTeen(Math::Vector pos, float angle, float zoom, float height, ObjectType type);
+ bool CreateQuartz(Math::Vector pos, float angle, float height, ObjectType type);
+ bool CreateRoot(Math::Vector pos, float angle, float height, ObjectType type);
+ bool CreateHome(Math::Vector pos, float angle, float height, ObjectType type);
+ bool CreateRuin(Math::Vector pos, float angle, float height, ObjectType type);
+ bool CreateApollo(Math::Vector pos, float angle, ObjectType type);
+
+ bool ReadProgram(int rank, char* filename);
+ bool WriteProgram(int rank, char* filename);
+ bool RunProgram(int rank);
+
+ int RetShadowLight();
+ int RetEffectLight();
+
+ void FlushCrashShere();
+ int CreateCrashSphere(Math::Vector pos, float radius, Sound sound, float hardness=0.45f);
+ int RetCrashSphereTotal();
+ bool GetCrashSphere(int rank, Math::Vector &pos, float &radius);
+ float RetCrashSphereHardness(int rank);
+ Sound RetCrashSphereSound(int rank);
+ void DeleteCrashSphere(int rank);
+ void SetGlobalSphere(Math::Vector pos, float radius);
+ void GetGlobalSphere(Math::Vector &pos, float &radius);
+ void SetJotlerSphere(Math::Vector pos, float radius);
+ void GetJotlerSphere(Math::Vector &pos, float &radius);
+ void SetShieldRadius(float radius);
+ float RetShieldRadius();
+
+ void SetFloorHeight(float height);
+ void FloorAdjust();
+
+ void SetLinVibration(Math::Vector dir);
+ Math::Vector RetLinVibration();
+ void SetCirVibration(Math::Vector dir);
+ Math::Vector RetCirVibration();
+ void SetInclinaison(Math::Vector dir);
+ Math::Vector RetInclinaison();
+
+ void SetPosition(int part, const Math::Vector &pos);
+ Math::Vector RetPosition(int part);
+ void SetAngle(int part, const Math::Vector &angle);
+ Math::Vector RetAngle(int part);
+ void SetAngleY(int part, float angle);
+ void SetAngleX(int part, float angle);
+ void SetAngleZ(int part, float angle);
+ float RetAngleY(int part);
+ float RetAngleX(int part);
+ float RetAngleZ(int part);
+ void SetZoom(int part, float zoom);
+ void SetZoom(int part, Math::Vector zoom);
+ Math::Vector RetZoom(int part);
+ void SetZoomX(int part, float zoom);
+ float RetZoomX(int part);
+ void SetZoomY(int part, float zoom);
+ float RetZoomY(int part);
+ void SetZoomZ(int part, float zoom);
+ float RetZoomZ(int part);
+
+ float RetWaterLevel();
+
+ void SetTrainer(bool bEnable);
+ bool RetTrainer();
+
+ void SetToy(bool bEnable);
+ bool RetToy();
+
+ void SetManual(bool bManual);
+ bool RetManual();
+
+ void SetResetCap(ResetCap cap);
+ ResetCap RetResetCap();
+ void SetResetBusy(bool bBusy);
+ bool RetResetBusy();
+ void SetResetPosition(const Math::Vector &pos);
+ Math::Vector RetResetPosition();
+ void SetResetAngle(const Math::Vector &angle);
+ Math::Vector RetResetAngle();
+ void SetResetRun(int run);
+ int RetResetRun();
+
+ void SetMasterParticule(int part, int parti);
+ int RetMasterParticule(int part);
+
+ void SetPower(CObject* power);
+ CObject* RetPower();
+ void SetFret(CObject* fret);
+ CObject* RetFret();
+ void SetTruck(CObject* truck);
+ CObject* RetTruck();
+ void SetTruckPart(int part);
+ int RetTruckPart();
+
+ void InfoFlush();
+ void DeleteInfo(int rank);
+ void SetInfo(int rank, Info info);
+ Info RetInfo(int rank);
+ int RetInfoTotal();
+ void SetInfoReturn(float value);
+ float RetInfoReturn();
+ void SetInfoUpdate(bool bUpdate);
+ bool RetInfoUpdate();
+
+ bool SetCmdLine(int rank, float value);
+ float RetCmdLine(int rank);
+
+ Math::Matrix* RetRotateMatrix(int part);
+ Math::Matrix* RetTranslateMatrix(int part);
+ Math::Matrix* RetTransformMatrix(int part);
+ Math::Matrix* RetWorldMatrix(int part);
+
+ void SetViewFromHere(Math::Vector &eye, float &dirH, float &dirV, Math::Vector &lookat, Math::Vector &upVec, CameraType type);
+
+ void SetCharacter(Character* character);
+ void GetCharacter(Character* character);
+ Character* RetCharacter();
+
+ float RetAbsTime();
+
+ void SetEnergy(float level);
+ float RetEnergy();
+
+ void SetCapacity(float capacity);
+ float RetCapacity();
+
+ void SetShield(float level);
+ float RetShield();
+
+ void SetRange(float delay);
+ float RetRange();
+
+ void SetTransparency(float value);
+ float RetTransparency();
+
+ ObjectMaterial RetMaterial();
+
+ void SetGadget(bool bMode);
+ bool RetGadget();
+
+ void SetFixed(bool bFixed);
+ bool RetFixed();
+
+ void SetClip(bool bClip);
+ bool RetClip();
+
+ bool JostleObject(float force);
+
+ void StartDetectEffect(CObject *target, bool bFound);
+
+ void SetVirusMode(bool bEnable);
+ bool RetVirusMode();
+ float RetVirusTime();
+
+ void SetCameraType(CameraType type);
+ CameraType RetCameraType();
+ void SetCameraDist(float dist);
+ float RetCameraDist();
+ void SetCameraLock(bool bLock);
+ bool RetCameraLock();
+
+ void SetHilite(bool bMode);
+ bool RetHilite();
+
+ void SetSelect(bool bMode, bool bDisplayError=true);
+ bool RetSelect(bool bReal=false);
+
+ void SetSelectable(bool bMode);
+ bool RetSelectable();
+
+ void SetActivity(bool bMode);
+ bool RetActivity();
+
+ void SetVisible(bool bVisible);
+ bool RetVisible();
+
+ void SetEnable(bool bEnable);
+ bool RetEnable();
+
+ void SetCheckToken(bool bMode);
+ bool RetCheckToken();
+
+ void SetProxyActivate(bool bActivate);
+ bool RetProxyActivate();
+ void SetProxyDistance(float distance);
+ float RetProxyDistance();
+
+ void SetMagnifyDamage(float factor);
+ float RetMagnifyDamage();
+
+ void SetParam(float value);
+ float RetParam();
+
+ void SetExplo(bool bExplo);
+ bool RetExplo();
+ void SetLock(bool bLock);
+ bool RetLock();
+ void SetCargo(bool bCargo);
+ bool RetCargo();
+ void SetBurn(bool bBurn);
+ bool RetBurn();
+ void SetDead(bool bDead);
+ bool RetDead();
+ bool RetRuin();
+ bool RetActif();
+
+ void SetGunGoalV(float gunGoal);
+ void SetGunGoalH(float gunGoal);
+ float RetGunGoalV();
+ float RetGunGoalH();
+
+ bool StartShowLimit();
+ void StopShowLimit();
+
+ bool IsProgram();
+ void CreateSelectParticule();
+
+ void SetRunScript(CScript* script);
+ CScript* RetRunScript();
+ CBotVar* RetBotVar();
+ CPhysics* RetPhysics();
+ CBrain* RetBrain();
+ CMotion* RetMotion();
+ CAuto* RetAuto();
+ void SetAuto(CAuto* automat);
+
+ void SetDefRank(int rank);
+ int RetDefRank();
+
+ bool GetTooltipName(char* name);
+
+ void AddDeselList(CObject* pObj);
+ CObject* SubDeselList();
+ void DeleteDeselList(CObject* pObj);
+
+ bool CreateShadowCircle(float radius, float intensity, D3DShadowType type=D3DSHADOWNORM);
+ bool CreateShadowLight(float height, D3DCOLORVALUE color);
+ bool CreateEffectLight(float height, D3DCOLORVALUE color);
+
+ void FlatParent();
+
+ bool RetTraceDown();
+ void SetTraceDown(bool bDown);
+ int RetTraceColor();
+ void SetTraceColor(int color);
+ float RetTraceWidth();
+ void SetTraceWidth(float width);
+
+protected:
+ bool EventFrame(const Event &event);
+ void VirusFrame(float rTime);
+ void PartiFrame(float rTime);
+ void CreateOtherObject(ObjectType type);
+ void InitPart(int part);
+ void UpdateTotalPart();
+ int SearchDescendant(int parent, int n);
+ void UpdateEnergyMapping();
+ bool UpdateTransformObject(int part, bool bForceUpdate);
+ bool UpdateTransformObject();
+ void UpdateSelectParticule();
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CLight* m_light;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CCamera* m_camera;
+ CParticule* m_particule;
+ CPhysics* m_physics;
+ CBrain* m_brain;
+ CMotion* m_motion;
+ CAuto* m_auto;
+ CDisplayText* m_displayText;
+ CRobotMain* m_main;
+ CSound* m_sound;
+ CBotVar* m_botVar;
+ CScript* m_runScript;
+
+ ObjectType m_type; // OBJECT_*
+ int m_id; // unique identifier
+ char m_name[50]; // name of the object
+ Character m_character; // characteristic
+ int m_option; // option
+ int m_partiReactor; // number of the particle of the reactor
+ int m_shadowLight; // number of light from the shadows
+ float m_shadowHeight; // height of light from the shadows
+ int m_effectLight; // number of light effects
+ float m_effectHeight; // height of light effects
+ Math::Vector m_linVibration; // linear vibration
+ Math::Vector m_cirVibration; // circular vibration
+ Math::Vector m_inclinaison; // tilt
+ CObject* m_power; // battery used by the vehicle
+ CObject* m_fret; // object transported
+ CObject* m_truck; // object with the latter
+ int m_truckLink; // part
+ float m_energy; // energy contained (if battery)
+ float m_lastEnergy;
+ float m_capacity; // capacity (if battery)
+ float m_shield; // shield
+ float m_range; // flight range
+ float m_transparency; // transparency (0..1)
+ int m_material; // matter(0..n)
+ float m_aTime;
+ float m_shotTime; // time since last shot
+ bool m_bVirusMode; // virus activated/triggered
+ float m_virusTime; // lifetime of the virus
+ float m_lastVirusParticule;
+ float m_lastParticule;
+ bool m_bHilite;
+ bool m_bSelect; // object selected
+ bool m_bSelectable; // selectable object
+ bool m_bCheckToken; // object with audited tokens
+ bool m_bVisible; // object active but undetectable
+ bool m_bEnable; // dead object
+ bool m_bProxyActivate; // active object so close
+ bool m_bGadget; // object nonessential
+ bool m_bLock;
+ bool m_bExplo;
+ bool m_bCargo;
+ bool m_bBurn;
+ bool m_bDead;
+ bool m_bFlat;
+ bool m_bTrainer; // drive vehicle (without remote)
+ bool m_bToy; // toy key
+ bool m_bManual; // manual control (Scribbler)
+ bool m_bFixed;
+ bool m_bClip;
+ bool m_bShowLimit;
+ float m_showLimitRadius;
+ float m_gunGoalV;
+ float m_gunGoalH;
+ CameraType m_cameraType;
+ float m_cameraDist;
+ bool m_bCameraLock;
+ int m_defRank;
+ float m_magnifyDamage;
+ float m_proxyDistance;
+ float m_param;
+
+ int m_crashSphereUsed; // number of spheres used
+ Math::Vector m_crashSpherePos[MAXCRASHSPHERE];
+ float m_crashSphereRadius[MAXCRASHSPHERE];
+ float m_crashSphereHardness[MAXCRASHSPHERE];
+ Sound m_crashSphereSound[MAXCRASHSPHERE];
+ Math::Vector m_globalSpherePos;
+ float m_globalSphereRadius;
+ Math::Vector m_jotlerSpherePos;
+ float m_jotlerSphereRadius;
+ float m_shieldRadius;
+
+ int m_totalPart;
+ ObjectPart m_objectPart[OBJECTMAXPART];
+
+ int m_totalDesectList;
+ CObject* m_objectDeselectList[OBJECTMAXDESELLIST];
+
+ int m_partiSel[4];
+
+ ResetCap m_resetCap;
+ bool m_bResetBusy;
+ Math::Vector m_resetPosition;
+ Math::Vector m_resetAngle;
+ int m_resetRun;
+
+ int m_infoTotal;
+ Info m_info[OBJECTMAXINFO];
+ float m_infoReturn;
+ bool m_bInfoUpdate;
+
+ float m_cmdLine[OBJECTMAXCMDLINE];
+};
+
diff --git a/src/object/robotmain.cpp b/src/object/robotmain.cpp
index 902c1cb..d519688 100644
--- a/src/object/robotmain.cpp
+++ b/src/object/robotmain.cpp
@@ -1,7032 +1,7032 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// robotmain.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "CBot/CBotDll.h"
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "math/conv.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/language.h"
-#include "common/global.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/profile.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "old/math3d.h"
-#include "old/light.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "old/cloud.h"
-#include "old/blitz.h"
-#include "old/planet.h"
-#include "object/object.h"
-#include "object/motion/motion.h"
-#include "object/motion/motiontoto.h"
-#include "object/motion/motionhuman.h"
-#include "physics/physics.h"
-#include "object/brain.h"
-#include "old/pyro.h"
-#include "old/modfile.h"
-#include "old/model.h"
-#include "old/camera.h"
-#include "object/task/task.h"
-#include "object/task/taskmanip.h"
-#include "object/task/taskbuild.h"
-#include "object/auto/auto.h"
-#include "object/auto/autobase.h"
-#include "ui/displayinfo.h"
-#include "ui/interface.h"
-#include "ui/shortcut.h"
-#include "ui/map.h"
-#include "ui/label.h"
-#include "ui/button.h"
-#include "ui/slider.h"
-#include "ui/window.h"
-#include "ui/edit.h"
-#include "ui/displaytext.h"
-#include "old/text.h"
-#include "old/sound.h"
-#include "script/cbottoken.h"
-#include "script/cmdtoken.h"
-#include "object/mainmovie.h"
-#include "ui/maindialog.h"
-#include "ui/mainshort.h"
-#include "ui/mainmap.h"
-#include "script/script.h"
-#include "object/robotmain.h"
-
-
-
-#define CBOT_STACK true // saves the stack of programs CBOT
-const float UNIT = 4.0f;
-
-
-
-// Global variables.
-
-long g_id; // unique identifier
-long g_build; // constructible buildings
-long g_researchDone; // research done
-long g_researchEnable; // research available
-float g_unit; // conversion factor
-
-
-
-#include "script/ClassFILE.cpp"
-
-
-
-// Compilation of class "point".
-
-CBotTypResult cPoint(CBotVar* pThis, CBotVar* &var)
-{
- if ( !pThis->IsElemOfClass("point") ) return CBotTypResult(CBotErrBadNum);
-
- if ( var == NULL ) return CBotTypResult(0); // ok if no parameter
-
- // First parameter (x):
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- // Second parameter (y):
- if ( var == NULL ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- // Third parameter (z):
- if ( var == NULL ) // only 2 parameters?
- {
- return CBotTypResult(0); // this function returns void
- }
-
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
- if ( var != NULL ) return CBotTypResult(CBotErrOverParam);
-
- return CBotTypResult(0); // this function returns void
-}
-
-//Execution of the class "point".
-
-bool rPoint(CBotVar* pThis, CBotVar* var, CBotVar* pResult, int& Exception)
-{
- CBotVar *pX, *pY, *pZ;
-
- if ( var == NULL ) return true; // constructor with no parameters is ok
-
- if ( var->GivType() > CBotTypDouble )
- {
- Exception = CBotErrBadNum; return false;
- }
-
- pX = pThis->GivItem("x");
- if ( pX == NULL )
- {
- Exception = CBotErrUndefItem; return false;
- }
- pX->SetValFloat( var->GivValFloat() );
- var = var->GivNext();
-
- if ( var == NULL )
- {
- Exception = CBotErrLowParam; return false;
- }
-
- if ( var->GivType() > CBotTypDouble )
- {
- Exception = CBotErrBadNum; return false;
- }
-
- pY = pThis->GivItem("y");
- if ( pY == NULL )
- {
- Exception = CBotErrUndefItem; return false;
- }
- pY->SetValFloat( var->GivValFloat() );
- var = var->GivNext();
-
- if ( var == NULL )
- {
- return true; // ok with only two parameters
- }
-
- pZ = pThis->GivItem("z");
- if ( pZ == NULL )
- {
- Exception = CBotErrUndefItem; return false;
- }
- pZ->SetValFloat( var->GivValFloat() );
- var = var->GivNext();
-
- if ( var != NULL )
- {
- Exception = CBotErrOverParam; return false;
- }
-
- return true; // no interruption
-}
-
-
-
-
-// Constructor of robot application.
-
-CRobotMain::CRobotMain(CInstanceManager* iMan)
-{
- ObjectType type;
- float fValue;
- int iValue, i;
- char* token;
-
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_MAIN, this);
-
- m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
- m_cloud = (CCloud*)m_iMan->SearchInstance(CLASS_CLOUD);
- m_blitz = (CBlitz*)m_iMan->SearchInstance(CLASS_BLITZ);
- m_planet = (CPlanet*)m_iMan->SearchInstance(CLASS_PLANET);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
-
- m_interface = new CInterface(m_iMan);
- m_terrain = new CTerrain(m_iMan);
- m_model = new CModel(m_iMan);
- m_camera = new CCamera(m_iMan);
- m_displayText = new CDisplayText(m_iMan);
- m_movie = new CMainMovie(m_iMan);
- m_dialog = new CMainDialog(m_iMan);
- m_short = new CMainShort(m_iMan);
- m_map = new CMainMap(m_iMan);
- m_displayInfo = 0;
-
- m_engine->SetTerrain(m_terrain);
- m_filesDir = m_dialog->RetFilesDir();
-
- m_time = 0.0f;
- m_gameTime = 0.0f;
- m_checkEndTime = 0.0f;
-
- m_phase = PHASE_NAME;
- m_cameraRank = -1;
- m_visitLast = EVENT_NULL;
- m_visitObject = 0;
- m_visitArrow = 0;
- m_audioTrack = 0;
- m_bAudioRepeat = true;
- m_delayWriteMessage = 0;
- m_selectObject = 0;
- m_infoUsed = 0;
-
- m_bBeginSatCom = false;
- m_bMovieLock = false;
- m_bSatComLock = false;
- m_bEditLock = false;
- m_bEditFull = false;
- m_bPause = false;
- m_bHilite = false;
- m_bFreePhoto = false;
- m_bShowPos = false;
- m_bSelectInsect = false;
- m_bShowSoluce = false;
- m_bShowAll = false;
- m_bCheatRadar = false;
- m_bFixScene = false;
- m_bTrainerPilot = false;
- m_bSuspend = false;
- m_bFriendAim = false;
- m_bResetCreate = false;
- m_bShortCut = true;
-
- m_engine->SetMovieLock(m_bMovieLock);
-
- m_movie->Flush();
- m_movieInfoIndex = -1;
-
- m_tooltipPos = Math::Point(0.0f, 0.0f);
- m_tooltipName[0] = 0;
- m_tooltipTime = 0.0f;
-
- m_endingWinRank = 0;
- m_endingLostRank = 0;
- m_bWinTerminate = false;
-
- FlushDisplayInfo();
-
- m_fontSize = 9.0f;
- m_windowPos = Math::Point(0.15f, 0.17f);
- m_windowDim = Math::Point(0.70f, 0.66f);
-
- if ( GetProfileFloat("Edit", "FontSize", fValue) ) m_fontSize = fValue;
- if ( GetProfileFloat("Edit", "WindowPos.x", fValue) ) m_windowPos.x = fValue;
- if ( GetProfileFloat("Edit", "WindowPos.y", fValue) ) m_windowPos.y = fValue;
- if ( GetProfileFloat("Edit", "WindowDim.x", fValue) ) m_windowDim.x = fValue;
- if ( GetProfileFloat("Edit", "WindowDim.y", fValue) ) m_windowDim.y = fValue;
-
- m_IOPublic = false;
- m_IODim = Math::Point(320.0f/640.0f, (121.0f+18.0f*8)/480.0f);
- m_IOPos.x = (1.0f-m_IODim.x)/2.0f; // in the middle
- m_IOPos.y = (1.0f-m_IODim.y)/2.0f;
-
- if ( GetProfileInt ("Edit", "IOPublic", iValue) ) m_IOPublic = iValue;
- if ( GetProfileFloat("Edit", "IOPos.x", fValue) ) m_IOPos.x = fValue;
- if ( GetProfileFloat("Edit", "IOPos.y", fValue) ) m_IOPos.y = fValue;
- if ( GetProfileFloat("Edit", "IODim.x", fValue) ) m_IODim.x = fValue;
- if ( GetProfileFloat("Edit", "IODim.y", fValue) ) m_IODim.y = fValue;
-
- m_short->FlushShortcuts();
- InitEye();
-
- m_engine->SetTracePrecision(1.0f);
-
- m_cameraPan = 0.0f;
- m_cameraZoom = 0.0f;
-
- g_id = 0;
- g_build = 0;
- g_researchDone = 0; // no research done
- g_researchEnable = 0;
- g_unit = 4.0f;
-
- m_gamerName[0] = 0;
- GetProfileString("Gamer", "LastName", m_gamerName, 100);
- SetGlobalGamerName(m_gamerName);
- ReadFreeParam();
- m_dialog->SetupRecall();
-
- for ( i=0 ; i<MAXSHOWLIMIT ; i++ )
- {
- m_showLimit[i].bUsed = false;
- m_showLimit[i].total = 0;
- m_showLimit[i].link = 0;
- }
-
- CBotProgram::SetTimer(100);
- CBotProgram::Init();
-
- for ( i=0 ; i<OBJECT_MAX ; i++ )
- {
- type = (ObjectType)i;
- token = RetObjectName(type);
- if ( token[0] != 0 )
- {
- CBotProgram::DefineNum(token, type);
- }
- token = RetObjectAlias(type);
- if ( token[0] != 0 )
- {
- CBotProgram::DefineNum(token, type);
- }
- }
-
- CBotProgram::DefineNum("White", 0);
- CBotProgram::DefineNum("Black", 1);
- CBotProgram::DefineNum("Gray", 2);
- CBotProgram::DefineNum("LightGray", 3);
- CBotProgram::DefineNum("Red", 4);
- CBotProgram::DefineNum("Pink", 5);
- CBotProgram::DefineNum("Purple", 6);
- CBotProgram::DefineNum("Orange", 7);
- CBotProgram::DefineNum("Yellow", 8);
- CBotProgram::DefineNum("Beige", 9);
- CBotProgram::DefineNum("Brown", 10);
- CBotProgram::DefineNum("Skin", 11);
- CBotProgram::DefineNum("Green", 12);
- CBotProgram::DefineNum("LightGreen", 13);
- CBotProgram::DefineNum("Blue", 14);
- CBotProgram::DefineNum("LightBlue", 15);
- CBotProgram::DefineNum("BlackArrow", 16);
- CBotProgram::DefineNum("RedArrow", 17);
-
- CBotProgram::DefineNum("Metal", OM_METAL);
- CBotProgram::DefineNum("Plastic", OM_PLASTIC);
-
- CBotProgram::DefineNum("InFront", TMA_FFRONT);
- CBotProgram::DefineNum("Behind", TMA_FBACK);
- CBotProgram::DefineNum("EnergyCell", TMA_POWER);
-
- CBotProgram::DefineNum("DisplayError", TT_ERROR);
- CBotProgram::DefineNum("DisplayWarning", TT_WARNING);
- CBotProgram::DefineNum("DisplayInfo", TT_INFO);
- CBotProgram::DefineNum("DisplayMessage", TT_MESSAGE);
-
- CBotProgram::DefineNum("FilterNone", FILTER_NONE);
- CBotProgram::DefineNum("FilterOnlyLanding", FILTER_ONLYLANDING);
- CBotProgram::DefineNum("FilterOnlyFliying", FILTER_ONLYFLYING);
-
- // Add the class Point.
- CBotClass* bc;
- bc = new CBotClass("point", NULL, true); // intrinsic class
- bc->AddItem("x", CBotTypFloat);
- bc->AddItem("y", CBotTypFloat);
- bc->AddItem("z", CBotTypFloat);
- bc->AddFunction("point", rPoint, cPoint);
-
- // Adds the class Object.
- bc = new CBotClass("object", NULL);
- bc->AddItem("category", CBotTypResult(CBotTypInt), PR_READ);
- bc->AddItem("position", CBotTypResult(CBotTypClass, "point"), PR_READ);
- bc->AddItem("orientation", CBotTypResult(CBotTypFloat), PR_READ);
- bc->AddItem("pitch", CBotTypResult(CBotTypFloat), PR_READ);
- bc->AddItem("roll", CBotTypResult(CBotTypFloat), PR_READ);
- bc->AddItem("energyLevel", CBotTypResult(CBotTypFloat), PR_READ);
- bc->AddItem("shieldLevel", CBotTypResult(CBotTypFloat), PR_READ);
- bc->AddItem("temperature", CBotTypResult(CBotTypFloat), PR_READ);
- bc->AddItem("altitude", CBotTypResult(CBotTypFloat), PR_READ);
- bc->AddItem("lifeTime", CBotTypResult(CBotTypFloat), PR_READ);
- bc->AddItem("material", CBotTypResult(CBotTypInt), PR_READ);
- bc->AddItem("energyCell", CBotTypResult(CBotTypPointer, "object"), PR_READ);
- bc->AddItem("load", CBotTypResult(CBotTypPointer, "object"), PR_READ);
-
- // Initializes the class FILE.
- InitClassFILE();
-
- CScript::InitFonctions();
-}
-
-// Destructor of robot application.
-
-CRobotMain::~CRobotMain()
-{
- delete m_movie;
- delete m_dialog;
- delete m_short;
- delete m_map;
- delete m_terrain;
- delete m_model;
-}
-
-
-// Creates the file colobot.ini at the first time.
-
-void CRobotMain::CreateIni()
-{
- int iValue;
-
- // colobot.ini don't exist?
- if ( !GetProfileInt("Setup", "TotoMode", iValue) )
- {
- m_dialog->SetupMemorize();
- }
-}
-
-
-// Changes phase.
-
-void CRobotMain::ChangePhase(Phase phase)
-{
- CEdit* pe;
- CButton* pb;
- D3DCOLORVALUE color;
- Math::Point pos, dim, ddim;
- float ox, oy, sx, sy;
- char* read;
- int rank, numTry;
- bool bLoading;
-
- if ( m_phase == PHASE_SIMUL ) // ends a simulation?
- {
- SaveAllScript();
- m_sound->StopMusic();
- m_camera->SetObject(0);
-
-#if _SCHOOL
- if ( true )
-#else
- if ( m_gameTime > 10.0f ) // did you play at least 10 seconds?
-#endif
- {
- rank = m_dialog->RetSceneRank();
- numTry = m_dialog->RetGamerInfoTry(rank);
- m_dialog->SetGamerInfoTry(rank, numTry+1);
- m_dialog->WriteGamerInfo();
- }
- }
-
- if ( phase == PHASE_WIN ) // wins a simulation?
- {
- rank = m_dialog->RetSceneRank();
- m_dialog->SetGamerInfoPassed(rank, true);
- m_dialog->NextMission(); // passes to the next mission
- m_dialog->WriteGamerInfo();
- }
-
- DeleteAllObjects(); // removes all the current 3D Scene
-
- m_phase = phase;
- m_winDelay = 0.0f;
- m_lostDelay = 0.0f;
- m_bBeginSatCom = false;
- m_bMovieLock = false;
- m_bSatComLock = false;
- m_bEditLock = false;
- m_bFreePhoto = false;
- m_bResetCreate = false;
-
- m_engine->SetMovieLock(m_bMovieLock);
- ChangePause(false);
- FlushDisplayInfo();
- m_engine->SetRankView(0);
- m_engine->FlushObject();
- color.r = color.g = color.b = color.a = 0.0f;
- m_engine->SetWaterAddColor(color);
- m_engine->SetBackground("");
- m_engine->SetBackForce(false);
- m_engine->SetFrontsizeName("");
- m_engine->SetOverColor();
- m_engine->GroundMarkDelete(0);
- SetSpeed(1.0f);
- m_terrain->SetWind(Math::Vector(0.0f, 0.0f, 0.0f));
- m_terrain->FlushBuildingLevel();
- m_terrain->FlushFlyingLimit();
- m_light->FlushLight();
- m_particule->FlushParticule();
- m_water->Flush();
- m_cloud->Flush();
- m_blitz->Flush();
- m_planet->Flush();
- m_iMan->Flush(CLASS_OBJECT);
- m_iMan->Flush(CLASS_PHYSICS);
- m_iMan->Flush(CLASS_BRAIN);
- m_iMan->Flush(CLASS_PYRO);
- m_model->StopUserAction();
- m_interface->Flush();
- ClearInterface();
- FlushNewScriptName();
- m_sound->SetListener(Math::Vector(0.0f, 0.0f, 0.0f), Math::Vector(0.0f, 0.0f, 1.0f));
- m_camera->SetType(CAMERA_DIALOG);
- m_movie->Flush();
- m_movieInfoIndex = -1;
- m_cameraPan = 0.0f;
- m_cameraZoom = 0.0f;
- m_bShortCut = true;
-
- // Creates and hide the command console.
- dim.x = 200.0f/640.0f;
- dim.y = 18.0f/480.0f;
- pos.x = 50.0f/640.0f;
- pos.y = 452.0f/480.0f;
- pe = m_interface->CreateEdit(pos, dim, 0, EVENT_CMD);
- if ( pe == 0 ) return;
- pe->ClearState(STATE_VISIBLE);
- m_bCmdEdit = false; // hidden for now
-
- // Creates the speedometer.
-#if _TEEN
- dim.x = 30.0f/640.0f;
- dim.y = 20.0f/480.0f;
- pos.x = 4.0f/640.0f;
- pos.y = 454.0f/480.0f;
-#else
- dim.x = 30.0f/640.0f;
- dim.y = 20.0f/480.0f;
- pos.x = 4.0f/640.0f;
- pos.y = 426.0f/480.0f;
-#endif
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_SPEED);
- if ( pb == 0 ) return;
- pb->SetState(STATE_SIMPLY);
- pb->ClearState(STATE_VISIBLE);
-
- m_dialog->ChangePhase(m_phase);
-
- dim.x = 32.0f/640.0f;
- dim.y = 32.0f/480.0f;
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = (32.0f+2.0f)/640.0f;
- sy = (32.0f+2.0f)/480.0f;
-
- if ( m_phase != PHASE_PERSO )
- {
- m_engine->SetDrawWorld(true);
- m_engine->SetDrawFront(false);
- m_bFixScene = false;
- }
-
- if ( m_phase == PHASE_INIT )
- {
-#if _NEWLOOK
- m_engine->FreeTexture("generna.tga");
- m_engine->FreeTexture("genernb.tga");
- m_engine->FreeTexture("genernc.tga");
- m_engine->FreeTexture("genernd.tga");
-#else
-#if _FRENCH
-#if _DEMO
- m_engine->FreeTexture("genedfa.tga");
- m_engine->FreeTexture("genedfb.tga");
- m_engine->FreeTexture("genedfc.tga");
- m_engine->FreeTexture("genedfd.tga");
-#else
- m_engine->FreeTexture("generfa.tga");
- m_engine->FreeTexture("generfb.tga");
- m_engine->FreeTexture("generfc.tga");
- m_engine->FreeTexture("generfd.tga");
-#endif
-#endif
-#if _ENGLISH
-#if _DEMO
- m_engine->FreeTexture("genedea.tga");
- m_engine->FreeTexture("genedeb.tga");
- m_engine->FreeTexture("genedec.tga");
- m_engine->FreeTexture("geneded.tga");
-#else
- m_engine->FreeTexture("generea.tga");
- m_engine->FreeTexture("genereb.tga");
- m_engine->FreeTexture("generec.tga");
- m_engine->FreeTexture("genered.tga");
-#endif
-#endif
-#if _GERMAN
-#if _DEMO
- m_engine->FreeTexture("genedda.tga");
- m_engine->FreeTexture("geneddb.tga");
- m_engine->FreeTexture("geneddc.tga");
- m_engine->FreeTexture("geneddd.tga");
-#else
- m_engine->FreeTexture("generea.tga");
- m_engine->FreeTexture("genereb.tga");
- m_engine->FreeTexture("generec.tga");
- m_engine->FreeTexture("genered.tga");
-#endif
-#endif
-#if _WG
-#if _DEMO
- m_engine->FreeTexture("genedda.tga");
- m_engine->FreeTexture("geneddb.tga");
- m_engine->FreeTexture("geneddc.tga");
- m_engine->FreeTexture("geneddd.tga");
-#else
- m_engine->FreeTexture("generda.tga");
- m_engine->FreeTexture("generdb.tga");
- m_engine->FreeTexture("generdc.tga");
- m_engine->FreeTexture("generdd.tga");
-#endif
-#endif
-#if _POLISH
-#if _DEMO
- m_engine->FreeTexture("genedpa.tga");
- m_engine->FreeTexture("genedpb.tga");
- m_engine->FreeTexture("genedpc.tga");
- m_engine->FreeTexture("genedpd.tga");
-#else
- m_engine->FreeTexture("generpa.tga");
- m_engine->FreeTexture("generpb.tga");
- m_engine->FreeTexture("generpc.tga");
- m_engine->FreeTexture("generpd.tga");
-#endif
-#endif
-#endif
- }
-
- if ( m_phase == PHASE_SIMUL )
- {
- m_engine->FreeTexture("inter01a.tga");
- m_engine->FreeTexture("inter01b.tga");
- m_engine->FreeTexture("inter01c.tga");
- m_engine->FreeTexture("inter01d.tga");
-
- read = m_dialog->RetSceneRead();
- bLoading = (read[0] != 0);
-
- m_map->CreateMap();
- CreateScene(m_dialog->RetSceneSoluce(), false, false); // interactive scene
- if ( m_bMapImage )
- {
- m_map->SetFixImage(m_mapFilename);
- }
-
- pos.x = 620.0f/640.0f;
- pos.y = 460.0f/480.0f;
- ddim.x = 20.0f/640.0f;
- ddim.y = 20.0f/480.0f;
- m_interface->CreateButton(pos, ddim, 11, EVENT_BUTTON_QUIT);
-
- if ( m_bImmediatSatCom && !bLoading &&
- m_infoFilename[SATCOM_HUSTON][0] != 0 )
- {
- StartDisplayInfo(SATCOM_HUSTON, false); // shows the instructions
- }
-
- m_sound->StopMusic();
- if ( !m_bBase || bLoading ) StartMusic();
- }
-
- if ( m_phase == PHASE_WIN )
- {
- if ( m_endingWinRank == -1 )
- {
- ChangePhase(PHASE_TERM);
- }
- else
- {
-#if _TEEN
- m_bWinTerminate = (m_endingWinRank == 900);
- m_dialog->SetSceneName("teenw");
-#else
- m_bWinTerminate = (m_endingWinRank == 904);
- m_dialog->SetSceneName("win");
-#endif
- m_dialog->SetSceneRank(m_endingWinRank);
- CreateScene(false, true, false); // sets scene
-
- pos.x = ox+sx*1; pos.y = oy+sy*1;
- ddim.x = dim.x*2; ddim.y = dim.y*2;
- m_interface->CreateButton(pos, ddim, 16, EVENT_BUTTON_OK);
-
- if ( m_bWinTerminate )
- {
-#if _TEEN
- pos.x = ox+sx*3; pos.y = oy+sy*1;
- ddim.x = dim.x*15; ddim.y = dim.y*2;
- pe = m_interface->CreateEdit(pos, ddim, 0, EVENT_EDIT0);
- pe->SetFontType(FONT_COLOBOT);
- pe->SetEditCap(false);
- pe->SetHiliteCap(false);
- pe->ReadText("help\\teenw.txt");
-#else
- pos.x = ox+sx*3; pos.y = oy+sy*0.2f;
- ddim.x = dim.x*15; ddim.y = dim.y*3.0f;
- pe = m_interface->CreateEdit(pos, ddim, 0, EVENT_EDIT0);
- pe->SetGenericMode(true);
- pe->SetFontType(FONT_COLOBOT);
- pe->SetEditCap(false);
- pe->SetHiliteCap(false);
- pe->ReadText("help\\win.txt");
-#endif
- }
- else
- {
- m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f), 15.0f, 60.0f, 1000.0f);
- }
- }
- m_sound->StopAll();
- StartMusic();
- }
-
- if ( m_phase == PHASE_LOST )
- {
- if ( m_endingLostRank == -1 )
- {
- ChangePhase(PHASE_TERM);
- }
- else
- {
- m_bWinTerminate = false;
- m_dialog->SetSceneName("lost");
- m_dialog->SetSceneRank(m_endingLostRank);
- CreateScene(false, true, false); // sets scene
-
- pos.x = ox+sx*1; pos.y = oy+sy*1;
- ddim.x = dim.x*2; ddim.y = dim.y*2;
- m_interface->CreateButton(pos, ddim, 16, EVENT_BUTTON_OK);
- m_displayText->DisplayError(INFO_LOST, Math::Vector(0.0f,0.0f,0.0f), 15.0f, 60.0f, 1000.0f);
- }
- m_sound->StopAll();
- StartMusic();
- }
-
- if ( m_phase == PHASE_MODEL )
- {
- pos.x = ox+sx*0; pos.y = oy+sy*0;
- m_interface->CreateButton(pos, dim, 11, EVENT_BUTTON_CANCEL);
-
- CreateModel();
- }
-
- if ( m_phase == PHASE_LOADING )
- {
- m_engine->SetMouseHide(true);
- }
- else
- {
- m_engine->SetMouseHide(false);
- }
-
- m_engine->LoadAllTexture();
-}
-
-
-// Processes an event.
-
-bool CRobotMain::EventProcess(const Event &event)
-{
- CEdit* pe;
- CObject* pObj;
- Event newEvent;
- MainMovieType type;
- int i;
-
- if ( event.event == EVENT_FRAME )
- {
- if ( !m_movie->EventProcess(event) ) // end of the movie?
- {
- type = m_movie->RetStopType();
- if ( type == MM_SATCOMopen )
- {
- ChangePause(false);
- SelectObject(m_infoObject, false); // hands over the command buttons
- m_map->ShowMap(m_bMapShow);
- m_displayText->HideText(false);
- i = m_movieInfoIndex;
- StartDisplayInfo(m_movieInfoIndex, false);
- m_movieInfoIndex = i;
- }
- }
-
- m_dialog->EventProcess(event);
- m_displayText->EventProcess(event);
- RemoteCamera(m_cameraPan, m_cameraZoom, event.rTime);
-
- m_interface->EventProcess(event);
- if ( m_displayInfo != 0 ) // current edition?
- {
- m_displayInfo->EventProcess(event);
- }
- return EventFrame(event);
- }
-
- // Management of the console.
-#if 0
- if ( m_phase != PHASE_NAME &&
- !m_movie->IsExist() &&
- event.event == EVENT_KEYDOWN &&
- event.param == VK_PAUSE &&
- (event.keyState&KS_CONTROL) != 0 )
-#else
- if ( m_phase != PHASE_NAME &&
- !m_movie->IsExist() &&
- event.event == EVENT_KEYDOWN &&
- event.param == VK_CANCEL ) // Ctrl+Pause ?
-#endif
- {
- pe = (CEdit*)m_interface->SearchControl(EVENT_CMD);
- if ( pe == 0 ) return false;
- pe->SetState(STATE_VISIBLE);
- pe->SetFocus(true);
- if ( m_phase == PHASE_SIMUL ) ChangePause(true);
- m_bCmdEdit = true;
- return false;
- }
- if ( event.event == EVENT_KEYDOWN &&
- event.param == VK_RETURN && m_bCmdEdit )
- {
- char cmd[50];
- pe = (CEdit*)m_interface->SearchControl(EVENT_CMD);
- if ( pe == 0 ) return false;
- pe->GetText(cmd, 50);
- pe->SetText("");
- pe->ClearState(STATE_VISIBLE);
- if ( m_phase == PHASE_SIMUL ) ChangePause(false);
- ExecuteCmd(cmd);
- m_bCmdEdit = false;
- return false;
- }
-
- // Management of the speed change.
- if ( event.event == EVENT_SPEED )
- {
- SetSpeed(1.0f);
- }
-
- if ( !m_dialog->EventProcess(event) )
- {
- if ( event.event == EVENT_MOUSEMOVE )
- {
- m_lastMousePos = event.pos;
- HiliteObject(event.pos);
- }
- return false;
- }
-
- if ( !m_displayText->EventProcess(event) )
- {
- return false;
- }
-
- if ( event.event == EVENT_MOUSEMOVE )
- {
- m_lastMousePos = event.pos;
- HiliteObject(event.pos);
- }
-
- if ( m_displayInfo != 0 ) // current info?
- {
- m_displayInfo->EventProcess(event);
-
- if ( event.event == EVENT_KEYDOWN )
- {
- if ( event.param == m_engine->RetKey(KEYRANK_HELP, 0) ||
- event.param == m_engine->RetKey(KEYRANK_HELP, 1) ||
- event.param == m_engine->RetKey(KEYRANK_PROG, 0) ||
- event.param == m_engine->RetKey(KEYRANK_PROG, 1) ||
- event.param == VK_ESCAPE )
- {
- StopDisplayInfo();
- }
- }
- if ( event.event == EVENT_OBJECT_INFOOK )
- {
- StopDisplayInfo();
- }
- return false;
- }
-
- // Simulation phase of the game
- if ( m_phase == PHASE_SIMUL )
- {
- UpdateInfoText();
-
- if ( !m_bEditFull )
- {
- m_camera->EventProcess(event);
- }
-
- switch( event.event )
- {
- case EVENT_KEYDOWN:
- KeyCamera(event.event, event.param);
- HiliteClear();
- if ( event.param == VK_F11 )
- {
- m_particule->WriteWheelTrace("Savegame\\t.bmp", 256, 256, Math::Vector(16.0f, 0.0f, -368.0f), Math::Vector(140.0f, 0.0f, -248.0f));
- return false;
- }
- if ( m_bEditLock ) // current edition?
- {
- if ( event.param == m_engine->RetKey(KEYRANK_HELP, 0) ||
- event.param == m_engine->RetKey(KEYRANK_HELP, 1) )
- {
- StartDisplayInfo(SATCOM_HUSTON, false);
- return false;
- }
- if ( event.param == m_engine->RetKey(KEYRANK_PROG, 0) ||
- event.param == m_engine->RetKey(KEYRANK_PROG, 1) )
- {
- StartDisplayInfo(SATCOM_PROG, false);
- return false;
- }
- break;
- }
- if ( m_bMovieLock ) // current movie?
- {
- if ( event.param == m_engine->RetKey(KEYRANK_QUIT, 0) ||
- event.param == m_engine->RetKey(KEYRANK_QUIT, 1) ||
- event.param == VK_ESCAPE )
- {
- AbortMovie();
- }
- return false;
- }
- if ( m_camera->RetType() == CAMERA_VISIT )
- {
- if ( event.param == m_engine->RetKey(KEYRANK_VISIT, 0) ||
- event.param == m_engine->RetKey(KEYRANK_VISIT, 1) )
- {
- StartDisplayVisit(EVENT_NULL);
- }
- if ( event.param == m_engine->RetKey(KEYRANK_QUIT, 0) ||
- event.param == m_engine->RetKey(KEYRANK_QUIT, 1) ||
- event.param == VK_ESCAPE )
- {
- StopDisplayVisit();
- }
- return false;
- }
- if ( event.param == m_engine->RetKey(KEYRANK_QUIT, 0) ||
- event.param == m_engine->RetKey(KEYRANK_QUIT, 1) )
- {
- if ( m_movie->IsExist() )
- {
- StartDisplayInfo(SATCOM_HUSTON, false);
- }
- else if ( m_winDelay > 0.0f )
- {
- ChangePhase(PHASE_WIN);
- }
- else if ( m_lostDelay > 0.0f )
- {
- ChangePhase(PHASE_LOST);
- }
- else
- {
- m_dialog->StartAbort(); // do you want to leave?
- }
- }
- if ( event.param == VK_PAUSE )
- {
- if ( !m_bMovieLock && !m_bEditLock && !m_bCmdEdit &&
- m_camera->RetType() != CAMERA_VISIT &&
- !m_movie->IsExist() )
- {
- ChangePause(!m_engine->RetPause());
- }
- }
- if ( event.param == m_engine->RetKey(KEYRANK_CAMERA, 0) ||
- event.param == m_engine->RetKey(KEYRANK_CAMERA, 1) )
- {
- ChangeCamera();
- }
- if ( event.param == m_engine->RetKey(KEYRANK_DESEL, 0) ||
- event.param == m_engine->RetKey(KEYRANK_DESEL, 1) )
- {
- if ( m_bShortCut )
- {
- DeselectObject();
- }
- }
- if ( event.param == m_engine->RetKey(KEYRANK_HUMAN, 0) ||
- event.param == m_engine->RetKey(KEYRANK_HUMAN, 1) )
- {
- SelectHuman();
- }
- if ( event.param == m_engine->RetKey(KEYRANK_NEXT, 0) ||
- event.param == m_engine->RetKey(KEYRANK_NEXT, 1) )
- {
- if ( m_bShortCut )
- {
- m_short->SelectNext();
- }
- }
- if ( event.param == m_engine->RetKey(KEYRANK_HELP, 0) ||
- event.param == m_engine->RetKey(KEYRANK_HELP, 1) )
- {
- StartDisplayInfo(SATCOM_HUSTON, true);
- }
- if ( event.param == m_engine->RetKey(KEYRANK_PROG, 0) ||
- event.param == m_engine->RetKey(KEYRANK_PROG, 1) )
- {
- StartDisplayInfo(SATCOM_PROG, true);
- }
- if ( event.param == m_engine->RetKey(KEYRANK_VISIT, 0) ||
- event.param == m_engine->RetKey(KEYRANK_VISIT, 1) )
- {
- StartDisplayVisit(EVENT_NULL);
- }
- if ( event.param == m_engine->RetKey(KEYRANK_SPEED10, 0) ||
- event.param == m_engine->RetKey(KEYRANK_SPEED10, 1) )
- {
- SetSpeed(1.0f);
- }
- if ( event.param == m_engine->RetKey(KEYRANK_SPEED15, 0) ||
- event.param == m_engine->RetKey(KEYRANK_SPEED15, 1) )
- {
- SetSpeed(1.5f);
- }
- if ( event.param == m_engine->RetKey(KEYRANK_SPEED20, 0) ||
- event.param == m_engine->RetKey(KEYRANK_SPEED20, 1) )
- {
- SetSpeed(2.0f);
- }
- if ( event.param == m_engine->RetKey(KEYRANK_SPEED30, 0) ||
- event.param == m_engine->RetKey(KEYRANK_SPEED30, 1) )
- {
- SetSpeed(3.0f);
- }
- break;
-
- case EVENT_KEYUP:
- KeyCamera(event.event, event.param);
- break;
-
- case EVENT_LBUTTONDOWN:
- pObj = DetectObject(event.pos);
- if ( !m_bShortCut ) pObj = 0;
- if ( pObj != 0 && pObj->RetType() == OBJECT_TOTO )
- {
- if ( m_displayInfo != 0 ) // current info?
- {
- StopDisplayInfo();
- }
- else
- {
- if ( !m_bEditLock )
- {
- StartDisplayInfo(SATCOM_HUSTON, true);
- }
- }
- }
- else
- {
- SelectObject(pObj);
- }
- break;
-
- case EVENT_LBUTTONUP:
- m_cameraPan = 0.0f;
- m_cameraZoom = 0.0f;
- break;
-
- case EVENT_BUTTON_QUIT:
- if ( m_movie->IsExist() )
- {
- StartDisplayInfo(SATCOM_HUSTON, false);
- }
- else if ( m_winDelay > 0.0f )
- {
- ChangePhase(PHASE_WIN);
- }
- else if ( m_lostDelay > 0.0f )
- {
- ChangePhase(PHASE_LOST);
- }
- else
- {
- m_dialog->StartAbort(); // do you want to leave?
- }
- break;
-
- case EVENT_OBJECT_LIMIT:
- StartShowLimit();
- break;
-
- case EVENT_OBJECT_DESELECT:
- if ( m_bShortCut )
- {
- DeselectObject();
- }
- break;
-
- case EVENT_OBJECT_HELP:
- HelpObject();
- break;
-
- case EVENT_OBJECT_CAMERA:
- ChangeCamera();
- break;
-
- case EVENT_OBJECT_CAMERAleft:
- m_cameraPan = -1.0f;
- break;
- case EVENT_OBJECT_CAMERAright:
- m_cameraPan = 1.0f;
- break;
- case EVENT_OBJECT_CAMERAnear:
- m_cameraZoom = -1.0f;
- break;
- case EVENT_OBJECT_CAMERAaway:
- m_cameraZoom = 1.0f;
- break;
-
- case EVENT_OBJECT_DELETE:
- m_dialog->StartDeleteObject(); // do you want to destroy it?
- break;
-
- case EVENT_OBJECT_BHELP:
- StartDisplayInfo(SATCOM_HUSTON, true);
- break;
-
- case EVENT_OBJECT_SOLUCE:
- StartDisplayInfo(SATCOM_SOLUCE, true);
- break;
-
- case EVENT_OBJECT_MAPZOOM:
- m_map->ZoomMap();
- break;
-
- case EVENT_DT_VISIT0:
- case EVENT_DT_VISIT1:
- case EVENT_DT_VISIT2:
- case EVENT_DT_VISIT3:
- case EVENT_DT_VISIT4:
- StartDisplayVisit(event.event);
- break;
-
- case EVENT_DT_END:
- StopDisplayVisit();
- break;
-
- case EVENT_OBJECT_SHORTCUT00:
- case EVENT_OBJECT_SHORTCUT01:
- case EVENT_OBJECT_SHORTCUT02:
- case EVENT_OBJECT_SHORTCUT03:
- case EVENT_OBJECT_SHORTCUT04:
- case EVENT_OBJECT_SHORTCUT05:
- case EVENT_OBJECT_SHORTCUT06:
- case EVENT_OBJECT_SHORTCUT07:
- case EVENT_OBJECT_SHORTCUT08:
- case EVENT_OBJECT_SHORTCUT09:
- case EVENT_OBJECT_SHORTCUT10:
- case EVENT_OBJECT_SHORTCUT11:
- case EVENT_OBJECT_SHORTCUT12:
- case EVENT_OBJECT_SHORTCUT13:
- case EVENT_OBJECT_SHORTCUT14:
- case EVENT_OBJECT_SHORTCUT15:
- case EVENT_OBJECT_SHORTCUT16:
- case EVENT_OBJECT_SHORTCUT17:
- case EVENT_OBJECT_SHORTCUT18:
- case EVENT_OBJECT_SHORTCUT19:
- m_short->SelectShortcut(event.event);
- break;
-
- case EVENT_OBJECT_MOVIELOCK:
- AbortMovie();
- break;
-
- case EVENT_WIN:
- ChangePhase(PHASE_WIN);
- break;
-
- case EVENT_LOST:
- ChangePhase(PHASE_LOST);
- break;
- }
-
- EventObject(event);
- return false;
- }
-
- if ( m_phase == PHASE_PERSO )
- {
- EventObject(event);
- }
-
- if ( m_phase == PHASE_WIN ||
- m_phase == PHASE_LOST )
- {
- EventObject(event);
-
- switch( event.event )
- {
- case EVENT_KEYDOWN:
- if ( event.param == VK_ESCAPE ||
- event.param == VK_RETURN )
- {
- if ( m_bWinTerminate )
- {
- ChangePhase(PHASE_INIT);
- }
- else
- {
- ChangePhase(PHASE_TERM);
- }
- }
- break;
-
- case EVENT_BUTTON_OK:
- if ( m_bWinTerminate )
- {
- ChangePhase(PHASE_INIT);
- }
- else
- {
- ChangePhase(PHASE_TERM);
- }
- break;
- }
- }
-
- if ( m_phase == PHASE_MODEL )
- {
- switch( event.event )
- {
- case EVENT_KEYDOWN:
- if ( event.param == VK_ESCAPE )
- {
- ChangePhase(PHASE_INIT);
- }
- if ( event.param == VK_HOME )
- {
- InitEye();
- }
- break;
-
- case EVENT_BUTTON_CANCEL:
- ChangePhase(PHASE_INIT);
- break;
- }
-
- m_model->EventProcess(event);
- return false;
- }
-
- return true;
-}
-
-
-
-// Executes a command.
-
-void CRobotMain::ExecuteCmd(char *cmd)
-{
- if ( cmd[0] == 0 ) return;
-
- if ( m_phase == PHASE_SIMUL )
- {
- if ( strcmp(cmd, "winmission") == 0 )
- {
- Event newEvent;
- m_event->MakeEvent(newEvent, EVENT_WIN);
- m_event->AddEvent(newEvent);
- }
-
- if ( strcmp(cmd, "lostmission") == 0 )
- {
- Event newEvent;
- m_event->MakeEvent(newEvent, EVENT_LOST);
- m_event->AddEvent(newEvent);
- }
-
- if ( strcmp(cmd, "trainerpilot") == 0 )
- {
- m_bTrainerPilot = !m_bTrainerPilot;
- return;
- }
-
- if ( strcmp(cmd, "fly") == 0 )
- {
- Event newEvent;
-
- g_researchDone |= RESEARCH_FLY;
-
- m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
- m_event->AddEvent(newEvent);
- return;
- }
-
- if ( strcmp(cmd, "allresearch") == 0 )
- {
- Event newEvent;
-
- g_researchDone = -1; // all research are done
-
- m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
- m_event->AddEvent(newEvent);
- return;
- }
-
- if ( strcmp(cmd, "nolimit") == 0 )
- {
- m_terrain->SetFlyingMaxHeight(280.0f);
- return;
- }
-
- if ( strcmp(cmd, "photo1") == 0 )
- {
- m_bFreePhoto = !m_bFreePhoto;
- if ( m_bFreePhoto )
- {
- m_camera->SetType(CAMERA_FREE);
- ChangePause(true);
- }
- else
- {
- m_camera->SetType(CAMERA_BACK);
- ChangePause(false);
- }
- return;
- }
-
- if ( strcmp(cmd, "photo2") == 0 )
- {
- m_bFreePhoto = !m_bFreePhoto;
- if ( m_bFreePhoto )
- {
- m_camera->SetType(CAMERA_FREE);
- ChangePause(true);
- DeselectAll(); // removes the control buttons
- m_map->ShowMap(false);
- m_displayText->HideText(true);
- }
- else
- {
- m_camera->SetType(CAMERA_BACK);
- ChangePause(false);
- m_map->ShowMap(m_bMapShow);
- m_displayText->HideText(false);
- }
- return;
- }
-
- if ( strcmp(cmd, "noclip") == 0 )
- {
- CObject* object;
-
- object = RetSelect();
- if ( object != 0 )
- {
- object->SetClip(false);
- }
- return;
- }
-
- if ( strcmp(cmd, "clip") == 0 )
- {
- CObject* object;
-
- object = RetSelect();
- if ( object != 0 )
- {
- object->SetClip(true);
- }
- return;
- }
-
- if ( strcmp(cmd, "addhusky") == 0 )
- {
- CObject* object;
-
- object = RetSelect();
- if ( object != 0 )
- {
- object->SetMagnifyDamage(object->RetMagnifyDamage()*0.1f);
- }
- return;
- }
-
- if ( strcmp(cmd, "addfreezer") == 0 )
- {
- CObject* object;
-
- object = RetSelect();
- if ( object != 0 )
- {
- object->SetRange(object->RetRange()*10.0f);
- }
- return;
- }
-
- if ( strcmp(cmd, "fullpower") == 0 )
- {
- CObject* object;
- CObject* power;
- CPhysics* physics;
-
- object = RetSelect();
- if ( object != 0 )
- {
- power = object->RetPower();
- if ( power != 0 )
- {
- power->SetEnergy(1.0f);
- }
- object->SetShield(1.0f);
- physics = object->RetPhysics();
- if ( physics != 0 )
- {
- physics->SetReactorRange(1.0f);
- }
- }
- return;
- }
-
- if ( strcmp(cmd, "fullenergy") == 0 )
- {
- CObject* object;
- CObject* power;
-
- object = RetSelect();
- if ( object != 0 )
- {
- power = object->RetPower();
- if ( power != 0 )
- {
- power->SetEnergy(1.0f);
- }
- }
- return;
- }
-
- if ( strcmp(cmd, "fullshield") == 0 )
- {
- CObject* object;
-
- object = RetSelect();
- if ( object != 0 )
- {
- object->SetShield(1.0f);
- }
- return;
- }
-
- if ( strcmp(cmd, "fullrange") == 0 )
- {
- CObject* object;
- CPhysics* physics;
-
- object = RetSelect();
- if ( object != 0 )
- {
- physics = object->RetPhysics();
- if ( physics != 0 )
- {
- physics->SetReactorRange(1.0f);
- }
- }
- return;
- }
- }
-
- if ( strcmp(cmd, "debugmode") == 0 )
- {
- m_engine->SetDebugMode(!m_engine->RetDebugMode());
- return;
- }
-
- if ( strcmp(cmd, "showstat") == 0 )
- {
- m_engine->SetShowStat(!m_engine->RetShowStat());
- return;
- }
-
- if ( strcmp(cmd, "invshadow") == 0 )
- {
- m_engine->SetShadow(!m_engine->RetShadow());
- return;
- }
-
- if ( strcmp(cmd, "invdirty") == 0 )
- {
- m_engine->SetDirty(!m_engine->RetDirty());
- return;
- }
-
- if ( strcmp(cmd, "invfog") == 0 )
- {
- m_engine->SetFog(!m_engine->RetFog());
- return;
- }
-
- if ( strcmp(cmd, "invlens") == 0 )
- {
- m_engine->SetLensMode(!m_engine->RetLensMode());
- return;
- }
-
- if ( strcmp(cmd, "invwater") == 0 )
- {
- m_engine->SetWaterMode(!m_engine->RetWaterMode());
- return;
- }
-
- if ( strcmp(cmd, "invsky") == 0 )
- {
- m_engine->SetSkyMode(!m_engine->RetSkyMode());
- return;
- }
-
- if ( strcmp(cmd, "invplanet") == 0 )
- {
- m_engine->SetPlanetMode(!m_engine->RetPlanetMode());
- return;
- }
-
- if ( strcmp(cmd, "showpos") == 0 )
- {
- m_bShowPos = !m_bShowPos;
- return;
- }
-
- if ( strcmp(cmd, "selectinsect") == 0 )
- {
- m_bSelectInsect = !m_bSelectInsect;
- return;
- }
-
- if ( strcmp(cmd, "showsoluce") == 0 )
- {
- m_bShowSoluce = !m_bShowSoluce;
- m_dialog->ShowSoluceUpdate();
- return;
- }
-
-#if _TEEN
- if ( strcmp(cmd, "allteens") == 0 )
-#else
- if ( strcmp(cmd, "allmission") == 0 )
-#endif
- {
- m_bShowAll = !m_bShowAll;
- m_dialog->AllMissionUpdate();
- return;
- }
-
- if ( strcmp(cmd, "invradar") == 0 )
- {
- m_bCheatRadar = !m_bCheatRadar;
- return;
- }
-
- if ( m_phase == PHASE_SIMUL )
- {
- m_displayText->DisplayError(ERR_CMD, Math::Vector(0.0f,0.0f,0.0f));
- }
-}
-
-
-
-// Returns the type of current movie.
-
-MainMovieType CRobotMain::RetMainMovie()
-{
- return m_movie->RetType();
-}
-
-
-// Clears the display of instructions.
-
-void CRobotMain::FlushDisplayInfo()
-{
- int i;
-
- for ( i=0 ; i<SATCOM_MAX ; i++ )
- {
- m_infoFilename[i][0] = 0;
- m_infoPos[i] = 0;
- }
- strcpy(m_infoFilename[SATCOM_OBJECT], "help\\objects.txt");
- m_infoIndex = 0;
-}
-
-// Beginning of the displaying of instructions.
-// index: SATCOM_*
-
-void CRobotMain::StartDisplayInfo(int index, bool bMovie)
-{
- CObject* pObj;
- CMotion* motion;
- bool bHuman;
-
- if ( m_bCmdEdit || m_bSatComLock ) return;
-
- pObj = RetSelect();
- bHuman = ( pObj != 0 && pObj->RetType() == OBJECT_HUMAN );
-
- if ( !m_bEditLock && bMovie && !m_movie->IsExist() && bHuman )
- {
- motion = pObj->RetMotion();
- if ( motion != 0 && motion->RetAction() == -1 )
- {
- m_movieInfoIndex = index;
- m_movie->Start(MM_SATCOMopen, 2.5f);
- ChangePause(true);
-//? m_map->ShowMap(false);
- m_infoObject = DeselectAll(); // removes the control buttons
- m_displayText->HideText(true);
- return;
- }
- }
-
- if ( m_movie->IsExist() )
- {
- m_movie->Stop();
- ChangePause(false);
- SelectObject(m_infoObject, false); // hands over the command buttons
-//? m_map->ShowMap(m_bMapShow);
- m_displayText->HideText(false);
- }
-
- StartDisplayInfo(m_infoFilename[index], index);
-}
-
-// Beginning of the displaying of instructions.
-
-void CRobotMain::StartDisplayInfo(char *filename, int index)
-{
- CButton* pb;
- bool bSoluce;
-
- if ( m_bCmdEdit ) return;
-
- m_movieInfoIndex = -1;
- ClearInterface(); // removes setting evidence and tooltip
-
- if ( !m_bEditLock )
- {
-//? m_map->ShowMap(false);
- m_infoObject = DeselectAll(); // removes the control buttons
- m_displayText->HideText(true);
- m_sound->MuteAll(true);
- }
-
- pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
- if ( pb != 0 )
- {
- pb->ClearState(STATE_VISIBLE);
- }
-
- bSoluce = m_dialog->RetSceneSoluce();
-
- m_displayInfo = new CDisplayInfo(m_iMan);
- m_displayInfo->StartDisplayInfo(filename, index, bSoluce);
-
- m_infoIndex = index;
- if ( index != -1 )
- {
- m_displayInfo->SetPosition(m_infoPos[index]);
- }
-}
-
-// End of displaying of instructions.
-
-void CRobotMain::StopDisplayInfo()
-{
- CButton* pb;
-
- if ( m_movieInfoIndex != -1 ) // film to read the SatCom?
- {
- m_movie->Start(MM_SATCOMclose, 2.0f);
- }
-
- if ( m_infoIndex != -1 )
- {
- m_infoPos[m_infoIndex] = m_displayInfo->RetPosition();
- }
- m_displayInfo->StopDisplayInfo();
-
- delete m_displayInfo;
- m_displayInfo = 0;
-
- if ( !m_bEditLock )
- {
- pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
- if ( pb != 0 )
- {
- pb->SetState(STATE_VISIBLE);
- }
-
- SelectObject(m_infoObject, false); // gives the command buttons
-//? m_map->ShowMap(m_bMapShow);
- m_displayText->HideText(false);
-
- m_sound->MuteAll(false);
- }
-
- if ( m_infoUsed == 0 )
- {
- m_displayText->ClearText(); // removes message "see SatCom ..."
- }
- m_infoUsed ++;
-}
-
-// Returns the name of the text display.
-
-char* CRobotMain::RetDisplayInfoName(int index)
-{
- return m_infoFilename[index];
-}
-
-// Returns the name of the text display.
-
-int CRobotMain::RetDisplayInfoPosition(int index)
-{
- return m_infoPos[index];
-}
-
-// Returns the name of the text display.
-
-void CRobotMain::SetDisplayInfoPosition(int index, int pos)
-{
- m_infoPos[index] = pos;
-}
-
-
-// Beginning of a dialogue during the game,
-
-void CRobotMain::StartSuspend()
-{
- CButton* pb;
-
- m_map->ShowMap(false);
- m_infoObject = DeselectAll(); // removes the control buttons
- m_displayText->HideText(true);
-
- pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
- if ( pb != 0 )
- {
- pb->ClearState(STATE_VISIBLE);
- }
-
- m_bSuspend = true;
-}
-
-// End of dialogue during the game,
-
-void CRobotMain::StopSuspend()
-{
- CButton* pb;
-
- pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
- if ( pb != 0 )
- {
- pb->SetState(STATE_VISIBLE);
- }
-
- SelectObject(m_infoObject, false); // gives the command buttons
- m_map->ShowMap(m_bMapShow);
- m_displayText->HideText(false);
-
- m_bSuspend = false;
-}
-
-
-// Returns the absolute time of the game
-
-float CRobotMain::RetGameTime()
-{
- return m_gameTime;
-}
-
-
-
-// Managing the size of the default fonts.
-
-void CRobotMain::SetFontSize(float size)
-{
- m_fontSize = size;
- SetProfileFloat("Edit", "FontSize", m_fontSize);
-}
-
-float CRobotMain::RetFontSize()
-{
- return m_fontSize;
-}
-
-// Managing the size of the default window.
-
-void CRobotMain::SetWindowPos(Math::Point pos)
-{
- m_windowPos = pos;
- SetProfileFloat("Edit", "WindowPos.x", m_windowPos.x);
- SetProfileFloat("Edit", "WindowPos.y", m_windowPos.y);
-}
-
-Math::Point CRobotMain::RetWindowPos()
-{
- return m_windowPos;
-}
-
-void CRobotMain::SetWindowDim(Math::Point dim)
-{
- m_windowDim = dim;
- SetProfileFloat("Edit", "WindowDim.x", m_windowDim.x);
- SetProfileFloat("Edit", "WindowDim.y", m_windowDim.y);
-}
-
-Math::Point CRobotMain::RetWindowDim()
-{
- return m_windowDim;
-}
-
-
-// Managing windows open/save.
-
-void CRobotMain::SetIOPublic(bool bMode)
-{
- m_IOPublic = bMode;
- SetProfileInt("Edit", "IOPublic", m_IOPublic);
-}
-
-bool CRobotMain::RetIOPublic()
-{
- return m_IOPublic;
-}
-
-void CRobotMain::SetIOPos(Math::Point pos)
-{
- m_IOPos = pos;
- SetProfileFloat("Edit", "IOPos.x", m_IOPos.x);
- SetProfileFloat("Edit", "IOPos.y", m_IOPos.y);
-}
-
-Math::Point CRobotMain::RetIOPos()
-{
- return m_IOPos;
-}
-
-void CRobotMain::SetIODim(Math::Point dim)
-{
- m_IODim = dim;
- SetProfileFloat("Edit", "IODim.x", m_IODim.x);
- SetProfileFloat("Edit", "IODim.y", m_IODim.y);
-}
-
-Math::Point CRobotMain::RetIODim()
-{
- return m_IODim;
-}
-
-
-
-// Start of the visit instead of an error.
-
-void CRobotMain::StartDisplayVisit(EventMsg event)
-{
- CWindow* pw;
- CButton* button;
- CGroup* group;
- Math::Vector goal;
- Math::Point pos, dim;
- int i, j;
-
- if ( m_bEditLock ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
- if ( pw == 0 ) return;
-
- if ( event == EVENT_NULL ) // visit by keyboard shortcut?
- {
- if ( m_visitLast != EVENT_NULL ) // already a current visit?
- {
- i = m_visitLast-EVENT_DT_VISIT0;
- }
- else
- {
- i = MAXDTLINE;
- }
-
- // Seeks the last.
- for ( j=0 ; j<MAXDTLINE ; j++ )
- {
- i --;
- if ( i < 0 ) i = MAXDTLINE-1;
-
- button = (CButton*)pw->SearchControl(EventMsg(EVENT_DT_VISIT0+i));
- if ( button == 0 || !button->TestState(STATE_ENABLE) ) continue;
-
- group = (CGroup*)pw->SearchControl(EventMsg(EVENT_DT_GROUP0+i));
- if ( group != 0 )
- {
- event = EventMsg(EVENT_DT_VISIT0+i);
- break;
- }
- }
- }
- if ( event == EVENT_NULL )
- {
- m_sound->Play(SOUND_TZOING); // nothing to do!
- return;
- }
-
- m_visitLast = event;
-
- ClearInterface(); // removes setting evidence and tooltip
-
- if ( m_camera->RetType() == CAMERA_VISIT ) // already a current visit?
- {
- m_camera->StopVisit();
- m_displayText->ClearVisit();
- }
- else
- {
- m_visitObject = DeselectAll(); // removes the control buttons
- }
-
- // Creates the "continue" button.
- if ( m_interface->SearchControl(EVENT_DT_END) == 0 )
- {
- pos.x = 10.0f/640.0f;
- pos.y = 10.0f/480.0f;
- dim.x = 50.0f/640.0f;
- dim.y = 50.0f/480.0f;
- m_interface->CreateButton(pos, dim, 16, EVENT_DT_END);
- }
-
- // Creates the arrow to show the place.
- if ( m_visitArrow != 0 )
- {
- m_visitArrow->DeleteObject();
- delete m_visitArrow;
- m_visitArrow = 0;
- }
- goal = m_displayText->RetVisitGoal(event);
- m_visitArrow = CreateObject(goal, 0.0f, 1.0f, 10.0f, OBJECT_SHOW, false, false, 0);
-
- m_visitPos = m_visitArrow->RetPosition(0);
- m_visitPosArrow = m_visitPos;
- m_visitPosArrow.y += m_displayText->RetVisitHeight(event);
- m_visitArrow->SetPosition(0, m_visitPosArrow);
-
- m_visitTime = 0.0;
- m_visitParticule = 0.0f;
-
- m_particule->DeleteParticule(PARTISHOW);
-
- m_camera->StartVisit(m_displayText->RetVisitGoal(event),
- m_displayText->RetVisitDist(event));
- m_displayText->SetVisit(event);
- ChangePause(true);
-}
-
-// Move the arrow to visit.
-
-void CRobotMain::FrameVisit(float rTime)
-{
- Math::Vector pos, speed;
- Math::Point dim;
- float level;
-
- if ( m_visitArrow == 0 ) return;
-
- // Moves the arrow.
- m_visitTime += rTime;
-
- pos = m_visitPosArrow;
- pos.y += 1.5f+sinf(m_visitTime*4.0f)*4.0f;
- m_visitArrow->SetPosition(0, pos);
- m_visitArrow->SetAngleY(0, m_visitTime*2.0f);
-
- // Manages the particles "arrows".
- m_visitParticule -= rTime;
- if ( m_visitParticule <= 0.0f )
- {
- m_visitParticule = 1.5f;
-
- pos = m_visitPos;
- level = m_terrain->RetFloorLevel(pos)+2.0f;
- if ( pos.y < level ) pos.y = level; // not below the ground
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 30.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISHOW, 2.0f);
- }
-}
-
-// End of the visit instead of an error.
-
-void CRobotMain::StopDisplayVisit()
-{
- m_visitLast = EVENT_NULL;
-
- // Removes the button.
- m_interface->DeleteControl(EVENT_DT_END);
-
- // Removes the arrow.
- if ( m_visitArrow != 0 )
- {
- m_visitArrow->DeleteObject();
- delete m_visitArrow;
- m_visitArrow = 0;
- }
-
- // Removes particles "arrows".
- m_particule->DeleteParticule(PARTISHOW);
-
- m_camera->StopVisit();
- m_displayText->ClearVisit();
- ChangePause(false);
- if ( m_visitObject != 0 )
- {
- SelectObject(m_visitObject, false); // gives the command buttons
- m_visitObject = 0;
- }
-}
-
-
-
-// Updates all the shortcuts.
-
-void CRobotMain::UpdateShortcuts()
-{
- m_short->UpdateShortcuts();
-}
-
-// Returns the object that default was select after the creation of a scene.
-
-CObject* CRobotMain::RetSelectObject()
-{
- if ( m_selectObject != 0 ) return m_selectObject;
- return SearchHuman();
-}
-
-// Deselects everything, and returns the object that was selected.
-
-CObject* CRobotMain::DeselectAll()
-{
- CObject* pObj;
- CObject* pPrev;
- int i;
-
- pPrev = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetSelect() ) pPrev = pObj;
- pObj->SetSelect(false);
- }
- return pPrev;
-}
-
-// Selects an object, without attending to deselect the rest.
-
-void CRobotMain::SelectOneObject(CObject* pObj, bool bDisplayError)
-{
- ObjectType type;
- CObject* toto;
- CMotionToto* mt;
-
- pObj->SetSelect(true, bDisplayError);
- m_camera->SetObject(pObj);
-
- type = pObj->RetType();
- if ( 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 ||
- type == OBJECT_APOLLO2 )
- {
- m_camera->SetType(pObj->RetCameraType());
- m_camera->SetDist(pObj->RetCameraDist());
- }
- else
- {
- m_camera->SetType(CAMERA_BACK);
- }
-
- toto = SearchToto();
- if ( toto != 0 )
- {
- mt = (CMotionToto*)toto->RetMotion();
- if ( mt != 0 )
- {
- mt->SetLinkType(type);
- }
- }
-}
-
-// Selects the object aimed by the mouse.
-
-bool CRobotMain::SelectObject(CObject* pObj, bool bDisplayError)
-{
- CObject* pPrev;
-
- if ( m_camera->RetType() == CAMERA_VISIT )
- {
- StopDisplayVisit();
- }
-
- if ( m_bMovieLock || m_bEditLock || m_bPause ) return false;
- if ( m_movie->IsExist() ) return false;
- if ( pObj == 0 || !IsSelectable(pObj) ) return false;
-
- pPrev = DeselectAll();
-
- if ( pPrev != 0 && pPrev != pObj )
- {
- pObj->AddDeselList(pPrev);
- }
-
- SelectOneObject(pObj, bDisplayError);
- m_short->UpdateShortcuts();
- return true;
-}
-
-// Deselects the selected object.
-
-bool CRobotMain::DeselectObject()
-{
- CObject* pObj;
- CObject* pPrev;
-
- pPrev = DeselectAll();
-
- if ( pPrev == 0 )
- {
- pObj = SearchHuman();
- }
- else
- {
- pObj = pPrev->SubDeselList();
- }
- if ( pObj == 0 )
- {
- pObj = SearchHuman();
- }
-
- if ( pObj != 0 )
- {
- SelectOneObject(pObj);
- }
- else
- {
- m_camera->SetType(CAMERA_FREE);
- }
-
- m_short->UpdateShortcuts();
- return true;
-}
-
-// Quickly removes all objects.
-
-void CRobotMain::DeleteAllObjects()
-{
- CPyro* pyro;
- CObject* pObj;
- int i;
-
- // Removes all pyrotechnic effects in progress.
- while ( true )
- {
- pyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, 0);
- if ( pyro == 0 ) break;
-
- pyro->DeleteObject();
- delete pyro;
- }
-
- // Removes the arrow.
- if ( m_visitArrow != 0 )
- {
- m_visitArrow->DeleteObject();
- delete m_visitArrow;
- m_visitArrow = 0;
- }
-
- for ( i=0 ; i<MAXSHOWLIMIT ; i++ )
- {
- FlushShowLimit(i);
- }
-
- while ( true )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, 0);
- if ( pObj == 0 ) break;
-
- pObj->DeleteObject(true); // destroys rapidly
- delete pObj;
- }
-}
-
-// Selects the human.
-
-void CRobotMain::SelectHuman()
-{
- SelectObject(SearchHuman());
-}
-
-// Returns the object human.
-
-CObject* CRobotMain::SearchHuman()
-{
- ObjectType type;
- CObject* pObj;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_HUMAN )
- {
- return pObj;
- }
- }
- return 0;
-}
-
-// Returns the object toto.
-
-CObject* CRobotMain::SearchToto()
-{
- ObjectType type;
- CObject* pObj;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_TOTO )
- {
- return pObj;
- }
- }
- return 0;
-}
-
-// Returns the nearest selectable object from a given position.
-
-CObject* CRobotMain::SearchNearest(Math::Vector pos, CObject* pExclu)
-{
- ObjectType type;
- CObject *pObj, *pBest;
- Math::Vector oPos;
- float min, dist;
- int i;
-
- min = 100000.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == pExclu ) continue;
- if ( !IsSelectable(pObj) ) continue;
-
- type = pObj->RetType();
- if ( type == OBJECT_TOTO ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, pos);
- if ( dist < min )
- {
- min = dist;
- pBest = pObj;
- }
- }
- return pBest;
-}
-
-// Returns the selected object.
-
-CObject* CRobotMain::RetSelect()
-{
- CObject* pObj;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetSelect() )
- {
- return pObj;
- }
- }
- return 0;
-}
-
-CObject* CRobotMain::SearchObject(ObjectType type)
-{
- CObject* pObj;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetType() == type )
- {
- return pObj;
- }
- }
- return 0;
-}
-
-// Detects the object aimed by the mouse.
-
-CObject* CRobotMain::DetectObject(Math::Point pos)
-{
- ObjectType type;
- CObject *pObj, *pTarget;
- int objRank, i, j, rank;
-
- objRank = m_engine->DetectObject(pos);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue;
- if ( pObj->RetProxyActivate() ) continue;
-
- pTarget = 0;
- type = pObj->RetType();
- if ( type == OBJECT_PORTICO ||
- 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 ||
- type == OBJECT_TARGET1 ||
- type == OBJECT_TARGET2 ||
- type == OBJECT_START ||
- type == OBJECT_END ||
- type == OBJECT_STONE ||
- type == OBJECT_URANIUM ||
- type == OBJECT_BULLET ||
- type == OBJECT_METAL ||
- type == OBJECT_BBOX ||
- type == OBJECT_KEYa ||
- type == OBJECT_KEYb ||
- type == OBJECT_KEYc ||
- type == OBJECT_KEYd ||
- type == OBJECT_TNT ||
- type == OBJECT_SCRAP1 ||
- type == OBJECT_SCRAP2 ||
- type == OBJECT_SCRAP3 ||
- type == OBJECT_SCRAP4 ||
- type == OBJECT_SCRAP5 ||
- type == OBJECT_BOMB ||
- type == OBJECT_BAG ||
- type == OBJECT_WAYPOINT ||
- type == OBJECT_FLAGb ||
- type == OBJECT_FLAGr ||
- type == OBJECT_FLAGg ||
- type == OBJECT_FLAGy ||
- type == OBJECT_FLAGv ||
- type == OBJECT_MARKPOWER ||
- type == OBJECT_MARKSTONE ||
- type == OBJECT_MARKURANIUM ||
- type == OBJECT_MARKKEYa ||
- type == OBJECT_MARKKEYb ||
- type == OBJECT_MARKKEYc ||
- type == OBJECT_MARKKEYd ||
- type == OBJECT_HUMAN ||
- type == OBJECT_TECH ||
- type == OBJECT_TOTO ||
- type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr ||
- type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ||
- type == OBJECT_EGG ||
- type == OBJECT_RUINmobilew1 ||
- type == OBJECT_RUINmobilew2 ||
- type == OBJECT_RUINmobilet1 ||
- type == OBJECT_RUINmobilet2 ||
- type == OBJECT_RUINmobiler1 ||
- type == OBJECT_RUINmobiler2 ||
- type == OBJECT_RUINfactory ||
- type == OBJECT_RUINdoor ||
- type == OBJECT_RUINsupport ||
- type == OBJECT_RUINradar ||
- type == OBJECT_RUINconvert ||
- type == OBJECT_RUINbase ||
- type == OBJECT_RUINhead ||
- type == OBJECT_APOLLO1 ||
- type == OBJECT_APOLLO2 ||
- type == OBJECT_APOLLO3 ||
- type == OBJECT_APOLLO4 ||
- type == OBJECT_APOLLO5 )
- {
- pTarget = pObj;
- }
- else if ( (type == OBJECT_POWER ||
- type == OBJECT_ATOMIC ) &&
- pObj->RetTruck() != 0 ) // battery used?
- {
- pTarget = pObj->RetTruck();
- }
- else if ( type == OBJECT_POWER ||
- type == OBJECT_ATOMIC )
- {
- pTarget = pObj;
- }
-
- for ( j=0 ; j<OBJECTMAXPART ; j++ )
- {
- rank = pObj->RetObjectRank(j);
- if ( rank == -1 ) continue;
- if ( rank != objRank ) continue;
- return pTarget;
- }
- }
- return 0;
-}
-
-// Indicates whether an object is selectable.
-
-bool CRobotMain::IsSelectable(CObject* pObj)
-{
- ObjectType type;
-
- if ( !pObj->RetSelectable() ) return false;
-
- type = pObj->RetType();
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TOTO ||
- 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 ||
- type == OBJECT_APOLLO2 ||
- 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 )
- {
- return true;
- }
-
- if ( m_bSelectInsect )
- {
- if ( type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ||
- type == OBJECT_MOBILEtg )
- {
- return true;
- }
- }
-
- return false;
-}
-
-
-// Deletes the selected object.
-
-bool CRobotMain::DeleteObject()
-{
- CObject* pObj;
- CPyro* pyro;
-
- pObj = RetSelect();
- if ( pObj == 0 ) return false;
-
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FRAGT, pObj);
-
- pObj->SetSelect(false); // deselects the object
- m_camera->SetType(CAMERA_EXPLO);
- DeselectAll();
- pObj->DeleteDeselList(pObj);
-
- return true;
-}
-
-
-// Removes setting evidence of the object with the mouse hovers over.
-
-void CRobotMain::HiliteClear()
-{
- CObject* pObj;
- int i;
-
- ClearTooltip();
- m_tooltipName[0] = 0; // really removes the tooltip
-
- if ( !m_bHilite ) return;
-
- i = -1;
- m_engine->SetHiliteRank(&i); // nothing more selected
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- pObj->SetHilite(false);
- m_map->SetHilite(0);
- m_short->SetHilite(0);
- }
-
- m_bHilite = false;
-}
-
-// Highlights the object with the mouse hovers over.
-
-void CRobotMain::HiliteObject(Math::Point pos)
-{
- CObject* pObj;
- char name[100];
- bool bInMap;
-
- if ( m_bFixScene && m_phase != PHASE_PERSO ) return;
- if ( m_bMovieLock ) return;
- if ( m_movie->IsExist() ) return;
- if ( m_engine->RetMouseHide() ) return;
-
- ClearInterface(); // removes setting evidence and tooltip
-
- pObj = m_short->DetectShort(pos);
-
- if ( m_dialog->RetTooltip() && m_interface->GetTooltip(pos, name) )
- {
- m_tooltipPos = pos;
- strcpy(m_tooltipName, name);
- m_tooltipTime = 0.0f;
- if ( pObj == 0 ) return;
- }
-
- if ( m_bSuspend ) return;
-
- if ( pObj == 0 )
- {
- pObj = m_map->DetectMap(pos, bInMap);
- if ( pObj == 0 )
- {
- if ( bInMap ) return;
-
- pObj = DetectObject(pos);
-
- if ( m_camera->RetType() == CAMERA_ONBOARD &&
- m_camera->RetObject() == pObj )
- {
- return;
- }
- }
- }
-
- if ( pObj != 0 )
- {
- if ( m_dialog->RetTooltip() && pObj->GetTooltipName(name) )
- {
- m_tooltipPos = pos;
- strcpy(m_tooltipName, name);
- m_tooltipTime = 0.0f;
- }
-
- if ( IsSelectable(pObj) )
- {
- pObj->SetHilite(true);
- m_map->SetHilite(pObj);
- m_short->SetHilite(pObj);
- m_bHilite = true;
- }
- }
-}
-
-// Highlights the object with the mouse hovers over.
-
-void CRobotMain::HiliteFrame(float rTime)
-{
- if ( m_bFixScene && m_phase != PHASE_PERSO ) return;
- if ( m_bMovieLock ) return;
- if ( m_movie->IsExist() ) return;
-
- m_tooltipTime += rTime;
-
- ClearTooltip();
-
- if ( m_tooltipTime >= 0.2f &&
- m_tooltipName[0] != 0 )
- {
- CreateTooltip(m_tooltipPos, m_tooltipName);
- }
-}
-
-// Creates a tooltip.
-
-void CRobotMain::CreateTooltip(Math::Point pos, char* text)
-{
- CWindow* pw;
- Math::Point start, end, dim, offset, corner;
-
- corner.x = pos.x+0.022f;
- corner.y = pos.y-0.052f;
-
- m_engine->RetText()->DimText(text, corner, 1,
- SMALLFONT, NORMSTRETCH, FONT_COLOBOT,
- start, end);
- start.x -= 0.010f;
- start.y -= 0.002f;
- end.x += 0.010f;
- end.y += 0.004f; // ch'tite (?) margin
-
- pos.x = start.x;
- pos.y = start.y;
- dim.x = end.x-start.x;
- dim.y = end.y-start.y;
-
- offset.x = 0.0f;
- offset.y = 0.0f;
- if ( pos.x+dim.x > 1.0f ) offset.x = 1.0f-(pos.x+dim.x);
- if ( pos.y < 0.0f ) offset.y = -pos.y;
-
- corner.x += offset.x;
- corner.y += offset.y;
- pos.x += offset.x;
- pos.y += offset.y;
-
- m_interface->CreateWindows(pos, dim, 1, EVENT_TOOLTIP);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_TOOLTIP);
- if ( pw != 0 )
- {
- pw->SetState(STATE_SHADOW);
- pw->SetTrashEvent(false);
-
- pos.y -= m_engine->RetText()->RetHeight(SMALLFONT, FONT_COLOBOT)/2.0f;
- pw->CreateLabel(pos, dim, -1, EVENT_LABEL2, text);
- }
-}
-
-// Clears the previous tooltip.
-
-void CRobotMain::ClearTooltip()
-{
- m_interface->DeleteControl(EVENT_TOOLTIP);
-}
-
-
-// Displays help for an object.
-
-void CRobotMain::HelpObject()
-{
- CObject* pObj;
- char* filename;
-
- pObj = RetSelect();
- if ( pObj == 0 ) return;
-
- filename = RetHelpFilename(pObj->RetType());
- if ( filename[0] == 0 ) return;
-
- StartDisplayInfo(filename, -1);
-}
-
-
-// Change the mode of the camera.
-
-void CRobotMain::ChangeCamera()
-{
- CObject* pObj;
- ObjectType oType;
- CameraType type;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetSelect() )
- {
- if ( pObj->RetCameraLock() ) return;
-
- oType = pObj->RetType();
- type = pObj->RetCameraType();
-
- if ( 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_APOLLO2 ) return;
-
- if ( oType == OBJECT_MOBILEdr ) // designer?
- {
- if ( type == CAMERA_PLANE ) type = CAMERA_BACK;
- else if ( type == CAMERA_BACK ) type = CAMERA_PLANE;
- }
- else if ( pObj->RetTrainer() ) // trainer?
- {
- if ( type == CAMERA_ONBOARD ) type = CAMERA_FIX;
- else if ( type == CAMERA_FIX ) type = CAMERA_PLANE;
- else if ( type == CAMERA_PLANE ) type = CAMERA_BACK;
- else if ( type == CAMERA_BACK ) type = CAMERA_ONBOARD;
- }
- else
- {
- if ( type == CAMERA_ONBOARD ) type = CAMERA_BACK;
- else if ( type == CAMERA_BACK ) type = CAMERA_ONBOARD;
- }
-
- pObj->SetCameraType(type);
- m_camera->SetType(type);
- }
- }
-}
-
-// Remote control the camera using the arrow keys.
-
-void CRobotMain::KeyCamera(EventMsg event, long param)
-{
- CObject* pObj;
-
- if ( event == EVENT_KEYUP )
- {
- if ( param == m_engine->RetKey(KEYRANK_LEFT, 0) ||
- param == m_engine->RetKey(KEYRANK_LEFT, 1) )
- {
- m_cameraPan = 0.0f;
- }
-
- if ( param == m_engine->RetKey(KEYRANK_RIGHT, 0) ||
- param == m_engine->RetKey(KEYRANK_RIGHT, 1) )
- {
- m_cameraPan = 0.0f;
- }
-
- if ( param == m_engine->RetKey(KEYRANK_UP, 0) ||
- param == m_engine->RetKey(KEYRANK_UP, 1) )
- {
- m_cameraZoom = 0.0f;
- }
-
- if ( param == m_engine->RetKey(KEYRANK_DOWN, 0) ||
- param == m_engine->RetKey(KEYRANK_DOWN, 1) )
- {
- m_cameraZoom = 0.0f;
- }
- }
-
- if ( m_phase != PHASE_SIMUL ) return;
- if ( m_bEditLock ) return; // current edition?
- if ( m_bTrainerPilot ) return;
-
- pObj = RetSelect();
- if ( pObj == 0 ) return;
- if ( !pObj->RetTrainer() ) return;
-
- if ( event == EVENT_KEYDOWN )
- {
- if ( param == m_engine->RetKey(KEYRANK_LEFT, 0) ||
- param == m_engine->RetKey(KEYRANK_LEFT, 1) )
- {
- m_cameraPan = -1.0f;
- }
-
- if ( param == m_engine->RetKey(KEYRANK_RIGHT, 0) ||
- param == m_engine->RetKey(KEYRANK_RIGHT, 1) )
- {
- m_cameraPan = 1.0f;
- }
-
- if ( param == m_engine->RetKey(KEYRANK_UP, 0) ||
- param == m_engine->RetKey(KEYRANK_UP, 1) )
- {
- m_cameraZoom = -1.0f;
- }
-
- if ( param == m_engine->RetKey(KEYRANK_DOWN, 0) ||
- param == m_engine->RetKey(KEYRANK_DOWN, 1) )
- {
- m_cameraZoom = 1.0f;
- }
- }
-}
-
-// Panned with the camera if a button is pressed.
-
-void CRobotMain::RemoteCamera(float pan, float zoom, float rTime)
-{
- float value;
-
- if ( pan != 0.0f )
- {
- value = m_camera->RetRemotePan();
- value += pan*rTime*1.5f;
- m_camera->SetRemotePan(value);
- }
-
- if ( zoom != 0.0f )
- {
- value = m_camera->RetRemoteZoom();
- value += zoom*rTime*0.3f;
- m_camera->SetRemoteZoom(value);
- }
-}
-
-
-
-// Cancels the current movie.
-
-void CRobotMain::AbortMovie()
-{
- CObject* pObj;
- CAuto* automat;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- automat = pObj->RetAuto();
- if ( automat != 0 )
- {
- automat->Abort();
- }
- }
-
- m_engine->SetMouseHide(false);
-}
-
-
-
-// Updates the text information.
-
-void CRobotMain::UpdateInfoText()
-{
- CObject* pObj;
- Math::Vector pos;
- char info[100];
-
- if ( m_bShowPos )
- {
- pObj = RetSelect();
- if ( pObj != 0 )
- {
- pos = pObj->RetPosition(0);
- sprintf(info, "Pos = %.2f ; %.2f", pos.x/g_unit, pos.z/g_unit);
- m_engine->SetInfoText(4, info);
- }
- }
-}
-
-
-// Initializes the view.
-
-void CRobotMain::InitEye()
-{
- if ( m_phase == PHASE_SIMUL )
- {
- m_camera->Init(Math::Vector( 0.0f, 10.0f, 0.0f),
- Math::Vector(10.0f, 5.0f, 0.0f), 0.0f);
- }
-
- if ( m_phase == PHASE_MODEL )
- {
- m_model->InitView();
- }
-}
-
-// Advances the entire scene.
-
-bool CRobotMain::EventFrame(const Event &event)
-{
- ObjectType type;
- CObject *pObj, *toto;
- CPyro* pPyro;
- CWindow* pw;
- CMap* pm;
- int i;
-
- m_time += event.rTime;
- if ( !m_bMovieLock ) m_gameTime += event.rTime;
-
- if ( !m_bImmediatSatCom && !m_bBeginSatCom &&
- m_gameTime > 0.1f && m_phase == PHASE_SIMUL )
- {
- m_displayText->DisplayError(INFO_BEGINSATCOM, Math::Vector(0.0f,0.0f,0.0f));
- m_bBeginSatCom = true; // message appears
- }
-
- m_water->EventProcess(event);
- m_cloud->EventProcess(event);
- m_blitz->EventProcess(event);
- m_planet->EventProcess(event);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw == 0 )
- {
- pm = 0;
- }
- else
- {
- pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
- if ( pm != 0 ) pm->FlushObject();
- }
-
- toto = 0;
- if ( !m_bFreePhoto )
- {
- // Advances all the robots, but not toto.
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
- if ( pm != 0 ) pm->UpdateObject(pObj);
- if ( pObj->RetTruck() != 0 ) continue;
- type = pObj->RetType();
- if ( type == OBJECT_TOTO )
- {
- toto = pObj;
- }
- else
- {
- pObj->EventProcess(event);
- }
- }
- // Advances all objects transported by robots.
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
- if ( pObj->RetTruck() == 0 ) continue;
- pObj->EventProcess(event);
- }
-
- // Advances pyrotechnic effects.
- for ( i=0 ; i<1000000 ; i++ )
- {
- pPyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, i);
- if ( pPyro == 0 ) break;
-
- pPyro->EventProcess(event);
- if ( pPyro->IsEnded() != ERR_CONTINUE )
- {
- pPyro->DeleteObject();
- delete pPyro;
- }
- }
- }
-
- // The camera follows the object, because its position
- // may depend on the selected object (CAMERA_ONBOARD or CAMERA_BACK).
- if ( m_phase == PHASE_SIMUL && !m_bEditFull )
- {
- m_camera->EventProcess(event);
-
- if ( m_engine->RetFog() )
- {
- m_camera->SetOverBaseColor(m_particule->RetFogColor(m_engine->RetEyePt()));
- }
- }
- if ( m_phase == PHASE_PERSO ||
- m_phase == PHASE_WIN ||
- m_phase == PHASE_LOST )
- {
- m_camera->EventProcess(event);
- }
-
- // Advances toto following the camera, because its position depends on the camera.
- if ( toto != 0 )
- {
- toto->EventProcess(event);
- }
-
- // Advances model.
- if ( m_phase == PHASE_MODEL )
- {
- m_model->ViewMove(event, 2.0f);
- m_model->UpdateView();
- m_model->EventProcess(event);
- }
-
- HiliteFrame(event.rTime);
-
- // Moves the film indicator.
- if ( m_bMovieLock && !m_bEditLock ) // movie in progress?
- {
- CControl* pc;
- Math::Point pos, dim;
- float zoom;
-
- pc = m_interface->SearchControl(EVENT_OBJECT_MOVIELOCK);
- if ( pc != 0 )
- {
- dim.x = 32.0f/640.0f;
- dim.y = 32.0f/480.0f;
- pos.x = 20.0f/640.0f;
- pos.y = (480.0f-24.0f)/480.0f;
-
- zoom = 1.0f+sinf(m_time*6.0f)*0.1f; // 0.9 .. 1.1
- dim.x *= zoom;
- dim.y *= zoom;
- pos.x -= dim.x/2.0f;
- pos.y -= dim.y/2.0f;
-
- pc->SetPos(pos);
- pc->SetDim(dim);
- }
- }
-
- // Moves edition indicator.
- if ( m_bEditLock || m_bPause ) // edition in progress?
- {
- CControl* pc;
- Math::Point pos, dim;
- float zoom;
-
- pc = m_interface->SearchControl(EVENT_OBJECT_EDITLOCK);
- if ( pc != 0 )
- {
- if ( m_bEditFull || m_bEditLock )
- {
- dim.x = 10.0f/640.0f;
- dim.y = 10.0f/480.0f;
- pos.x = -20.0f/640.0f;
- pos.y = -20.0f/480.0f; // invisible!
- }
- else
- {
- dim.x = 32.0f/640.0f;
- dim.y = 32.0f/480.0f;
- pos.x = 20.0f/640.0f;
- pos.y = (480.0f-24.0f)/480.0f;
-
- zoom = 1.0f+sinf(m_time*6.0f)*0.1f; // 0.9 .. 1.1
- dim.x *= zoom;
- dim.y *= zoom;
- pos.x -= dim.x/2.0f;
- pos.y -= dim.y/2.0f;
- }
- pc->SetPos(pos);
- pc->SetDim(dim);
- }
- }
-
- // Will move the arrow to visit.
- if ( m_camera->RetType() == CAMERA_VISIT )
- {
- FrameVisit(event.rTime);
- }
-
- // Moves the boundaries.
- FrameShowLimit(event.rTime);
-
- if ( m_phase == PHASE_SIMUL )
- {
- if ( !m_bEditLock && m_checkEndTime+1.0f < m_time )
- {
- m_checkEndTime = m_time;
- CheckEndMission(true);
- }
-
- if ( m_winDelay > 0.0f && !m_bEditLock )
- {
- m_winDelay -= event.rTime;
- if ( m_winDelay <= 0.0f )
- {
- if ( m_bMovieLock )
- {
- m_winDelay = 1.0f;
- }
- else
- {
- Event newEvent;
- m_event->MakeEvent(newEvent, EVENT_WIN);
- m_event->AddEvent(newEvent);
- }
- }
- }
-
- if ( m_lostDelay > 0.0f && !m_bEditLock )
- {
- m_lostDelay -= event.rTime;
- if ( m_lostDelay <= 0.0f )
- {
- if ( m_bMovieLock )
- {
- m_winDelay = 1.0f;
- }
- else
- {
- Event newEvent;
- m_event->MakeEvent(newEvent, EVENT_LOST);
- m_event->AddEvent(newEvent);
- }
- }
- }
- }
-
- if ( m_delayWriteMessage > 0 )
- {
- m_delayWriteMessage --;
- if ( m_delayWriteMessage == 0 )
- {
- m_displayText->DisplayError(INFO_WRITEOK, Math::Vector(0.0f,0.0f,0.0f));
- }
- }
-
- return S_OK;
-}
-
-// Makes the event for all robots.
-
-bool CRobotMain::EventObject(const Event &event)
-{
- CObject* pObj;
- int i;
-
- if ( m_bFreePhoto ) return S_OK;
-
- m_bResetCreate = false;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- pObj->EventProcess(event);
- }
-
- if ( m_bResetCreate )
- {
- ResetCreate();
- }
-
- return S_OK;
-}
-
-
-// Calculates the point of arrival of the camera.
-
-Math::Vector CRobotMain::LookatPoint(Math::Vector eye, float angleH, float angleV,
- float length)
-{
- Math::Vector lookat;
-
- lookat = eye;
- lookat.z += length;
-
- RotatePoint(eye, angleH, angleV, lookat);
- return lookat;
-}
-
-
-
-char* SkipNum(char *p)
-{
- while ( *p == ' ' || *p == '.' || *p == '-' || (*p >= '0' && *p <= '9') )
- {
- p++;
- }
- return p;
-}
-
-// Conversion of units.
-
-void CRobotMain::Convert()
-{
- FILE* file = NULL;
- FILE* fileNew = NULL;
- char line[500];
- char lineNew[500];
- char s[200];
- char* base;
- char* p;
- int rank;
- Math::Vector pos;
- float value;
-
- base = m_dialog->RetSceneName();
- rank = m_dialog->RetSceneRank();
-
- m_dialog->BuildSceneName(line, base, rank);
- file = fopen(line, "r");
- if ( file == NULL ) return;
-
- strcpy(line+strlen(line)-4, ".new");
- fileNew = fopen(line, "w");
- if ( fileNew == NULL ) return;
-
- while ( fgets(line, 500, file) != NULL )
- {
- strcpy(lineNew, line);
-
- if ( Cmd(line, "DeepView") )
- {
- p = strstr(line, "air=");
- if ( p != 0 )
- {
- value = OpFloat(line, "air", 500.0f);
- value /= g_unit;
- p[0] = 0;
- p = SkipNum(p+4);
- strcpy(lineNew, line);
- strcat(lineNew, "air=");
- sprintf(s, "%.2f", value);
- strcat(lineNew, s);
- strcat(lineNew, " ");
- strcat(lineNew, p);
- }
- strcpy(line, lineNew);
-
- p = strstr(line, "water=");
- if ( p != 0 )
- {
- value = OpFloat(line, "water", 100.0f);
- value /= g_unit;
- p[0] = 0;
- p = SkipNum(p+6);
- strcpy(lineNew, line);
- strcat(lineNew, "water=");
- sprintf(s, "%.2f", value);
- strcat(lineNew, s);
- strcat(lineNew, " ");
- strcat(lineNew, p);
- }
- strcpy(line, lineNew);
- }
-
- if ( Cmd(line, "TerrainGenerate") )
- {
- p = strstr(line, "vision=");
- if ( p != 0 )
- {
- value = OpFloat(line, "vision", 500.0f);
- value /= g_unit;
- p[0] = 0;
- p = SkipNum(p+7);
- strcpy(lineNew, line);
- strcat(lineNew, "vision=");
- sprintf(s, "%.2f", value);
- strcat(lineNew, s);
- strcat(lineNew, " ");
- strcat(lineNew, p);
- }
- }
-
- if ( Cmd(line, "CreateObject") ||
- Cmd(line, "CreateSpot") )
- {
- p = strstr(line, "pos=");
- if ( p != 0 )
- {
- pos = OpPos(line, "pos");
- pos.x /= g_unit;
- pos.y /= g_unit;
- pos.z /= g_unit;
- p[0] = 0;
- p = SkipNum(p+4);
- p = SkipNum(p+1);
- strcpy(lineNew, line);
- strcat(lineNew, "pos=");
- sprintf(s, "%.2f", pos.x);
- strcat(lineNew, s);
- strcat(lineNew, ";");
- sprintf(s, "%.2f", pos.z);
- strcat(lineNew, s);
- strcat(lineNew, " ");
- strcat(lineNew, p);
- }
- }
-
- if ( Cmd(line, "EndMissionTake") )
- {
- p = strstr(line, "pos=");
- if ( p != 0 )
- {
- pos = OpPos(line, "pos");
- pos.x /= g_unit;
- pos.y /= g_unit;
- pos.z /= g_unit;
- p[0] = 0;
- p = SkipNum(p+4);
- p = SkipNum(p+1);
- strcpy(lineNew, line);
- strcat(lineNew, "pos=");
- sprintf(s, "%.2f", pos.x);
- strcat(lineNew, s);
- strcat(lineNew, ";");
- sprintf(s, "%.2f", pos.z);
- strcat(lineNew, s);
- strcat(lineNew, " ");
- strcat(lineNew, p);
- }
- strcpy(line, lineNew);
-
- p = strstr(line, "dist=");
- if ( p != 0 )
- {
- value = OpFloat(line, "dist", 32.0f);
- value /= g_unit;
- p[0] = 0;
- p = SkipNum(p+5);
- strcpy(lineNew, line);
- strcat(lineNew, "dist=");
- sprintf(s, "%.2f", value);
- strcat(lineNew, s);
- strcat(lineNew, " ");
- strcat(lineNew, p);
- }
- strcpy(line, lineNew);
- }
-
- if ( Cmd(line, "Camera") )
- {
- p = strstr(line, "pos=");
- if ( p != 0 )
- {
- pos = OpPos(line, "pos");
- pos.x /= g_unit;
- pos.y /= g_unit;
- pos.z /= g_unit;
- p[0] = 0;
- p = SkipNum(p+4);
- p = SkipNum(p+1);
- strcpy(lineNew, line);
- strcat(lineNew, "pos=");
- sprintf(s, "%.2f", pos.x);
- strcat(lineNew, s);
- strcat(lineNew, ";");
- sprintf(s, "%.2f", pos.z);
- strcat(lineNew, s);
- strcat(lineNew, " ");
- strcat(lineNew, p);
- }
- strcpy(line, lineNew);
-
- p = strstr(line, "h=");
- if ( p != 0 )
- {
- value = OpFloat(line, "h", 32.0f);
- value /= g_unit;
- p[0] = 0;
- p = SkipNum(p+2);
- strcpy(lineNew, line);
- strcat(lineNew, "h=");
- sprintf(s, "%.2f", value);
- strcat(lineNew, s);
- strcat(lineNew, " ");
- strcat(lineNew, p);
- }
- strcpy(line, lineNew);
- }
-
- fputs(lineNew, fileNew);
- }
-
- fclose(fileNew);
- fclose(file);
-}
-
-// Load the scene for the character.
-
-void CRobotMain::ScenePerso()
-{
- CObject* pObj;
-
- DeleteAllObjects(); // removes all the current 3D Scene
- m_engine->FlushObject();
- m_terrain->FlushRelief(); // all flat
- m_terrain->FlushBuildingLevel();
- m_terrain->FlushFlyingLimit();
- m_light->FlushLight();
- m_particule->FlushParticule();
- m_iMan->Flush(CLASS_OBJECT);
- m_iMan->Flush(CLASS_PHYSICS);
- m_iMan->Flush(CLASS_BRAIN);
- m_iMan->Flush(CLASS_PYRO);
-
- m_dialog->SetSceneName("perso");
- m_dialog->SetSceneRank(0);
- CreateScene(false, true, false); // sets scene
-
- m_engine->SetDrawWorld(false); // does not draw anything on the interface
- m_engine->SetDrawFront(true); // draws on the human interface
- pObj = SearchHuman();
- if ( pObj != 0 )
- {
- CMotionHuman* mh;
-
- pObj->SetDrawFront(true); // draws the interface
-
- mh = (CMotionHuman*)pObj->RetMotion();
- if ( mh != 0 )
- {
- mh->StartDisplayPerso();
- }
- }
-}
-
-// Creates the whole stage.
-
-void CRobotMain::CreateScene(bool bSoluce, bool bFixScene, bool bResetObject)
-{
- CObject* pObj;
- CObject* pSel;
- CMotion* motion;
- FILE* file = NULL;
- char line[500];
- char name[200];
- char dir[100];
- char op[100];
- char* read;
- char* stack;
- char* base;
- D3DCOLORVALUE color;
- Math::Vector pos;
- int rank, obj, i, rankObj, rankGadget;
-
-//? Convert();
-
- base = m_dialog->RetSceneName();
- rank = m_dialog->RetSceneRank();
- read = m_dialog->RetSceneRead();
- stack = m_dialog->RetStackRead();
- m_dialog->SetUserDir(base, rank);
-
- m_bFixScene = bFixScene;
-
- g_id = 0;
- m_bBase = false;
-
- if ( !bResetObject )
- {
- g_build = 0;
- g_researchDone = 0; // no research done
- g_researchEnable = 0;
-
- FlushDisplayInfo();
- m_terrain->LevelFlush();
- m_audioTrack = 0;
- m_bAudioRepeat = true;
- m_displayText->SetDelay(1.0f);
- m_displayText->SetEnable(true);
- m_bImmediatSatCom = false;
- m_endingWinRank = 0;
- m_endingLostRank = 0;
- m_endTakeTotal = 0;
- m_endTakeResearch = 0;
- m_endTakeWinDelay = 2.0f;
- m_endTakeLostDelay = 2.0f;
- m_obligatoryTotal = 0;
- m_prohibitedTotal = 0;
- m_bMapShow = true;
- m_bMapImage = false;
- m_mapFilename[0] = 0;
-
- m_colorRefBot.r = 10.0f/256.0f;
- m_colorRefBot.g = 166.0f/256.0f;
- m_colorRefBot.b = 254.0f/256.0f; // blue
- m_colorRefBot.a = 0.0f;
- m_colorNewBot = m_colorRefBot;
-
- m_colorRefAlien.r = 135.0f/256.0f;
- m_colorRefAlien.g = 170.0f/256.0f;
- m_colorRefAlien.b = 13.0f/256.0f; // green
- m_colorRefAlien.a = 0.0f;
- m_colorNewAlien = m_colorRefAlien;
-
- m_colorRefGreen.r = 135.0f/256.0f;
- m_colorRefGreen.g = 170.0f/256.0f;
- m_colorRefGreen.b = 13.0f/256.0f; // green
- m_colorRefGreen.a = 0.0f;
- m_colorNewGreen = m_colorRefGreen;
-
- m_colorRefWater.r = 25.0f/256.0f;
- m_colorRefWater.g = 255.0f/256.0f;
- m_colorRefWater.b = 240.0f/256.0f; // cyan
- m_colorRefWater.a = 0.0f;
- m_colorNewWater = m_colorRefWater;
-
- m_dialog->BuildResumeName(m_title, base, rank);
- m_dialog->BuildResumeName(m_resume, base, rank);
- GetResource(RES_TEXT, RT_SCRIPT_NEW, m_scriptName);
- m_scriptFile[0] = 0;
- }
-
- m_dialog->BuildSceneName(line, base, rank);
- file = fopen(line, "r");
- if ( file == NULL ) return;
-
- rankObj = 0;
- rankGadget = 0;
- pSel = 0;
-
- while ( fgets(line, 500, file) != NULL )
- {
- for ( i=0 ; i<500 ; i++ )
- {
- if ( line[i] == '\t' ) line[i] = ' '; // replace tab by space
- if ( line[i] == '/' && line[i+1] == '/' )
- {
- line[i] = 0;
- break;
- }
- }
-
- sprintf(op, "Title.%c", RetLanguageLetter());
- if ( Cmd(line, op) && !bResetObject )
- {
- OpString(line, "text", m_title);
- }
-
- sprintf(op, "Resume.%c", RetLanguageLetter());
- if ( Cmd(line, op) && !bResetObject )
- {
- OpString(line, "text", m_resume);
- }
-
- sprintf(op, "ScriptName.%c", RetLanguageLetter());
- if ( Cmd(line, op) && !bResetObject )
- {
- OpString(line, "text", m_scriptName);
- }
-
- if ( Cmd(line, "ScriptFile") && !bResetObject )
- {
- OpString(line, "name", m_scriptFile);
- }
-
- if ( Cmd(line, "Instructions") && !bResetObject )
- {
- OpString(line, "name", name);
-//? sprintf(m_infoFilename[SATCOM_HUSTON], "help\\%s", name);
- UserDir(m_infoFilename[SATCOM_HUSTON], name, "help");
-
- m_bImmediatSatCom = OpInt(line, "immediat", 0);
- }
-
- if ( Cmd(line, "Satellite") && !bResetObject )
- {
- OpString(line, "name", name);
-//? sprintf(m_infoFilename[SATCOM_SAT], "help\\%s", name);
- UserDir(m_infoFilename[SATCOM_SAT], name, "help");
- }
-
- if ( Cmd(line, "Loading") && !bResetObject )
- {
- OpString(line, "name", name);
-//? sprintf(m_infoFilename[SATCOM_LOADING], "help\\%s", name);
- UserDir(m_infoFilename[SATCOM_LOADING], name, "help");
- }
-
- if ( Cmd(line, "HelpFile") && !bResetObject )
- {
- OpString(line, "name", name);
-//? sprintf(m_infoFilename[SATCOM_PROG], "help\\%s", name);
- UserDir(m_infoFilename[SATCOM_PROG], name, "help");
- }
- if ( Cmd(line, "SoluceFile") && !bResetObject )
- {
- OpString(line, "name", name);
-//? sprintf(m_infoFilename[SATCOM_SOLUCE], "help\\%s", name);
- UserDir(m_infoFilename[SATCOM_SOLUCE], name, "help");
- }
-
- if ( Cmd(line, "EndingFile") && !bResetObject )
- {
- m_endingWinRank = OpInt(line, "win", 0);
- m_endingLostRank = OpInt(line, "lost", 0);
- }
-
- if ( Cmd(line, "MessageDelay") && !bResetObject )
- {
- m_displayText->SetDelay(OpFloat(line, "factor", 1.0f));
- }
-
- if ( Cmd(line, "Audio") && !bResetObject )
- {
- m_audioTrack = OpInt(line, "track", 0);
- m_bAudioRepeat = OpInt(line, "repeat", 1);
- }
-
- if ( Cmd(line, "AmbiantColor") && !bResetObject )
- {
- m_engine->SetAmbiantColor(OpColor(line, "air", 0x88888888), 0);
- m_engine->SetAmbiantColor(OpColor(line, "water", 0x88888888), 1);
- }
-
- if ( Cmd(line, "FogColor") && !bResetObject )
- {
- m_engine->SetFogColor(OpColor(line, "air", 0x88888888), 0);
- m_engine->SetFogColor(OpColor(line, "water", 0x88888888), 1);
- }
-
- if ( Cmd(line, "VehicleColor") && !bResetObject )
- {
- m_colorNewBot = RetColor(OpColor(line, "color", 0x88888888));
- }
-
- if ( Cmd(line, "InsectColor") && !bResetObject )
- {
- m_colorNewAlien = RetColor(OpColor(line, "color", 0x88888888));
- }
-
- if ( Cmd(line, "GreeneryColor") && !bResetObject )
- {
- m_colorNewGreen = RetColor(OpColor(line, "color", 0x88888888));
- }
-
- if ( Cmd(line, "DeepView") && !bResetObject )
- {
- m_engine->SetDeepView(OpFloat(line, "air", 500.0f)*UNIT, 0, true);
- m_engine->SetDeepView(OpFloat(line, "water", 100.0f)*UNIT, 1, true);
- }
-
- if ( Cmd(line, "FogStart") && !bResetObject )
- {
- m_engine->SetFogStart(OpFloat(line, "air", 0.5f), 0);
- m_engine->SetFogStart(OpFloat(line, "water", 0.5f), 1);
- }
-
- if ( Cmd(line, "SecondTexture") && !bResetObject )
- {
- m_engine->SetSecondTexture(OpInt(line, "rank", 1));
- }
-
- if ( Cmd(line, "Background") && !bResetObject )
- {
- OpString(line, "image", name);
- UserDir(dir, name, "");
- m_engine->SetBackground(dir,
- OpColor(line, "up", 0x00000000),
- OpColor(line, "down", 0x00000000),
- OpColor(line, "cloudUp", 0x00000000),
- OpColor(line, "cloudDown", 0x00000000),
- OpInt(line, "full", 0));
- }
-
- if ( Cmd(line, "Planet") && !bResetObject )
- {
- Math::Vector ppos, uv1, uv2;
-
- ppos = OpPos(line, "pos");
- uv1 = OpPos(line, "uv1");
- uv2 = OpPos(line, "uv2");
- OpString(line, "image", name);
- UserDir(dir, name, "");
- m_planet->Create(OpInt(line, "mode", 0),
- Math::Point(ppos.x, ppos.z),
- OpFloat(line, "dim", 0.2f),
- OpFloat(line, "speed", 0.0f),
- OpFloat(line, "dir", 0.0f),
- dir,
- Math::Point(uv1.x, uv1.z),
- Math::Point(uv2.x, uv2.z));
- }
-
- if ( Cmd(line, "FrontsizeName") && !bResetObject )
- {
- OpString(line, "image", name);
- UserDir(dir, name, "");
- m_engine->SetFrontsizeName(dir);
- }
-
- if ( Cmd(line, "Global") && !bResetObject )
- {
- g_unit = OpFloat(line, "unitScale", 4.0f);
- m_engine->SetTracePrecision(OpFloat(line, "traceQuality", 1.0f));
- m_bShortCut = OpInt(line, "shortcut", 1);
- }
-
- if ( Cmd(line, "TerrainGenerate") && !bResetObject )
- {
- m_terrain->Generate(OpInt(line, "mosaic", 20),
- OpInt(line, "brick", 3),
- OpFloat(line, "size", 20.0f),
- OpFloat(line, "vision", 500.0f)*UNIT,
- OpInt(line, "depth", 2),
- OpFloat(line, "hard", 0.5f));
- }
-
- if ( Cmd(line, "TerrainWind") && !bResetObject )
- {
- m_terrain->SetWind(OpPos(line, "speed"));
- }
-
- if ( Cmd(line, "TerrainRelief") && !bResetObject )
- {
- OpString(line, "image", name);
- UserDir(dir, name, "textures");
- m_terrain->ReliefFromBMP(dir, OpFloat(line, "factor", 1.0f), OpInt(line, "border", 1));
- }
-
- if ( Cmd(line, "TerrainReliefDXF") && !bResetObject )
- {
- OpString(line, "image", name);
- UserDir(dir, name, "textures");
- m_terrain->ReliefFromDXF(dir, OpFloat(line, "factor", 1.0f));
- }
-
- if ( Cmd(line, "TerrainResource") && !bResetObject )
- {
- OpString(line, "image", name);
- UserDir(dir, name, "textures");
- m_terrain->ResFromBMP(dir);
- }
-
- if ( Cmd(line, "TerrainWater") && !bResetObject )
- {
- OpString(line, "image", name);
- UserDir(dir, name, "");
- pos.x = OpFloat(line, "moveX", 0.0f);
- pos.y = OpFloat(line, "moveY", 0.0f);
- pos.z = pos.x;
- m_water->Create(OpTypeWater(line, "air", WATER_TT),
- OpTypeWater(line, "water", WATER_TT),
- dir,
- RetColor(OpColor(line, "diffuse", 0xffffffff)),
- RetColor(OpColor(line, "ambiant", 0xffffffff)),
- OpFloat(line, "level", 100.0f)*UNIT,
- OpFloat(line, "glint", 1.0f),
- pos);
- m_colorNewWater = RetColor(OpColor(line, "color", RetColor(m_colorRefWater)));
- m_colorShiftWater = OpFloat(line, "brightness", 0.0f);
- }
-
- if ( Cmd(line, "TerrainLava") && !bResetObject )
- {
- m_water->SetLava(OpInt(line, "mode", 0));
- }
-
- if ( Cmd(line, "TerrainCloud") && !bResetObject )
- {
- OpString(line, "image", name);
- UserDir(dir, name, "");
- m_cloud->Create(dir,
- RetColor(OpColor(line, "diffuse", 0xffffffff)),
- RetColor(OpColor(line, "ambiant", 0xffffffff)),
- OpFloat(line, "level", 500.0f)*UNIT);
- }
-
- if ( Cmd(line, "TerrainBlitz") && !bResetObject )
- {
- m_blitz->Create(OpFloat(line, "sleep", 0.0f),
- OpFloat(line, "delay", 3.0f),
- OpFloat(line, "magnetic", 50.0f)*UNIT);
- }
-
- if ( Cmd(line, "TerrainInitTextures") && !bResetObject )
- {
- int dx, dy, tt[100];
- char* op;
-
- OpString(line, "image", name);
- AddExt(name, ".tga");
- dx = OpInt(line, "dx", 1);
- dy = OpInt(line, "dy", 1);
- op = SearchOp(line, "table");
- for ( i=0 ; i<dx*dy ; i++ )
- {
- tt[i] = GetInt(op, i, 0);
- }
-
- if ( strstr(name, "%user%") != 0 )
- {
- CopyFileListToTemp(name, tt, dx*dy);
- }
-
- m_terrain->InitTextures(name, tt, dx, dy);
- }
-
- if ( Cmd(line, "TerrainInit") && !bResetObject )
- {
- m_terrain->LevelInit(OpInt(line, "id", 1));
- }
-
- if ( Cmd(line, "TerrainMaterial") && !bResetObject )
- {
- OpString(line, "image", name);
- AddExt(name, ".tga");
- if ( strstr(name, "%user%") != 0 )
- {
- CopyFileToTemp(name);
- }
-
- m_terrain->LevelMaterial(OpInt(line, "id", 0),
- name,
- OpFloat(line, "u", 0.0f),
- OpFloat(line, "v", 0.0f),
- OpInt(line, "up", 1),
- OpInt(line, "right", 1),
- OpInt(line, "down", 1),
- OpInt(line, "left", 1),
- OpFloat(line, "hard", 0.5f));
- }
-
- if ( Cmd(line, "TerrainLevel") && !bResetObject )
- {
- int id[50];
- char* op;
-
- op = SearchOp(line, "id");
- i = 0;
- while ( true )
- {
- id[i] = GetInt(op, i, 0);
- if ( id[i++] == 0 ) break;
- }
-
- m_terrain->LevelGenerate(id,
- OpFloat(line, "min", 0.0f)*UNIT,
- OpFloat(line, "max", 100.0f)*UNIT,
- OpFloat(line, "slope", 5.0f),
- OpFloat(line, "freq", 100.0f),
- OpPos(line, "center")*g_unit,
- OpFloat(line, "radius", 0.0f)*g_unit);
- }
-
- if ( Cmd(line, "TerrainCreate") && !bResetObject )
- {
- m_terrain->CreateObjects(true);
- }
-
- if ( Cmd(line, "BeginObject") )
- {
- InitEye();
- SetMovieLock(false);
- if ( !m_bFixScene )
- {
-//? CreateObject(Math::Vector(0.0f, 0.0f, 0.0f), 0.0f, 0.0f, OBJECT_TOTO);
- }
-
- if ( read[0] != 0 ) // loading file ?
- {
- pSel = IOReadScene(read, stack);
- }
- }
-
- if ( Cmd(line, "CreateObject") && read[0] == 0 )
- {
- CObject* pObj;
- CBrain* pBrain;
- CAuto* pAuto;
- CPyro* pyro;
- ObjectType type;
- PyroType pType;
- CameraType cType;
- Info info;
- float dir;
- char op[20];
- char text[100];
- char* p;
- int run, gadget;
-
- type = OpTypeObject(line, "type", OBJECT_NULL);
-
- gadget = OpInt(line, "gadget", -1);
- if ( gadget == -1 )
- {
- gadget = 0;
- if ( type == OBJECT_TECH ||
- (type >= OBJECT_PLANT0 &&
- type <= OBJECT_PLANT19 ) ||
- (type >= OBJECT_TREE0 &&
- type <= OBJECT_TREE9 ) ||
- (type >= OBJECT_TEEN0 &&
- type <= OBJECT_TEEN49 ) ||
- (type >= OBJECT_QUARTZ0 &&
- type <= OBJECT_QUARTZ9 ) ||
- (type >= OBJECT_ROOT0 &&
- type <= OBJECT_ROOT4 ) ) // not ROOT5!
- {
- if ( type != OBJECT_TEEN11 && // lamp?
- type != OBJECT_TEEN12 && // coke?
- type != OBJECT_TEEN20 && // wall?
- type != OBJECT_TEEN21 && // wall?
- type != OBJECT_TEEN22 && // wall?
- type != OBJECT_TEEN26 && // lamp?
- type != OBJECT_TEEN28 && // bottle?
- type != OBJECT_TEEN34 ) // stone?
- {
- gadget = 1;
- }
- }
- }
- if ( gadget != 0 ) // is this a gadget?
- {
- if ( !TestGadgetQuantity(rankGadget++) ) continue;
- }
-
- pos = OpPos(line, "pos")*g_unit;
- dir = OpFloat(line, "dir", 0.0f)*Math::PI;
- pObj = CreateObject(pos, dir,
- OpFloat(line, "z", 1.0f),
- OpFloat(line, "h", 0.0f),
- type,
- OpFloat(line, "power", 1.0f),
- OpInt(line, "trainer", 0),
- OpInt(line, "toy", 0),
- OpInt(line, "option", 0));
-
- if ( pObj != 0 )
- {
- pObj->SetDefRank(rankObj);
-
- if ( type == OBJECT_BASE ) m_bBase = true;
-
- cType = OpCamera(line, "camera");
- if ( cType != CAMERA_NULL )
- {
- pObj->SetCameraType(cType);
- }
- pObj->SetCameraDist(OpFloat(line, "cameraDist", 50.0f));
- pObj->SetCameraLock(OpInt(line, "cameraLock", 0));
-
- pType = OpPyro(line, "pyro");
- if ( pType != PT_NULL )
- {
- pyro = new CPyro(m_iMan);
- pyro->Create(pType, pObj);
- }
-
- // Puts information in terminal (OBJECT_INFO).
- for ( i=0 ; i<OBJECTMAXINFO ; i++ )
- {
- sprintf(op, "info%d", i+1);
- OpString(line, op, text);
- if ( text[0] == 0 ) break;
- p = strchr(text, '=');
- if ( p == 0 ) break;
- *p = 0;
- strcpy(info.name, text);
- sscanf(p+1, "%f", &info.value);
- pObj->SetInfo(i, info);
- }
-
- // Sets the parameters of the command line.
- p = SearchOp(line, "cmdline");
- for ( i=0 ; i<OBJECTMAXCMDLINE ; i++ )
- {
- float value;
- value = GetFloat(p, i, NAN);
- if ( value == NAN ) break;
- pObj->SetCmdLine(i, value);
- }
-
- if ( OpInt(line, "select", 0) == 1 )
- {
- pSel = pObj;
- }
-
- pObj->SetSelectable(OpInt(line, "selectable", 1));
- pObj->SetEnable(OpInt(line, "enable", 1));
- pObj->SetProxyActivate(OpInt(line, "proxyActivate", 0));
- pObj->SetProxyDistance(OpFloat(line, "proxyDistance", 15.0f)*g_unit);
- pObj->SetRange(OpFloat(line, "range", 30.0f));
- pObj->SetShield(OpFloat(line, "shield", 1.0f));
- pObj->SetMagnifyDamage(OpFloat(line, "magnifyDamage", 1.0f));
- pObj->SetClip(OpInt(line, "clip", 1));
- pObj->SetCheckToken(OpInt(line, "checkToken", 1));
- pObj->SetManual(OpInt(line, "manual", 0));
-
- motion = pObj->RetMotion();
- if ( motion != 0 )
- {
- p = SearchOp(line, "param");
- for ( i=0 ; i<10 ; i++ )
- {
- float value;
- value = GetFloat(p, i, NAN);
- if ( value == NAN ) break;
- motion->SetParam(i, value);
- }
- }
-
- run = -1;
- pBrain = pObj->RetBrain();
- if ( pBrain != 0 )
- {
- for ( i=0 ; i<10 ; i++ )
- {
- sprintf(op, "script%d", i+1); // script1..script10
- OpString(line, op, name);
-#if _SCHOOL
- if ( !m_dialog->RetSoluce4() && i == 3 ) continue;
-#endif
- if ( name[0] != 0 )
- {
- pBrain->SetScriptName(i, name);
- }
- }
-
- i = OpInt(line, "run", 0);
- if ( i != 0 )
- {
- run = i-1;
- pBrain->SetScriptRun(run);
- }
- }
- pAuto = pObj->RetAuto();
- if ( pAuto != 0 )
- {
- type = OpTypeObject(line, "autoType", OBJECT_NULL);
- pAuto->SetType(type);
- for ( i=0 ; i<5 ; i++ )
- {
- sprintf(op, "autoValue%d", i+1); // autoValue1..autoValue5
- pAuto->SetValue(i, OpFloat(line, op, 0.0f));
- }
- OpString(line, "autoString", name);
- pAuto->SetString(name);
-
- i = OpInt(line, "run", -1);
- if ( i != -1 )
- {
- if ( i != PARAM_FIXSCENE &&
- !m_dialog->RetMovies() ) i = 0;
- pAuto->Start(i); // starts the film
- }
- }
-
- OpString(line, "soluce", name);
- if ( bSoluce && pBrain != 0 && name[0] != 0 )
- {
- pBrain->SetSoluceName(name);
- }
-
- pObj->SetResetPosition(pObj->RetPosition(0));
- pObj->SetResetAngle(pObj->RetAngle(0));
- pObj->SetResetRun(run);
-
- if ( OpInt(line, "reset", 0) == 1 )
- {
- pObj->SetResetCap(RESET_MOVE);
- }
- }
-
- rankObj ++;
- }
-
- if ( Cmd(line, "CreateFog") && !bResetObject )
- {
- ParticuleType type;
- Math::Point dim;
- float height, ddim, delay;
-
- type = (ParticuleType)(PARTIFOG0+OpInt(line, "type", 0));
- pos = OpPos(line, "pos")*g_unit;
- height = OpFloat(line, "height", 1.0f)*g_unit;
- ddim = OpFloat(line, "dim", 50.0f)*g_unit;
- delay = OpFloat(line, "delay", 2.0f);
- m_terrain->MoveOnFloor(pos);
- pos.y += height;
- dim.x = ddim;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), dim, type, delay, 0.0f, 0.0f);
- }
-
- if ( Cmd(line, "CreateLight") && !bResetObject )
- {
- D3DTypeObj type;
-
- color.r = 0.5f;
- color.g = 0.5f;
- color.b = 0.5f;
- color.a = 1.0f;
- obj = CreateLight(OpDir(line, "dir"),
- OpColorValue(line, "color", color));
-
- type = OpTypeTerrain(line, "type", TYPENULL);
- if ( type == TYPETERRAIN )
- {
- m_light->SetLightIncluType(obj, TYPETERRAIN);
- }
- if ( type == TYPEQUARTZ )
- {
- m_light->SetLightIncluType(obj, TYPEQUARTZ);
- }
- if ( type == TYPEMETAL )
- {
- m_light->SetLightIncluType(obj, TYPEMETAL);
- }
- if ( type == TYPEFIX )
- {
- m_light->SetLightExcluType(obj, TYPETERRAIN);
- }
- }
- if ( Cmd(line, "CreateSpot") && !bResetObject )
- {
- D3DTypeObj type;
-
- color.r = 0.5f;
- color.g = 0.5f;
- color.b = 0.5f;
- color.a = 1.0f;
- obj = CreateSpot(OpDir(line, "pos")*g_unit,
- OpColorValue(line, "color", color));
-
- type = OpTypeTerrain(line, "type", TYPENULL);
- if ( type == TYPETERRAIN )
- {
- m_light->SetLightIncluType(obj, TYPETERRAIN);
- }
- if ( type == TYPEQUARTZ )
- {
- m_light->SetLightIncluType(obj, TYPEQUARTZ);
- }
- if ( type == TYPEMETAL )
- {
- m_light->SetLightIncluType(obj, TYPEMETAL);
- }
- if ( type == TYPEFIX )
- {
- m_light->SetLightExcluType(obj, TYPETERRAIN);
- }
- }
-
- if ( Cmd(line, "GroundSpot") && !bResetObject )
- {
- rank = m_engine->GroundSpotCreate();
- if ( rank != -1 )
- {
- m_engine->SetObjectGroundSpotPos(rank, OpPos(line, "pos")*g_unit);
- m_engine->SetObjectGroundSpotRadius(rank, OpFloat(line, "radius", 10.0f)*g_unit);
- m_engine->SetObjectGroundSpotColor(rank, RetColor(OpColor(line, "color", 0x88888888)));
- m_engine->SetObjectGroundSpotSmooth(rank, OpFloat(line, "smooth", 1.0f));
- m_engine->SetObjectGroundSpotMinMax(rank, OpFloat(line, "min", 0.0f)*g_unit,
- OpFloat(line, "max", 0.0f)*g_unit);
- }
- }
-
- if ( Cmd(line, "WaterColor") && !bResetObject )
- {
- color.r = 0.0f;
- color.g = 0.0f;
- color.b = 0.0f;
- color.a = 1.0f;
- m_engine->SetWaterAddColor(OpColorValue(line, "color", color));
- }
-
- if ( Cmd(line, "MapColor") && !bResetObject )
- {
- m_map->FloorColorMap(RetColor(OpColor(line, "floor", 0x88888888)),
- RetColor(OpColor(line, "water", 0x88888888)));
- m_bMapShow = OpInt(line, "show", 1);
- m_map->ShowMap(m_bMapShow);
- m_map->SetToy(OpInt(line, "toyIcon", 0));
- m_bMapImage = OpInt(line, "image", 0);
- if ( m_bMapImage )
- {
- Math::Vector offset;
- OpString(line, "filename", m_mapFilename);
- offset = OpPos(line, "offset");
- m_map->SetFixParam(OpFloat(line, "zoom", 1.0f),
- offset.x, offset.z,
- OpFloat(line, "angle", 0.0f)*Math::PI/180.0f,
- OpInt(line, "mode", 0),
- OpInt(line, "debug", 0));
- }
- }
- if ( Cmd(line, "MapZoom") && !bResetObject )
- {
- m_map->ZoomMap(OpFloat(line, "factor", 2.0f));
- m_map->MapEnable(OpInt(line, "enable", 1));
- }
-
- if ( Cmd(line, "MaxFlyingHeight") && !bResetObject )
- {
- m_terrain->SetFlyingMaxHeight(OpFloat(line, "max", 280.0f)*g_unit);
- }
- if ( Cmd(line, "AddFlyingHeight") && !bResetObject )
- {
- m_terrain->AddFlyingLimit(OpPos(line, "center")*g_unit,
- OpFloat(line, "extRadius", 20.0f)*g_unit,
- OpFloat(line, "intRadius", 10.0f)*g_unit,
- OpFloat(line, "maxHeight", 200.0f));
- }
-
- if ( Cmd(line, "Camera") )
- {
- m_camera->Init(OpDir(line, "eye")*g_unit,
- OpDir(line, "lookat")*g_unit,
- bResetObject?0.0f:OpFloat(line, "delay", 0.0f));
-
- if ( OpInt(line, "fadeIn", 0) == 1 )
- {
- m_camera->StartOver(OE_FADEINw, Math::Vector(0.0f, 0.0f, 0.0f), 1.0f);
- }
- m_camera->SetFixDirection(OpFloat(line, "fixDirection", 0.25f)*Math::PI);
- }
-
- if ( Cmd(line, "EndMissionTake") && !bResetObject )
- {
- i = m_endTakeTotal;
- if ( i < 10 )
- {
- m_endTake[i].pos = OpPos(line, "pos")*g_unit;
- m_endTake[i].dist = OpFloat(line, "dist", 8.0f)*g_unit;
- m_endTake[i].type = OpTypeObject(line, "type", OBJECT_NULL);
- m_endTake[i].min = OpInt(line, "min", 1);
- m_endTake[i].max = OpInt(line, "max", 9999);
- m_endTake[i].lost = OpInt(line, "lost", -1);
- m_endTake[i].bImmediat = OpInt(line, "immediat", 0);
- OpString(line, "message", m_endTake[i].message);
- m_endTakeTotal ++;
- }
- }
- if ( Cmd(line, "EndMissionDelay") && !bResetObject )
- {
- m_endTakeWinDelay = OpFloat(line, "win", 2.0f);
- m_endTakeLostDelay = OpFloat(line, "lost", 2.0f);
- }
- if ( Cmd(line, "EndMissionResearch") && !bResetObject )
- {
- m_endTakeResearch |= OpResearch(line, "type");
- }
-
- if ( Cmd(line, "ObligatoryToken") && !bResetObject )
- {
- i = m_obligatoryTotal;
- if ( i < 100 )
- {
- OpString(line, "text", m_obligatoryToken[i]);
- m_obligatoryTotal ++;
- }
- }
-
- if ( Cmd(line, "ProhibitedToken") && !bResetObject )
- {
- i = m_prohibitedTotal;
- if ( i < 100 )
- {
- OpString(line, "text", m_prohibitedToken[i]);
- m_prohibitedTotal ++;
- }
- }
-
- if ( Cmd(line, "EnableBuild") && !bResetObject )
- {
- g_build |= OpBuild(line, "type");
- }
-
- if ( Cmd(line, "EnableResearch") && !bResetObject )
- {
- g_researchEnable |= OpResearch(line, "type");
- }
- if ( Cmd(line, "DoneResearch") && read[0] == 0 && !bResetObject ) // not loading file?
- {
- g_researchDone |= OpResearch(line, "type");
- }
-
- if ( Cmd(line, "NewScript") && !bResetObject )
- {
- OpString(line, "name", name);
- AddNewScriptName(OpTypeObject(line, "type", OBJECT_NULL), name);
- }
- }
-
- fclose(file);
-
- if ( read[0] == 0 )
- {
- CompileScript(bSoluce); // compiles all scripts
- }
-
- if ( strcmp(base, "scene") == 0 && !bResetObject ) // mission?
- {
- WriteFreeParam();
- }
- if ( strcmp(base, "free") == 0 && !bResetObject ) // free play?
- {
- g_researchDone = m_freeResearch;
-
- g_build = m_freeBuild;
- g_build &= ~BUILD_RESEARCH;
- g_build &= ~BUILD_LABO;
- g_build |= BUILD_FACTORY;
- g_build |= BUILD_GFLAT;
- g_build |= BUILD_FLAG;
- }
-
- if ( !bResetObject )
- {
- ChangeColor(); // changes the colors of texture
- m_short->SetMode(false); // vehicles?
- }
-
- CreateShortcuts();
- m_map->UpdateMap();
- m_engine->TimeInit();
- m_engine->FlushPressKey();
- m_time = 0.0f;
- m_gameTime = 0.0f;
- m_checkEndTime = 0.0f;
- m_infoUsed = 0;
-
- m_selectObject = pSel;
-
- if ( !m_bBase && // no main base?
- !m_bFixScene ) // interractive scene?
- {
- if ( pSel == 0 )
- {
- pObj = SearchHuman();
- }
- else
- {
- pObj = pSel;
- }
- if ( pObj != 0 )
- {
- SelectObject(pObj);
- m_camera->SetObject(pObj);
-//? m_camera->SetType(CAMERA_BACK);
- m_camera->SetType(pObj->RetCameraType());
- }
- }
- if ( m_bFixScene )
- {
- m_camera->SetType(CAMERA_SCRIPT);
- }
-
- if ( read[0] != 0 && pSel != 0 ) // loading file?
- {
- pos = pSel->RetPosition(0);
- m_camera->Init(pos, pos, 0.0f);
- m_camera->FixCamera();
-
- SelectObject(pSel);
- m_camera->SetObject(pSel);
-
- m_bBeginSatCom = true; // message already displayed
- }
- m_dialog->SetSceneRead("");
- m_dialog->SetStackRead("");
-}
-
-// Creates an object of decoration mobile or stationary.
-
-CObject* CRobotMain::CreateObject(Math::Vector pos, float angle, float zoom, float height,
- ObjectType type, float power,
- bool bTrainer, bool bToy,
- int option)
-{
- CObject* pObject = 0;
- CAuto* automat;
-
- if ( type == OBJECT_NULL ) return 0;
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH )
- {
- bTrainer = false; // necessarily
- }
-
- if ( type == OBJECT_PORTICO ||
- type == OBJECT_BASE ||
- type == OBJECT_DERRICK ||
- type == OBJECT_FACTORY ||
- type == OBJECT_STATION ||
- type == OBJECT_CONVERT ||
- type == OBJECT_REPAIR ||
- type == OBJECT_DESTROYER||
- type == OBJECT_TOWER ||
- type == OBJECT_NEST ||
- 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 ||
- type == OBJECT_TARGET1 ||
- type == OBJECT_TARGET2 ||
- type == OBJECT_START ||
- type == OBJECT_END )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateBuilding(pos, angle, height, type, power);
-
- automat = pObject->RetAuto();
- if ( automat != 0 )
- {
- automat->Init();
- }
- }
- else
- if ( type == OBJECT_FRET ||
- type == OBJECT_STONE ||
- type == OBJECT_URANIUM ||
- type == OBJECT_METAL ||
- type == OBJECT_POWER ||
- type == OBJECT_ATOMIC ||
- type == OBJECT_BULLET ||
- type == OBJECT_BBOX ||
- type == OBJECT_KEYa ||
- type == OBJECT_KEYb ||
- type == OBJECT_KEYc ||
- type == OBJECT_KEYd ||
- type == OBJECT_TNT ||
- type == OBJECT_SCRAP1 ||
- type == OBJECT_SCRAP2 ||
- type == OBJECT_SCRAP3 ||
- type == OBJECT_SCRAP4 ||
- type == OBJECT_SCRAP5 ||
- type == OBJECT_BOMB ||
- type == OBJECT_WAYPOINT ||
- type == OBJECT_SHOW ||
- type == OBJECT_WINFIRE ||
- type == OBJECT_BAG ||
- type == OBJECT_MARKPOWER ||
- type == OBJECT_MARKSTONE ||
- type == OBJECT_MARKURANIUM ||
- type == OBJECT_MARKKEYa ||
- type == OBJECT_MARKKEYb ||
- type == OBJECT_MARKKEYc ||
- type == OBJECT_MARKKEYd ||
- type == OBJECT_EGG )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateResource(pos, angle, type, power);
- }
- else
- if ( type == OBJECT_FLAGb ||
- type == OBJECT_FLAGr ||
- type == OBJECT_FLAGg ||
- type == OBJECT_FLAGy ||
- type == OBJECT_FLAGv )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateFlag(pos, angle, type);
- }
- else
- if ( type == OBJECT_BARRIER0 ||
- type == OBJECT_BARRIER1 ||
- type == OBJECT_BARRIER2 ||
- type == OBJECT_BARRIER3 ||
- type == OBJECT_BARRIER4 )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateBarrier(pos, angle, height, type);
- }
- else
- if ( type == OBJECT_PLANT0 ||
- type == OBJECT_PLANT1 ||
- type == OBJECT_PLANT2 ||
- type == OBJECT_PLANT3 ||
- type == OBJECT_PLANT4 ||
- type == OBJECT_PLANT5 ||
- type == OBJECT_PLANT6 ||
- type == OBJECT_PLANT7 ||
- type == OBJECT_PLANT8 ||
- type == OBJECT_PLANT9 ||
- type == OBJECT_PLANT10 ||
- type == OBJECT_PLANT11 ||
- type == OBJECT_PLANT12 ||
- type == OBJECT_PLANT13 ||
- type == OBJECT_PLANT14 ||
- type == OBJECT_PLANT15 ||
- type == OBJECT_PLANT16 ||
- type == OBJECT_PLANT17 ||
- type == OBJECT_PLANT18 ||
- type == OBJECT_PLANT19 ||
- type == OBJECT_TREE0 ||
- type == OBJECT_TREE1 ||
- type == OBJECT_TREE2 ||
- type == OBJECT_TREE3 ||
- type == OBJECT_TREE4 ||
- type == OBJECT_TREE5 ||
- type == OBJECT_TREE6 ||
- type == OBJECT_TREE7 ||
- type == OBJECT_TREE8 ||
- type == OBJECT_TREE9 )
- {
- pObject = new CObject(m_iMan);
- pObject->CreatePlant(pos, angle, height, type);
- }
- else
- if ( type == OBJECT_MUSHROOM0 ||
- type == OBJECT_MUSHROOM1 ||
- type == OBJECT_MUSHROOM2 ||
- type == OBJECT_MUSHROOM3 ||
- type == OBJECT_MUSHROOM4 ||
- type == OBJECT_MUSHROOM5 ||
- type == OBJECT_MUSHROOM6 ||
- type == OBJECT_MUSHROOM7 ||
- type == OBJECT_MUSHROOM8 ||
- type == OBJECT_MUSHROOM9 )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateMushroom(pos, angle, height, type);
- }
- else
- if ( type == OBJECT_TEEN0 ||
- type == OBJECT_TEEN1 ||
- type == OBJECT_TEEN2 ||
- type == OBJECT_TEEN3 ||
- type == OBJECT_TEEN4 ||
- type == OBJECT_TEEN5 ||
- type == OBJECT_TEEN6 ||
- type == OBJECT_TEEN7 ||
- type == OBJECT_TEEN8 ||
- type == OBJECT_TEEN9 ||
- type == OBJECT_TEEN10 ||
- type == OBJECT_TEEN11 ||
- type == OBJECT_TEEN12 ||
- type == OBJECT_TEEN13 ||
- type == OBJECT_TEEN14 ||
- type == OBJECT_TEEN15 ||
- type == OBJECT_TEEN16 ||
- type == OBJECT_TEEN17 ||
- type == OBJECT_TEEN18 ||
- type == OBJECT_TEEN19 ||
- type == OBJECT_TEEN20 ||
- type == OBJECT_TEEN21 ||
- type == OBJECT_TEEN22 ||
- type == OBJECT_TEEN23 ||
- type == OBJECT_TEEN24 ||
- type == OBJECT_TEEN25 ||
- type == OBJECT_TEEN26 ||
- type == OBJECT_TEEN27 ||
- type == OBJECT_TEEN28 ||
- type == OBJECT_TEEN29 ||
- type == OBJECT_TEEN30 ||
- type == OBJECT_TEEN31 ||
- type == OBJECT_TEEN32 ||
- type == OBJECT_TEEN33 ||
- type == OBJECT_TEEN34 ||
- type == OBJECT_TEEN35 ||
- type == OBJECT_TEEN36 ||
- type == OBJECT_TEEN37 ||
- type == OBJECT_TEEN38 ||
- type == OBJECT_TEEN39 ||
- type == OBJECT_TEEN40 ||
- type == OBJECT_TEEN41 ||
- type == OBJECT_TEEN42 ||
- type == OBJECT_TEEN43 ||
- type == OBJECT_TEEN44 ||
- type == OBJECT_TEEN45 ||
- type == OBJECT_TEEN46 ||
- type == OBJECT_TEEN47 ||
- type == OBJECT_TEEN48 ||
- type == OBJECT_TEEN49 )
- {
- pObject = new CObject(m_iMan);
- pObject->SetOption(option);
- pObject->CreateTeen(pos, angle, zoom, height, type);
- }
- else
- if ( type == OBJECT_QUARTZ0 ||
- type == OBJECT_QUARTZ1 ||
- type == OBJECT_QUARTZ2 ||
- type == OBJECT_QUARTZ3 ||
- type == OBJECT_QUARTZ4 ||
- type == OBJECT_QUARTZ5 ||
- type == OBJECT_QUARTZ6 ||
- type == OBJECT_QUARTZ7 ||
- type == OBJECT_QUARTZ8 ||
- type == OBJECT_QUARTZ9 )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateQuartz(pos, angle, height, type);
- }
- else
- if ( type == OBJECT_ROOT0 ||
- type == OBJECT_ROOT1 ||
- type == OBJECT_ROOT2 ||
- type == OBJECT_ROOT3 ||
- type == OBJECT_ROOT4 ||
- type == OBJECT_ROOT5 ||
- type == OBJECT_ROOT6 ||
- type == OBJECT_ROOT7 ||
- type == OBJECT_ROOT8 ||
- type == OBJECT_ROOT9 )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateRoot(pos, angle, height, type);
- }
- else
- if ( type == OBJECT_HOME1 )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateHome(pos, angle, height, type);
- }
- else
- if ( type == OBJECT_RUINmobilew1 ||
- type == OBJECT_RUINmobilew2 ||
- type == OBJECT_RUINmobilet1 ||
- type == OBJECT_RUINmobilet2 ||
- type == OBJECT_RUINmobiler1 ||
- type == OBJECT_RUINmobiler2 ||
- type == OBJECT_RUINfactory ||
- type == OBJECT_RUINdoor ||
- type == OBJECT_RUINsupport ||
- type == OBJECT_RUINradar ||
- type == OBJECT_RUINconvert ||
- type == OBJECT_RUINbase ||
- type == OBJECT_RUINhead )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateRuin(pos, angle, height, type);
- }
- else
- if ( type == OBJECT_APOLLO1 ||
- type == OBJECT_APOLLO3 ||
- type == OBJECT_APOLLO4 ||
- type == OBJECT_APOLLO5 )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateApollo(pos, angle, type);
- }
- else
- if ( type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM )
- {
- pObject = new CObject(m_iMan);
- pObject->CreateInsect(pos, angle, type); // no eggs
- }
- else
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH ||
- type == OBJECT_TOTO ||
- type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr ||
- type == OBJECT_APOLLO2 )
- {
- pObject = new CObject(m_iMan);
- pObject->SetOption(option);
- pObject->CreateVehicle(pos, angle, type, power, bTrainer, bToy);
- }
-
- if ( m_bFixScene && type == OBJECT_HUMAN )
- {
- CMotion* motion;
-
- motion = pObject->RetMotion();
- if ( m_phase == PHASE_WIN ) motion->SetAction(MHS_WIN, 0.4f);
- if ( m_phase == PHASE_LOST ) motion->SetAction(MHS_LOST, 0.5f);
- }
-
- return pObject;
-}
-
-
-// Creates the editable model.
-
-void CRobotMain::CreateModel()
-{
- Math::Vector direction;
- D3DCOLORVALUE color;
-
- m_engine->SetAmbiantColor(0xC0C0C0C0); // gray
- m_engine->SetBackground("", 0x80808080, 0x80808080, 0x80808080, 0x80808080);
- m_engine->SetFogColor(0x80808080);
- m_engine->SetDeepView(500.0f, 0);
- m_engine->SetDeepView(100.0f, 1);
- m_engine->SetFogStart(0.5f);
-
- m_model->StartUserAction();
-
- direction = Math::Vector(1.0f, -1.0f, 1.0f);
- color.r = 0.7f;
- color.g = 0.7f;
- color.b = 0.7f; // white
- CreateLight(direction, color);
-
- direction = Math::Vector(-1.0f, -1.0f, 1.0f);
- color.r = 0.7f;
- color.g = 0.7f;
- color.b = 0.7f; // white
- CreateLight(direction, color);
-
- direction = Math::Vector(1.0f, -1.0f, -1.0f);
- color.r = 0.7f;
- color.g = 0.7f;
- color.b = 0.7f; // white
- CreateLight(direction, color);
-
- direction = Math::Vector(-1.0f, -1.0f, -1.0f);
- color.r = 0.7f;
- color.g = 0.7f;
- color.b = 0.7f; // white
- CreateLight(direction, color);
-
- direction = Math::Vector(0.0f, 1.0f, 0.0f);
- color.r = 0.7f;
- color.g = 0.7f;
- color.b = 0.7f; // white
- CreateLight(direction, color);
-
- InitEye();
-
- m_engine->TimeInit();
- m_time = 0.0f;
- m_gameTime = 0.0f;
- m_checkEndTime = 0.0f;
-}
-
-
-// Creates a directional light.
-
-int CRobotMain::CreateLight(Math::Vector direction, D3DCOLORVALUE color)
-{
- D3DLIGHT7 light;
- int obj;
-
- if ( direction.x == 0.0f &&
- direction.y == 0.0f &&
- direction.z == 0.0f )
- {
- direction.y = -1.0f;
- }
-
- ZeroMemory(&light, sizeof(D3DLIGHT7));
- light.dltType = D3DLIGHT_DIRECTIONAL;
- light.dcvDiffuse.r = color.r;
- light.dcvDiffuse.g = color.g;
- light.dcvDiffuse.b = color.b;
- light.dvDirection = VEC_TO_D3DVEC(direction);
- obj = m_light->CreateLight();
- m_light->SetLight(obj, light);
-
- return obj;
-}
-
-// Creates a light spot.
-
-int CRobotMain::CreateSpot(Math::Vector pos, D3DCOLORVALUE color)
-{
- D3DLIGHT7 light;
- int obj;
-
- if ( !m_engine->RetLightMode() ) return -1;
-
- pos.y += m_terrain->RetFloorLevel(pos);
-
- ZeroMemory(&light, sizeof(D3DLIGHT7));
- light.dltType = D3DLIGHT_SPOT;
- light.dcvDiffuse.r = color.r;
- light.dcvDiffuse.g = color.g;
- light.dcvDiffuse.b = color.b;
- light.dvPosition = VEC_TO_D3DVEC(pos);
- light.dvDirection = D3DVECTOR(0.0f, -1.0f, 0.0f);
- light.dvRange = D3DLIGHT_RANGE_MAX;
- light.dvFalloff = 1.0f;
- light.dvTheta = 10.0f*Math::PI/180.0f;
- light.dvPhi = 90.0f*Math::PI/180.0f;
- light.dvAttenuation0 = 2.0f;
- light.dvAttenuation1 = 0.0f;
- light.dvAttenuation2 = 0.0f;
- obj = m_light->CreateLight();
- m_light->SetLight(obj, light);
-
- return obj;
-}
-
-
-// Change the colors and textures.
-
-void CRobotMain::ChangeColor()
-{
- D3DCOLORVALUE colorRef1, colorNew1, colorRef2, colorNew2;
- Math::Point ts, ti;
- Math::Point exclu[6];
- char name[100];
- int face;
- float tolerance;
-
- ts = Math::Point(0.0f, 0.0f);
- ti = Math::Point(1.0f, 1.0f); // the entire image
-
- colorRef1.a = 0.0f;
- colorRef2.a = 0.0f;
-
- colorRef1.r = 206.0f/256.0f;
- colorRef1.g = 206.0f/256.0f;
- colorRef1.b = 204.0f/256.0f; // ~white
- colorNew1 = m_dialog->RetGamerColorCombi();
- colorRef2.r = 255.0f/256.0f;
- colorRef2.g = 132.0f/256.0f;
- colorRef2.b = 1.0f/256.0f; // orange
- colorNew2 = m_dialog->RetGamerColorBand();
- exclu[0] = Math::Point(192.0f/256.0f, 0.0f/256.0f);
- exclu[1] = Math::Point(256.0f/256.0f, 64.0f/256.0f); // crystals + cylinders
- exclu[2] = Math::Point(208.0f/256.0f, 224.0f/256.0f);
- exclu[3] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // SatCom screen
- exclu[4] = Math::Point(0.0f, 0.0f);
- exclu[5] = Math::Point(0.0f, 0.0f); // terminator
- m_engine->ChangeColor("human.tga", colorRef1, colorNew1, colorRef2, colorNew2, 0.30f, 0.01f, ts, ti, exclu);
-
- face = RetGamerFace();
- if ( face == 0 ) // normal?
- {
- colorRef1.r = 90.0f/256.0f;
- colorRef1.g = 95.0f/256.0f;
- colorRef1.b = 85.0f/256.0f; // black
- tolerance = 0.15f;
- }
- if ( face == 1 ) // bald?
- {
- colorRef1.r = 74.0f/256.0f;
- colorRef1.g = 58.0f/256.0f;
- colorRef1.b = 46.0f/256.0f; // brown
- tolerance = 0.20f;
- }
- if ( face == 2 ) // carlos?
- {
- colorRef1.r = 70.0f/256.0f;
- colorRef1.g = 40.0f/256.0f;
- colorRef1.b = 8.0f/256.0f; // brown
- tolerance = 0.30f;
- }
- if ( face == 3 ) // blonde?
- {
- colorRef1.r = 74.0f/256.0f;
- colorRef1.g = 16.0f/256.0f;
- colorRef1.b = 0.0f/256.0f; // yellow
- tolerance = 0.20f;
- }
- colorNew1 = m_dialog->RetGamerColorHair();
- colorRef2.r = 0.0f;
- colorRef2.g = 0.0f;
- colorRef2.b = 0.0f;
- colorNew2.r = 0.0f;
- colorNew2.g = 0.0f;
- colorNew2.b = 0.0f;
- sprintf(name, "face%.2d.tga", face+1);
- exclu[0] = Math::Point(105.0f/256.0f, 47.0f/166.0f);
- exclu[1] = Math::Point(153.0f/256.0f, 79.0f/166.0f); // blue canister
- exclu[2] = Math::Point(0.0f, 0.0f);
- exclu[3] = Math::Point(0.0f, 0.0f); // terminator
- m_engine->ChangeColor(name, colorRef1, colorNew1, colorRef2, colorNew2, tolerance, 0.00f, ts, ti, exclu);
-
- colorRef2.r = 0.0f;
- colorRef2.g = 0.0f;
- colorRef2.b = 0.0f;
- colorNew2.r = 0.0f;
- colorNew2.g = 0.0f;
- colorNew2.b = 0.0f;
-
- m_engine->ChangeColor("base1.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
- m_engine->ChangeColor("convert.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
- m_engine->ChangeColor("derrick.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
- m_engine->ChangeColor("factory.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
- m_engine->ChangeColor("lemt.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
- m_engine->ChangeColor("roller.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
- m_engine->ChangeColor("search.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
-
- exclu[0] = Math::Point( 0.0f/256.0f, 160.0f/256.0f);
- exclu[1] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // pencils
- exclu[2] = Math::Point(0.0f, 0.0f);
- exclu[3] = Math::Point(0.0f, 0.0f); // terminator
- m_engine->ChangeColor("drawer.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true);
-
- exclu[0] = Math::Point(237.0f/256.0f, 176.0f/256.0f);
- exclu[1] = Math::Point(256.0f/256.0f, 220.0f/256.0f); // blue canister
- exclu[2] = Math::Point(106.0f/256.0f, 150.0f/256.0f);
- exclu[3] = Math::Point(130.0f/256.0f, 214.0f/256.0f); // safe location
- exclu[4] = Math::Point(0.0f, 0.0f);
- exclu[5] = Math::Point(0.0f, 0.0f); // terminator
- m_engine->ChangeColor("subm.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true);
-
- exclu[0] = Math::Point(128.0f/256.0f, 160.0f/256.0f);
- exclu[1] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // SatCom
- exclu[2] = Math::Point(0.0f, 0.0f);
- exclu[3] = Math::Point(0.0f, 0.0f); // terminator
- m_engine->ChangeColor("ant.tga", m_colorRefAlien, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti, exclu);
- m_engine->ChangeColor("mother.tga", m_colorRefAlien, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti);
-
- m_engine->ChangeColor("plant.tga", m_colorRefGreen, m_colorNewGreen, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti);
-
- // PARTIPLOUF0 and PARTIDROP :
- ts = Math::Point(0.500f, 0.500f);
- ti = Math::Point(0.875f, 0.750f);
- m_engine->ChangeColor("effect00.tga", m_colorRefWater, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, 0, m_colorShiftWater, true);
-
- // PARTIFLIC :
- ts = Math::Point(0.00f, 0.75f);
- ti = Math::Point(0.25f, 1.00f);
- m_engine->ChangeColor("effect02.tga", m_colorRefWater, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, 0, m_colorShiftWater, true);
-}
-
-// Updates the number of unnecessary objects.
-
-bool CRobotMain::TestGadgetQuantity(int rank)
-{
- float percent;
- int *table;
-
- static int table10[10] = {0,1,0,0,0,0,0,0,0,0};
- static int table20[10] = {0,1,0,0,0,1,0,0,0,0};
- static int table30[10] = {0,1,0,1,0,1,0,0,0,0};
- static int table40[10] = {0,1,0,1,0,1,0,1,0,0};
- static int table50[10] = {0,1,0,1,0,1,0,1,0,1};
- static int table60[10] = {0,1,0,1,1,1,0,1,0,1};
- static int table70[10] = {0,1,0,1,1,1,0,1,1,1};
- static int table80[10] = {0,1,1,1,1,1,0,1,1,1};
- static int table90[10] = {0,1,1,1,1,1,1,1,1,1};
-
- percent = m_engine->RetGadgetQuantity();
- if ( percent == 0.0f ) return false;
- if ( percent == 1.0f ) return true;
-
- if ( percent <= 0.15f ) table = table10;
- else if ( percent <= 0.25f ) table = table20;
- else if ( percent <= 0.35f ) table = table30;
- else if ( percent <= 0.45f ) table = table40;
- else if ( percent <= 0.55f ) table = table50;
- else if ( percent <= 0.65f ) table = table60;
- else if ( percent <= 0.75f ) table = table70;
- else if ( percent <= 0.85f ) table = table80;
- else table = table90;
-
- return table[rank%10];
-}
-
-
-
-// Calculates the distance to the nearest object.
-
-float CRobotMain::SearchNearestObject(Math::Vector center, CObject *exclu)
-{
- CObject* pObj;
- ObjectType type;
- Math::Vector oPos;
- float min, dist, oRadius;
- int i, j;
-
- min = 100000.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object carries?
- if ( pObj == exclu ) continue;
-
- type = pObj->RetType();
-
- if ( type == OBJECT_BASE )
- {
- oPos = pObj->RetPosition(0);
- if ( oPos.x != center.x ||
- oPos.z != center.z )
- {
- dist = Math::Distance(center, oPos)-80.0f;
- if ( dist < 0.0f ) dist = 0.0f;
- min = Math::Min(min, dist);
- continue;
- }
- }
-
- if ( type == OBJECT_STATION ||
- type == OBJECT_REPAIR ||
- type == OBJECT_DESTROYER )
- {
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(center, oPos)-8.0f;
- if ( dist < 0.0f ) dist = 0.0f;
- min = Math::Min(min, dist);
- }
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- dist = Math::Distance(center, oPos)-oRadius;
- if ( dist < 0.0f ) dist = 0.0f;
- min = Math::Min(min, dist);
- }
- }
- return min;
-}
-
-// Calculates a free space.
-
-bool CRobotMain::FreeSpace(Math::Vector &center, float minRadius, float maxRadius,
- float space, CObject *exclu)
-{
- Math::Vector pos;
- Math::Point p;
- float radius, ia, angle, dist, flat;
-
- if ( minRadius < maxRadius ) // from internal to external?
- {
- for ( radius=minRadius ; radius<=maxRadius ; radius+=space )
- {
- ia = space/radius;
- for ( angle=0.0f ; angle<Math::PI*2.0f ; angle+=ia )
- {
- p.x = center.x+radius;
- p.y = center.z;
- p = Math::RotatePoint(Math::Point(center.x, center.z), angle, p);
- pos.x = p.x;
- pos.z = p.y;
- pos.y = 0.0f;
- m_terrain->MoveOnFloor(pos, true);
- dist = SearchNearestObject(pos, exclu);
- if ( dist >= space )
- {
- flat = m_terrain->RetFlatZoneRadius(pos, dist/2.0f);
- if ( flat >= dist/2.0f )
- {
- center = pos;
- return true;
- }
- }
- }
- }
- }
- else // from external to internal?
- {
- for ( radius=maxRadius ; radius>=minRadius ; radius-=space )
- {
- ia = space/radius;
- for ( angle=0.0f ; angle<Math::PI*2.0f ; angle+=ia )
- {
- p.x = center.x+radius;
- p.y = center.z;
- p = Math::RotatePoint(Math::Point(center.x, center.z), angle, p);
- pos.x = p.x;
- pos.z = p.y;
- pos.y = 0.0f;
- m_terrain->MoveOnFloor(pos, true);
- dist = SearchNearestObject(pos, exclu);
- if ( dist >= space )
- {
- flat = m_terrain->RetFlatZoneRadius(pos, dist/2.0f);
- if ( flat >= dist/2.0f )
- {
- center = pos;
- return true;
- }
- }
- }
- }
- }
- return false;
-}
-
-// Calculates the maximum radius of a free space.
-
-float CRobotMain::RetFlatZoneRadius(Math::Vector center, float maxRadius,
- CObject *exclu)
-{
- float dist;
-
- dist = SearchNearestObject(center, exclu);
- if ( dist == 0.0f ) return 0.0f;
- if ( dist < maxRadius )
- {
- maxRadius = dist;
- }
- return m_terrain->RetFlatZoneRadius(center, maxRadius);
-}
-
-
-// Hides buildable area when a cube of metal is taken up.
-
-void CRobotMain::HideDropZone(CObject* metal)
-{
- if ( m_showLimit[1].bUsed &&
- m_showLimit[1].link == metal )
- {
- FlushShowLimit(1);
- }
-
- if ( m_showLimit[2].bUsed &&
- m_showLimit[2].link == metal )
- {
- FlushShowLimit(2);
- }
-}
-
-// Shows the buildable area when a cube of metal is deposited.
-
-void CRobotMain::ShowDropZone(CObject* metal, CObject* truck)
-{
- CObject* pObj;
- ObjectType type;
- Math::Vector center, oPos;
- float oMax, tMax, dist, oRadius, radius;
- int i, j;
-
- if ( metal == 0 ) return;
-
- center = metal->RetPosition(0);
-
- // Calculates the maximum radius possible depending on other items.
- oMax = 30.0f; // radius to build the biggest building
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object carried?
- if ( pObj == metal ) continue;
- if ( pObj == truck ) continue;
-
- type = pObj->RetType();
- if ( type == OBJECT_BASE )
- {
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(center, oPos)-80.0f;
- oMax = Math::Min(oMax, dist);
- }
- else
- {
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- dist = Math::Distance(center, oPos)-oRadius;
- oMax = Math::Min(oMax, dist);
- }
- }
-
- if ( type == OBJECT_DERRICK ||
- type == OBJECT_FACTORY ||
- type == OBJECT_STATION ||
- type == OBJECT_CONVERT ||
- type == OBJECT_REPAIR ||
- type == OBJECT_DESTROYER||
- type == OBJECT_TOWER ||
- type == OBJECT_RESEARCH ||
- type == OBJECT_RADAR ||
- type == OBJECT_ENERGY ||
- type == OBJECT_LABO ||
- type == OBJECT_NUCLEAR ||
- type == OBJECT_START ||
- type == OBJECT_END ||
- type == OBJECT_INFO ||
- type == OBJECT_PARA ||
- type == OBJECT_SAFE ||
- type == OBJECT_HUSTON ) // building?
- {
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- dist = Math::Distance(center, oPos)-oRadius-BUILDMARGIN;
- oMax = Math::Min(oMax, dist);
- }
- }
- }
-
- // Calculates the maximum possible radius depending on terrain.
- if ( oMax >= 2.0f )
- {
- tMax = m_terrain->RetFlatZoneRadius(center, 30.0f);
- }
- else
- {
- tMax = 0.0f;
- }
-
- radius = Math::Min(oMax, tMax);
- if ( radius >= 2.0f )
- {
- SetShowLimit(1, PARTILIMIT2, metal, center, radius, 10.0f);
- }
-}
-
-// Erases the boundaries shown.
-
-void CRobotMain::FlushShowLimit(int i)
-{
- int j;
-
- if ( m_showLimit[i].link != 0 )
- {
- m_showLimit[i].link->StopShowLimit();
- }
-
- for ( j=0 ; j<m_showLimit[i].total ; j++ )
- {
- if ( m_showLimit[i].parti[j] == 0 ) continue;
-
- m_particule->DeleteParticule(m_showLimit[i].parti[j]);
- m_showLimit[i].parti[j] = 0;
- }
-
- m_showLimit[i].total = 0;
- m_showLimit[i].link = 0;
- m_showLimit[i].bUsed = false;
-}
-
-// Specifies the boundaries to show.
-
-void CRobotMain::SetShowLimit(int i, ParticuleType parti, CObject *pObj,
- Math::Vector pos, float radius, float duration)
-{
- Math::Point dim;
- float dist;
- int j;
-
- FlushShowLimit(i); // erases the current boundaries
-
- if ( radius <= 0.0f ) return;
-
- if ( radius <= 50.0f )
- {
- dim = Math::Point(0.3f, 0.3f);
- dist = 2.5f;
- }
- else
- {
- dim = Math::Point(1.5f, 1.5f);
- dist = 10.0f;
- }
-
- m_showLimit[i].bUsed = true;
- m_showLimit[i].link = pObj;
- m_showLimit[i].pos = pos;
- m_showLimit[i].radius = radius;
- m_showLimit[i].duration = duration;
- m_showLimit[i].total = (int)((radius*2.0f*Math::PI)/dist);
- if ( m_showLimit[i].total > MAXSHOWPARTI ) m_showLimit[i].total = MAXSHOWPARTI;
- m_showLimit[i].time = 0.0f;
-
- for ( j=0 ; j<m_showLimit[i].total ; j++ )
- {
- m_showLimit[i].parti[j] = m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), dim, parti, duration);
- }
-}
-
-// Adjusts the boundaries to show.
-
-void CRobotMain::AdjustShowLimit(int i, Math::Vector pos)
-{
- m_showLimit[i].pos = pos;
-}
-
-// Mount the boundaries of the selected object.
-
-void CRobotMain::StartShowLimit()
-{
- CObject* pObj;
-
- pObj = RetSelect();
- if ( pObj == 0 ) return;
-
- pObj->StartShowLimit();
-}
-
-// Advances the boundaries shown.
-
-void CRobotMain::FrameShowLimit(float rTime)
-{
- Math::Vector pos;
- Math::Point center, rotate;
- float angle, factor, speed;
- int i, j;
-
- if ( m_engine->RetPause() ) return;
-
- for ( i=0 ; i<MAXSHOWLIMIT ; i++ )
- {
- if ( !m_showLimit[i].bUsed ) continue;
-
- m_showLimit[i].time += rTime;
-
- if ( m_showLimit[i].time >= m_showLimit[i].duration )
- {
- FlushShowLimit(i);
- continue;
- }
-
- if ( m_showLimit[i].time < 1.0f )
- {
- factor = m_showLimit[i].time;
- }
- else if ( m_showLimit[i].time > m_showLimit[i].duration-1.0f )
- {
- factor = m_showLimit[i].duration-m_showLimit[i].time;
- }
- else
- {
- factor = 1.0f;
- }
-
- speed = 0.4f-m_showLimit[i].radius*0.001f;
- if ( speed < 0.1f ) speed = 0.1f;
- angle = m_showLimit[i].time*speed;
-
- for ( j=0 ; j<m_showLimit[i].total ; j++ )
- {
- if ( m_showLimit[i].parti[j] == 0 ) continue;
-
- center.x = m_showLimit[i].pos.x;
- center.y = m_showLimit[i].pos.z;
- rotate.x = center.x+m_showLimit[i].radius*factor;
- rotate.y = center.y;
- rotate = Math::RotatePoint(center, angle, rotate);
-
- pos.x = rotate.x;
- pos.z = rotate.y;
- pos.y = 0.0f;
- m_terrain->MoveOnFloor(pos, true);
- if ( m_showLimit[i].radius <= 50.0f ) pos.y += 0.5f;
- else pos.y += 2.0f;
- m_particule->SetPosition(m_showLimit[i].parti[j], pos);
-//? m_particule->SetAngle(m_showLimit[i].parti[j], angle-Math::PI/2.0f);
-
- angle += (2.0f*Math::PI)/m_showLimit[i].total;
- }
- }
-}
-
-
-
-// Returns a pointer to the last backslash in a filename.
-
-char* SearchLastDir(char *filename)
-{
- char* p = filename;
-
- while ( *p++ != 0 );
- p --; // ^on the zero terminator
-
- while ( p != filename )
- {
- if ( *(--p) == '\\' ) return p;
- }
- return 0;
-}
-
-
-// Compiles all scripts of robots.
-
-void CRobotMain::CompileScript(bool bSoluce)
-{
- CObject* pObj;
- CBrain* brain;
- int i, j, nbError, lastError, run;
- char* name;
-
- nbError = 0;
- do
- {
- lastError = nbError;
- nbError = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
- if ( pObj->RetTruck() != 0 ) continue;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) continue;
-
- for ( j=0 ; j<10 ; j++ )
- {
- if ( brain->RetCompile(j) ) continue;
-
- name = brain->RetScriptName(j);
- if ( name[0] != 0 )
- {
- brain->ReadProgram(j, name);
- if ( !brain->RetCompile(j) ) nbError++;
- }
- }
-
- LoadOneScript(pObj, nbError);
- }
- }
- while ( nbError > 0 && nbError != lastError );
-
- // Load all solutions.
- if ( bSoluce )
- {
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
- if ( pObj->RetTruck() != 0 ) continue;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) continue;
-
- name = brain->RetSoluceName();
- if ( name[0] != 0 )
- {
- brain->ReadSoluce(name); // load solution
- }
- }
- }
-
- // Start all programs according to the command "run".
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
- if ( pObj->RetTruck() != 0 ) continue;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) continue;
-
- run = brain->RetScriptRun();
- if ( run != -1 )
- {
- brain->RunProgram(run); // starts the program
- }
- }
-}
-
-// Load all programs of the robot.
-
-void CRobotMain::LoadOneScript(CObject *pObj, int &nbError)
-{
- ObjectType type;
- CBrain* brain;
- char filename[_MAX_FNAME];
- char* name;
- int rank, i, objRank;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) return;
-
- if ( !IsSelectable(pObj) ) return;
-
- type = pObj->RetType();
- if ( type == OBJECT_HUMAN ) return;
-
- objRank = pObj->RetDefRank();
- if ( objRank == -1 ) return;
-
- name = m_dialog->RetSceneName();
- rank = m_dialog->RetSceneRank();
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- if ( brain->RetCompile(i) ) continue;
-//? if ( brain->ProgramExist(i) ) continue;
-
- sprintf(filename, "%s\\%s\\%c%.3d%.3d%.1d.txt",
- RetSavegameDir(), m_gamerName, name[0], rank, objRank, i);
- brain->ReadProgram(i, filename);
- if ( !brain->RetCompile(i) ) nbError++;
- }
-}
-
-// Load all programs of the robot.
-
-void CRobotMain::LoadFileScript(CObject *pObj, char* filename, int objRank,
- int &nbError)
-{
- ObjectType type;
- CBrain* brain;
- char fn[_MAX_FNAME];
- char* ldir;
- char* name;
- int rank, i;
-
- if ( objRank == -1 ) return;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) return;
-
- type = pObj->RetType();
- if ( type == OBJECT_HUMAN ) return;
-
- name = m_dialog->RetSceneName();
- rank = m_dialog->RetSceneRank();
-
- strcpy(fn, filename);
- ldir = SearchLastDir(fn);
- if ( ldir == 0 ) return;
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- if ( brain->RetCompile(i) ) continue;
-//? if ( brain->ProgramExist(i) ) continue;
-
- sprintf(ldir, "\\prog%.3d%.1d.txt", objRank, i);
- brain->ReadProgram(i, fn);
- if ( !brain->RetCompile(i) ) nbError++;
- }
-}
-
-// Saves all programs of all the robots.
-
-void CRobotMain::SaveAllScript()
-{
- CObject* pObj;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- SaveOneScript(pObj);
- }
-}
-
-// Saves all programs of the robot.
-// If a program does not exist, the corresponding file is destroyed.
-
-void CRobotMain::SaveOneScript(CObject *pObj)
-{
- ObjectType type;
- CBrain* brain;
- char filename[_MAX_FNAME];
- char* name;
- int rank, i, objRank;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) return;
-
- if ( !IsSelectable(pObj) ) return;
-
- type = pObj->RetType();
- if ( type == OBJECT_HUMAN ) return;
-
- objRank = pObj->RetDefRank();
- if ( objRank == -1 ) return;
-
- name = m_dialog->RetSceneName();
- rank = m_dialog->RetSceneRank();
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- sprintf(filename, "%s\\%s\\%c%.3d%.3d%.1d.txt",
- RetSavegameDir(), m_gamerName, name[0], rank, objRank, i);
- brain->WriteProgram(i, filename);
- }
-}
-
-// Saves all programs of the robot.
-// If a program does not exist, the corresponding file is destroyed.
-
-void CRobotMain::SaveFileScript(CObject *pObj, char* filename, int objRank)
-{
- ObjectType type;
- CBrain* brain;
- char fn[_MAX_FNAME];
- char* ldir;
- char* name;
- int rank, i;
-
- if ( objRank == -1 ) return;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) return;
-
- type = pObj->RetType();
- if ( type == OBJECT_HUMAN ) return;
-
- name = m_dialog->RetSceneName();
- rank = m_dialog->RetSceneRank();
-
- strcpy(fn, filename);
- ldir = SearchLastDir(fn);
- if ( ldir == 0 ) return;
-
- for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
- {
- sprintf(ldir, "\\prog%.3d%.1d.txt", objRank, i);
- brain->WriteProgram(i, fn);
- }
-}
-
-// Saves the stack of the program in execution of a robot.
-
-bool CRobotMain::SaveFileStack(CObject *pObj, FILE *file, int objRank)
-{
- ObjectType type;
- CBrain* brain;
-
- if ( objRank == -1 ) return true;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) return true;
-
- type = pObj->RetType();
- if ( type == OBJECT_HUMAN ) return true;
-
- return brain->WriteStack(file);
-}
-
-// Resumes the execution stack of the program in a robot.
-
-bool CRobotMain::ReadFileStack(CObject *pObj, FILE *file, int objRank)
-{
- ObjectType type;
- CBrain* brain;
-
- if ( objRank == -1 ) return true;
-
- brain = pObj->RetBrain();
- if ( brain == 0 ) return true;
-
- type = pObj->RetType();
- if ( type == OBJECT_HUMAN ) return true;
-
- return brain->ReadStack(file);
-}
-
-
-// Empty the list.
-
-bool CRobotMain::FlushNewScriptName()
-{
- int i;
-
- for ( i=0 ; i<MAXNEWSCRIPTNAME ; i++ )
- {
- m_newScriptName[i].bUsed = false;
- }
- return true;
-}
-
-// Adds a script name.
-
-bool CRobotMain::AddNewScriptName(ObjectType type, char *name)
-{
- int i;
-
- for ( i=0 ; i<MAXNEWSCRIPTNAME ; i++ )
- {
- if ( !m_newScriptName[i].bUsed )
- {
- m_newScriptName[i].bUsed = true;
- m_newScriptName[i].type = type;
- strcpy(m_newScriptName[i].name, name);
- return true;
- }
- }
- return false;
-}
-
-// Seeks a script name for a given type.
-
-char* CRobotMain::RetNewScriptName(ObjectType type, int rank)
-{
- int i;
-
- for ( i=0 ; i<MAXNEWSCRIPTNAME ; i++ )
- {
- if ( m_newScriptName[i].bUsed &&
- (m_newScriptName[i].type == type ||
- m_newScriptName[i].type == OBJECT_NULL ) )
- {
- if ( rank == 0 ) return m_newScriptName[i].name;
- else rank --;
- }
- }
-
- return 0;
-}
-
-
-// Seeks if an object occupies in a spot, to prevent a backup of the game.
-
-bool CRobotMain::IsBusy()
-{
- CObject* pObj;
- CBrain* pBrain;
-//? CAuto* pAuto;
- int i;
-
- if ( m_CompteurFileOpen > 0 ) return true;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- pBrain = pObj->RetBrain();
- if ( pBrain != 0 )
- {
- if ( pBrain->IsBusy() ) return true;
- }
-
-//? pAuto = pObj->RetAuto();
-//? if ( pAuto != 0 )
-//? {
-//? if ( pAuto->RetBusy() ) return true;
-//? }
- }
- return false;
-}
-
-// Writes an object into the backup file.
-
-void CRobotMain::IOWriteObject(FILE *file, CObject* pObj, char *cmd)
-{
- Math::Vector pos;
- CBrain* pBrain;
- char line[3000];
- char name[100];
- int run, i;
-
- if ( pObj->RetType() == OBJECT_FIX ) return;
-
- strcpy(line, cmd);
-
- sprintf(name, " type=%s", GetTypeObject(pObj->RetType()));
- strcat(line, name);
-
- sprintf(name, " id=%d", pObj->RetID());
- strcat(line, name);
-
- pos = pObj->RetPosition(0)/g_unit;
- sprintf(name, " pos=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
- strcat(line, name);
-
- pos = pObj->RetAngle(0)/(Math::PI/180.0f);
- sprintf(name, " angle=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
- strcat(line, name);
-
- pos = pObj->RetZoom(0);
- sprintf(name, " zoom=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
- strcat(line, name);
-
- for ( i=1 ; i<OBJECTMAXPART ; i++ )
- {
- if ( pObj->RetObjectRank(i) == -1 ) continue;
-
- pos = pObj->RetPosition(i);
- if ( pos.x != 0.0f || pos.y != 0.0f || pos.z != 0.0f )
- {
- pos /= g_unit;
- sprintf(name, " p%d=%.2f;%.2f;%.2f", i, pos.x, pos.y, pos.z);
- strcat(line, name);
- }
-
- pos = pObj->RetAngle(i);
- if ( pos.x != 0.0f || pos.y != 0.0f || pos.z != 0.0f )
- {
- pos /= (Math::PI/180.0f);
- sprintf(name, " a%d=%.2f;%.2f;%.2f", i, pos.x, pos.y, pos.z);
- strcat(line, name);
- }
-
- pos = pObj->RetZoom(i);
- if ( pos.x != 1.0f || pos.y != 1.0f || pos.z != 1.0f )
- {
- sprintf(name, " z%d=%.2f;%.2f;%.2f", i, pos.x, pos.y, pos.z);
- strcat(line, name);
- }
- }
-
- sprintf(name, " trainer=%d", pObj->RetTrainer());
- strcat(line, name);
-
- sprintf(name, " option=%d", pObj->RetOption());
- strcat(line, name);
-
- if ( pObj == m_infoObject ) // selects object?
- {
- sprintf(name, " select=1");
- strcat(line, name);
- }
-
- pObj->Write(line);
-
- if ( pObj->RetType() == OBJECT_BASE )
- {
- sprintf(name, " run=3"); // stops and open (PARAM_FIXSCENE)
- strcat(line, name);
- }
-
- pBrain = pObj->RetBrain();
- if ( pBrain != 0 )
- {
- run = pBrain->RetProgram();
- if ( run != -1 )
- {
- sprintf(name, " run=%d", run+1);
- strcat(line, name);
- }
- }
-
- strcat(line, "\n");
- fputs(line, file);
-}
-
-// Saves the current game.
-
-bool CRobotMain::IOWriteScene(char *filename, char *filecbot, char *info)
-{
- FILE* file;
- char line[500];
- char* name;
- CObject *pObj, *pPower, *pFret;
- float sleep, delay, magnetic, progress;
- int i, objRank;
- long version;
-
- file = fopen(filename, "w");
- if ( file == NULL ) return false;
-
- sprintf(line, "Title text=\"%s\"\n", info);
- fputs(line, file);
-
- sprintf(line, "Version maj=%d min=%d\n", 0, 1);
- fputs(line, file);
-
- name = m_dialog->RetSceneName();
- if ( strcmp(name, "user") == 0 )
- {
- sprintf(line, "Mission base=\"%s\" rank=%.3d dir=\"%s\"\n", name, m_dialog->RetSceneRank(), m_dialog->RetSceneDir());
- }
- else
- {
- sprintf(line, "Mission base=\"%s\" rank=%.3d\n", name, m_dialog->RetSceneRank());
- }
- fputs(line, file);
-
- sprintf(line, "Map zoom=%.2f\n", m_map->RetZoomMap());
- fputs(line, file);
-
- sprintf(line, "DoneResearch bits=%d\n", g_researchDone);
- fputs(line, file);
-
- if ( m_blitz->GetStatus(sleep, delay, magnetic, progress) )
- {
- sprintf(line, "BlitzMode sleep=%.2f delay=%.2f magnetic=%.2f progress=%.2f\n", sleep, delay, magnetic/g_unit, progress);
- fputs(line, file);
- }
-
- objRank = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetType() == OBJECT_TOTO ) continue;
- if ( pObj->RetType() == OBJECT_FIX ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
- if ( pObj->RetBurn() ) continue;
- if ( pObj->RetDead() ) continue;
- if ( pObj->RetExplo() ) continue;
-
- pPower = pObj->RetPower();
- pFret = pObj->RetFret();
-
- if ( pFret != 0 ) // object transported?
- {
- IOWriteObject(file, pFret, "CreateFret");
- }
-
- if ( pPower != 0 ) // battery transported?
- {
- IOWriteObject(file, pPower, "CreatePower");
- }
-
- IOWriteObject(file, pObj, "CreateObject");
-
- SaveFileScript(pObj, filename, objRank++);
- }
- fclose(file);
-
-#if CBOT_STACK
- // Writes the file of stacks of execution.
- file = fOpen(filecbot, "wb");
- if ( file == NULL ) return false;
-
- version = 1;
- fWrite(&version, sizeof(long), 1, file); // version of COLOBOT
- version = CBotProgram::GivVersion();
- fWrite(&version, sizeof(long), 1, file); // version of CBOT
-
- objRank = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetType() == OBJECT_TOTO ) continue;
- if ( pObj->RetType() == OBJECT_FIX ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
- if ( pObj->RetBurn() ) continue;
- if ( pObj->RetDead() ) continue;
-
- if ( !SaveFileStack(pObj, file, objRank++) ) break;
- }
- CBotClass::SaveStaticState(file);
- fClose(file);
-#endif
-
- m_delayWriteMessage = 4; // displays message in 3 frames
- return true;
-}
-
-// Resumes the game.
-
-CObject* CRobotMain::IOReadObject(char *line, char* filename, int objRank)
-{
- CObject* pObj;
-//? CBrain* pBrain;
- CAuto* pAuto;
- Math::Vector pos, dir, zoom;
- ObjectType type;
- int id, run, trainer, toy, option, i;
- char op[10];
-
- pos = OpDir(line, "pos")*g_unit;
- dir = OpDir(line, "angle")*(Math::PI/180.0f);
- zoom = OpDir(line, "zoom");
- type = OpTypeObject(line, "type", OBJECT_NULL);
- id = OpInt(line, "id", 0);
- if ( type == OBJECT_NULL ) return 0;
- trainer = OpInt(line, "trainer", 0);
- toy = OpInt(line, "toy", 0);
- option = OpInt(line, "option", 0);
- pObj = CreateObject(pos, dir.y, 1.0f, 0.0f, type, 0.0f, trainer, toy, option);
- pObj->SetDefRank(objRank);
- pObj->SetPosition(0, pos);
- pObj->SetAngle(0, dir);
- pObj->SetID(id);
- if ( g_id < id ) g_id = id;
-
- if ( zoom.x != 0.0f || zoom.y != 0.0f || zoom.z != 0.0f )
- {
- pObj->SetZoom(0, zoom);
- }
-
- for ( i=1 ; i<OBJECTMAXPART ; i++ )
- {
- if ( pObj->RetObjectRank(i) == -1 ) continue;
-
- sprintf(op, "p%d", i);
- pos = OpDir(line, op);
- if ( pos.x != 0.0f || pos.y != 0.0f || pos.z != 0.0f )
- {
- pObj->SetPosition(i, pos*g_unit);
- }
-
- sprintf(op, "a%d", i);
- dir = OpDir(line, op);
- if ( dir.x != 0.0f || dir.y != 0.0f || dir.z != 0.0f )
- {
- pObj->SetAngle(i, dir*(Math::PI/180.0f));
- }
-
- sprintf(op, "z%d", i);
- zoom = OpDir(line, op);
- if ( zoom.x != 0.0f || zoom.y != 0.0f || zoom.z != 0.0f )
- {
- pObj->SetZoom(i, zoom);
- }
- }
-
- if ( type == OBJECT_BASE ) m_bBase = true;
-
- pObj->Read(line);
-
-#if CBOT_STACK
-#else
- LoadFileScript(pObj, filename, objRank, i);
-#endif
-
- run = OpInt(line, "run", -1);
- if ( run != -1 )
- {
-#if CBOT_STACK
-#else
- pBrain = pObj->RetBrain();
- if ( pBrain != 0 )
- {
- pBrain->RunProgram(run-1); // starts the program
- }
-#endif
-
- pAuto = pObj->RetAuto();
- if ( pAuto != 0 )
- {
- pAuto->Start(run); // starts the film
- }
- }
-
- return pObj;
-}
-
-// Resumes some part of the game.
-
-CObject* CRobotMain::IOReadScene(char *filename, char *filecbot)
-{
- FILE* file;
- CObject *pObj, *pPower, *pFret, *pSel;
- char line[3000];
- float sleep, delay, progress, magnetic;
- int i, objRank, nbError, lastError;
- long version;
-
- m_bBase = false;
-
- file = fopen(filename, "r");
- if ( file == NULL ) return 0;
-
- pFret = 0;
- pPower = 0;
- pSel = 0;
- objRank = 0;
- while ( fgets(line, 3000, file) != NULL )
- {
- for ( i=0 ; i<3000 ; i++ )
- {
- if ( line[i] == '\t' ) line[i] = ' '; // replace tab by space
- if ( line[i] == '/' && line[i+1] == '/' )
- {
- line[i] = 0;
- break;
- }
- }
-
- if ( Cmd(line, "Map") )
- {
- m_map->ZoomMap(OpFloat(line, "zoom", 1.0f));
- }
-
- if ( Cmd(line, "DoneResearch") )
- {
- g_researchDone = OpInt(line, "bits", 0);
- }
-
- if ( Cmd(line, "BlitzMode") )
- {
- sleep = OpFloat(line, "sleep", 0.0f);
- delay = OpFloat(line, "delay", 3.0f);
- magnetic = OpFloat(line, "magnetic", 50.0f)*g_unit;
- progress = OpFloat(line, "progress", 0.0f);
- m_blitz->SetStatus(sleep, delay, magnetic, progress);
- }
-
- if ( Cmd(line, "CreateFret") )
- {
- pFret = IOReadObject(line, filename, -1);
- }
-
- if ( Cmd(line, "CreatePower") )
- {
- pPower = IOReadObject(line, filename, -1);
- }
-
- if ( Cmd(line, "CreateObject") )
- {
- pObj = IOReadObject(line, filename, objRank++);
-
- if ( OpInt(line, "select", 0) )
- {
- pSel = pObj;
- }
-
- if ( pFret != 0 )
- {
- CTaskManip* task;
-
- pObj->SetFret(pFret);
- task = new CTaskManip(m_iMan, pObj);
- task->Start(TMO_AUTO, TMA_GRAB); // holds the object!
- delete task;
- }
-
- if ( pPower != 0 )
- {
- pObj->SetPower(pPower);
- pPower->SetTruck(pObj);
- }
-
- pFret = 0;
- pPower = 0;
- }
- }
- fclose(file);
-
-#if CBOT_STACK
- // Compiles scripts.
- nbError = 0;
- do
- {
- lastError = nbError;
- nbError = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
- if ( pObj->RetTruck() != 0 ) continue;
-
- objRank = pObj->RetDefRank();
- if ( objRank == -1 ) continue;
-
- LoadFileScript(pObj, filename, objRank, nbError);
- }
- }
- while ( nbError > 0 && nbError != lastError );
-
- // Reads the file of stacks of execution.
- file = fOpen(filecbot, "rb");
- if ( file != NULL )
- {
- fRead(&version, sizeof(long), 1, file); // version of COLOBOT
- if ( version == 1 )
- {
- fRead(&version, sizeof(long), 1, file); // version of CBOT
- if ( version == CBotProgram::GivVersion() )
- {
- objRank = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetType() == OBJECT_TOTO ) continue;
- if ( pObj->RetType() == OBJECT_FIX ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
- if ( pObj->RetBurn() ) continue;
- if ( pObj->RetDead() ) continue;
-
- if ( !ReadFileStack(pObj, file, objRank++) ) break;
- }
- }
- }
- CBotClass::RestoreStaticState(file);
- fClose(file);
- }
-#endif
-
- return pSel;
-}
-
-
-// Writes the global parameters for free play.
-
-void CRobotMain::WriteFreeParam()
-{
- FILE* file;
- char filename[_MAX_FNAME];
- char line[100];
-
- m_freeResearch |= g_researchDone;
- m_freeBuild |= g_build;
-
- if ( m_gamerName[0] == 0 ) return;
-
- sprintf(filename, "%s\\%s\\research.gam", RetSavegameDir(), m_gamerName);
- file = fopen(filename, "w");
- if ( file == NULL ) return;
-
- sprintf(line, "research=%d build=%d\n", m_freeResearch, m_freeBuild);
- fputs(line, file);
- fclose(file);
-}
-
-// Reads the global parameters for free play.
-
-void CRobotMain::ReadFreeParam()
-{
- FILE* file;
- char filename[_MAX_FNAME];
- char line[100];
-
- m_freeResearch = 0;
- m_freeBuild = 0;
-
- if ( m_gamerName[0] == 0 ) return;
-
- sprintf(filename, "%s\\%s\\research.gam", RetSavegameDir(), m_gamerName);
- file = fopen(filename, "r");
- if ( file == NULL ) return;
-
- if ( fgets(line, 100, file) != NULL )
- {
- sscanf(line, "research=%d build=%d\n", &m_freeResearch, &m_freeBuild);
- }
-
- fclose(file);
-}
-
-
-// Resets all objects to their original position.
-
-void CRobotMain::ResetObject()
-{
-#if 0
- CObject* pObj;
- CObject* pTruck;
- CAuto* pAuto;
- CBrain* brain;
- CPyro* pyro;
- ResetCap cap;
- Math::Vector pos, angle;
- int i;
-
- // Removes all pyrotechnic effects in progress.
- while ( true )
- {
- pyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, 0);
- if ( pyro == 0 ) break;
-
- pyro->DeleteObject();
- delete pyro;
- }
-
- // Removes all bullets in progress.
- m_particule->DeleteParticule(PARTIGUN1);
- m_particule->DeleteParticule(PARTIGUN2);
- m_particule->DeleteParticule(PARTIGUN3);
- m_particule->DeleteParticule(PARTIGUN4);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- cap = pObj->RetResetCap();
- if ( cap == RESET_NONE ) continue;
-
- if ( cap == RESET_DELETE )
- {
- pTruck = pObj->RetTruck();
- if ( pTruck != 0 )
- {
- pTruck->SetFret(0);
- pObj->SetTruck(0);
- }
- pObj->DeleteObject();
- delete pObj;
- i --;
- continue;
- }
-
- pAuto = pObj->RetAuto();
- if ( pAuto != 0 )
- {
- pAuto->Abort();
- }
-
- if ( pObj->RetEnable() ) // object still active?
- {
- brain = pObj->RetBrain();
- if ( brain != 0 )
- {
- pos = pObj->RetResetPosition();
- angle = pObj->RetResetAngle();
-
- if ( pos == pObj->RetPosition(0) &&
- angle == pObj->RetAngle(0) ) continue;
- brain->StartTaskReset(pos, angle);
- continue;
- }
- }
-
- pObj->SetEnable(true); // active again
-
- pos = pObj->RetResetPosition();
- angle = pObj->RetResetAngle();
-
- if ( pos == pObj->RetPosition(0) &&
- angle == pObj->RetAngle(0) ) continue;
-
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_RESET, pObj);
-
- brain = pObj->RetBrain();
- if ( brain != 0 )
- {
- brain->RunProgram(pObj->RetResetRun());
- }
- }
-#else
- m_bResetCreate = true;
-#endif
-}
-
-// Resets all objects to their original position.
-
-void CRobotMain::ResetCreate()
-{
- CObject* pObj;
- CPyro* pyro;
- ResetCap cap;
- int i;
-
- SaveAllScript();
-
- // Removes all bullets in progress.
- m_particule->DeleteParticule(PARTIGUN1);
- m_particule->DeleteParticule(PARTIGUN2);
- m_particule->DeleteParticule(PARTIGUN3);
- m_particule->DeleteParticule(PARTIGUN4);
-
- DeselectAll(); // removes the control buttons
- DeleteAllObjects(); // removes all the current 3D Scene
-
- m_particule->FlushParticule();
- m_terrain->FlushBuildingLevel();
- m_iMan->Flush(CLASS_OBJECT);
- m_iMan->Flush(CLASS_PHYSICS);
- m_iMan->Flush(CLASS_BRAIN);
- m_iMan->Flush(CLASS_PYRO);
- m_camera->SetType(CAMERA_DIALOG);
-
- CreateScene(m_dialog->RetSceneSoluce(), false, true);
-
- if ( !RetNiceReset() ) return;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- cap = pObj->RetResetCap();
- if ( cap == RESET_NONE ) continue;
-
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_RESET, pObj);
- }
-}
-
-// Checks if the mission is over.
-
-Error CRobotMain::CheckEndMission(bool bFrame)
-{
- CObject* pObj;
- Math::Vector bPos, oPos;
- ObjectType type;
- int t, i, nb;
-
- for ( t=0 ; t<m_endTakeTotal ; t++ )
- {
- if ( m_endTake[t].message[0] != 0 ) continue;
-
- bPos = m_endTake[t].pos;
- bPos.y = 0.0f;
-
- nb = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- // Do not use RetActif () because an invisible worm (underground)
- // should be regarded as existing here!
- if ( pObj->RetLock() ) continue;
- if ( pObj->RetRuin() ) continue;
- if ( !pObj->RetEnable() ) continue;
-
- type = pObj->RetType();
- if ( type == OBJECT_SCRAP2 ||
- type == OBJECT_SCRAP3 ||
- type == OBJECT_SCRAP4 ||
- type == OBJECT_SCRAP5 ) // wastes?
- {
- type = OBJECT_SCRAP1;
- }
- if ( type != m_endTake[t].type ) continue;
-
- if ( pObj->RetTruck() == 0 )
- {
- oPos = pObj->RetPosition(0);
- }
- else
- {
- oPos = pObj->RetTruck()->RetPosition(0);
- }
- oPos.y = 0.0f;
- if ( Math::DistanceProjected(oPos, bPos) <= m_endTake[t].dist )
- {
- nb ++;
- }
- }
-
- if ( nb <= m_endTake[t].lost )
- {
- if ( m_endTake[t].type == OBJECT_HUMAN )
- {
- if ( m_lostDelay == 0.0f )
- {
- m_lostDelay = 0.1f; // lost immediately
- m_winDelay = 0.0f;
- }
- m_displayText->SetEnable(false);
- return INFO_LOSTq;
- }
- else
- {
- if ( m_lostDelay == 0.0f )
- {
- m_displayText->DisplayError(INFO_LOST, Math::Vector(0.0f,0.0f,0.0f));
- m_lostDelay = m_endTakeLostDelay; // lost in 6 seconds
- m_winDelay = 0.0f;
- }
- m_displayText->SetEnable(false);
- return INFO_LOST;
- }
- }
- if ( nb < m_endTake[t].min ||
- nb > m_endTake[t].max )
- {
- m_displayText->SetEnable(true);
- return ERR_MISSION_NOTERM;
- }
- if ( m_endTake[t].bImmediat )
- {
- if ( m_winDelay == 0.0f )
- {
- m_winDelay = m_endTakeWinDelay; // wins in x seconds
- m_lostDelay = 0.0f;
- }
- m_displayText->SetEnable(false);
- return ERR_OK; // mission ended
- }
- }
-
- if ( m_endTakeResearch != 0 )
- {
- if ( m_endTakeResearch != (m_endTakeResearch&g_researchDone) )
- {
- m_displayText->SetEnable(true);
- return ERR_MISSION_NOTERM;
- }
- }
-
- if ( m_endTakeWinDelay == -1.0f )
- {
- m_winDelay = 1.0f; // wins in one second
- m_lostDelay = 0.0f;
- m_displayText->SetEnable(false);
- return ERR_OK; // mission ended
- }
-
- if ( bFrame && m_bBase ) return ERR_MISSION_NOTERM;
-
- if ( m_winDelay == 0.0f )
- {
- m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f));
- m_winDelay = m_endTakeWinDelay; // wins in two seconds
- m_lostDelay = 0.0f;
- }
- m_displayText->SetEnable(false);
- return ERR_OK; // mission ended
-}
-
-// Checks if the mission is finished after displaying a message.
-
-void CRobotMain::CheckEndMessage(char *message)
-{
- int t;
-
- for ( t=0 ; t<m_endTakeTotal ; t++ )
- {
- if ( m_endTake[t].message[0] == 0 ) continue;
-
- if ( strcmp(m_endTake[t].message, message) == 0 )
- {
- m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f));
- m_winDelay = m_endTakeWinDelay; // wins in 2 seconds
- m_lostDelay = 0.0f;
- }
- }
-}
-
-
-// Returns the number of instructions required.
-
-int CRobotMain::RetObligatoryToken()
-{
- return m_obligatoryTotal;
-}
-
-// Returns the name of a required instruction.
-
-char* CRobotMain::RetObligatoryToken(int i)
-{
- return m_obligatoryToken[i];
-}
-
-// Checks if an instruction is part of the obligatory list.
-
-int CRobotMain::IsObligatoryToken(char *token)
-{
- int i;
-
- for ( i=0 ; i<m_obligatoryTotal ; i++ )
- {
- if ( strcmp(token, m_obligatoryToken[i]) == 0 )
- {
- return i;
- }
- }
- return -1;
-}
-
-// Checks if an instruction is not part of the banned list.
-
-bool CRobotMain::IsProhibitedToken(char *token)
-{
- int i;
-
- for ( i=0 ; i<m_prohibitedTotal ; i++ )
- {
- if ( strcmp(token, m_prohibitedToken[i]) == 0 )
- {
- return false;
- }
- }
- return true;
-}
-
-
-// Indicates whether it is possible to control a driving robot.
-
-bool CRobotMain::RetTrainerPilot()
-{
- return m_bTrainerPilot;
-}
-
-// Indicates whether the scene is fixed, without interaction.
-
-bool CRobotMain::RetFixScene()
-{
- return m_bFixScene;
-}
-
-
-char* CRobotMain::RetTitle()
-{
- return m_title;
-}
-
-char* CRobotMain::RetResume()
-{
- return m_resume;
-}
-
-char* CRobotMain::RetScriptName()
-{
- return m_scriptName;
-}
-
-char* CRobotMain::RetScriptFile()
-{
- return m_scriptFile;
-}
-
-
-bool CRobotMain::RetGlint()
-{
- return m_dialog->RetGlint();
-}
-
-bool CRobotMain::RetSoluce4()
-{
- return m_dialog->RetSoluce4();
-}
-
-bool CRobotMain::RetMovies()
-{
- return m_dialog->RetMovies();
-}
-
-bool CRobotMain::RetNiceReset()
-{
- return m_dialog->RetNiceReset();
-}
-
-bool CRobotMain::RetHimselfDamage()
-{
- return m_dialog->RetHimselfDamage();
-}
-
-bool CRobotMain::RetShowSoluce()
-{
- return m_bShowSoluce;
-}
-
-bool CRobotMain::RetSceneSoluce()
-{
- if ( m_infoFilename[SATCOM_SOLUCE][0] == 0 ) return false;
- return m_dialog->RetSceneSoluce();
-}
-
-bool CRobotMain::RetShowAll()
-{
- return m_bShowAll;
-}
-
-bool CRobotMain::RetCheatRadar()
-{
- return m_bCheatRadar;
-}
-
-char* CRobotMain::RetSavegameDir()
-{
- return m_dialog->RetSavegameDir();
-}
-
-char* CRobotMain::RetPublicDir()
-{
- return m_dialog->RetPublicDir();
-}
-
-char* CRobotMain::RetFilesDir()
-{
- return m_dialog->RetFilesDir();
-}
-
-
-// Change the player's name.
-
-void CRobotMain::SetGamerName(char *name)
-{
- strcpy(m_gamerName, name);
- SetGlobalGamerName(m_gamerName);
- ReadFreeParam();
-}
-
-// Gives the player's name.
-
-char* CRobotMain::RetGamerName()
-{
- return m_gamerName;
-}
-
-
-// Returns the representation to use for the player.
-
-int CRobotMain::RetGamerFace()
-{
- return m_dialog->RetGamerFace();
-}
-
-// Returns the representation to use for the player.
-
-int CRobotMain::RetGamerGlasses()
-{
- return m_dialog->RetGamerGlasses();
-}
-
-// Returns the mode with just the head.
-
-bool CRobotMain::RetGamerOnlyHead()
-{
- return m_dialog->RetGamerOnlyHead();
-}
-
-// Returns the angle of presentation.
-
-float CRobotMain::RetPersoAngle()
-{
- return m_dialog->RetPersoAngle();
-}
-
-
-// Changes on the pause mode.
-
-void CRobotMain::ChangePause(bool bPause)
-{
- m_bPause = bPause;
- m_engine->SetPause(m_bPause);
-
- m_sound->MuteAll(m_bPause);
- CreateShortcuts();
- if ( m_bPause ) HiliteClear();
-}
-
-
-// Changes game speed
-
-void CRobotMain::SetSpeed(float speed)
-{
- CButton* pb;
- char text[10];
-
- m_engine->SetSpeed(speed);
-
- pb = (CButton*)m_interface->SearchControl(EVENT_SPEED);
- if ( pb != 0 )
- {
- if ( speed == 1.0f )
- {
- pb->ClearState(STATE_VISIBLE);
- }
- else
- {
- sprintf(text, "x%.1f", speed);
- pb->SetName(text);
- pb->SetState(STATE_VISIBLE);
- }
- }
-}
-
-float CRobotMain::RetSpeed()
-{
- return m_engine->RetSpeed();
-}
-
-
-// Creates interface shortcuts to the units.
-
-bool CRobotMain::CreateShortcuts()
-{
- if ( m_phase != PHASE_SIMUL ) return false;
- if ( !m_bShortCut ) return false;
- return m_short->CreateShortcuts();
-}
-
-// Updates the map.
-
-void CRobotMain::UpdateMap()
-{
- m_map->UpdateMap();
-}
-
-// Indicates whether the mini-map is visible.
-
-bool CRobotMain::RetShowMap()
-{
- return m_map->RetShowMap() && m_bMapShow;
-}
-
-
-// Management of the lock mode for movies.
-
-void CRobotMain::SetMovieLock(bool bLock)
-{
- m_bMovieLock = bLock;
- m_engine->SetMovieLock(m_bMovieLock);
-
- CreateShortcuts();
- m_map->ShowMap(!m_bMovieLock && m_bMapShow);
- if ( m_bMovieLock ) HiliteClear();
- m_engine->SetMouseHide(m_bMovieLock);
-}
-
-bool CRobotMain::RetMovieLock()
-{
- return m_bMovieLock;
-}
-
-bool CRobotMain::RetInfoLock()
-{
- return ( m_displayInfo != 0 ); // info in progress?
-}
-
-// Management of the blocking of the call of SatCom.
-
-void CRobotMain::SetSatComLock(bool bLock)
-{
- m_bSatComLock = bLock;
-}
-
-bool CRobotMain::RetSatComLock()
-{
- return m_bSatComLock;
-}
-
-// Management of the lock mode for the edition.
-
-void CRobotMain::SetEditLock(bool bLock, bool bEdit)
-{
- m_bEditLock = bLock;
-
- CreateShortcuts();
-
- // Do not remove the card if it contains a still image.
- if ( !bLock || !m_map->RetFixImage() )
- {
- m_map->ShowMap(!m_bEditLock && m_bMapShow);
- }
-
- m_displayText->HideText(bLock);
- m_engine->FlushPressKey();
-
- if ( m_bEditLock )
- {
- HiliteClear();
- }
- else
- {
- m_bEditFull = false;
- }
-}
-
-bool CRobotMain::RetEditLock()
-{
- return m_bEditLock;
-}
-
-// Management of the fullscreen mode during editing.
-
-void CRobotMain::SetEditFull(bool bFull)
-{
- m_bEditFull = bFull;
-}
-
-bool CRobotMain::RetEditFull()
-{
- return m_bEditFull;
-}
-
-
-bool CRobotMain::RetFreePhoto()
-{
- return m_bFreePhoto;
-}
-
-
-// Indicates whether mouse is on an friend object, on which we should not shoot.
-
-void CRobotMain::SetFriendAim(bool bFriend)
-{
- m_bFriendAim = bFriend;
-}
-
-bool CRobotMain::RetFriendAim()
-{
- return m_bFriendAim;
-}
-
-
-// Management of the precision of drawing the ground.
-
-void CRobotMain::SetTracePrecision(float factor)
-{
- m_engine->SetTracePrecision(factor);
-}
-
-float CRobotMain::RetTracePrecision()
-{
- return m_engine->RetTracePrecision();
-}
-
-
-// Starts music with a mission.
-
-void CRobotMain::StartMusic()
-{
- if ( m_audioTrack != 0 )
- {
- m_sound->StopMusic();
- m_sound->PlayMusic(m_audioTrack, m_bAudioRepeat);
- }
-}
-
-// Removes hilite and tooltip.
-
-void CRobotMain::ClearInterface()
-{
- HiliteClear(); // removes setting evidence
- m_tooltipName[0] = 0; // really removes the tooltip
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// robotmain.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "CBot/CBotDll.h"
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "math/conv.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/language.h"
+#include "common/global.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/profile.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "old/math3d.h"
+#include "old/light.h"
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "old/cloud.h"
+#include "old/blitz.h"
+#include "old/planet.h"
+#include "object/object.h"
+#include "object/motion/motion.h"
+#include "object/motion/motiontoto.h"
+#include "object/motion/motionhuman.h"
+#include "physics/physics.h"
+#include "object/brain.h"
+#include "old/pyro.h"
+#include "old/modfile.h"
+#include "old/model.h"
+#include "old/camera.h"
+#include "object/task/task.h"
+#include "object/task/taskmanip.h"
+#include "object/task/taskbuild.h"
+#include "object/auto/auto.h"
+#include "object/auto/autobase.h"
+#include "ui/displayinfo.h"
+#include "ui/interface.h"
+#include "ui/shortcut.h"
+#include "ui/map.h"
+#include "ui/label.h"
+#include "ui/button.h"
+#include "ui/slider.h"
+#include "ui/window.h"
+#include "ui/edit.h"
+#include "ui/displaytext.h"
+#include "old/text.h"
+#include "old/sound.h"
+#include "script/cbottoken.h"
+#include "script/cmdtoken.h"
+#include "object/mainmovie.h"
+#include "ui/maindialog.h"
+#include "ui/mainshort.h"
+#include "ui/mainmap.h"
+#include "script/script.h"
+#include "object/robotmain.h"
+
+
+
+#define CBOT_STACK true // saves the stack of programs CBOT
+const float UNIT = 4.0f;
+
+
+
+// Global variables.
+
+long g_id; // unique identifier
+long g_build; // constructible buildings
+long g_researchDone; // research done
+long g_researchEnable; // research available
+float g_unit; // conversion factor
+
+
+
+#include "script/ClassFILE.cpp"
+
+
+
+// Compilation of class "point".
+
+CBotTypResult cPoint(CBotVar* pThis, CBotVar* &var)
+{
+ if ( !pThis->IsElemOfClass("point") ) return CBotTypResult(CBotErrBadNum);
+
+ if ( var == NULL ) return CBotTypResult(0); // ok if no parameter
+
+ // First parameter (x):
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ // Second parameter (y):
+ if ( var == NULL ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ // Third parameter (z):
+ if ( var == NULL ) // only 2 parameters?
+ {
+ return CBotTypResult(0); // this function returns void
+ }
+
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+ if ( var != NULL ) return CBotTypResult(CBotErrOverParam);
+
+ return CBotTypResult(0); // this function returns void
+}
+
+//Execution of the class "point".
+
+bool rPoint(CBotVar* pThis, CBotVar* var, CBotVar* pResult, int& Exception)
+{
+ CBotVar *pX, *pY, *pZ;
+
+ if ( var == NULL ) return true; // constructor with no parameters is ok
+
+ if ( var->GivType() > CBotTypDouble )
+ {
+ Exception = CBotErrBadNum; return false;
+ }
+
+ pX = pThis->GivItem("x");
+ if ( pX == NULL )
+ {
+ Exception = CBotErrUndefItem; return false;
+ }
+ pX->SetValFloat( var->GivValFloat() );
+ var = var->GivNext();
+
+ if ( var == NULL )
+ {
+ Exception = CBotErrLowParam; return false;
+ }
+
+ if ( var->GivType() > CBotTypDouble )
+ {
+ Exception = CBotErrBadNum; return false;
+ }
+
+ pY = pThis->GivItem("y");
+ if ( pY == NULL )
+ {
+ Exception = CBotErrUndefItem; return false;
+ }
+ pY->SetValFloat( var->GivValFloat() );
+ var = var->GivNext();
+
+ if ( var == NULL )
+ {
+ return true; // ok with only two parameters
+ }
+
+ pZ = pThis->GivItem("z");
+ if ( pZ == NULL )
+ {
+ Exception = CBotErrUndefItem; return false;
+ }
+ pZ->SetValFloat( var->GivValFloat() );
+ var = var->GivNext();
+
+ if ( var != NULL )
+ {
+ Exception = CBotErrOverParam; return false;
+ }
+
+ return true; // no interruption
+}
+
+
+
+
+// Constructor of robot application.
+
+CRobotMain::CRobotMain(CInstanceManager* iMan)
+{
+ ObjectType type;
+ float fValue;
+ int iValue, i;
+ char* token;
+
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_MAIN, this);
+
+ m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ m_cloud = (CCloud*)m_iMan->SearchInstance(CLASS_CLOUD);
+ m_blitz = (CBlitz*)m_iMan->SearchInstance(CLASS_BLITZ);
+ m_planet = (CPlanet*)m_iMan->SearchInstance(CLASS_PLANET);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+
+ m_interface = new CInterface(m_iMan);
+ m_terrain = new CTerrain(m_iMan);
+ m_model = new CModel(m_iMan);
+ m_camera = new CCamera(m_iMan);
+ m_displayText = new CDisplayText(m_iMan);
+ m_movie = new CMainMovie(m_iMan);
+ m_dialog = new CMainDialog(m_iMan);
+ m_short = new CMainShort(m_iMan);
+ m_map = new CMainMap(m_iMan);
+ m_displayInfo = 0;
+
+ m_engine->SetTerrain(m_terrain);
+ m_filesDir = m_dialog->RetFilesDir();
+
+ m_time = 0.0f;
+ m_gameTime = 0.0f;
+ m_checkEndTime = 0.0f;
+
+ m_phase = PHASE_NAME;
+ m_cameraRank = -1;
+ m_visitLast = EVENT_NULL;
+ m_visitObject = 0;
+ m_visitArrow = 0;
+ m_audioTrack = 0;
+ m_bAudioRepeat = true;
+ m_delayWriteMessage = 0;
+ m_selectObject = 0;
+ m_infoUsed = 0;
+
+ m_bBeginSatCom = false;
+ m_bMovieLock = false;
+ m_bSatComLock = false;
+ m_bEditLock = false;
+ m_bEditFull = false;
+ m_bPause = false;
+ m_bHilite = false;
+ m_bFreePhoto = false;
+ m_bShowPos = false;
+ m_bSelectInsect = false;
+ m_bShowSoluce = false;
+ m_bShowAll = false;
+ m_bCheatRadar = false;
+ m_bFixScene = false;
+ m_bTrainerPilot = false;
+ m_bSuspend = false;
+ m_bFriendAim = false;
+ m_bResetCreate = false;
+ m_bShortCut = true;
+
+ m_engine->SetMovieLock(m_bMovieLock);
+
+ m_movie->Flush();
+ m_movieInfoIndex = -1;
+
+ m_tooltipPos = Math::Point(0.0f, 0.0f);
+ m_tooltipName[0] = 0;
+ m_tooltipTime = 0.0f;
+
+ m_endingWinRank = 0;
+ m_endingLostRank = 0;
+ m_bWinTerminate = false;
+
+ FlushDisplayInfo();
+
+ m_fontSize = 9.0f;
+ m_windowPos = Math::Point(0.15f, 0.17f);
+ m_windowDim = Math::Point(0.70f, 0.66f);
+
+ if ( GetProfileFloat("Edit", "FontSize", fValue) ) m_fontSize = fValue;
+ if ( GetProfileFloat("Edit", "WindowPos.x", fValue) ) m_windowPos.x = fValue;
+ if ( GetProfileFloat("Edit", "WindowPos.y", fValue) ) m_windowPos.y = fValue;
+ if ( GetProfileFloat("Edit", "WindowDim.x", fValue) ) m_windowDim.x = fValue;
+ if ( GetProfileFloat("Edit", "WindowDim.y", fValue) ) m_windowDim.y = fValue;
+
+ m_IOPublic = false;
+ m_IODim = Math::Point(320.0f/640.0f, (121.0f+18.0f*8)/480.0f);
+ m_IOPos.x = (1.0f-m_IODim.x)/2.0f; // in the middle
+ m_IOPos.y = (1.0f-m_IODim.y)/2.0f;
+
+ if ( GetProfileInt ("Edit", "IOPublic", iValue) ) m_IOPublic = iValue;
+ if ( GetProfileFloat("Edit", "IOPos.x", fValue) ) m_IOPos.x = fValue;
+ if ( GetProfileFloat("Edit", "IOPos.y", fValue) ) m_IOPos.y = fValue;
+ if ( GetProfileFloat("Edit", "IODim.x", fValue) ) m_IODim.x = fValue;
+ if ( GetProfileFloat("Edit", "IODim.y", fValue) ) m_IODim.y = fValue;
+
+ m_short->FlushShortcuts();
+ InitEye();
+
+ m_engine->SetTracePrecision(1.0f);
+
+ m_cameraPan = 0.0f;
+ m_cameraZoom = 0.0f;
+
+ g_id = 0;
+ g_build = 0;
+ g_researchDone = 0; // no research done
+ g_researchEnable = 0;
+ g_unit = 4.0f;
+
+ m_gamerName[0] = 0;
+ GetProfileString("Gamer", "LastName", m_gamerName, 100);
+ SetGlobalGamerName(m_gamerName);
+ ReadFreeParam();
+ m_dialog->SetupRecall();
+
+ for ( i=0 ; i<MAXSHOWLIMIT ; i++ )
+ {
+ m_showLimit[i].bUsed = false;
+ m_showLimit[i].total = 0;
+ m_showLimit[i].link = 0;
+ }
+
+ CBotProgram::SetTimer(100);
+ CBotProgram::Init();
+
+ for ( i=0 ; i<OBJECT_MAX ; i++ )
+ {
+ type = (ObjectType)i;
+ token = RetObjectName(type);
+ if ( token[0] != 0 )
+ {
+ CBotProgram::DefineNum(token, type);
+ }
+ token = RetObjectAlias(type);
+ if ( token[0] != 0 )
+ {
+ CBotProgram::DefineNum(token, type);
+ }
+ }
+
+ CBotProgram::DefineNum("White", 0);
+ CBotProgram::DefineNum("Black", 1);
+ CBotProgram::DefineNum("Gray", 2);
+ CBotProgram::DefineNum("LightGray", 3);
+ CBotProgram::DefineNum("Red", 4);
+ CBotProgram::DefineNum("Pink", 5);
+ CBotProgram::DefineNum("Purple", 6);
+ CBotProgram::DefineNum("Orange", 7);
+ CBotProgram::DefineNum("Yellow", 8);
+ CBotProgram::DefineNum("Beige", 9);
+ CBotProgram::DefineNum("Brown", 10);
+ CBotProgram::DefineNum("Skin", 11);
+ CBotProgram::DefineNum("Green", 12);
+ CBotProgram::DefineNum("LightGreen", 13);
+ CBotProgram::DefineNum("Blue", 14);
+ CBotProgram::DefineNum("LightBlue", 15);
+ CBotProgram::DefineNum("BlackArrow", 16);
+ CBotProgram::DefineNum("RedArrow", 17);
+
+ CBotProgram::DefineNum("Metal", OM_METAL);
+ CBotProgram::DefineNum("Plastic", OM_PLASTIC);
+
+ CBotProgram::DefineNum("InFront", TMA_FFRONT);
+ CBotProgram::DefineNum("Behind", TMA_FBACK);
+ CBotProgram::DefineNum("EnergyCell", TMA_POWER);
+
+ CBotProgram::DefineNum("DisplayError", TT_ERROR);
+ CBotProgram::DefineNum("DisplayWarning", TT_WARNING);
+ CBotProgram::DefineNum("DisplayInfo", TT_INFO);
+ CBotProgram::DefineNum("DisplayMessage", TT_MESSAGE);
+
+ CBotProgram::DefineNum("FilterNone", FILTER_NONE);
+ CBotProgram::DefineNum("FilterOnlyLanding", FILTER_ONLYLANDING);
+ CBotProgram::DefineNum("FilterOnlyFliying", FILTER_ONLYFLYING);
+
+ // Add the class Point.
+ CBotClass* bc;
+ bc = new CBotClass("point", NULL, true); // intrinsic class
+ bc->AddItem("x", CBotTypFloat);
+ bc->AddItem("y", CBotTypFloat);
+ bc->AddItem("z", CBotTypFloat);
+ bc->AddFunction("point", rPoint, cPoint);
+
+ // Adds the class Object.
+ bc = new CBotClass("object", NULL);
+ bc->AddItem("category", CBotTypResult(CBotTypInt), PR_READ);
+ bc->AddItem("position", CBotTypResult(CBotTypClass, "point"), PR_READ);
+ bc->AddItem("orientation", CBotTypResult(CBotTypFloat), PR_READ);
+ bc->AddItem("pitch", CBotTypResult(CBotTypFloat), PR_READ);
+ bc->AddItem("roll", CBotTypResult(CBotTypFloat), PR_READ);
+ bc->AddItem("energyLevel", CBotTypResult(CBotTypFloat), PR_READ);
+ bc->AddItem("shieldLevel", CBotTypResult(CBotTypFloat), PR_READ);
+ bc->AddItem("temperature", CBotTypResult(CBotTypFloat), PR_READ);
+ bc->AddItem("altitude", CBotTypResult(CBotTypFloat), PR_READ);
+ bc->AddItem("lifeTime", CBotTypResult(CBotTypFloat), PR_READ);
+ bc->AddItem("material", CBotTypResult(CBotTypInt), PR_READ);
+ bc->AddItem("energyCell", CBotTypResult(CBotTypPointer, "object"), PR_READ);
+ bc->AddItem("load", CBotTypResult(CBotTypPointer, "object"), PR_READ);
+
+ // Initializes the class FILE.
+ InitClassFILE();
+
+ CScript::InitFonctions();
+}
+
+// Destructor of robot application.
+
+CRobotMain::~CRobotMain()
+{
+ delete m_movie;
+ delete m_dialog;
+ delete m_short;
+ delete m_map;
+ delete m_terrain;
+ delete m_model;
+}
+
+
+// Creates the file colobot.ini at the first time.
+
+void CRobotMain::CreateIni()
+{
+ int iValue;
+
+ // colobot.ini don't exist?
+ if ( !GetProfileInt("Setup", "TotoMode", iValue) )
+ {
+ m_dialog->SetupMemorize();
+ }
+}
+
+
+// Changes phase.
+
+void CRobotMain::ChangePhase(Phase phase)
+{
+ CEdit* pe;
+ CButton* pb;
+ D3DCOLORVALUE color;
+ Math::Point pos, dim, ddim;
+ float ox, oy, sx, sy;
+ char* read;
+ int rank, numTry;
+ bool bLoading;
+
+ if ( m_phase == PHASE_SIMUL ) // ends a simulation?
+ {
+ SaveAllScript();
+ m_sound->StopMusic();
+ m_camera->SetObject(0);
+
+#if _SCHOOL
+ if ( true )
+#else
+ if ( m_gameTime > 10.0f ) // did you play at least 10 seconds?
+#endif
+ {
+ rank = m_dialog->RetSceneRank();
+ numTry = m_dialog->RetGamerInfoTry(rank);
+ m_dialog->SetGamerInfoTry(rank, numTry+1);
+ m_dialog->WriteGamerInfo();
+ }
+ }
+
+ if ( phase == PHASE_WIN ) // wins a simulation?
+ {
+ rank = m_dialog->RetSceneRank();
+ m_dialog->SetGamerInfoPassed(rank, true);
+ m_dialog->NextMission(); // passes to the next mission
+ m_dialog->WriteGamerInfo();
+ }
+
+ DeleteAllObjects(); // removes all the current 3D Scene
+
+ m_phase = phase;
+ m_winDelay = 0.0f;
+ m_lostDelay = 0.0f;
+ m_bBeginSatCom = false;
+ m_bMovieLock = false;
+ m_bSatComLock = false;
+ m_bEditLock = false;
+ m_bFreePhoto = false;
+ m_bResetCreate = false;
+
+ m_engine->SetMovieLock(m_bMovieLock);
+ ChangePause(false);
+ FlushDisplayInfo();
+ m_engine->SetRankView(0);
+ m_engine->FlushObject();
+ color.r = color.g = color.b = color.a = 0.0f;
+ m_engine->SetWaterAddColor(color);
+ m_engine->SetBackground("");
+ m_engine->SetBackForce(false);
+ m_engine->SetFrontsizeName("");
+ m_engine->SetOverColor();
+ m_engine->GroundMarkDelete(0);
+ SetSpeed(1.0f);
+ m_terrain->SetWind(Math::Vector(0.0f, 0.0f, 0.0f));
+ m_terrain->FlushBuildingLevel();
+ m_terrain->FlushFlyingLimit();
+ m_light->FlushLight();
+ m_particule->FlushParticule();
+ m_water->Flush();
+ m_cloud->Flush();
+ m_blitz->Flush();
+ m_planet->Flush();
+ m_iMan->Flush(CLASS_OBJECT);
+ m_iMan->Flush(CLASS_PHYSICS);
+ m_iMan->Flush(CLASS_BRAIN);
+ m_iMan->Flush(CLASS_PYRO);
+ m_model->StopUserAction();
+ m_interface->Flush();
+ ClearInterface();
+ FlushNewScriptName();
+ m_sound->SetListener(Math::Vector(0.0f, 0.0f, 0.0f), Math::Vector(0.0f, 0.0f, 1.0f));
+ m_camera->SetType(CAMERA_DIALOG);
+ m_movie->Flush();
+ m_movieInfoIndex = -1;
+ m_cameraPan = 0.0f;
+ m_cameraZoom = 0.0f;
+ m_bShortCut = true;
+
+ // Creates and hide the command console.
+ dim.x = 200.0f/640.0f;
+ dim.y = 18.0f/480.0f;
+ pos.x = 50.0f/640.0f;
+ pos.y = 452.0f/480.0f;
+ pe = m_interface->CreateEdit(pos, dim, 0, EVENT_CMD);
+ if ( pe == 0 ) return;
+ pe->ClearState(STATE_VISIBLE);
+ m_bCmdEdit = false; // hidden for now
+
+ // Creates the speedometer.
+#if _TEEN
+ dim.x = 30.0f/640.0f;
+ dim.y = 20.0f/480.0f;
+ pos.x = 4.0f/640.0f;
+ pos.y = 454.0f/480.0f;
+#else
+ dim.x = 30.0f/640.0f;
+ dim.y = 20.0f/480.0f;
+ pos.x = 4.0f/640.0f;
+ pos.y = 426.0f/480.0f;
+#endif
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_SPEED);
+ if ( pb == 0 ) return;
+ pb->SetState(STATE_SIMPLY);
+ pb->ClearState(STATE_VISIBLE);
+
+ m_dialog->ChangePhase(m_phase);
+
+ dim.x = 32.0f/640.0f;
+ dim.y = 32.0f/480.0f;
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = (32.0f+2.0f)/640.0f;
+ sy = (32.0f+2.0f)/480.0f;
+
+ if ( m_phase != PHASE_PERSO )
+ {
+ m_engine->SetDrawWorld(true);
+ m_engine->SetDrawFront(false);
+ m_bFixScene = false;
+ }
+
+ if ( m_phase == PHASE_INIT )
+ {
+#if _NEWLOOK
+ m_engine->FreeTexture("generna.tga");
+ m_engine->FreeTexture("genernb.tga");
+ m_engine->FreeTexture("genernc.tga");
+ m_engine->FreeTexture("genernd.tga");
+#else
+#if _FRENCH
+#if _DEMO
+ m_engine->FreeTexture("genedfa.tga");
+ m_engine->FreeTexture("genedfb.tga");
+ m_engine->FreeTexture("genedfc.tga");
+ m_engine->FreeTexture("genedfd.tga");
+#else
+ m_engine->FreeTexture("generfa.tga");
+ m_engine->FreeTexture("generfb.tga");
+ m_engine->FreeTexture("generfc.tga");
+ m_engine->FreeTexture("generfd.tga");
+#endif
+#endif
+#if _ENGLISH
+#if _DEMO
+ m_engine->FreeTexture("genedea.tga");
+ m_engine->FreeTexture("genedeb.tga");
+ m_engine->FreeTexture("genedec.tga");
+ m_engine->FreeTexture("geneded.tga");
+#else
+ m_engine->FreeTexture("generea.tga");
+ m_engine->FreeTexture("genereb.tga");
+ m_engine->FreeTexture("generec.tga");
+ m_engine->FreeTexture("genered.tga");
+#endif
+#endif
+#if _GERMAN
+#if _DEMO
+ m_engine->FreeTexture("genedda.tga");
+ m_engine->FreeTexture("geneddb.tga");
+ m_engine->FreeTexture("geneddc.tga");
+ m_engine->FreeTexture("geneddd.tga");
+#else
+ m_engine->FreeTexture("generea.tga");
+ m_engine->FreeTexture("genereb.tga");
+ m_engine->FreeTexture("generec.tga");
+ m_engine->FreeTexture("genered.tga");
+#endif
+#endif
+#if _WG
+#if _DEMO
+ m_engine->FreeTexture("genedda.tga");
+ m_engine->FreeTexture("geneddb.tga");
+ m_engine->FreeTexture("geneddc.tga");
+ m_engine->FreeTexture("geneddd.tga");
+#else
+ m_engine->FreeTexture("generda.tga");
+ m_engine->FreeTexture("generdb.tga");
+ m_engine->FreeTexture("generdc.tga");
+ m_engine->FreeTexture("generdd.tga");
+#endif
+#endif
+#if _POLISH
+#if _DEMO
+ m_engine->FreeTexture("genedpa.tga");
+ m_engine->FreeTexture("genedpb.tga");
+ m_engine->FreeTexture("genedpc.tga");
+ m_engine->FreeTexture("genedpd.tga");
+#else
+ m_engine->FreeTexture("generpa.tga");
+ m_engine->FreeTexture("generpb.tga");
+ m_engine->FreeTexture("generpc.tga");
+ m_engine->FreeTexture("generpd.tga");
+#endif
+#endif
+#endif
+ }
+
+ if ( m_phase == PHASE_SIMUL )
+ {
+ m_engine->FreeTexture("inter01a.tga");
+ m_engine->FreeTexture("inter01b.tga");
+ m_engine->FreeTexture("inter01c.tga");
+ m_engine->FreeTexture("inter01d.tga");
+
+ read = m_dialog->RetSceneRead();
+ bLoading = (read[0] != 0);
+
+ m_map->CreateMap();
+ CreateScene(m_dialog->RetSceneSoluce(), false, false); // interactive scene
+ if ( m_bMapImage )
+ {
+ m_map->SetFixImage(m_mapFilename);
+ }
+
+ pos.x = 620.0f/640.0f;
+ pos.y = 460.0f/480.0f;
+ ddim.x = 20.0f/640.0f;
+ ddim.y = 20.0f/480.0f;
+ m_interface->CreateButton(pos, ddim, 11, EVENT_BUTTON_QUIT);
+
+ if ( m_bImmediatSatCom && !bLoading &&
+ m_infoFilename[SATCOM_HUSTON][0] != 0 )
+ {
+ StartDisplayInfo(SATCOM_HUSTON, false); // shows the instructions
+ }
+
+ m_sound->StopMusic();
+ if ( !m_bBase || bLoading ) StartMusic();
+ }
+
+ if ( m_phase == PHASE_WIN )
+ {
+ if ( m_endingWinRank == -1 )
+ {
+ ChangePhase(PHASE_TERM);
+ }
+ else
+ {
+#if _TEEN
+ m_bWinTerminate = (m_endingWinRank == 900);
+ m_dialog->SetSceneName("teenw");
+#else
+ m_bWinTerminate = (m_endingWinRank == 904);
+ m_dialog->SetSceneName("win");
+#endif
+ m_dialog->SetSceneRank(m_endingWinRank);
+ CreateScene(false, true, false); // sets scene
+
+ pos.x = ox+sx*1; pos.y = oy+sy*1;
+ ddim.x = dim.x*2; ddim.y = dim.y*2;
+ m_interface->CreateButton(pos, ddim, 16, EVENT_BUTTON_OK);
+
+ if ( m_bWinTerminate )
+ {
+#if _TEEN
+ pos.x = ox+sx*3; pos.y = oy+sy*1;
+ ddim.x = dim.x*15; ddim.y = dim.y*2;
+ pe = m_interface->CreateEdit(pos, ddim, 0, EVENT_EDIT0);
+ pe->SetFontType(FONT_COLOBOT);
+ pe->SetEditCap(false);
+ pe->SetHiliteCap(false);
+ pe->ReadText("help\\teenw.txt");
+#else
+ pos.x = ox+sx*3; pos.y = oy+sy*0.2f;
+ ddim.x = dim.x*15; ddim.y = dim.y*3.0f;
+ pe = m_interface->CreateEdit(pos, ddim, 0, EVENT_EDIT0);
+ pe->SetGenericMode(true);
+ pe->SetFontType(FONT_COLOBOT);
+ pe->SetEditCap(false);
+ pe->SetHiliteCap(false);
+ pe->ReadText("help\\win.txt");
+#endif
+ }
+ else
+ {
+ m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f), 15.0f, 60.0f, 1000.0f);
+ }
+ }
+ m_sound->StopAll();
+ StartMusic();
+ }
+
+ if ( m_phase == PHASE_LOST )
+ {
+ if ( m_endingLostRank == -1 )
+ {
+ ChangePhase(PHASE_TERM);
+ }
+ else
+ {
+ m_bWinTerminate = false;
+ m_dialog->SetSceneName("lost");
+ m_dialog->SetSceneRank(m_endingLostRank);
+ CreateScene(false, true, false); // sets scene
+
+ pos.x = ox+sx*1; pos.y = oy+sy*1;
+ ddim.x = dim.x*2; ddim.y = dim.y*2;
+ m_interface->CreateButton(pos, ddim, 16, EVENT_BUTTON_OK);
+ m_displayText->DisplayError(INFO_LOST, Math::Vector(0.0f,0.0f,0.0f), 15.0f, 60.0f, 1000.0f);
+ }
+ m_sound->StopAll();
+ StartMusic();
+ }
+
+ if ( m_phase == PHASE_MODEL )
+ {
+ pos.x = ox+sx*0; pos.y = oy+sy*0;
+ m_interface->CreateButton(pos, dim, 11, EVENT_BUTTON_CANCEL);
+
+ CreateModel();
+ }
+
+ if ( m_phase == PHASE_LOADING )
+ {
+ m_engine->SetMouseHide(true);
+ }
+ else
+ {
+ m_engine->SetMouseHide(false);
+ }
+
+ m_engine->LoadAllTexture();
+}
+
+
+// Processes an event.
+
+bool CRobotMain::EventProcess(const Event &event)
+{
+ CEdit* pe;
+ CObject* pObj;
+ Event newEvent;
+ MainMovieType type;
+ int i;
+
+ if ( event.event == EVENT_FRAME )
+ {
+ if ( !m_movie->EventProcess(event) ) // end of the movie?
+ {
+ type = m_movie->RetStopType();
+ if ( type == MM_SATCOMopen )
+ {
+ ChangePause(false);
+ SelectObject(m_infoObject, false); // hands over the command buttons
+ m_map->ShowMap(m_bMapShow);
+ m_displayText->HideText(false);
+ i = m_movieInfoIndex;
+ StartDisplayInfo(m_movieInfoIndex, false);
+ m_movieInfoIndex = i;
+ }
+ }
+
+ m_dialog->EventProcess(event);
+ m_displayText->EventProcess(event);
+ RemoteCamera(m_cameraPan, m_cameraZoom, event.rTime);
+
+ m_interface->EventProcess(event);
+ if ( m_displayInfo != 0 ) // current edition?
+ {
+ m_displayInfo->EventProcess(event);
+ }
+ return EventFrame(event);
+ }
+
+ // Management of the console.
+#if 0
+ if ( m_phase != PHASE_NAME &&
+ !m_movie->IsExist() &&
+ event.event == EVENT_KEYDOWN &&
+ event.param == VK_PAUSE &&
+ (event.keyState&KS_CONTROL) != 0 )
+#else
+ if ( m_phase != PHASE_NAME &&
+ !m_movie->IsExist() &&
+ event.event == EVENT_KEYDOWN &&
+ event.param == VK_CANCEL ) // Ctrl+Pause ?
+#endif
+ {
+ pe = (CEdit*)m_interface->SearchControl(EVENT_CMD);
+ if ( pe == 0 ) return false;
+ pe->SetState(STATE_VISIBLE);
+ pe->SetFocus(true);
+ if ( m_phase == PHASE_SIMUL ) ChangePause(true);
+ m_bCmdEdit = true;
+ return false;
+ }
+ if ( event.event == EVENT_KEYDOWN &&
+ event.param == VK_RETURN && m_bCmdEdit )
+ {
+ char cmd[50];
+ pe = (CEdit*)m_interface->SearchControl(EVENT_CMD);
+ if ( pe == 0 ) return false;
+ pe->GetText(cmd, 50);
+ pe->SetText("");
+ pe->ClearState(STATE_VISIBLE);
+ if ( m_phase == PHASE_SIMUL ) ChangePause(false);
+ ExecuteCmd(cmd);
+ m_bCmdEdit = false;
+ return false;
+ }
+
+ // Management of the speed change.
+ if ( event.event == EVENT_SPEED )
+ {
+ SetSpeed(1.0f);
+ }
+
+ if ( !m_dialog->EventProcess(event) )
+ {
+ if ( event.event == EVENT_MOUSEMOVE )
+ {
+ m_lastMousePos = event.pos;
+ HiliteObject(event.pos);
+ }
+ return false;
+ }
+
+ if ( !m_displayText->EventProcess(event) )
+ {
+ return false;
+ }
+
+ if ( event.event == EVENT_MOUSEMOVE )
+ {
+ m_lastMousePos = event.pos;
+ HiliteObject(event.pos);
+ }
+
+ if ( m_displayInfo != 0 ) // current info?
+ {
+ m_displayInfo->EventProcess(event);
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+ if ( event.param == m_engine->RetKey(KEYRANK_HELP, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_HELP, 1) ||
+ event.param == m_engine->RetKey(KEYRANK_PROG, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_PROG, 1) ||
+ event.param == VK_ESCAPE )
+ {
+ StopDisplayInfo();
+ }
+ }
+ if ( event.event == EVENT_OBJECT_INFOOK )
+ {
+ StopDisplayInfo();
+ }
+ return false;
+ }
+
+ // Simulation phase of the game
+ if ( m_phase == PHASE_SIMUL )
+ {
+ UpdateInfoText();
+
+ if ( !m_bEditFull )
+ {
+ m_camera->EventProcess(event);
+ }
+
+ switch( event.event )
+ {
+ case EVENT_KEYDOWN:
+ KeyCamera(event.event, event.param);
+ HiliteClear();
+ if ( event.param == VK_F11 )
+ {
+ m_particule->WriteWheelTrace("Savegame\\t.bmp", 256, 256, Math::Vector(16.0f, 0.0f, -368.0f), Math::Vector(140.0f, 0.0f, -248.0f));
+ return false;
+ }
+ if ( m_bEditLock ) // current edition?
+ {
+ if ( event.param == m_engine->RetKey(KEYRANK_HELP, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_HELP, 1) )
+ {
+ StartDisplayInfo(SATCOM_HUSTON, false);
+ return false;
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_PROG, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_PROG, 1) )
+ {
+ StartDisplayInfo(SATCOM_PROG, false);
+ return false;
+ }
+ break;
+ }
+ if ( m_bMovieLock ) // current movie?
+ {
+ if ( event.param == m_engine->RetKey(KEYRANK_QUIT, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_QUIT, 1) ||
+ event.param == VK_ESCAPE )
+ {
+ AbortMovie();
+ }
+ return false;
+ }
+ if ( m_camera->RetType() == CAMERA_VISIT )
+ {
+ if ( event.param == m_engine->RetKey(KEYRANK_VISIT, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_VISIT, 1) )
+ {
+ StartDisplayVisit(EVENT_NULL);
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_QUIT, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_QUIT, 1) ||
+ event.param == VK_ESCAPE )
+ {
+ StopDisplayVisit();
+ }
+ return false;
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_QUIT, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_QUIT, 1) )
+ {
+ if ( m_movie->IsExist() )
+ {
+ StartDisplayInfo(SATCOM_HUSTON, false);
+ }
+ else if ( m_winDelay > 0.0f )
+ {
+ ChangePhase(PHASE_WIN);
+ }
+ else if ( m_lostDelay > 0.0f )
+ {
+ ChangePhase(PHASE_LOST);
+ }
+ else
+ {
+ m_dialog->StartAbort(); // do you want to leave?
+ }
+ }
+ if ( event.param == VK_PAUSE )
+ {
+ if ( !m_bMovieLock && !m_bEditLock && !m_bCmdEdit &&
+ m_camera->RetType() != CAMERA_VISIT &&
+ !m_movie->IsExist() )
+ {
+ ChangePause(!m_engine->RetPause());
+ }
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_CAMERA, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_CAMERA, 1) )
+ {
+ ChangeCamera();
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_DESEL, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_DESEL, 1) )
+ {
+ if ( m_bShortCut )
+ {
+ DeselectObject();
+ }
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_HUMAN, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_HUMAN, 1) )
+ {
+ SelectHuman();
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_NEXT, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_NEXT, 1) )
+ {
+ if ( m_bShortCut )
+ {
+ m_short->SelectNext();
+ }
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_HELP, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_HELP, 1) )
+ {
+ StartDisplayInfo(SATCOM_HUSTON, true);
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_PROG, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_PROG, 1) )
+ {
+ StartDisplayInfo(SATCOM_PROG, true);
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_VISIT, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_VISIT, 1) )
+ {
+ StartDisplayVisit(EVENT_NULL);
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_SPEED10, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_SPEED10, 1) )
+ {
+ SetSpeed(1.0f);
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_SPEED15, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_SPEED15, 1) )
+ {
+ SetSpeed(1.5f);
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_SPEED20, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_SPEED20, 1) )
+ {
+ SetSpeed(2.0f);
+ }
+ if ( event.param == m_engine->RetKey(KEYRANK_SPEED30, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_SPEED30, 1) )
+ {
+ SetSpeed(3.0f);
+ }
+ break;
+
+ case EVENT_KEYUP:
+ KeyCamera(event.event, event.param);
+ break;
+
+ case EVENT_LBUTTONDOWN:
+ pObj = DetectObject(event.pos);
+ if ( !m_bShortCut ) pObj = 0;
+ if ( pObj != 0 && pObj->RetType() == OBJECT_TOTO )
+ {
+ if ( m_displayInfo != 0 ) // current info?
+ {
+ StopDisplayInfo();
+ }
+ else
+ {
+ if ( !m_bEditLock )
+ {
+ StartDisplayInfo(SATCOM_HUSTON, true);
+ }
+ }
+ }
+ else
+ {
+ SelectObject(pObj);
+ }
+ break;
+
+ case EVENT_LBUTTONUP:
+ m_cameraPan = 0.0f;
+ m_cameraZoom = 0.0f;
+ break;
+
+ case EVENT_BUTTON_QUIT:
+ if ( m_movie->IsExist() )
+ {
+ StartDisplayInfo(SATCOM_HUSTON, false);
+ }
+ else if ( m_winDelay > 0.0f )
+ {
+ ChangePhase(PHASE_WIN);
+ }
+ else if ( m_lostDelay > 0.0f )
+ {
+ ChangePhase(PHASE_LOST);
+ }
+ else
+ {
+ m_dialog->StartAbort(); // do you want to leave?
+ }
+ break;
+
+ case EVENT_OBJECT_LIMIT:
+ StartShowLimit();
+ break;
+
+ case EVENT_OBJECT_DESELECT:
+ if ( m_bShortCut )
+ {
+ DeselectObject();
+ }
+ break;
+
+ case EVENT_OBJECT_HELP:
+ HelpObject();
+ break;
+
+ case EVENT_OBJECT_CAMERA:
+ ChangeCamera();
+ break;
+
+ case EVENT_OBJECT_CAMERAleft:
+ m_cameraPan = -1.0f;
+ break;
+ case EVENT_OBJECT_CAMERAright:
+ m_cameraPan = 1.0f;
+ break;
+ case EVENT_OBJECT_CAMERAnear:
+ m_cameraZoom = -1.0f;
+ break;
+ case EVENT_OBJECT_CAMERAaway:
+ m_cameraZoom = 1.0f;
+ break;
+
+ case EVENT_OBJECT_DELETE:
+ m_dialog->StartDeleteObject(); // do you want to destroy it?
+ break;
+
+ case EVENT_OBJECT_BHELP:
+ StartDisplayInfo(SATCOM_HUSTON, true);
+ break;
+
+ case EVENT_OBJECT_SOLUCE:
+ StartDisplayInfo(SATCOM_SOLUCE, true);
+ break;
+
+ case EVENT_OBJECT_MAPZOOM:
+ m_map->ZoomMap();
+ break;
+
+ case EVENT_DT_VISIT0:
+ case EVENT_DT_VISIT1:
+ case EVENT_DT_VISIT2:
+ case EVENT_DT_VISIT3:
+ case EVENT_DT_VISIT4:
+ StartDisplayVisit(event.event);
+ break;
+
+ case EVENT_DT_END:
+ StopDisplayVisit();
+ break;
+
+ case EVENT_OBJECT_SHORTCUT00:
+ case EVENT_OBJECT_SHORTCUT01:
+ case EVENT_OBJECT_SHORTCUT02:
+ case EVENT_OBJECT_SHORTCUT03:
+ case EVENT_OBJECT_SHORTCUT04:
+ case EVENT_OBJECT_SHORTCUT05:
+ case EVENT_OBJECT_SHORTCUT06:
+ case EVENT_OBJECT_SHORTCUT07:
+ case EVENT_OBJECT_SHORTCUT08:
+ case EVENT_OBJECT_SHORTCUT09:
+ case EVENT_OBJECT_SHORTCUT10:
+ case EVENT_OBJECT_SHORTCUT11:
+ case EVENT_OBJECT_SHORTCUT12:
+ case EVENT_OBJECT_SHORTCUT13:
+ case EVENT_OBJECT_SHORTCUT14:
+ case EVENT_OBJECT_SHORTCUT15:
+ case EVENT_OBJECT_SHORTCUT16:
+ case EVENT_OBJECT_SHORTCUT17:
+ case EVENT_OBJECT_SHORTCUT18:
+ case EVENT_OBJECT_SHORTCUT19:
+ m_short->SelectShortcut(event.event);
+ break;
+
+ case EVENT_OBJECT_MOVIELOCK:
+ AbortMovie();
+ break;
+
+ case EVENT_WIN:
+ ChangePhase(PHASE_WIN);
+ break;
+
+ case EVENT_LOST:
+ ChangePhase(PHASE_LOST);
+ break;
+ }
+
+ EventObject(event);
+ return false;
+ }
+
+ if ( m_phase == PHASE_PERSO )
+ {
+ EventObject(event);
+ }
+
+ if ( m_phase == PHASE_WIN ||
+ m_phase == PHASE_LOST )
+ {
+ EventObject(event);
+
+ switch( event.event )
+ {
+ case EVENT_KEYDOWN:
+ if ( event.param == VK_ESCAPE ||
+ event.param == VK_RETURN )
+ {
+ if ( m_bWinTerminate )
+ {
+ ChangePhase(PHASE_INIT);
+ }
+ else
+ {
+ ChangePhase(PHASE_TERM);
+ }
+ }
+ break;
+
+ case EVENT_BUTTON_OK:
+ if ( m_bWinTerminate )
+ {
+ ChangePhase(PHASE_INIT);
+ }
+ else
+ {
+ ChangePhase(PHASE_TERM);
+ }
+ break;
+ }
+ }
+
+ if ( m_phase == PHASE_MODEL )
+ {
+ switch( event.event )
+ {
+ case EVENT_KEYDOWN:
+ if ( event.param == VK_ESCAPE )
+ {
+ ChangePhase(PHASE_INIT);
+ }
+ if ( event.param == VK_HOME )
+ {
+ InitEye();
+ }
+ break;
+
+ case EVENT_BUTTON_CANCEL:
+ ChangePhase(PHASE_INIT);
+ break;
+ }
+
+ m_model->EventProcess(event);
+ return false;
+ }
+
+ return true;
+}
+
+
+
+// Executes a command.
+
+void CRobotMain::ExecuteCmd(char *cmd)
+{
+ if ( cmd[0] == 0 ) return;
+
+ if ( m_phase == PHASE_SIMUL )
+ {
+ if ( strcmp(cmd, "winmission") == 0 )
+ {
+ Event newEvent;
+ m_event->MakeEvent(newEvent, EVENT_WIN);
+ m_event->AddEvent(newEvent);
+ }
+
+ if ( strcmp(cmd, "lostmission") == 0 )
+ {
+ Event newEvent;
+ m_event->MakeEvent(newEvent, EVENT_LOST);
+ m_event->AddEvent(newEvent);
+ }
+
+ if ( strcmp(cmd, "trainerpilot") == 0 )
+ {
+ m_bTrainerPilot = !m_bTrainerPilot;
+ return;
+ }
+
+ if ( strcmp(cmd, "fly") == 0 )
+ {
+ Event newEvent;
+
+ g_researchDone |= RESEARCH_FLY;
+
+ m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
+ m_event->AddEvent(newEvent);
+ return;
+ }
+
+ if ( strcmp(cmd, "allresearch") == 0 )
+ {
+ Event newEvent;
+
+ g_researchDone = -1; // all research are done
+
+ m_event->MakeEvent(newEvent, EVENT_UPDINTERFACE);
+ m_event->AddEvent(newEvent);
+ return;
+ }
+
+ if ( strcmp(cmd, "nolimit") == 0 )
+ {
+ m_terrain->SetFlyingMaxHeight(280.0f);
+ return;
+ }
+
+ if ( strcmp(cmd, "photo1") == 0 )
+ {
+ m_bFreePhoto = !m_bFreePhoto;
+ if ( m_bFreePhoto )
+ {
+ m_camera->SetType(CAMERA_FREE);
+ ChangePause(true);
+ }
+ else
+ {
+ m_camera->SetType(CAMERA_BACK);
+ ChangePause(false);
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "photo2") == 0 )
+ {
+ m_bFreePhoto = !m_bFreePhoto;
+ if ( m_bFreePhoto )
+ {
+ m_camera->SetType(CAMERA_FREE);
+ ChangePause(true);
+ DeselectAll(); // removes the control buttons
+ m_map->ShowMap(false);
+ m_displayText->HideText(true);
+ }
+ else
+ {
+ m_camera->SetType(CAMERA_BACK);
+ ChangePause(false);
+ m_map->ShowMap(m_bMapShow);
+ m_displayText->HideText(false);
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "noclip") == 0 )
+ {
+ CObject* object;
+
+ object = RetSelect();
+ if ( object != 0 )
+ {
+ object->SetClip(false);
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "clip") == 0 )
+ {
+ CObject* object;
+
+ object = RetSelect();
+ if ( object != 0 )
+ {
+ object->SetClip(true);
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "addhusky") == 0 )
+ {
+ CObject* object;
+
+ object = RetSelect();
+ if ( object != 0 )
+ {
+ object->SetMagnifyDamage(object->RetMagnifyDamage()*0.1f);
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "addfreezer") == 0 )
+ {
+ CObject* object;
+
+ object = RetSelect();
+ if ( object != 0 )
+ {
+ object->SetRange(object->RetRange()*10.0f);
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "fullpower") == 0 )
+ {
+ CObject* object;
+ CObject* power;
+ CPhysics* physics;
+
+ object = RetSelect();
+ if ( object != 0 )
+ {
+ power = object->RetPower();
+ if ( power != 0 )
+ {
+ power->SetEnergy(1.0f);
+ }
+ object->SetShield(1.0f);
+ physics = object->RetPhysics();
+ if ( physics != 0 )
+ {
+ physics->SetReactorRange(1.0f);
+ }
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "fullenergy") == 0 )
+ {
+ CObject* object;
+ CObject* power;
+
+ object = RetSelect();
+ if ( object != 0 )
+ {
+ power = object->RetPower();
+ if ( power != 0 )
+ {
+ power->SetEnergy(1.0f);
+ }
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "fullshield") == 0 )
+ {
+ CObject* object;
+
+ object = RetSelect();
+ if ( object != 0 )
+ {
+ object->SetShield(1.0f);
+ }
+ return;
+ }
+
+ if ( strcmp(cmd, "fullrange") == 0 )
+ {
+ CObject* object;
+ CPhysics* physics;
+
+ object = RetSelect();
+ if ( object != 0 )
+ {
+ physics = object->RetPhysics();
+ if ( physics != 0 )
+ {
+ physics->SetReactorRange(1.0f);
+ }
+ }
+ return;
+ }
+ }
+
+ if ( strcmp(cmd, "debugmode") == 0 )
+ {
+ m_engine->SetDebugMode(!m_engine->RetDebugMode());
+ return;
+ }
+
+ if ( strcmp(cmd, "showstat") == 0 )
+ {
+ m_engine->SetShowStat(!m_engine->RetShowStat());
+ return;
+ }
+
+ if ( strcmp(cmd, "invshadow") == 0 )
+ {
+ m_engine->SetShadow(!m_engine->RetShadow());
+ return;
+ }
+
+ if ( strcmp(cmd, "invdirty") == 0 )
+ {
+ m_engine->SetDirty(!m_engine->RetDirty());
+ return;
+ }
+
+ if ( strcmp(cmd, "invfog") == 0 )
+ {
+ m_engine->SetFog(!m_engine->RetFog());
+ return;
+ }
+
+ if ( strcmp(cmd, "invlens") == 0 )
+ {
+ m_engine->SetLensMode(!m_engine->RetLensMode());
+ return;
+ }
+
+ if ( strcmp(cmd, "invwater") == 0 )
+ {
+ m_engine->SetWaterMode(!m_engine->RetWaterMode());
+ return;
+ }
+
+ if ( strcmp(cmd, "invsky") == 0 )
+ {
+ m_engine->SetSkyMode(!m_engine->RetSkyMode());
+ return;
+ }
+
+ if ( strcmp(cmd, "invplanet") == 0 )
+ {
+ m_engine->SetPlanetMode(!m_engine->RetPlanetMode());
+ return;
+ }
+
+ if ( strcmp(cmd, "showpos") == 0 )
+ {
+ m_bShowPos = !m_bShowPos;
+ return;
+ }
+
+ if ( strcmp(cmd, "selectinsect") == 0 )
+ {
+ m_bSelectInsect = !m_bSelectInsect;
+ return;
+ }
+
+ if ( strcmp(cmd, "showsoluce") == 0 )
+ {
+ m_bShowSoluce = !m_bShowSoluce;
+ m_dialog->ShowSoluceUpdate();
+ return;
+ }
+
+#if _TEEN
+ if ( strcmp(cmd, "allteens") == 0 )
+#else
+ if ( strcmp(cmd, "allmission") == 0 )
+#endif
+ {
+ m_bShowAll = !m_bShowAll;
+ m_dialog->AllMissionUpdate();
+ return;
+ }
+
+ if ( strcmp(cmd, "invradar") == 0 )
+ {
+ m_bCheatRadar = !m_bCheatRadar;
+ return;
+ }
+
+ if ( m_phase == PHASE_SIMUL )
+ {
+ m_displayText->DisplayError(ERR_CMD, Math::Vector(0.0f,0.0f,0.0f));
+ }
+}
+
+
+
+// Returns the type of current movie.
+
+MainMovieType CRobotMain::RetMainMovie()
+{
+ return m_movie->RetType();
+}
+
+
+// Clears the display of instructions.
+
+void CRobotMain::FlushDisplayInfo()
+{
+ int i;
+
+ for ( i=0 ; i<SATCOM_MAX ; i++ )
+ {
+ m_infoFilename[i][0] = 0;
+ m_infoPos[i] = 0;
+ }
+ strcpy(m_infoFilename[SATCOM_OBJECT], "help\\objects.txt");
+ m_infoIndex = 0;
+}
+
+// Beginning of the displaying of instructions.
+// index: SATCOM_*
+
+void CRobotMain::StartDisplayInfo(int index, bool bMovie)
+{
+ CObject* pObj;
+ CMotion* motion;
+ bool bHuman;
+
+ if ( m_bCmdEdit || m_bSatComLock ) return;
+
+ pObj = RetSelect();
+ bHuman = ( pObj != 0 && pObj->RetType() == OBJECT_HUMAN );
+
+ if ( !m_bEditLock && bMovie && !m_movie->IsExist() && bHuman )
+ {
+ motion = pObj->RetMotion();
+ if ( motion != 0 && motion->RetAction() == -1 )
+ {
+ m_movieInfoIndex = index;
+ m_movie->Start(MM_SATCOMopen, 2.5f);
+ ChangePause(true);
+//? m_map->ShowMap(false);
+ m_infoObject = DeselectAll(); // removes the control buttons
+ m_displayText->HideText(true);
+ return;
+ }
+ }
+
+ if ( m_movie->IsExist() )
+ {
+ m_movie->Stop();
+ ChangePause(false);
+ SelectObject(m_infoObject, false); // hands over the command buttons
+//? m_map->ShowMap(m_bMapShow);
+ m_displayText->HideText(false);
+ }
+
+ StartDisplayInfo(m_infoFilename[index], index);
+}
+
+// Beginning of the displaying of instructions.
+
+void CRobotMain::StartDisplayInfo(char *filename, int index)
+{
+ CButton* pb;
+ bool bSoluce;
+
+ if ( m_bCmdEdit ) return;
+
+ m_movieInfoIndex = -1;
+ ClearInterface(); // removes setting evidence and tooltip
+
+ if ( !m_bEditLock )
+ {
+//? m_map->ShowMap(false);
+ m_infoObject = DeselectAll(); // removes the control buttons
+ m_displayText->HideText(true);
+ m_sound->MuteAll(true);
+ }
+
+ pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
+ if ( pb != 0 )
+ {
+ pb->ClearState(STATE_VISIBLE);
+ }
+
+ bSoluce = m_dialog->RetSceneSoluce();
+
+ m_displayInfo = new CDisplayInfo(m_iMan);
+ m_displayInfo->StartDisplayInfo(filename, index, bSoluce);
+
+ m_infoIndex = index;
+ if ( index != -1 )
+ {
+ m_displayInfo->SetPosition(m_infoPos[index]);
+ }
+}
+
+// End of displaying of instructions.
+
+void CRobotMain::StopDisplayInfo()
+{
+ CButton* pb;
+
+ if ( m_movieInfoIndex != -1 ) // film to read the SatCom?
+ {
+ m_movie->Start(MM_SATCOMclose, 2.0f);
+ }
+
+ if ( m_infoIndex != -1 )
+ {
+ m_infoPos[m_infoIndex] = m_displayInfo->RetPosition();
+ }
+ m_displayInfo->StopDisplayInfo();
+
+ delete m_displayInfo;
+ m_displayInfo = 0;
+
+ if ( !m_bEditLock )
+ {
+ pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
+ if ( pb != 0 )
+ {
+ pb->SetState(STATE_VISIBLE);
+ }
+
+ SelectObject(m_infoObject, false); // gives the command buttons
+//? m_map->ShowMap(m_bMapShow);
+ m_displayText->HideText(false);
+
+ m_sound->MuteAll(false);
+ }
+
+ if ( m_infoUsed == 0 )
+ {
+ m_displayText->ClearText(); // removes message "see SatCom ..."
+ }
+ m_infoUsed ++;
+}
+
+// Returns the name of the text display.
+
+char* CRobotMain::RetDisplayInfoName(int index)
+{
+ return m_infoFilename[index];
+}
+
+// Returns the name of the text display.
+
+int CRobotMain::RetDisplayInfoPosition(int index)
+{
+ return m_infoPos[index];
+}
+
+// Returns the name of the text display.
+
+void CRobotMain::SetDisplayInfoPosition(int index, int pos)
+{
+ m_infoPos[index] = pos;
+}
+
+
+// Beginning of a dialogue during the game,
+
+void CRobotMain::StartSuspend()
+{
+ CButton* pb;
+
+ m_map->ShowMap(false);
+ m_infoObject = DeselectAll(); // removes the control buttons
+ m_displayText->HideText(true);
+
+ pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
+ if ( pb != 0 )
+ {
+ pb->ClearState(STATE_VISIBLE);
+ }
+
+ m_bSuspend = true;
+}
+
+// End of dialogue during the game,
+
+void CRobotMain::StopSuspend()
+{
+ CButton* pb;
+
+ pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
+ if ( pb != 0 )
+ {
+ pb->SetState(STATE_VISIBLE);
+ }
+
+ SelectObject(m_infoObject, false); // gives the command buttons
+ m_map->ShowMap(m_bMapShow);
+ m_displayText->HideText(false);
+
+ m_bSuspend = false;
+}
+
+
+// Returns the absolute time of the game
+
+float CRobotMain::RetGameTime()
+{
+ return m_gameTime;
+}
+
+
+
+// Managing the size of the default fonts.
+
+void CRobotMain::SetFontSize(float size)
+{
+ m_fontSize = size;
+ SetProfileFloat("Edit", "FontSize", m_fontSize);
+}
+
+float CRobotMain::RetFontSize()
+{
+ return m_fontSize;
+}
+
+// Managing the size of the default window.
+
+void CRobotMain::SetWindowPos(Math::Point pos)
+{
+ m_windowPos = pos;
+ SetProfileFloat("Edit", "WindowPos.x", m_windowPos.x);
+ SetProfileFloat("Edit", "WindowPos.y", m_windowPos.y);
+}
+
+Math::Point CRobotMain::RetWindowPos()
+{
+ return m_windowPos;
+}
+
+void CRobotMain::SetWindowDim(Math::Point dim)
+{
+ m_windowDim = dim;
+ SetProfileFloat("Edit", "WindowDim.x", m_windowDim.x);
+ SetProfileFloat("Edit", "WindowDim.y", m_windowDim.y);
+}
+
+Math::Point CRobotMain::RetWindowDim()
+{
+ return m_windowDim;
+}
+
+
+// Managing windows open/save.
+
+void CRobotMain::SetIOPublic(bool bMode)
+{
+ m_IOPublic = bMode;
+ SetProfileInt("Edit", "IOPublic", m_IOPublic);
+}
+
+bool CRobotMain::RetIOPublic()
+{
+ return m_IOPublic;
+}
+
+void CRobotMain::SetIOPos(Math::Point pos)
+{
+ m_IOPos = pos;
+ SetProfileFloat("Edit", "IOPos.x", m_IOPos.x);
+ SetProfileFloat("Edit", "IOPos.y", m_IOPos.y);
+}
+
+Math::Point CRobotMain::RetIOPos()
+{
+ return m_IOPos;
+}
+
+void CRobotMain::SetIODim(Math::Point dim)
+{
+ m_IODim = dim;
+ SetProfileFloat("Edit", "IODim.x", m_IODim.x);
+ SetProfileFloat("Edit", "IODim.y", m_IODim.y);
+}
+
+Math::Point CRobotMain::RetIODim()
+{
+ return m_IODim;
+}
+
+
+
+// Start of the visit instead of an error.
+
+void CRobotMain::StartDisplayVisit(EventMsg event)
+{
+ CWindow* pw;
+ CButton* button;
+ CGroup* group;
+ Math::Vector goal;
+ Math::Point pos, dim;
+ int i, j;
+
+ if ( m_bEditLock ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
+ if ( pw == 0 ) return;
+
+ if ( event == EVENT_NULL ) // visit by keyboard shortcut?
+ {
+ if ( m_visitLast != EVENT_NULL ) // already a current visit?
+ {
+ i = m_visitLast-EVENT_DT_VISIT0;
+ }
+ else
+ {
+ i = MAXDTLINE;
+ }
+
+ // Seeks the last.
+ for ( j=0 ; j<MAXDTLINE ; j++ )
+ {
+ i --;
+ if ( i < 0 ) i = MAXDTLINE-1;
+
+ button = (CButton*)pw->SearchControl(EventMsg(EVENT_DT_VISIT0+i));
+ if ( button == 0 || !button->TestState(STATE_ENABLE) ) continue;
+
+ group = (CGroup*)pw->SearchControl(EventMsg(EVENT_DT_GROUP0+i));
+ if ( group != 0 )
+ {
+ event = EventMsg(EVENT_DT_VISIT0+i);
+ break;
+ }
+ }
+ }
+ if ( event == EVENT_NULL )
+ {
+ m_sound->Play(SOUND_TZOING); // nothing to do!
+ return;
+ }
+
+ m_visitLast = event;
+
+ ClearInterface(); // removes setting evidence and tooltip
+
+ if ( m_camera->RetType() == CAMERA_VISIT ) // already a current visit?
+ {
+ m_camera->StopVisit();
+ m_displayText->ClearVisit();
+ }
+ else
+ {
+ m_visitObject = DeselectAll(); // removes the control buttons
+ }
+
+ // Creates the "continue" button.
+ if ( m_interface->SearchControl(EVENT_DT_END) == 0 )
+ {
+ pos.x = 10.0f/640.0f;
+ pos.y = 10.0f/480.0f;
+ dim.x = 50.0f/640.0f;
+ dim.y = 50.0f/480.0f;
+ m_interface->CreateButton(pos, dim, 16, EVENT_DT_END);
+ }
+
+ // Creates the arrow to show the place.
+ if ( m_visitArrow != 0 )
+ {
+ m_visitArrow->DeleteObject();
+ delete m_visitArrow;
+ m_visitArrow = 0;
+ }
+ goal = m_displayText->RetVisitGoal(event);
+ m_visitArrow = CreateObject(goal, 0.0f, 1.0f, 10.0f, OBJECT_SHOW, false, false, 0);
+
+ m_visitPos = m_visitArrow->RetPosition(0);
+ m_visitPosArrow = m_visitPos;
+ m_visitPosArrow.y += m_displayText->RetVisitHeight(event);
+ m_visitArrow->SetPosition(0, m_visitPosArrow);
+
+ m_visitTime = 0.0;
+ m_visitParticule = 0.0f;
+
+ m_particule->DeleteParticule(PARTISHOW);
+
+ m_camera->StartVisit(m_displayText->RetVisitGoal(event),
+ m_displayText->RetVisitDist(event));
+ m_displayText->SetVisit(event);
+ ChangePause(true);
+}
+
+// Move the arrow to visit.
+
+void CRobotMain::FrameVisit(float rTime)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float level;
+
+ if ( m_visitArrow == 0 ) return;
+
+ // Moves the arrow.
+ m_visitTime += rTime;
+
+ pos = m_visitPosArrow;
+ pos.y += 1.5f+sinf(m_visitTime*4.0f)*4.0f;
+ m_visitArrow->SetPosition(0, pos);
+ m_visitArrow->SetAngleY(0, m_visitTime*2.0f);
+
+ // Manages the particles "arrows".
+ m_visitParticule -= rTime;
+ if ( m_visitParticule <= 0.0f )
+ {
+ m_visitParticule = 1.5f;
+
+ pos = m_visitPos;
+ level = m_terrain->RetFloorLevel(pos)+2.0f;
+ if ( pos.y < level ) pos.y = level; // not below the ground
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 30.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISHOW, 2.0f);
+ }
+}
+
+// End of the visit instead of an error.
+
+void CRobotMain::StopDisplayVisit()
+{
+ m_visitLast = EVENT_NULL;
+
+ // Removes the button.
+ m_interface->DeleteControl(EVENT_DT_END);
+
+ // Removes the arrow.
+ if ( m_visitArrow != 0 )
+ {
+ m_visitArrow->DeleteObject();
+ delete m_visitArrow;
+ m_visitArrow = 0;
+ }
+
+ // Removes particles "arrows".
+ m_particule->DeleteParticule(PARTISHOW);
+
+ m_camera->StopVisit();
+ m_displayText->ClearVisit();
+ ChangePause(false);
+ if ( m_visitObject != 0 )
+ {
+ SelectObject(m_visitObject, false); // gives the command buttons
+ m_visitObject = 0;
+ }
+}
+
+
+
+// Updates all the shortcuts.
+
+void CRobotMain::UpdateShortcuts()
+{
+ m_short->UpdateShortcuts();
+}
+
+// Returns the object that default was select after the creation of a scene.
+
+CObject* CRobotMain::RetSelectObject()
+{
+ if ( m_selectObject != 0 ) return m_selectObject;
+ return SearchHuman();
+}
+
+// Deselects everything, and returns the object that was selected.
+
+CObject* CRobotMain::DeselectAll()
+{
+ CObject* pObj;
+ CObject* pPrev;
+ int i;
+
+ pPrev = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetSelect() ) pPrev = pObj;
+ pObj->SetSelect(false);
+ }
+ return pPrev;
+}
+
+// Selects an object, without attending to deselect the rest.
+
+void CRobotMain::SelectOneObject(CObject* pObj, bool bDisplayError)
+{
+ ObjectType type;
+ CObject* toto;
+ CMotionToto* mt;
+
+ pObj->SetSelect(true, bDisplayError);
+ m_camera->SetObject(pObj);
+
+ type = pObj->RetType();
+ if ( 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 ||
+ type == OBJECT_APOLLO2 )
+ {
+ m_camera->SetType(pObj->RetCameraType());
+ m_camera->SetDist(pObj->RetCameraDist());
+ }
+ else
+ {
+ m_camera->SetType(CAMERA_BACK);
+ }
+
+ toto = SearchToto();
+ if ( toto != 0 )
+ {
+ mt = (CMotionToto*)toto->RetMotion();
+ if ( mt != 0 )
+ {
+ mt->SetLinkType(type);
+ }
+ }
+}
+
+// Selects the object aimed by the mouse.
+
+bool CRobotMain::SelectObject(CObject* pObj, bool bDisplayError)
+{
+ CObject* pPrev;
+
+ if ( m_camera->RetType() == CAMERA_VISIT )
+ {
+ StopDisplayVisit();
+ }
+
+ if ( m_bMovieLock || m_bEditLock || m_bPause ) return false;
+ if ( m_movie->IsExist() ) return false;
+ if ( pObj == 0 || !IsSelectable(pObj) ) return false;
+
+ pPrev = DeselectAll();
+
+ if ( pPrev != 0 && pPrev != pObj )
+ {
+ pObj->AddDeselList(pPrev);
+ }
+
+ SelectOneObject(pObj, bDisplayError);
+ m_short->UpdateShortcuts();
+ return true;
+}
+
+// Deselects the selected object.
+
+bool CRobotMain::DeselectObject()
+{
+ CObject* pObj;
+ CObject* pPrev;
+
+ pPrev = DeselectAll();
+
+ if ( pPrev == 0 )
+ {
+ pObj = SearchHuman();
+ }
+ else
+ {
+ pObj = pPrev->SubDeselList();
+ }
+ if ( pObj == 0 )
+ {
+ pObj = SearchHuman();
+ }
+
+ if ( pObj != 0 )
+ {
+ SelectOneObject(pObj);
+ }
+ else
+ {
+ m_camera->SetType(CAMERA_FREE);
+ }
+
+ m_short->UpdateShortcuts();
+ return true;
+}
+
+// Quickly removes all objects.
+
+void CRobotMain::DeleteAllObjects()
+{
+ CPyro* pyro;
+ CObject* pObj;
+ int i;
+
+ // Removes all pyrotechnic effects in progress.
+ while ( true )
+ {
+ pyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, 0);
+ if ( pyro == 0 ) break;
+
+ pyro->DeleteObject();
+ delete pyro;
+ }
+
+ // Removes the arrow.
+ if ( m_visitArrow != 0 )
+ {
+ m_visitArrow->DeleteObject();
+ delete m_visitArrow;
+ m_visitArrow = 0;
+ }
+
+ for ( i=0 ; i<MAXSHOWLIMIT ; i++ )
+ {
+ FlushShowLimit(i);
+ }
+
+ while ( true )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, 0);
+ if ( pObj == 0 ) break;
+
+ pObj->DeleteObject(true); // destroys rapidly
+ delete pObj;
+ }
+}
+
+// Selects the human.
+
+void CRobotMain::SelectHuman()
+{
+ SelectObject(SearchHuman());
+}
+
+// Returns the object human.
+
+CObject* CRobotMain::SearchHuman()
+{
+ ObjectType type;
+ CObject* pObj;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_HUMAN )
+ {
+ return pObj;
+ }
+ }
+ return 0;
+}
+
+// Returns the object toto.
+
+CObject* CRobotMain::SearchToto()
+{
+ ObjectType type;
+ CObject* pObj;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_TOTO )
+ {
+ return pObj;
+ }
+ }
+ return 0;
+}
+
+// Returns the nearest selectable object from a given position.
+
+CObject* CRobotMain::SearchNearest(Math::Vector pos, CObject* pExclu)
+{
+ ObjectType type;
+ CObject *pObj, *pBest;
+ Math::Vector oPos;
+ float min, dist;
+ int i;
+
+ min = 100000.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == pExclu ) continue;
+ if ( !IsSelectable(pObj) ) continue;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_TOTO ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, pos);
+ if ( dist < min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+ return pBest;
+}
+
+// Returns the selected object.
+
+CObject* CRobotMain::RetSelect()
+{
+ CObject* pObj;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetSelect() )
+ {
+ return pObj;
+ }
+ }
+ return 0;
+}
+
+CObject* CRobotMain::SearchObject(ObjectType type)
+{
+ CObject* pObj;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetType() == type )
+ {
+ return pObj;
+ }
+ }
+ return 0;
+}
+
+// Detects the object aimed by the mouse.
+
+CObject* CRobotMain::DetectObject(Math::Point pos)
+{
+ ObjectType type;
+ CObject *pObj, *pTarget;
+ int objRank, i, j, rank;
+
+ objRank = m_engine->DetectObject(pos);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue;
+ if ( pObj->RetProxyActivate() ) continue;
+
+ pTarget = 0;
+ type = pObj->RetType();
+ if ( type == OBJECT_PORTICO ||
+ 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 ||
+ type == OBJECT_TARGET1 ||
+ type == OBJECT_TARGET2 ||
+ type == OBJECT_START ||
+ type == OBJECT_END ||
+ type == OBJECT_STONE ||
+ type == OBJECT_URANIUM ||
+ type == OBJECT_BULLET ||
+ type == OBJECT_METAL ||
+ type == OBJECT_BBOX ||
+ type == OBJECT_KEYa ||
+ type == OBJECT_KEYb ||
+ type == OBJECT_KEYc ||
+ type == OBJECT_KEYd ||
+ type == OBJECT_TNT ||
+ type == OBJECT_SCRAP1 ||
+ type == OBJECT_SCRAP2 ||
+ type == OBJECT_SCRAP3 ||
+ type == OBJECT_SCRAP4 ||
+ type == OBJECT_SCRAP5 ||
+ type == OBJECT_BOMB ||
+ type == OBJECT_BAG ||
+ type == OBJECT_WAYPOINT ||
+ type == OBJECT_FLAGb ||
+ type == OBJECT_FLAGr ||
+ type == OBJECT_FLAGg ||
+ type == OBJECT_FLAGy ||
+ type == OBJECT_FLAGv ||
+ type == OBJECT_MARKPOWER ||
+ type == OBJECT_MARKSTONE ||
+ type == OBJECT_MARKURANIUM ||
+ type == OBJECT_MARKKEYa ||
+ type == OBJECT_MARKKEYb ||
+ type == OBJECT_MARKKEYc ||
+ type == OBJECT_MARKKEYd ||
+ type == OBJECT_HUMAN ||
+ type == OBJECT_TECH ||
+ type == OBJECT_TOTO ||
+ type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr ||
+ type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ||
+ type == OBJECT_EGG ||
+ type == OBJECT_RUINmobilew1 ||
+ type == OBJECT_RUINmobilew2 ||
+ type == OBJECT_RUINmobilet1 ||
+ type == OBJECT_RUINmobilet2 ||
+ type == OBJECT_RUINmobiler1 ||
+ type == OBJECT_RUINmobiler2 ||
+ type == OBJECT_RUINfactory ||
+ type == OBJECT_RUINdoor ||
+ type == OBJECT_RUINsupport ||
+ type == OBJECT_RUINradar ||
+ type == OBJECT_RUINconvert ||
+ type == OBJECT_RUINbase ||
+ type == OBJECT_RUINhead ||
+ type == OBJECT_APOLLO1 ||
+ type == OBJECT_APOLLO2 ||
+ type == OBJECT_APOLLO3 ||
+ type == OBJECT_APOLLO4 ||
+ type == OBJECT_APOLLO5 )
+ {
+ pTarget = pObj;
+ }
+ else if ( (type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC ) &&
+ pObj->RetTruck() != 0 ) // battery used?
+ {
+ pTarget = pObj->RetTruck();
+ }
+ else if ( type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC )
+ {
+ pTarget = pObj;
+ }
+
+ for ( j=0 ; j<OBJECTMAXPART ; j++ )
+ {
+ rank = pObj->RetObjectRank(j);
+ if ( rank == -1 ) continue;
+ if ( rank != objRank ) continue;
+ return pTarget;
+ }
+ }
+ return 0;
+}
+
+// Indicates whether an object is selectable.
+
+bool CRobotMain::IsSelectable(CObject* pObj)
+{
+ ObjectType type;
+
+ if ( !pObj->RetSelectable() ) return false;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TOTO ||
+ 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 ||
+ type == OBJECT_APOLLO2 ||
+ 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 )
+ {
+ return true;
+ }
+
+ if ( m_bSelectInsect )
+ {
+ if ( type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ||
+ type == OBJECT_MOBILEtg )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+// Deletes the selected object.
+
+bool CRobotMain::DeleteObject()
+{
+ CObject* pObj;
+ CPyro* pyro;
+
+ pObj = RetSelect();
+ if ( pObj == 0 ) return false;
+
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FRAGT, pObj);
+
+ pObj->SetSelect(false); // deselects the object
+ m_camera->SetType(CAMERA_EXPLO);
+ DeselectAll();
+ pObj->DeleteDeselList(pObj);
+
+ return true;
+}
+
+
+// Removes setting evidence of the object with the mouse hovers over.
+
+void CRobotMain::HiliteClear()
+{
+ CObject* pObj;
+ int i;
+
+ ClearTooltip();
+ m_tooltipName[0] = 0; // really removes the tooltip
+
+ if ( !m_bHilite ) return;
+
+ i = -1;
+ m_engine->SetHiliteRank(&i); // nothing more selected
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ pObj->SetHilite(false);
+ m_map->SetHilite(0);
+ m_short->SetHilite(0);
+ }
+
+ m_bHilite = false;
+}
+
+// Highlights the object with the mouse hovers over.
+
+void CRobotMain::HiliteObject(Math::Point pos)
+{
+ CObject* pObj;
+ char name[100];
+ bool bInMap;
+
+ if ( m_bFixScene && m_phase != PHASE_PERSO ) return;
+ if ( m_bMovieLock ) return;
+ if ( m_movie->IsExist() ) return;
+ if ( m_engine->RetMouseHide() ) return;
+
+ ClearInterface(); // removes setting evidence and tooltip
+
+ pObj = m_short->DetectShort(pos);
+
+ if ( m_dialog->RetTooltip() && m_interface->GetTooltip(pos, name) )
+ {
+ m_tooltipPos = pos;
+ strcpy(m_tooltipName, name);
+ m_tooltipTime = 0.0f;
+ if ( pObj == 0 ) return;
+ }
+
+ if ( m_bSuspend ) return;
+
+ if ( pObj == 0 )
+ {
+ pObj = m_map->DetectMap(pos, bInMap);
+ if ( pObj == 0 )
+ {
+ if ( bInMap ) return;
+
+ pObj = DetectObject(pos);
+
+ if ( m_camera->RetType() == CAMERA_ONBOARD &&
+ m_camera->RetObject() == pObj )
+ {
+ return;
+ }
+ }
+ }
+
+ if ( pObj != 0 )
+ {
+ if ( m_dialog->RetTooltip() && pObj->GetTooltipName(name) )
+ {
+ m_tooltipPos = pos;
+ strcpy(m_tooltipName, name);
+ m_tooltipTime = 0.0f;
+ }
+
+ if ( IsSelectable(pObj) )
+ {
+ pObj->SetHilite(true);
+ m_map->SetHilite(pObj);
+ m_short->SetHilite(pObj);
+ m_bHilite = true;
+ }
+ }
+}
+
+// Highlights the object with the mouse hovers over.
+
+void CRobotMain::HiliteFrame(float rTime)
+{
+ if ( m_bFixScene && m_phase != PHASE_PERSO ) return;
+ if ( m_bMovieLock ) return;
+ if ( m_movie->IsExist() ) return;
+
+ m_tooltipTime += rTime;
+
+ ClearTooltip();
+
+ if ( m_tooltipTime >= 0.2f &&
+ m_tooltipName[0] != 0 )
+ {
+ CreateTooltip(m_tooltipPos, m_tooltipName);
+ }
+}
+
+// Creates a tooltip.
+
+void CRobotMain::CreateTooltip(Math::Point pos, char* text)
+{
+ CWindow* pw;
+ Math::Point start, end, dim, offset, corner;
+
+ corner.x = pos.x+0.022f;
+ corner.y = pos.y-0.052f;
+
+ m_engine->RetText()->DimText(text, corner, 1,
+ SMALLFONT, NORMSTRETCH, FONT_COLOBOT,
+ start, end);
+ start.x -= 0.010f;
+ start.y -= 0.002f;
+ end.x += 0.010f;
+ end.y += 0.004f; // ch'tite (?) margin
+
+ pos.x = start.x;
+ pos.y = start.y;
+ dim.x = end.x-start.x;
+ dim.y = end.y-start.y;
+
+ offset.x = 0.0f;
+ offset.y = 0.0f;
+ if ( pos.x+dim.x > 1.0f ) offset.x = 1.0f-(pos.x+dim.x);
+ if ( pos.y < 0.0f ) offset.y = -pos.y;
+
+ corner.x += offset.x;
+ corner.y += offset.y;
+ pos.x += offset.x;
+ pos.y += offset.y;
+
+ m_interface->CreateWindows(pos, dim, 1, EVENT_TOOLTIP);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_TOOLTIP);
+ if ( pw != 0 )
+ {
+ pw->SetState(STATE_SHADOW);
+ pw->SetTrashEvent(false);
+
+ pos.y -= m_engine->RetText()->RetHeight(SMALLFONT, FONT_COLOBOT)/2.0f;
+ pw->CreateLabel(pos, dim, -1, EVENT_LABEL2, text);
+ }
+}
+
+// Clears the previous tooltip.
+
+void CRobotMain::ClearTooltip()
+{
+ m_interface->DeleteControl(EVENT_TOOLTIP);
+}
+
+
+// Displays help for an object.
+
+void CRobotMain::HelpObject()
+{
+ CObject* pObj;
+ char* filename;
+
+ pObj = RetSelect();
+ if ( pObj == 0 ) return;
+
+ filename = RetHelpFilename(pObj->RetType());
+ if ( filename[0] == 0 ) return;
+
+ StartDisplayInfo(filename, -1);
+}
+
+
+// Change the mode of the camera.
+
+void CRobotMain::ChangeCamera()
+{
+ CObject* pObj;
+ ObjectType oType;
+ CameraType type;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetSelect() )
+ {
+ if ( pObj->RetCameraLock() ) return;
+
+ oType = pObj->RetType();
+ type = pObj->RetCameraType();
+
+ if ( 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_APOLLO2 ) return;
+
+ if ( oType == OBJECT_MOBILEdr ) // designer?
+ {
+ if ( type == CAMERA_PLANE ) type = CAMERA_BACK;
+ else if ( type == CAMERA_BACK ) type = CAMERA_PLANE;
+ }
+ else if ( pObj->RetTrainer() ) // trainer?
+ {
+ if ( type == CAMERA_ONBOARD ) type = CAMERA_FIX;
+ else if ( type == CAMERA_FIX ) type = CAMERA_PLANE;
+ else if ( type == CAMERA_PLANE ) type = CAMERA_BACK;
+ else if ( type == CAMERA_BACK ) type = CAMERA_ONBOARD;
+ }
+ else
+ {
+ if ( type == CAMERA_ONBOARD ) type = CAMERA_BACK;
+ else if ( type == CAMERA_BACK ) type = CAMERA_ONBOARD;
+ }
+
+ pObj->SetCameraType(type);
+ m_camera->SetType(type);
+ }
+ }
+}
+
+// Remote control the camera using the arrow keys.
+
+void CRobotMain::KeyCamera(EventMsg event, long param)
+{
+ CObject* pObj;
+
+ if ( event == EVENT_KEYUP )
+ {
+ if ( param == m_engine->RetKey(KEYRANK_LEFT, 0) ||
+ param == m_engine->RetKey(KEYRANK_LEFT, 1) )
+ {
+ m_cameraPan = 0.0f;
+ }
+
+ if ( param == m_engine->RetKey(KEYRANK_RIGHT, 0) ||
+ param == m_engine->RetKey(KEYRANK_RIGHT, 1) )
+ {
+ m_cameraPan = 0.0f;
+ }
+
+ if ( param == m_engine->RetKey(KEYRANK_UP, 0) ||
+ param == m_engine->RetKey(KEYRANK_UP, 1) )
+ {
+ m_cameraZoom = 0.0f;
+ }
+
+ if ( param == m_engine->RetKey(KEYRANK_DOWN, 0) ||
+ param == m_engine->RetKey(KEYRANK_DOWN, 1) )
+ {
+ m_cameraZoom = 0.0f;
+ }
+ }
+
+ if ( m_phase != PHASE_SIMUL ) return;
+ if ( m_bEditLock ) return; // current edition?
+ if ( m_bTrainerPilot ) return;
+
+ pObj = RetSelect();
+ if ( pObj == 0 ) return;
+ if ( !pObj->RetTrainer() ) return;
+
+ if ( event == EVENT_KEYDOWN )
+ {
+ if ( param == m_engine->RetKey(KEYRANK_LEFT, 0) ||
+ param == m_engine->RetKey(KEYRANK_LEFT, 1) )
+ {
+ m_cameraPan = -1.0f;
+ }
+
+ if ( param == m_engine->RetKey(KEYRANK_RIGHT, 0) ||
+ param == m_engine->RetKey(KEYRANK_RIGHT, 1) )
+ {
+ m_cameraPan = 1.0f;
+ }
+
+ if ( param == m_engine->RetKey(KEYRANK_UP, 0) ||
+ param == m_engine->RetKey(KEYRANK_UP, 1) )
+ {
+ m_cameraZoom = -1.0f;
+ }
+
+ if ( param == m_engine->RetKey(KEYRANK_DOWN, 0) ||
+ param == m_engine->RetKey(KEYRANK_DOWN, 1) )
+ {
+ m_cameraZoom = 1.0f;
+ }
+ }
+}
+
+// Panned with the camera if a button is pressed.
+
+void CRobotMain::RemoteCamera(float pan, float zoom, float rTime)
+{
+ float value;
+
+ if ( pan != 0.0f )
+ {
+ value = m_camera->RetRemotePan();
+ value += pan*rTime*1.5f;
+ m_camera->SetRemotePan(value);
+ }
+
+ if ( zoom != 0.0f )
+ {
+ value = m_camera->RetRemoteZoom();
+ value += zoom*rTime*0.3f;
+ m_camera->SetRemoteZoom(value);
+ }
+}
+
+
+
+// Cancels the current movie.
+
+void CRobotMain::AbortMovie()
+{
+ CObject* pObj;
+ CAuto* automat;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ automat = pObj->RetAuto();
+ if ( automat != 0 )
+ {
+ automat->Abort();
+ }
+ }
+
+ m_engine->SetMouseHide(false);
+}
+
+
+
+// Updates the text information.
+
+void CRobotMain::UpdateInfoText()
+{
+ CObject* pObj;
+ Math::Vector pos;
+ char info[100];
+
+ if ( m_bShowPos )
+ {
+ pObj = RetSelect();
+ if ( pObj != 0 )
+ {
+ pos = pObj->RetPosition(0);
+ sprintf(info, "Pos = %.2f ; %.2f", pos.x/g_unit, pos.z/g_unit);
+ m_engine->SetInfoText(4, info);
+ }
+ }
+}
+
+
+// Initializes the view.
+
+void CRobotMain::InitEye()
+{
+ if ( m_phase == PHASE_SIMUL )
+ {
+ m_camera->Init(Math::Vector( 0.0f, 10.0f, 0.0f),
+ Math::Vector(10.0f, 5.0f, 0.0f), 0.0f);
+ }
+
+ if ( m_phase == PHASE_MODEL )
+ {
+ m_model->InitView();
+ }
+}
+
+// Advances the entire scene.
+
+bool CRobotMain::EventFrame(const Event &event)
+{
+ ObjectType type;
+ CObject *pObj, *toto;
+ CPyro* pPyro;
+ CWindow* pw;
+ CMap* pm;
+ int i;
+
+ m_time += event.rTime;
+ if ( !m_bMovieLock ) m_gameTime += event.rTime;
+
+ if ( !m_bImmediatSatCom && !m_bBeginSatCom &&
+ m_gameTime > 0.1f && m_phase == PHASE_SIMUL )
+ {
+ m_displayText->DisplayError(INFO_BEGINSATCOM, Math::Vector(0.0f,0.0f,0.0f));
+ m_bBeginSatCom = true; // message appears
+ }
+
+ m_water->EventProcess(event);
+ m_cloud->EventProcess(event);
+ m_blitz->EventProcess(event);
+ m_planet->EventProcess(event);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw == 0 )
+ {
+ pm = 0;
+ }
+ else
+ {
+ pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
+ if ( pm != 0 ) pm->FlushObject();
+ }
+
+ toto = 0;
+ if ( !m_bFreePhoto )
+ {
+ // Advances all the robots, but not toto.
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pm != 0 ) pm->UpdateObject(pObj);
+ if ( pObj->RetTruck() != 0 ) continue;
+ type = pObj->RetType();
+ if ( type == OBJECT_TOTO )
+ {
+ toto = pObj;
+ }
+ else
+ {
+ pObj->EventProcess(event);
+ }
+ }
+ // Advances all objects transported by robots.
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pObj->RetTruck() == 0 ) continue;
+ pObj->EventProcess(event);
+ }
+
+ // Advances pyrotechnic effects.
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pPyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, i);
+ if ( pPyro == 0 ) break;
+
+ pPyro->EventProcess(event);
+ if ( pPyro->IsEnded() != ERR_CONTINUE )
+ {
+ pPyro->DeleteObject();
+ delete pPyro;
+ }
+ }
+ }
+
+ // The camera follows the object, because its position
+ // may depend on the selected object (CAMERA_ONBOARD or CAMERA_BACK).
+ if ( m_phase == PHASE_SIMUL && !m_bEditFull )
+ {
+ m_camera->EventProcess(event);
+
+ if ( m_engine->RetFog() )
+ {
+ m_camera->SetOverBaseColor(m_particule->RetFogColor(m_engine->RetEyePt()));
+ }
+ }
+ if ( m_phase == PHASE_PERSO ||
+ m_phase == PHASE_WIN ||
+ m_phase == PHASE_LOST )
+ {
+ m_camera->EventProcess(event);
+ }
+
+ // Advances toto following the camera, because its position depends on the camera.
+ if ( toto != 0 )
+ {
+ toto->EventProcess(event);
+ }
+
+ // Advances model.
+ if ( m_phase == PHASE_MODEL )
+ {
+ m_model->ViewMove(event, 2.0f);
+ m_model->UpdateView();
+ m_model->EventProcess(event);
+ }
+
+ HiliteFrame(event.rTime);
+
+ // Moves the film indicator.
+ if ( m_bMovieLock && !m_bEditLock ) // movie in progress?
+ {
+ CControl* pc;
+ Math::Point pos, dim;
+ float zoom;
+
+ pc = m_interface->SearchControl(EVENT_OBJECT_MOVIELOCK);
+ if ( pc != 0 )
+ {
+ dim.x = 32.0f/640.0f;
+ dim.y = 32.0f/480.0f;
+ pos.x = 20.0f/640.0f;
+ pos.y = (480.0f-24.0f)/480.0f;
+
+ zoom = 1.0f+sinf(m_time*6.0f)*0.1f; // 0.9 .. 1.1
+ dim.x *= zoom;
+ dim.y *= zoom;
+ pos.x -= dim.x/2.0f;
+ pos.y -= dim.y/2.0f;
+
+ pc->SetPos(pos);
+ pc->SetDim(dim);
+ }
+ }
+
+ // Moves edition indicator.
+ if ( m_bEditLock || m_bPause ) // edition in progress?
+ {
+ CControl* pc;
+ Math::Point pos, dim;
+ float zoom;
+
+ pc = m_interface->SearchControl(EVENT_OBJECT_EDITLOCK);
+ if ( pc != 0 )
+ {
+ if ( m_bEditFull || m_bEditLock )
+ {
+ dim.x = 10.0f/640.0f;
+ dim.y = 10.0f/480.0f;
+ pos.x = -20.0f/640.0f;
+ pos.y = -20.0f/480.0f; // invisible!
+ }
+ else
+ {
+ dim.x = 32.0f/640.0f;
+ dim.y = 32.0f/480.0f;
+ pos.x = 20.0f/640.0f;
+ pos.y = (480.0f-24.0f)/480.0f;
+
+ zoom = 1.0f+sinf(m_time*6.0f)*0.1f; // 0.9 .. 1.1
+ dim.x *= zoom;
+ dim.y *= zoom;
+ pos.x -= dim.x/2.0f;
+ pos.y -= dim.y/2.0f;
+ }
+ pc->SetPos(pos);
+ pc->SetDim(dim);
+ }
+ }
+
+ // Will move the arrow to visit.
+ if ( m_camera->RetType() == CAMERA_VISIT )
+ {
+ FrameVisit(event.rTime);
+ }
+
+ // Moves the boundaries.
+ FrameShowLimit(event.rTime);
+
+ if ( m_phase == PHASE_SIMUL )
+ {
+ if ( !m_bEditLock && m_checkEndTime+1.0f < m_time )
+ {
+ m_checkEndTime = m_time;
+ CheckEndMission(true);
+ }
+
+ if ( m_winDelay > 0.0f && !m_bEditLock )
+ {
+ m_winDelay -= event.rTime;
+ if ( m_winDelay <= 0.0f )
+ {
+ if ( m_bMovieLock )
+ {
+ m_winDelay = 1.0f;
+ }
+ else
+ {
+ Event newEvent;
+ m_event->MakeEvent(newEvent, EVENT_WIN);
+ m_event->AddEvent(newEvent);
+ }
+ }
+ }
+
+ if ( m_lostDelay > 0.0f && !m_bEditLock )
+ {
+ m_lostDelay -= event.rTime;
+ if ( m_lostDelay <= 0.0f )
+ {
+ if ( m_bMovieLock )
+ {
+ m_winDelay = 1.0f;
+ }
+ else
+ {
+ Event newEvent;
+ m_event->MakeEvent(newEvent, EVENT_LOST);
+ m_event->AddEvent(newEvent);
+ }
+ }
+ }
+ }
+
+ if ( m_delayWriteMessage > 0 )
+ {
+ m_delayWriteMessage --;
+ if ( m_delayWriteMessage == 0 )
+ {
+ m_displayText->DisplayError(INFO_WRITEOK, Math::Vector(0.0f,0.0f,0.0f));
+ }
+ }
+
+ return S_OK;
+}
+
+// Makes the event for all robots.
+
+bool CRobotMain::EventObject(const Event &event)
+{
+ CObject* pObj;
+ int i;
+
+ if ( m_bFreePhoto ) return S_OK;
+
+ m_bResetCreate = false;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ pObj->EventProcess(event);
+ }
+
+ if ( m_bResetCreate )
+ {
+ ResetCreate();
+ }
+
+ return S_OK;
+}
+
+
+// Calculates the point of arrival of the camera.
+
+Math::Vector CRobotMain::LookatPoint(Math::Vector eye, float angleH, float angleV,
+ float length)
+{
+ Math::Vector lookat;
+
+ lookat = eye;
+ lookat.z += length;
+
+ RotatePoint(eye, angleH, angleV, lookat);
+ return lookat;
+}
+
+
+
+char* SkipNum(char *p)
+{
+ while ( *p == ' ' || *p == '.' || *p == '-' || (*p >= '0' && *p <= '9') )
+ {
+ p++;
+ }
+ return p;
+}
+
+// Conversion of units.
+
+void CRobotMain::Convert()
+{
+ FILE* file = NULL;
+ FILE* fileNew = NULL;
+ char line[500];
+ char lineNew[500];
+ char s[200];
+ char* base;
+ char* p;
+ int rank;
+ Math::Vector pos;
+ float value;
+
+ base = m_dialog->RetSceneName();
+ rank = m_dialog->RetSceneRank();
+
+ m_dialog->BuildSceneName(line, base, rank);
+ file = fopen(line, "r");
+ if ( file == NULL ) return;
+
+ strcpy(line+strlen(line)-4, ".new");
+ fileNew = fopen(line, "w");
+ if ( fileNew == NULL ) return;
+
+ while ( fgets(line, 500, file) != NULL )
+ {
+ strcpy(lineNew, line);
+
+ if ( Cmd(line, "DeepView") )
+ {
+ p = strstr(line, "air=");
+ if ( p != 0 )
+ {
+ value = OpFloat(line, "air", 500.0f);
+ value /= g_unit;
+ p[0] = 0;
+ p = SkipNum(p+4);
+ strcpy(lineNew, line);
+ strcat(lineNew, "air=");
+ sprintf(s, "%.2f", value);
+ strcat(lineNew, s);
+ strcat(lineNew, " ");
+ strcat(lineNew, p);
+ }
+ strcpy(line, lineNew);
+
+ p = strstr(line, "water=");
+ if ( p != 0 )
+ {
+ value = OpFloat(line, "water", 100.0f);
+ value /= g_unit;
+ p[0] = 0;
+ p = SkipNum(p+6);
+ strcpy(lineNew, line);
+ strcat(lineNew, "water=");
+ sprintf(s, "%.2f", value);
+ strcat(lineNew, s);
+ strcat(lineNew, " ");
+ strcat(lineNew, p);
+ }
+ strcpy(line, lineNew);
+ }
+
+ if ( Cmd(line, "TerrainGenerate") )
+ {
+ p = strstr(line, "vision=");
+ if ( p != 0 )
+ {
+ value = OpFloat(line, "vision", 500.0f);
+ value /= g_unit;
+ p[0] = 0;
+ p = SkipNum(p+7);
+ strcpy(lineNew, line);
+ strcat(lineNew, "vision=");
+ sprintf(s, "%.2f", value);
+ strcat(lineNew, s);
+ strcat(lineNew, " ");
+ strcat(lineNew, p);
+ }
+ }
+
+ if ( Cmd(line, "CreateObject") ||
+ Cmd(line, "CreateSpot") )
+ {
+ p = strstr(line, "pos=");
+ if ( p != 0 )
+ {
+ pos = OpPos(line, "pos");
+ pos.x /= g_unit;
+ pos.y /= g_unit;
+ pos.z /= g_unit;
+ p[0] = 0;
+ p = SkipNum(p+4);
+ p = SkipNum(p+1);
+ strcpy(lineNew, line);
+ strcat(lineNew, "pos=");
+ sprintf(s, "%.2f", pos.x);
+ strcat(lineNew, s);
+ strcat(lineNew, ";");
+ sprintf(s, "%.2f", pos.z);
+ strcat(lineNew, s);
+ strcat(lineNew, " ");
+ strcat(lineNew, p);
+ }
+ }
+
+ if ( Cmd(line, "EndMissionTake") )
+ {
+ p = strstr(line, "pos=");
+ if ( p != 0 )
+ {
+ pos = OpPos(line, "pos");
+ pos.x /= g_unit;
+ pos.y /= g_unit;
+ pos.z /= g_unit;
+ p[0] = 0;
+ p = SkipNum(p+4);
+ p = SkipNum(p+1);
+ strcpy(lineNew, line);
+ strcat(lineNew, "pos=");
+ sprintf(s, "%.2f", pos.x);
+ strcat(lineNew, s);
+ strcat(lineNew, ";");
+ sprintf(s, "%.2f", pos.z);
+ strcat(lineNew, s);
+ strcat(lineNew, " ");
+ strcat(lineNew, p);
+ }
+ strcpy(line, lineNew);
+
+ p = strstr(line, "dist=");
+ if ( p != 0 )
+ {
+ value = OpFloat(line, "dist", 32.0f);
+ value /= g_unit;
+ p[0] = 0;
+ p = SkipNum(p+5);
+ strcpy(lineNew, line);
+ strcat(lineNew, "dist=");
+ sprintf(s, "%.2f", value);
+ strcat(lineNew, s);
+ strcat(lineNew, " ");
+ strcat(lineNew, p);
+ }
+ strcpy(line, lineNew);
+ }
+
+ if ( Cmd(line, "Camera") )
+ {
+ p = strstr(line, "pos=");
+ if ( p != 0 )
+ {
+ pos = OpPos(line, "pos");
+ pos.x /= g_unit;
+ pos.y /= g_unit;
+ pos.z /= g_unit;
+ p[0] = 0;
+ p = SkipNum(p+4);
+ p = SkipNum(p+1);
+ strcpy(lineNew, line);
+ strcat(lineNew, "pos=");
+ sprintf(s, "%.2f", pos.x);
+ strcat(lineNew, s);
+ strcat(lineNew, ";");
+ sprintf(s, "%.2f", pos.z);
+ strcat(lineNew, s);
+ strcat(lineNew, " ");
+ strcat(lineNew, p);
+ }
+ strcpy(line, lineNew);
+
+ p = strstr(line, "h=");
+ if ( p != 0 )
+ {
+ value = OpFloat(line, "h", 32.0f);
+ value /= g_unit;
+ p[0] = 0;
+ p = SkipNum(p+2);
+ strcpy(lineNew, line);
+ strcat(lineNew, "h=");
+ sprintf(s, "%.2f", value);
+ strcat(lineNew, s);
+ strcat(lineNew, " ");
+ strcat(lineNew, p);
+ }
+ strcpy(line, lineNew);
+ }
+
+ fputs(lineNew, fileNew);
+ }
+
+ fclose(fileNew);
+ fclose(file);
+}
+
+// Load the scene for the character.
+
+void CRobotMain::ScenePerso()
+{
+ CObject* pObj;
+
+ DeleteAllObjects(); // removes all the current 3D Scene
+ m_engine->FlushObject();
+ m_terrain->FlushRelief(); // all flat
+ m_terrain->FlushBuildingLevel();
+ m_terrain->FlushFlyingLimit();
+ m_light->FlushLight();
+ m_particule->FlushParticule();
+ m_iMan->Flush(CLASS_OBJECT);
+ m_iMan->Flush(CLASS_PHYSICS);
+ m_iMan->Flush(CLASS_BRAIN);
+ m_iMan->Flush(CLASS_PYRO);
+
+ m_dialog->SetSceneName("perso");
+ m_dialog->SetSceneRank(0);
+ CreateScene(false, true, false); // sets scene
+
+ m_engine->SetDrawWorld(false); // does not draw anything on the interface
+ m_engine->SetDrawFront(true); // draws on the human interface
+ pObj = SearchHuman();
+ if ( pObj != 0 )
+ {
+ CMotionHuman* mh;
+
+ pObj->SetDrawFront(true); // draws the interface
+
+ mh = (CMotionHuman*)pObj->RetMotion();
+ if ( mh != 0 )
+ {
+ mh->StartDisplayPerso();
+ }
+ }
+}
+
+// Creates the whole stage.
+
+void CRobotMain::CreateScene(bool bSoluce, bool bFixScene, bool bResetObject)
+{
+ CObject* pObj;
+ CObject* pSel;
+ CMotion* motion;
+ FILE* file = NULL;
+ char line[500];
+ char name[200];
+ char dir[100];
+ char op[100];
+ char* read;
+ char* stack;
+ char* base;
+ D3DCOLORVALUE color;
+ Math::Vector pos;
+ int rank, obj, i, rankObj, rankGadget;
+
+//? Convert();
+
+ base = m_dialog->RetSceneName();
+ rank = m_dialog->RetSceneRank();
+ read = m_dialog->RetSceneRead();
+ stack = m_dialog->RetStackRead();
+ m_dialog->SetUserDir(base, rank);
+
+ m_bFixScene = bFixScene;
+
+ g_id = 0;
+ m_bBase = false;
+
+ if ( !bResetObject )
+ {
+ g_build = 0;
+ g_researchDone = 0; // no research done
+ g_researchEnable = 0;
+
+ FlushDisplayInfo();
+ m_terrain->LevelFlush();
+ m_audioTrack = 0;
+ m_bAudioRepeat = true;
+ m_displayText->SetDelay(1.0f);
+ m_displayText->SetEnable(true);
+ m_bImmediatSatCom = false;
+ m_endingWinRank = 0;
+ m_endingLostRank = 0;
+ m_endTakeTotal = 0;
+ m_endTakeResearch = 0;
+ m_endTakeWinDelay = 2.0f;
+ m_endTakeLostDelay = 2.0f;
+ m_obligatoryTotal = 0;
+ m_prohibitedTotal = 0;
+ m_bMapShow = true;
+ m_bMapImage = false;
+ m_mapFilename[0] = 0;
+
+ m_colorRefBot.r = 10.0f/256.0f;
+ m_colorRefBot.g = 166.0f/256.0f;
+ m_colorRefBot.b = 254.0f/256.0f; // blue
+ m_colorRefBot.a = 0.0f;
+ m_colorNewBot = m_colorRefBot;
+
+ m_colorRefAlien.r = 135.0f/256.0f;
+ m_colorRefAlien.g = 170.0f/256.0f;
+ m_colorRefAlien.b = 13.0f/256.0f; // green
+ m_colorRefAlien.a = 0.0f;
+ m_colorNewAlien = m_colorRefAlien;
+
+ m_colorRefGreen.r = 135.0f/256.0f;
+ m_colorRefGreen.g = 170.0f/256.0f;
+ m_colorRefGreen.b = 13.0f/256.0f; // green
+ m_colorRefGreen.a = 0.0f;
+ m_colorNewGreen = m_colorRefGreen;
+
+ m_colorRefWater.r = 25.0f/256.0f;
+ m_colorRefWater.g = 255.0f/256.0f;
+ m_colorRefWater.b = 240.0f/256.0f; // cyan
+ m_colorRefWater.a = 0.0f;
+ m_colorNewWater = m_colorRefWater;
+
+ m_dialog->BuildResumeName(m_title, base, rank);
+ m_dialog->BuildResumeName(m_resume, base, rank);
+ GetResource(RES_TEXT, RT_SCRIPT_NEW, m_scriptName);
+ m_scriptFile[0] = 0;
+ }
+
+ m_dialog->BuildSceneName(line, base, rank);
+ file = fopen(line, "r");
+ if ( file == NULL ) return;
+
+ rankObj = 0;
+ rankGadget = 0;
+ pSel = 0;
+
+ while ( fgets(line, 500, file) != NULL )
+ {
+ for ( i=0 ; i<500 ; i++ )
+ {
+ if ( line[i] == '\t' ) line[i] = ' '; // replace tab by space
+ if ( line[i] == '/' && line[i+1] == '/' )
+ {
+ line[i] = 0;
+ break;
+ }
+ }
+
+ sprintf(op, "Title.%c", RetLanguageLetter());
+ if ( Cmd(line, op) && !bResetObject )
+ {
+ OpString(line, "text", m_title);
+ }
+
+ sprintf(op, "Resume.%c", RetLanguageLetter());
+ if ( Cmd(line, op) && !bResetObject )
+ {
+ OpString(line, "text", m_resume);
+ }
+
+ sprintf(op, "ScriptName.%c", RetLanguageLetter());
+ if ( Cmd(line, op) && !bResetObject )
+ {
+ OpString(line, "text", m_scriptName);
+ }
+
+ if ( Cmd(line, "ScriptFile") && !bResetObject )
+ {
+ OpString(line, "name", m_scriptFile);
+ }
+
+ if ( Cmd(line, "Instructions") && !bResetObject )
+ {
+ OpString(line, "name", name);
+//? sprintf(m_infoFilename[SATCOM_HUSTON], "help\\%s", name);
+ UserDir(m_infoFilename[SATCOM_HUSTON], name, "help");
+
+ m_bImmediatSatCom = OpInt(line, "immediat", 0);
+ }
+
+ if ( Cmd(line, "Satellite") && !bResetObject )
+ {
+ OpString(line, "name", name);
+//? sprintf(m_infoFilename[SATCOM_SAT], "help\\%s", name);
+ UserDir(m_infoFilename[SATCOM_SAT], name, "help");
+ }
+
+ if ( Cmd(line, "Loading") && !bResetObject )
+ {
+ OpString(line, "name", name);
+//? sprintf(m_infoFilename[SATCOM_LOADING], "help\\%s", name);
+ UserDir(m_infoFilename[SATCOM_LOADING], name, "help");
+ }
+
+ if ( Cmd(line, "HelpFile") && !bResetObject )
+ {
+ OpString(line, "name", name);
+//? sprintf(m_infoFilename[SATCOM_PROG], "help\\%s", name);
+ UserDir(m_infoFilename[SATCOM_PROG], name, "help");
+ }
+ if ( Cmd(line, "SoluceFile") && !bResetObject )
+ {
+ OpString(line, "name", name);
+//? sprintf(m_infoFilename[SATCOM_SOLUCE], "help\\%s", name);
+ UserDir(m_infoFilename[SATCOM_SOLUCE], name, "help");
+ }
+
+ if ( Cmd(line, "EndingFile") && !bResetObject )
+ {
+ m_endingWinRank = OpInt(line, "win", 0);
+ m_endingLostRank = OpInt(line, "lost", 0);
+ }
+
+ if ( Cmd(line, "MessageDelay") && !bResetObject )
+ {
+ m_displayText->SetDelay(OpFloat(line, "factor", 1.0f));
+ }
+
+ if ( Cmd(line, "Audio") && !bResetObject )
+ {
+ m_audioTrack = OpInt(line, "track", 0);
+ m_bAudioRepeat = OpInt(line, "repeat", 1);
+ }
+
+ if ( Cmd(line, "AmbiantColor") && !bResetObject )
+ {
+ m_engine->SetAmbiantColor(OpColor(line, "air", 0x88888888), 0);
+ m_engine->SetAmbiantColor(OpColor(line, "water", 0x88888888), 1);
+ }
+
+ if ( Cmd(line, "FogColor") && !bResetObject )
+ {
+ m_engine->SetFogColor(OpColor(line, "air", 0x88888888), 0);
+ m_engine->SetFogColor(OpColor(line, "water", 0x88888888), 1);
+ }
+
+ if ( Cmd(line, "VehicleColor") && !bResetObject )
+ {
+ m_colorNewBot = RetColor(OpColor(line, "color", 0x88888888));
+ }
+
+ if ( Cmd(line, "InsectColor") && !bResetObject )
+ {
+ m_colorNewAlien = RetColor(OpColor(line, "color", 0x88888888));
+ }
+
+ if ( Cmd(line, "GreeneryColor") && !bResetObject )
+ {
+ m_colorNewGreen = RetColor(OpColor(line, "color", 0x88888888));
+ }
+
+ if ( Cmd(line, "DeepView") && !bResetObject )
+ {
+ m_engine->SetDeepView(OpFloat(line, "air", 500.0f)*UNIT, 0, true);
+ m_engine->SetDeepView(OpFloat(line, "water", 100.0f)*UNIT, 1, true);
+ }
+
+ if ( Cmd(line, "FogStart") && !bResetObject )
+ {
+ m_engine->SetFogStart(OpFloat(line, "air", 0.5f), 0);
+ m_engine->SetFogStart(OpFloat(line, "water", 0.5f), 1);
+ }
+
+ if ( Cmd(line, "SecondTexture") && !bResetObject )
+ {
+ m_engine->SetSecondTexture(OpInt(line, "rank", 1));
+ }
+
+ if ( Cmd(line, "Background") && !bResetObject )
+ {
+ OpString(line, "image", name);
+ UserDir(dir, name, "");
+ m_engine->SetBackground(dir,
+ OpColor(line, "up", 0x00000000),
+ OpColor(line, "down", 0x00000000),
+ OpColor(line, "cloudUp", 0x00000000),
+ OpColor(line, "cloudDown", 0x00000000),
+ OpInt(line, "full", 0));
+ }
+
+ if ( Cmd(line, "Planet") && !bResetObject )
+ {
+ Math::Vector ppos, uv1, uv2;
+
+ ppos = OpPos(line, "pos");
+ uv1 = OpPos(line, "uv1");
+ uv2 = OpPos(line, "uv2");
+ OpString(line, "image", name);
+ UserDir(dir, name, "");
+ m_planet->Create(OpInt(line, "mode", 0),
+ Math::Point(ppos.x, ppos.z),
+ OpFloat(line, "dim", 0.2f),
+ OpFloat(line, "speed", 0.0f),
+ OpFloat(line, "dir", 0.0f),
+ dir,
+ Math::Point(uv1.x, uv1.z),
+ Math::Point(uv2.x, uv2.z));
+ }
+
+ if ( Cmd(line, "FrontsizeName") && !bResetObject )
+ {
+ OpString(line, "image", name);
+ UserDir(dir, name, "");
+ m_engine->SetFrontsizeName(dir);
+ }
+
+ if ( Cmd(line, "Global") && !bResetObject )
+ {
+ g_unit = OpFloat(line, "unitScale", 4.0f);
+ m_engine->SetTracePrecision(OpFloat(line, "traceQuality", 1.0f));
+ m_bShortCut = OpInt(line, "shortcut", 1);
+ }
+
+ if ( Cmd(line, "TerrainGenerate") && !bResetObject )
+ {
+ m_terrain->Generate(OpInt(line, "mosaic", 20),
+ OpInt(line, "brick", 3),
+ OpFloat(line, "size", 20.0f),
+ OpFloat(line, "vision", 500.0f)*UNIT,
+ OpInt(line, "depth", 2),
+ OpFloat(line, "hard", 0.5f));
+ }
+
+ if ( Cmd(line, "TerrainWind") && !bResetObject )
+ {
+ m_terrain->SetWind(OpPos(line, "speed"));
+ }
+
+ if ( Cmd(line, "TerrainRelief") && !bResetObject )
+ {
+ OpString(line, "image", name);
+ UserDir(dir, name, "textures");
+ m_terrain->ReliefFromBMP(dir, OpFloat(line, "factor", 1.0f), OpInt(line, "border", 1));
+ }
+
+ if ( Cmd(line, "TerrainReliefDXF") && !bResetObject )
+ {
+ OpString(line, "image", name);
+ UserDir(dir, name, "textures");
+ m_terrain->ReliefFromDXF(dir, OpFloat(line, "factor", 1.0f));
+ }
+
+ if ( Cmd(line, "TerrainResource") && !bResetObject )
+ {
+ OpString(line, "image", name);
+ UserDir(dir, name, "textures");
+ m_terrain->ResFromBMP(dir);
+ }
+
+ if ( Cmd(line, "TerrainWater") && !bResetObject )
+ {
+ OpString(line, "image", name);
+ UserDir(dir, name, "");
+ pos.x = OpFloat(line, "moveX", 0.0f);
+ pos.y = OpFloat(line, "moveY", 0.0f);
+ pos.z = pos.x;
+ m_water->Create(OpTypeWater(line, "air", WATER_TT),
+ OpTypeWater(line, "water", WATER_TT),
+ dir,
+ RetColor(OpColor(line, "diffuse", 0xffffffff)),
+ RetColor(OpColor(line, "ambiant", 0xffffffff)),
+ OpFloat(line, "level", 100.0f)*UNIT,
+ OpFloat(line, "glint", 1.0f),
+ pos);
+ m_colorNewWater = RetColor(OpColor(line, "color", RetColor(m_colorRefWater)));
+ m_colorShiftWater = OpFloat(line, "brightness", 0.0f);
+ }
+
+ if ( Cmd(line, "TerrainLava") && !bResetObject )
+ {
+ m_water->SetLava(OpInt(line, "mode", 0));
+ }
+
+ if ( Cmd(line, "TerrainCloud") && !bResetObject )
+ {
+ OpString(line, "image", name);
+ UserDir(dir, name, "");
+ m_cloud->Create(dir,
+ RetColor(OpColor(line, "diffuse", 0xffffffff)),
+ RetColor(OpColor(line, "ambiant", 0xffffffff)),
+ OpFloat(line, "level", 500.0f)*UNIT);
+ }
+
+ if ( Cmd(line, "TerrainBlitz") && !bResetObject )
+ {
+ m_blitz->Create(OpFloat(line, "sleep", 0.0f),
+ OpFloat(line, "delay", 3.0f),
+ OpFloat(line, "magnetic", 50.0f)*UNIT);
+ }
+
+ if ( Cmd(line, "TerrainInitTextures") && !bResetObject )
+ {
+ int dx, dy, tt[100];
+ char* op;
+
+ OpString(line, "image", name);
+ AddExt(name, ".tga");
+ dx = OpInt(line, "dx", 1);
+ dy = OpInt(line, "dy", 1);
+ op = SearchOp(line, "table");
+ for ( i=0 ; i<dx*dy ; i++ )
+ {
+ tt[i] = GetInt(op, i, 0);
+ }
+
+ if ( strstr(name, "%user%") != 0 )
+ {
+ CopyFileListToTemp(name, tt, dx*dy);
+ }
+
+ m_terrain->InitTextures(name, tt, dx, dy);
+ }
+
+ if ( Cmd(line, "TerrainInit") && !bResetObject )
+ {
+ m_terrain->LevelInit(OpInt(line, "id", 1));
+ }
+
+ if ( Cmd(line, "TerrainMaterial") && !bResetObject )
+ {
+ OpString(line, "image", name);
+ AddExt(name, ".tga");
+ if ( strstr(name, "%user%") != 0 )
+ {
+ CopyFileToTemp(name);
+ }
+
+ m_terrain->LevelMaterial(OpInt(line, "id", 0),
+ name,
+ OpFloat(line, "u", 0.0f),
+ OpFloat(line, "v", 0.0f),
+ OpInt(line, "up", 1),
+ OpInt(line, "right", 1),
+ OpInt(line, "down", 1),
+ OpInt(line, "left", 1),
+ OpFloat(line, "hard", 0.5f));
+ }
+
+ if ( Cmd(line, "TerrainLevel") && !bResetObject )
+ {
+ int id[50];
+ char* op;
+
+ op = SearchOp(line, "id");
+ i = 0;
+ while ( true )
+ {
+ id[i] = GetInt(op, i, 0);
+ if ( id[i++] == 0 ) break;
+ }
+
+ m_terrain->LevelGenerate(id,
+ OpFloat(line, "min", 0.0f)*UNIT,
+ OpFloat(line, "max", 100.0f)*UNIT,
+ OpFloat(line, "slope", 5.0f),
+ OpFloat(line, "freq", 100.0f),
+ OpPos(line, "center")*g_unit,
+ OpFloat(line, "radius", 0.0f)*g_unit);
+ }
+
+ if ( Cmd(line, "TerrainCreate") && !bResetObject )
+ {
+ m_terrain->CreateObjects(true);
+ }
+
+ if ( Cmd(line, "BeginObject") )
+ {
+ InitEye();
+ SetMovieLock(false);
+ if ( !m_bFixScene )
+ {
+//? CreateObject(Math::Vector(0.0f, 0.0f, 0.0f), 0.0f, 0.0f, OBJECT_TOTO);
+ }
+
+ if ( read[0] != 0 ) // loading file ?
+ {
+ pSel = IOReadScene(read, stack);
+ }
+ }
+
+ if ( Cmd(line, "CreateObject") && read[0] == 0 )
+ {
+ CObject* pObj;
+ CBrain* pBrain;
+ CAuto* pAuto;
+ CPyro* pyro;
+ ObjectType type;
+ PyroType pType;
+ CameraType cType;
+ Info info;
+ float dir;
+ char op[20];
+ char text[100];
+ char* p;
+ int run, gadget;
+
+ type = OpTypeObject(line, "type", OBJECT_NULL);
+
+ gadget = OpInt(line, "gadget", -1);
+ if ( gadget == -1 )
+ {
+ gadget = 0;
+ if ( type == OBJECT_TECH ||
+ (type >= OBJECT_PLANT0 &&
+ type <= OBJECT_PLANT19 ) ||
+ (type >= OBJECT_TREE0 &&
+ type <= OBJECT_TREE9 ) ||
+ (type >= OBJECT_TEEN0 &&
+ type <= OBJECT_TEEN49 ) ||
+ (type >= OBJECT_QUARTZ0 &&
+ type <= OBJECT_QUARTZ9 ) ||
+ (type >= OBJECT_ROOT0 &&
+ type <= OBJECT_ROOT4 ) ) // not ROOT5!
+ {
+ if ( type != OBJECT_TEEN11 && // lamp?
+ type != OBJECT_TEEN12 && // coke?
+ type != OBJECT_TEEN20 && // wall?
+ type != OBJECT_TEEN21 && // wall?
+ type != OBJECT_TEEN22 && // wall?
+ type != OBJECT_TEEN26 && // lamp?
+ type != OBJECT_TEEN28 && // bottle?
+ type != OBJECT_TEEN34 ) // stone?
+ {
+ gadget = 1;
+ }
+ }
+ }
+ if ( gadget != 0 ) // is this a gadget?
+ {
+ if ( !TestGadgetQuantity(rankGadget++) ) continue;
+ }
+
+ pos = OpPos(line, "pos")*g_unit;
+ dir = OpFloat(line, "dir", 0.0f)*Math::PI;
+ pObj = CreateObject(pos, dir,
+ OpFloat(line, "z", 1.0f),
+ OpFloat(line, "h", 0.0f),
+ type,
+ OpFloat(line, "power", 1.0f),
+ OpInt(line, "trainer", 0),
+ OpInt(line, "toy", 0),
+ OpInt(line, "option", 0));
+
+ if ( pObj != 0 )
+ {
+ pObj->SetDefRank(rankObj);
+
+ if ( type == OBJECT_BASE ) m_bBase = true;
+
+ cType = OpCamera(line, "camera");
+ if ( cType != CAMERA_NULL )
+ {
+ pObj->SetCameraType(cType);
+ }
+ pObj->SetCameraDist(OpFloat(line, "cameraDist", 50.0f));
+ pObj->SetCameraLock(OpInt(line, "cameraLock", 0));
+
+ pType = OpPyro(line, "pyro");
+ if ( pType != PT_NULL )
+ {
+ pyro = new CPyro(m_iMan);
+ pyro->Create(pType, pObj);
+ }
+
+ // Puts information in terminal (OBJECT_INFO).
+ for ( i=0 ; i<OBJECTMAXINFO ; i++ )
+ {
+ sprintf(op, "info%d", i+1);
+ OpString(line, op, text);
+ if ( text[0] == 0 ) break;
+ p = strchr(text, '=');
+ if ( p == 0 ) break;
+ *p = 0;
+ strcpy(info.name, text);
+ sscanf(p+1, "%f", &info.value);
+ pObj->SetInfo(i, info);
+ }
+
+ // Sets the parameters of the command line.
+ p = SearchOp(line, "cmdline");
+ for ( i=0 ; i<OBJECTMAXCMDLINE ; i++ )
+ {
+ float value;
+ value = GetFloat(p, i, NAN);
+ if ( value == NAN ) break;
+ pObj->SetCmdLine(i, value);
+ }
+
+ if ( OpInt(line, "select", 0) == 1 )
+ {
+ pSel = pObj;
+ }
+
+ pObj->SetSelectable(OpInt(line, "selectable", 1));
+ pObj->SetEnable(OpInt(line, "enable", 1));
+ pObj->SetProxyActivate(OpInt(line, "proxyActivate", 0));
+ pObj->SetProxyDistance(OpFloat(line, "proxyDistance", 15.0f)*g_unit);
+ pObj->SetRange(OpFloat(line, "range", 30.0f));
+ pObj->SetShield(OpFloat(line, "shield", 1.0f));
+ pObj->SetMagnifyDamage(OpFloat(line, "magnifyDamage", 1.0f));
+ pObj->SetClip(OpInt(line, "clip", 1));
+ pObj->SetCheckToken(OpInt(line, "checkToken", 1));
+ pObj->SetManual(OpInt(line, "manual", 0));
+
+ motion = pObj->RetMotion();
+ if ( motion != 0 )
+ {
+ p = SearchOp(line, "param");
+ for ( i=0 ; i<10 ; i++ )
+ {
+ float value;
+ value = GetFloat(p, i, NAN);
+ if ( value == NAN ) break;
+ motion->SetParam(i, value);
+ }
+ }
+
+ run = -1;
+ pBrain = pObj->RetBrain();
+ if ( pBrain != 0 )
+ {
+ for ( i=0 ; i<10 ; i++ )
+ {
+ sprintf(op, "script%d", i+1); // script1..script10
+ OpString(line, op, name);
+#if _SCHOOL
+ if ( !m_dialog->RetSoluce4() && i == 3 ) continue;
+#endif
+ if ( name[0] != 0 )
+ {
+ pBrain->SetScriptName(i, name);
+ }
+ }
+
+ i = OpInt(line, "run", 0);
+ if ( i != 0 )
+ {
+ run = i-1;
+ pBrain->SetScriptRun(run);
+ }
+ }
+ pAuto = pObj->RetAuto();
+ if ( pAuto != 0 )
+ {
+ type = OpTypeObject(line, "autoType", OBJECT_NULL);
+ pAuto->SetType(type);
+ for ( i=0 ; i<5 ; i++ )
+ {
+ sprintf(op, "autoValue%d", i+1); // autoValue1..autoValue5
+ pAuto->SetValue(i, OpFloat(line, op, 0.0f));
+ }
+ OpString(line, "autoString", name);
+ pAuto->SetString(name);
+
+ i = OpInt(line, "run", -1);
+ if ( i != -1 )
+ {
+ if ( i != PARAM_FIXSCENE &&
+ !m_dialog->RetMovies() ) i = 0;
+ pAuto->Start(i); // starts the film
+ }
+ }
+
+ OpString(line, "soluce", name);
+ if ( bSoluce && pBrain != 0 && name[0] != 0 )
+ {
+ pBrain->SetSoluceName(name);
+ }
+
+ pObj->SetResetPosition(pObj->RetPosition(0));
+ pObj->SetResetAngle(pObj->RetAngle(0));
+ pObj->SetResetRun(run);
+
+ if ( OpInt(line, "reset", 0) == 1 )
+ {
+ pObj->SetResetCap(RESET_MOVE);
+ }
+ }
+
+ rankObj ++;
+ }
+
+ if ( Cmd(line, "CreateFog") && !bResetObject )
+ {
+ ParticuleType type;
+ Math::Point dim;
+ float height, ddim, delay;
+
+ type = (ParticuleType)(PARTIFOG0+OpInt(line, "type", 0));
+ pos = OpPos(line, "pos")*g_unit;
+ height = OpFloat(line, "height", 1.0f)*g_unit;
+ ddim = OpFloat(line, "dim", 50.0f)*g_unit;
+ delay = OpFloat(line, "delay", 2.0f);
+ m_terrain->MoveOnFloor(pos);
+ pos.y += height;
+ dim.x = ddim;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), dim, type, delay, 0.0f, 0.0f);
+ }
+
+ if ( Cmd(line, "CreateLight") && !bResetObject )
+ {
+ D3DTypeObj type;
+
+ color.r = 0.5f;
+ color.g = 0.5f;
+ color.b = 0.5f;
+ color.a = 1.0f;
+ obj = CreateLight(OpDir(line, "dir"),
+ OpColorValue(line, "color", color));
+
+ type = OpTypeTerrain(line, "type", TYPENULL);
+ if ( type == TYPETERRAIN )
+ {
+ m_light->SetLightIncluType(obj, TYPETERRAIN);
+ }
+ if ( type == TYPEQUARTZ )
+ {
+ m_light->SetLightIncluType(obj, TYPEQUARTZ);
+ }
+ if ( type == TYPEMETAL )
+ {
+ m_light->SetLightIncluType(obj, TYPEMETAL);
+ }
+ if ( type == TYPEFIX )
+ {
+ m_light->SetLightExcluType(obj, TYPETERRAIN);
+ }
+ }
+ if ( Cmd(line, "CreateSpot") && !bResetObject )
+ {
+ D3DTypeObj type;
+
+ color.r = 0.5f;
+ color.g = 0.5f;
+ color.b = 0.5f;
+ color.a = 1.0f;
+ obj = CreateSpot(OpDir(line, "pos")*g_unit,
+ OpColorValue(line, "color", color));
+
+ type = OpTypeTerrain(line, "type", TYPENULL);
+ if ( type == TYPETERRAIN )
+ {
+ m_light->SetLightIncluType(obj, TYPETERRAIN);
+ }
+ if ( type == TYPEQUARTZ )
+ {
+ m_light->SetLightIncluType(obj, TYPEQUARTZ);
+ }
+ if ( type == TYPEMETAL )
+ {
+ m_light->SetLightIncluType(obj, TYPEMETAL);
+ }
+ if ( type == TYPEFIX )
+ {
+ m_light->SetLightExcluType(obj, TYPETERRAIN);
+ }
+ }
+
+ if ( Cmd(line, "GroundSpot") && !bResetObject )
+ {
+ rank = m_engine->GroundSpotCreate();
+ if ( rank != -1 )
+ {
+ m_engine->SetObjectGroundSpotPos(rank, OpPos(line, "pos")*g_unit);
+ m_engine->SetObjectGroundSpotRadius(rank, OpFloat(line, "radius", 10.0f)*g_unit);
+ m_engine->SetObjectGroundSpotColor(rank, RetColor(OpColor(line, "color", 0x88888888)));
+ m_engine->SetObjectGroundSpotSmooth(rank, OpFloat(line, "smooth", 1.0f));
+ m_engine->SetObjectGroundSpotMinMax(rank, OpFloat(line, "min", 0.0f)*g_unit,
+ OpFloat(line, "max", 0.0f)*g_unit);
+ }
+ }
+
+ if ( Cmd(line, "WaterColor") && !bResetObject )
+ {
+ color.r = 0.0f;
+ color.g = 0.0f;
+ color.b = 0.0f;
+ color.a = 1.0f;
+ m_engine->SetWaterAddColor(OpColorValue(line, "color", color));
+ }
+
+ if ( Cmd(line, "MapColor") && !bResetObject )
+ {
+ m_map->FloorColorMap(RetColor(OpColor(line, "floor", 0x88888888)),
+ RetColor(OpColor(line, "water", 0x88888888)));
+ m_bMapShow = OpInt(line, "show", 1);
+ m_map->ShowMap(m_bMapShow);
+ m_map->SetToy(OpInt(line, "toyIcon", 0));
+ m_bMapImage = OpInt(line, "image", 0);
+ if ( m_bMapImage )
+ {
+ Math::Vector offset;
+ OpString(line, "filename", m_mapFilename);
+ offset = OpPos(line, "offset");
+ m_map->SetFixParam(OpFloat(line, "zoom", 1.0f),
+ offset.x, offset.z,
+ OpFloat(line, "angle", 0.0f)*Math::PI/180.0f,
+ OpInt(line, "mode", 0),
+ OpInt(line, "debug", 0));
+ }
+ }
+ if ( Cmd(line, "MapZoom") && !bResetObject )
+ {
+ m_map->ZoomMap(OpFloat(line, "factor", 2.0f));
+ m_map->MapEnable(OpInt(line, "enable", 1));
+ }
+
+ if ( Cmd(line, "MaxFlyingHeight") && !bResetObject )
+ {
+ m_terrain->SetFlyingMaxHeight(OpFloat(line, "max", 280.0f)*g_unit);
+ }
+ if ( Cmd(line, "AddFlyingHeight") && !bResetObject )
+ {
+ m_terrain->AddFlyingLimit(OpPos(line, "center")*g_unit,
+ OpFloat(line, "extRadius", 20.0f)*g_unit,
+ OpFloat(line, "intRadius", 10.0f)*g_unit,
+ OpFloat(line, "maxHeight", 200.0f));
+ }
+
+ if ( Cmd(line, "Camera") )
+ {
+ m_camera->Init(OpDir(line, "eye")*g_unit,
+ OpDir(line, "lookat")*g_unit,
+ bResetObject?0.0f:OpFloat(line, "delay", 0.0f));
+
+ if ( OpInt(line, "fadeIn", 0) == 1 )
+ {
+ m_camera->StartOver(OE_FADEINw, Math::Vector(0.0f, 0.0f, 0.0f), 1.0f);
+ }
+ m_camera->SetFixDirection(OpFloat(line, "fixDirection", 0.25f)*Math::PI);
+ }
+
+ if ( Cmd(line, "EndMissionTake") && !bResetObject )
+ {
+ i = m_endTakeTotal;
+ if ( i < 10 )
+ {
+ m_endTake[i].pos = OpPos(line, "pos")*g_unit;
+ m_endTake[i].dist = OpFloat(line, "dist", 8.0f)*g_unit;
+ m_endTake[i].type = OpTypeObject(line, "type", OBJECT_NULL);
+ m_endTake[i].min = OpInt(line, "min", 1);
+ m_endTake[i].max = OpInt(line, "max", 9999);
+ m_endTake[i].lost = OpInt(line, "lost", -1);
+ m_endTake[i].bImmediat = OpInt(line, "immediat", 0);
+ OpString(line, "message", m_endTake[i].message);
+ m_endTakeTotal ++;
+ }
+ }
+ if ( Cmd(line, "EndMissionDelay") && !bResetObject )
+ {
+ m_endTakeWinDelay = OpFloat(line, "win", 2.0f);
+ m_endTakeLostDelay = OpFloat(line, "lost", 2.0f);
+ }
+ if ( Cmd(line, "EndMissionResearch") && !bResetObject )
+ {
+ m_endTakeResearch |= OpResearch(line, "type");
+ }
+
+ if ( Cmd(line, "ObligatoryToken") && !bResetObject )
+ {
+ i = m_obligatoryTotal;
+ if ( i < 100 )
+ {
+ OpString(line, "text", m_obligatoryToken[i]);
+ m_obligatoryTotal ++;
+ }
+ }
+
+ if ( Cmd(line, "ProhibitedToken") && !bResetObject )
+ {
+ i = m_prohibitedTotal;
+ if ( i < 100 )
+ {
+ OpString(line, "text", m_prohibitedToken[i]);
+ m_prohibitedTotal ++;
+ }
+ }
+
+ if ( Cmd(line, "EnableBuild") && !bResetObject )
+ {
+ g_build |= OpBuild(line, "type");
+ }
+
+ if ( Cmd(line, "EnableResearch") && !bResetObject )
+ {
+ g_researchEnable |= OpResearch(line, "type");
+ }
+ if ( Cmd(line, "DoneResearch") && read[0] == 0 && !bResetObject ) // not loading file?
+ {
+ g_researchDone |= OpResearch(line, "type");
+ }
+
+ if ( Cmd(line, "NewScript") && !bResetObject )
+ {
+ OpString(line, "name", name);
+ AddNewScriptName(OpTypeObject(line, "type", OBJECT_NULL), name);
+ }
+ }
+
+ fclose(file);
+
+ if ( read[0] == 0 )
+ {
+ CompileScript(bSoluce); // compiles all scripts
+ }
+
+ if ( strcmp(base, "scene") == 0 && !bResetObject ) // mission?
+ {
+ WriteFreeParam();
+ }
+ if ( strcmp(base, "free") == 0 && !bResetObject ) // free play?
+ {
+ g_researchDone = m_freeResearch;
+
+ g_build = m_freeBuild;
+ g_build &= ~BUILD_RESEARCH;
+ g_build &= ~BUILD_LABO;
+ g_build |= BUILD_FACTORY;
+ g_build |= BUILD_GFLAT;
+ g_build |= BUILD_FLAG;
+ }
+
+ if ( !bResetObject )
+ {
+ ChangeColor(); // changes the colors of texture
+ m_short->SetMode(false); // vehicles?
+ }
+
+ CreateShortcuts();
+ m_map->UpdateMap();
+ m_engine->TimeInit();
+ m_engine->FlushPressKey();
+ m_time = 0.0f;
+ m_gameTime = 0.0f;
+ m_checkEndTime = 0.0f;
+ m_infoUsed = 0;
+
+ m_selectObject = pSel;
+
+ if ( !m_bBase && // no main base?
+ !m_bFixScene ) // interractive scene?
+ {
+ if ( pSel == 0 )
+ {
+ pObj = SearchHuman();
+ }
+ else
+ {
+ pObj = pSel;
+ }
+ if ( pObj != 0 )
+ {
+ SelectObject(pObj);
+ m_camera->SetObject(pObj);
+//? m_camera->SetType(CAMERA_BACK);
+ m_camera->SetType(pObj->RetCameraType());
+ }
+ }
+ if ( m_bFixScene )
+ {
+ m_camera->SetType(CAMERA_SCRIPT);
+ }
+
+ if ( read[0] != 0 && pSel != 0 ) // loading file?
+ {
+ pos = pSel->RetPosition(0);
+ m_camera->Init(pos, pos, 0.0f);
+ m_camera->FixCamera();
+
+ SelectObject(pSel);
+ m_camera->SetObject(pSel);
+
+ m_bBeginSatCom = true; // message already displayed
+ }
+ m_dialog->SetSceneRead("");
+ m_dialog->SetStackRead("");
+}
+
+// Creates an object of decoration mobile or stationary.
+
+CObject* CRobotMain::CreateObject(Math::Vector pos, float angle, float zoom, float height,
+ ObjectType type, float power,
+ bool bTrainer, bool bToy,
+ int option)
+{
+ CObject* pObject = 0;
+ CAuto* automat;
+
+ if ( type == OBJECT_NULL ) return 0;
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH )
+ {
+ bTrainer = false; // necessarily
+ }
+
+ if ( type == OBJECT_PORTICO ||
+ type == OBJECT_BASE ||
+ type == OBJECT_DERRICK ||
+ type == OBJECT_FACTORY ||
+ type == OBJECT_STATION ||
+ type == OBJECT_CONVERT ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_DESTROYER||
+ type == OBJECT_TOWER ||
+ type == OBJECT_NEST ||
+ 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 ||
+ type == OBJECT_TARGET1 ||
+ type == OBJECT_TARGET2 ||
+ type == OBJECT_START ||
+ type == OBJECT_END )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateBuilding(pos, angle, height, type, power);
+
+ automat = pObject->RetAuto();
+ if ( automat != 0 )
+ {
+ automat->Init();
+ }
+ }
+ else
+ if ( type == OBJECT_FRET ||
+ type == OBJECT_STONE ||
+ type == OBJECT_URANIUM ||
+ type == OBJECT_METAL ||
+ type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC ||
+ type == OBJECT_BULLET ||
+ type == OBJECT_BBOX ||
+ type == OBJECT_KEYa ||
+ type == OBJECT_KEYb ||
+ type == OBJECT_KEYc ||
+ type == OBJECT_KEYd ||
+ type == OBJECT_TNT ||
+ type == OBJECT_SCRAP1 ||
+ type == OBJECT_SCRAP2 ||
+ type == OBJECT_SCRAP3 ||
+ type == OBJECT_SCRAP4 ||
+ type == OBJECT_SCRAP5 ||
+ type == OBJECT_BOMB ||
+ type == OBJECT_WAYPOINT ||
+ type == OBJECT_SHOW ||
+ type == OBJECT_WINFIRE ||
+ type == OBJECT_BAG ||
+ type == OBJECT_MARKPOWER ||
+ type == OBJECT_MARKSTONE ||
+ type == OBJECT_MARKURANIUM ||
+ type == OBJECT_MARKKEYa ||
+ type == OBJECT_MARKKEYb ||
+ type == OBJECT_MARKKEYc ||
+ type == OBJECT_MARKKEYd ||
+ type == OBJECT_EGG )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateResource(pos, angle, type, power);
+ }
+ else
+ if ( type == OBJECT_FLAGb ||
+ type == OBJECT_FLAGr ||
+ type == OBJECT_FLAGg ||
+ type == OBJECT_FLAGy ||
+ type == OBJECT_FLAGv )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateFlag(pos, angle, type);
+ }
+ else
+ if ( type == OBJECT_BARRIER0 ||
+ type == OBJECT_BARRIER1 ||
+ type == OBJECT_BARRIER2 ||
+ type == OBJECT_BARRIER3 ||
+ type == OBJECT_BARRIER4 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateBarrier(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_PLANT0 ||
+ type == OBJECT_PLANT1 ||
+ type == OBJECT_PLANT2 ||
+ type == OBJECT_PLANT3 ||
+ type == OBJECT_PLANT4 ||
+ type == OBJECT_PLANT5 ||
+ type == OBJECT_PLANT6 ||
+ type == OBJECT_PLANT7 ||
+ type == OBJECT_PLANT8 ||
+ type == OBJECT_PLANT9 ||
+ type == OBJECT_PLANT10 ||
+ type == OBJECT_PLANT11 ||
+ type == OBJECT_PLANT12 ||
+ type == OBJECT_PLANT13 ||
+ type == OBJECT_PLANT14 ||
+ type == OBJECT_PLANT15 ||
+ type == OBJECT_PLANT16 ||
+ type == OBJECT_PLANT17 ||
+ type == OBJECT_PLANT18 ||
+ type == OBJECT_PLANT19 ||
+ type == OBJECT_TREE0 ||
+ type == OBJECT_TREE1 ||
+ type == OBJECT_TREE2 ||
+ type == OBJECT_TREE3 ||
+ type == OBJECT_TREE4 ||
+ type == OBJECT_TREE5 ||
+ type == OBJECT_TREE6 ||
+ type == OBJECT_TREE7 ||
+ type == OBJECT_TREE8 ||
+ type == OBJECT_TREE9 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreatePlant(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_MUSHROOM0 ||
+ type == OBJECT_MUSHROOM1 ||
+ type == OBJECT_MUSHROOM2 ||
+ type == OBJECT_MUSHROOM3 ||
+ type == OBJECT_MUSHROOM4 ||
+ type == OBJECT_MUSHROOM5 ||
+ type == OBJECT_MUSHROOM6 ||
+ type == OBJECT_MUSHROOM7 ||
+ type == OBJECT_MUSHROOM8 ||
+ type == OBJECT_MUSHROOM9 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateMushroom(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_TEEN0 ||
+ type == OBJECT_TEEN1 ||
+ type == OBJECT_TEEN2 ||
+ type == OBJECT_TEEN3 ||
+ type == OBJECT_TEEN4 ||
+ type == OBJECT_TEEN5 ||
+ type == OBJECT_TEEN6 ||
+ type == OBJECT_TEEN7 ||
+ type == OBJECT_TEEN8 ||
+ type == OBJECT_TEEN9 ||
+ type == OBJECT_TEEN10 ||
+ type == OBJECT_TEEN11 ||
+ type == OBJECT_TEEN12 ||
+ type == OBJECT_TEEN13 ||
+ type == OBJECT_TEEN14 ||
+ type == OBJECT_TEEN15 ||
+ type == OBJECT_TEEN16 ||
+ type == OBJECT_TEEN17 ||
+ type == OBJECT_TEEN18 ||
+ type == OBJECT_TEEN19 ||
+ type == OBJECT_TEEN20 ||
+ type == OBJECT_TEEN21 ||
+ type == OBJECT_TEEN22 ||
+ type == OBJECT_TEEN23 ||
+ type == OBJECT_TEEN24 ||
+ type == OBJECT_TEEN25 ||
+ type == OBJECT_TEEN26 ||
+ type == OBJECT_TEEN27 ||
+ type == OBJECT_TEEN28 ||
+ type == OBJECT_TEEN29 ||
+ type == OBJECT_TEEN30 ||
+ type == OBJECT_TEEN31 ||
+ type == OBJECT_TEEN32 ||
+ type == OBJECT_TEEN33 ||
+ type == OBJECT_TEEN34 ||
+ type == OBJECT_TEEN35 ||
+ type == OBJECT_TEEN36 ||
+ type == OBJECT_TEEN37 ||
+ type == OBJECT_TEEN38 ||
+ type == OBJECT_TEEN39 ||
+ type == OBJECT_TEEN40 ||
+ type == OBJECT_TEEN41 ||
+ type == OBJECT_TEEN42 ||
+ type == OBJECT_TEEN43 ||
+ type == OBJECT_TEEN44 ||
+ type == OBJECT_TEEN45 ||
+ type == OBJECT_TEEN46 ||
+ type == OBJECT_TEEN47 ||
+ type == OBJECT_TEEN48 ||
+ type == OBJECT_TEEN49 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->SetOption(option);
+ pObject->CreateTeen(pos, angle, zoom, height, type);
+ }
+ else
+ if ( type == OBJECT_QUARTZ0 ||
+ type == OBJECT_QUARTZ1 ||
+ type == OBJECT_QUARTZ2 ||
+ type == OBJECT_QUARTZ3 ||
+ type == OBJECT_QUARTZ4 ||
+ type == OBJECT_QUARTZ5 ||
+ type == OBJECT_QUARTZ6 ||
+ type == OBJECT_QUARTZ7 ||
+ type == OBJECT_QUARTZ8 ||
+ type == OBJECT_QUARTZ9 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateQuartz(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_ROOT0 ||
+ type == OBJECT_ROOT1 ||
+ type == OBJECT_ROOT2 ||
+ type == OBJECT_ROOT3 ||
+ type == OBJECT_ROOT4 ||
+ type == OBJECT_ROOT5 ||
+ type == OBJECT_ROOT6 ||
+ type == OBJECT_ROOT7 ||
+ type == OBJECT_ROOT8 ||
+ type == OBJECT_ROOT9 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateRoot(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_HOME1 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateHome(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_RUINmobilew1 ||
+ type == OBJECT_RUINmobilew2 ||
+ type == OBJECT_RUINmobilet1 ||
+ type == OBJECT_RUINmobilet2 ||
+ type == OBJECT_RUINmobiler1 ||
+ type == OBJECT_RUINmobiler2 ||
+ type == OBJECT_RUINfactory ||
+ type == OBJECT_RUINdoor ||
+ type == OBJECT_RUINsupport ||
+ type == OBJECT_RUINradar ||
+ type == OBJECT_RUINconvert ||
+ type == OBJECT_RUINbase ||
+ type == OBJECT_RUINhead )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateRuin(pos, angle, height, type);
+ }
+ else
+ if ( type == OBJECT_APOLLO1 ||
+ type == OBJECT_APOLLO3 ||
+ type == OBJECT_APOLLO4 ||
+ type == OBJECT_APOLLO5 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateApollo(pos, angle, type);
+ }
+ else
+ if ( type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->CreateInsect(pos, angle, type); // no eggs
+ }
+ else
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH ||
+ type == OBJECT_TOTO ||
+ type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr ||
+ type == OBJECT_APOLLO2 )
+ {
+ pObject = new CObject(m_iMan);
+ pObject->SetOption(option);
+ pObject->CreateVehicle(pos, angle, type, power, bTrainer, bToy);
+ }
+
+ if ( m_bFixScene && type == OBJECT_HUMAN )
+ {
+ CMotion* motion;
+
+ motion = pObject->RetMotion();
+ if ( m_phase == PHASE_WIN ) motion->SetAction(MHS_WIN, 0.4f);
+ if ( m_phase == PHASE_LOST ) motion->SetAction(MHS_LOST, 0.5f);
+ }
+
+ return pObject;
+}
+
+
+// Creates the editable model.
+
+void CRobotMain::CreateModel()
+{
+ Math::Vector direction;
+ D3DCOLORVALUE color;
+
+ m_engine->SetAmbiantColor(0xC0C0C0C0); // gray
+ m_engine->SetBackground("", 0x80808080, 0x80808080, 0x80808080, 0x80808080);
+ m_engine->SetFogColor(0x80808080);
+ m_engine->SetDeepView(500.0f, 0);
+ m_engine->SetDeepView(100.0f, 1);
+ m_engine->SetFogStart(0.5f);
+
+ m_model->StartUserAction();
+
+ direction = Math::Vector(1.0f, -1.0f, 1.0f);
+ color.r = 0.7f;
+ color.g = 0.7f;
+ color.b = 0.7f; // white
+ CreateLight(direction, color);
+
+ direction = Math::Vector(-1.0f, -1.0f, 1.0f);
+ color.r = 0.7f;
+ color.g = 0.7f;
+ color.b = 0.7f; // white
+ CreateLight(direction, color);
+
+ direction = Math::Vector(1.0f, -1.0f, -1.0f);
+ color.r = 0.7f;
+ color.g = 0.7f;
+ color.b = 0.7f; // white
+ CreateLight(direction, color);
+
+ direction = Math::Vector(-1.0f, -1.0f, -1.0f);
+ color.r = 0.7f;
+ color.g = 0.7f;
+ color.b = 0.7f; // white
+ CreateLight(direction, color);
+
+ direction = Math::Vector(0.0f, 1.0f, 0.0f);
+ color.r = 0.7f;
+ color.g = 0.7f;
+ color.b = 0.7f; // white
+ CreateLight(direction, color);
+
+ InitEye();
+
+ m_engine->TimeInit();
+ m_time = 0.0f;
+ m_gameTime = 0.0f;
+ m_checkEndTime = 0.0f;
+}
+
+
+// Creates a directional light.
+
+int CRobotMain::CreateLight(Math::Vector direction, D3DCOLORVALUE color)
+{
+ D3DLIGHT7 light;
+ int obj;
+
+ if ( direction.x == 0.0f &&
+ direction.y == 0.0f &&
+ direction.z == 0.0f )
+ {
+ direction.y = -1.0f;
+ }
+
+ ZeroMemory(&light, sizeof(D3DLIGHT7));
+ light.dltType = D3DLIGHT_DIRECTIONAL;
+ light.dcvDiffuse.r = color.r;
+ light.dcvDiffuse.g = color.g;
+ light.dcvDiffuse.b = color.b;
+ light.dvDirection = VEC_TO_D3DVEC(direction);
+ obj = m_light->CreateLight();
+ m_light->SetLight(obj, light);
+
+ return obj;
+}
+
+// Creates a light spot.
+
+int CRobotMain::CreateSpot(Math::Vector pos, D3DCOLORVALUE color)
+{
+ D3DLIGHT7 light;
+ int obj;
+
+ if ( !m_engine->RetLightMode() ) return -1;
+
+ pos.y += m_terrain->RetFloorLevel(pos);
+
+ ZeroMemory(&light, sizeof(D3DLIGHT7));
+ light.dltType = D3DLIGHT_SPOT;
+ light.dcvDiffuse.r = color.r;
+ light.dcvDiffuse.g = color.g;
+ light.dcvDiffuse.b = color.b;
+ light.dvPosition = VEC_TO_D3DVEC(pos);
+ light.dvDirection = D3DVECTOR(0.0f, -1.0f, 0.0f);
+ light.dvRange = D3DLIGHT_RANGE_MAX;
+ light.dvFalloff = 1.0f;
+ light.dvTheta = 10.0f*Math::PI/180.0f;
+ light.dvPhi = 90.0f*Math::PI/180.0f;
+ light.dvAttenuation0 = 2.0f;
+ light.dvAttenuation1 = 0.0f;
+ light.dvAttenuation2 = 0.0f;
+ obj = m_light->CreateLight();
+ m_light->SetLight(obj, light);
+
+ return obj;
+}
+
+
+// Change the colors and textures.
+
+void CRobotMain::ChangeColor()
+{
+ D3DCOLORVALUE colorRef1, colorNew1, colorRef2, colorNew2;
+ Math::Point ts, ti;
+ Math::Point exclu[6];
+ char name[100];
+ int face;
+ float tolerance;
+
+ ts = Math::Point(0.0f, 0.0f);
+ ti = Math::Point(1.0f, 1.0f); // the entire image
+
+ colorRef1.a = 0.0f;
+ colorRef2.a = 0.0f;
+
+ colorRef1.r = 206.0f/256.0f;
+ colorRef1.g = 206.0f/256.0f;
+ colorRef1.b = 204.0f/256.0f; // ~white
+ colorNew1 = m_dialog->RetGamerColorCombi();
+ colorRef2.r = 255.0f/256.0f;
+ colorRef2.g = 132.0f/256.0f;
+ colorRef2.b = 1.0f/256.0f; // orange
+ colorNew2 = m_dialog->RetGamerColorBand();
+ exclu[0] = Math::Point(192.0f/256.0f, 0.0f/256.0f);
+ exclu[1] = Math::Point(256.0f/256.0f, 64.0f/256.0f); // crystals + cylinders
+ exclu[2] = Math::Point(208.0f/256.0f, 224.0f/256.0f);
+ exclu[3] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // SatCom screen
+ exclu[4] = Math::Point(0.0f, 0.0f);
+ exclu[5] = Math::Point(0.0f, 0.0f); // terminator
+ m_engine->ChangeColor("human.tga", colorRef1, colorNew1, colorRef2, colorNew2, 0.30f, 0.01f, ts, ti, exclu);
+
+ face = RetGamerFace();
+ if ( face == 0 ) // normal?
+ {
+ colorRef1.r = 90.0f/256.0f;
+ colorRef1.g = 95.0f/256.0f;
+ colorRef1.b = 85.0f/256.0f; // black
+ tolerance = 0.15f;
+ }
+ if ( face == 1 ) // bald?
+ {
+ colorRef1.r = 74.0f/256.0f;
+ colorRef1.g = 58.0f/256.0f;
+ colorRef1.b = 46.0f/256.0f; // brown
+ tolerance = 0.20f;
+ }
+ if ( face == 2 ) // carlos?
+ {
+ colorRef1.r = 70.0f/256.0f;
+ colorRef1.g = 40.0f/256.0f;
+ colorRef1.b = 8.0f/256.0f; // brown
+ tolerance = 0.30f;
+ }
+ if ( face == 3 ) // blonde?
+ {
+ colorRef1.r = 74.0f/256.0f;
+ colorRef1.g = 16.0f/256.0f;
+ colorRef1.b = 0.0f/256.0f; // yellow
+ tolerance = 0.20f;
+ }
+ colorNew1 = m_dialog->RetGamerColorHair();
+ colorRef2.r = 0.0f;
+ colorRef2.g = 0.0f;
+ colorRef2.b = 0.0f;
+ colorNew2.r = 0.0f;
+ colorNew2.g = 0.0f;
+ colorNew2.b = 0.0f;
+ sprintf(name, "face%.2d.tga", face+1);
+ exclu[0] = Math::Point(105.0f/256.0f, 47.0f/166.0f);
+ exclu[1] = Math::Point(153.0f/256.0f, 79.0f/166.0f); // blue canister
+ exclu[2] = Math::Point(0.0f, 0.0f);
+ exclu[3] = Math::Point(0.0f, 0.0f); // terminator
+ m_engine->ChangeColor(name, colorRef1, colorNew1, colorRef2, colorNew2, tolerance, 0.00f, ts, ti, exclu);
+
+ colorRef2.r = 0.0f;
+ colorRef2.g = 0.0f;
+ colorRef2.b = 0.0f;
+ colorNew2.r = 0.0f;
+ colorNew2.g = 0.0f;
+ colorNew2.b = 0.0f;
+
+ m_engine->ChangeColor("base1.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
+ m_engine->ChangeColor("convert.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
+ m_engine->ChangeColor("derrick.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
+ m_engine->ChangeColor("factory.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
+ m_engine->ChangeColor("lemt.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
+ m_engine->ChangeColor("roller.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
+ m_engine->ChangeColor("search.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true);
+
+ exclu[0] = Math::Point( 0.0f/256.0f, 160.0f/256.0f);
+ exclu[1] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // pencils
+ exclu[2] = Math::Point(0.0f, 0.0f);
+ exclu[3] = Math::Point(0.0f, 0.0f); // terminator
+ m_engine->ChangeColor("drawer.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true);
+
+ exclu[0] = Math::Point(237.0f/256.0f, 176.0f/256.0f);
+ exclu[1] = Math::Point(256.0f/256.0f, 220.0f/256.0f); // blue canister
+ exclu[2] = Math::Point(106.0f/256.0f, 150.0f/256.0f);
+ exclu[3] = Math::Point(130.0f/256.0f, 214.0f/256.0f); // safe location
+ exclu[4] = Math::Point(0.0f, 0.0f);
+ exclu[5] = Math::Point(0.0f, 0.0f); // terminator
+ m_engine->ChangeColor("subm.tga", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true);
+
+ exclu[0] = Math::Point(128.0f/256.0f, 160.0f/256.0f);
+ exclu[1] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // SatCom
+ exclu[2] = Math::Point(0.0f, 0.0f);
+ exclu[3] = Math::Point(0.0f, 0.0f); // terminator
+ m_engine->ChangeColor("ant.tga", m_colorRefAlien, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti, exclu);
+ m_engine->ChangeColor("mother.tga", m_colorRefAlien, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti);
+
+ m_engine->ChangeColor("plant.tga", m_colorRefGreen, m_colorNewGreen, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti);
+
+ // PARTIPLOUF0 and PARTIDROP :
+ ts = Math::Point(0.500f, 0.500f);
+ ti = Math::Point(0.875f, 0.750f);
+ m_engine->ChangeColor("effect00.tga", m_colorRefWater, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, 0, m_colorShiftWater, true);
+
+ // PARTIFLIC :
+ ts = Math::Point(0.00f, 0.75f);
+ ti = Math::Point(0.25f, 1.00f);
+ m_engine->ChangeColor("effect02.tga", m_colorRefWater, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, 0, m_colorShiftWater, true);
+}
+
+// Updates the number of unnecessary objects.
+
+bool CRobotMain::TestGadgetQuantity(int rank)
+{
+ float percent;
+ int *table;
+
+ static int table10[10] = {0,1,0,0,0,0,0,0,0,0};
+ static int table20[10] = {0,1,0,0,0,1,0,0,0,0};
+ static int table30[10] = {0,1,0,1,0,1,0,0,0,0};
+ static int table40[10] = {0,1,0,1,0,1,0,1,0,0};
+ static int table50[10] = {0,1,0,1,0,1,0,1,0,1};
+ static int table60[10] = {0,1,0,1,1,1,0,1,0,1};
+ static int table70[10] = {0,1,0,1,1,1,0,1,1,1};
+ static int table80[10] = {0,1,1,1,1,1,0,1,1,1};
+ static int table90[10] = {0,1,1,1,1,1,1,1,1,1};
+
+ percent = m_engine->RetGadgetQuantity();
+ if ( percent == 0.0f ) return false;
+ if ( percent == 1.0f ) return true;
+
+ if ( percent <= 0.15f ) table = table10;
+ else if ( percent <= 0.25f ) table = table20;
+ else if ( percent <= 0.35f ) table = table30;
+ else if ( percent <= 0.45f ) table = table40;
+ else if ( percent <= 0.55f ) table = table50;
+ else if ( percent <= 0.65f ) table = table60;
+ else if ( percent <= 0.75f ) table = table70;
+ else if ( percent <= 0.85f ) table = table80;
+ else table = table90;
+
+ return table[rank%10];
+}
+
+
+
+// Calculates the distance to the nearest object.
+
+float CRobotMain::SearchNearestObject(Math::Vector center, CObject *exclu)
+{
+ CObject* pObj;
+ ObjectType type;
+ Math::Vector oPos;
+ float min, dist, oRadius;
+ int i, j;
+
+ min = 100000.0f;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue; // inactive?
+ if ( pObj->RetTruck() != 0 ) continue; // object carries?
+ if ( pObj == exclu ) continue;
+
+ type = pObj->RetType();
+
+ if ( type == OBJECT_BASE )
+ {
+ oPos = pObj->RetPosition(0);
+ if ( oPos.x != center.x ||
+ oPos.z != center.z )
+ {
+ dist = Math::Distance(center, oPos)-80.0f;
+ if ( dist < 0.0f ) dist = 0.0f;
+ min = Math::Min(min, dist);
+ continue;
+ }
+ }
+
+ if ( type == OBJECT_STATION ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_DESTROYER )
+ {
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(center, oPos)-8.0f;
+ if ( dist < 0.0f ) dist = 0.0f;
+ min = Math::Min(min, dist);
+ }
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ dist = Math::Distance(center, oPos)-oRadius;
+ if ( dist < 0.0f ) dist = 0.0f;
+ min = Math::Min(min, dist);
+ }
+ }
+ return min;
+}
+
+// Calculates a free space.
+
+bool CRobotMain::FreeSpace(Math::Vector &center, float minRadius, float maxRadius,
+ float space, CObject *exclu)
+{
+ Math::Vector pos;
+ Math::Point p;
+ float radius, ia, angle, dist, flat;
+
+ if ( minRadius < maxRadius ) // from internal to external?
+ {
+ for ( radius=minRadius ; radius<=maxRadius ; radius+=space )
+ {
+ ia = space/radius;
+ for ( angle=0.0f ; angle<Math::PI*2.0f ; angle+=ia )
+ {
+ p.x = center.x+radius;
+ p.y = center.z;
+ p = Math::RotatePoint(Math::Point(center.x, center.z), angle, p);
+ pos.x = p.x;
+ pos.z = p.y;
+ pos.y = 0.0f;
+ m_terrain->MoveOnFloor(pos, true);
+ dist = SearchNearestObject(pos, exclu);
+ if ( dist >= space )
+ {
+ flat = m_terrain->RetFlatZoneRadius(pos, dist/2.0f);
+ if ( flat >= dist/2.0f )
+ {
+ center = pos;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ else // from external to internal?
+ {
+ for ( radius=maxRadius ; radius>=minRadius ; radius-=space )
+ {
+ ia = space/radius;
+ for ( angle=0.0f ; angle<Math::PI*2.0f ; angle+=ia )
+ {
+ p.x = center.x+radius;
+ p.y = center.z;
+ p = Math::RotatePoint(Math::Point(center.x, center.z), angle, p);
+ pos.x = p.x;
+ pos.z = p.y;
+ pos.y = 0.0f;
+ m_terrain->MoveOnFloor(pos, true);
+ dist = SearchNearestObject(pos, exclu);
+ if ( dist >= space )
+ {
+ flat = m_terrain->RetFlatZoneRadius(pos, dist/2.0f);
+ if ( flat >= dist/2.0f )
+ {
+ center = pos;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+// Calculates the maximum radius of a free space.
+
+float CRobotMain::RetFlatZoneRadius(Math::Vector center, float maxRadius,
+ CObject *exclu)
+{
+ float dist;
+
+ dist = SearchNearestObject(center, exclu);
+ if ( dist == 0.0f ) return 0.0f;
+ if ( dist < maxRadius )
+ {
+ maxRadius = dist;
+ }
+ return m_terrain->RetFlatZoneRadius(center, maxRadius);
+}
+
+
+// Hides buildable area when a cube of metal is taken up.
+
+void CRobotMain::HideDropZone(CObject* metal)
+{
+ if ( m_showLimit[1].bUsed &&
+ m_showLimit[1].link == metal )
+ {
+ FlushShowLimit(1);
+ }
+
+ if ( m_showLimit[2].bUsed &&
+ m_showLimit[2].link == metal )
+ {
+ FlushShowLimit(2);
+ }
+}
+
+// Shows the buildable area when a cube of metal is deposited.
+
+void CRobotMain::ShowDropZone(CObject* metal, CObject* truck)
+{
+ CObject* pObj;
+ ObjectType type;
+ Math::Vector center, oPos;
+ float oMax, tMax, dist, oRadius, radius;
+ int i, j;
+
+ if ( metal == 0 ) return;
+
+ center = metal->RetPosition(0);
+
+ // Calculates the maximum radius possible depending on other items.
+ oMax = 30.0f; // radius to build the biggest building
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue; // inactive?
+ if ( pObj->RetTruck() != 0 ) continue; // object carried?
+ if ( pObj == metal ) continue;
+ if ( pObj == truck ) continue;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_BASE )
+ {
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(center, oPos)-80.0f;
+ oMax = Math::Min(oMax, dist);
+ }
+ else
+ {
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ dist = Math::Distance(center, oPos)-oRadius;
+ oMax = Math::Min(oMax, dist);
+ }
+ }
+
+ if ( type == OBJECT_DERRICK ||
+ type == OBJECT_FACTORY ||
+ type == OBJECT_STATION ||
+ type == OBJECT_CONVERT ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_DESTROYER||
+ type == OBJECT_TOWER ||
+ type == OBJECT_RESEARCH ||
+ type == OBJECT_RADAR ||
+ type == OBJECT_ENERGY ||
+ type == OBJECT_LABO ||
+ type == OBJECT_NUCLEAR ||
+ type == OBJECT_START ||
+ type == OBJECT_END ||
+ type == OBJECT_INFO ||
+ type == OBJECT_PARA ||
+ type == OBJECT_SAFE ||
+ type == OBJECT_HUSTON ) // building?
+ {
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ dist = Math::Distance(center, oPos)-oRadius-BUILDMARGIN;
+ oMax = Math::Min(oMax, dist);
+ }
+ }
+ }
+
+ // Calculates the maximum possible radius depending on terrain.
+ if ( oMax >= 2.0f )
+ {
+ tMax = m_terrain->RetFlatZoneRadius(center, 30.0f);
+ }
+ else
+ {
+ tMax = 0.0f;
+ }
+
+ radius = Math::Min(oMax, tMax);
+ if ( radius >= 2.0f )
+ {
+ SetShowLimit(1, PARTILIMIT2, metal, center, radius, 10.0f);
+ }
+}
+
+// Erases the boundaries shown.
+
+void CRobotMain::FlushShowLimit(int i)
+{
+ int j;
+
+ if ( m_showLimit[i].link != 0 )
+ {
+ m_showLimit[i].link->StopShowLimit();
+ }
+
+ for ( j=0 ; j<m_showLimit[i].total ; j++ )
+ {
+ if ( m_showLimit[i].parti[j] == 0 ) continue;
+
+ m_particule->DeleteParticule(m_showLimit[i].parti[j]);
+ m_showLimit[i].parti[j] = 0;
+ }
+
+ m_showLimit[i].total = 0;
+ m_showLimit[i].link = 0;
+ m_showLimit[i].bUsed = false;
+}
+
+// Specifies the boundaries to show.
+
+void CRobotMain::SetShowLimit(int i, ParticuleType parti, CObject *pObj,
+ Math::Vector pos, float radius, float duration)
+{
+ Math::Point dim;
+ float dist;
+ int j;
+
+ FlushShowLimit(i); // erases the current boundaries
+
+ if ( radius <= 0.0f ) return;
+
+ if ( radius <= 50.0f )
+ {
+ dim = Math::Point(0.3f, 0.3f);
+ dist = 2.5f;
+ }
+ else
+ {
+ dim = Math::Point(1.5f, 1.5f);
+ dist = 10.0f;
+ }
+
+ m_showLimit[i].bUsed = true;
+ m_showLimit[i].link = pObj;
+ m_showLimit[i].pos = pos;
+ m_showLimit[i].radius = radius;
+ m_showLimit[i].duration = duration;
+ m_showLimit[i].total = (int)((radius*2.0f*Math::PI)/dist);
+ if ( m_showLimit[i].total > MAXSHOWPARTI ) m_showLimit[i].total = MAXSHOWPARTI;
+ m_showLimit[i].time = 0.0f;
+
+ for ( j=0 ; j<m_showLimit[i].total ; j++ )
+ {
+ m_showLimit[i].parti[j] = m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), dim, parti, duration);
+ }
+}
+
+// Adjusts the boundaries to show.
+
+void CRobotMain::AdjustShowLimit(int i, Math::Vector pos)
+{
+ m_showLimit[i].pos = pos;
+}
+
+// Mount the boundaries of the selected object.
+
+void CRobotMain::StartShowLimit()
+{
+ CObject* pObj;
+
+ pObj = RetSelect();
+ if ( pObj == 0 ) return;
+
+ pObj->StartShowLimit();
+}
+
+// Advances the boundaries shown.
+
+void CRobotMain::FrameShowLimit(float rTime)
+{
+ Math::Vector pos;
+ Math::Point center, rotate;
+ float angle, factor, speed;
+ int i, j;
+
+ if ( m_engine->RetPause() ) return;
+
+ for ( i=0 ; i<MAXSHOWLIMIT ; i++ )
+ {
+ if ( !m_showLimit[i].bUsed ) continue;
+
+ m_showLimit[i].time += rTime;
+
+ if ( m_showLimit[i].time >= m_showLimit[i].duration )
+ {
+ FlushShowLimit(i);
+ continue;
+ }
+
+ if ( m_showLimit[i].time < 1.0f )
+ {
+ factor = m_showLimit[i].time;
+ }
+ else if ( m_showLimit[i].time > m_showLimit[i].duration-1.0f )
+ {
+ factor = m_showLimit[i].duration-m_showLimit[i].time;
+ }
+ else
+ {
+ factor = 1.0f;
+ }
+
+ speed = 0.4f-m_showLimit[i].radius*0.001f;
+ if ( speed < 0.1f ) speed = 0.1f;
+ angle = m_showLimit[i].time*speed;
+
+ for ( j=0 ; j<m_showLimit[i].total ; j++ )
+ {
+ if ( m_showLimit[i].parti[j] == 0 ) continue;
+
+ center.x = m_showLimit[i].pos.x;
+ center.y = m_showLimit[i].pos.z;
+ rotate.x = center.x+m_showLimit[i].radius*factor;
+ rotate.y = center.y;
+ rotate = Math::RotatePoint(center, angle, rotate);
+
+ pos.x = rotate.x;
+ pos.z = rotate.y;
+ pos.y = 0.0f;
+ m_terrain->MoveOnFloor(pos, true);
+ if ( m_showLimit[i].radius <= 50.0f ) pos.y += 0.5f;
+ else pos.y += 2.0f;
+ m_particule->SetPosition(m_showLimit[i].parti[j], pos);
+//? m_particule->SetAngle(m_showLimit[i].parti[j], angle-Math::PI/2.0f);
+
+ angle += (2.0f*Math::PI)/m_showLimit[i].total;
+ }
+ }
+}
+
+
+
+// Returns a pointer to the last backslash in a filename.
+
+char* SearchLastDir(char *filename)
+{
+ char* p = filename;
+
+ while ( *p++ != 0 );
+ p --; // ^on the zero terminator
+
+ while ( p != filename )
+ {
+ if ( *(--p) == '\\' ) return p;
+ }
+ return 0;
+}
+
+
+// Compiles all scripts of robots.
+
+void CRobotMain::CompileScript(bool bSoluce)
+{
+ CObject* pObj;
+ CBrain* brain;
+ int i, j, nbError, lastError, run;
+ char* name;
+
+ nbError = 0;
+ do
+ {
+ lastError = nbError;
+ nbError = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) continue;
+
+ for ( j=0 ; j<10 ; j++ )
+ {
+ if ( brain->RetCompile(j) ) continue;
+
+ name = brain->RetScriptName(j);
+ if ( name[0] != 0 )
+ {
+ brain->ReadProgram(j, name);
+ if ( !brain->RetCompile(j) ) nbError++;
+ }
+ }
+
+ LoadOneScript(pObj, nbError);
+ }
+ }
+ while ( nbError > 0 && nbError != lastError );
+
+ // Load all solutions.
+ if ( bSoluce )
+ {
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) continue;
+
+ name = brain->RetSoluceName();
+ if ( name[0] != 0 )
+ {
+ brain->ReadSoluce(name); // load solution
+ }
+ }
+ }
+
+ // Start all programs according to the command "run".
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) continue;
+
+ run = brain->RetScriptRun();
+ if ( run != -1 )
+ {
+ brain->RunProgram(run); // starts the program
+ }
+ }
+}
+
+// Load all programs of the robot.
+
+void CRobotMain::LoadOneScript(CObject *pObj, int &nbError)
+{
+ ObjectType type;
+ CBrain* brain;
+ char filename[_MAX_FNAME];
+ char* name;
+ int rank, i, objRank;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) return;
+
+ if ( !IsSelectable(pObj) ) return;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_HUMAN ) return;
+
+ objRank = pObj->RetDefRank();
+ if ( objRank == -1 ) return;
+
+ name = m_dialog->RetSceneName();
+ rank = m_dialog->RetSceneRank();
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ if ( brain->RetCompile(i) ) continue;
+//? if ( brain->ProgramExist(i) ) continue;
+
+ sprintf(filename, "%s\\%s\\%c%.3d%.3d%.1d.txt",
+ RetSavegameDir(), m_gamerName, name[0], rank, objRank, i);
+ brain->ReadProgram(i, filename);
+ if ( !brain->RetCompile(i) ) nbError++;
+ }
+}
+
+// Load all programs of the robot.
+
+void CRobotMain::LoadFileScript(CObject *pObj, char* filename, int objRank,
+ int &nbError)
+{
+ ObjectType type;
+ CBrain* brain;
+ char fn[_MAX_FNAME];
+ char* ldir;
+ char* name;
+ int rank, i;
+
+ if ( objRank == -1 ) return;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) return;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_HUMAN ) return;
+
+ name = m_dialog->RetSceneName();
+ rank = m_dialog->RetSceneRank();
+
+ strcpy(fn, filename);
+ ldir = SearchLastDir(fn);
+ if ( ldir == 0 ) return;
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ if ( brain->RetCompile(i) ) continue;
+//? if ( brain->ProgramExist(i) ) continue;
+
+ sprintf(ldir, "\\prog%.3d%.1d.txt", objRank, i);
+ brain->ReadProgram(i, fn);
+ if ( !brain->RetCompile(i) ) nbError++;
+ }
+}
+
+// Saves all programs of all the robots.
+
+void CRobotMain::SaveAllScript()
+{
+ CObject* pObj;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ SaveOneScript(pObj);
+ }
+}
+
+// Saves all programs of the robot.
+// If a program does not exist, the corresponding file is destroyed.
+
+void CRobotMain::SaveOneScript(CObject *pObj)
+{
+ ObjectType type;
+ CBrain* brain;
+ char filename[_MAX_FNAME];
+ char* name;
+ int rank, i, objRank;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) return;
+
+ if ( !IsSelectable(pObj) ) return;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_HUMAN ) return;
+
+ objRank = pObj->RetDefRank();
+ if ( objRank == -1 ) return;
+
+ name = m_dialog->RetSceneName();
+ rank = m_dialog->RetSceneRank();
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ sprintf(filename, "%s\\%s\\%c%.3d%.3d%.1d.txt",
+ RetSavegameDir(), m_gamerName, name[0], rank, objRank, i);
+ brain->WriteProgram(i, filename);
+ }
+}
+
+// Saves all programs of the robot.
+// If a program does not exist, the corresponding file is destroyed.
+
+void CRobotMain::SaveFileScript(CObject *pObj, char* filename, int objRank)
+{
+ ObjectType type;
+ CBrain* brain;
+ char fn[_MAX_FNAME];
+ char* ldir;
+ char* name;
+ int rank, i;
+
+ if ( objRank == -1 ) return;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) return;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_HUMAN ) return;
+
+ name = m_dialog->RetSceneName();
+ rank = m_dialog->RetSceneRank();
+
+ strcpy(fn, filename);
+ ldir = SearchLastDir(fn);
+ if ( ldir == 0 ) return;
+
+ for ( i=0 ; i<BRAINMAXSCRIPT ; i++ )
+ {
+ sprintf(ldir, "\\prog%.3d%.1d.txt", objRank, i);
+ brain->WriteProgram(i, fn);
+ }
+}
+
+// Saves the stack of the program in execution of a robot.
+
+bool CRobotMain::SaveFileStack(CObject *pObj, FILE *file, int objRank)
+{
+ ObjectType type;
+ CBrain* brain;
+
+ if ( objRank == -1 ) return true;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) return true;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_HUMAN ) return true;
+
+ return brain->WriteStack(file);
+}
+
+// Resumes the execution stack of the program in a robot.
+
+bool CRobotMain::ReadFileStack(CObject *pObj, FILE *file, int objRank)
+{
+ ObjectType type;
+ CBrain* brain;
+
+ if ( objRank == -1 ) return true;
+
+ brain = pObj->RetBrain();
+ if ( brain == 0 ) return true;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_HUMAN ) return true;
+
+ return brain->ReadStack(file);
+}
+
+
+// Empty the list.
+
+bool CRobotMain::FlushNewScriptName()
+{
+ int i;
+
+ for ( i=0 ; i<MAXNEWSCRIPTNAME ; i++ )
+ {
+ m_newScriptName[i].bUsed = false;
+ }
+ return true;
+}
+
+// Adds a script name.
+
+bool CRobotMain::AddNewScriptName(ObjectType type, char *name)
+{
+ int i;
+
+ for ( i=0 ; i<MAXNEWSCRIPTNAME ; i++ )
+ {
+ if ( !m_newScriptName[i].bUsed )
+ {
+ m_newScriptName[i].bUsed = true;
+ m_newScriptName[i].type = type;
+ strcpy(m_newScriptName[i].name, name);
+ return true;
+ }
+ }
+ return false;
+}
+
+// Seeks a script name for a given type.
+
+char* CRobotMain::RetNewScriptName(ObjectType type, int rank)
+{
+ int i;
+
+ for ( i=0 ; i<MAXNEWSCRIPTNAME ; i++ )
+ {
+ if ( m_newScriptName[i].bUsed &&
+ (m_newScriptName[i].type == type ||
+ m_newScriptName[i].type == OBJECT_NULL ) )
+ {
+ if ( rank == 0 ) return m_newScriptName[i].name;
+ else rank --;
+ }
+ }
+
+ return 0;
+}
+
+
+// Seeks if an object occupies in a spot, to prevent a backup of the game.
+
+bool CRobotMain::IsBusy()
+{
+ CObject* pObj;
+ CBrain* pBrain;
+//? CAuto* pAuto;
+ int i;
+
+ if ( m_CompteurFileOpen > 0 ) return true;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ pBrain = pObj->RetBrain();
+ if ( pBrain != 0 )
+ {
+ if ( pBrain->IsBusy() ) return true;
+ }
+
+//? pAuto = pObj->RetAuto();
+//? if ( pAuto != 0 )
+//? {
+//? if ( pAuto->RetBusy() ) return true;
+//? }
+ }
+ return false;
+}
+
+// Writes an object into the backup file.
+
+void CRobotMain::IOWriteObject(FILE *file, CObject* pObj, char *cmd)
+{
+ Math::Vector pos;
+ CBrain* pBrain;
+ char line[3000];
+ char name[100];
+ int run, i;
+
+ if ( pObj->RetType() == OBJECT_FIX ) return;
+
+ strcpy(line, cmd);
+
+ sprintf(name, " type=%s", GetTypeObject(pObj->RetType()));
+ strcat(line, name);
+
+ sprintf(name, " id=%d", pObj->RetID());
+ strcat(line, name);
+
+ pos = pObj->RetPosition(0)/g_unit;
+ sprintf(name, " pos=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
+ strcat(line, name);
+
+ pos = pObj->RetAngle(0)/(Math::PI/180.0f);
+ sprintf(name, " angle=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
+ strcat(line, name);
+
+ pos = pObj->RetZoom(0);
+ sprintf(name, " zoom=%.2f;%.2f;%.2f", pos.x, pos.y, pos.z);
+ strcat(line, name);
+
+ for ( i=1 ; i<OBJECTMAXPART ; i++ )
+ {
+ if ( pObj->RetObjectRank(i) == -1 ) continue;
+
+ pos = pObj->RetPosition(i);
+ if ( pos.x != 0.0f || pos.y != 0.0f || pos.z != 0.0f )
+ {
+ pos /= g_unit;
+ sprintf(name, " p%d=%.2f;%.2f;%.2f", i, pos.x, pos.y, pos.z);
+ strcat(line, name);
+ }
+
+ pos = pObj->RetAngle(i);
+ if ( pos.x != 0.0f || pos.y != 0.0f || pos.z != 0.0f )
+ {
+ pos /= (Math::PI/180.0f);
+ sprintf(name, " a%d=%.2f;%.2f;%.2f", i, pos.x, pos.y, pos.z);
+ strcat(line, name);
+ }
+
+ pos = pObj->RetZoom(i);
+ if ( pos.x != 1.0f || pos.y != 1.0f || pos.z != 1.0f )
+ {
+ sprintf(name, " z%d=%.2f;%.2f;%.2f", i, pos.x, pos.y, pos.z);
+ strcat(line, name);
+ }
+ }
+
+ sprintf(name, " trainer=%d", pObj->RetTrainer());
+ strcat(line, name);
+
+ sprintf(name, " option=%d", pObj->RetOption());
+ strcat(line, name);
+
+ if ( pObj == m_infoObject ) // selects object?
+ {
+ sprintf(name, " select=1");
+ strcat(line, name);
+ }
+
+ pObj->Write(line);
+
+ if ( pObj->RetType() == OBJECT_BASE )
+ {
+ sprintf(name, " run=3"); // stops and open (PARAM_FIXSCENE)
+ strcat(line, name);
+ }
+
+ pBrain = pObj->RetBrain();
+ if ( pBrain != 0 )
+ {
+ run = pBrain->RetProgram();
+ if ( run != -1 )
+ {
+ sprintf(name, " run=%d", run+1);
+ strcat(line, name);
+ }
+ }
+
+ strcat(line, "\n");
+ fputs(line, file);
+}
+
+// Saves the current game.
+
+bool CRobotMain::IOWriteScene(char *filename, char *filecbot, char *info)
+{
+ FILE* file;
+ char line[500];
+ char* name;
+ CObject *pObj, *pPower, *pFret;
+ float sleep, delay, magnetic, progress;
+ int i, objRank;
+ long version;
+
+ file = fopen(filename, "w");
+ if ( file == NULL ) return false;
+
+ sprintf(line, "Title text=\"%s\"\n", info);
+ fputs(line, file);
+
+ sprintf(line, "Version maj=%d min=%d\n", 0, 1);
+ fputs(line, file);
+
+ name = m_dialog->RetSceneName();
+ if ( strcmp(name, "user") == 0 )
+ {
+ sprintf(line, "Mission base=\"%s\" rank=%.3d dir=\"%s\"\n", name, m_dialog->RetSceneRank(), m_dialog->RetSceneDir());
+ }
+ else
+ {
+ sprintf(line, "Mission base=\"%s\" rank=%.3d\n", name, m_dialog->RetSceneRank());
+ }
+ fputs(line, file);
+
+ sprintf(line, "Map zoom=%.2f\n", m_map->RetZoomMap());
+ fputs(line, file);
+
+ sprintf(line, "DoneResearch bits=%d\n", g_researchDone);
+ fputs(line, file);
+
+ if ( m_blitz->GetStatus(sleep, delay, magnetic, progress) )
+ {
+ sprintf(line, "BlitzMode sleep=%.2f delay=%.2f magnetic=%.2f progress=%.2f\n", sleep, delay, magnetic/g_unit, progress);
+ fputs(line, file);
+ }
+
+ objRank = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetType() == OBJECT_TOTO ) continue;
+ if ( pObj->RetType() == OBJECT_FIX ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+ if ( pObj->RetBurn() ) continue;
+ if ( pObj->RetDead() ) continue;
+ if ( pObj->RetExplo() ) continue;
+
+ pPower = pObj->RetPower();
+ pFret = pObj->RetFret();
+
+ if ( pFret != 0 ) // object transported?
+ {
+ IOWriteObject(file, pFret, "CreateFret");
+ }
+
+ if ( pPower != 0 ) // battery transported?
+ {
+ IOWriteObject(file, pPower, "CreatePower");
+ }
+
+ IOWriteObject(file, pObj, "CreateObject");
+
+ SaveFileScript(pObj, filename, objRank++);
+ }
+ fclose(file);
+
+#if CBOT_STACK
+ // Writes the file of stacks of execution.
+ file = fOpen(filecbot, "wb");
+ if ( file == NULL ) return false;
+
+ version = 1;
+ fWrite(&version, sizeof(long), 1, file); // version of COLOBOT
+ version = CBotProgram::GivVersion();
+ fWrite(&version, sizeof(long), 1, file); // version of CBOT
+
+ objRank = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetType() == OBJECT_TOTO ) continue;
+ if ( pObj->RetType() == OBJECT_FIX ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+ if ( pObj->RetBurn() ) continue;
+ if ( pObj->RetDead() ) continue;
+
+ if ( !SaveFileStack(pObj, file, objRank++) ) break;
+ }
+ CBotClass::SaveStaticState(file);
+ fClose(file);
+#endif
+
+ m_delayWriteMessage = 4; // displays message in 3 frames
+ return true;
+}
+
+// Resumes the game.
+
+CObject* CRobotMain::IOReadObject(char *line, char* filename, int objRank)
+{
+ CObject* pObj;
+//? CBrain* pBrain;
+ CAuto* pAuto;
+ Math::Vector pos, dir, zoom;
+ ObjectType type;
+ int id, run, trainer, toy, option, i;
+ char op[10];
+
+ pos = OpDir(line, "pos")*g_unit;
+ dir = OpDir(line, "angle")*(Math::PI/180.0f);
+ zoom = OpDir(line, "zoom");
+ type = OpTypeObject(line, "type", OBJECT_NULL);
+ id = OpInt(line, "id", 0);
+ if ( type == OBJECT_NULL ) return 0;
+ trainer = OpInt(line, "trainer", 0);
+ toy = OpInt(line, "toy", 0);
+ option = OpInt(line, "option", 0);
+ pObj = CreateObject(pos, dir.y, 1.0f, 0.0f, type, 0.0f, trainer, toy, option);
+ pObj->SetDefRank(objRank);
+ pObj->SetPosition(0, pos);
+ pObj->SetAngle(0, dir);
+ pObj->SetID(id);
+ if ( g_id < id ) g_id = id;
+
+ if ( zoom.x != 0.0f || zoom.y != 0.0f || zoom.z != 0.0f )
+ {
+ pObj->SetZoom(0, zoom);
+ }
+
+ for ( i=1 ; i<OBJECTMAXPART ; i++ )
+ {
+ if ( pObj->RetObjectRank(i) == -1 ) continue;
+
+ sprintf(op, "p%d", i);
+ pos = OpDir(line, op);
+ if ( pos.x != 0.0f || pos.y != 0.0f || pos.z != 0.0f )
+ {
+ pObj->SetPosition(i, pos*g_unit);
+ }
+
+ sprintf(op, "a%d", i);
+ dir = OpDir(line, op);
+ if ( dir.x != 0.0f || dir.y != 0.0f || dir.z != 0.0f )
+ {
+ pObj->SetAngle(i, dir*(Math::PI/180.0f));
+ }
+
+ sprintf(op, "z%d", i);
+ zoom = OpDir(line, op);
+ if ( zoom.x != 0.0f || zoom.y != 0.0f || zoom.z != 0.0f )
+ {
+ pObj->SetZoom(i, zoom);
+ }
+ }
+
+ if ( type == OBJECT_BASE ) m_bBase = true;
+
+ pObj->Read(line);
+
+#if CBOT_STACK
+#else
+ LoadFileScript(pObj, filename, objRank, i);
+#endif
+
+ run = OpInt(line, "run", -1);
+ if ( run != -1 )
+ {
+#if CBOT_STACK
+#else
+ pBrain = pObj->RetBrain();
+ if ( pBrain != 0 )
+ {
+ pBrain->RunProgram(run-1); // starts the program
+ }
+#endif
+
+ pAuto = pObj->RetAuto();
+ if ( pAuto != 0 )
+ {
+ pAuto->Start(run); // starts the film
+ }
+ }
+
+ return pObj;
+}
+
+// Resumes some part of the game.
+
+CObject* CRobotMain::IOReadScene(char *filename, char *filecbot)
+{
+ FILE* file;
+ CObject *pObj, *pPower, *pFret, *pSel;
+ char line[3000];
+ float sleep, delay, progress, magnetic;
+ int i, objRank, nbError, lastError;
+ long version;
+
+ m_bBase = false;
+
+ file = fopen(filename, "r");
+ if ( file == NULL ) return 0;
+
+ pFret = 0;
+ pPower = 0;
+ pSel = 0;
+ objRank = 0;
+ while ( fgets(line, 3000, file) != NULL )
+ {
+ for ( i=0 ; i<3000 ; i++ )
+ {
+ if ( line[i] == '\t' ) line[i] = ' '; // replace tab by space
+ if ( line[i] == '/' && line[i+1] == '/' )
+ {
+ line[i] = 0;
+ break;
+ }
+ }
+
+ if ( Cmd(line, "Map") )
+ {
+ m_map->ZoomMap(OpFloat(line, "zoom", 1.0f));
+ }
+
+ if ( Cmd(line, "DoneResearch") )
+ {
+ g_researchDone = OpInt(line, "bits", 0);
+ }
+
+ if ( Cmd(line, "BlitzMode") )
+ {
+ sleep = OpFloat(line, "sleep", 0.0f);
+ delay = OpFloat(line, "delay", 3.0f);
+ magnetic = OpFloat(line, "magnetic", 50.0f)*g_unit;
+ progress = OpFloat(line, "progress", 0.0f);
+ m_blitz->SetStatus(sleep, delay, magnetic, progress);
+ }
+
+ if ( Cmd(line, "CreateFret") )
+ {
+ pFret = IOReadObject(line, filename, -1);
+ }
+
+ if ( Cmd(line, "CreatePower") )
+ {
+ pPower = IOReadObject(line, filename, -1);
+ }
+
+ if ( Cmd(line, "CreateObject") )
+ {
+ pObj = IOReadObject(line, filename, objRank++);
+
+ if ( OpInt(line, "select", 0) )
+ {
+ pSel = pObj;
+ }
+
+ if ( pFret != 0 )
+ {
+ CTaskManip* task;
+
+ pObj->SetFret(pFret);
+ task = new CTaskManip(m_iMan, pObj);
+ task->Start(TMO_AUTO, TMA_GRAB); // holds the object!
+ delete task;
+ }
+
+ if ( pPower != 0 )
+ {
+ pObj->SetPower(pPower);
+ pPower->SetTruck(pObj);
+ }
+
+ pFret = 0;
+ pPower = 0;
+ }
+ }
+ fclose(file);
+
+#if CBOT_STACK
+ // Compiles scripts.
+ nbError = 0;
+ do
+ {
+ lastError = nbError;
+ nbError = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ objRank = pObj->RetDefRank();
+ if ( objRank == -1 ) continue;
+
+ LoadFileScript(pObj, filename, objRank, nbError);
+ }
+ }
+ while ( nbError > 0 && nbError != lastError );
+
+ // Reads the file of stacks of execution.
+ file = fOpen(filecbot, "rb");
+ if ( file != NULL )
+ {
+ fRead(&version, sizeof(long), 1, file); // version of COLOBOT
+ if ( version == 1 )
+ {
+ fRead(&version, sizeof(long), 1, file); // version of CBOT
+ if ( version == CBotProgram::GivVersion() )
+ {
+ objRank = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetType() == OBJECT_TOTO ) continue;
+ if ( pObj->RetType() == OBJECT_FIX ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+ if ( pObj->RetBurn() ) continue;
+ if ( pObj->RetDead() ) continue;
+
+ if ( !ReadFileStack(pObj, file, objRank++) ) break;
+ }
+ }
+ }
+ CBotClass::RestoreStaticState(file);
+ fClose(file);
+ }
+#endif
+
+ return pSel;
+}
+
+
+// Writes the global parameters for free play.
+
+void CRobotMain::WriteFreeParam()
+{
+ FILE* file;
+ char filename[_MAX_FNAME];
+ char line[100];
+
+ m_freeResearch |= g_researchDone;
+ m_freeBuild |= g_build;
+
+ if ( m_gamerName[0] == 0 ) return;
+
+ sprintf(filename, "%s\\%s\\research.gam", RetSavegameDir(), m_gamerName);
+ file = fopen(filename, "w");
+ if ( file == NULL ) return;
+
+ sprintf(line, "research=%d build=%d\n", m_freeResearch, m_freeBuild);
+ fputs(line, file);
+ fclose(file);
+}
+
+// Reads the global parameters for free play.
+
+void CRobotMain::ReadFreeParam()
+{
+ FILE* file;
+ char filename[_MAX_FNAME];
+ char line[100];
+
+ m_freeResearch = 0;
+ m_freeBuild = 0;
+
+ if ( m_gamerName[0] == 0 ) return;
+
+ sprintf(filename, "%s\\%s\\research.gam", RetSavegameDir(), m_gamerName);
+ file = fopen(filename, "r");
+ if ( file == NULL ) return;
+
+ if ( fgets(line, 100, file) != NULL )
+ {
+ sscanf(line, "research=%d build=%d\n", &m_freeResearch, &m_freeBuild);
+ }
+
+ fclose(file);
+}
+
+
+// Resets all objects to their original position.
+
+void CRobotMain::ResetObject()
+{
+#if 0
+ CObject* pObj;
+ CObject* pTruck;
+ CAuto* pAuto;
+ CBrain* brain;
+ CPyro* pyro;
+ ResetCap cap;
+ Math::Vector pos, angle;
+ int i;
+
+ // Removes all pyrotechnic effects in progress.
+ while ( true )
+ {
+ pyro = (CPyro*)m_iMan->SearchInstance(CLASS_PYRO, 0);
+ if ( pyro == 0 ) break;
+
+ pyro->DeleteObject();
+ delete pyro;
+ }
+
+ // Removes all bullets in progress.
+ m_particule->DeleteParticule(PARTIGUN1);
+ m_particule->DeleteParticule(PARTIGUN2);
+ m_particule->DeleteParticule(PARTIGUN3);
+ m_particule->DeleteParticule(PARTIGUN4);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ cap = pObj->RetResetCap();
+ if ( cap == RESET_NONE ) continue;
+
+ if ( cap == RESET_DELETE )
+ {
+ pTruck = pObj->RetTruck();
+ if ( pTruck != 0 )
+ {
+ pTruck->SetFret(0);
+ pObj->SetTruck(0);
+ }
+ pObj->DeleteObject();
+ delete pObj;
+ i --;
+ continue;
+ }
+
+ pAuto = pObj->RetAuto();
+ if ( pAuto != 0 )
+ {
+ pAuto->Abort();
+ }
+
+ if ( pObj->RetEnable() ) // object still active?
+ {
+ brain = pObj->RetBrain();
+ if ( brain != 0 )
+ {
+ pos = pObj->RetResetPosition();
+ angle = pObj->RetResetAngle();
+
+ if ( pos == pObj->RetPosition(0) &&
+ angle == pObj->RetAngle(0) ) continue;
+ brain->StartTaskReset(pos, angle);
+ continue;
+ }
+ }
+
+ pObj->SetEnable(true); // active again
+
+ pos = pObj->RetResetPosition();
+ angle = pObj->RetResetAngle();
+
+ if ( pos == pObj->RetPosition(0) &&
+ angle == pObj->RetAngle(0) ) continue;
+
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_RESET, pObj);
+
+ brain = pObj->RetBrain();
+ if ( brain != 0 )
+ {
+ brain->RunProgram(pObj->RetResetRun());
+ }
+ }
+#else
+ m_bResetCreate = true;
+#endif
+}
+
+// Resets all objects to their original position.
+
+void CRobotMain::ResetCreate()
+{
+ CObject* pObj;
+ CPyro* pyro;
+ ResetCap cap;
+ int i;
+
+ SaveAllScript();
+
+ // Removes all bullets in progress.
+ m_particule->DeleteParticule(PARTIGUN1);
+ m_particule->DeleteParticule(PARTIGUN2);
+ m_particule->DeleteParticule(PARTIGUN3);
+ m_particule->DeleteParticule(PARTIGUN4);
+
+ DeselectAll(); // removes the control buttons
+ DeleteAllObjects(); // removes all the current 3D Scene
+
+ m_particule->FlushParticule();
+ m_terrain->FlushBuildingLevel();
+ m_iMan->Flush(CLASS_OBJECT);
+ m_iMan->Flush(CLASS_PHYSICS);
+ m_iMan->Flush(CLASS_BRAIN);
+ m_iMan->Flush(CLASS_PYRO);
+ m_camera->SetType(CAMERA_DIALOG);
+
+ CreateScene(m_dialog->RetSceneSoluce(), false, true);
+
+ if ( !RetNiceReset() ) return;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ cap = pObj->RetResetCap();
+ if ( cap == RESET_NONE ) continue;
+
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_RESET, pObj);
+ }
+}
+
+// Checks if the mission is over.
+
+Error CRobotMain::CheckEndMission(bool bFrame)
+{
+ CObject* pObj;
+ Math::Vector bPos, oPos;
+ ObjectType type;
+ int t, i, nb;
+
+ for ( t=0 ; t<m_endTakeTotal ; t++ )
+ {
+ if ( m_endTake[t].message[0] != 0 ) continue;
+
+ bPos = m_endTake[t].pos;
+ bPos.y = 0.0f;
+
+ nb = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ // Do not use RetActif () because an invisible worm (underground)
+ // should be regarded as existing here!
+ if ( pObj->RetLock() ) continue;
+ if ( pObj->RetRuin() ) continue;
+ if ( !pObj->RetEnable() ) continue;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_SCRAP2 ||
+ type == OBJECT_SCRAP3 ||
+ type == OBJECT_SCRAP4 ||
+ type == OBJECT_SCRAP5 ) // wastes?
+ {
+ type = OBJECT_SCRAP1;
+ }
+ if ( type != m_endTake[t].type ) continue;
+
+ if ( pObj->RetTruck() == 0 )
+ {
+ oPos = pObj->RetPosition(0);
+ }
+ else
+ {
+ oPos = pObj->RetTruck()->RetPosition(0);
+ }
+ oPos.y = 0.0f;
+ if ( Math::DistanceProjected(oPos, bPos) <= m_endTake[t].dist )
+ {
+ nb ++;
+ }
+ }
+
+ if ( nb <= m_endTake[t].lost )
+ {
+ if ( m_endTake[t].type == OBJECT_HUMAN )
+ {
+ if ( m_lostDelay == 0.0f )
+ {
+ m_lostDelay = 0.1f; // lost immediately
+ m_winDelay = 0.0f;
+ }
+ m_displayText->SetEnable(false);
+ return INFO_LOSTq;
+ }
+ else
+ {
+ if ( m_lostDelay == 0.0f )
+ {
+ m_displayText->DisplayError(INFO_LOST, Math::Vector(0.0f,0.0f,0.0f));
+ m_lostDelay = m_endTakeLostDelay; // lost in 6 seconds
+ m_winDelay = 0.0f;
+ }
+ m_displayText->SetEnable(false);
+ return INFO_LOST;
+ }
+ }
+ if ( nb < m_endTake[t].min ||
+ nb > m_endTake[t].max )
+ {
+ m_displayText->SetEnable(true);
+ return ERR_MISSION_NOTERM;
+ }
+ if ( m_endTake[t].bImmediat )
+ {
+ if ( m_winDelay == 0.0f )
+ {
+ m_winDelay = m_endTakeWinDelay; // wins in x seconds
+ m_lostDelay = 0.0f;
+ }
+ m_displayText->SetEnable(false);
+ return ERR_OK; // mission ended
+ }
+ }
+
+ if ( m_endTakeResearch != 0 )
+ {
+ if ( m_endTakeResearch != (m_endTakeResearch&g_researchDone) )
+ {
+ m_displayText->SetEnable(true);
+ return ERR_MISSION_NOTERM;
+ }
+ }
+
+ if ( m_endTakeWinDelay == -1.0f )
+ {
+ m_winDelay = 1.0f; // wins in one second
+ m_lostDelay = 0.0f;
+ m_displayText->SetEnable(false);
+ return ERR_OK; // mission ended
+ }
+
+ if ( bFrame && m_bBase ) return ERR_MISSION_NOTERM;
+
+ if ( m_winDelay == 0.0f )
+ {
+ m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f));
+ m_winDelay = m_endTakeWinDelay; // wins in two seconds
+ m_lostDelay = 0.0f;
+ }
+ m_displayText->SetEnable(false);
+ return ERR_OK; // mission ended
+}
+
+// Checks if the mission is finished after displaying a message.
+
+void CRobotMain::CheckEndMessage(char *message)
+{
+ int t;
+
+ for ( t=0 ; t<m_endTakeTotal ; t++ )
+ {
+ if ( m_endTake[t].message[0] == 0 ) continue;
+
+ if ( strcmp(m_endTake[t].message, message) == 0 )
+ {
+ m_displayText->DisplayError(INFO_WIN, Math::Vector(0.0f,0.0f,0.0f));
+ m_winDelay = m_endTakeWinDelay; // wins in 2 seconds
+ m_lostDelay = 0.0f;
+ }
+ }
+}
+
+
+// Returns the number of instructions required.
+
+int CRobotMain::RetObligatoryToken()
+{
+ return m_obligatoryTotal;
+}
+
+// Returns the name of a required instruction.
+
+char* CRobotMain::RetObligatoryToken(int i)
+{
+ return m_obligatoryToken[i];
+}
+
+// Checks if an instruction is part of the obligatory list.
+
+int CRobotMain::IsObligatoryToken(char *token)
+{
+ int i;
+
+ for ( i=0 ; i<m_obligatoryTotal ; i++ )
+ {
+ if ( strcmp(token, m_obligatoryToken[i]) == 0 )
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+// Checks if an instruction is not part of the banned list.
+
+bool CRobotMain::IsProhibitedToken(char *token)
+{
+ int i;
+
+ for ( i=0 ; i<m_prohibitedTotal ; i++ )
+ {
+ if ( strcmp(token, m_prohibitedToken[i]) == 0 )
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+// Indicates whether it is possible to control a driving robot.
+
+bool CRobotMain::RetTrainerPilot()
+{
+ return m_bTrainerPilot;
+}
+
+// Indicates whether the scene is fixed, without interaction.
+
+bool CRobotMain::RetFixScene()
+{
+ return m_bFixScene;
+}
+
+
+char* CRobotMain::RetTitle()
+{
+ return m_title;
+}
+
+char* CRobotMain::RetResume()
+{
+ return m_resume;
+}
+
+char* CRobotMain::RetScriptName()
+{
+ return m_scriptName;
+}
+
+char* CRobotMain::RetScriptFile()
+{
+ return m_scriptFile;
+}
+
+
+bool CRobotMain::RetGlint()
+{
+ return m_dialog->RetGlint();
+}
+
+bool CRobotMain::RetSoluce4()
+{
+ return m_dialog->RetSoluce4();
+}
+
+bool CRobotMain::RetMovies()
+{
+ return m_dialog->RetMovies();
+}
+
+bool CRobotMain::RetNiceReset()
+{
+ return m_dialog->RetNiceReset();
+}
+
+bool CRobotMain::RetHimselfDamage()
+{
+ return m_dialog->RetHimselfDamage();
+}
+
+bool CRobotMain::RetShowSoluce()
+{
+ return m_bShowSoluce;
+}
+
+bool CRobotMain::RetSceneSoluce()
+{
+ if ( m_infoFilename[SATCOM_SOLUCE][0] == 0 ) return false;
+ return m_dialog->RetSceneSoluce();
+}
+
+bool CRobotMain::RetShowAll()
+{
+ return m_bShowAll;
+}
+
+bool CRobotMain::RetCheatRadar()
+{
+ return m_bCheatRadar;
+}
+
+char* CRobotMain::RetSavegameDir()
+{
+ return m_dialog->RetSavegameDir();
+}
+
+char* CRobotMain::RetPublicDir()
+{
+ return m_dialog->RetPublicDir();
+}
+
+char* CRobotMain::RetFilesDir()
+{
+ return m_dialog->RetFilesDir();
+}
+
+
+// Change the player's name.
+
+void CRobotMain::SetGamerName(char *name)
+{
+ strcpy(m_gamerName, name);
+ SetGlobalGamerName(m_gamerName);
+ ReadFreeParam();
+}
+
+// Gives the player's name.
+
+char* CRobotMain::RetGamerName()
+{
+ return m_gamerName;
+}
+
+
+// Returns the representation to use for the player.
+
+int CRobotMain::RetGamerFace()
+{
+ return m_dialog->RetGamerFace();
+}
+
+// Returns the representation to use for the player.
+
+int CRobotMain::RetGamerGlasses()
+{
+ return m_dialog->RetGamerGlasses();
+}
+
+// Returns the mode with just the head.
+
+bool CRobotMain::RetGamerOnlyHead()
+{
+ return m_dialog->RetGamerOnlyHead();
+}
+
+// Returns the angle of presentation.
+
+float CRobotMain::RetPersoAngle()
+{
+ return m_dialog->RetPersoAngle();
+}
+
+
+// Changes on the pause mode.
+
+void CRobotMain::ChangePause(bool bPause)
+{
+ m_bPause = bPause;
+ m_engine->SetPause(m_bPause);
+
+ m_sound->MuteAll(m_bPause);
+ CreateShortcuts();
+ if ( m_bPause ) HiliteClear();
+}
+
+
+// Changes game speed
+
+void CRobotMain::SetSpeed(float speed)
+{
+ CButton* pb;
+ char text[10];
+
+ m_engine->SetSpeed(speed);
+
+ pb = (CButton*)m_interface->SearchControl(EVENT_SPEED);
+ if ( pb != 0 )
+ {
+ if ( speed == 1.0f )
+ {
+ pb->ClearState(STATE_VISIBLE);
+ }
+ else
+ {
+ sprintf(text, "x%.1f", speed);
+ pb->SetName(text);
+ pb->SetState(STATE_VISIBLE);
+ }
+ }
+}
+
+float CRobotMain::RetSpeed()
+{
+ return m_engine->RetSpeed();
+}
+
+
+// Creates interface shortcuts to the units.
+
+bool CRobotMain::CreateShortcuts()
+{
+ if ( m_phase != PHASE_SIMUL ) return false;
+ if ( !m_bShortCut ) return false;
+ return m_short->CreateShortcuts();
+}
+
+// Updates the map.
+
+void CRobotMain::UpdateMap()
+{
+ m_map->UpdateMap();
+}
+
+// Indicates whether the mini-map is visible.
+
+bool CRobotMain::RetShowMap()
+{
+ return m_map->RetShowMap() && m_bMapShow;
+}
+
+
+// Management of the lock mode for movies.
+
+void CRobotMain::SetMovieLock(bool bLock)
+{
+ m_bMovieLock = bLock;
+ m_engine->SetMovieLock(m_bMovieLock);
+
+ CreateShortcuts();
+ m_map->ShowMap(!m_bMovieLock && m_bMapShow);
+ if ( m_bMovieLock ) HiliteClear();
+ m_engine->SetMouseHide(m_bMovieLock);
+}
+
+bool CRobotMain::RetMovieLock()
+{
+ return m_bMovieLock;
+}
+
+bool CRobotMain::RetInfoLock()
+{
+ return ( m_displayInfo != 0 ); // info in progress?
+}
+
+// Management of the blocking of the call of SatCom.
+
+void CRobotMain::SetSatComLock(bool bLock)
+{
+ m_bSatComLock = bLock;
+}
+
+bool CRobotMain::RetSatComLock()
+{
+ return m_bSatComLock;
+}
+
+// Management of the lock mode for the edition.
+
+void CRobotMain::SetEditLock(bool bLock, bool bEdit)
+{
+ m_bEditLock = bLock;
+
+ CreateShortcuts();
+
+ // Do not remove the card if it contains a still image.
+ if ( !bLock || !m_map->RetFixImage() )
+ {
+ m_map->ShowMap(!m_bEditLock && m_bMapShow);
+ }
+
+ m_displayText->HideText(bLock);
+ m_engine->FlushPressKey();
+
+ if ( m_bEditLock )
+ {
+ HiliteClear();
+ }
+ else
+ {
+ m_bEditFull = false;
+ }
+}
+
+bool CRobotMain::RetEditLock()
+{
+ return m_bEditLock;
+}
+
+// Management of the fullscreen mode during editing.
+
+void CRobotMain::SetEditFull(bool bFull)
+{
+ m_bEditFull = bFull;
+}
+
+bool CRobotMain::RetEditFull()
+{
+ return m_bEditFull;
+}
+
+
+bool CRobotMain::RetFreePhoto()
+{
+ return m_bFreePhoto;
+}
+
+
+// Indicates whether mouse is on an friend object, on which we should not shoot.
+
+void CRobotMain::SetFriendAim(bool bFriend)
+{
+ m_bFriendAim = bFriend;
+}
+
+bool CRobotMain::RetFriendAim()
+{
+ return m_bFriendAim;
+}
+
+
+// Management of the precision of drawing the ground.
+
+void CRobotMain::SetTracePrecision(float factor)
+{
+ m_engine->SetTracePrecision(factor);
+}
+
+float CRobotMain::RetTracePrecision()
+{
+ return m_engine->RetTracePrecision();
+}
+
+
+// Starts music with a mission.
+
+void CRobotMain::StartMusic()
+{
+ if ( m_audioTrack != 0 )
+ {
+ m_sound->StopMusic();
+ m_sound->PlayMusic(m_audioTrack, m_bAudioRepeat);
+ }
+}
+
+// Removes hilite and tooltip.
+
+void CRobotMain::ClearInterface()
+{
+ HiliteClear(); // removes setting evidence
+ m_tooltipName[0] = 0; // really removes the tooltip
+}
+
+
diff --git a/src/object/robotmain.h b/src/object/robotmain.h
index a4b0489..559453b 100644
--- a/src/object/robotmain.h
+++ b/src/object/robotmain.h
@@ -1,459 +1,459 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// robotmain.h
-
-#pragma once
-
-
-#include <stdio.h>
-
-#include "common/misc.h"
-#include "old/d3dengine.h"
-#include "object/object.h"
-#include "object/mainmovie.h"
-#include "old/camera.h"
-#include "old/particule.h"
-
-
-enum Phase
-{
- PHASE_INIT,
- PHASE_TERM,
- PHASE_NAME,
- PHASE_PERSO,
- PHASE_TRAINER,
- PHASE_DEFI,
- PHASE_MISSION,
- PHASE_FREE,
- PHASE_TEEN,
- PHASE_USER,
- PHASE_PROTO,
- PHASE_LOADING,
- PHASE_SIMUL,
- PHASE_MODEL,
- PHASE_SETUPd,
- PHASE_SETUPg,
- PHASE_SETUPp,
- PHASE_SETUPc,
- PHASE_SETUPs,
- PHASE_SETUPds,
- PHASE_SETUPgs,
- PHASE_SETUPps,
- PHASE_SETUPcs,
- PHASE_SETUPss,
- PHASE_WRITE,
- PHASE_READ,
- PHASE_WRITEs,
- PHASE_READs,
- PHASE_WIN,
- PHASE_LOST,
- PHASE_WELCOME1,
- PHASE_WELCOME2,
- PHASE_WELCOME3,
- PHASE_GENERIC,
-};
-
-
-class CInstanceManager;
-class CMainDialog;
-class CMainShort;
-class CMainMap;
-class CEvent;
-class CD3DEngine;
-class CLight;
-class CWater;
-class CCloud;
-class CBlitz;
-class CPlanet;
-class CTerrain;
-class CModel;
-class CInterface;
-class CWindow;
-class CControl;
-class CDisplayText;
-class CDisplayInfo;
-class CSound;
-
-
-struct EndTake
-{
- Math::Vector pos;
- float dist;
- ObjectType type;
- int min; // wins if>
- int max; // wins if <
- int lost; // lost if <=
- bool bImmediat;
- char message[100];
-};
-
-
-const int MAXNEWSCRIPTNAME = 20;
-
-struct NewScriptName
-{
- bool bUsed;
- ObjectType type;
- char name[40];
-};
-
-
-const int MAXSHOWLIMIT = 5;
-const int MAXSHOWPARTI = 200;
-const float SHOWLIMITTIME = 20.0f;
-
-struct ShowLimit
-{
- bool bUsed;
- Math::Vector pos;
- float radius;
- int total;
- int parti[MAXSHOWPARTI];
- CObject* link;
- float duration;
- float time;
-};
-
-
-const int SATCOM_HUSTON = 0;
-const int SATCOM_SAT = 1;
-const int SATCOM_OBJECT = 2;
-const int SATCOM_LOADING = 3;
-const int SATCOM_PROG = 4;
-const int SATCOM_SOLUCE = 5;
-const int SATCOM_MAX = 6;
-
-
-
-class CRobotMain
-{
-public:
- CRobotMain(CInstanceManager* iMan);
- ~CRobotMain();
-
- void CreateIni();
-
- void ChangePhase(Phase phase);
- bool EventProcess(const Event &event);
-
- bool CreateShortcuts();
- void ScenePerso();
-
- void SetMovieLock(bool bLock);
- bool RetMovieLock();
- bool RetInfoLock();
- void SetSatComLock(bool bLock);
- bool RetSatComLock();
- void SetEditLock(bool bLock, bool bEdit);
- bool RetEditLock();
- void SetEditFull(bool bFull);
- bool RetEditFull();
- bool RetFreePhoto();
- void SetFriendAim(bool bFriend);
- bool RetFriendAim();
-
- void SetTracePrecision(float factor);
- float RetTracePrecision();
-
- void ChangePause(bool bPause);
-
- void SetSpeed(float speed);
- float RetSpeed();
-
- void UpdateShortcuts();
- void SelectHuman();
- CObject* SearchHuman();
- CObject* SearchToto();
- CObject* SearchNearest(Math::Vector pos, CObject* pExclu);
- bool SelectObject(CObject* pObj, bool bDisplayError=true);
- CObject* RetSelectObject();
- CObject* DeselectAll();
- bool DeleteObject();
-
- void ResetObject();
- void ResetCreate();
- Error CheckEndMission(bool bFrame);
- void CheckEndMessage(char *message);
- int RetObligatoryToken();
- char* RetObligatoryToken(int i);
- int IsObligatoryToken(char *token);
- bool IsProhibitedToken(char *token);
- void UpdateMap();
- bool RetShowMap();
-
- MainMovieType RetMainMovie();
-
- void FlushDisplayInfo();
- void StartDisplayInfo(int index, bool bMovie);
- void StartDisplayInfo(char *filename, int index);
- void StopDisplayInfo();
- char* RetDisplayInfoName(int index);
- int RetDisplayInfoPosition(int index);
- void SetDisplayInfoPosition(int index, int pos);
-
- void StartSuspend();
- void StopSuspend();
-
- float RetGameTime();
-
- void SetFontSize(float size);
- float RetFontSize();
- void SetWindowPos(Math::Point pos);
- Math::Point RetWindowPos();
- void SetWindowDim(Math::Point dim);
- Math::Point RetWindowDim();
-
- void SetIOPublic(bool bMode);
- bool RetIOPublic();
- void SetIOPos(Math::Point pos);
- Math::Point RetIOPos();
- void SetIODim(Math::Point dim);
- Math::Point RetIODim();
-
- char* RetTitle();
- char* RetResume();
- char* RetScriptName();
- char* RetScriptFile();
- bool RetTrainerPilot();
- bool RetFixScene();
- bool RetGlint();
- bool RetSoluce4();
- bool RetMovies();
- bool RetNiceReset();
- bool RetHimselfDamage();
- bool RetShowSoluce();
- bool RetSceneSoluce();
- bool RetShowAll();
- bool RetCheatRadar();
- char* RetSavegameDir();
- char* RetPublicDir();
- char* RetFilesDir();
-
- void SetGamerName(char *name);
- char* RetGamerName();
- int RetGamerFace();
- int RetGamerGlasses();
- bool RetGamerOnlyHead();
- float RetPersoAngle();
-
- void StartMusic();
- void ClearInterface();
- void ChangeColor();
-
- float SearchNearestObject(Math::Vector center, CObject *exclu);
- bool FreeSpace(Math::Vector &center, float minRadius, float maxRadius, float space, CObject *exclu);
- float RetFlatZoneRadius(Math::Vector center, float maxRadius, CObject *exclu);
- void HideDropZone(CObject* metal);
- void ShowDropZone(CObject* metal, CObject* truck);
- void FlushShowLimit(int i);
- void SetShowLimit(int i, ParticuleType parti, CObject *pObj, Math::Vector pos, float radius, float duration=SHOWLIMITTIME);
- void AdjustShowLimit(int i, Math::Vector pos);
- void StartShowLimit();
- void FrameShowLimit(float rTime);
-
- void CompileScript(bool bSoluce);
- void LoadOneScript(CObject *pObj, int &nbError);
- void LoadFileScript(CObject *pObj, char* filename, int objRank, int &nbError);
- void SaveAllScript();
- void SaveOneScript(CObject *pObj);
- void SaveFileScript(CObject *pObj, char* filename, int objRank);
- bool SaveFileStack(CObject *pObj, FILE *file, int objRank);
- bool ReadFileStack(CObject *pObj, FILE *file, int objRank);
-
- bool FlushNewScriptName();
- bool AddNewScriptName(ObjectType type, char *name);
- char* RetNewScriptName(ObjectType type, int rank);
-
- void WriteFreeParam();
- void ReadFreeParam();
-
- bool IsBusy();
- bool IOWriteScene(char *filename, char *filecbot, char *info);
- CObject* IOReadScene(char *filename, char *filecbot);
- void IOWriteObject(FILE *file, CObject* pObj, char *cmd);
- CObject* IOReadObject(char *line, char* filename, int objRank);
-
- int CreateSpot(Math::Vector pos, D3DCOLORVALUE color);
-
-protected:
- bool EventFrame(const Event &event);
- bool EventObject(const Event &event);
- void InitEye();
-
- void Convert();
- void CreateScene(bool bSoluce, bool bFixScene, bool bResetObject);
-
- void CreateModel();
- Math::Vector LookatPoint( Math::Vector eye, float angleH, float angleV, float length );
- CObject* CreateObject(Math::Vector pos, float angle, float zoom, float height, ObjectType type, float power=1.0f, bool bTrainer=false, bool bToy=false, int option=0);
- int CreateLight(Math::Vector direction, D3DCOLORVALUE color);
- void HiliteClear();
- void HiliteObject(Math::Point pos);
- void HiliteFrame(float rTime);
- void CreateTooltip(Math::Point pos, char* text);
- void ClearTooltip();
- CObject* DetectObject(Math::Point pos);
- void ChangeCamera();
- void RemoteCamera(float pan, float zoom, float rTime);
- void KeyCamera(EventMsg event, long param);
- void AbortMovie();
- bool IsSelectable(CObject* pObj);
- void SelectOneObject(CObject* pObj, bool bDisplayError=true);
- void HelpObject();
- bool DeselectObject();
- void DeleteAllObjects();
- void UpdateInfoText();
- CObject* SearchObject(ObjectType type);
- CObject* RetSelect();
- void StartDisplayVisit(EventMsg event);
- void FrameVisit(float rTime);
- void StopDisplayVisit();
- void ExecuteCmd(char *cmd);
- bool TestGadgetQuantity(int rank);
-
-protected:
- CInstanceManager* m_iMan;
- CMainMovie* m_movie;
- CMainDialog* m_dialog;
- CMainShort* m_short;
- CMainMap* m_map;
- CEvent* m_event;
- CD3DEngine* m_engine;
- CParticule* m_particule;
- CWater* m_water;
- CCloud* m_cloud;
- CBlitz* m_blitz;
- CPlanet* m_planet;
- CLight* m_light;
- CTerrain* m_terrain;
- CModel* m_model;
- CInterface* m_interface;
- CCamera* m_camera;
- CDisplayText* m_displayText;
- CDisplayInfo* m_displayInfo;
- CSound* m_sound;
-
- float m_time;
- float m_gameTime;
- float m_checkEndTime;
- float m_winDelay;
- float m_lostDelay;
- bool m_bFixScene; // scene fixed, no interraction
- bool m_bBase; // OBJECT_BASE exists in mission
- Math::Point m_lastMousePos;
- CObject* m_selectObject;
-
- Phase m_phase;
- int m_cameraRank;
- D3DCOLORVALUE m_color;
- bool m_bFreePhoto;
- bool m_bCmdEdit;
- bool m_bShowPos;
- bool m_bSelectInsect;
- bool m_bShowSoluce;
- bool m_bShowAll;
- bool m_bCheatRadar;
- bool m_bAudioRepeat;
- bool m_bShortCut;
- int m_audioTrack;
- int m_delayWriteMessage;
- int m_movieInfoIndex;
-
- bool m_bImmediatSatCom; // SatCom immediately?
- bool m_bBeginSatCom; // messages SatCom poster?
- bool m_bMovieLock; // movie in progress?
- bool m_bSatComLock; // call of SatCom is possible?
- bool m_bEditLock; // edition in progress?
- bool m_bEditFull; // edition in full screen?
- bool m_bPause; // simulation paused
- bool m_bHilite;
- bool m_bTrainerPilot; // remote trainer?
- bool m_bSuspend;
- bool m_bFriendAim;
- bool m_bResetCreate;
- bool m_bMapShow;
- bool m_bMapImage;
- char m_mapFilename[100];
-
- Math::Point m_tooltipPos;
- char m_tooltipName[100];
- float m_tooltipTime;
-
- char m_infoFilename[SATCOM_MAX][100]; // names of text files
- CObject* m_infoObject;
- int m_infoIndex;
- int m_infoPos[SATCOM_MAX];
- int m_infoUsed;
-
- char m_title[100];
- char m_resume[500];
- char m_scriptName[100];
- char m_scriptFile[100];
- int m_endingWinRank;
- int m_endingLostRank;
- bool m_bWinTerminate;
-
- float m_fontSize;
- Math::Point m_windowPos;
- Math::Point m_windowDim;
-
- bool m_IOPublic;
- Math::Point m_IOPos;
- Math::Point m_IODim;
-
- NewScriptName m_newScriptName[MAXNEWSCRIPTNAME];
-
- float m_cameraPan;
- float m_cameraZoom;
-
- EventMsg m_visitLast;
- CObject* m_visitObject;
- CObject* m_visitArrow;
- float m_visitTime;
- float m_visitParticule;
- Math::Vector m_visitPos;
- Math::Vector m_visitPosArrow;
-
- int m_endTakeTotal;
- EndTake m_endTake[10];
- long m_endTakeResearch;
- float m_endTakeWinDelay;
- float m_endTakeLostDelay;
-
- int m_obligatoryTotal;
- char m_obligatoryToken[100][20];
- int m_prohibitedTotal;
- char m_prohibitedToken[100][20];
-
- char m_gamerName[100];
-
- long m_freeBuild; // constructible buildings
- long m_freeResearch; // researches possible
-
- ShowLimit m_showLimit[MAXSHOWLIMIT];
-
- D3DCOLORVALUE m_colorRefBot;
- D3DCOLORVALUE m_colorNewBot;
- D3DCOLORVALUE m_colorRefAlien;
- D3DCOLORVALUE m_colorNewAlien;
- D3DCOLORVALUE m_colorRefGreen;
- D3DCOLORVALUE m_colorNewGreen;
- D3DCOLORVALUE m_colorRefWater;
- D3DCOLORVALUE m_colorNewWater;
- float m_colorShiftWater;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// robotmain.h
+
+#pragma once
+
+
+#include <stdio.h>
+
+#include "common/misc.h"
+#include "old/d3dengine.h"
+#include "object/object.h"
+#include "object/mainmovie.h"
+#include "old/camera.h"
+#include "old/particule.h"
+
+
+enum Phase
+{
+ PHASE_INIT,
+ PHASE_TERM,
+ PHASE_NAME,
+ PHASE_PERSO,
+ PHASE_TRAINER,
+ PHASE_DEFI,
+ PHASE_MISSION,
+ PHASE_FREE,
+ PHASE_TEEN,
+ PHASE_USER,
+ PHASE_PROTO,
+ PHASE_LOADING,
+ PHASE_SIMUL,
+ PHASE_MODEL,
+ PHASE_SETUPd,
+ PHASE_SETUPg,
+ PHASE_SETUPp,
+ PHASE_SETUPc,
+ PHASE_SETUPs,
+ PHASE_SETUPds,
+ PHASE_SETUPgs,
+ PHASE_SETUPps,
+ PHASE_SETUPcs,
+ PHASE_SETUPss,
+ PHASE_WRITE,
+ PHASE_READ,
+ PHASE_WRITEs,
+ PHASE_READs,
+ PHASE_WIN,
+ PHASE_LOST,
+ PHASE_WELCOME1,
+ PHASE_WELCOME2,
+ PHASE_WELCOME3,
+ PHASE_GENERIC,
+};
+
+
+class CInstanceManager;
+class CMainDialog;
+class CMainShort;
+class CMainMap;
+class CEvent;
+class CD3DEngine;
+class CLight;
+class CWater;
+class CCloud;
+class CBlitz;
+class CPlanet;
+class CTerrain;
+class CModel;
+class CInterface;
+class CWindow;
+class CControl;
+class CDisplayText;
+class CDisplayInfo;
+class CSound;
+
+
+struct EndTake
+{
+ Math::Vector pos;
+ float dist;
+ ObjectType type;
+ int min; // wins if>
+ int max; // wins if <
+ int lost; // lost if <=
+ bool bImmediat;
+ char message[100];
+};
+
+
+const int MAXNEWSCRIPTNAME = 20;
+
+struct NewScriptName
+{
+ bool bUsed;
+ ObjectType type;
+ char name[40];
+};
+
+
+const int MAXSHOWLIMIT = 5;
+const int MAXSHOWPARTI = 200;
+const float SHOWLIMITTIME = 20.0f;
+
+struct ShowLimit
+{
+ bool bUsed;
+ Math::Vector pos;
+ float radius;
+ int total;
+ int parti[MAXSHOWPARTI];
+ CObject* link;
+ float duration;
+ float time;
+};
+
+
+const int SATCOM_HUSTON = 0;
+const int SATCOM_SAT = 1;
+const int SATCOM_OBJECT = 2;
+const int SATCOM_LOADING = 3;
+const int SATCOM_PROG = 4;
+const int SATCOM_SOLUCE = 5;
+const int SATCOM_MAX = 6;
+
+
+
+class CRobotMain
+{
+public:
+ CRobotMain(CInstanceManager* iMan);
+ ~CRobotMain();
+
+ void CreateIni();
+
+ void ChangePhase(Phase phase);
+ bool EventProcess(const Event &event);
+
+ bool CreateShortcuts();
+ void ScenePerso();
+
+ void SetMovieLock(bool bLock);
+ bool RetMovieLock();
+ bool RetInfoLock();
+ void SetSatComLock(bool bLock);
+ bool RetSatComLock();
+ void SetEditLock(bool bLock, bool bEdit);
+ bool RetEditLock();
+ void SetEditFull(bool bFull);
+ bool RetEditFull();
+ bool RetFreePhoto();
+ void SetFriendAim(bool bFriend);
+ bool RetFriendAim();
+
+ void SetTracePrecision(float factor);
+ float RetTracePrecision();
+
+ void ChangePause(bool bPause);
+
+ void SetSpeed(float speed);
+ float RetSpeed();
+
+ void UpdateShortcuts();
+ void SelectHuman();
+ CObject* SearchHuman();
+ CObject* SearchToto();
+ CObject* SearchNearest(Math::Vector pos, CObject* pExclu);
+ bool SelectObject(CObject* pObj, bool bDisplayError=true);
+ CObject* RetSelectObject();
+ CObject* DeselectAll();
+ bool DeleteObject();
+
+ void ResetObject();
+ void ResetCreate();
+ Error CheckEndMission(bool bFrame);
+ void CheckEndMessage(char *message);
+ int RetObligatoryToken();
+ char* RetObligatoryToken(int i);
+ int IsObligatoryToken(char *token);
+ bool IsProhibitedToken(char *token);
+ void UpdateMap();
+ bool RetShowMap();
+
+ MainMovieType RetMainMovie();
+
+ void FlushDisplayInfo();
+ void StartDisplayInfo(int index, bool bMovie);
+ void StartDisplayInfo(char *filename, int index);
+ void StopDisplayInfo();
+ char* RetDisplayInfoName(int index);
+ int RetDisplayInfoPosition(int index);
+ void SetDisplayInfoPosition(int index, int pos);
+
+ void StartSuspend();
+ void StopSuspend();
+
+ float RetGameTime();
+
+ void SetFontSize(float size);
+ float RetFontSize();
+ void SetWindowPos(Math::Point pos);
+ Math::Point RetWindowPos();
+ void SetWindowDim(Math::Point dim);
+ Math::Point RetWindowDim();
+
+ void SetIOPublic(bool bMode);
+ bool RetIOPublic();
+ void SetIOPos(Math::Point pos);
+ Math::Point RetIOPos();
+ void SetIODim(Math::Point dim);
+ Math::Point RetIODim();
+
+ char* RetTitle();
+ char* RetResume();
+ char* RetScriptName();
+ char* RetScriptFile();
+ bool RetTrainerPilot();
+ bool RetFixScene();
+ bool RetGlint();
+ bool RetSoluce4();
+ bool RetMovies();
+ bool RetNiceReset();
+ bool RetHimselfDamage();
+ bool RetShowSoluce();
+ bool RetSceneSoluce();
+ bool RetShowAll();
+ bool RetCheatRadar();
+ char* RetSavegameDir();
+ char* RetPublicDir();
+ char* RetFilesDir();
+
+ void SetGamerName(char *name);
+ char* RetGamerName();
+ int RetGamerFace();
+ int RetGamerGlasses();
+ bool RetGamerOnlyHead();
+ float RetPersoAngle();
+
+ void StartMusic();
+ void ClearInterface();
+ void ChangeColor();
+
+ float SearchNearestObject(Math::Vector center, CObject *exclu);
+ bool FreeSpace(Math::Vector &center, float minRadius, float maxRadius, float space, CObject *exclu);
+ float RetFlatZoneRadius(Math::Vector center, float maxRadius, CObject *exclu);
+ void HideDropZone(CObject* metal);
+ void ShowDropZone(CObject* metal, CObject* truck);
+ void FlushShowLimit(int i);
+ void SetShowLimit(int i, ParticuleType parti, CObject *pObj, Math::Vector pos, float radius, float duration=SHOWLIMITTIME);
+ void AdjustShowLimit(int i, Math::Vector pos);
+ void StartShowLimit();
+ void FrameShowLimit(float rTime);
+
+ void CompileScript(bool bSoluce);
+ void LoadOneScript(CObject *pObj, int &nbError);
+ void LoadFileScript(CObject *pObj, char* filename, int objRank, int &nbError);
+ void SaveAllScript();
+ void SaveOneScript(CObject *pObj);
+ void SaveFileScript(CObject *pObj, char* filename, int objRank);
+ bool SaveFileStack(CObject *pObj, FILE *file, int objRank);
+ bool ReadFileStack(CObject *pObj, FILE *file, int objRank);
+
+ bool FlushNewScriptName();
+ bool AddNewScriptName(ObjectType type, char *name);
+ char* RetNewScriptName(ObjectType type, int rank);
+
+ void WriteFreeParam();
+ void ReadFreeParam();
+
+ bool IsBusy();
+ bool IOWriteScene(char *filename, char *filecbot, char *info);
+ CObject* IOReadScene(char *filename, char *filecbot);
+ void IOWriteObject(FILE *file, CObject* pObj, char *cmd);
+ CObject* IOReadObject(char *line, char* filename, int objRank);
+
+ int CreateSpot(Math::Vector pos, D3DCOLORVALUE color);
+
+protected:
+ bool EventFrame(const Event &event);
+ bool EventObject(const Event &event);
+ void InitEye();
+
+ void Convert();
+ void CreateScene(bool bSoluce, bool bFixScene, bool bResetObject);
+
+ void CreateModel();
+ Math::Vector LookatPoint( Math::Vector eye, float angleH, float angleV, float length );
+ CObject* CreateObject(Math::Vector pos, float angle, float zoom, float height, ObjectType type, float power=1.0f, bool bTrainer=false, bool bToy=false, int option=0);
+ int CreateLight(Math::Vector direction, D3DCOLORVALUE color);
+ void HiliteClear();
+ void HiliteObject(Math::Point pos);
+ void HiliteFrame(float rTime);
+ void CreateTooltip(Math::Point pos, char* text);
+ void ClearTooltip();
+ CObject* DetectObject(Math::Point pos);
+ void ChangeCamera();
+ void RemoteCamera(float pan, float zoom, float rTime);
+ void KeyCamera(EventMsg event, long param);
+ void AbortMovie();
+ bool IsSelectable(CObject* pObj);
+ void SelectOneObject(CObject* pObj, bool bDisplayError=true);
+ void HelpObject();
+ bool DeselectObject();
+ void DeleteAllObjects();
+ void UpdateInfoText();
+ CObject* SearchObject(ObjectType type);
+ CObject* RetSelect();
+ void StartDisplayVisit(EventMsg event);
+ void FrameVisit(float rTime);
+ void StopDisplayVisit();
+ void ExecuteCmd(char *cmd);
+ bool TestGadgetQuantity(int rank);
+
+protected:
+ CInstanceManager* m_iMan;
+ CMainMovie* m_movie;
+ CMainDialog* m_dialog;
+ CMainShort* m_short;
+ CMainMap* m_map;
+ CEvent* m_event;
+ CD3DEngine* m_engine;
+ CParticule* m_particule;
+ CWater* m_water;
+ CCloud* m_cloud;
+ CBlitz* m_blitz;
+ CPlanet* m_planet;
+ CLight* m_light;
+ CTerrain* m_terrain;
+ CModel* m_model;
+ CInterface* m_interface;
+ CCamera* m_camera;
+ CDisplayText* m_displayText;
+ CDisplayInfo* m_displayInfo;
+ CSound* m_sound;
+
+ float m_time;
+ float m_gameTime;
+ float m_checkEndTime;
+ float m_winDelay;
+ float m_lostDelay;
+ bool m_bFixScene; // scene fixed, no interraction
+ bool m_bBase; // OBJECT_BASE exists in mission
+ Math::Point m_lastMousePos;
+ CObject* m_selectObject;
+
+ Phase m_phase;
+ int m_cameraRank;
+ D3DCOLORVALUE m_color;
+ bool m_bFreePhoto;
+ bool m_bCmdEdit;
+ bool m_bShowPos;
+ bool m_bSelectInsect;
+ bool m_bShowSoluce;
+ bool m_bShowAll;
+ bool m_bCheatRadar;
+ bool m_bAudioRepeat;
+ bool m_bShortCut;
+ int m_audioTrack;
+ int m_delayWriteMessage;
+ int m_movieInfoIndex;
+
+ bool m_bImmediatSatCom; // SatCom immediately?
+ bool m_bBeginSatCom; // messages SatCom poster?
+ bool m_bMovieLock; // movie in progress?
+ bool m_bSatComLock; // call of SatCom is possible?
+ bool m_bEditLock; // edition in progress?
+ bool m_bEditFull; // edition in full screen?
+ bool m_bPause; // simulation paused
+ bool m_bHilite;
+ bool m_bTrainerPilot; // remote trainer?
+ bool m_bSuspend;
+ bool m_bFriendAim;
+ bool m_bResetCreate;
+ bool m_bMapShow;
+ bool m_bMapImage;
+ char m_mapFilename[100];
+
+ Math::Point m_tooltipPos;
+ char m_tooltipName[100];
+ float m_tooltipTime;
+
+ char m_infoFilename[SATCOM_MAX][100]; // names of text files
+ CObject* m_infoObject;
+ int m_infoIndex;
+ int m_infoPos[SATCOM_MAX];
+ int m_infoUsed;
+
+ char m_title[100];
+ char m_resume[500];
+ char m_scriptName[100];
+ char m_scriptFile[100];
+ int m_endingWinRank;
+ int m_endingLostRank;
+ bool m_bWinTerminate;
+
+ float m_fontSize;
+ Math::Point m_windowPos;
+ Math::Point m_windowDim;
+
+ bool m_IOPublic;
+ Math::Point m_IOPos;
+ Math::Point m_IODim;
+
+ NewScriptName m_newScriptName[MAXNEWSCRIPTNAME];
+
+ float m_cameraPan;
+ float m_cameraZoom;
+
+ EventMsg m_visitLast;
+ CObject* m_visitObject;
+ CObject* m_visitArrow;
+ float m_visitTime;
+ float m_visitParticule;
+ Math::Vector m_visitPos;
+ Math::Vector m_visitPosArrow;
+
+ int m_endTakeTotal;
+ EndTake m_endTake[10];
+ long m_endTakeResearch;
+ float m_endTakeWinDelay;
+ float m_endTakeLostDelay;
+
+ int m_obligatoryTotal;
+ char m_obligatoryToken[100][20];
+ int m_prohibitedTotal;
+ char m_prohibitedToken[100][20];
+
+ char m_gamerName[100];
+
+ long m_freeBuild; // constructible buildings
+ long m_freeResearch; // researches possible
+
+ ShowLimit m_showLimit[MAXSHOWLIMIT];
+
+ D3DCOLORVALUE m_colorRefBot;
+ D3DCOLORVALUE m_colorNewBot;
+ D3DCOLORVALUE m_colorRefAlien;
+ D3DCOLORVALUE m_colorNewAlien;
+ D3DCOLORVALUE m_colorRefGreen;
+ D3DCOLORVALUE m_colorNewGreen;
+ D3DCOLORVALUE m_colorRefWater;
+ D3DCOLORVALUE m_colorNewWater;
+ float m_colorShiftWater;
+};
+
diff --git a/src/object/task/task.cpp b/src/object/task/task.cpp
index 593d4e6..f910ea2 100644
--- a/src/object/task/task.cpp
+++ b/src/object/task/task.cpp
@@ -1,89 +1,89 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// task.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/task.h"
-
-#include "common/iman.h"
-#include "object/object.h"
-
-
-
-// Object's constructor.
-
-CTask::CTask(CInstanceManager* iMan, CObject* object)
-{
- m_iMan = iMan;
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
-
- m_object = object;
- m_physics = m_object->RetPhysics();
- m_brain = m_object->RetBrain();
- m_motion = m_object->RetMotion();
-}
-
-// Object's destructor.
-
-CTask::~CTask()
-{
-}
-
-
-// Management of an event.
-
-bool CTask::EventProcess(const Event &event)
-{
- return true;
-}
-
-
-// Indicates whether the action is finished.
-
-Error CTask::IsEnded()
-{
- return ERR_STOP;
-}
-
-
-// Indicates whether the action is pending.
-
-bool CTask::IsBusy()
-{
- return true;
-}
-
-
-// Suddenly ends the current action.
-
-bool CTask::Abort()
-{
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// task.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/task.h"
+
+#include "common/iman.h"
+#include "object/object.h"
+
+
+
+// Object's constructor.
+
+CTask::CTask(CInstanceManager* iMan, CObject* object)
+{
+ m_iMan = iMan;
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+
+ m_object = object;
+ m_physics = m_object->RetPhysics();
+ m_brain = m_object->RetBrain();
+ m_motion = m_object->RetMotion();
+}
+
+// Object's destructor.
+
+CTask::~CTask()
+{
+}
+
+
+// Management of an event.
+
+bool CTask::EventProcess(const Event &event)
+{
+ return true;
+}
+
+
+// Indicates whether the action is finished.
+
+Error CTask::IsEnded()
+{
+ return ERR_STOP;
+}
+
+
+// Indicates whether the action is pending.
+
+bool CTask::IsBusy()
+{
+ return true;
+}
+
+
+// Suddenly ends the current action.
+
+bool CTask::Abort()
+{
+ return true;
+}
+
+
diff --git a/src/object/task/task.h b/src/object/task/task.h
index 8a1255e..a3ec62c 100644
--- a/src/object/task/task.h
+++ b/src/object/task/task.h
@@ -1,86 +1,86 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// task.h
-
-#pragma once
-
-
-#include "common/misc.h"
-#include "math/const.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CLight;
-class CParticule;
-class CTerrain;
-class CWater;
-class CCamera;
-class CBrain;
-class CPhysics;
-class CMotion;
-class CObject;
-class CRobotMain;
-class CDisplayText;
-class CSound;
-
-
-const float TAKE_DIST = 6.0f; // distance to an object to pick it
-const float TAKE_DIST_OTHER = 1.5f; // additional distance if on friend
-
-//?const float ARM_NEUTRAL_ANGLE1 = 155.0f*Math::PI/180.0f;
-//?const float ARM_NEUTRAL_ANGLE2 = -125.0f*Math::PI/180.0f;
-//?const float ARM_NEUTRAL_ANGLE3 = -45.0f*Math::PI/180.0f;
-const float ARM_NEUTRAL_ANGLE1 = 110.0f*Math::PI/180.0f;
-const float ARM_NEUTRAL_ANGLE2 = -130.0f*Math::PI/180.0f;
-const float ARM_NEUTRAL_ANGLE3 = -50.0f*Math::PI/180.0f;
-
-const float ARM_STOCK_ANGLE1 = 110.0f*Math::PI/180.0f;
-const float ARM_STOCK_ANGLE2 = -100.0f*Math::PI/180.0f;
-const float ARM_STOCK_ANGLE3 = -70.0f*Math::PI/180.0f;
-
-
-class CTask
-{
-public:
- CTask(CInstanceManager* iMan, CObject* object);
- virtual ~CTask();
-
- virtual bool EventProcess(const Event &event);
- virtual Error IsEnded();
- virtual bool IsBusy();
- virtual bool Abort();
-
-protected:
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CLight* m_light;
- CParticule* m_particule;
- CTerrain* m_terrain;
- CWater* m_water;
- CCamera* m_camera;
- CMotion* m_motion;
- CBrain* m_brain;
- CPhysics* m_physics;
- CObject* m_object;
- CRobotMain* m_main;
- CDisplayText* m_displayText;
- CSound* m_sound;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// task.h
+
+#pragma once
+
+
+#include "common/misc.h"
+#include "math/const.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CLight;
+class CParticule;
+class CTerrain;
+class CWater;
+class CCamera;
+class CBrain;
+class CPhysics;
+class CMotion;
+class CObject;
+class CRobotMain;
+class CDisplayText;
+class CSound;
+
+
+const float TAKE_DIST = 6.0f; // distance to an object to pick it
+const float TAKE_DIST_OTHER = 1.5f; // additional distance if on friend
+
+//?const float ARM_NEUTRAL_ANGLE1 = 155.0f*Math::PI/180.0f;
+//?const float ARM_NEUTRAL_ANGLE2 = -125.0f*Math::PI/180.0f;
+//?const float ARM_NEUTRAL_ANGLE3 = -45.0f*Math::PI/180.0f;
+const float ARM_NEUTRAL_ANGLE1 = 110.0f*Math::PI/180.0f;
+const float ARM_NEUTRAL_ANGLE2 = -130.0f*Math::PI/180.0f;
+const float ARM_NEUTRAL_ANGLE3 = -50.0f*Math::PI/180.0f;
+
+const float ARM_STOCK_ANGLE1 = 110.0f*Math::PI/180.0f;
+const float ARM_STOCK_ANGLE2 = -100.0f*Math::PI/180.0f;
+const float ARM_STOCK_ANGLE3 = -70.0f*Math::PI/180.0f;
+
+
+class CTask
+{
+public:
+ CTask(CInstanceManager* iMan, CObject* object);
+ virtual ~CTask();
+
+ virtual bool EventProcess(const Event &event);
+ virtual Error IsEnded();
+ virtual bool IsBusy();
+ virtual bool Abort();
+
+protected:
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CLight* m_light;
+ CParticule* m_particule;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CCamera* m_camera;
+ CMotion* m_motion;
+ CBrain* m_brain;
+ CPhysics* m_physics;
+ CObject* m_object;
+ CRobotMain* m_main;
+ CDisplayText* m_displayText;
+ CSound* m_sound;
+};
+
diff --git a/src/object/task/taskadvance.cpp b/src/object/task/taskadvance.cpp
index c5a87d3..e50cb08 100644
--- a/src/object/task/taskadvance.cpp
+++ b/src/object/task/taskadvance.cpp
@@ -1,146 +1,146 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskadvance.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskadvance.h"
-
-#include "math/geometry.h"
-#include "physics/physics.h"
-
-
-
-
-// Object's constructor.
-
-CTaskAdvance::CTaskAdvance(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskAdvance::~CTaskAdvance()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskAdvance::EventProcess(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_fixTime += event.rTime;
-
- // Momentarily stationary object (ant on the back)?
- if ( m_object->RetFixed() )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_bError = true;
- return true;
- }
-
- m_timeLimit -= event.rTime;
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskAdvance::Start(float length)
-{
- m_direction = (length>=0.0f)?1.0f:-1.0f;
- m_totalLength = fabs(length);
- m_advanceLength = m_physics->RetLinLength(length);
- m_startPos = m_object->RetPosition(0);
- m_lastDist = 0.0f;
- m_fixTime = 0.0f;
-
- m_timeLimit = m_physics->RetLinTimeLength(m_totalLength, m_direction)*3.0f;
- if ( m_timeLimit < 2.0f ) m_timeLimit = 2.0f;
-
- m_physics->SetMotorSpeedX(m_direction*1.0f); // forward/backward
- m_physics->SetMotorSpeedY(0.0f);
- m_physics->SetMotorSpeedZ(0.0f);
-
- m_bError = false;
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskAdvance::IsEnded()
-{
- Math::Vector pos;
- float length;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
-
- if ( m_bError )
- {
- return ERR_STOP;
- }
-
- if ( m_timeLimit < 0.0f )
- {
- m_physics->SetMotorSpeedX(0.0f);
- return ERR_MOVE_IMPOSSIBLE;
- }
-
- pos = m_object->RetPosition(0);
- length = Math::DistanceProjected(pos, m_startPos);
-
- if ( length > m_lastDist ) // forward?
- {
- m_fixTime = 0.0f;
- }
- else // still stands?
- {
- if ( m_fixTime > 1.0f ) // for more than a second?
- {
- m_physics->SetMotorSpeedX(0.0f);
- return ERR_MOVE_IMPOSSIBLE;
- }
- }
- m_lastDist = length;
-
- if ( length >= m_totalLength )
- {
- m_physics->SetMotorSpeedX(0.0f);
- m_physics->SetLinMotionX(MO_CURSPEED, 0.0f);
-
- if ( length != 0.0f )
- {
- pos = m_startPos+((pos-m_startPos)*m_totalLength/length);
- m_object->SetPosition(0, pos);
- }
- return ERR_STOP;
- }
-
- if ( length >= m_advanceLength )
- {
- m_physics->SetMotorSpeedX(m_direction*0.1f);
- }
- return ERR_CONTINUE;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskadvance.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskadvance.h"
+
+#include "math/geometry.h"
+#include "physics/physics.h"
+
+
+
+
+// Object's constructor.
+
+CTaskAdvance::CTaskAdvance(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+}
+
+// Object's destructor.
+
+CTaskAdvance::~CTaskAdvance()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskAdvance::EventProcess(const Event &event)
+{
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_fixTime += event.rTime;
+
+ // Momentarily stationary object (ant on the back)?
+ if ( m_object->RetFixed() )
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ m_bError = true;
+ return true;
+ }
+
+ m_timeLimit -= event.rTime;
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskAdvance::Start(float length)
+{
+ m_direction = (length>=0.0f)?1.0f:-1.0f;
+ m_totalLength = fabs(length);
+ m_advanceLength = m_physics->RetLinLength(length);
+ m_startPos = m_object->RetPosition(0);
+ m_lastDist = 0.0f;
+ m_fixTime = 0.0f;
+
+ m_timeLimit = m_physics->RetLinTimeLength(m_totalLength, m_direction)*3.0f;
+ if ( m_timeLimit < 2.0f ) m_timeLimit = 2.0f;
+
+ m_physics->SetMotorSpeedX(m_direction*1.0f); // forward/backward
+ m_physics->SetMotorSpeedY(0.0f);
+ m_physics->SetMotorSpeedZ(0.0f);
+
+ m_bError = false;
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskAdvance::IsEnded()
+{
+ Math::Vector pos;
+ float length;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+
+ if ( m_bError )
+ {
+ return ERR_STOP;
+ }
+
+ if ( m_timeLimit < 0.0f )
+ {
+ m_physics->SetMotorSpeedX(0.0f);
+ return ERR_MOVE_IMPOSSIBLE;
+ }
+
+ pos = m_object->RetPosition(0);
+ length = Math::DistanceProjected(pos, m_startPos);
+
+ if ( length > m_lastDist ) // forward?
+ {
+ m_fixTime = 0.0f;
+ }
+ else // still stands?
+ {
+ if ( m_fixTime > 1.0f ) // for more than a second?
+ {
+ m_physics->SetMotorSpeedX(0.0f);
+ return ERR_MOVE_IMPOSSIBLE;
+ }
+ }
+ m_lastDist = length;
+
+ if ( length >= m_totalLength )
+ {
+ m_physics->SetMotorSpeedX(0.0f);
+ m_physics->SetLinMotionX(MO_CURSPEED, 0.0f);
+
+ if ( length != 0.0f )
+ {
+ pos = m_startPos+((pos-m_startPos)*m_totalLength/length);
+ m_object->SetPosition(0, pos);
+ }
+ return ERR_STOP;
+ }
+
+ if ( length >= m_advanceLength )
+ {
+ m_physics->SetMotorSpeedX(m_direction*0.1f);
+ }
+ return ERR_CONTINUE;
+}
+
+
diff --git a/src/object/task/taskadvance.h b/src/object/task/taskadvance.h
index b0f09b1..dbb80d9 100644
--- a/src/object/task/taskadvance.h
+++ b/src/object/task/taskadvance.h
@@ -1,50 +1,50 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskadvance.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-class CTaskAdvance : public CTask
-{
-public:
- CTaskAdvance(CInstanceManager* iMan, CObject* object);
- ~CTaskAdvance();
-
- bool EventProcess(const Event &event);
-
- Error Start(float length);
- Error IsEnded();
-
-protected:
-
-protected:
- float m_totalLength;
- float m_advanceLength;
- float m_direction;
- float m_timeLimit;
- Math::Vector m_startPos;
- float m_lastDist;
- float m_fixTime;
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskadvance.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "math/vector.h"
+
+
+
+class CTaskAdvance : public CTask
+{
+public:
+ CTaskAdvance(CInstanceManager* iMan, CObject* object);
+ ~CTaskAdvance();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(float length);
+ Error IsEnded();
+
+protected:
+
+protected:
+ float m_totalLength;
+ float m_advanceLength;
+ float m_direction;
+ float m_timeLimit;
+ Math::Vector m_startPos;
+ float m_lastDist;
+ float m_fixTime;
+ bool m_bError;
+};
+
diff --git a/src/object/task/taskbuild.cpp b/src/object/task/taskbuild.cpp
index f9d6c57..25936f9 100644
--- a/src/object/task/taskbuild.cpp
+++ b/src/object/task/taskbuild.cpp
@@ -1,806 +1,806 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskbuild.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskbuild.h"
-
-#include "common/iman.h"
-#include "old/light.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "math/geometry.h"
-#include "object/auto/auto.h"
-#include "object/motion/motionhuman.h"
-#include "object/robotmain.h"
-#include "physics/physics.h"
-#include "ui/displaytext.h"
-
-
-
-
-// Object's constructor.
-
-CTaskBuild::CTaskBuild(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- int i;
-
- m_type = OBJECT_DERRICK;
- m_time = 0.0f;
- m_soundChannel = -1;
-
- for ( i=0 ; i<TBMAXLIGHT ; i++ )
- {
- m_lightRank[i] = -1;
- }
-}
-
-// Object's destructor.
-
-CTaskBuild::~CTaskBuild()
-{
- int i;
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- for ( i=0 ; i<TBMAXLIGHT ; i++ )
- {
- if ( m_lightRank[i] == -1 ) continue;
- m_light->DeleteLight(m_lightRank[i]);
- }
-}
-
-
-// Creates a building.
-
-bool CTaskBuild::CreateBuilding(Math::Vector pos, float angle)
-{
- m_building = new CObject(m_iMan);
- if ( !m_building->CreateBuilding(pos, angle, 0.0f, m_type, 0.0f) )
- {
- delete m_building;
- m_building = 0;
- return false;
- }
- m_building->UpdateMapping();
- m_building->SetLock(true); // not yet usable
-
- if ( m_type == OBJECT_DERRICK ) m_buildingHeight = 35.0f;
- if ( m_type == OBJECT_FACTORY ) m_buildingHeight = 28.0f;
- if ( m_type == OBJECT_REPAIR ) m_buildingHeight = 30.0f;
- if ( m_type == OBJECT_STATION ) m_buildingHeight = 13.0f;
- if ( m_type == OBJECT_CONVERT ) m_buildingHeight = 20.0f;
- if ( m_type == OBJECT_TOWER ) m_buildingHeight = 30.0f;
- if ( m_type == OBJECT_RESEARCH ) m_buildingHeight = 22.0f;
- if ( m_type == OBJECT_RADAR ) m_buildingHeight = 19.0f;
- if ( m_type == OBJECT_ENERGY ) m_buildingHeight = 20.0f;
- if ( m_type == OBJECT_LABO ) m_buildingHeight = 16.0f;
- if ( m_type == OBJECT_NUCLEAR ) m_buildingHeight = 40.0f;
- if ( m_type == OBJECT_PARA ) m_buildingHeight = 68.0f;
- if ( m_type == OBJECT_INFO ) m_buildingHeight = 19.0f;
- m_buildingHeight *= 0.25f;
-
- m_buildingPos = m_building->RetPosition(0);
- m_buildingPos.y -= m_buildingHeight;
- m_building->SetPosition(0, m_buildingPos);
- return true;
-}
-
-// Creates lights for the effects.
-
-void CTaskBuild::CreateLight()
-{
- D3DLIGHT7 light;
- D3DCOLORVALUE color;
- Math::Vector center, pos, dir;
- Math::Point c, p;
- float angle;
- int i;
-
- if ( !m_engine->RetLightMode() ) return;
-
- center = m_metal->RetPosition(0);
-
- angle = 0;
- for ( i=0 ; i<TBMAXLIGHT ; i++ )
- {
- m_lightRank[i] = m_light->CreateLight();
- if ( m_lightRank[i] == -1 ) continue;
-
- c.x = center.x;
- c.y = center.z;
- p.x = center.x+40.0f;
- p.y = center.z;
- p = Math::RotatePoint(c, angle, p);
- pos.x = p.x;
- pos.z = p.y;
- pos.y = center.y+40.0f;
- dir = center-pos;
-
- ZeroMemory( &light, sizeof(light) );
- light.dltType = D3DLIGHT_SPOT;
- light.dcvDiffuse.r = 0.0f;
- light.dcvDiffuse.g = 0.0f;
- light.dcvDiffuse.b = 0.0f; // white (invisible)
- light.dvPosition.x = pos.x;
- light.dvPosition.y = pos.y;
- light.dvPosition.z = pos.z;
- light.dvDirection.x = dir.x;
- light.dvDirection.y = dir.y;
- light.dvDirection.z = dir.z;
- light.dvRange = D3DLIGHT_RANGE_MAX;
- light.dvFalloff = 1.0f;
- light.dvAttenuation0 = 1.0f;
- light.dvAttenuation1 = 0.0f;
- light.dvAttenuation2 = 0.0f;
- light.dvTheta = 0.0f;
- light.dvPhi = Math::PI/4.0f;
- m_light->SetLight(m_lightRank[i], light);
-
- color.r = -1.0f;
- color.g = -1.0f;
- color.b = -0.5f; // violet
- color.a = 0.0f;
- m_light->SetLightColor(m_lightRank[i], color);
- m_light->SetLightColorSpeed(m_lightRank[i], 1.0f/((1.0f/m_speed)*0.25f));
-
- angle += (Math::PI*2.0f)/TBMAXLIGHT;
- }
-
- m_bBlack = false;
-}
-
-// Switches the lights from black to white.
-
-void CTaskBuild::BlackLight()
-{
- D3DCOLORVALUE color;
- int i;
-
- for ( i=0 ; i<TBMAXLIGHT ; i++ )
- {
- if ( m_lightRank[i] == -1 ) continue;
-
- color.r = 0.0f;
- color.g = 0.0f;
- color.b = 0.0f; // white (invisible)
- color.a = 0.0f;
- m_light->SetLightColor(m_lightRank[i], color);
- m_light->SetLightColorSpeed(m_lightRank[i], 1.0f/((1.0f/m_speed)*0.75f));
- }
-
- m_bBlack = true;
-}
-
-// Management of an event.
-
-bool CTaskBuild::EventProcess(const Event &event)
-{
- Math::Matrix* mat;
- Math::Vector pos, dir, speed;
- Math::Point dim;
- float a, g, cirSpeed, dist, linSpeed;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_time += event.rTime;
-
- m_progress += event.rTime*m_speed; // other advance
-
- if ( m_phase == TBP_TURN ) // preliminary rotation?
- {
- a = m_object->RetAngleY(0);
- g = m_angleY;
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left/right
- return true;
- }
-
- if ( m_phase == TBP_MOVE ) // preliminary forward/backward?
- {
- dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0));
- linSpeed = 0.0f;
- if ( dist > 30.0f ) linSpeed = 1.0f;
- if ( dist < 30.0f ) linSpeed = -1.0f;
- m_physics->SetMotorSpeedX(linSpeed); // forward/backward
- return true;
- }
-
- if ( m_phase == TBP_RECEDE ) // terminal back?
- {
- m_physics->SetMotorSpeedX(-1.0f); // back
- return true;
- }
-
- if ( m_phase == TBP_TAKE ) // takes gun?
- {
- return true;
- }
-
- if ( m_phase == TBP_PREP ) // prepares?
- {
- return true;
- }
-
- if ( m_phase == TBP_TERM ) // ends?
- {
- return true;
- }
-
- if ( !m_bBuild ) // building to build?
- {
- m_bBuild = true;
-
- pos = m_metal->RetPosition(0);
- a = m_object->RetAngleY(0);
- if ( !CreateBuilding(pos, a+Math::PI) )
- {
- m_metal->SetLock(false); // usable again
- m_motion->SetAction(-1);
- m_object->SetObjectParent(14, 0);
- m_object->SetPosition(14, Math::Vector(-1.5f, 0.3f, -1.35f));
- m_object->SetAngleZ(14, Math::PI);
- m_camera->FlushEffect();
- Abort();
- m_bError = true;
- m_displayText->DisplayError(ERR_TOOMANY, m_object->RetPosition(0));
- return false;
- }
- CreateLight();
- }
-
- pos = m_buildingPos;
- pos.y += m_buildingHeight*m_progress;
- m_building->SetPosition(0, pos); // the building rises
-
- m_building->SetZoom(0, m_progress*0.75f+0.25f);
- m_metal->SetZoom(0, 1.0f-m_progress);
-
- a = (2.0f-2.0f*m_progress);
- if ( a > 1.0f ) a = 1.0f;
- dir.x = (Math::Rand()-0.5f)*a*0.1f;
- dir.z = (Math::Rand()-0.5f)*a*0.1f;
- dir.y = (Math::Rand()-0.5f)*a*0.1f;
- m_building->SetCirVibration(dir);
-
- if ( !m_bBlack && m_progress >= 0.25f )
- {
- BlackLight();
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_metal->RetPosition(0);
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = Math::Rand()*10.0f;
- dim.x = Math::Rand()*6.0f+4.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFIRE);
-
- pos = Math::Vector(0.0f, 0.5f, 0.0f);
- mat = m_object->RetWorldMatrix(14);
- pos = Transform(*mat, pos);
- speed = m_metal->RetPosition(0);
- speed.x += (Math::Rand()-0.5f)*5.0f;
- speed.z += (Math::Rand()-0.5f)*5.0f;
- speed -= pos;
- dim.x = 2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ);
-
- if ( Math::Rand() < 0.3f )
- {
- m_sound->Play(SOUND_BUILD, m_object->RetPosition(0), 0.5f, 1.0f*Math::Rand()*1.5f);
- }
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskBuild::Start(ObjectType type)
-{
- Math::Vector pos, speed, pv, pm;
- Error err;
- float iAngle, oAngle;
-
- m_type = type;
- m_lastParticule = 0.0f;
- m_progress = 0.0f;
-
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
- oAngle = iAngle;
-
- m_bError = true; // operation impossible
-
- pos = m_object->RetPosition(0);
- if ( pos.y < m_water->RetLevel() ) return ERR_BUILD_WATER;
-
- if ( !m_physics->RetLand() ) return ERR_BUILD_FLY;
-
- speed = m_physics->RetMotorSpeed();
- if ( speed.x != 0.0f ||
- speed.z != 0.0f ) return ERR_BUILD_MOTOR;
-
- if ( m_object->RetFret() != 0 ) return ERR_MANIP_BUSY;
-
- m_metal = SearchMetalObject(oAngle, 2.0f, 100.0f, Math::PI*0.25f, err);
- if ( err == ERR_BUILD_METALNEAR && m_metal != 0 )
- {
- err = FlatFloor();
- if ( err != ERR_OK ) return err;
- return ERR_BUILD_METALNEAR;
- }
- if ( err != ERR_OK ) return err;
-
- err = FlatFloor();
- if ( err != ERR_OK ) return err;
-
- m_metal->SetLock(true); // not usable
- m_camera->StartCentering(m_object, Math::PI*0.15f, 99.9f, 0.0f, 1.0f);
-
- m_phase = TBP_TURN; // rotation necessary preliminary
- m_angleY = oAngle; // angle was reached
-
- pv = m_object->RetPosition(0);
- pv.y += 8.3f;
- pm = m_metal->RetPosition(0);
- m_angleZ = Math::RotateAngle(Math::DistanceProjected(pv, pm), fabs(pv.y-pm.y));
-
- m_physics->SetFreeze(true); // it does not move
-
- m_bBuild = false; // not yet built
- m_bError = false; // ok
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskBuild::IsEnded()
-{
- CAuto* automat;
- float angle, dist, time;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_phase == TBP_TURN ) // preliminary rotation?
- {
- angle = m_object->RetAngleY(0);
- angle = Math::NormAngle(angle); // 0..2*Math::PI
-
- if ( Math::TestAngle(angle, m_angleY-Math::PI*0.01f, m_angleY+Math::PI*0.01f) )
- {
- m_physics->SetMotorSpeedZ(0.0f);
-
- dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0));
- if ( dist > 30.0f )
- {
- time = m_physics->RetLinTimeLength(dist-30.0f, 1.0f);
- m_speed = 1.0f/time;
- }
- else
- {
- time = m_physics->RetLinTimeLength(30.0f-dist, -1.0f);
- m_speed = 1.0f/time;
- }
- m_phase = TBP_MOVE;
- m_progress = 0.0f;
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TBP_MOVE ) // preliminary forward/backward?
- {
- dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0));
-
- if ( dist >= 25.0f && dist <= 35.0f )
- {
- m_physics->SetMotorSpeedX(0.0f);
- m_motion->SetAction(MHS_GUN); // takes gun
-
- m_phase = TBP_TAKE;
- m_speed = 1.0f/1.0f;
- m_progress = 0.0f;
- }
- else
- {
- if ( m_progress > 1.0f ) // timeout?
- {
- m_metal->SetLock(false); // usable again
- if ( dist < 30.0f ) return ERR_BUILD_METALNEAR;
- else return ERR_BUILD_METALAWAY;
- }
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TBP_TAKE ) // takes gun
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_motion->SetAction(MHS_FIRE); // shooting position
- m_object->SetObjectParent(14, 4);
- m_object->SetPosition(14, Math::Vector(0.6f, 0.1f, 0.3f));
- m_object->SetAngleZ(14, 0.0f);
-
- m_phase = TBP_PREP;
- m_speed = 1.0f/1.0f;
- m_progress = 0.0f;
- }
-
- if ( m_phase == TBP_PREP ) // prepares?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_soundChannel = m_sound->Play(SOUND_TREMBLE, m_object->RetPosition(0), 0.0f, 1.0f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.7f, 1.0f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.7f, 1.5f, 7.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.5f, 2.0f, SOPER_STOP);
-
- m_camera->StartEffect(CE_VIBRATION, m_metal->RetPosition(0), 1.0f);
-
- m_phase = TBP_BUILD;
- m_speed = 1.0f/10.f; // duration of 10s
- m_progress = 0.0f;
- }
-
- if ( m_phase == TBP_BUILD ) // construction?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- DeleteMark(m_metal->RetPosition(0), 20.0f);
-
- m_metal->DeleteObject(); // removes the metal
- delete m_metal;
- m_metal = 0;
-
- m_building->SetZoom(0, 1.0f);
- m_building->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- m_building->SetLock(false); // building usable
- m_main->CreateShortcuts();
- m_displayText->DisplayError(INFO_BUILD, m_buildingPos, 10.0f, 50.0f);
-
- automat = m_building->RetAuto();
- if ( automat != 0 )
- {
- automat->Init();
- }
-
- m_motion->SetAction(MHS_GUN); // hands gun
- m_phase = TBP_TERM;
- m_speed = 1.0f/1.0f;
- m_progress = 0.0f;
- }
-
- if ( m_phase == TBP_TERM ) // rotation terminale ?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_motion->SetAction(-1);
- m_object->SetObjectParent(14, 0);
- m_object->SetPosition(14, Math::Vector(-1.5f, 0.3f, -1.35f));
- m_object->SetAngleZ(14, Math::PI);
-
- if ( m_type == OBJECT_FACTORY ||
- m_type == OBJECT_RESEARCH ||
- m_type == OBJECT_NUCLEAR )
- {
-
- m_phase = TBP_RECEDE;
- m_speed = 1.0f/1.5f;
- m_progress = 0.0f;
- }
- }
-
- if ( m_phase == TBP_RECEDE ) // back?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_physics->SetMotorSpeedX(0.0f);
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskBuild::Abort()
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- m_camera->StopCentering(m_object, 2.0f);
- m_physics->SetFreeze(false); // is moving again
- return true;
-}
-
-
-// Checks whether the terrain is fairly flat
-// and if there is not too close to another object.
-
-Error CTaskBuild::FlatFloor()
-{
- CObject *pObj;
- ObjectType type;
- Math::Vector center, pos, oPos, bPos;
- Math::Point c, p;
- float radius, max, oRadius, bRadius, angle, dist;
- int i, j;
- bool bLittleFlat, bBase;
-
- radius = 0.0f;
- if ( m_type == OBJECT_DERRICK ) radius = 5.0f;
- if ( m_type == OBJECT_FACTORY ) radius = 15.0f;
- if ( m_type == OBJECT_REPAIR ) radius = 12.0f;
- if ( m_type == OBJECT_STATION ) radius = 12.0f;
- if ( m_type == OBJECT_CONVERT ) radius = 12.0f;
- if ( m_type == OBJECT_TOWER ) radius = 7.0f;
- if ( m_type == OBJECT_RESEARCH ) radius = 10.0f;
- if ( m_type == OBJECT_RADAR ) radius = 5.0f;
- if ( m_type == OBJECT_ENERGY ) radius = 8.0f;
- if ( m_type == OBJECT_LABO ) radius = 12.0f;
- if ( m_type == OBJECT_NUCLEAR ) radius = 20.0f;
- if ( m_type == OBJECT_PARA ) radius = 20.0f;
- if ( m_type == OBJECT_INFO ) radius = 5.0f;
- if ( radius == 0.0f ) return ERR_GENERIC;
-
- center = m_metal->RetPosition(0);
- angle = m_terrain->RetFineSlope(center);
- bLittleFlat = ( angle < FLATLIMIT );
-
- max = m_terrain->RetFlatZoneRadius(center, radius);
- if ( max < radius ) // area too small?
- {
- if ( bLittleFlat )
- {
- m_main->SetShowLimit(1, PARTILIMIT3, m_metal, center, max, 10.0f);
- }
- return bLittleFlat?ERR_BUILD_FLATLIT:ERR_BUILD_FLAT;
- }
-
- max = 100000.0f;
- bBase = false;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj == m_metal ) continue;
- if ( pObj == m_object ) continue;
-
- type = pObj->RetType();
- if ( type == OBJECT_BASE )
- {
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(center, oPos)-80.0f;
- if ( dist < max )
- {
- max = dist;
- bPos = oPos;
- bRadius = oRadius;
- bBase = true;
- }
- }
- else
- {
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- dist = Math::Distance(center, oPos)-oRadius;
- if ( dist < max )
- {
- max = dist;
- bPos = oPos;
- bRadius = oRadius;
- bBase = false;
- }
- }
- }
- }
- if ( max < radius )
- {
- m_main->SetShowLimit(1, PARTILIMIT2, m_metal, center, max, 10.0f);
- if ( bRadius < 2.0f ) bRadius = 2.0f;
- m_main->SetShowLimit(2, PARTILIMIT3, m_metal, bPos, bRadius, 10.0f);
- return bBase?ERR_BUILD_BASE:ERR_BUILD_BUSY;
- }
-
- max = 100000.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj == m_metal ) continue;
- if ( pObj == m_object ) continue;
-
- type = pObj->RetType();
- if ( type == OBJECT_DERRICK ||
- type == OBJECT_FACTORY ||
- type == OBJECT_STATION ||
- type == OBJECT_CONVERT ||
- type == OBJECT_REPAIR ||
- type == OBJECT_TOWER ||
- type == OBJECT_RESEARCH ||
- type == OBJECT_RADAR ||
- type == OBJECT_ENERGY ||
- type == OBJECT_LABO ||
- type == OBJECT_NUCLEAR ||
- type == OBJECT_START ||
- type == OBJECT_END ||
- type == OBJECT_INFO ||
- type == OBJECT_PARA ||
- type == OBJECT_SAFE ||
- type == OBJECT_HUSTON ) // building?
- {
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- dist = Math::Distance(center, oPos)-oRadius;
- if ( dist < max )
- {
- max = dist;
- bPos = oPos;
- bRadius = oRadius;
- }
- }
- }
- }
- if ( max-BUILDMARGIN < radius )
- {
- m_main->SetShowLimit(1, PARTILIMIT2, m_metal, center, max-BUILDMARGIN, 10.0f);
- m_main->SetShowLimit(2, PARTILIMIT3, m_metal, bPos, bRadius+BUILDMARGIN, 10.0f);
- return bBase?ERR_BUILD_BASE:ERR_BUILD_NARROW;
- }
-
- return ERR_OK;
-}
-
-// Seeks the nearest metal object.
-
-CObject* CTaskBuild::SearchMetalObject(float &angle, float dMin, float dMax,
- float aLimit, Error &err)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float min, iAngle, a, aa, aBest, distance, magic;
- int i;
- bool bMetal;
-
- iPos = m_object->RetPosition(0);
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- min = 1000000.0f;
- pBest = 0;
- bMetal = false;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // objet inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- type = pObj->RetType();
- if ( type != OBJECT_METAL ) continue;
-
- bMetal = true; // metal exists
-
- oPos = pObj->RetPosition(0);
- distance = Math::Distance(oPos, iPos);
- a = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW!
-
- if ( distance > dMax ) continue;
- if ( !Math::TestAngle(a, iAngle-aLimit, iAngle+aLimit) ) continue;
-
- if ( distance < dMin )
- {
- err = ERR_BUILD_METALNEAR; // too close
- return pObj;
- }
-
- aa = fabs(a-iAngle);
- if ( aa > Math::PI ) aa = Math::PI*2.0f-aa;
- magic = distance*aa;
-
- if ( magic < min )
- {
- min = magic;
- aBest = a;
- pBest = pObj;
- }
- }
-
- if ( pBest == 0 )
- {
- if ( bMetal ) err = ERR_BUILD_METALAWAY; // too far
- else err = ERR_BUILD_METALINEX; // non-existent
- }
- else
- {
- angle = aBest;
- err = ERR_OK;
- }
- return pBest;
-}
-
-// Destroys all the close marks.
-
-void CTaskBuild::DeleteMark(Math::Vector pos, float radius)
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- float distance;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_MARKSTONE &&
- type != OBJECT_MARKURANIUM &&
- type != OBJECT_MARKKEYa &&
- type != OBJECT_MARKKEYb &&
- type != OBJECT_MARKKEYc &&
- type != OBJECT_MARKKEYd &&
- type != OBJECT_MARKPOWER ) continue;
-
- oPos = pObj->RetPosition(0);
- distance = Math::Distance(oPos, pos);
- if ( distance <= radius )
- {
- pObj->DeleteObject(); // removes the mark
- delete pObj;
- i --;
- }
- }
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskbuild.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskbuild.h"
+
+#include "common/iman.h"
+#include "old/light.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "math/geometry.h"
+#include "object/auto/auto.h"
+#include "object/motion/motionhuman.h"
+#include "object/robotmain.h"
+#include "physics/physics.h"
+#include "ui/displaytext.h"
+
+
+
+
+// Object's constructor.
+
+CTaskBuild::CTaskBuild(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ int i;
+
+ m_type = OBJECT_DERRICK;
+ m_time = 0.0f;
+ m_soundChannel = -1;
+
+ for ( i=0 ; i<TBMAXLIGHT ; i++ )
+ {
+ m_lightRank[i] = -1;
+ }
+}
+
+// Object's destructor.
+
+CTaskBuild::~CTaskBuild()
+{
+ int i;
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ for ( i=0 ; i<TBMAXLIGHT ; i++ )
+ {
+ if ( m_lightRank[i] == -1 ) continue;
+ m_light->DeleteLight(m_lightRank[i]);
+ }
+}
+
+
+// Creates a building.
+
+bool CTaskBuild::CreateBuilding(Math::Vector pos, float angle)
+{
+ m_building = new CObject(m_iMan);
+ if ( !m_building->CreateBuilding(pos, angle, 0.0f, m_type, 0.0f) )
+ {
+ delete m_building;
+ m_building = 0;
+ return false;
+ }
+ m_building->UpdateMapping();
+ m_building->SetLock(true); // not yet usable
+
+ if ( m_type == OBJECT_DERRICK ) m_buildingHeight = 35.0f;
+ if ( m_type == OBJECT_FACTORY ) m_buildingHeight = 28.0f;
+ if ( m_type == OBJECT_REPAIR ) m_buildingHeight = 30.0f;
+ if ( m_type == OBJECT_STATION ) m_buildingHeight = 13.0f;
+ if ( m_type == OBJECT_CONVERT ) m_buildingHeight = 20.0f;
+ if ( m_type == OBJECT_TOWER ) m_buildingHeight = 30.0f;
+ if ( m_type == OBJECT_RESEARCH ) m_buildingHeight = 22.0f;
+ if ( m_type == OBJECT_RADAR ) m_buildingHeight = 19.0f;
+ if ( m_type == OBJECT_ENERGY ) m_buildingHeight = 20.0f;
+ if ( m_type == OBJECT_LABO ) m_buildingHeight = 16.0f;
+ if ( m_type == OBJECT_NUCLEAR ) m_buildingHeight = 40.0f;
+ if ( m_type == OBJECT_PARA ) m_buildingHeight = 68.0f;
+ if ( m_type == OBJECT_INFO ) m_buildingHeight = 19.0f;
+ m_buildingHeight *= 0.25f;
+
+ m_buildingPos = m_building->RetPosition(0);
+ m_buildingPos.y -= m_buildingHeight;
+ m_building->SetPosition(0, m_buildingPos);
+ return true;
+}
+
+// Creates lights for the effects.
+
+void CTaskBuild::CreateLight()
+{
+ D3DLIGHT7 light;
+ D3DCOLORVALUE color;
+ Math::Vector center, pos, dir;
+ Math::Point c, p;
+ float angle;
+ int i;
+
+ if ( !m_engine->RetLightMode() ) return;
+
+ center = m_metal->RetPosition(0);
+
+ angle = 0;
+ for ( i=0 ; i<TBMAXLIGHT ; i++ )
+ {
+ m_lightRank[i] = m_light->CreateLight();
+ if ( m_lightRank[i] == -1 ) continue;
+
+ c.x = center.x;
+ c.y = center.z;
+ p.x = center.x+40.0f;
+ p.y = center.z;
+ p = Math::RotatePoint(c, angle, p);
+ pos.x = p.x;
+ pos.z = p.y;
+ pos.y = center.y+40.0f;
+ dir = center-pos;
+
+ ZeroMemory( &light, sizeof(light) );
+ light.dltType = D3DLIGHT_SPOT;
+ light.dcvDiffuse.r = 0.0f;
+ light.dcvDiffuse.g = 0.0f;
+ light.dcvDiffuse.b = 0.0f; // white (invisible)
+ light.dvPosition.x = pos.x;
+ light.dvPosition.y = pos.y;
+ light.dvPosition.z = pos.z;
+ light.dvDirection.x = dir.x;
+ light.dvDirection.y = dir.y;
+ light.dvDirection.z = dir.z;
+ light.dvRange = D3DLIGHT_RANGE_MAX;
+ light.dvFalloff = 1.0f;
+ light.dvAttenuation0 = 1.0f;
+ light.dvAttenuation1 = 0.0f;
+ light.dvAttenuation2 = 0.0f;
+ light.dvTheta = 0.0f;
+ light.dvPhi = Math::PI/4.0f;
+ m_light->SetLight(m_lightRank[i], light);
+
+ color.r = -1.0f;
+ color.g = -1.0f;
+ color.b = -0.5f; // violet
+ color.a = 0.0f;
+ m_light->SetLightColor(m_lightRank[i], color);
+ m_light->SetLightColorSpeed(m_lightRank[i], 1.0f/((1.0f/m_speed)*0.25f));
+
+ angle += (Math::PI*2.0f)/TBMAXLIGHT;
+ }
+
+ m_bBlack = false;
+}
+
+// Switches the lights from black to white.
+
+void CTaskBuild::BlackLight()
+{
+ D3DCOLORVALUE color;
+ int i;
+
+ for ( i=0 ; i<TBMAXLIGHT ; i++ )
+ {
+ if ( m_lightRank[i] == -1 ) continue;
+
+ color.r = 0.0f;
+ color.g = 0.0f;
+ color.b = 0.0f; // white (invisible)
+ color.a = 0.0f;
+ m_light->SetLightColor(m_lightRank[i], color);
+ m_light->SetLightColorSpeed(m_lightRank[i], 1.0f/((1.0f/m_speed)*0.75f));
+ }
+
+ m_bBlack = true;
+}
+
+// Management of an event.
+
+bool CTaskBuild::EventProcess(const Event &event)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, dir, speed;
+ Math::Point dim;
+ float a, g, cirSpeed, dist, linSpeed;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ m_time += event.rTime;
+
+ m_progress += event.rTime*m_speed; // other advance
+
+ if ( m_phase == TBP_TURN ) // preliminary rotation?
+ {
+ a = m_object->RetAngleY(0);
+ g = m_angleY;
+ cirSpeed = Math::Direction(a, g)*1.0f;
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left/right
+ return true;
+ }
+
+ if ( m_phase == TBP_MOVE ) // preliminary forward/backward?
+ {
+ dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0));
+ linSpeed = 0.0f;
+ if ( dist > 30.0f ) linSpeed = 1.0f;
+ if ( dist < 30.0f ) linSpeed = -1.0f;
+ m_physics->SetMotorSpeedX(linSpeed); // forward/backward
+ return true;
+ }
+
+ if ( m_phase == TBP_RECEDE ) // terminal back?
+ {
+ m_physics->SetMotorSpeedX(-1.0f); // back
+ return true;
+ }
+
+ if ( m_phase == TBP_TAKE ) // takes gun?
+ {
+ return true;
+ }
+
+ if ( m_phase == TBP_PREP ) // prepares?
+ {
+ return true;
+ }
+
+ if ( m_phase == TBP_TERM ) // ends?
+ {
+ return true;
+ }
+
+ if ( !m_bBuild ) // building to build?
+ {
+ m_bBuild = true;
+
+ pos = m_metal->RetPosition(0);
+ a = m_object->RetAngleY(0);
+ if ( !CreateBuilding(pos, a+Math::PI) )
+ {
+ m_metal->SetLock(false); // usable again
+ m_motion->SetAction(-1);
+ m_object->SetObjectParent(14, 0);
+ m_object->SetPosition(14, Math::Vector(-1.5f, 0.3f, -1.35f));
+ m_object->SetAngleZ(14, Math::PI);
+ m_camera->FlushEffect();
+ Abort();
+ m_bError = true;
+ m_displayText->DisplayError(ERR_TOOMANY, m_object->RetPosition(0));
+ return false;
+ }
+ CreateLight();
+ }
+
+ pos = m_buildingPos;
+ pos.y += m_buildingHeight*m_progress;
+ m_building->SetPosition(0, pos); // the building rises
+
+ m_building->SetZoom(0, m_progress*0.75f+0.25f);
+ m_metal->SetZoom(0, 1.0f-m_progress);
+
+ a = (2.0f-2.0f*m_progress);
+ if ( a > 1.0f ) a = 1.0f;
+ dir.x = (Math::Rand()-0.5f)*a*0.1f;
+ dir.z = (Math::Rand()-0.5f)*a*0.1f;
+ dir.y = (Math::Rand()-0.5f)*a*0.1f;
+ m_building->SetCirVibration(dir);
+
+ if ( !m_bBlack && m_progress >= 0.25f )
+ {
+ BlackLight();
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_metal->RetPosition(0);
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ speed.y = Math::Rand()*10.0f;
+ dim.x = Math::Rand()*6.0f+4.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFIRE);
+
+ pos = Math::Vector(0.0f, 0.5f, 0.0f);
+ mat = m_object->RetWorldMatrix(14);
+ pos = Transform(*mat, pos);
+ speed = m_metal->RetPosition(0);
+ speed.x += (Math::Rand()-0.5f)*5.0f;
+ speed.z += (Math::Rand()-0.5f)*5.0f;
+ speed -= pos;
+ dim.x = 2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFIREZ);
+
+ if ( Math::Rand() < 0.3f )
+ {
+ m_sound->Play(SOUND_BUILD, m_object->RetPosition(0), 0.5f, 1.0f*Math::Rand()*1.5f);
+ }
+ }
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskBuild::Start(ObjectType type)
+{
+ Math::Vector pos, speed, pv, pm;
+ Error err;
+ float iAngle, oAngle;
+
+ m_type = type;
+ m_lastParticule = 0.0f;
+ m_progress = 0.0f;
+
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+ oAngle = iAngle;
+
+ m_bError = true; // operation impossible
+
+ pos = m_object->RetPosition(0);
+ if ( pos.y < m_water->RetLevel() ) return ERR_BUILD_WATER;
+
+ if ( !m_physics->RetLand() ) return ERR_BUILD_FLY;
+
+ speed = m_physics->RetMotorSpeed();
+ if ( speed.x != 0.0f ||
+ speed.z != 0.0f ) return ERR_BUILD_MOTOR;
+
+ if ( m_object->RetFret() != 0 ) return ERR_MANIP_BUSY;
+
+ m_metal = SearchMetalObject(oAngle, 2.0f, 100.0f, Math::PI*0.25f, err);
+ if ( err == ERR_BUILD_METALNEAR && m_metal != 0 )
+ {
+ err = FlatFloor();
+ if ( err != ERR_OK ) return err;
+ return ERR_BUILD_METALNEAR;
+ }
+ if ( err != ERR_OK ) return err;
+
+ err = FlatFloor();
+ if ( err != ERR_OK ) return err;
+
+ m_metal->SetLock(true); // not usable
+ m_camera->StartCentering(m_object, Math::PI*0.15f, 99.9f, 0.0f, 1.0f);
+
+ m_phase = TBP_TURN; // rotation necessary preliminary
+ m_angleY = oAngle; // angle was reached
+
+ pv = m_object->RetPosition(0);
+ pv.y += 8.3f;
+ pm = m_metal->RetPosition(0);
+ m_angleZ = Math::RotateAngle(Math::DistanceProjected(pv, pm), fabs(pv.y-pm.y));
+
+ m_physics->SetFreeze(true); // it does not move
+
+ m_bBuild = false; // not yet built
+ m_bError = false; // ok
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskBuild::IsEnded()
+{
+ CAuto* automat;
+ float angle, dist, time;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_phase == TBP_TURN ) // preliminary rotation?
+ {
+ angle = m_object->RetAngleY(0);
+ angle = Math::NormAngle(angle); // 0..2*Math::PI
+
+ if ( Math::TestAngle(angle, m_angleY-Math::PI*0.01f, m_angleY+Math::PI*0.01f) )
+ {
+ m_physics->SetMotorSpeedZ(0.0f);
+
+ dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0));
+ if ( dist > 30.0f )
+ {
+ time = m_physics->RetLinTimeLength(dist-30.0f, 1.0f);
+ m_speed = 1.0f/time;
+ }
+ else
+ {
+ time = m_physics->RetLinTimeLength(30.0f-dist, -1.0f);
+ m_speed = 1.0f/time;
+ }
+ m_phase = TBP_MOVE;
+ m_progress = 0.0f;
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TBP_MOVE ) // preliminary forward/backward?
+ {
+ dist = Math::Distance(m_object->RetPosition(0), m_metal->RetPosition(0));
+
+ if ( dist >= 25.0f && dist <= 35.0f )
+ {
+ m_physics->SetMotorSpeedX(0.0f);
+ m_motion->SetAction(MHS_GUN); // takes gun
+
+ m_phase = TBP_TAKE;
+ m_speed = 1.0f/1.0f;
+ m_progress = 0.0f;
+ }
+ else
+ {
+ if ( m_progress > 1.0f ) // timeout?
+ {
+ m_metal->SetLock(false); // usable again
+ if ( dist < 30.0f ) return ERR_BUILD_METALNEAR;
+ else return ERR_BUILD_METALAWAY;
+ }
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TBP_TAKE ) // takes gun
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_motion->SetAction(MHS_FIRE); // shooting position
+ m_object->SetObjectParent(14, 4);
+ m_object->SetPosition(14, Math::Vector(0.6f, 0.1f, 0.3f));
+ m_object->SetAngleZ(14, 0.0f);
+
+ m_phase = TBP_PREP;
+ m_speed = 1.0f/1.0f;
+ m_progress = 0.0f;
+ }
+
+ if ( m_phase == TBP_PREP ) // prepares?
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_soundChannel = m_sound->Play(SOUND_TREMBLE, m_object->RetPosition(0), 0.0f, 1.0f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.7f, 1.0f, 1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.7f, 1.5f, 7.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.5f, 2.0f, SOPER_STOP);
+
+ m_camera->StartEffect(CE_VIBRATION, m_metal->RetPosition(0), 1.0f);
+
+ m_phase = TBP_BUILD;
+ m_speed = 1.0f/10.f; // duration of 10s
+ m_progress = 0.0f;
+ }
+
+ if ( m_phase == TBP_BUILD ) // construction?
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ DeleteMark(m_metal->RetPosition(0), 20.0f);
+
+ m_metal->DeleteObject(); // removes the metal
+ delete m_metal;
+ m_metal = 0;
+
+ m_building->SetZoom(0, 1.0f);
+ m_building->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ m_building->SetLock(false); // building usable
+ m_main->CreateShortcuts();
+ m_displayText->DisplayError(INFO_BUILD, m_buildingPos, 10.0f, 50.0f);
+
+ automat = m_building->RetAuto();
+ if ( automat != 0 )
+ {
+ automat->Init();
+ }
+
+ m_motion->SetAction(MHS_GUN); // hands gun
+ m_phase = TBP_TERM;
+ m_speed = 1.0f/1.0f;
+ m_progress = 0.0f;
+ }
+
+ if ( m_phase == TBP_TERM ) // rotation terminale ?
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_motion->SetAction(-1);
+ m_object->SetObjectParent(14, 0);
+ m_object->SetPosition(14, Math::Vector(-1.5f, 0.3f, -1.35f));
+ m_object->SetAngleZ(14, Math::PI);
+
+ if ( m_type == OBJECT_FACTORY ||
+ m_type == OBJECT_RESEARCH ||
+ m_type == OBJECT_NUCLEAR )
+ {
+
+ m_phase = TBP_RECEDE;
+ m_speed = 1.0f/1.5f;
+ m_progress = 0.0f;
+ }
+ }
+
+ if ( m_phase == TBP_RECEDE ) // back?
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_physics->SetMotorSpeedX(0.0f);
+ }
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskBuild::Abort()
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ m_camera->StopCentering(m_object, 2.0f);
+ m_physics->SetFreeze(false); // is moving again
+ return true;
+}
+
+
+// Checks whether the terrain is fairly flat
+// and if there is not too close to another object.
+
+Error CTaskBuild::FlatFloor()
+{
+ CObject *pObj;
+ ObjectType type;
+ Math::Vector center, pos, oPos, bPos;
+ Math::Point c, p;
+ float radius, max, oRadius, bRadius, angle, dist;
+ int i, j;
+ bool bLittleFlat, bBase;
+
+ radius = 0.0f;
+ if ( m_type == OBJECT_DERRICK ) radius = 5.0f;
+ if ( m_type == OBJECT_FACTORY ) radius = 15.0f;
+ if ( m_type == OBJECT_REPAIR ) radius = 12.0f;
+ if ( m_type == OBJECT_STATION ) radius = 12.0f;
+ if ( m_type == OBJECT_CONVERT ) radius = 12.0f;
+ if ( m_type == OBJECT_TOWER ) radius = 7.0f;
+ if ( m_type == OBJECT_RESEARCH ) radius = 10.0f;
+ if ( m_type == OBJECT_RADAR ) radius = 5.0f;
+ if ( m_type == OBJECT_ENERGY ) radius = 8.0f;
+ if ( m_type == OBJECT_LABO ) radius = 12.0f;
+ if ( m_type == OBJECT_NUCLEAR ) radius = 20.0f;
+ if ( m_type == OBJECT_PARA ) radius = 20.0f;
+ if ( m_type == OBJECT_INFO ) radius = 5.0f;
+ if ( radius == 0.0f ) return ERR_GENERIC;
+
+ center = m_metal->RetPosition(0);
+ angle = m_terrain->RetFineSlope(center);
+ bLittleFlat = ( angle < FLATLIMIT );
+
+ max = m_terrain->RetFlatZoneRadius(center, radius);
+ if ( max < radius ) // area too small?
+ {
+ if ( bLittleFlat )
+ {
+ m_main->SetShowLimit(1, PARTILIMIT3, m_metal, center, max, 10.0f);
+ }
+ return bLittleFlat?ERR_BUILD_FLATLIT:ERR_BUILD_FLAT;
+ }
+
+ max = 100000.0f;
+ bBase = false;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue; // inactive?
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( pObj == m_metal ) continue;
+ if ( pObj == m_object ) continue;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_BASE )
+ {
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(center, oPos)-80.0f;
+ if ( dist < max )
+ {
+ max = dist;
+ bPos = oPos;
+ bRadius = oRadius;
+ bBase = true;
+ }
+ }
+ else
+ {
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ dist = Math::Distance(center, oPos)-oRadius;
+ if ( dist < max )
+ {
+ max = dist;
+ bPos = oPos;
+ bRadius = oRadius;
+ bBase = false;
+ }
+ }
+ }
+ }
+ if ( max < radius )
+ {
+ m_main->SetShowLimit(1, PARTILIMIT2, m_metal, center, max, 10.0f);
+ if ( bRadius < 2.0f ) bRadius = 2.0f;
+ m_main->SetShowLimit(2, PARTILIMIT3, m_metal, bPos, bRadius, 10.0f);
+ return bBase?ERR_BUILD_BASE:ERR_BUILD_BUSY;
+ }
+
+ max = 100000.0f;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue; // inactive?
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( pObj == m_metal ) continue;
+ if ( pObj == m_object ) continue;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_DERRICK ||
+ type == OBJECT_FACTORY ||
+ type == OBJECT_STATION ||
+ type == OBJECT_CONVERT ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_TOWER ||
+ type == OBJECT_RESEARCH ||
+ type == OBJECT_RADAR ||
+ type == OBJECT_ENERGY ||
+ type == OBJECT_LABO ||
+ type == OBJECT_NUCLEAR ||
+ type == OBJECT_START ||
+ type == OBJECT_END ||
+ type == OBJECT_INFO ||
+ type == OBJECT_PARA ||
+ type == OBJECT_SAFE ||
+ type == OBJECT_HUSTON ) // building?
+ {
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ dist = Math::Distance(center, oPos)-oRadius;
+ if ( dist < max )
+ {
+ max = dist;
+ bPos = oPos;
+ bRadius = oRadius;
+ }
+ }
+ }
+ }
+ if ( max-BUILDMARGIN < radius )
+ {
+ m_main->SetShowLimit(1, PARTILIMIT2, m_metal, center, max-BUILDMARGIN, 10.0f);
+ m_main->SetShowLimit(2, PARTILIMIT3, m_metal, bPos, bRadius+BUILDMARGIN, 10.0f);
+ return bBase?ERR_BUILD_BASE:ERR_BUILD_NARROW;
+ }
+
+ return ERR_OK;
+}
+
+// Seeks the nearest metal object.
+
+CObject* CTaskBuild::SearchMetalObject(float &angle, float dMin, float dMax,
+ float aLimit, Error &err)
+{
+ CObject *pObj, *pBest;
+ Math::Vector iPos, oPos;
+ ObjectType type;
+ float min, iAngle, a, aa, aBest, distance, magic;
+ int i;
+ bool bMetal;
+
+ iPos = m_object->RetPosition(0);
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+
+ min = 1000000.0f;
+ pBest = 0;
+ bMetal = false;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue; // objet inactive?
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+
+ type = pObj->RetType();
+ if ( type != OBJECT_METAL ) continue;
+
+ bMetal = true; // metal exists
+
+ oPos = pObj->RetPosition(0);
+ distance = Math::Distance(oPos, iPos);
+ a = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW!
+
+ if ( distance > dMax ) continue;
+ if ( !Math::TestAngle(a, iAngle-aLimit, iAngle+aLimit) ) continue;
+
+ if ( distance < dMin )
+ {
+ err = ERR_BUILD_METALNEAR; // too close
+ return pObj;
+ }
+
+ aa = fabs(a-iAngle);
+ if ( aa > Math::PI ) aa = Math::PI*2.0f-aa;
+ magic = distance*aa;
+
+ if ( magic < min )
+ {
+ min = magic;
+ aBest = a;
+ pBest = pObj;
+ }
+ }
+
+ if ( pBest == 0 )
+ {
+ if ( bMetal ) err = ERR_BUILD_METALAWAY; // too far
+ else err = ERR_BUILD_METALINEX; // non-existent
+ }
+ else
+ {
+ angle = aBest;
+ err = ERR_OK;
+ }
+ return pBest;
+}
+
+// Destroys all the close marks.
+
+void CTaskBuild::DeleteMark(Math::Vector pos, float radius)
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ ObjectType type;
+ float distance;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_MARKSTONE &&
+ type != OBJECT_MARKURANIUM &&
+ type != OBJECT_MARKKEYa &&
+ type != OBJECT_MARKKEYb &&
+ type != OBJECT_MARKKEYc &&
+ type != OBJECT_MARKKEYd &&
+ type != OBJECT_MARKPOWER ) continue;
+
+ oPos = pObj->RetPosition(0);
+ distance = Math::Distance(oPos, pos);
+ if ( distance <= radius )
+ {
+ pObj->DeleteObject(); // removes the mark
+ delete pObj;
+ i --;
+ }
+ }
+}
+
diff --git a/src/object/task/taskbuild.h b/src/object/task/taskbuild.h
index 0ca7b9b..682086d 100644
--- a/src/object/task/taskbuild.h
+++ b/src/object/task/taskbuild.h
@@ -1,85 +1,85 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskbuild.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-#include "math/vector.h"
-
-
-
-const float BUILDMARGIN = 16.0f;
-const int TBMAXLIGHT = 4;
-
-
-enum TaskBuildPhase
-{
- TBP_TURN = 1, // turns
- TBP_MOVE = 2, // forward/backward
- TBP_TAKE = 3, // takes gun
- TBP_PREP = 4, // prepares
- TBP_BUILD = 5, // builds
- TBP_TERM = 6, // ends
- TBP_RECEDE = 7, // back terminal
-};
-
-
-
-class CTaskBuild : public CTask
-{
-public:
- CTaskBuild(CInstanceManager* iMan, CObject* object);
- ~CTaskBuild();
-
- bool EventProcess(const Event &event);
-
- Error Start(ObjectType type);
- Error IsEnded();
- bool Abort();
-
-protected:
- Error FlatFloor();
- bool CreateBuilding(Math::Vector pos, float angle);
- void CreateLight();
- void BlackLight();
- CObject* SearchMetalObject(float &angle, float dMin, float dMax, float aLimit, Error &err);
- void DeleteMark(Math::Vector pos, float radius);
-
-protected:
- ObjectType m_type; // type of construction
- CObject* m_metal; // transforms metal object
- CObject* m_power; // the vehicle battery
- CObject* m_building; // building built
- TaskBuildPhase m_phase; // phase of the operation
- bool m_bError; // true -> operation impossible
- bool m_bBuild; // true -> building built
- bool m_bBlack; // true -> lights black -> white
- float m_time; // absolute time
- float m_lastParticule; // time of generation last particle
- float m_progress; // progression (0..1)
- float m_speed; // speed of progression
- float m_angleY; // rotation angle of the vehicle
- float m_angleZ; // angle of rotation of the gun
- Math::Vector m_buildingPos; // initial position of the building
- float m_buildingHeight; // height of the building
- int m_lightRank[TBMAXLIGHT];// lights for the effects
- int m_soundChannel;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskbuild.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "object/object.h"
+#include "math/vector.h"
+
+
+
+const float BUILDMARGIN = 16.0f;
+const int TBMAXLIGHT = 4;
+
+
+enum TaskBuildPhase
+{
+ TBP_TURN = 1, // turns
+ TBP_MOVE = 2, // forward/backward
+ TBP_TAKE = 3, // takes gun
+ TBP_PREP = 4, // prepares
+ TBP_BUILD = 5, // builds
+ TBP_TERM = 6, // ends
+ TBP_RECEDE = 7, // back terminal
+};
+
+
+
+class CTaskBuild : public CTask
+{
+public:
+ CTaskBuild(CInstanceManager* iMan, CObject* object);
+ ~CTaskBuild();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(ObjectType type);
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ Error FlatFloor();
+ bool CreateBuilding(Math::Vector pos, float angle);
+ void CreateLight();
+ void BlackLight();
+ CObject* SearchMetalObject(float &angle, float dMin, float dMax, float aLimit, Error &err);
+ void DeleteMark(Math::Vector pos, float radius);
+
+protected:
+ ObjectType m_type; // type of construction
+ CObject* m_metal; // transforms metal object
+ CObject* m_power; // the vehicle battery
+ CObject* m_building; // building built
+ TaskBuildPhase m_phase; // phase of the operation
+ bool m_bError; // true -> operation impossible
+ bool m_bBuild; // true -> building built
+ bool m_bBlack; // true -> lights black -> white
+ float m_time; // absolute time
+ float m_lastParticule; // time of generation last particle
+ float m_progress; // progression (0..1)
+ float m_speed; // speed of progression
+ float m_angleY; // rotation angle of the vehicle
+ float m_angleZ; // angle of rotation of the gun
+ Math::Vector m_buildingPos; // initial position of the building
+ float m_buildingHeight; // height of the building
+ int m_lightRank[TBMAXLIGHT];// lights for the effects
+ int m_soundChannel;
+};
+
diff --git a/src/object/task/taskfire.cpp b/src/object/task/taskfire.cpp
index 4bab31e..8d300e6 100644
--- a/src/object/task/taskfire.cpp
+++ b/src/object/task/taskfire.cpp
@@ -1,384 +1,384 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskfire.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskfire.h"
-
-#include "old/particule.h"
-#include "math/geometry.h"
-#include "physics/physics.h"
-
-
-
-const float ENERGY_FIRE = (0.25f/2.5f); // energy consumed/shot
-const float ENERGY_FIREr = (0.25f/1.5f); // energy consumed/ray
-const float ENERGY_FIREi = (0.10f/2.5f); // energy consumed/organic
-
-
-// Object's constructor.
-
-CTaskFire::CTaskFire(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_soundChannel = -1;
-}
-
-// Object's destructor.
-
-CTaskFire::~CTaskFire()
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-}
-
-
-// Management of an event.
-
-bool CTaskFire::EventProcess(const Event &event)
-{
- CObject* power;
- CPhysics* physics;
- Math::Matrix* mat;
- Math::Vector pos, speed, dir, vib;
- ObjectType type;
- Math::Point dim;
- float energy, fire;
- int i, channel;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_time += event.rTime;
- m_lastSound -= event.rTime;
- m_progress += event.rTime*m_speed;
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- if ( m_bOrganic ) fire = ENERGY_FIREi;
- else if ( m_bRay ) fire = ENERGY_FIREr;
- else fire = ENERGY_FIRE;
- energy -= event.rTime*fire/power->RetCapacity();
- power->SetEnergy(energy);
- }
-
- if ( m_lastParticule+0.05f <= m_time )
- {
- m_lastParticule = m_time;
-
- if ( m_bOrganic )
- {
- mat = m_object->RetWorldMatrix(1); // insect-cannon
-
- for ( i=0 ; i<6 ; i++ )
- {
- pos = Math::Vector(0.0f, 2.5f, 0.0f);
- pos = Math::Transform(*mat, pos);
-
- speed = Math::Vector(200.0f, 0.0f, 0.0f);
-
- physics = m_object->RetPhysics();
- if ( physics != 0 )
- {
- speed += physics->RetLinMotion(MO_REASPEED);
- }
-
- speed.x += (Math::Rand()-0.5f)*10.0f;
- speed.y += (Math::Rand()-0.5f)*20.0f;
- speed.z += (Math::Rand()-0.5f)*30.0f;
- speed = Math::Transform(*mat, speed);
- speed -= pos;
-
- dim.x = Math::Rand()*0.5f+0.5f;
- dim.y = dim.x;
-
- channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN4, 0.8f, 0.0f, 0.0f);
- m_particule->SetObjectFather(channel, m_object);
- }
- }
- else if ( m_bRay )
- {
- mat = m_object->RetWorldMatrix(2); // cannon
-
- for ( i=0 ; i<4 ; i++ )
- {
- pos = Math::Vector(4.0f, 0.0f, 0.0f);
- pos.y += (rand()%3-1)*1.5f;
- pos.z += (rand()%3-1)*1.5f;
- pos = Math::Transform(*mat, pos);
-
- speed = Math::Vector(200.0f, 0.0f, 0.0f);
- speed.x += (Math::Rand()-0.5f)*6.0f;
- speed.y += (Math::Rand()-0.5f)*12.0f;
- speed.z += (Math::Rand()-0.5f)*12.0f;
- speed = Math::Transform(*mat, speed);
- speed -= pos;
-
- dim.x = 1.0f;
- dim.y = dim.x;
- channel = m_particule->CreateTrack(pos, speed, dim, PARTITRACK11,
- 2.0f, 200.0f, 0.5f, 1.0f);
- m_particule->SetObjectFather(channel, m_object);
-
- speed = Math::Vector(5.0f, 0.0f, 0.0f);
- speed.x += (Math::Rand()-0.5f)*1.0f;
- speed.y += (Math::Rand()-0.5f)*2.0f;
- speed.z += (Math::Rand()-0.5f)*2.0f;
- speed = Math::Transform(*mat, speed);
- speed -= pos;
- speed.y += 5.0f;
-
- dim.x = 2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE2, 2.0f, 0.0f, 0.5f);
- }
- }
- else
- {
- type = m_object->RetType();
-
- if ( type == OBJECT_MOBILErc )
- {
- mat = m_object->RetWorldMatrix(2); // cannon
- }
- else
- {
- mat = m_object->RetWorldMatrix(1); // cannon
- }
-
- for ( i=0 ; i<3 ; i++ )
- {
- if ( type == OBJECT_MOBILErc )
- {
- pos = Math::Vector(0.0f, 0.0f, 0.0f);
- }
- else
- {
- pos = Math::Vector(3.0f, 1.0f, 0.0f);
- }
- pos.y += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- pos = Math::Transform(*mat, pos);
-
- speed = Math::Vector(200.0f, 0.0f, 0.0f);
-
- physics = m_object->RetPhysics();
- if ( physics != 0 )
- {
- speed += physics->RetLinMotion(MO_REASPEED);
- }
-
- speed.x += (Math::Rand()-0.5f)*3.0f;
- speed.y += (Math::Rand()-0.5f)*6.0f;
- speed.z += (Math::Rand()-0.5f)*6.0f;
- speed = Math::Transform(*mat, speed);
- speed -= pos;
-
- dim.x = Math::Rand()*0.7f+0.7f;
- dim.y = dim.x;
-
- channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN1, 0.8f, 0.0f, 0.0f);
- m_particule->SetObjectFather(channel, m_object);
- }
-
- if ( type != OBJECT_MOBILErc &&
- m_progress > 0.3f )
- {
- pos = Math::Vector(-1.0f, 1.0f, 0.0f);
- pos.y += (Math::Rand()-0.5f)*0.4f;
- pos.z += (Math::Rand()-0.5f)*0.4f;
- pos = Math::Transform(*mat, pos);
-
- speed = Math::Vector(-4.0f, 0.0f, 0.0f);
- speed.x += (Math::Rand()-0.5f)*2.0f;
- speed.y += (Math::Rand()-0.2f)*4.0f;
- speed.z += (Math::Rand()-0.5f)*4.0f;
- speed = Math::Transform(*mat, speed);
- speed -= pos;
-
- dim.x = Math::Rand()*1.2f+1.2f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f);
-//? m_particule->CreateParticule(pos, speed, dim, PARTISMOKE2, 4.0f, 0.0f, 0.0f);
- }
- }
-
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- if ( m_progress < 0.1f )
- {
- dir.z = (Math::PI*0.04f)*(m_progress*10.0f);
- }
- else if ( m_progress < 0.9f )
- {
- dir.z = (Math::PI*0.04f);
- }
- else
- {
- dir.z = (Math::PI*0.04f)*(1.0f-(m_progress-0.9f)*10.0f);
- }
- m_object->SetInclinaison(dir);
-
- vib.x = (Math::Rand()-0.5f)*0.01f;
- vib.y = (Math::Rand()-0.5f)*0.02f;
- vib.z = (Math::Rand()-0.5f)*0.02f;
- m_object->SetCirVibration(vib);
-
- vib.x = (Math::Rand()-0.5f)*0.20f;
- vib.y = (Math::Rand()-0.5f)*0.05f;
- vib.z = (Math::Rand()-0.5f)*0.20f;
- m_object->SetLinVibration(vib);
- }
-
- if ( m_bRay && m_lastSound <= 0.0f )
- {
- m_lastSound = Math::Rand()*0.4f+0.4f;
- m_sound->Play(SOUND_FIREp, m_object->RetPosition(0));
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskFire::Start(float delay)
-{
- CObject* power;
- Math::Vector pos, goal, speed;
- float energy, fire;
- ObjectType type;
-
- m_bError = true; // operation impossible
-
- type = m_object->RetType();
- if ( 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_MOBILErc ) return ERR_FIRE_VEH;
-
-//? if ( !m_physics->RetLand() ) return ERR_FIRE_FLY;
-
- speed = m_physics->RetMotorSpeed();
-//? if ( speed.x != 0.0f ||
-//? speed.z != 0.0f ) return ERR_FIRE_MOTOR;
-
- m_bRay = (type == OBJECT_MOBILErc);
-
- m_bOrganic = false;
- if ( type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii )
- {
- m_bOrganic = true;
- }
-
- if ( delay == 0.0f )
- {
- if ( m_bRay ) delay = 1.2f;
- else delay = 2.0f;
- }
- m_delay = delay;
-
- power = m_object->RetPower();
- if ( power == 0 ) return ERR_FIRE_ENERGY;
- energy = power->RetEnergy();
- if ( m_bOrganic ) fire = m_delay*ENERGY_FIREi;
- else if ( m_bRay ) fire = m_delay*ENERGY_FIREr;
- else fire = m_delay*ENERGY_FIRE;
- if ( energy < fire/power->RetCapacity()+0.05f ) return ERR_FIRE_ENERGY;
-
- m_speed = 1.0f/m_delay;
- m_progress = 0.0f;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- m_lastSound = 0.0f;
- m_bError = false; // ok
-
-//? m_camera->StartCentering(m_object, Math::PI*0.15f, 99.9f, 0.0f, 1.0f);
-
- if ( m_bOrganic )
- {
- m_soundChannel = m_sound->Play(SOUND_FIREi, m_object->RetPosition(0), 1.0f, 1.0f, true);
- if ( m_soundChannel != -1 )
- {
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, m_delay, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.5f, SOPER_STOP);
- }
- }
- else if ( m_bRay )
- {
- }
- else
- {
- m_soundChannel = m_sound->Play(SOUND_FIRE, m_object->RetPosition(0), 1.0f, 1.0f, true);
- if ( m_soundChannel != -1 )
- {
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, m_delay, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.5f, SOPER_STOP);
- }
- }
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskFire::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskFire::Abort()
-{
- m_object->SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetLinVibration(Math::Vector(0.0f, 0.0f, 0.0f));
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
-//? m_camera->StopCentering(m_object, 1.0f);
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskfire.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskfire.h"
+
+#include "old/particule.h"
+#include "math/geometry.h"
+#include "physics/physics.h"
+
+
+
+const float ENERGY_FIRE = (0.25f/2.5f); // energy consumed/shot
+const float ENERGY_FIREr = (0.25f/1.5f); // energy consumed/ray
+const float ENERGY_FIREi = (0.10f/2.5f); // energy consumed/organic
+
+
+// Object's constructor.
+
+CTaskFire::CTaskFire(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_soundChannel = -1;
+}
+
+// Object's destructor.
+
+CTaskFire::~CTaskFire()
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+}
+
+
+// Management of an event.
+
+bool CTaskFire::EventProcess(const Event &event)
+{
+ CObject* power;
+ CPhysics* physics;
+ Math::Matrix* mat;
+ Math::Vector pos, speed, dir, vib;
+ ObjectType type;
+ Math::Point dim;
+ float energy, fire;
+ int i, channel;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ m_time += event.rTime;
+ m_lastSound -= event.rTime;
+ m_progress += event.rTime*m_speed;
+
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ if ( m_bOrganic ) fire = ENERGY_FIREi;
+ else if ( m_bRay ) fire = ENERGY_FIREr;
+ else fire = ENERGY_FIRE;
+ energy -= event.rTime*fire/power->RetCapacity();
+ power->SetEnergy(energy);
+ }
+
+ if ( m_lastParticule+0.05f <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ if ( m_bOrganic )
+ {
+ mat = m_object->RetWorldMatrix(1); // insect-cannon
+
+ for ( i=0 ; i<6 ; i++ )
+ {
+ pos = Math::Vector(0.0f, 2.5f, 0.0f);
+ pos = Math::Transform(*mat, pos);
+
+ speed = Math::Vector(200.0f, 0.0f, 0.0f);
+
+ physics = m_object->RetPhysics();
+ if ( physics != 0 )
+ {
+ speed += physics->RetLinMotion(MO_REASPEED);
+ }
+
+ speed.x += (Math::Rand()-0.5f)*10.0f;
+ speed.y += (Math::Rand()-0.5f)*20.0f;
+ speed.z += (Math::Rand()-0.5f)*30.0f;
+ speed = Math::Transform(*mat, speed);
+ speed -= pos;
+
+ dim.x = Math::Rand()*0.5f+0.5f;
+ dim.y = dim.x;
+
+ channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN4, 0.8f, 0.0f, 0.0f);
+ m_particule->SetObjectFather(channel, m_object);
+ }
+ }
+ else if ( m_bRay )
+ {
+ mat = m_object->RetWorldMatrix(2); // cannon
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ pos = Math::Vector(4.0f, 0.0f, 0.0f);
+ pos.y += (rand()%3-1)*1.5f;
+ pos.z += (rand()%3-1)*1.5f;
+ pos = Math::Transform(*mat, pos);
+
+ speed = Math::Vector(200.0f, 0.0f, 0.0f);
+ speed.x += (Math::Rand()-0.5f)*6.0f;
+ speed.y += (Math::Rand()-0.5f)*12.0f;
+ speed.z += (Math::Rand()-0.5f)*12.0f;
+ speed = Math::Transform(*mat, speed);
+ speed -= pos;
+
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ channel = m_particule->CreateTrack(pos, speed, dim, PARTITRACK11,
+ 2.0f, 200.0f, 0.5f, 1.0f);
+ m_particule->SetObjectFather(channel, m_object);
+
+ speed = Math::Vector(5.0f, 0.0f, 0.0f);
+ speed.x += (Math::Rand()-0.5f)*1.0f;
+ speed.y += (Math::Rand()-0.5f)*2.0f;
+ speed.z += (Math::Rand()-0.5f)*2.0f;
+ speed = Math::Transform(*mat, speed);
+ speed -= pos;
+ speed.y += 5.0f;
+
+ dim.x = 2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE2, 2.0f, 0.0f, 0.5f);
+ }
+ }
+ else
+ {
+ type = m_object->RetType();
+
+ if ( type == OBJECT_MOBILErc )
+ {
+ mat = m_object->RetWorldMatrix(2); // cannon
+ }
+ else
+ {
+ mat = m_object->RetWorldMatrix(1); // cannon
+ }
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ if ( type == OBJECT_MOBILErc )
+ {
+ pos = Math::Vector(0.0f, 0.0f, 0.0f);
+ }
+ else
+ {
+ pos = Math::Vector(3.0f, 1.0f, 0.0f);
+ }
+ pos.y += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ pos = Math::Transform(*mat, pos);
+
+ speed = Math::Vector(200.0f, 0.0f, 0.0f);
+
+ physics = m_object->RetPhysics();
+ if ( physics != 0 )
+ {
+ speed += physics->RetLinMotion(MO_REASPEED);
+ }
+
+ speed.x += (Math::Rand()-0.5f)*3.0f;
+ speed.y += (Math::Rand()-0.5f)*6.0f;
+ speed.z += (Math::Rand()-0.5f)*6.0f;
+ speed = Math::Transform(*mat, speed);
+ speed -= pos;
+
+ dim.x = Math::Rand()*0.7f+0.7f;
+ dim.y = dim.x;
+
+ channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN1, 0.8f, 0.0f, 0.0f);
+ m_particule->SetObjectFather(channel, m_object);
+ }
+
+ if ( type != OBJECT_MOBILErc &&
+ m_progress > 0.3f )
+ {
+ pos = Math::Vector(-1.0f, 1.0f, 0.0f);
+ pos.y += (Math::Rand()-0.5f)*0.4f;
+ pos.z += (Math::Rand()-0.5f)*0.4f;
+ pos = Math::Transform(*mat, pos);
+
+ speed = Math::Vector(-4.0f, 0.0f, 0.0f);
+ speed.x += (Math::Rand()-0.5f)*2.0f;
+ speed.y += (Math::Rand()-0.2f)*4.0f;
+ speed.z += (Math::Rand()-0.5f)*4.0f;
+ speed = Math::Transform(*mat, speed);
+ speed -= pos;
+
+ dim.x = Math::Rand()*1.2f+1.2f;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.0f);
+//? m_particule->CreateParticule(pos, speed, dim, PARTISMOKE2, 4.0f, 0.0f, 0.0f);
+ }
+ }
+
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ if ( m_progress < 0.1f )
+ {
+ dir.z = (Math::PI*0.04f)*(m_progress*10.0f);
+ }
+ else if ( m_progress < 0.9f )
+ {
+ dir.z = (Math::PI*0.04f);
+ }
+ else
+ {
+ dir.z = (Math::PI*0.04f)*(1.0f-(m_progress-0.9f)*10.0f);
+ }
+ m_object->SetInclinaison(dir);
+
+ vib.x = (Math::Rand()-0.5f)*0.01f;
+ vib.y = (Math::Rand()-0.5f)*0.02f;
+ vib.z = (Math::Rand()-0.5f)*0.02f;
+ m_object->SetCirVibration(vib);
+
+ vib.x = (Math::Rand()-0.5f)*0.20f;
+ vib.y = (Math::Rand()-0.5f)*0.05f;
+ vib.z = (Math::Rand()-0.5f)*0.20f;
+ m_object->SetLinVibration(vib);
+ }
+
+ if ( m_bRay && m_lastSound <= 0.0f )
+ {
+ m_lastSound = Math::Rand()*0.4f+0.4f;
+ m_sound->Play(SOUND_FIREp, m_object->RetPosition(0));
+ }
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskFire::Start(float delay)
+{
+ CObject* power;
+ Math::Vector pos, goal, speed;
+ float energy, fire;
+ ObjectType type;
+
+ m_bError = true; // operation impossible
+
+ type = m_object->RetType();
+ if ( 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_MOBILErc ) return ERR_FIRE_VEH;
+
+//? if ( !m_physics->RetLand() ) return ERR_FIRE_FLY;
+
+ speed = m_physics->RetMotorSpeed();
+//? if ( speed.x != 0.0f ||
+//? speed.z != 0.0f ) return ERR_FIRE_MOTOR;
+
+ m_bRay = (type == OBJECT_MOBILErc);
+
+ m_bOrganic = false;
+ if ( type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii )
+ {
+ m_bOrganic = true;
+ }
+
+ if ( delay == 0.0f )
+ {
+ if ( m_bRay ) delay = 1.2f;
+ else delay = 2.0f;
+ }
+ m_delay = delay;
+
+ power = m_object->RetPower();
+ if ( power == 0 ) return ERR_FIRE_ENERGY;
+ energy = power->RetEnergy();
+ if ( m_bOrganic ) fire = m_delay*ENERGY_FIREi;
+ else if ( m_bRay ) fire = m_delay*ENERGY_FIREr;
+ else fire = m_delay*ENERGY_FIRE;
+ if ( energy < fire/power->RetCapacity()+0.05f ) return ERR_FIRE_ENERGY;
+
+ m_speed = 1.0f/m_delay;
+ m_progress = 0.0f;
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+ m_lastSound = 0.0f;
+ m_bError = false; // ok
+
+//? m_camera->StartCentering(m_object, Math::PI*0.15f, 99.9f, 0.0f, 1.0f);
+
+ if ( m_bOrganic )
+ {
+ m_soundChannel = m_sound->Play(SOUND_FIREi, m_object->RetPosition(0), 1.0f, 1.0f, true);
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, m_delay, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.5f, SOPER_STOP);
+ }
+ }
+ else if ( m_bRay )
+ {
+ }
+ else
+ {
+ m_soundChannel = m_sound->Play(SOUND_FIRE, m_object->RetPosition(0), 1.0f, 1.0f, true);
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, m_delay, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.5f, SOPER_STOP);
+ }
+ }
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskFire::IsEnded()
+{
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskFire::Abort()
+{
+ m_object->SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
+ m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ m_object->SetLinVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+//? m_camera->StopCentering(m_object, 1.0f);
+ return true;
+}
+
diff --git a/src/object/task/taskfire.h b/src/object/task/taskfire.h
index 43f654e..f06b9f6 100644
--- a/src/object/task/taskfire.h
+++ b/src/object/task/taskfire.h
@@ -1,52 +1,52 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskfire.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskFire : public CTask
-{
-public:
- CTaskFire(CInstanceManager* iMan, CObject* object);
- ~CTaskFire();
-
- bool EventProcess(const Event &event);
-
- Error Start(float delay);
- Error IsEnded();
- bool Abort();
-
-protected:
-
-protected:
- float m_delay;
- float m_progress;
- bool m_bError;
- bool m_bRay;
- bool m_bOrganic;
- float m_time;
- float m_speed;
- float m_lastParticule;
- float m_lastSound;
- int m_soundChannel;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskfire.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+
+
+
+class CTaskFire : public CTask
+{
+public:
+ CTaskFire(CInstanceManager* iMan, CObject* object);
+ ~CTaskFire();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(float delay);
+ Error IsEnded();
+ bool Abort();
+
+protected:
+
+protected:
+ float m_delay;
+ float m_progress;
+ bool m_bError;
+ bool m_bRay;
+ bool m_bOrganic;
+ float m_time;
+ float m_speed;
+ float m_lastParticule;
+ float m_lastSound;
+ int m_soundChannel;
+};
+
diff --git a/src/object/task/taskfireant.cpp b/src/object/task/taskfireant.cpp
index d4a8a61..8eb2217 100644
--- a/src/object/task/taskfireant.cpp
+++ b/src/object/task/taskfireant.cpp
@@ -1,212 +1,212 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskfireant.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskfireant.h"
-
-#include "old/particule.h"
-#include "math/geometry.h"
-#include "object/motion/motionant.h"
-#include "physics/physics.h"
-
-
-
-
-// Object's constructor.
-
-CTaskFireAnt::CTaskFireAnt(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_phase = TFA_NULL;
-}
-
-// Object's destructor.
-
-CTaskFireAnt::~CTaskFireAnt()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskFireAnt::EventProcess(const Event &event)
-{
- Math::Vector dir, vib;
- float a, g, cirSpeed;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- if ( m_object->RetFixed() ) // insect on its back?
- {
- m_bError = true;
- return false;
- }
-
- m_time += event.rTime;
- m_progress += event.rTime*m_speed;
-
- if ( m_phase == TFA_TURN ) // preliminary rotation?
- {
- a = m_object->RetAngleY(0);
- g = m_angle;
- cirSpeed = Math::Direction(a, g)*2.0f;
- if ( cirSpeed > 2.0f ) cirSpeed = 2.0f;
- if ( cirSpeed < -2.0f ) cirSpeed = -2.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left/right
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskFireAnt::Start(Math::Vector impact)
-{
- Math::Vector pos;
- ObjectType type;
-
- m_impact = impact;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() ) return ERR_FIRE_VEH;
-
- type = m_object->RetType();
- if ( type != OBJECT_ANT ) return ERR_FIRE_VEH;
-
- // Insect on its back?
- if ( m_object->RetFixed() ) return ERR_FIRE_VEH;
-
- m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));
-
- pos = m_object->RetPosition(0);
- m_angle = Math::RotateAngle(m_impact.x-pos.x, pos.z-m_impact.z); // CW !
-
- m_phase = TFA_TURN;
- m_speed = 1.0f/1.0f;
- m_progress = 0.0f;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- m_bError = false; // ok
- m_bFire = false; // once!
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskFireAnt::IsEnded()
-{
- Math::Matrix* mat;
- Math::Vector pos, speed;
- Math::Point dim;
- float angle, dist;
- int i, channel;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
- if ( m_object->RetFixed() ) return ERR_STOP; // insect on its back?
-
- if ( m_phase == TFA_TURN ) // rotation ?
- {
- angle = m_object->RetAngleY(0);
- angle = Math::NormAngle(angle); // 0..2*Math::PI
- if ( !Math::TestAngle(angle, m_angle-Math::PI*0.05f, m_angle+Math::PI*0.05f) ) return ERR_CONTINUE;
-
- m_physics->SetMotorSpeedZ(0.0f); // rotation ended
-
- m_phase = TFA_PREPARE;
-//? m_speed = 1.0f/1.5f;
- m_speed = 1.0f/0.4f;
- m_progress = 0.0f;
-//? m_motion->SetAction(MAS_PREPARE, 1.5f);
- m_motion->SetAction(MAS_PREPARE, 0.4f);
- }
-
- if ( m_phase == TFA_PREPARE ) // preparation?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_phase = TFA_FIRE;
-//? m_speed = 1.0f/2.0f;
- m_speed = 1.0f/0.5f;
- m_progress = 0.0f;
-//? m_motion->SetAction(MAS_FIRE, 2.0f);
- m_motion->SetAction(MAS_FIRE, 0.5f);
- }
-
- if ( m_phase == TFA_FIRE ) // shooting?
- {
- if ( m_progress > 0.75f && !m_bFire )
- {
- m_bFire = true; // once
-
- for ( i=0 ; i<20 ; i++ )
- {
- pos = Math::Vector(-2.5f, -0.7f, 0.0f);
- mat = m_object->RetWorldMatrix(2);
- pos = Math::Transform(*mat, pos);
- dist = Math::Distance(pos, m_impact);
- speed = m_impact-pos;
- speed.x += (Math::Rand()-0.5f)*dist*1.2f;
- speed.y += (Math::Rand()-0.5f)*dist*0.4f+50.0f;
- speed.z += (Math::Rand()-0.5f)*dist*1.2f;
- dim.x = 1.0f;
- dim.y = dim.x;
- channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN2, 2.0f, 100.0f, 0.0f);
- m_particule->SetObjectFather(channel, m_object);
- }
- }
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_phase = TFA_TERMINATE;
-//? m_speed = 1.0f/0.9f;
- m_speed = 1.0f/0.4f;
- m_progress = 0.0f;
-//? m_motion->SetAction(MAS_TERMINATE, 0.9f);
- m_motion->SetAction(MAS_TERMINATE, 0.4f);
- }
-
- if ( m_phase == TFA_TERMINATE ) // ends?
- {
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_phase = TFA_NULL;
- m_speed = 1.0f/1.0f;
- m_progress = 0.0f;
- }
-
- Abort();
- return ERR_STOP;
-}
-
-
-// Suddenly ends the current action.
-
-bool CTaskFireAnt::Abort()
-{
- m_motion->SetAction(-1);
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskfireant.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskfireant.h"
+
+#include "old/particule.h"
+#include "math/geometry.h"
+#include "object/motion/motionant.h"
+#include "physics/physics.h"
+
+
+
+
+// Object's constructor.
+
+CTaskFireAnt::CTaskFireAnt(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_phase = TFA_NULL;
+}
+
+// Object's destructor.
+
+CTaskFireAnt::~CTaskFireAnt()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskFireAnt::EventProcess(const Event &event)
+{
+ Math::Vector dir, vib;
+ float a, g, cirSpeed;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ if ( m_object->RetFixed() ) // insect on its back?
+ {
+ m_bError = true;
+ return false;
+ }
+
+ m_time += event.rTime;
+ m_progress += event.rTime*m_speed;
+
+ if ( m_phase == TFA_TURN ) // preliminary rotation?
+ {
+ a = m_object->RetAngleY(0);
+ g = m_angle;
+ cirSpeed = Math::Direction(a, g)*2.0f;
+ if ( cirSpeed > 2.0f ) cirSpeed = 2.0f;
+ if ( cirSpeed < -2.0f ) cirSpeed = -2.0f;
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left/right
+ }
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskFireAnt::Start(Math::Vector impact)
+{
+ Math::Vector pos;
+ ObjectType type;
+
+ m_impact = impact;
+
+ m_bError = true; // operation impossible
+ if ( !m_physics->RetLand() ) return ERR_FIRE_VEH;
+
+ type = m_object->RetType();
+ if ( type != OBJECT_ANT ) return ERR_FIRE_VEH;
+
+ // Insect on its back?
+ if ( m_object->RetFixed() ) return ERR_FIRE_VEH;
+
+ m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));
+
+ pos = m_object->RetPosition(0);
+ m_angle = Math::RotateAngle(m_impact.x-pos.x, pos.z-m_impact.z); // CW !
+
+ m_phase = TFA_TURN;
+ m_speed = 1.0f/1.0f;
+ m_progress = 0.0f;
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+ m_bError = false; // ok
+ m_bFire = false; // once!
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskFireAnt::IsEnded()
+{
+ Math::Matrix* mat;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float angle, dist;
+ int i, channel;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+ if ( m_object->RetFixed() ) return ERR_STOP; // insect on its back?
+
+ if ( m_phase == TFA_TURN ) // rotation ?
+ {
+ angle = m_object->RetAngleY(0);
+ angle = Math::NormAngle(angle); // 0..2*Math::PI
+ if ( !Math::TestAngle(angle, m_angle-Math::PI*0.05f, m_angle+Math::PI*0.05f) ) return ERR_CONTINUE;
+
+ m_physics->SetMotorSpeedZ(0.0f); // rotation ended
+
+ m_phase = TFA_PREPARE;
+//? m_speed = 1.0f/1.5f;
+ m_speed = 1.0f/0.4f;
+ m_progress = 0.0f;
+//? m_motion->SetAction(MAS_PREPARE, 1.5f);
+ m_motion->SetAction(MAS_PREPARE, 0.4f);
+ }
+
+ if ( m_phase == TFA_PREPARE ) // preparation?
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_phase = TFA_FIRE;
+//? m_speed = 1.0f/2.0f;
+ m_speed = 1.0f/0.5f;
+ m_progress = 0.0f;
+//? m_motion->SetAction(MAS_FIRE, 2.0f);
+ m_motion->SetAction(MAS_FIRE, 0.5f);
+ }
+
+ if ( m_phase == TFA_FIRE ) // shooting?
+ {
+ if ( m_progress > 0.75f && !m_bFire )
+ {
+ m_bFire = true; // once
+
+ for ( i=0 ; i<20 ; i++ )
+ {
+ pos = Math::Vector(-2.5f, -0.7f, 0.0f);
+ mat = m_object->RetWorldMatrix(2);
+ pos = Math::Transform(*mat, pos);
+ dist = Math::Distance(pos, m_impact);
+ speed = m_impact-pos;
+ speed.x += (Math::Rand()-0.5f)*dist*1.2f;
+ speed.y += (Math::Rand()-0.5f)*dist*0.4f+50.0f;
+ speed.z += (Math::Rand()-0.5f)*dist*1.2f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN2, 2.0f, 100.0f, 0.0f);
+ m_particule->SetObjectFather(channel, m_object);
+ }
+ }
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_phase = TFA_TERMINATE;
+//? m_speed = 1.0f/0.9f;
+ m_speed = 1.0f/0.4f;
+ m_progress = 0.0f;
+//? m_motion->SetAction(MAS_TERMINATE, 0.9f);
+ m_motion->SetAction(MAS_TERMINATE, 0.4f);
+ }
+
+ if ( m_phase == TFA_TERMINATE ) // ends?
+ {
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_phase = TFA_NULL;
+ m_speed = 1.0f/1.0f;
+ m_progress = 0.0f;
+ }
+
+ Abort();
+ return ERR_STOP;
+}
+
+
+// Suddenly ends the current action.
+
+bool CTaskFireAnt::Abort()
+{
+ m_motion->SetAction(-1);
+ return true;
+}
+
diff --git a/src/object/task/taskfireant.h b/src/object/task/taskfireant.h
index 5b45775..1d8ef62 100644
--- a/src/object/task/taskfireant.h
+++ b/src/object/task/taskfireant.h
@@ -1,63 +1,63 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskfireant.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-enum TaskFireAnt
-{
- TFA_NULL = 0, // nothing to do
- TFA_TURN = 1, // turns
- TFA_PREPARE = 2, // prepares shooting position
- TFA_FIRE = 3, // shooting
- TFA_TERMINATE = 4, // ends shooting position
-};
-
-
-
-class CTaskFireAnt : public CTask
-{
-public:
- CTaskFireAnt(CInstanceManager* iMan, CObject* object);
- ~CTaskFireAnt();
-
- bool EventProcess(const Event &event);
-
- Error Start(Math::Vector impact);
- Error IsEnded();
- bool Abort();
-
-protected:
-
-protected:
- Math::Vector m_impact;
- TaskFireAnt m_phase;
- float m_progress;
- float m_speed;
- float m_angle;
- bool m_bError;
- bool m_bFire;
- float m_time;
- float m_lastParticule;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskfireant.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "math/vector.h"
+
+
+
+enum TaskFireAnt
+{
+ TFA_NULL = 0, // nothing to do
+ TFA_TURN = 1, // turns
+ TFA_PREPARE = 2, // prepares shooting position
+ TFA_FIRE = 3, // shooting
+ TFA_TERMINATE = 4, // ends shooting position
+};
+
+
+
+class CTaskFireAnt : public CTask
+{
+public:
+ CTaskFireAnt(CInstanceManager* iMan, CObject* object);
+ ~CTaskFireAnt();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(Math::Vector impact);
+ Error IsEnded();
+ bool Abort();
+
+protected:
+
+protected:
+ Math::Vector m_impact;
+ TaskFireAnt m_phase;
+ float m_progress;
+ float m_speed;
+ float m_angle;
+ bool m_bError;
+ bool m_bFire;
+ float m_time;
+ float m_lastParticule;
+};
+
diff --git a/src/object/task/taskflag.cpp b/src/object/task/taskflag.cpp
index f76fef6..7fba689 100644
--- a/src/object/task/taskflag.cpp
+++ b/src/object/task/taskflag.cpp
@@ -1,305 +1,305 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskflag.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskflag.h"
-
-#include "math/geometry.h"
-#include "common/iman.h"
-#include "old/water.h"
-#include "old/pyro.h"
-#include "physics/physics.h"
-#include "object/motion/motionhuman.h"
-
-
-
-
-
-// Object's constructor.
-
-CTaskFlag::CTaskFlag(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskFlag::~CTaskFlag()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskFlag::EventProcess(const Event &event)
-{
- if ( m_bError ) return true;
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_time += event.rTime;
-
- return true;
-}
-
-
-
-// Assigns the goal was achieved.
-
-Error CTaskFlag::Start(TaskFlagOrder order, int rank)
-{
- Math::Vector pos, speed;
- Error err;
-
- m_order = order;
- m_time = 0.0f;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() )
- {
- pos = m_object->RetPosition(0);
- if ( pos.y < m_water->RetLevel() ) return ERR_FLAG_WATER;
- return ERR_FLAG_FLY;
- }
-
- speed = m_physics->RetMotorSpeed();
- if ( speed.x != 0.0f ||
- speed.z != 0.0f ) return ERR_FLAG_MOTOR;
-
- if ( m_object->RetFret() != 0 ) return ERR_FLAG_BUSY;
-
- if ( order == TFL_CREATE )
- {
- err = CreateFlag(rank);
- if ( err != ERR_OK ) return err;
- }
-
- if ( order == TFL_DELETE )
- {
- err = DeleteFlag();
- if ( err != ERR_OK ) return err;
- }
-
- m_bError = false;
-
- m_motion->SetAction(MHS_FLAG); // sets/removes flag
- m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.5f);
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskFlag::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
-
- if ( m_bError ) return ERR_STOP;
- if ( m_time < 2.0f ) return ERR_CONTINUE;
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskFlag::Abort()
-{
- m_motion->SetAction(-1);
- m_camera->StopCentering(m_object, 2.0f);
- return true;
-}
-
-
-
-// Returns the closest object to a given position.
-
-CObject* CTaskFlag::SearchNearest(Math::Vector pos, ObjectType type)
-{
- ObjectType oType;
- CObject *pObj, *pBest;
- Math::Vector oPos;
- float min, dist;
- int i;
-
- min = 100000.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetEnable() ) continue;
-
- oType = pObj->RetType();
- if ( type == OBJECT_NULL )
- {
- if ( oType != OBJECT_FLAGb &&
- oType != OBJECT_FLAGr &&
- oType != OBJECT_FLAGg &&
- oType != OBJECT_FLAGy &&
- oType != OBJECT_FLAGv ) continue;
- }
- else
- {
- if ( oType != type ) continue;
- }
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, pos);
- if ( dist < min )
- {
- min = dist;
- pBest = pObj;
- }
- }
- return pBest;
-}
-
-// Counts the number of existing objects.
-
-int CTaskFlag::CountObject(ObjectType type)
-{
- ObjectType oType;
- CObject *pObj;
- Math::Vector oPos;
- int i, count;
-
- count = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetEnable() ) continue;
-
- oType = pObj->RetType();
- if ( type == OBJECT_NULL )
- {
- if ( oType != OBJECT_FLAGb &&
- oType != OBJECT_FLAGr &&
- oType != OBJECT_FLAGg &&
- oType != OBJECT_FLAGy &&
- oType != OBJECT_FLAGv ) continue;
- }
- else
- {
- if ( oType != type ) continue;
- }
-
- count ++;
- }
- return count;
-}
-
-// Creates a color indicator.
-
-Error CTaskFlag::CreateFlag(int rank)
-{
- CObject* pObj;
- CObject* pNew;
- CPyro* pyro;
- Math::Matrix* mat;
- Math::Vector pos;
- float dist;
- int i;
-
- ObjectType table[5] =
- {
- OBJECT_FLAGb,
- OBJECT_FLAGr,
- OBJECT_FLAGg,
- OBJECT_FLAGy,
- OBJECT_FLAGv,
- };
-
- mat = m_object->RetWorldMatrix(0);
- pos = Transform(*mat, Math::Vector(4.0f, 0.0f, 0.0f));
-
- pObj = SearchNearest(pos, OBJECT_NULL);
- if ( pObj != 0 )
- {
- dist = Math::Distance(pos, pObj->RetPosition(0));
- if ( dist < 10.0f )
- {
- return ERR_FLAG_PROXY;
- }
- }
-
- i = rank;
- if ( CountObject(table[i]) >= 5 )
- {
- return ERR_FLAG_CREATE;
- }
-
- pNew = new CObject(m_iMan);
- if ( !pNew->CreateFlag(pos, 0.0f, table[i]) )
- {
- delete pNew;
- return ERR_TOOMANY;
- }
- pNew->SetZoom(0, 0.0f);
-
- m_sound->Play(SOUND_WAYPOINT, pos);
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FLCREATE, pNew);
-
- return ERR_OK;
-}
-
-// Deletes a color indicator.
-
-Error CTaskFlag::DeleteFlag()
-{
- CObject* pObj;
- CPyro* pyro;
- Math::Vector iPos, oPos;
- float iAngle, angle, aLimit, dist;
-
- iPos = m_object->RetPosition(0);
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- pObj = SearchNearest(iPos, OBJECT_NULL);
- if ( pObj == 0 )
- {
- return ERR_FLAG_DELETE;
- }
- dist = Math::Distance(iPos, pObj->RetPosition(0));
- if ( dist > 10.0f )
- {
- return ERR_FLAG_DELETE;
- }
-
- oPos = pObj->RetPosition(0);
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- aLimit = 45.0f*Math::PI/180.0f;
- if ( !Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
- {
- return ERR_FLAG_DELETE;
- }
-
- m_sound->Play(SOUND_WAYPOINT, iPos);
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FLDELETE, pObj);
-
- return ERR_OK;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskflag.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskflag.h"
+
+#include "math/geometry.h"
+#include "common/iman.h"
+#include "old/water.h"
+#include "old/pyro.h"
+#include "physics/physics.h"
+#include "object/motion/motionhuman.h"
+
+
+
+
+
+// Object's constructor.
+
+CTaskFlag::CTaskFlag(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+}
+
+// Object's destructor.
+
+CTaskFlag::~CTaskFlag()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskFlag::EventProcess(const Event &event)
+{
+ if ( m_bError ) return true;
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_time += event.rTime;
+
+ return true;
+}
+
+
+
+// Assigns the goal was achieved.
+
+Error CTaskFlag::Start(TaskFlagOrder order, int rank)
+{
+ Math::Vector pos, speed;
+ Error err;
+
+ m_order = order;
+ m_time = 0.0f;
+
+ m_bError = true; // operation impossible
+ if ( !m_physics->RetLand() )
+ {
+ pos = m_object->RetPosition(0);
+ if ( pos.y < m_water->RetLevel() ) return ERR_FLAG_WATER;
+ return ERR_FLAG_FLY;
+ }
+
+ speed = m_physics->RetMotorSpeed();
+ if ( speed.x != 0.0f ||
+ speed.z != 0.0f ) return ERR_FLAG_MOTOR;
+
+ if ( m_object->RetFret() != 0 ) return ERR_FLAG_BUSY;
+
+ if ( order == TFL_CREATE )
+ {
+ err = CreateFlag(rank);
+ if ( err != ERR_OK ) return err;
+ }
+
+ if ( order == TFL_DELETE )
+ {
+ err = DeleteFlag();
+ if ( err != ERR_OK ) return err;
+ }
+
+ m_bError = false;
+
+ m_motion->SetAction(MHS_FLAG); // sets/removes flag
+ m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.5f);
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskFlag::IsEnded()
+{
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+
+ if ( m_bError ) return ERR_STOP;
+ if ( m_time < 2.0f ) return ERR_CONTINUE;
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskFlag::Abort()
+{
+ m_motion->SetAction(-1);
+ m_camera->StopCentering(m_object, 2.0f);
+ return true;
+}
+
+
+
+// Returns the closest object to a given position.
+
+CObject* CTaskFlag::SearchNearest(Math::Vector pos, ObjectType type)
+{
+ ObjectType oType;
+ CObject *pObj, *pBest;
+ Math::Vector oPos;
+ float min, dist;
+ int i;
+
+ min = 100000.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetEnable() ) continue;
+
+ oType = pObj->RetType();
+ if ( type == OBJECT_NULL )
+ {
+ if ( oType != OBJECT_FLAGb &&
+ oType != OBJECT_FLAGr &&
+ oType != OBJECT_FLAGg &&
+ oType != OBJECT_FLAGy &&
+ oType != OBJECT_FLAGv ) continue;
+ }
+ else
+ {
+ if ( oType != type ) continue;
+ }
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, pos);
+ if ( dist < min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+ return pBest;
+}
+
+// Counts the number of existing objects.
+
+int CTaskFlag::CountObject(ObjectType type)
+{
+ ObjectType oType;
+ CObject *pObj;
+ Math::Vector oPos;
+ int i, count;
+
+ count = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetEnable() ) continue;
+
+ oType = pObj->RetType();
+ if ( type == OBJECT_NULL )
+ {
+ if ( oType != OBJECT_FLAGb &&
+ oType != OBJECT_FLAGr &&
+ oType != OBJECT_FLAGg &&
+ oType != OBJECT_FLAGy &&
+ oType != OBJECT_FLAGv ) continue;
+ }
+ else
+ {
+ if ( oType != type ) continue;
+ }
+
+ count ++;
+ }
+ return count;
+}
+
+// Creates a color indicator.
+
+Error CTaskFlag::CreateFlag(int rank)
+{
+ CObject* pObj;
+ CObject* pNew;
+ CPyro* pyro;
+ Math::Matrix* mat;
+ Math::Vector pos;
+ float dist;
+ int i;
+
+ ObjectType table[5] =
+ {
+ OBJECT_FLAGb,
+ OBJECT_FLAGr,
+ OBJECT_FLAGg,
+ OBJECT_FLAGy,
+ OBJECT_FLAGv,
+ };
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, Math::Vector(4.0f, 0.0f, 0.0f));
+
+ pObj = SearchNearest(pos, OBJECT_NULL);
+ if ( pObj != 0 )
+ {
+ dist = Math::Distance(pos, pObj->RetPosition(0));
+ if ( dist < 10.0f )
+ {
+ return ERR_FLAG_PROXY;
+ }
+ }
+
+ i = rank;
+ if ( CountObject(table[i]) >= 5 )
+ {
+ return ERR_FLAG_CREATE;
+ }
+
+ pNew = new CObject(m_iMan);
+ if ( !pNew->CreateFlag(pos, 0.0f, table[i]) )
+ {
+ delete pNew;
+ return ERR_TOOMANY;
+ }
+ pNew->SetZoom(0, 0.0f);
+
+ m_sound->Play(SOUND_WAYPOINT, pos);
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FLCREATE, pNew);
+
+ return ERR_OK;
+}
+
+// Deletes a color indicator.
+
+Error CTaskFlag::DeleteFlag()
+{
+ CObject* pObj;
+ CPyro* pyro;
+ Math::Vector iPos, oPos;
+ float iAngle, angle, aLimit, dist;
+
+ iPos = m_object->RetPosition(0);
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+
+ pObj = SearchNearest(iPos, OBJECT_NULL);
+ if ( pObj == 0 )
+ {
+ return ERR_FLAG_DELETE;
+ }
+ dist = Math::Distance(iPos, pObj->RetPosition(0));
+ if ( dist > 10.0f )
+ {
+ return ERR_FLAG_DELETE;
+ }
+
+ oPos = pObj->RetPosition(0);
+ angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+ aLimit = 45.0f*Math::PI/180.0f;
+ if ( !Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
+ {
+ return ERR_FLAG_DELETE;
+ }
+
+ m_sound->Play(SOUND_WAYPOINT, iPos);
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FLDELETE, pObj);
+
+ return ERR_OK;
+}
+
diff --git a/src/object/task/taskflag.h b/src/object/task/taskflag.h
index 4a56357..5b0a058 100644
--- a/src/object/task/taskflag.h
+++ b/src/object/task/taskflag.h
@@ -1,58 +1,58 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-// taskflag.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-#include "math/vector.h"
-
-
-
-enum TaskFlagOrder
-{
- TFL_CREATE = 0, // sets
- TFL_DELETE = 1, // removes
-};
-
-
-
-class CTaskFlag : public CTask
-{
-public:
- CTaskFlag(CInstanceManager* iMan, CObject* object);
- ~CTaskFlag();
-
- bool EventProcess(const Event &event);
-
- Error Start(TaskFlagOrder order, int rank);
- Error IsEnded();
- bool Abort();
-
-protected:
- Error CreateFlag(int rank);
- Error DeleteFlag();
- CObject* SearchNearest(Math::Vector pos, ObjectType type);
- int CountObject(ObjectType type);
-
-protected:
- TaskFlagOrder m_order;
- float m_time;
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+// taskflag.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "object/object.h"
+#include "math/vector.h"
+
+
+
+enum TaskFlagOrder
+{
+ TFL_CREATE = 0, // sets
+ TFL_DELETE = 1, // removes
+};
+
+
+
+class CTaskFlag : public CTask
+{
+public:
+ CTaskFlag(CInstanceManager* iMan, CObject* object);
+ ~CTaskFlag();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(TaskFlagOrder order, int rank);
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ Error CreateFlag(int rank);
+ Error DeleteFlag();
+ CObject* SearchNearest(Math::Vector pos, ObjectType type);
+ int CountObject(ObjectType type);
+
+protected:
+ TaskFlagOrder m_order;
+ float m_time;
+ bool m_bError;
+};
+
diff --git a/src/object/task/taskgoto.cpp b/src/object/task/taskgoto.cpp
index 5ab248c..a3b1515 100644
--- a/src/object/task/taskgoto.cpp
+++ b/src/object/task/taskgoto.cpp
@@ -1,2341 +1,2341 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskgoto.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskgoto.h"
-
-#include "common/event.h"
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "math/geometry.h"
-#include "physics/physics.h"
-
-
-
-const float FLY_DIST_GROUND = 80.0f; // minimum distance to remain on the ground
-const float FLY_DEF_HEIGHT = 50.0f; // default flying height
-const float BM_DIM_STEP = 5.0f;
-
-
-
-
-// Object's constructor.
-
-CTaskGoto::CTaskGoto(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_bmArray = 0;
-}
-
-// Object's destructor.
-
-CTaskGoto::~CTaskGoto()
-{
- BitmapClose();
-}
-
-
-// Management of an event.
-
-bool CTaskGoto::EventProcess(const Event &event)
-{
- Math::Vector pos, goal;
- Math::Point rot, repulse;
- float a, g, dist, linSpeed, cirSpeed, h, hh, factor, dir;
- Error ret;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- // Momentarily stationary object (ant on the back)?
- if ( m_object->RetFixed() )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- return true;
- }
-
- if ( m_error != ERR_OK ) return false;
-
- if ( m_bWorm )
- {
- WormFrame(event.rTime);
- }
-
- if ( m_phase == TGP_BEAMLEAK ) // leak?
- {
- m_leakTime += event.rTime;
-
- pos = m_object->RetPosition(0);
-
- rot.x = m_leakPos.x-pos.x;
- rot.y = m_leakPos.z-pos.z;
- dist = Math::Point(rot.x, rot.y).Length();
- rot.x /= dist;
- rot.y /= dist;
-
- a = m_object->RetAngleY(0);
- g = Math::RotateAngle(rot.x, -rot.y); // CW !
- a = Math::Direction(a, g)*1.0f;
- cirSpeed = a;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- a = Math::NormAngle(a);
- if ( a > Math::PI*0.5f && a < Math::PI*1.5f )
- {
- linSpeed = 1.0f; // obstacle behind -> advance
- cirSpeed = -cirSpeed;
- }
- else
- {
- linSpeed = -1.0f; // obstacle in front -> back
- }
-
- if ( m_bLeakRecede )
- {
- linSpeed = -1.0f;
- cirSpeed = 0.0f;
- }
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- m_physics->SetMotorSpeedX(linSpeed); // advance
- return true;
- }
-
- if ( m_phase == TGP_BEAMSEARCH ) // search path?
- {
- if ( m_bmStep == 0 )
- {
- // Frees the area around the departure.
- BitmapClearCircle(m_object->RetPosition(0), BM_DIM_STEP*1.8f);
- }
-
- pos = m_object->RetPosition(0);
-
- if ( m_bmFretObject == 0 )
- {
- goal = m_goal;
- dist = 0.0f;
- }
- else
- {
- goal = m_goalObject;
- dist = TAKE_DIST+2.0f;
- if ( m_bmFretObject->RetType() == OBJECT_BASE ) dist = 12.0f;
- }
-
- ret = BeamSearch(pos, goal, dist);
- if ( ret == ERR_OK )
- {
-#if 0
- Math::Vector min, max;
- min = pos;
- max = m_goal;
- if ( min.x > max.x ) Math::Swap(min.x, max.x);
- if ( min.z > max.z ) Math::Swap(min.z, max.z);
- min.x -= 50.0f;
- min.z -= 50.0f;
- max.x += 50.0f;
- max.z += 50.0f;
- BitmapDebug(min, max, m_object->RetPosition(0), m_goal);
-#endif
- if ( m_physics->RetLand() ) m_phase = TGP_BEAMWCOLD;
- else m_phase = TGP_BEAMGOTO;
- m_bmIndex = 0;
- m_bmWatchDogPos = m_object->RetPosition(0);
- m_bmWatchDogTime = 0.0f;
- }
- if ( ret == ERR_GOTO_IMPOSSIBLE || ret == ERR_GOTO_ITER )
- {
-#if 0
- Math::Vector min, max;
- min = pos;
- max = m_goal;
- if ( min.x > max.x ) Math::Swap(min.x, max.x);
- if ( min.z > max.z ) Math::Swap(min.z, max.z);
- min.x -= 50.0f;
- min.z -= 50.0f;
- max.x += 50.0f;
- max.z += 50.0f;
- BitmapDebug(min, max, m_object->RetPosition(0), m_goal);
-#endif
- m_error = ret;
- return false;
- }
- return true;
- }
-
- if ( m_phase == TGP_BEAMWCOLD ) // expects cooled reactor?
- {
- return true;
- }
-
- if ( m_phase == TGP_BEAMUP ) // off?
- {
- m_physics->SetMotorSpeedY(1.0f); // up
- return true;
- }
-
- if ( m_phase == TGP_BEAMGOTO ) // goto dot list? (?)
- {
- if ( m_physics->RetCollision() ) // collision?
- {
- m_physics->SetCollision(false); // there's more
- }
-
- pos = m_object->RetPosition(0);
-
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude == 0.0f )
- {
- if ( m_physics->RetLand() )
- {
- m_physics->SetMotorSpeedY(0.0f);
- }
- else
- {
- m_physics->SetMotorSpeedY(-1.0f);
- }
- }
-
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
- {
- goal = m_bmPoints[m_bmIndex];
- goal.y = pos.y;
- h = m_terrain->RetFloorHeight(goal, true, true);
- dist = Math::DistanceProjected(pos, goal);
- if ( dist != 0.0f ) // anticipates?
- {
- linSpeed = m_physics->RetLinMotionX(MO_REASPEED);
- linSpeed /= m_physics->RetLinMotionX(MO_ADVSPEED);
- goal.x = pos.x + (goal.x-pos.x)*linSpeed*20.0f/dist;
- goal.z = pos.z + (goal.z-pos.z)*linSpeed*20.0f/dist;
- }
- goal.y = pos.y;
- hh = m_terrain->RetFloorHeight(goal, true, true);
- h = Math::Min(h, hh);
- linSpeed = 0.0f;
- if ( h < m_altitude-1.0f )
- {
- linSpeed = 0.2f+((m_altitude-1.0f)-h)*0.1f; // up
- if ( linSpeed > 1.0f ) linSpeed = 1.0f;
- }
- if ( h > m_altitude+1.0f )
- {
- linSpeed = -0.2f; // down
- }
- m_physics->SetMotorSpeedY(linSpeed);
- }
-
- rot.x = m_bmPoints[m_bmIndex].x-pos.x;
- rot.y = m_bmPoints[m_bmIndex].z-pos.z;
- dist = Math::Point(rot.x, rot.y).Length();
- rot.x /= dist;
- rot.y /= dist;
-
- a = m_object->RetAngleY(0);
- g = Math::RotateAngle(rot.x, -rot.y); // CW !
- cirSpeed = Math::Direction(a, g)*2.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
- if ( dist < 4.0f ) cirSpeed *= dist/4.0f; // so close -> turns less
-
- if ( m_bmIndex == m_bmTotal ) // last point?
- {
- linSpeed = dist/(m_physics->RetLinStopLength()*1.5f);
- if ( linSpeed > 1.0f ) linSpeed = 1.0f;
- }
- else
- {
- linSpeed = 1.0f; // dark without stopping
- }
-
- linSpeed *= 1.0f-(1.0f-0.3f)*fabs(cirSpeed);
-
-//? if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f )
- if ( fabs(cirSpeed) >= 0.2f )
- {
- linSpeed = 0.0f; // turns first, then advance
- }
-
- dist = Math::DistanceProjected(pos, m_bmWatchDogPos);
- if ( dist < 1.0f && linSpeed != 0.0f )
- {
- m_bmWatchDogTime += event.rTime;
- }
- else
- {
- m_bmWatchDogTime = 0.0f;
- m_bmWatchDogPos = pos;
- }
-
- if ( m_bmWatchDogTime >= 1.0f ) // immobile for a long time?
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- BeamStart(); // we start all
- return true;
- }
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- m_physics->SetMotorSpeedX(linSpeed); // advance
- return true;
- }
-
- if ( m_phase == TGP_BEAMDOWN ) // landed?
- {
- m_physics->SetMotorSpeedY(-0.5f); // tomb
- return true;
- }
-
- if ( m_phase == TGP_LAND ) // landed?
- {
- m_physics->SetMotorSpeedY(-0.5f); // tomb
- return true;
- }
-
- if ( m_goalMode == TGG_EXPRESS )
- {
- if ( m_crashMode == TGC_HALT )
- {
- if ( m_physics->RetCollision() ) // collision?
- {
- m_physics->SetCollision(false); // there's more
- m_error = ERR_STOP;
- return true;
- }
- }
-
- pos = m_object->RetPosition(0);
-
- if ( m_altitude > 0.0f )
- {
- h = m_terrain->RetFloorHeight(pos, true, true);
- linSpeed = 0.0f;
- if ( h < m_altitude )
- {
- linSpeed = 0.1f; // up
- }
- if ( h > m_altitude )
- {
- linSpeed = -0.2f; // down
- }
- m_physics->SetMotorSpeedY(linSpeed);
- }
-
- rot.x = m_goal.x-pos.x;
- rot.y = m_goal.z-pos.z;
- a = m_object->RetAngleY(0);
- g = Math::RotateAngle(rot.x, -rot.y); // CW !
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- m_physics->SetMotorSpeedX(1.0f); // advance
- return true;
- }
-
- if ( m_phase != TGP_TURN &&
- m_physics->RetType() == TYPE_FLYING &&
- m_altitude > 0.0f )
- {
- pos = m_object->RetPosition(0);
- dist = Math::DistanceProjected(m_goal, pos);
- factor = (dist-20.0f)/20.0f;
- if ( factor < 0.0f ) factor = 0.0f;
- if ( factor > 1.0f ) factor = 1.0f;
-
- h = m_terrain->RetFloorHeight(m_object->RetPosition(0), true, true);
- linSpeed = 0.0f;
- if ( h < (m_altitude-0.5f)*factor && factor == 1.0f )
- {
- linSpeed = 0.1f; // up
- }
- if ( h > m_altitude*factor )
- {
- linSpeed = -0.2f; // down
- }
- ComputeFlyingRepulse(dir);
- linSpeed += dir*0.2f;
-
- m_physics->SetMotorSpeedY(linSpeed);
- }
-
- if ( m_phase == TGP_ADVANCE ) // going towards the goal?
- {
- if ( m_physics->RetCollision() ) // collision?
- {
- m_physics->SetCollision(false); // there's more
- m_time = 0.0f;
- m_phase = TGP_CRWAIT;
- return true;
- }
-
-#if 0
- pos = m_object->RetPosition(0);
- a = m_object->RetAngleY(0);
- g = Math::RotateAngle(m_goal.x-pos.x, pos.z-m_goal.z); // CW !
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- dist = Math::DistanceProjected(m_goal, pos);
- linSpeed = dist/(m_physics->RetLinStopLength()*1.5f);
- if ( linSpeed > 1.0f ) linSpeed = 1.0f;
-
- if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f )
- {
- linSpeed = 0.0f; // turns first, then advance
- }
-#else
- pos = m_object->RetPosition(0);
-
- rot.x = m_goal.x-pos.x;
- rot.y = m_goal.z-pos.z;
- dist = Math::Point(rot.x, rot.y).Length();
- rot.x /= dist;
- rot.y /= dist;
-
- ComputeRepulse(repulse);
- rot.x += repulse.x*2.0f;
- rot.y += repulse.y*2.0f;
-
- a = m_object->RetAngleY(0);
- g = Math::RotateAngle(rot.x, -rot.y); // CW !
- cirSpeed = Math::Direction(a, g)*1.0f;
-//? if ( m_physics->RetType() == TYPE_FLYING &&
-//? m_physics->RetLand() ) // flying on the ground?
-//? {
-//? cirSpeed *= 4.0f; // more fishing
-//? }
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- dist = Math::DistanceProjected(m_goal, pos);
- linSpeed = dist/(m_physics->RetLinStopLength()*1.5f);
-//? if ( m_physics->RetType() == TYPE_FLYING &&
-//? m_physics->RetLand() ) // flying on the ground?
-//? {
-//? linSpeed *= 8.0f; // more fishing
-//? }
- if ( linSpeed > 1.0f ) linSpeed = 1.0f;
-
- linSpeed *= 1.0f-(1.0f-0.3f)*fabs(cirSpeed);
-
- if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f )
- {
- linSpeed = 0.0f; // turns first, then advance
- }
-#endif
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- m_physics->SetMotorSpeedX(linSpeed); // advance
- }
-
- if ( m_phase == TGP_TURN || // turns to the object?
- m_phase == TGP_CRTURN || // turns after collision?
- m_phase == TGP_CLTURN ) // turns after collision?
- {
- a = m_object->RetAngleY(0);
- g = m_angle;
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- }
-
- if ( m_phase == TGP_CRWAIT || // waits after collision?
- m_phase == TGP_CLWAIT ) // waits after collision?
- {
- m_time += event.rTime;
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- }
-
- if ( m_phase == TGP_CRADVANCE ) // advance after collision?
- {
- if ( m_physics->RetCollision() ) // collision?
- {
- m_physics->SetCollision(false); // there's more
- m_time = 0.0f;
- m_phase = TGP_CLWAIT;
- return true;
- }
- m_physics->SetMotorSpeedX(0.5f); // advance mollo
- }
-
- if ( m_phase == TGP_CLADVANCE ) // advance after collision?
- {
- if ( m_physics->RetCollision() ) // collision?
- {
- m_physics->SetCollision(false); // there's more
- m_time = 0.0f;
- m_phase = TGP_CRWAIT;
- return true;
- }
- m_physics->SetMotorSpeedX(0.5f); // advance mollo
- }
-
- if ( m_phase == TGP_MOVE ) // final advance?
- {
- m_bmTimeLimit -= event.rTime;
- m_physics->SetMotorSpeedX(1.0f);
- }
-
- return true;
-}
-
-
-// Sought a target for the worm.
-
-CObject* CTaskGoto::WormSearch(Math::Vector &impact)
-{
- CObject* pObj;
- CObject* pBest = 0;
- Math::Vector iPos, oPos;
- ObjectType oType;
- float distance, min, radius;
- int i;
-
- iPos = m_object->RetPosition(0);
- min = 1000000.0f;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( 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_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 ) continue;
-
- if ( pObj->RetVirusMode() ) continue; // object infected?
-
- if ( !pObj->GetCrashSphere(0, oPos, radius) ) continue;
- distance = Math::DistanceProjected(oPos, iPos);
- if ( distance < min )
- {
- min = distance;
- pBest = pObj;
- }
- }
- if ( pBest == 0 ) return 0;
-
- impact = pBest->RetPosition(0);
- return pBest;
-}
-
-// Contaminate objects near the worm.
-
-void CTaskGoto::WormFrame(float rTime)
-{
- CObject* pObj;
- Math::Vector impact, pos;
- float dist;
-
- m_wormLastTime += rTime;
-
- if ( m_wormLastTime >= 0.5f )
- {
- m_wormLastTime = 0.0f;
-
- pObj = WormSearch(impact);
- if ( pObj != 0 )
- {
- pos = m_object->RetPosition(0);
- dist = Math::Distance(pos, impact);
- if ( dist <= 15.0f )
- {
- pObj->SetVirusMode(true); // bam, infected!
- }
- }
- }
-}
-
-
-
-// Assigns the goal was achieved.
-// "dist" is the distance that needs to go far to make a deposit or object.
-
-Error CTaskGoto::Start(Math::Vector goal, float altitude,
- TaskGotoGoal goalMode, TaskGotoCrash crashMode)
-{
- Math::Vector pos;
- CObject* target;
- ObjectType type;
- float dist;
- int x, y;
-
- type = m_object->RetType();
-
- if ( goalMode == TGG_DEFAULT )
- {
- goalMode = TGG_STOP;
- if ( type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_WORM )
- {
- goalMode = TGG_EXPRESS;
- }
- }
-
- if ( crashMode == TGC_DEFAULT )
- {
-//? crashMode = TGC_RIGHTLEFT;
- crashMode = TGC_BEAM;
- if ( type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_WORM ||
- type == OBJECT_BEE )
- {
- crashMode = TGC_HALT;
- }
- }
-
- m_altitude = altitude;
- m_goalMode = goalMode;
- m_crashMode = crashMode;
- m_goalObject = goal;
- m_goal = goal;
-
- m_bTake = false;
- m_phase = TGP_ADVANCE;
- m_error = ERR_OK;
- m_try = 0;
- m_bmFretObject = 0;
- m_bmFinalMove = 0.0f;
-
- pos = m_object->RetPosition(0);
- dist = Math::DistanceProjected(pos, m_goal);
- if ( dist < 10.0f && m_crashMode == TGC_BEAM )
- {
- m_crashMode = TGC_RIGHTLEFT;
- }
-
- m_bWorm = false;
- if ( type == OBJECT_WORM )
- {
- m_bWorm = true;
- m_wormLastTime = 0.0f;
- }
-
- m_bApprox = false;
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH ||
- type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs )
- {
- m_bApprox = true;
- }
-
- if ( !m_bApprox && m_crashMode != TGC_BEAM )
- {
- target = SearchTarget(goal, 1.0f);
- if ( target != 0 )
- {
- m_goal = target->RetPosition(0);
- dist = 0.0f;
- if ( !AdjustBuilding(m_goal, 1.0f, dist) )
- {
- dist = 0.0f;
- AdjustTarget(target, m_goal, dist);
- }
- m_bTake = true; // object was taken on arrival (final rotation)
- }
- }
-
- m_lastDistance = 1000.0f;
- m_physics->SetCollision(false);
-
- if ( m_crashMode == TGC_BEAM ) // with the algorithm of rays?
- {
- target = SearchTarget(goal, 1.0f);
- if ( target != 0 )
- {
- m_goal = target->RetPosition(0);
- dist = 4.0f;
- if ( AdjustBuilding(m_goal, 1.0f, dist) )
- {
- m_bmFinalMove = dist;
- }
- else
- {
- dist = 4.0f;
- if ( AdjustTarget(target, m_goal, dist) )
- {
- m_bmFretObject = target; // cargo on the ground
- }
- else
- {
- m_bmFinalMove = dist;
- }
- }
- m_bTake = true; // object was taken on arrival (final rotation)
- }
-
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude == 0.0f )
- {
- pos = m_object->RetPosition(0);
- dist = Math::DistanceProjected(pos, m_goal);
- if ( dist > FLY_DIST_GROUND ) // over 20 meters?
- {
- m_altitude = FLY_DEF_HEIGHT; // default altitude
- }
- }
-
- BeamStart();
-
- if ( m_bmFretObject == 0 )
- {
- x = (int)((m_goal.x+1600.0f)/BM_DIM_STEP);
- y = (int)((m_goal.z+1600.0f)/BM_DIM_STEP);
- if ( BitmapTestDot(0, x, y) ) // arrival occupied?
- {
-#if 0
- Math::Vector min, max;
- min = m_object->RetPosition(0);
- max = m_goal;
- if ( min.x > max.x ) Math::Swap(min.x, max.x);
- if ( min.z > max.z ) Math::Swap(min.z, max.z);
- min.x -= 50.0f;
- min.z -= 50.0f;
- max.x += 50.0f;
- max.z += 50.0f;
- BitmapDebug(min, max, m_object->RetPosition(0), m_goal);
-#endif
- m_error = ERR_GOTO_BUSY;
- return m_error;
- }
- }
- }
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskGoto::IsEnded()
-{
- Math::Vector pos;
- float limit, angle, dist, h, level;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_error != ERR_OK ) return m_error;
-
- pos = m_object->RetPosition(0);
-
- if ( m_phase == TGP_BEAMLEAK ) // leak?
- {
- if ( m_leakTime >= m_leakDelay )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- BeamInit();
- m_phase = TGP_BEAMSEARCH; // will seek the path
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TGP_BEAMSEARCH ) // search path?
- {
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TGP_BEAMWCOLD ) // expects cool reactor?
- {
- if ( m_altitude != 0.0f &&
- m_physics->RetReactorRange() < 1.0f ) return ERR_CONTINUE;
- m_phase = TGP_BEAMUP;
- }
-
- if ( m_phase == TGP_BEAMUP ) // off?
- {
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
- {
- level = m_terrain->RetFloorLevel(pos, true, true);
- h = level+m_altitude-20.0f;
- limit = m_terrain->RetFlyingMaxHeight();
- if ( h > limit ) h = limit;
- if ( pos.y < h-1.0f ) return ERR_CONTINUE;
-
- m_physics->SetMotorSpeedY(0.0f); // stops the ascent
- }
- m_phase = TGP_BEAMGOTO;
- }
-
- if ( m_phase == TGP_BEAMGOTO ) // goto dot list ?
- {
- if ( m_altitude != 0.0f &&
- m_physics->RetReactorRange() < 0.1f ) // overheating?
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_physics->SetMotorSpeedY(-1.0f); // tomb
- m_phase = TGP_BEAMWCOLD;
- return ERR_CONTINUE;
- }
-
- if ( m_physics->RetLand() ) // on the ground?
- {
- limit = 1.0f;
- }
- else // in flight?
- {
- limit = 2.0f;
- if ( m_bmIndex < m_bmTotal ) limit *= 2.0f; // intermediate point
- }
- if ( m_bApprox ) limit = 2.0f;
-
- if ( fabs(pos.x - m_bmPoints[m_bmIndex].x) < limit &&
- fabs(pos.z - m_bmPoints[m_bmIndex].z) < limit )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
-
- m_bmIndex = BeamShortcut();
-
- if ( m_bmIndex > m_bmTotal )
- {
- m_phase = TGP_BEAMDOWN;
- }
- }
- }
-
- if ( m_phase == TGP_BEAMDOWN ) // landed?
- {
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
- {
- if ( !m_physics->RetLand() ) return ERR_CONTINUE;
- m_physics->SetMotorSpeedY(0.0f); // stops the descent
-
- m_altitude = 0.0f;
- m_phase = TGP_BEAMGOTO; // advance finely on the ground to finish
- m_bmIndex = m_bmTotal;
- return ERR_CONTINUE;
- }
-
- if ( m_bTake )
- {
- m_angle = Math::RotateAngle(m_goalObject.x-pos.x, pos.z-m_goalObject.z);
- m_phase = TGP_TURN;
- }
- else
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- return ERR_STOP;
- }
- }
-
- if ( m_goalMode == TGG_EXPRESS )
- {
- dist = Math::DistanceProjected(m_goal, pos);
- if ( dist < 10.0f && dist > m_lastDistance )
- {
- return ERR_STOP;
- }
- m_lastDistance = dist;
- }
-
- if ( m_phase == TGP_ADVANCE ) // going towards the goal?
- {
- if ( m_physics->RetLand() ) limit = 0.1f; // on the ground
- else limit = 1.0f; // flying
- if ( m_bApprox ) limit = 2.0f;
-
- if ( fabs(pos.x - m_goal.x) < limit &&
- fabs(pos.z - m_goal.z) < limit )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_phase = TGP_LAND;
- }
- }
-
- if ( m_phase == TGP_LAND ) // landed?
- {
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
- {
- if ( !m_physics->RetLand() ) return ERR_CONTINUE;
- m_physics->SetMotorSpeedY(0.0f);
- }
-
- if ( m_bTake )
- {
- m_angle = Math::RotateAngle(m_goalObject.x-pos.x, pos.z-m_goalObject.z);
- m_phase = TGP_TURN;
- }
- else
- {
- return ERR_STOP;
- }
- }
-
- if ( m_phase == TGP_TURN ) // turns to the object?
- {
- angle = Math::NormAngle(m_object->RetAngleY(0));
- limit = 0.02f;
- if ( m_bApprox ) limit = 0.10f;
- if ( fabs(angle-m_angle) < limit )
- {
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- if ( m_bmFinalMove == 0.0f ) return ERR_STOP;
-
- m_bmFinalPos = m_object->RetPosition(0);
- m_bmFinalDist = m_physics->RetLinLength(m_bmFinalMove);
- m_bmTimeLimit = m_physics->RetLinTimeLength(fabs(m_bmFinalMove))*1.5f;
- if ( m_bmTimeLimit < 0.5f ) m_bmTimeLimit = 0.5f;
- m_phase = TGP_MOVE;
- }
- }
-
- if ( m_phase == TGP_CRWAIT ) // waits after collision?
- {
- if ( m_crashMode == TGC_HALT )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_error = ERR_GENERIC;
- return m_error;
- }
- if ( m_time >= 1.0f )
- {
- if ( m_crashMode == TGC_RIGHTLEFT ||
- m_crashMode == TGC_RIGHT ) angle = Math::PI/2.0f; // 90 deegres to the right
- else angle = -Math::PI/2.0f; // 90 deegres to the left
- m_angle = Math::NormAngle(m_object->RetAngleY(0)+angle);
- m_phase = TGP_CRTURN;
-//? m_phase = TGP_ADVANCE;
- }
- }
-
- if ( m_phase == TGP_CRTURN ) // turns after collision?
- {
- angle = Math::NormAngle(m_object->RetAngleY(0));
- limit = 0.1f;
- if ( fabs(angle-m_angle) < limit )
- {
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_pos = pos;
- m_phase = TGP_CRADVANCE;
- }
- }
-
- if ( m_phase == TGP_CRADVANCE ) // advance after collision?
- {
- if ( Math::Distance(pos, m_pos) >= 5.0f )
- {
- m_phase = TGP_ADVANCE;
- }
- }
-
- if ( m_phase == TGP_CLWAIT ) // waits after collision?
- {
- if ( m_time >= 1.0f )
- {
- if ( m_crashMode == TGC_RIGHTLEFT ) angle = -Math::PI;
- if ( m_crashMode == TGC_LEFTRIGHT ) angle = Math::PI;
- if ( m_crashMode == TGC_RIGHT ) angle = Math::PI/2.0f;
- if ( m_crashMode == TGC_LEFT ) angle = -Math::PI/2.0f;
- m_angle = Math::NormAngle(m_object->RetAngleY(0)+angle);
- m_phase = TGP_CLTURN;
- }
- }
-
- if ( m_phase == TGP_CLTURN ) // turns after collision?
- {
- angle = Math::NormAngle(m_object->RetAngleY(0));
- limit = 0.1f;
- if ( fabs(angle-m_angle) < limit )
- {
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_pos = pos;
- m_phase = TGP_CLADVANCE;
- }
- }
-
- if ( m_phase == TGP_CLADVANCE ) // advance after collision?
- {
- if ( Math::Distance(pos, m_pos) >= 10.0f )
- {
- m_phase = TGP_ADVANCE;
- m_try ++;
- }
- }
-
- if ( m_phase == TGP_MOVE ) // final advance?
- {
- if ( m_bmTimeLimit <= 0.0f )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops
- Abort();
- return ERR_STOP;
- }
-
- dist = Math::Distance(m_bmFinalPos, m_object->RetPosition(0));
- if ( dist < m_bmFinalDist ) return ERR_CONTINUE;
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- return ERR_STOP;
- }
-
- return ERR_CONTINUE;
-}
-
-
-// Tries the object is the target position.
-
-CObject* CTaskGoto::SearchTarget(Math::Vector pos, float margin)
-{
- CObject *pObj, *pBest;
- Math::Vector oPos;
- float dist, min;
- int i;
-
- pBest = 0;
- min = 1000000.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue;
- if ( pObj->RetTruck() != 0 ) continue; // object transtorted?
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(pos, oPos);
-
- if ( dist <= margin && dist <= min )
- {
- min = dist;
- pBest = pObj;
- }
- }
-
- return pBest;
-}
-
-// Adjusts the target as a function of the object.
-// Returns true if it is cargo laying on the ground, which can be approached from any site.
-
-bool CTaskGoto::AdjustTarget(CObject* pObj, Math::Vector &pos, float &distance)
-{
- ObjectType type;
- Character* character;
- Math::Matrix* mat;
- Math::Vector goal;
- float dist, suppl;
-
- type = m_object->RetType();
- if ( type == OBJECT_BEE ||
- type == OBJECT_WORM )
- {
- pos = pObj->RetPosition(0);
- return false; // single approach
- }
-
- type = pObj->RetType();
-
- if ( type == OBJECT_FRET ||
- type == OBJECT_STONE ||
- type == OBJECT_URANIUM ||
- type == OBJECT_METAL ||
- type == OBJECT_POWER ||
- type == OBJECT_ATOMIC ||
- type == OBJECT_BULLET ||
- type == OBJECT_BBOX ||
- type == OBJECT_KEYa ||
- type == OBJECT_KEYb ||
- type == OBJECT_KEYc ||
- type == OBJECT_KEYd ||
- type == OBJECT_TNT ||
- type == OBJECT_SCRAP1 ||
- type == OBJECT_SCRAP2 ||
- type == OBJECT_SCRAP3 ||
- type == OBJECT_SCRAP4 ||
- type == OBJECT_SCRAP5 ||
- type == OBJECT_BOMB ||
- type == OBJECT_RUINmobilew1 ||
- type == OBJECT_RUINmobilew2 ||
- type == OBJECT_RUINmobilet1 ||
- type == OBJECT_RUINmobilet2 ||
- type == OBJECT_RUINmobiler1 ||
- type == OBJECT_RUINmobiler2 )
- {
- pos = m_object->RetPosition(0);
- goal = pObj->RetPosition(0);
- dist = Math::Distance(goal, pos);
- pos = (pos-goal)*(TAKE_DIST+distance)/dist + goal;
- return true; // approach from all sites
- }
-
- if ( type == OBJECT_BASE )
- {
- pos = m_object->RetPosition(0);
- goal = pObj->RetPosition(0);
- dist = Math::Distance(goal, pos);
- pos = (pos-goal)*(TAKE_DIST+distance)/dist + goal;
- return true; // approach from all sites
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- 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_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr )
- {
- character = pObj->RetCharacter();
- pos = character->posPower;
- pos.x -= TAKE_DIST+TAKE_DIST_OTHER+distance;
- mat = pObj->RetWorldMatrix(0);
- pos = Transform(*mat, pos);
- return false; // single approach
- }
-
- if ( GetHotPoint(pObj, goal, true, distance, suppl) )
- {
- pos = goal;
- distance += suppl;
- return false; // single approach
- }
-
- pos = pObj->RetPosition(0);
- distance = 0.0f;
- return false; // single approach
-}
-
-// If you are on an object produced by a building (ore produced by derrick),
-// changes the position by report the building.
-
-bool CTaskGoto::AdjustBuilding(Math::Vector &pos, float margin, float &distance)
-{
- CObject* pObj;
- Math::Vector oPos;
- float dist, suppl;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue;
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- if ( !GetHotPoint(pObj, oPos, false, 0.0f, suppl) ) continue;
- dist = Math::DistanceProjected(pos, oPos);
- if ( dist <= margin )
- {
- GetHotPoint(pObj, pos, true, distance, suppl);
- distance += suppl;
- return true;
- }
- }
- return false;
-}
-
-// Returns the item or product or pose is something on a building.
-
-bool CTaskGoto::GetHotPoint(CObject *pObj, Math::Vector &pos,
- bool bTake, float distance, float &suppl)
-{
- ObjectType type;
- Math::Matrix* mat;
-
- pos = Math::Vector(0.0f, 0.0f, 0.0f);
- suppl = 0.0f;
- type = pObj->RetType();
-
- if ( type == OBJECT_DERRICK )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 8.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_CONVERT )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 0.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_RESEARCH )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 10.0f;
- if ( bTake && distance != 0.0f ) suppl = 2.5f;
- if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_ENERGY )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 6.0f;
- if ( bTake && distance != 0.0f ) suppl = 6.0f;
- if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_TOWER )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 5.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_LABO )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 6.0f;
- if ( bTake && distance != 0.0f ) suppl = 6.0f;
- if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_NUCLEAR )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 22.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_FACTORY )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 4.0f;
- if ( bTake && distance != 0.0f ) suppl = 6.0f;
- if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_STATION )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 4.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += distance;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_REPAIR )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 4.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += distance;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_DESTROYER )
- {
- mat = pObj->RetWorldMatrix(0);
- pos.x += 0.0f;
- if ( bTake && distance != 0.0f ) suppl = 4.0f;
- if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- if ( type == OBJECT_PARA && m_physics->RetType() == TYPE_FLYING )
- {
- mat = pObj->RetWorldMatrix(0);
- if ( bTake && distance != 0.0f ) suppl = 20.0f;
- if ( bTake ) pos.x += distance+suppl;
- pos = Transform(*mat, pos);
- return true;
- }
-
- suppl = 0.0f;
- return false;
-}
-
-
-// Seeks an object too close that he must flee.
-
-bool CTaskGoto::LeakSearch(Math::Vector &pos, float &delay)
-{
- CObject *pObj, *pObstacle;
- Math::Vector iPos, oPos, bPos;
- float iRadius, oRadius, bRadius, dist, min, dir;
- int i, j;
-
- if ( !m_physics->RetLand() ) return false; // in flight?
-
- m_object->GetCrashSphere(0, iPos, iRadius);
-
- min = 100000.0f;
- bRadius = 0.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( !pObj->RetActif() ) continue;
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- dist = Math::DistanceProjected(oPos, iPos);
- if ( dist < min )
- {
- min = dist;
- bPos = oPos;
- bRadius = oRadius;
- pObstacle = pObj;
- }
- }
- }
- if ( min > iRadius+bRadius+4.0f ) return false;
-
- m_bLeakRecede = false;
-
- dist = 4.0f;
- dir = 1.0f;
- if ( pObstacle->RetType() == OBJECT_FACTORY )
- {
- dist = 16.0f;
- dir = -1.0f;
- m_bLeakRecede = true; // simply recoils
- }
-
- pos = bPos;
- delay = m_physics->RetLinTimeLength(dist, dir);
- return true;
-}
-
-
-// Calculates the force of repulsion due to obstacles.
-// The vector length rendered is between 0 and 1.
-
-void CTaskGoto::ComputeRepulse(Math::Point &dir)
-{
-#if 0
- Math::Vector iPos, oPos;
- Math::Point repulse;
- CObject *pObj;
- float dist, iRadius, oRadius;
- int i;
-
- dir.x = 0.0f;
- dir.y = 0.0f;
-
- m_object->GetCrashSphere(0, iPos, iRadius);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, m_goalObject);
- if ( dist <= 1.0f ) continue;
-
- pObj->GetGlobalSphere(oPos, oRadius);
- oRadius += iRadius+m_physics->RetLinStopLength()*1.1f;
- dist = Math::DistanceProjected(oPos, iPos);
- if ( dist <= oRadius )
- {
- repulse.x = iPos.x-oPos.x;
- repulse.y = iPos.z-oPos.z;
-
-//? dist = 0.2f-(0.2f*dist/oRadius);
- dist = powf(dist/oRadius, 2.0f);
- dist = 0.2f-0.2f*dist;
- repulse.x *= dist;
- repulse.y *= dist;
-//? repulse.x /= dist;
-//? repulse.y /= dist;
-
- dir.x += repulse.x;
- dir.y += repulse.y;
- }
- }
-#else
- ObjectType iType, oType;
- Math::Vector iPos, oPos;
- Math::Point repulse;
- CObject *pObj;
- float gDist, add, addi, fac, dist, iRadius, oRadius;
- int i, j;
- bool bAlien;
-
- dir.x = 0.0f;
- dir.y = 0.0f;
-
- // The worm goes everywhere and through everything!
- iType = m_object->RetType();
- if ( iType == OBJECT_WORM ) return;
-
- m_object->GetCrashSphere(0, iPos, iRadius);
- gDist = Math::Distance(iPos, m_goal);
-
- add = m_physics->RetLinStopLength()*1.1f; // braking distance
- fac = 2.0f;
-
- if ( iType == OBJECT_MOBILEwa ||
- iType == OBJECT_MOBILEwc ||
- iType == OBJECT_MOBILEwi ||
- iType == OBJECT_MOBILEws ||
- iType == OBJECT_MOBILEwt ) // wheels?
- {
- add = 5.0f;
- fac = 1.5f;
- }
- if ( iType == OBJECT_MOBILEta ||
- iType == OBJECT_MOBILEtc ||
- iType == OBJECT_MOBILEti ||
- iType == OBJECT_MOBILEts ||
- iType == OBJECT_MOBILEtt ||
- iType == OBJECT_MOBILEdr ) // caterpillars?
- {
- add = 4.0f;
- fac = 1.5f;
- }
- if ( iType == OBJECT_MOBILEfa ||
- iType == OBJECT_MOBILEfc ||
- iType == OBJECT_MOBILEfi ||
- iType == OBJECT_MOBILEfs ||
- iType == OBJECT_MOBILEft ) // flying?
- {
- if ( m_physics->RetLand() )
- {
- add = 5.0f;
- fac = 1.5f;
- }
- else
- {
- add = 10.0f;
- fac = 1.5f;
- }
- }
- if ( iType == OBJECT_MOBILEia ||
- iType == OBJECT_MOBILEic ||
- iType == OBJECT_MOBILEii ||
- iType == OBJECT_MOBILEis ||
- iType == OBJECT_MOBILEit ) // legs?
- {
- add = 4.0f;
- fac = 1.5f;
- }
- if ( iType == OBJECT_BEE ) // wasp?
- {
- if ( m_physics->RetLand() )
- {
- add = 3.0f;
- fac = 1.5f;
- }
- else
- {
- add = 5.0f;
- fac = 1.5f;
- }
- }
-
- bAlien = false;
- if ( iType == OBJECT_MOTHER ||
- iType == OBJECT_ANT ||
- iType == OBJECT_SPIDER ||
- iType == OBJECT_BEE ||
- iType == OBJECT_WORM )
- {
- bAlien = true;
- }
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- oType = pObj->RetType();
-
- if ( oType == OBJECT_WORM ) continue;
-
- if ( bAlien )
- {
- if ( oType == OBJECT_STONE ||
- oType == OBJECT_URANIUM ||
- oType == OBJECT_METAL ||
- oType == OBJECT_POWER ||
- oType == OBJECT_ATOMIC ||
- oType == OBJECT_BULLET ||
- oType == OBJECT_BBOX ||
- oType == OBJECT_KEYa ||
- oType == OBJECT_KEYb ||
- oType == OBJECT_KEYc ||
- oType == OBJECT_KEYd ||
- oType == OBJECT_TNT ||
- oType == OBJECT_SCRAP1 ||
- oType == OBJECT_SCRAP2 ||
- oType == OBJECT_SCRAP3 ||
- oType == OBJECT_SCRAP4 ||
- oType == OBJECT_SCRAP5 ||
- oType == OBJECT_BOMB ||
- (oType >= OBJECT_PLANT0 &&
- oType <= OBJECT_PLANT19 ) ||
- (oType >= OBJECT_MUSHROOM0 &&
- oType <= OBJECT_MUSHROOM9 ) ) continue;
- }
-
- addi = add;
- if ( iType == OBJECT_BEE &&
- oType == OBJECT_BEE )
- {
- addi = 2.0f; // between wasps, do not annoy too much
- }
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- if ( oPos.y-oRadius > iPos.y+iRadius ) continue;
- if ( oPos.y+oRadius < iPos.y-iRadius ) continue;
-
- dist = Math::Distance(oPos, m_goal);
- if ( dist <= 1.0f ) continue; // on purpose?
-
- oRadius += iRadius+addi;
- dist = Math::DistanceProjected(oPos, iPos);
- if ( dist > gDist ) continue; // beyond the goal?
- if ( dist <= oRadius )
- {
- repulse.x = iPos.x-oPos.x;
- repulse.y = iPos.z-oPos.z;
-
- dist = powf(dist/oRadius, fac);
- dist = 0.2f-0.2f*dist;
- repulse.x *= dist;
- repulse.y *= dist;
-
- dir.x += repulse.x;
- dir.y += repulse.y;
- }
- }
- }
-#endif
-}
-
-// Calculates the force of vertical repulsion according to barriers.
-// The vector length is made​between -1 and 1.
-
-void CTaskGoto::ComputeFlyingRepulse(float &dir)
-{
- ObjectType oType;
- Math::Vector iPos, oPos;
- CObject *pObj;
- float add, fac, dist, iRadius, oRadius, repulse;
- int i, j;
-
- m_object->GetCrashSphere(0, iPos, iRadius);
-
- add = 0.0f;
- fac = 1.5f;
- dir = 0.0f;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- oType = pObj->RetType();
-
- if ( oType == OBJECT_WORM ) continue;
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- oRadius += iRadius+add;
- dist = Math::DistanceProjected(oPos, iPos);
- if ( dist <= oRadius )
- {
- repulse = iPos.y-oPos.y;
-
- dist = powf(dist/oRadius, fac);
- dist = 0.2f-0.2f*dist;
- repulse *= dist;
-
- dir += repulse;
- }
- }
- }
-
- if ( dir < -1.0f ) dir = -1.0f;
- if ( dir > 1.0f ) dir = 1.0f;
-}
-
-
-
-// Among all of the following, seek if there is one allowing to go directly to the crow flies.
-// If yes, skip all the unnecessary intermediate points.
-
-int CTaskGoto::BeamShortcut()
-{
- int i;
-
- for ( i=m_bmTotal ; i>=m_bmIndex+2 ; i-- ) // tries from the last
- {
- if ( BitmapTestLine(m_bmPoints[m_bmIndex], m_bmPoints[i], 0.0f, false) )
- {
- return i; // bingo, found
- }
- }
-
- return m_bmIndex+1; // simply goes to the next
-}
-
-// That's the big start.
-
-void CTaskGoto::BeamStart()
-{
- Math::Vector min, max;
-
- BitmapOpen();
- BitmapObject();
-
- min = m_object->RetPosition(0);
- max = m_goal;
- if ( min.x > max.x ) Math::Swap(min.x, max.x);
- if ( min.z > max.z ) Math::Swap(min.z, max.z);
- min.x -= 10.0f*BM_DIM_STEP;
- min.z -= 10.0f*BM_DIM_STEP;
- max.x += 10.0f*BM_DIM_STEP;
- max.z += 10.0f*BM_DIM_STEP;
- BitmapTerrain(min, max);
-
- if ( LeakSearch(m_leakPos, m_leakDelay) )
- {
- m_phase = TGP_BEAMLEAK; // must first leak
- m_leakTime = 0.0f;
- }
- else
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- BeamInit();
- m_phase = TGP_BEAMSEARCH; // will seek the path
- }
-}
-
-// Initialization before the first BeamSearch.
-
-void CTaskGoto::BeamInit()
-{
- int i;
-
- for ( i=0 ; i<MAXPOINTS ; i++ )
- {
- m_bmIter[i] = -1;
- }
- m_bmStep = 0;
-}
-
-// Calculates points and passes to go from start to goal.
-// Returns:
-// ERR_OK if it's good
-// ERR_GOTO_IMPOSSIBLE if impossible
-// ERR_GOTO_ITER if aborts because too many recursions
-// ERR_CONTINUE if not done yet
-// goalRadius: distance at which we must approach the goal
-
-Error CTaskGoto::BeamSearch(const Math::Vector &start, const Math::Vector &goal,
- float goalRadius)
-{
- float step, len;
- int nbIter;
-
- m_bmStep ++;
-
- len = Math::DistanceProjected(start, goal);
- step = len/5.0f;
- if ( step < BM_DIM_STEP*2.1f ) step = BM_DIM_STEP*2.1f;
- if ( step > 20.0f ) step = 20.0f;
- nbIter = 200; // in order not to lower the framerate
- m_bmIterCounter = 0;
- return BeamExplore(start, start, goal, goalRadius, 165.0f*Math::PI/180.0f, 22, step, 0, nbIter);
-}
-
-// prevPos: previous position
-// curPos: current position
-// goalPos: position that seeks to achieve
-// angle: angle to the goal we explores
-// nbDiv: number of subdivisions being done with angle
-// step length of a step
-// i number of recursions made
-// nbIter maximum number of iterations you have the right to make before temporarily interrupt
-
-Error CTaskGoto::BeamExplore(const Math::Vector &prevPos, const Math::Vector &curPos,
- const Math::Vector &goalPos, float goalRadius,
- float angle, int nbDiv, float step,
- int i, int nbIter)
-{
- Math::Vector newPos;
- Error ret;
- int iDiv, iClear, iLar;
-
- iLar = 0;
- if ( i >= MAXPOINTS ) return ERR_GOTO_ITER; // too many recursions
-
- if ( m_bmIter[i] == -1 )
- {
- m_bmIter[i] = 0;
-
- if ( i == 0 )
- {
- m_bmPoints[i] = curPos;
- }
- else
- {
- if ( !BitmapTestLine(prevPos, curPos, angle/nbDiv, true) ) return ERR_GOTO_IMPOSSIBLE;
-
- m_bmPoints[i] = curPos;
-
- if ( Math::DistanceProjected(curPos, goalPos)-goalRadius <= step )
- {
- if ( goalRadius == 0.0f )
- {
- newPos = goalPos;
- }
- else
- {
- newPos = BeamPoint(curPos, goalPos, 0, Math::DistanceProjected(curPos, goalPos)-goalRadius);
- }
- if ( BitmapTestLine(curPos, newPos, angle/nbDiv, false) )
- {
- m_bmPoints[i+1] = newPos;
- m_bmTotal = i+1;
- return ERR_OK;
- }
- }
- }
- }
-
- if ( iLar >= m_bmIter[i] )
- {
- newPos = BeamPoint(curPos, goalPos, 0, step);
- ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter);
- if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret;
- m_bmIter[i] = iLar+1;
- for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1;
- m_bmIterCounter ++;
- if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE;
- }
- iLar ++;
-
- for ( iDiv=1 ; iDiv<=nbDiv ; iDiv++ )
- {
- if ( iLar >= m_bmIter[i] )
- {
- newPos = BeamPoint(curPos, goalPos, angle*iDiv/nbDiv, step);
- ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter);
- if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret;
- m_bmIter[i] = iLar+1;
- for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1;
- m_bmIterCounter ++;
- if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE;
- }
- iLar ++;
-
- if ( iLar >= m_bmIter[i] )
- {
- newPos = BeamPoint(curPos, goalPos, -angle*iDiv/nbDiv, step);
- ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter);
- if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret;
- m_bmIter[i] = iLar+1;
- for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1;
- m_bmIterCounter ++;
- if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE;
- }
- iLar ++;
- }
-
- return ERR_GOTO_IMPOSSIBLE;
-}
-
-// Is a right "start-goal". Calculates the point located at the distance "step"
-// from the point "start" and an angle "angle" with the right.
-
-Math::Vector CTaskGoto::BeamPoint(const Math::Vector &startPoint,
- const Math::Vector &goalPoint,
- float angle, float step)
-{
- Math::Vector resPoint;
- float goalAngle;
-
- goalAngle = Math::RotateAngle(goalPoint.x-startPoint.x, goalPoint.z-startPoint.z);
-
- resPoint.x = startPoint.x + cosf(goalAngle+angle)*step;
- resPoint.z = startPoint.z + sinf(goalAngle+angle)*step;
- resPoint.y = 0.0f;
-
- return resPoint;
-}
-
-// Displays a bitmap part.
-
-void CTaskGoto::BitmapDebug(const Math::Vector &min, const Math::Vector &max,
- const Math::Vector &start, const Math::Vector &goal)
-{
- int minx, miny, maxx, maxy, x, y, i ,n;
- char s[2000];
-
- minx = (int)((min.x+1600.0f)/BM_DIM_STEP);
- miny = (int)((min.z+1600.0f)/BM_DIM_STEP);
- maxx = (int)((max.x+1600.0f)/BM_DIM_STEP);
- maxy = (int)((max.z+1600.0f)/BM_DIM_STEP);
-
- if ( minx > maxx ) Math::Swap(minx, maxx);
- if ( miny > maxy ) Math::Swap(miny, maxy);
-
- OutputDebugString("Bitmap :\n");
- for ( y=miny ; y<=maxy ; y++ )
- {
- s[0] = 0;
- for ( x=minx ; x<=maxx ; x++ )
- {
- n = -1;
- for ( i=0 ; i<=m_bmTotal ; i++ )
- {
- if ( x == (int)((m_bmPoints[i].x+1600.0f)/BM_DIM_STEP) &&
- y == (int)((m_bmPoints[i].z+1600.0f)/BM_DIM_STEP) )
- {
- n = i;
- break;
- }
- }
-
- if ( BitmapTestDot(0, x,y) )
- {
- strcat(s, "o");
- }
- else
- {
- if ( BitmapTestDot(1, x,y) )
- {
- strcat(s, "-");
- }
- else
- {
- strcat(s, ".");
- }
- }
-
- if ( x == (int)((start.x+1600.0f)/BM_DIM_STEP) &&
- y == (int)((start.z+1600.0f)/BM_DIM_STEP) )
- {
- strcat(s, "s");
- }
- else
- if ( x == (int)((goal.x+1600.0f)/BM_DIM_STEP) &&
- y == (int)((goal.z+1600.0f)/BM_DIM_STEP) )
- {
- strcat(s, "g");
- }
- else
- if ( n != -1 )
- {
- char ss[2];
- ss[0] = 'A'+n;
- ss[1] = 0;
- strcat(s, ss);
- }
- else
- {
- strcat(s, " ");
- }
- }
- strcat(s, "\n");
- OutputDebugString(s);
- }
-}
-
-// Tests if a path along a straight line is possible.
-
-bool CTaskGoto::BitmapTestLine(const Math::Vector &start, const Math::Vector &goal,
- float stepAngle, bool bSecond)
-{
- Math::Vector pos, inc;
- float dist, step;
- float distNoB2;
- int i, max, x, y;
-
- if ( m_bmArray == 0 ) return true;
-
- dist = Math::DistanceProjected(start, goal);
- if ( dist == 0.0f ) return true;
- step = BM_DIM_STEP*0.5f;
-
- inc.x = (goal.x-start.x)*step/dist;
- inc.z = (goal.z-start.z)*step/dist;
-
- pos = start;
-
- if ( bSecond )
- {
- x = (int)((pos.x+1600.0f)/BM_DIM_STEP);
- y = (int)((pos.z+1600.0f)/BM_DIM_STEP);
- BitmapSetDot(1, x, y); // puts the flag as the starting point
- }
-
- max = (int)(dist/step);
- if ( max == 0 ) max = 1;
- distNoB2 = BM_DIM_STEP*sqrtf(2.0f)/sinf(stepAngle);
- for ( i=0 ; i<max ; i++ )
- {
- if ( i == max-1 )
- {
- pos = goal; // tests the point of arrival
- }
- else
- {
- pos.x += inc.x;
- pos.z += inc.z;
- }
-
- x = (int)((pos.x+1600.0f)/BM_DIM_STEP);
- y = (int)((pos.z+1600.0f)/BM_DIM_STEP);
-
- if ( bSecond )
- {
- if ( i > 2 && BitmapTestDot(1, x, y) ) return false;
-
- if ( step*(i+1) > distNoB2 && i < max-2 )
- {
- BitmapSetDot(1, x, y);
- }
- }
-
- if ( BitmapTestDot(0, x, y) ) return false;
- }
- return true;
-}
-
-// Adds the objects in the bitmap.
-
-void CTaskGoto::BitmapObject()
-{
- CObject *pObj;
- ObjectType type;
- Math::Vector iPos, oPos;
- float iRadius, oRadius, h;
- int i, j;
-
- m_object->GetCrashSphere(0, iPos, iRadius);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
-
- if ( pObj == m_object ) continue;
- if ( pObj == m_bmFretObject ) continue;
- if ( pObj->RetTruck() != 0 ) continue;
-
- h = m_terrain->RetFloorLevel(pObj->RetPosition(0), false);
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
- {
- h += m_altitude;
- }
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f ) // flying?
- {
- if ( oPos.y-oRadius > h+8.0f ||
- oPos.y+oRadius < h-8.0f ) continue;
- }
- else // crawling?
- {
- if ( oPos.y-oRadius > h+8.0f ) continue;
- }
-
- if ( type == OBJECT_PARA ) oRadius -= 2.0f;
- BitmapSetCircle(oPos, oRadius+iRadius+4.0f);
- }
- }
-}
-
-// Adds a section of land in the bitmap.
-
-void CTaskGoto::BitmapTerrain(const Math::Vector &min, const Math::Vector &max)
-{
- int minx, miny, maxx, maxy;
-
- minx = (int)((min.x+1600.0f)/BM_DIM_STEP);
- miny = (int)((min.z+1600.0f)/BM_DIM_STEP);
- maxx = (int)((max.x+1600.0f)/BM_DIM_STEP);
- maxy = (int)((max.z+1600.0f)/BM_DIM_STEP);
-
- BitmapTerrain(minx, miny, maxx, maxy);
-}
-
-// Adds a section of land in the bitmap.
-
-void CTaskGoto::BitmapTerrain(int minx, int miny, int maxx, int maxy)
-{
- ObjectType type;
- Math::Vector p;
- float aLimit, angle, h;
- int x, y;
- bool bAcceptWater, bFly;
-
- if ( minx > maxx ) Math::Swap(minx, maxx);
- if ( miny > maxy ) Math::Swap(miny, maxy);
-
- if ( minx < 0 ) minx = 0;
- if ( miny < 0 ) miny = 0;
- if ( maxx > m_bmSize-1 ) maxx = m_bmSize-1;
- if ( maxy > m_bmSize-1 ) maxy = m_bmSize-1;
-
- if ( minx > m_bmMinX ) minx = m_bmMinX;
- if ( miny > m_bmMinY ) miny = m_bmMinY;
- if ( maxx < m_bmMaxX ) maxx = m_bmMaxX;
- if ( maxy < m_bmMaxY ) maxy = m_bmMaxY;
-
- if ( minx >= m_bmMinX && maxx <= m_bmMaxX &&
- miny >= m_bmMinY && maxy <= m_bmMaxY ) return;
-
- aLimit = 20.0f*Math::PI/180.0f;
- bAcceptWater = false;
- bFly = false;
-
- type = m_object->RetType();
-
- if ( type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEtg ) // wheels?
- {
- aLimit = 20.0f*Math::PI/180.0f;
- }
-
- if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts ) // caterpillars?
- {
- aLimit = 35.0f*Math::PI/180.0f;
- }
-
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ) // large caterpillars?
- {
- aLimit = 35.0f*Math::PI/180.0f;
- }
-
- if ( type == OBJECT_MOBILEsa ) // submarine caterpillars?
- {
- aLimit = 35.0f*Math::PI/180.0f;
- bAcceptWater = true;
- }
-
- if ( type == OBJECT_MOBILEdr ) // designer caterpillars?
- {
- aLimit = 35.0f*Math::PI/180.0f;
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEft ) // flying?
- {
- aLimit = 15.0f*Math::PI/180.0f;
- bFly = true;
- }
-
- if ( type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILEii ) // insect legs?
- {
- aLimit = 60.0f*Math::PI/180.0f;
- }
-
- for ( y=miny ; y<=maxy ; y++ )
- {
- for ( x=minx ; x<=maxx ; x++ )
- {
- if ( x >= m_bmMinX && x <= m_bmMaxX &&
- y >= m_bmMinY && y <= m_bmMaxY ) continue;
-
- p.x = x*BM_DIM_STEP-1600.0f;
- p.z = y*BM_DIM_STEP-1600.0f;
-
- if ( bFly ) // flying robot?
- {
- h = m_terrain->RetFloorLevel(p, true);
- if ( h >= m_terrain->RetFlyingMaxHeight()-5.0f )
- {
- BitmapSetDot(0, x, y);
- }
- continue;
- }
-
- if ( !bAcceptWater ) // not going underwater?
- {
- h = m_terrain->RetFloorLevel(p, true);
- if ( h < m_water->RetLevel()-2.0f ) // under water (*)?
- {
-//? BitmapSetDot(0, x, y);
- BitmapSetCircle(p, BM_DIM_STEP*1.0f);
- continue;
- }
- }
-
- angle = m_terrain->RetFineSlope(p);
- if ( angle > aLimit )
- {
- BitmapSetDot(0, x, y);
- }
- }
- }
-
- m_bmMinX = minx;
- m_bmMinY = miny;
- m_bmMaxX = maxx;
- m_bmMaxY = maxy; // expanded rectangular area
-}
-
-// (*) Accepts that a robot is 50cm under water, for example Tropica 3!
-
-// Opens an empty bitmap.
-
-bool CTaskGoto::BitmapOpen()
-{
- BitmapClose();
-
- m_bmSize = (int)(3200.0f/BM_DIM_STEP);
- m_bmArray = (unsigned char*)malloc(m_bmSize*m_bmSize/8*2);
- ZeroMemory(m_bmArray, m_bmSize*m_bmSize/8*2);
-
- m_bmOffset = m_bmSize/2;
- m_bmLine = m_bmSize/8;
-
- m_bmMinX = m_bmSize; // non-existent rectangular area
- m_bmMinY = m_bmSize;
- m_bmMaxX = 0;
- m_bmMaxY = 0;
-
- return true;
-}
-
-// Closes the bitmap.
-
-bool CTaskGoto::BitmapClose()
-{
- free(m_bmArray);
- m_bmArray = 0;
- return true;
-}
-
-// Puts a circle in the bitmap.
-
-void CTaskGoto::BitmapSetCircle(const Math::Vector &pos, float radius)
-{
- float d, r;
- int cx, cy, ix, iy;
-
- cx = (int)((pos.x+1600.0f)/BM_DIM_STEP);
- cy = (int)((pos.z+1600.0f)/BM_DIM_STEP);
- r = radius/BM_DIM_STEP;
-
- for ( iy=cy-(int)r ; iy<=cy+(int)r ; iy++ )
- {
- for ( ix=cx-(int)r ; ix<=cx+(int)r ; ix++ )
- {
- d = Math::Point((float)(ix-cx), (float)(iy-cy)).Length();
- if ( d > r ) continue;
- BitmapSetDot(0, ix, iy);
- }
- }
-}
-
-// Removes a circle in the bitmap.
-
-void CTaskGoto::BitmapClearCircle(const Math::Vector &pos, float radius)
-{
- float d, r;
- int cx, cy, ix, iy;
-
- cx = (int)((pos.x+1600.0f)/BM_DIM_STEP);
- cy = (int)((pos.z+1600.0f)/BM_DIM_STEP);
- r = radius/BM_DIM_STEP;
-
- for ( iy=cy-(int)r ; iy<=cy+(int)r ; iy++ )
- {
- for ( ix=cx-(int)r ; ix<=cx+(int)r ; ix++ )
- {
- d = Math::Point((float)(ix-cx), (float)(iy-cy)).Length();
- if ( d > r ) continue;
- BitmapClearDot(0, ix, iy);
- }
- }
-}
-
-// Makes a point in the bitmap.
-// x:y: 0..m_bmSize-1
-
-void CTaskGoto::BitmapSetDot(int rank, int x, int y)
-{
- if ( x < 0 || x >= m_bmSize ||
- y < 0 || y >= m_bmSize ) return;
-
- m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] |= (1<<x%8);
-}
-
-// Removes a point in the bitmap.
-// x:y: 0..m_bmSize-1
-
-void CTaskGoto::BitmapClearDot(int rank, int x, int y)
-{
- if ( x < 0 || x >= m_bmSize ||
- y < 0 || y >= m_bmSize ) return;
-
- m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] &= ~(1<<x%8);
-}
-
-// Tests a point in the bitmap.
-// x:y: 0..m_bmSize-1
-
-bool CTaskGoto::BitmapTestDot(int rank, int x, int y)
-{
- if ( x < 0 || x >= m_bmSize ||
- y < 0 || y >= m_bmSize ) return false;
-
- if ( x < m_bmMinX || x > m_bmMaxX ||
- y < m_bmMinY || y > m_bmMaxY )
- {
- BitmapTerrain(x-10,y-10, x+10,y+10); // remade a layer
- }
-
- return m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] & (1<<x%8);
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskgoto.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskgoto.h"
+
+#include "common/event.h"
+#include "common/iman.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "math/geometry.h"
+#include "physics/physics.h"
+
+
+
+const float FLY_DIST_GROUND = 80.0f; // minimum distance to remain on the ground
+const float FLY_DEF_HEIGHT = 50.0f; // default flying height
+const float BM_DIM_STEP = 5.0f;
+
+
+
+
+// Object's constructor.
+
+CTaskGoto::CTaskGoto(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_bmArray = 0;
+}
+
+// Object's destructor.
+
+CTaskGoto::~CTaskGoto()
+{
+ BitmapClose();
+}
+
+
+// Management of an event.
+
+bool CTaskGoto::EventProcess(const Event &event)
+{
+ Math::Vector pos, goal;
+ Math::Point rot, repulse;
+ float a, g, dist, linSpeed, cirSpeed, h, hh, factor, dir;
+ Error ret;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ // Momentarily stationary object (ant on the back)?
+ if ( m_object->RetFixed() )
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ return true;
+ }
+
+ if ( m_error != ERR_OK ) return false;
+
+ if ( m_bWorm )
+ {
+ WormFrame(event.rTime);
+ }
+
+ if ( m_phase == TGP_BEAMLEAK ) // leak?
+ {
+ m_leakTime += event.rTime;
+
+ pos = m_object->RetPosition(0);
+
+ rot.x = m_leakPos.x-pos.x;
+ rot.y = m_leakPos.z-pos.z;
+ dist = Math::Point(rot.x, rot.y).Length();
+ rot.x /= dist;
+ rot.y /= dist;
+
+ a = m_object->RetAngleY(0);
+ g = Math::RotateAngle(rot.x, -rot.y); // CW !
+ a = Math::Direction(a, g)*1.0f;
+ cirSpeed = a;
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ a = Math::NormAngle(a);
+ if ( a > Math::PI*0.5f && a < Math::PI*1.5f )
+ {
+ linSpeed = 1.0f; // obstacle behind -> advance
+ cirSpeed = -cirSpeed;
+ }
+ else
+ {
+ linSpeed = -1.0f; // obstacle in front -> back
+ }
+
+ if ( m_bLeakRecede )
+ {
+ linSpeed = -1.0f;
+ cirSpeed = 0.0f;
+ }
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
+ m_physics->SetMotorSpeedX(linSpeed); // advance
+ return true;
+ }
+
+ if ( m_phase == TGP_BEAMSEARCH ) // search path?
+ {
+ if ( m_bmStep == 0 )
+ {
+ // Frees the area around the departure.
+ BitmapClearCircle(m_object->RetPosition(0), BM_DIM_STEP*1.8f);
+ }
+
+ pos = m_object->RetPosition(0);
+
+ if ( m_bmFretObject == 0 )
+ {
+ goal = m_goal;
+ dist = 0.0f;
+ }
+ else
+ {
+ goal = m_goalObject;
+ dist = TAKE_DIST+2.0f;
+ if ( m_bmFretObject->RetType() == OBJECT_BASE ) dist = 12.0f;
+ }
+
+ ret = BeamSearch(pos, goal, dist);
+ if ( ret == ERR_OK )
+ {
+#if 0
+ Math::Vector min, max;
+ min = pos;
+ max = m_goal;
+ if ( min.x > max.x ) Math::Swap(min.x, max.x);
+ if ( min.z > max.z ) Math::Swap(min.z, max.z);
+ min.x -= 50.0f;
+ min.z -= 50.0f;
+ max.x += 50.0f;
+ max.z += 50.0f;
+ BitmapDebug(min, max, m_object->RetPosition(0), m_goal);
+#endif
+ if ( m_physics->RetLand() ) m_phase = TGP_BEAMWCOLD;
+ else m_phase = TGP_BEAMGOTO;
+ m_bmIndex = 0;
+ m_bmWatchDogPos = m_object->RetPosition(0);
+ m_bmWatchDogTime = 0.0f;
+ }
+ if ( ret == ERR_GOTO_IMPOSSIBLE || ret == ERR_GOTO_ITER )
+ {
+#if 0
+ Math::Vector min, max;
+ min = pos;
+ max = m_goal;
+ if ( min.x > max.x ) Math::Swap(min.x, max.x);
+ if ( min.z > max.z ) Math::Swap(min.z, max.z);
+ min.x -= 50.0f;
+ min.z -= 50.0f;
+ max.x += 50.0f;
+ max.z += 50.0f;
+ BitmapDebug(min, max, m_object->RetPosition(0), m_goal);
+#endif
+ m_error = ret;
+ return false;
+ }
+ return true;
+ }
+
+ if ( m_phase == TGP_BEAMWCOLD ) // expects cooled reactor?
+ {
+ return true;
+ }
+
+ if ( m_phase == TGP_BEAMUP ) // off?
+ {
+ m_physics->SetMotorSpeedY(1.0f); // up
+ return true;
+ }
+
+ if ( m_phase == TGP_BEAMGOTO ) // goto dot list? (?)
+ {
+ if ( m_physics->RetCollision() ) // collision?
+ {
+ m_physics->SetCollision(false); // there's more
+ }
+
+ pos = m_object->RetPosition(0);
+
+ if ( m_physics->RetType() == TYPE_FLYING && m_altitude == 0.0f )
+ {
+ if ( m_physics->RetLand() )
+ {
+ m_physics->SetMotorSpeedY(0.0f);
+ }
+ else
+ {
+ m_physics->SetMotorSpeedY(-1.0f);
+ }
+ }
+
+ if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
+ {
+ goal = m_bmPoints[m_bmIndex];
+ goal.y = pos.y;
+ h = m_terrain->RetFloorHeight(goal, true, true);
+ dist = Math::DistanceProjected(pos, goal);
+ if ( dist != 0.0f ) // anticipates?
+ {
+ linSpeed = m_physics->RetLinMotionX(MO_REASPEED);
+ linSpeed /= m_physics->RetLinMotionX(MO_ADVSPEED);
+ goal.x = pos.x + (goal.x-pos.x)*linSpeed*20.0f/dist;
+ goal.z = pos.z + (goal.z-pos.z)*linSpeed*20.0f/dist;
+ }
+ goal.y = pos.y;
+ hh = m_terrain->RetFloorHeight(goal, true, true);
+ h = Math::Min(h, hh);
+ linSpeed = 0.0f;
+ if ( h < m_altitude-1.0f )
+ {
+ linSpeed = 0.2f+((m_altitude-1.0f)-h)*0.1f; // up
+ if ( linSpeed > 1.0f ) linSpeed = 1.0f;
+ }
+ if ( h > m_altitude+1.0f )
+ {
+ linSpeed = -0.2f; // down
+ }
+ m_physics->SetMotorSpeedY(linSpeed);
+ }
+
+ rot.x = m_bmPoints[m_bmIndex].x-pos.x;
+ rot.y = m_bmPoints[m_bmIndex].z-pos.z;
+ dist = Math::Point(rot.x, rot.y).Length();
+ rot.x /= dist;
+ rot.y /= dist;
+
+ a = m_object->RetAngleY(0);
+ g = Math::RotateAngle(rot.x, -rot.y); // CW !
+ cirSpeed = Math::Direction(a, g)*2.0f;
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+ if ( dist < 4.0f ) cirSpeed *= dist/4.0f; // so close -> turns less
+
+ if ( m_bmIndex == m_bmTotal ) // last point?
+ {
+ linSpeed = dist/(m_physics->RetLinStopLength()*1.5f);
+ if ( linSpeed > 1.0f ) linSpeed = 1.0f;
+ }
+ else
+ {
+ linSpeed = 1.0f; // dark without stopping
+ }
+
+ linSpeed *= 1.0f-(1.0f-0.3f)*fabs(cirSpeed);
+
+//? if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f )
+ if ( fabs(cirSpeed) >= 0.2f )
+ {
+ linSpeed = 0.0f; // turns first, then advance
+ }
+
+ dist = Math::DistanceProjected(pos, m_bmWatchDogPos);
+ if ( dist < 1.0f && linSpeed != 0.0f )
+ {
+ m_bmWatchDogTime += event.rTime;
+ }
+ else
+ {
+ m_bmWatchDogTime = 0.0f;
+ m_bmWatchDogPos = pos;
+ }
+
+ if ( m_bmWatchDogTime >= 1.0f ) // immobile for a long time?
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ BeamStart(); // we start all
+ return true;
+ }
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
+ m_physics->SetMotorSpeedX(linSpeed); // advance
+ return true;
+ }
+
+ if ( m_phase == TGP_BEAMDOWN ) // landed?
+ {
+ m_physics->SetMotorSpeedY(-0.5f); // tomb
+ return true;
+ }
+
+ if ( m_phase == TGP_LAND ) // landed?
+ {
+ m_physics->SetMotorSpeedY(-0.5f); // tomb
+ return true;
+ }
+
+ if ( m_goalMode == TGG_EXPRESS )
+ {
+ if ( m_crashMode == TGC_HALT )
+ {
+ if ( m_physics->RetCollision() ) // collision?
+ {
+ m_physics->SetCollision(false); // there's more
+ m_error = ERR_STOP;
+ return true;
+ }
+ }
+
+ pos = m_object->RetPosition(0);
+
+ if ( m_altitude > 0.0f )
+ {
+ h = m_terrain->RetFloorHeight(pos, true, true);
+ linSpeed = 0.0f;
+ if ( h < m_altitude )
+ {
+ linSpeed = 0.1f; // up
+ }
+ if ( h > m_altitude )
+ {
+ linSpeed = -0.2f; // down
+ }
+ m_physics->SetMotorSpeedY(linSpeed);
+ }
+
+ rot.x = m_goal.x-pos.x;
+ rot.y = m_goal.z-pos.z;
+ a = m_object->RetAngleY(0);
+ g = Math::RotateAngle(rot.x, -rot.y); // CW !
+ cirSpeed = Math::Direction(a, g)*1.0f;
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
+ m_physics->SetMotorSpeedX(1.0f); // advance
+ return true;
+ }
+
+ if ( m_phase != TGP_TURN &&
+ m_physics->RetType() == TYPE_FLYING &&
+ m_altitude > 0.0f )
+ {
+ pos = m_object->RetPosition(0);
+ dist = Math::DistanceProjected(m_goal, pos);
+ factor = (dist-20.0f)/20.0f;
+ if ( factor < 0.0f ) factor = 0.0f;
+ if ( factor > 1.0f ) factor = 1.0f;
+
+ h = m_terrain->RetFloorHeight(m_object->RetPosition(0), true, true);
+ linSpeed = 0.0f;
+ if ( h < (m_altitude-0.5f)*factor && factor == 1.0f )
+ {
+ linSpeed = 0.1f; // up
+ }
+ if ( h > m_altitude*factor )
+ {
+ linSpeed = -0.2f; // down
+ }
+ ComputeFlyingRepulse(dir);
+ linSpeed += dir*0.2f;
+
+ m_physics->SetMotorSpeedY(linSpeed);
+ }
+
+ if ( m_phase == TGP_ADVANCE ) // going towards the goal?
+ {
+ if ( m_physics->RetCollision() ) // collision?
+ {
+ m_physics->SetCollision(false); // there's more
+ m_time = 0.0f;
+ m_phase = TGP_CRWAIT;
+ return true;
+ }
+
+#if 0
+ pos = m_object->RetPosition(0);
+ a = m_object->RetAngleY(0);
+ g = Math::RotateAngle(m_goal.x-pos.x, pos.z-m_goal.z); // CW !
+ cirSpeed = Math::Direction(a, g)*1.0f;
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ dist = Math::DistanceProjected(m_goal, pos);
+ linSpeed = dist/(m_physics->RetLinStopLength()*1.5f);
+ if ( linSpeed > 1.0f ) linSpeed = 1.0f;
+
+ if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f )
+ {
+ linSpeed = 0.0f; // turns first, then advance
+ }
+#else
+ pos = m_object->RetPosition(0);
+
+ rot.x = m_goal.x-pos.x;
+ rot.y = m_goal.z-pos.z;
+ dist = Math::Point(rot.x, rot.y).Length();
+ rot.x /= dist;
+ rot.y /= dist;
+
+ ComputeRepulse(repulse);
+ rot.x += repulse.x*2.0f;
+ rot.y += repulse.y*2.0f;
+
+ a = m_object->RetAngleY(0);
+ g = Math::RotateAngle(rot.x, -rot.y); // CW !
+ cirSpeed = Math::Direction(a, g)*1.0f;
+//? if ( m_physics->RetType() == TYPE_FLYING &&
+//? m_physics->RetLand() ) // flying on the ground?
+//? {
+//? cirSpeed *= 4.0f; // more fishing
+//? }
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ dist = Math::DistanceProjected(m_goal, pos);
+ linSpeed = dist/(m_physics->RetLinStopLength()*1.5f);
+//? if ( m_physics->RetType() == TYPE_FLYING &&
+//? m_physics->RetLand() ) // flying on the ground?
+//? {
+//? linSpeed *= 8.0f; // more fishing
+//? }
+ if ( linSpeed > 1.0f ) linSpeed = 1.0f;
+
+ linSpeed *= 1.0f-(1.0f-0.3f)*fabs(cirSpeed);
+
+ if ( dist < 20.0f && fabs(cirSpeed) >= 0.5f )
+ {
+ linSpeed = 0.0f; // turns first, then advance
+ }
+#endif
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
+ m_physics->SetMotorSpeedX(linSpeed); // advance
+ }
+
+ if ( m_phase == TGP_TURN || // turns to the object?
+ m_phase == TGP_CRTURN || // turns after collision?
+ m_phase == TGP_CLTURN ) // turns after collision?
+ {
+ a = m_object->RetAngleY(0);
+ g = m_angle;
+ cirSpeed = Math::Direction(a, g)*1.0f;
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
+ }
+
+ if ( m_phase == TGP_CRWAIT || // waits after collision?
+ m_phase == TGP_CLWAIT ) // waits after collision?
+ {
+ m_time += event.rTime;
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ }
+
+ if ( m_phase == TGP_CRADVANCE ) // advance after collision?
+ {
+ if ( m_physics->RetCollision() ) // collision?
+ {
+ m_physics->SetCollision(false); // there's more
+ m_time = 0.0f;
+ m_phase = TGP_CLWAIT;
+ return true;
+ }
+ m_physics->SetMotorSpeedX(0.5f); // advance mollo
+ }
+
+ if ( m_phase == TGP_CLADVANCE ) // advance after collision?
+ {
+ if ( m_physics->RetCollision() ) // collision?
+ {
+ m_physics->SetCollision(false); // there's more
+ m_time = 0.0f;
+ m_phase = TGP_CRWAIT;
+ return true;
+ }
+ m_physics->SetMotorSpeedX(0.5f); // advance mollo
+ }
+
+ if ( m_phase == TGP_MOVE ) // final advance?
+ {
+ m_bmTimeLimit -= event.rTime;
+ m_physics->SetMotorSpeedX(1.0f);
+ }
+
+ return true;
+}
+
+
+// Sought a target for the worm.
+
+CObject* CTaskGoto::WormSearch(Math::Vector &impact)
+{
+ CObject* pObj;
+ CObject* pBest = 0;
+ Math::Vector iPos, oPos;
+ ObjectType oType;
+ float distance, min, radius;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+ min = 1000000.0f;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( 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_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 ) continue;
+
+ if ( pObj->RetVirusMode() ) continue; // object infected?
+
+ if ( !pObj->GetCrashSphere(0, oPos, radius) ) continue;
+ distance = Math::DistanceProjected(oPos, iPos);
+ if ( distance < min )
+ {
+ min = distance;
+ pBest = pObj;
+ }
+ }
+ if ( pBest == 0 ) return 0;
+
+ impact = pBest->RetPosition(0);
+ return pBest;
+}
+
+// Contaminate objects near the worm.
+
+void CTaskGoto::WormFrame(float rTime)
+{
+ CObject* pObj;
+ Math::Vector impact, pos;
+ float dist;
+
+ m_wormLastTime += rTime;
+
+ if ( m_wormLastTime >= 0.5f )
+ {
+ m_wormLastTime = 0.0f;
+
+ pObj = WormSearch(impact);
+ if ( pObj != 0 )
+ {
+ pos = m_object->RetPosition(0);
+ dist = Math::Distance(pos, impact);
+ if ( dist <= 15.0f )
+ {
+ pObj->SetVirusMode(true); // bam, infected!
+ }
+ }
+ }
+}
+
+
+
+// Assigns the goal was achieved.
+// "dist" is the distance that needs to go far to make a deposit or object.
+
+Error CTaskGoto::Start(Math::Vector goal, float altitude,
+ TaskGotoGoal goalMode, TaskGotoCrash crashMode)
+{
+ Math::Vector pos;
+ CObject* target;
+ ObjectType type;
+ float dist;
+ int x, y;
+
+ type = m_object->RetType();
+
+ if ( goalMode == TGG_DEFAULT )
+ {
+ goalMode = TGG_STOP;
+ if ( type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_WORM )
+ {
+ goalMode = TGG_EXPRESS;
+ }
+ }
+
+ if ( crashMode == TGC_DEFAULT )
+ {
+//? crashMode = TGC_RIGHTLEFT;
+ crashMode = TGC_BEAM;
+ if ( type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_WORM ||
+ type == OBJECT_BEE )
+ {
+ crashMode = TGC_HALT;
+ }
+ }
+
+ m_altitude = altitude;
+ m_goalMode = goalMode;
+ m_crashMode = crashMode;
+ m_goalObject = goal;
+ m_goal = goal;
+
+ m_bTake = false;
+ m_phase = TGP_ADVANCE;
+ m_error = ERR_OK;
+ m_try = 0;
+ m_bmFretObject = 0;
+ m_bmFinalMove = 0.0f;
+
+ pos = m_object->RetPosition(0);
+ dist = Math::DistanceProjected(pos, m_goal);
+ if ( dist < 10.0f && m_crashMode == TGC_BEAM )
+ {
+ m_crashMode = TGC_RIGHTLEFT;
+ }
+
+ m_bWorm = false;
+ if ( type == OBJECT_WORM )
+ {
+ m_bWorm = true;
+ m_wormLastTime = 0.0f;
+ }
+
+ m_bApprox = false;
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH ||
+ type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ m_bApprox = true;
+ }
+
+ if ( !m_bApprox && m_crashMode != TGC_BEAM )
+ {
+ target = SearchTarget(goal, 1.0f);
+ if ( target != 0 )
+ {
+ m_goal = target->RetPosition(0);
+ dist = 0.0f;
+ if ( !AdjustBuilding(m_goal, 1.0f, dist) )
+ {
+ dist = 0.0f;
+ AdjustTarget(target, m_goal, dist);
+ }
+ m_bTake = true; // object was taken on arrival (final rotation)
+ }
+ }
+
+ m_lastDistance = 1000.0f;
+ m_physics->SetCollision(false);
+
+ if ( m_crashMode == TGC_BEAM ) // with the algorithm of rays?
+ {
+ target = SearchTarget(goal, 1.0f);
+ if ( target != 0 )
+ {
+ m_goal = target->RetPosition(0);
+ dist = 4.0f;
+ if ( AdjustBuilding(m_goal, 1.0f, dist) )
+ {
+ m_bmFinalMove = dist;
+ }
+ else
+ {
+ dist = 4.0f;
+ if ( AdjustTarget(target, m_goal, dist) )
+ {
+ m_bmFretObject = target; // cargo on the ground
+ }
+ else
+ {
+ m_bmFinalMove = dist;
+ }
+ }
+ m_bTake = true; // object was taken on arrival (final rotation)
+ }
+
+ if ( m_physics->RetType() == TYPE_FLYING && m_altitude == 0.0f )
+ {
+ pos = m_object->RetPosition(0);
+ dist = Math::DistanceProjected(pos, m_goal);
+ if ( dist > FLY_DIST_GROUND ) // over 20 meters?
+ {
+ m_altitude = FLY_DEF_HEIGHT; // default altitude
+ }
+ }
+
+ BeamStart();
+
+ if ( m_bmFretObject == 0 )
+ {
+ x = (int)((m_goal.x+1600.0f)/BM_DIM_STEP);
+ y = (int)((m_goal.z+1600.0f)/BM_DIM_STEP);
+ if ( BitmapTestDot(0, x, y) ) // arrival occupied?
+ {
+#if 0
+ Math::Vector min, max;
+ min = m_object->RetPosition(0);
+ max = m_goal;
+ if ( min.x > max.x ) Math::Swap(min.x, max.x);
+ if ( min.z > max.z ) Math::Swap(min.z, max.z);
+ min.x -= 50.0f;
+ min.z -= 50.0f;
+ max.x += 50.0f;
+ max.z += 50.0f;
+ BitmapDebug(min, max, m_object->RetPosition(0), m_goal);
+#endif
+ m_error = ERR_GOTO_BUSY;
+ return m_error;
+ }
+ }
+ }
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskGoto::IsEnded()
+{
+ Math::Vector pos;
+ float limit, angle, dist, h, level;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_error != ERR_OK ) return m_error;
+
+ pos = m_object->RetPosition(0);
+
+ if ( m_phase == TGP_BEAMLEAK ) // leak?
+ {
+ if ( m_leakTime >= m_leakDelay )
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ BeamInit();
+ m_phase = TGP_BEAMSEARCH; // will seek the path
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TGP_BEAMSEARCH ) // search path?
+ {
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TGP_BEAMWCOLD ) // expects cool reactor?
+ {
+ if ( m_altitude != 0.0f &&
+ m_physics->RetReactorRange() < 1.0f ) return ERR_CONTINUE;
+ m_phase = TGP_BEAMUP;
+ }
+
+ if ( m_phase == TGP_BEAMUP ) // off?
+ {
+ if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
+ {
+ level = m_terrain->RetFloorLevel(pos, true, true);
+ h = level+m_altitude-20.0f;
+ limit = m_terrain->RetFlyingMaxHeight();
+ if ( h > limit ) h = limit;
+ if ( pos.y < h-1.0f ) return ERR_CONTINUE;
+
+ m_physics->SetMotorSpeedY(0.0f); // stops the ascent
+ }
+ m_phase = TGP_BEAMGOTO;
+ }
+
+ if ( m_phase == TGP_BEAMGOTO ) // goto dot list ?
+ {
+ if ( m_altitude != 0.0f &&
+ m_physics->RetReactorRange() < 0.1f ) // overheating?
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ m_physics->SetMotorSpeedY(-1.0f); // tomb
+ m_phase = TGP_BEAMWCOLD;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_physics->RetLand() ) // on the ground?
+ {
+ limit = 1.0f;
+ }
+ else // in flight?
+ {
+ limit = 2.0f;
+ if ( m_bmIndex < m_bmTotal ) limit *= 2.0f; // intermediate point
+ }
+ if ( m_bApprox ) limit = 2.0f;
+
+ if ( fabs(pos.x - m_bmPoints[m_bmIndex].x) < limit &&
+ fabs(pos.z - m_bmPoints[m_bmIndex].z) < limit )
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+
+ m_bmIndex = BeamShortcut();
+
+ if ( m_bmIndex > m_bmTotal )
+ {
+ m_phase = TGP_BEAMDOWN;
+ }
+ }
+ }
+
+ if ( m_phase == TGP_BEAMDOWN ) // landed?
+ {
+ if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
+ {
+ if ( !m_physics->RetLand() ) return ERR_CONTINUE;
+ m_physics->SetMotorSpeedY(0.0f); // stops the descent
+
+ m_altitude = 0.0f;
+ m_phase = TGP_BEAMGOTO; // advance finely on the ground to finish
+ m_bmIndex = m_bmTotal;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_bTake )
+ {
+ m_angle = Math::RotateAngle(m_goalObject.x-pos.x, pos.z-m_goalObject.z);
+ m_phase = TGP_TURN;
+ }
+ else
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ return ERR_STOP;
+ }
+ }
+
+ if ( m_goalMode == TGG_EXPRESS )
+ {
+ dist = Math::DistanceProjected(m_goal, pos);
+ if ( dist < 10.0f && dist > m_lastDistance )
+ {
+ return ERR_STOP;
+ }
+ m_lastDistance = dist;
+ }
+
+ if ( m_phase == TGP_ADVANCE ) // going towards the goal?
+ {
+ if ( m_physics->RetLand() ) limit = 0.1f; // on the ground
+ else limit = 1.0f; // flying
+ if ( m_bApprox ) limit = 2.0f;
+
+ if ( fabs(pos.x - m_goal.x) < limit &&
+ fabs(pos.z - m_goal.z) < limit )
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ m_phase = TGP_LAND;
+ }
+ }
+
+ if ( m_phase == TGP_LAND ) // landed?
+ {
+ if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
+ {
+ if ( !m_physics->RetLand() ) return ERR_CONTINUE;
+ m_physics->SetMotorSpeedY(0.0f);
+ }
+
+ if ( m_bTake )
+ {
+ m_angle = Math::RotateAngle(m_goalObject.x-pos.x, pos.z-m_goalObject.z);
+ m_phase = TGP_TURN;
+ }
+ else
+ {
+ return ERR_STOP;
+ }
+ }
+
+ if ( m_phase == TGP_TURN ) // turns to the object?
+ {
+ angle = Math::NormAngle(m_object->RetAngleY(0));
+ limit = 0.02f;
+ if ( m_bApprox ) limit = 0.10f;
+ if ( fabs(angle-m_angle) < limit )
+ {
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ if ( m_bmFinalMove == 0.0f ) return ERR_STOP;
+
+ m_bmFinalPos = m_object->RetPosition(0);
+ m_bmFinalDist = m_physics->RetLinLength(m_bmFinalMove);
+ m_bmTimeLimit = m_physics->RetLinTimeLength(fabs(m_bmFinalMove))*1.5f;
+ if ( m_bmTimeLimit < 0.5f ) m_bmTimeLimit = 0.5f;
+ m_phase = TGP_MOVE;
+ }
+ }
+
+ if ( m_phase == TGP_CRWAIT ) // waits after collision?
+ {
+ if ( m_crashMode == TGC_HALT )
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ m_error = ERR_GENERIC;
+ return m_error;
+ }
+ if ( m_time >= 1.0f )
+ {
+ if ( m_crashMode == TGC_RIGHTLEFT ||
+ m_crashMode == TGC_RIGHT ) angle = Math::PI/2.0f; // 90 deegres to the right
+ else angle = -Math::PI/2.0f; // 90 deegres to the left
+ m_angle = Math::NormAngle(m_object->RetAngleY(0)+angle);
+ m_phase = TGP_CRTURN;
+//? m_phase = TGP_ADVANCE;
+ }
+ }
+
+ if ( m_phase == TGP_CRTURN ) // turns after collision?
+ {
+ angle = Math::NormAngle(m_object->RetAngleY(0));
+ limit = 0.1f;
+ if ( fabs(angle-m_angle) < limit )
+ {
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ m_pos = pos;
+ m_phase = TGP_CRADVANCE;
+ }
+ }
+
+ if ( m_phase == TGP_CRADVANCE ) // advance after collision?
+ {
+ if ( Math::Distance(pos, m_pos) >= 5.0f )
+ {
+ m_phase = TGP_ADVANCE;
+ }
+ }
+
+ if ( m_phase == TGP_CLWAIT ) // waits after collision?
+ {
+ if ( m_time >= 1.0f )
+ {
+ if ( m_crashMode == TGC_RIGHTLEFT ) angle = -Math::PI;
+ if ( m_crashMode == TGC_LEFTRIGHT ) angle = Math::PI;
+ if ( m_crashMode == TGC_RIGHT ) angle = Math::PI/2.0f;
+ if ( m_crashMode == TGC_LEFT ) angle = -Math::PI/2.0f;
+ m_angle = Math::NormAngle(m_object->RetAngleY(0)+angle);
+ m_phase = TGP_CLTURN;
+ }
+ }
+
+ if ( m_phase == TGP_CLTURN ) // turns after collision?
+ {
+ angle = Math::NormAngle(m_object->RetAngleY(0));
+ limit = 0.1f;
+ if ( fabs(angle-m_angle) < limit )
+ {
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ m_pos = pos;
+ m_phase = TGP_CLADVANCE;
+ }
+ }
+
+ if ( m_phase == TGP_CLADVANCE ) // advance after collision?
+ {
+ if ( Math::Distance(pos, m_pos) >= 10.0f )
+ {
+ m_phase = TGP_ADVANCE;
+ m_try ++;
+ }
+ }
+
+ if ( m_phase == TGP_MOVE ) // final advance?
+ {
+ if ( m_bmTimeLimit <= 0.0f )
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops
+ Abort();
+ return ERR_STOP;
+ }
+
+ dist = Math::Distance(m_bmFinalPos, m_object->RetPosition(0));
+ if ( dist < m_bmFinalDist ) return ERR_CONTINUE;
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ return ERR_STOP;
+ }
+
+ return ERR_CONTINUE;
+}
+
+
+// Tries the object is the target position.
+
+CObject* CTaskGoto::SearchTarget(Math::Vector pos, float margin)
+{
+ CObject *pObj, *pBest;
+ Math::Vector oPos;
+ float dist, min;
+ int i;
+
+ pBest = 0;
+ min = 1000000.0f;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue;
+ if ( pObj->RetTruck() != 0 ) continue; // object transtorted?
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(pos, oPos);
+
+ if ( dist <= margin && dist <= min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+
+ return pBest;
+}
+
+// Adjusts the target as a function of the object.
+// Returns true if it is cargo laying on the ground, which can be approached from any site.
+
+bool CTaskGoto::AdjustTarget(CObject* pObj, Math::Vector &pos, float &distance)
+{
+ ObjectType type;
+ Character* character;
+ Math::Matrix* mat;
+ Math::Vector goal;
+ float dist, suppl;
+
+ type = m_object->RetType();
+ if ( type == OBJECT_BEE ||
+ type == OBJECT_WORM )
+ {
+ pos = pObj->RetPosition(0);
+ return false; // single approach
+ }
+
+ type = pObj->RetType();
+
+ if ( type == OBJECT_FRET ||
+ type == OBJECT_STONE ||
+ type == OBJECT_URANIUM ||
+ type == OBJECT_METAL ||
+ type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC ||
+ type == OBJECT_BULLET ||
+ type == OBJECT_BBOX ||
+ type == OBJECT_KEYa ||
+ type == OBJECT_KEYb ||
+ type == OBJECT_KEYc ||
+ type == OBJECT_KEYd ||
+ type == OBJECT_TNT ||
+ type == OBJECT_SCRAP1 ||
+ type == OBJECT_SCRAP2 ||
+ type == OBJECT_SCRAP3 ||
+ type == OBJECT_SCRAP4 ||
+ type == OBJECT_SCRAP5 ||
+ type == OBJECT_BOMB ||
+ type == OBJECT_RUINmobilew1 ||
+ type == OBJECT_RUINmobilew2 ||
+ type == OBJECT_RUINmobilet1 ||
+ type == OBJECT_RUINmobilet2 ||
+ type == OBJECT_RUINmobiler1 ||
+ type == OBJECT_RUINmobiler2 )
+ {
+ pos = m_object->RetPosition(0);
+ goal = pObj->RetPosition(0);
+ dist = Math::Distance(goal, pos);
+ pos = (pos-goal)*(TAKE_DIST+distance)/dist + goal;
+ return true; // approach from all sites
+ }
+
+ if ( type == OBJECT_BASE )
+ {
+ pos = m_object->RetPosition(0);
+ goal = pObj->RetPosition(0);
+ dist = Math::Distance(goal, pos);
+ pos = (pos-goal)*(TAKE_DIST+distance)/dist + goal;
+ return true; // approach from all sites
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ 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_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr )
+ {
+ character = pObj->RetCharacter();
+ pos = character->posPower;
+ pos.x -= TAKE_DIST+TAKE_DIST_OTHER+distance;
+ mat = pObj->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+ return false; // single approach
+ }
+
+ if ( GetHotPoint(pObj, goal, true, distance, suppl) )
+ {
+ pos = goal;
+ distance += suppl;
+ return false; // single approach
+ }
+
+ pos = pObj->RetPosition(0);
+ distance = 0.0f;
+ return false; // single approach
+}
+
+// If you are on an object produced by a building (ore produced by derrick),
+// changes the position by report the building.
+
+bool CTaskGoto::AdjustBuilding(Math::Vector &pos, float margin, float &distance)
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ float dist, suppl;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue;
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+
+ if ( !GetHotPoint(pObj, oPos, false, 0.0f, suppl) ) continue;
+ dist = Math::DistanceProjected(pos, oPos);
+ if ( dist <= margin )
+ {
+ GetHotPoint(pObj, pos, true, distance, suppl);
+ distance += suppl;
+ return true;
+ }
+ }
+ return false;
+}
+
+// Returns the item or product or pose is something on a building.
+
+bool CTaskGoto::GetHotPoint(CObject *pObj, Math::Vector &pos,
+ bool bTake, float distance, float &suppl)
+{
+ ObjectType type;
+ Math::Matrix* mat;
+
+ pos = Math::Vector(0.0f, 0.0f, 0.0f);
+ suppl = 0.0f;
+ type = pObj->RetType();
+
+ if ( type == OBJECT_DERRICK )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 8.0f;
+ if ( bTake && distance != 0.0f ) suppl = 4.0f;
+ if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_CONVERT )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 0.0f;
+ if ( bTake && distance != 0.0f ) suppl = 4.0f;
+ if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_RESEARCH )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 10.0f;
+ if ( bTake && distance != 0.0f ) suppl = 2.5f;
+ if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_ENERGY )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 6.0f;
+ if ( bTake && distance != 0.0f ) suppl = 6.0f;
+ if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_TOWER )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 5.0f;
+ if ( bTake && distance != 0.0f ) suppl = 4.0f;
+ if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_LABO )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 6.0f;
+ if ( bTake && distance != 0.0f ) suppl = 6.0f;
+ if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_NUCLEAR )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 22.0f;
+ if ( bTake && distance != 0.0f ) suppl = 4.0f;
+ if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_FACTORY )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 4.0f;
+ if ( bTake && distance != 0.0f ) suppl = 6.0f;
+ if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_STATION )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 4.0f;
+ if ( bTake && distance != 0.0f ) suppl = 4.0f;
+ if ( bTake ) pos.x += distance;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_REPAIR )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 4.0f;
+ if ( bTake && distance != 0.0f ) suppl = 4.0f;
+ if ( bTake ) pos.x += distance;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_DESTROYER )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ pos.x += 0.0f;
+ if ( bTake && distance != 0.0f ) suppl = 4.0f;
+ if ( bTake ) pos.x += TAKE_DIST+distance+suppl;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ if ( type == OBJECT_PARA && m_physics->RetType() == TYPE_FLYING )
+ {
+ mat = pObj->RetWorldMatrix(0);
+ if ( bTake && distance != 0.0f ) suppl = 20.0f;
+ if ( bTake ) pos.x += distance+suppl;
+ pos = Transform(*mat, pos);
+ return true;
+ }
+
+ suppl = 0.0f;
+ return false;
+}
+
+
+// Seeks an object too close that he must flee.
+
+bool CTaskGoto::LeakSearch(Math::Vector &pos, float &delay)
+{
+ CObject *pObj, *pObstacle;
+ Math::Vector iPos, oPos, bPos;
+ float iRadius, oRadius, bRadius, dist, min, dir;
+ int i, j;
+
+ if ( !m_physics->RetLand() ) return false; // in flight?
+
+ m_object->GetCrashSphere(0, iPos, iRadius);
+
+ min = 100000.0f;
+ bRadius = 0.0f;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue;
+ if ( !pObj->RetActif() ) continue;
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ dist = Math::DistanceProjected(oPos, iPos);
+ if ( dist < min )
+ {
+ min = dist;
+ bPos = oPos;
+ bRadius = oRadius;
+ pObstacle = pObj;
+ }
+ }
+ }
+ if ( min > iRadius+bRadius+4.0f ) return false;
+
+ m_bLeakRecede = false;
+
+ dist = 4.0f;
+ dir = 1.0f;
+ if ( pObstacle->RetType() == OBJECT_FACTORY )
+ {
+ dist = 16.0f;
+ dir = -1.0f;
+ m_bLeakRecede = true; // simply recoils
+ }
+
+ pos = bPos;
+ delay = m_physics->RetLinTimeLength(dist, dir);
+ return true;
+}
+
+
+// Calculates the force of repulsion due to obstacles.
+// The vector length rendered is between 0 and 1.
+
+void CTaskGoto::ComputeRepulse(Math::Point &dir)
+{
+#if 0
+ Math::Vector iPos, oPos;
+ Math::Point repulse;
+ CObject *pObj;
+ float dist, iRadius, oRadius;
+ int i;
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+
+ m_object->GetCrashSphere(0, iPos, iRadius);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, m_goalObject);
+ if ( dist <= 1.0f ) continue;
+
+ pObj->GetGlobalSphere(oPos, oRadius);
+ oRadius += iRadius+m_physics->RetLinStopLength()*1.1f;
+ dist = Math::DistanceProjected(oPos, iPos);
+ if ( dist <= oRadius )
+ {
+ repulse.x = iPos.x-oPos.x;
+ repulse.y = iPos.z-oPos.z;
+
+//? dist = 0.2f-(0.2f*dist/oRadius);
+ dist = powf(dist/oRadius, 2.0f);
+ dist = 0.2f-0.2f*dist;
+ repulse.x *= dist;
+ repulse.y *= dist;
+//? repulse.x /= dist;
+//? repulse.y /= dist;
+
+ dir.x += repulse.x;
+ dir.y += repulse.y;
+ }
+ }
+#else
+ ObjectType iType, oType;
+ Math::Vector iPos, oPos;
+ Math::Point repulse;
+ CObject *pObj;
+ float gDist, add, addi, fac, dist, iRadius, oRadius;
+ int i, j;
+ bool bAlien;
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+
+ // The worm goes everywhere and through everything!
+ iType = m_object->RetType();
+ if ( iType == OBJECT_WORM ) return;
+
+ m_object->GetCrashSphere(0, iPos, iRadius);
+ gDist = Math::Distance(iPos, m_goal);
+
+ add = m_physics->RetLinStopLength()*1.1f; // braking distance
+ fac = 2.0f;
+
+ if ( iType == OBJECT_MOBILEwa ||
+ iType == OBJECT_MOBILEwc ||
+ iType == OBJECT_MOBILEwi ||
+ iType == OBJECT_MOBILEws ||
+ iType == OBJECT_MOBILEwt ) // wheels?
+ {
+ add = 5.0f;
+ fac = 1.5f;
+ }
+ if ( iType == OBJECT_MOBILEta ||
+ iType == OBJECT_MOBILEtc ||
+ iType == OBJECT_MOBILEti ||
+ iType == OBJECT_MOBILEts ||
+ iType == OBJECT_MOBILEtt ||
+ iType == OBJECT_MOBILEdr ) // caterpillars?
+ {
+ add = 4.0f;
+ fac = 1.5f;
+ }
+ if ( iType == OBJECT_MOBILEfa ||
+ iType == OBJECT_MOBILEfc ||
+ iType == OBJECT_MOBILEfi ||
+ iType == OBJECT_MOBILEfs ||
+ iType == OBJECT_MOBILEft ) // flying?
+ {
+ if ( m_physics->RetLand() )
+ {
+ add = 5.0f;
+ fac = 1.5f;
+ }
+ else
+ {
+ add = 10.0f;
+ fac = 1.5f;
+ }
+ }
+ if ( iType == OBJECT_MOBILEia ||
+ iType == OBJECT_MOBILEic ||
+ iType == OBJECT_MOBILEii ||
+ iType == OBJECT_MOBILEis ||
+ iType == OBJECT_MOBILEit ) // legs?
+ {
+ add = 4.0f;
+ fac = 1.5f;
+ }
+ if ( iType == OBJECT_BEE ) // wasp?
+ {
+ if ( m_physics->RetLand() )
+ {
+ add = 3.0f;
+ fac = 1.5f;
+ }
+ else
+ {
+ add = 5.0f;
+ fac = 1.5f;
+ }
+ }
+
+ bAlien = false;
+ if ( iType == OBJECT_MOTHER ||
+ iType == OBJECT_ANT ||
+ iType == OBJECT_SPIDER ||
+ iType == OBJECT_BEE ||
+ iType == OBJECT_WORM )
+ {
+ bAlien = true;
+ }
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ oType = pObj->RetType();
+
+ if ( oType == OBJECT_WORM ) continue;
+
+ if ( bAlien )
+ {
+ if ( oType == OBJECT_STONE ||
+ oType == OBJECT_URANIUM ||
+ oType == OBJECT_METAL ||
+ oType == OBJECT_POWER ||
+ oType == OBJECT_ATOMIC ||
+ oType == OBJECT_BULLET ||
+ oType == OBJECT_BBOX ||
+ oType == OBJECT_KEYa ||
+ oType == OBJECT_KEYb ||
+ oType == OBJECT_KEYc ||
+ oType == OBJECT_KEYd ||
+ oType == OBJECT_TNT ||
+ oType == OBJECT_SCRAP1 ||
+ oType == OBJECT_SCRAP2 ||
+ oType == OBJECT_SCRAP3 ||
+ oType == OBJECT_SCRAP4 ||
+ oType == OBJECT_SCRAP5 ||
+ oType == OBJECT_BOMB ||
+ (oType >= OBJECT_PLANT0 &&
+ oType <= OBJECT_PLANT19 ) ||
+ (oType >= OBJECT_MUSHROOM0 &&
+ oType <= OBJECT_MUSHROOM9 ) ) continue;
+ }
+
+ addi = add;
+ if ( iType == OBJECT_BEE &&
+ oType == OBJECT_BEE )
+ {
+ addi = 2.0f; // between wasps, do not annoy too much
+ }
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ if ( oPos.y-oRadius > iPos.y+iRadius ) continue;
+ if ( oPos.y+oRadius < iPos.y-iRadius ) continue;
+
+ dist = Math::Distance(oPos, m_goal);
+ if ( dist <= 1.0f ) continue; // on purpose?
+
+ oRadius += iRadius+addi;
+ dist = Math::DistanceProjected(oPos, iPos);
+ if ( dist > gDist ) continue; // beyond the goal?
+ if ( dist <= oRadius )
+ {
+ repulse.x = iPos.x-oPos.x;
+ repulse.y = iPos.z-oPos.z;
+
+ dist = powf(dist/oRadius, fac);
+ dist = 0.2f-0.2f*dist;
+ repulse.x *= dist;
+ repulse.y *= dist;
+
+ dir.x += repulse.x;
+ dir.y += repulse.y;
+ }
+ }
+ }
+#endif
+}
+
+// Calculates the force of vertical repulsion according to barriers.
+// The vector length is made​between -1 and 1.
+
+void CTaskGoto::ComputeFlyingRepulse(float &dir)
+{
+ ObjectType oType;
+ Math::Vector iPos, oPos;
+ CObject *pObj;
+ float add, fac, dist, iRadius, oRadius, repulse;
+ int i, j;
+
+ m_object->GetCrashSphere(0, iPos, iRadius);
+
+ add = 0.0f;
+ fac = 1.5f;
+ dir = 0.0f;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ oType = pObj->RetType();
+
+ if ( oType == OBJECT_WORM ) continue;
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ oRadius += iRadius+add;
+ dist = Math::DistanceProjected(oPos, iPos);
+ if ( dist <= oRadius )
+ {
+ repulse = iPos.y-oPos.y;
+
+ dist = powf(dist/oRadius, fac);
+ dist = 0.2f-0.2f*dist;
+ repulse *= dist;
+
+ dir += repulse;
+ }
+ }
+ }
+
+ if ( dir < -1.0f ) dir = -1.0f;
+ if ( dir > 1.0f ) dir = 1.0f;
+}
+
+
+
+// Among all of the following, seek if there is one allowing to go directly to the crow flies.
+// If yes, skip all the unnecessary intermediate points.
+
+int CTaskGoto::BeamShortcut()
+{
+ int i;
+
+ for ( i=m_bmTotal ; i>=m_bmIndex+2 ; i-- ) // tries from the last
+ {
+ if ( BitmapTestLine(m_bmPoints[m_bmIndex], m_bmPoints[i], 0.0f, false) )
+ {
+ return i; // bingo, found
+ }
+ }
+
+ return m_bmIndex+1; // simply goes to the next
+}
+
+// That's the big start.
+
+void CTaskGoto::BeamStart()
+{
+ Math::Vector min, max;
+
+ BitmapOpen();
+ BitmapObject();
+
+ min = m_object->RetPosition(0);
+ max = m_goal;
+ if ( min.x > max.x ) Math::Swap(min.x, max.x);
+ if ( min.z > max.z ) Math::Swap(min.z, max.z);
+ min.x -= 10.0f*BM_DIM_STEP;
+ min.z -= 10.0f*BM_DIM_STEP;
+ max.x += 10.0f*BM_DIM_STEP;
+ max.z += 10.0f*BM_DIM_STEP;
+ BitmapTerrain(min, max);
+
+ if ( LeakSearch(m_leakPos, m_leakDelay) )
+ {
+ m_phase = TGP_BEAMLEAK; // must first leak
+ m_leakTime = 0.0f;
+ }
+ else
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ BeamInit();
+ m_phase = TGP_BEAMSEARCH; // will seek the path
+ }
+}
+
+// Initialization before the first BeamSearch.
+
+void CTaskGoto::BeamInit()
+{
+ int i;
+
+ for ( i=0 ; i<MAXPOINTS ; i++ )
+ {
+ m_bmIter[i] = -1;
+ }
+ m_bmStep = 0;
+}
+
+// Calculates points and passes to go from start to goal.
+// Returns:
+// ERR_OK if it's good
+// ERR_GOTO_IMPOSSIBLE if impossible
+// ERR_GOTO_ITER if aborts because too many recursions
+// ERR_CONTINUE if not done yet
+// goalRadius: distance at which we must approach the goal
+
+Error CTaskGoto::BeamSearch(const Math::Vector &start, const Math::Vector &goal,
+ float goalRadius)
+{
+ float step, len;
+ int nbIter;
+
+ m_bmStep ++;
+
+ len = Math::DistanceProjected(start, goal);
+ step = len/5.0f;
+ if ( step < BM_DIM_STEP*2.1f ) step = BM_DIM_STEP*2.1f;
+ if ( step > 20.0f ) step = 20.0f;
+ nbIter = 200; // in order not to lower the framerate
+ m_bmIterCounter = 0;
+ return BeamExplore(start, start, goal, goalRadius, 165.0f*Math::PI/180.0f, 22, step, 0, nbIter);
+}
+
+// prevPos: previous position
+// curPos: current position
+// goalPos: position that seeks to achieve
+// angle: angle to the goal we explores
+// nbDiv: number of subdivisions being done with angle
+// step length of a step
+// i number of recursions made
+// nbIter maximum number of iterations you have the right to make before temporarily interrupt
+
+Error CTaskGoto::BeamExplore(const Math::Vector &prevPos, const Math::Vector &curPos,
+ const Math::Vector &goalPos, float goalRadius,
+ float angle, int nbDiv, float step,
+ int i, int nbIter)
+{
+ Math::Vector newPos;
+ Error ret;
+ int iDiv, iClear, iLar;
+
+ iLar = 0;
+ if ( i >= MAXPOINTS ) return ERR_GOTO_ITER; // too many recursions
+
+ if ( m_bmIter[i] == -1 )
+ {
+ m_bmIter[i] = 0;
+
+ if ( i == 0 )
+ {
+ m_bmPoints[i] = curPos;
+ }
+ else
+ {
+ if ( !BitmapTestLine(prevPos, curPos, angle/nbDiv, true) ) return ERR_GOTO_IMPOSSIBLE;
+
+ m_bmPoints[i] = curPos;
+
+ if ( Math::DistanceProjected(curPos, goalPos)-goalRadius <= step )
+ {
+ if ( goalRadius == 0.0f )
+ {
+ newPos = goalPos;
+ }
+ else
+ {
+ newPos = BeamPoint(curPos, goalPos, 0, Math::DistanceProjected(curPos, goalPos)-goalRadius);
+ }
+ if ( BitmapTestLine(curPos, newPos, angle/nbDiv, false) )
+ {
+ m_bmPoints[i+1] = newPos;
+ m_bmTotal = i+1;
+ return ERR_OK;
+ }
+ }
+ }
+ }
+
+ if ( iLar >= m_bmIter[i] )
+ {
+ newPos = BeamPoint(curPos, goalPos, 0, step);
+ ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter);
+ if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret;
+ m_bmIter[i] = iLar+1;
+ for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1;
+ m_bmIterCounter ++;
+ if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE;
+ }
+ iLar ++;
+
+ for ( iDiv=1 ; iDiv<=nbDiv ; iDiv++ )
+ {
+ if ( iLar >= m_bmIter[i] )
+ {
+ newPos = BeamPoint(curPos, goalPos, angle*iDiv/nbDiv, step);
+ ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter);
+ if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret;
+ m_bmIter[i] = iLar+1;
+ for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1;
+ m_bmIterCounter ++;
+ if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE;
+ }
+ iLar ++;
+
+ if ( iLar >= m_bmIter[i] )
+ {
+ newPos = BeamPoint(curPos, goalPos, -angle*iDiv/nbDiv, step);
+ ret = BeamExplore(curPos, newPos, goalPos, goalRadius, angle, nbDiv, step, i+1, nbIter);
+ if ( ret != ERR_GOTO_IMPOSSIBLE ) return ret;
+ m_bmIter[i] = iLar+1;
+ for ( iClear=i+1 ; iClear<=MAXPOINTS ; iClear++ ) m_bmIter[iClear] = -1;
+ m_bmIterCounter ++;
+ if ( m_bmIterCounter >= nbIter ) return ERR_CONTINUE;
+ }
+ iLar ++;
+ }
+
+ return ERR_GOTO_IMPOSSIBLE;
+}
+
+// Is a right "start-goal". Calculates the point located at the distance "step"
+// from the point "start" and an angle "angle" with the right.
+
+Math::Vector CTaskGoto::BeamPoint(const Math::Vector &startPoint,
+ const Math::Vector &goalPoint,
+ float angle, float step)
+{
+ Math::Vector resPoint;
+ float goalAngle;
+
+ goalAngle = Math::RotateAngle(goalPoint.x-startPoint.x, goalPoint.z-startPoint.z);
+
+ resPoint.x = startPoint.x + cosf(goalAngle+angle)*step;
+ resPoint.z = startPoint.z + sinf(goalAngle+angle)*step;
+ resPoint.y = 0.0f;
+
+ return resPoint;
+}
+
+// Displays a bitmap part.
+
+void CTaskGoto::BitmapDebug(const Math::Vector &min, const Math::Vector &max,
+ const Math::Vector &start, const Math::Vector &goal)
+{
+ int minx, miny, maxx, maxy, x, y, i ,n;
+ char s[2000];
+
+ minx = (int)((min.x+1600.0f)/BM_DIM_STEP);
+ miny = (int)((min.z+1600.0f)/BM_DIM_STEP);
+ maxx = (int)((max.x+1600.0f)/BM_DIM_STEP);
+ maxy = (int)((max.z+1600.0f)/BM_DIM_STEP);
+
+ if ( minx > maxx ) Math::Swap(minx, maxx);
+ if ( miny > maxy ) Math::Swap(miny, maxy);
+
+ OutputDebugString("Bitmap :\n");
+ for ( y=miny ; y<=maxy ; y++ )
+ {
+ s[0] = 0;
+ for ( x=minx ; x<=maxx ; x++ )
+ {
+ n = -1;
+ for ( i=0 ; i<=m_bmTotal ; i++ )
+ {
+ if ( x == (int)((m_bmPoints[i].x+1600.0f)/BM_DIM_STEP) &&
+ y == (int)((m_bmPoints[i].z+1600.0f)/BM_DIM_STEP) )
+ {
+ n = i;
+ break;
+ }
+ }
+
+ if ( BitmapTestDot(0, x,y) )
+ {
+ strcat(s, "o");
+ }
+ else
+ {
+ if ( BitmapTestDot(1, x,y) )
+ {
+ strcat(s, "-");
+ }
+ else
+ {
+ strcat(s, ".");
+ }
+ }
+
+ if ( x == (int)((start.x+1600.0f)/BM_DIM_STEP) &&
+ y == (int)((start.z+1600.0f)/BM_DIM_STEP) )
+ {
+ strcat(s, "s");
+ }
+ else
+ if ( x == (int)((goal.x+1600.0f)/BM_DIM_STEP) &&
+ y == (int)((goal.z+1600.0f)/BM_DIM_STEP) )
+ {
+ strcat(s, "g");
+ }
+ else
+ if ( n != -1 )
+ {
+ char ss[2];
+ ss[0] = 'A'+n;
+ ss[1] = 0;
+ strcat(s, ss);
+ }
+ else
+ {
+ strcat(s, " ");
+ }
+ }
+ strcat(s, "\n");
+ OutputDebugString(s);
+ }
+}
+
+// Tests if a path along a straight line is possible.
+
+bool CTaskGoto::BitmapTestLine(const Math::Vector &start, const Math::Vector &goal,
+ float stepAngle, bool bSecond)
+{
+ Math::Vector pos, inc;
+ float dist, step;
+ float distNoB2;
+ int i, max, x, y;
+
+ if ( m_bmArray == 0 ) return true;
+
+ dist = Math::DistanceProjected(start, goal);
+ if ( dist == 0.0f ) return true;
+ step = BM_DIM_STEP*0.5f;
+
+ inc.x = (goal.x-start.x)*step/dist;
+ inc.z = (goal.z-start.z)*step/dist;
+
+ pos = start;
+
+ if ( bSecond )
+ {
+ x = (int)((pos.x+1600.0f)/BM_DIM_STEP);
+ y = (int)((pos.z+1600.0f)/BM_DIM_STEP);
+ BitmapSetDot(1, x, y); // puts the flag as the starting point
+ }
+
+ max = (int)(dist/step);
+ if ( max == 0 ) max = 1;
+ distNoB2 = BM_DIM_STEP*sqrtf(2.0f)/sinf(stepAngle);
+ for ( i=0 ; i<max ; i++ )
+ {
+ if ( i == max-1 )
+ {
+ pos = goal; // tests the point of arrival
+ }
+ else
+ {
+ pos.x += inc.x;
+ pos.z += inc.z;
+ }
+
+ x = (int)((pos.x+1600.0f)/BM_DIM_STEP);
+ y = (int)((pos.z+1600.0f)/BM_DIM_STEP);
+
+ if ( bSecond )
+ {
+ if ( i > 2 && BitmapTestDot(1, x, y) ) return false;
+
+ if ( step*(i+1) > distNoB2 && i < max-2 )
+ {
+ BitmapSetDot(1, x, y);
+ }
+ }
+
+ if ( BitmapTestDot(0, x, y) ) return false;
+ }
+ return true;
+}
+
+// Adds the objects in the bitmap.
+
+void CTaskGoto::BitmapObject()
+{
+ CObject *pObj;
+ ObjectType type;
+ Math::Vector iPos, oPos;
+ float iRadius, oRadius, h;
+ int i, j;
+
+ m_object->GetCrashSphere(0, iPos, iRadius);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+
+ if ( pObj == m_object ) continue;
+ if ( pObj == m_bmFretObject ) continue;
+ if ( pObj->RetTruck() != 0 ) continue;
+
+ h = m_terrain->RetFloorLevel(pObj->RetPosition(0), false);
+ if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f )
+ {
+ h += m_altitude;
+ }
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ if ( m_physics->RetType() == TYPE_FLYING && m_altitude > 0.0f ) // flying?
+ {
+ if ( oPos.y-oRadius > h+8.0f ||
+ oPos.y+oRadius < h-8.0f ) continue;
+ }
+ else // crawling?
+ {
+ if ( oPos.y-oRadius > h+8.0f ) continue;
+ }
+
+ if ( type == OBJECT_PARA ) oRadius -= 2.0f;
+ BitmapSetCircle(oPos, oRadius+iRadius+4.0f);
+ }
+ }
+}
+
+// Adds a section of land in the bitmap.
+
+void CTaskGoto::BitmapTerrain(const Math::Vector &min, const Math::Vector &max)
+{
+ int minx, miny, maxx, maxy;
+
+ minx = (int)((min.x+1600.0f)/BM_DIM_STEP);
+ miny = (int)((min.z+1600.0f)/BM_DIM_STEP);
+ maxx = (int)((max.x+1600.0f)/BM_DIM_STEP);
+ maxy = (int)((max.z+1600.0f)/BM_DIM_STEP);
+
+ BitmapTerrain(minx, miny, maxx, maxy);
+}
+
+// Adds a section of land in the bitmap.
+
+void CTaskGoto::BitmapTerrain(int minx, int miny, int maxx, int maxy)
+{
+ ObjectType type;
+ Math::Vector p;
+ float aLimit, angle, h;
+ int x, y;
+ bool bAcceptWater, bFly;
+
+ if ( minx > maxx ) Math::Swap(minx, maxx);
+ if ( miny > maxy ) Math::Swap(miny, maxy);
+
+ if ( minx < 0 ) minx = 0;
+ if ( miny < 0 ) miny = 0;
+ if ( maxx > m_bmSize-1 ) maxx = m_bmSize-1;
+ if ( maxy > m_bmSize-1 ) maxy = m_bmSize-1;
+
+ if ( minx > m_bmMinX ) minx = m_bmMinX;
+ if ( miny > m_bmMinY ) miny = m_bmMinY;
+ if ( maxx < m_bmMaxX ) maxx = m_bmMaxX;
+ if ( maxy < m_bmMaxY ) maxy = m_bmMaxY;
+
+ if ( minx >= m_bmMinX && maxx <= m_bmMaxX &&
+ miny >= m_bmMinY && maxy <= m_bmMaxY ) return;
+
+ aLimit = 20.0f*Math::PI/180.0f;
+ bAcceptWater = false;
+ bFly = false;
+
+ type = m_object->RetType();
+
+ if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEtg ) // wheels?
+ {
+ aLimit = 20.0f*Math::PI/180.0f;
+ }
+
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts ) // caterpillars?
+ {
+ aLimit = 35.0f*Math::PI/180.0f;
+ }
+
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ) // large caterpillars?
+ {
+ aLimit = 35.0f*Math::PI/180.0f;
+ }
+
+ if ( type == OBJECT_MOBILEsa ) // submarine caterpillars?
+ {
+ aLimit = 35.0f*Math::PI/180.0f;
+ bAcceptWater = true;
+ }
+
+ if ( type == OBJECT_MOBILEdr ) // designer caterpillars?
+ {
+ aLimit = 35.0f*Math::PI/180.0f;
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEft ) // flying?
+ {
+ aLimit = 15.0f*Math::PI/180.0f;
+ bFly = true;
+ }
+
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILEii ) // insect legs?
+ {
+ aLimit = 60.0f*Math::PI/180.0f;
+ }
+
+ for ( y=miny ; y<=maxy ; y++ )
+ {
+ for ( x=minx ; x<=maxx ; x++ )
+ {
+ if ( x >= m_bmMinX && x <= m_bmMaxX &&
+ y >= m_bmMinY && y <= m_bmMaxY ) continue;
+
+ p.x = x*BM_DIM_STEP-1600.0f;
+ p.z = y*BM_DIM_STEP-1600.0f;
+
+ if ( bFly ) // flying robot?
+ {
+ h = m_terrain->RetFloorLevel(p, true);
+ if ( h >= m_terrain->RetFlyingMaxHeight()-5.0f )
+ {
+ BitmapSetDot(0, x, y);
+ }
+ continue;
+ }
+
+ if ( !bAcceptWater ) // not going underwater?
+ {
+ h = m_terrain->RetFloorLevel(p, true);
+ if ( h < m_water->RetLevel()-2.0f ) // under water (*)?
+ {
+//? BitmapSetDot(0, x, y);
+ BitmapSetCircle(p, BM_DIM_STEP*1.0f);
+ continue;
+ }
+ }
+
+ angle = m_terrain->RetFineSlope(p);
+ if ( angle > aLimit )
+ {
+ BitmapSetDot(0, x, y);
+ }
+ }
+ }
+
+ m_bmMinX = minx;
+ m_bmMinY = miny;
+ m_bmMaxX = maxx;
+ m_bmMaxY = maxy; // expanded rectangular area
+}
+
+// (*) Accepts that a robot is 50cm under water, for example Tropica 3!
+
+// Opens an empty bitmap.
+
+bool CTaskGoto::BitmapOpen()
+{
+ BitmapClose();
+
+ m_bmSize = (int)(3200.0f/BM_DIM_STEP);
+ m_bmArray = (unsigned char*)malloc(m_bmSize*m_bmSize/8*2);
+ ZeroMemory(m_bmArray, m_bmSize*m_bmSize/8*2);
+
+ m_bmOffset = m_bmSize/2;
+ m_bmLine = m_bmSize/8;
+
+ m_bmMinX = m_bmSize; // non-existent rectangular area
+ m_bmMinY = m_bmSize;
+ m_bmMaxX = 0;
+ m_bmMaxY = 0;
+
+ return true;
+}
+
+// Closes the bitmap.
+
+bool CTaskGoto::BitmapClose()
+{
+ free(m_bmArray);
+ m_bmArray = 0;
+ return true;
+}
+
+// Puts a circle in the bitmap.
+
+void CTaskGoto::BitmapSetCircle(const Math::Vector &pos, float radius)
+{
+ float d, r;
+ int cx, cy, ix, iy;
+
+ cx = (int)((pos.x+1600.0f)/BM_DIM_STEP);
+ cy = (int)((pos.z+1600.0f)/BM_DIM_STEP);
+ r = radius/BM_DIM_STEP;
+
+ for ( iy=cy-(int)r ; iy<=cy+(int)r ; iy++ )
+ {
+ for ( ix=cx-(int)r ; ix<=cx+(int)r ; ix++ )
+ {
+ d = Math::Point((float)(ix-cx), (float)(iy-cy)).Length();
+ if ( d > r ) continue;
+ BitmapSetDot(0, ix, iy);
+ }
+ }
+}
+
+// Removes a circle in the bitmap.
+
+void CTaskGoto::BitmapClearCircle(const Math::Vector &pos, float radius)
+{
+ float d, r;
+ int cx, cy, ix, iy;
+
+ cx = (int)((pos.x+1600.0f)/BM_DIM_STEP);
+ cy = (int)((pos.z+1600.0f)/BM_DIM_STEP);
+ r = radius/BM_DIM_STEP;
+
+ for ( iy=cy-(int)r ; iy<=cy+(int)r ; iy++ )
+ {
+ for ( ix=cx-(int)r ; ix<=cx+(int)r ; ix++ )
+ {
+ d = Math::Point((float)(ix-cx), (float)(iy-cy)).Length();
+ if ( d > r ) continue;
+ BitmapClearDot(0, ix, iy);
+ }
+ }
+}
+
+// Makes a point in the bitmap.
+// x:y: 0..m_bmSize-1
+
+void CTaskGoto::BitmapSetDot(int rank, int x, int y)
+{
+ if ( x < 0 || x >= m_bmSize ||
+ y < 0 || y >= m_bmSize ) return;
+
+ m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] |= (1<<x%8);
+}
+
+// Removes a point in the bitmap.
+// x:y: 0..m_bmSize-1
+
+void CTaskGoto::BitmapClearDot(int rank, int x, int y)
+{
+ if ( x < 0 || x >= m_bmSize ||
+ y < 0 || y >= m_bmSize ) return;
+
+ m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] &= ~(1<<x%8);
+}
+
+// Tests a point in the bitmap.
+// x:y: 0..m_bmSize-1
+
+bool CTaskGoto::BitmapTestDot(int rank, int x, int y)
+{
+ if ( x < 0 || x >= m_bmSize ||
+ y < 0 || y >= m_bmSize ) return false;
+
+ if ( x < m_bmMinX || x > m_bmMaxX ||
+ y < m_bmMinY || y > m_bmMaxY )
+ {
+ BitmapTerrain(x-10,y-10, x+10,y+10); // remade a layer
+ }
+
+ return m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] & (1<<x%8);
+}
+
+
diff --git a/src/object/task/taskgoto.h b/src/object/task/taskgoto.h
index ae83459..1382d4c 100644
--- a/src/object/task/taskgoto.h
+++ b/src/object/task/taskgoto.h
@@ -1,157 +1,157 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskgoto.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-const int MAXPOINTS = 500;
-
-
-
-enum TaskGotoGoal
-{
- TGG_DEFAULT = -1, // default mode
- TGG_STOP = 0, // goes to destination pausing with precision
- TGG_EXPRESS = 1, // goes to destination without stopping
-};
-
-enum TaskGotoCrash
-{
- TGC_DEFAULT = -1, // default mode
- TGC_HALT = 0, // stops if collision
- TGC_RIGHTLEFT = 1, // right-left
- TGC_LEFTRIGHT = 2, // left-right
- TGC_LEFT = 3, // left
- TGC_RIGHT = 4, // right
- TGC_BEAM = 5, // algorithm "sunlight"
-};
-
-
-enum TaskGotoPhase
-{
- TGP_ADVANCE = 1, // advance
- TGP_LAND = 2, // landed
- TGP_TURN = 3, // turns to finish
- TGP_MOVE = 4, // advance to finish
- TGP_CRWAIT = 5, // waits after collision
- TGP_CRTURN = 6, // turns right after collision
- TGP_CRADVANCE = 7, // advance to the right after collision
- TGP_CLWAIT = 8, // waits after collision
- TGP_CLTURN = 9, // turns left after collision
- TGP_CLADVANCE = 10, // advance to the left after collision
- TGP_BEAMLEAK = 11, // beam: leak (leaking)
- TGP_BEAMSEARCH = 12, // beam: search
- TGP_BEAMWCOLD = 13, // beam: expects cool reactor
- TGP_BEAMUP = 14, // beam: off
- TGP_BEAMGOTO = 15, // beam: goto dot list
- TGP_BEAMDOWN = 16, // beam: landed
-};
-
-
-
-class CTaskGoto : public CTask
-{
-public:
- CTaskGoto(CInstanceManager* iMan, CObject* object);
- ~CTaskGoto();
-
- bool EventProcess(const Event &event);
-
- Error Start(Math::Vector goal, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode);
- Error IsEnded();
-
-protected:
- CObject* WormSearch(Math::Vector &impact);
- void WormFrame(float rTime);
- CObject* SearchTarget(Math::Vector pos, float margin);
- bool AdjustTarget(CObject* pObj, Math::Vector &pos, float &distance);
- bool AdjustBuilding(Math::Vector &pos, float margin, float &distance);
- bool GetHotPoint(CObject *pObj, Math::Vector &pos, bool bTake, float distance, float &suppl);
- bool LeakSearch(Math::Vector &pos, float &delay);
- void ComputeRepulse(Math::Point &dir);
- void ComputeFlyingRepulse(float &dir);
-
- int BeamShortcut();
- void BeamStart();
- void BeamInit();
- Error BeamSearch(const Math::Vector &start, const Math::Vector &goal, float goalRadius);
- Error BeamExplore(const Math::Vector &prevPos, const Math::Vector &curPos, const Math::Vector &goalPos, float goalRadius, float angle, int nbDiv, float step, int i, int nbIter);
- Math::Vector BeamPoint(const Math::Vector &startPoint, const Math::Vector &goalPoint, float angle, float step);
-
- void BitmapDebug(const Math::Vector &min, const Math::Vector &max, const Math::Vector &start, const Math::Vector &goal);
- bool BitmapTestLine(const Math::Vector &start, const Math::Vector &goal, float stepAngle, bool bSecond);
- void BitmapObject();
- void BitmapTerrain(const Math::Vector &min, const Math::Vector &max);
- void BitmapTerrain(int minx, int miny, int maxx, int maxy);
- bool BitmapOpen();
- bool BitmapClose();
- void BitmapSetCircle(const Math::Vector &pos, float radius);
- void BitmapClearCircle(const Math::Vector &pos, float radius);
- void BitmapSetDot(int rank, int x, int y);
- void BitmapClearDot(int rank, int x, int y);
- bool BitmapTestDot(int rank, int x, int y);
-
-protected:
- Math::Vector m_goal;
- Math::Vector m_goalObject;
- float m_angle;
- float m_altitude;
- TaskGotoCrash m_crashMode;
- TaskGotoGoal m_goalMode;
- TaskGotoPhase m_phase;
- int m_try;
- Error m_error;
- bool m_bTake;
- float m_stopLength; // braking distance
- float m_time;
- Math::Vector m_pos;
- bool m_bWorm;
- bool m_bApprox;
- float m_wormLastTime;
- float m_lastDistance;
-
- int m_bmSize; // width or height of the table
- int m_bmOffset; // m_bmSize/2
- int m_bmLine; // increment line m_bmSize/8
- unsigned char* m_bmArray; // bit table
- int m_bmMinX, m_bmMinY;
- int m_bmMaxX, m_bmMaxY;
- int m_bmTotal; // number of points in m_bmPoints
- int m_bmIndex; // index in m_bmPoints
- Math::Vector m_bmPoints[MAXPOINTS+2];
- char m_bmIter[MAXPOINTS+2];
- int m_bmIterCounter;
- CObject* m_bmFretObject;
- float m_bmFinalMove; // final advance distance
- float m_bmFinalDist; // effective distance to advance
- Math::Vector m_bmFinalPos; // initial position before advance
- float m_bmTimeLimit;
- int m_bmStep;
- Math::Vector m_bmWatchDogPos;
- float m_bmWatchDogTime;
- Math::Vector m_leakPos; // initial position leak
- float m_leakDelay;
- float m_leakTime;
- bool m_bLeakRecede;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskgoto.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "math/vector.h"
+
+
+
+const int MAXPOINTS = 500;
+
+
+
+enum TaskGotoGoal
+{
+ TGG_DEFAULT = -1, // default mode
+ TGG_STOP = 0, // goes to destination pausing with precision
+ TGG_EXPRESS = 1, // goes to destination without stopping
+};
+
+enum TaskGotoCrash
+{
+ TGC_DEFAULT = -1, // default mode
+ TGC_HALT = 0, // stops if collision
+ TGC_RIGHTLEFT = 1, // right-left
+ TGC_LEFTRIGHT = 2, // left-right
+ TGC_LEFT = 3, // left
+ TGC_RIGHT = 4, // right
+ TGC_BEAM = 5, // algorithm "sunlight"
+};
+
+
+enum TaskGotoPhase
+{
+ TGP_ADVANCE = 1, // advance
+ TGP_LAND = 2, // landed
+ TGP_TURN = 3, // turns to finish
+ TGP_MOVE = 4, // advance to finish
+ TGP_CRWAIT = 5, // waits after collision
+ TGP_CRTURN = 6, // turns right after collision
+ TGP_CRADVANCE = 7, // advance to the right after collision
+ TGP_CLWAIT = 8, // waits after collision
+ TGP_CLTURN = 9, // turns left after collision
+ TGP_CLADVANCE = 10, // advance to the left after collision
+ TGP_BEAMLEAK = 11, // beam: leak (leaking)
+ TGP_BEAMSEARCH = 12, // beam: search
+ TGP_BEAMWCOLD = 13, // beam: expects cool reactor
+ TGP_BEAMUP = 14, // beam: off
+ TGP_BEAMGOTO = 15, // beam: goto dot list
+ TGP_BEAMDOWN = 16, // beam: landed
+};
+
+
+
+class CTaskGoto : public CTask
+{
+public:
+ CTaskGoto(CInstanceManager* iMan, CObject* object);
+ ~CTaskGoto();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(Math::Vector goal, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode);
+ Error IsEnded();
+
+protected:
+ CObject* WormSearch(Math::Vector &impact);
+ void WormFrame(float rTime);
+ CObject* SearchTarget(Math::Vector pos, float margin);
+ bool AdjustTarget(CObject* pObj, Math::Vector &pos, float &distance);
+ bool AdjustBuilding(Math::Vector &pos, float margin, float &distance);
+ bool GetHotPoint(CObject *pObj, Math::Vector &pos, bool bTake, float distance, float &suppl);
+ bool LeakSearch(Math::Vector &pos, float &delay);
+ void ComputeRepulse(Math::Point &dir);
+ void ComputeFlyingRepulse(float &dir);
+
+ int BeamShortcut();
+ void BeamStart();
+ void BeamInit();
+ Error BeamSearch(const Math::Vector &start, const Math::Vector &goal, float goalRadius);
+ Error BeamExplore(const Math::Vector &prevPos, const Math::Vector &curPos, const Math::Vector &goalPos, float goalRadius, float angle, int nbDiv, float step, int i, int nbIter);
+ Math::Vector BeamPoint(const Math::Vector &startPoint, const Math::Vector &goalPoint, float angle, float step);
+
+ void BitmapDebug(const Math::Vector &min, const Math::Vector &max, const Math::Vector &start, const Math::Vector &goal);
+ bool BitmapTestLine(const Math::Vector &start, const Math::Vector &goal, float stepAngle, bool bSecond);
+ void BitmapObject();
+ void BitmapTerrain(const Math::Vector &min, const Math::Vector &max);
+ void BitmapTerrain(int minx, int miny, int maxx, int maxy);
+ bool BitmapOpen();
+ bool BitmapClose();
+ void BitmapSetCircle(const Math::Vector &pos, float radius);
+ void BitmapClearCircle(const Math::Vector &pos, float radius);
+ void BitmapSetDot(int rank, int x, int y);
+ void BitmapClearDot(int rank, int x, int y);
+ bool BitmapTestDot(int rank, int x, int y);
+
+protected:
+ Math::Vector m_goal;
+ Math::Vector m_goalObject;
+ float m_angle;
+ float m_altitude;
+ TaskGotoCrash m_crashMode;
+ TaskGotoGoal m_goalMode;
+ TaskGotoPhase m_phase;
+ int m_try;
+ Error m_error;
+ bool m_bTake;
+ float m_stopLength; // braking distance
+ float m_time;
+ Math::Vector m_pos;
+ bool m_bWorm;
+ bool m_bApprox;
+ float m_wormLastTime;
+ float m_lastDistance;
+
+ int m_bmSize; // width or height of the table
+ int m_bmOffset; // m_bmSize/2
+ int m_bmLine; // increment line m_bmSize/8
+ unsigned char* m_bmArray; // bit table
+ int m_bmMinX, m_bmMinY;
+ int m_bmMaxX, m_bmMaxY;
+ int m_bmTotal; // number of points in m_bmPoints
+ int m_bmIndex; // index in m_bmPoints
+ Math::Vector m_bmPoints[MAXPOINTS+2];
+ char m_bmIter[MAXPOINTS+2];
+ int m_bmIterCounter;
+ CObject* m_bmFretObject;
+ float m_bmFinalMove; // final advance distance
+ float m_bmFinalDist; // effective distance to advance
+ Math::Vector m_bmFinalPos; // initial position before advance
+ float m_bmTimeLimit;
+ int m_bmStep;
+ Math::Vector m_bmWatchDogPos;
+ float m_bmWatchDogTime;
+ Math::Vector m_leakPos; // initial position leak
+ float m_leakDelay;
+ float m_leakTime;
+ bool m_bLeakRecede;
+};
+
diff --git a/src/object/task/taskgungoal.cpp b/src/object/task/taskgungoal.cpp
index 0635b97..e259ca8 100644
--- a/src/object/task/taskgungoal.cpp
+++ b/src/object/task/taskgungoal.cpp
@@ -1,149 +1,149 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskgungoal.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskgungoal.h"
-
-#include "object/object.h"
-
-
-
-
-// Object's constructor.
-
-CTaskGunGoal::CTaskGunGoal(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskGunGoal::~CTaskGunGoal()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskGunGoal::EventProcess(const Event &event)
-{
- float dir;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_progress += event.rTime*m_speed;
-
- if ( m_progress < 1.0f )
- {
- dir = m_initialDirV + (m_finalDirV-m_initialDirV)*m_progress;
- }
- else
- {
- dir = m_finalDirV;
- }
- m_object->SetGunGoalV(dir);
-
- if ( m_progress < 1.0f )
- {
- dir = m_initialDirH + (m_finalDirH-m_initialDirH)*m_progress;
- }
- else
- {
- dir = m_finalDirH;
- }
- m_object->SetGunGoalH(dir);
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskGunGoal::Start(float dirV, float dirH)
-{
- float speedV, speedH;
- int i;
-
- m_initialDirV = m_object->RetGunGoalV();
- m_object->SetGunGoalV(dirV);
- m_finalDirV = m_object->RetGunGoalV(); // possible direction
- m_object->SetGunGoalV(m_initialDirV); // gives initial direction
-
- if ( m_finalDirV == m_initialDirV )
- {
- speedV = 100.0f;
- }
- else
- {
- speedV = 1.0f/(fabs(m_finalDirV-m_initialDirV)*1.0f);
- }
-
- m_initialDirH = m_object->RetGunGoalH();
- m_object->SetGunGoalH(dirH);
- m_finalDirH = m_object->RetGunGoalH(); // possible direction
- m_object->SetGunGoalH(m_initialDirH); // gives initial direction
-
- if ( m_finalDirH == m_initialDirH )
- {
- speedH = 100.0f;
- }
- else
- {
- speedH = 1.0f/(fabs(m_finalDirH-m_initialDirH)*1.0f);
- }
-
- m_speed = Math::Min(speedV, speedH);
-
- if ( m_finalDirV != m_initialDirV ||
- m_finalDirH != m_initialDirH )
- {
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.3f, 1.5f, true);
- m_sound->AddEnvelope(i, 0.3f, 1.5f, 1.0f/m_speed, SOPER_STOP);
- }
-
- m_progress = 0.0f;
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskGunGoal::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
-
- if ( m_initialDirV == m_finalDirV &&
- m_initialDirH == m_finalDirH ) return ERR_STOP;
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- m_object->SetGunGoalV(m_finalDirV);
- m_object->SetGunGoalH(m_finalDirH);
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskGunGoal::Abort()
-{
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskgungoal.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskgungoal.h"
+
+#include "object/object.h"
+
+
+
+
+// Object's constructor.
+
+CTaskGunGoal::CTaskGunGoal(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+}
+
+// Object's destructor.
+
+CTaskGunGoal::~CTaskGunGoal()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskGunGoal::EventProcess(const Event &event)
+{
+ float dir;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_progress += event.rTime*m_speed;
+
+ if ( m_progress < 1.0f )
+ {
+ dir = m_initialDirV + (m_finalDirV-m_initialDirV)*m_progress;
+ }
+ else
+ {
+ dir = m_finalDirV;
+ }
+ m_object->SetGunGoalV(dir);
+
+ if ( m_progress < 1.0f )
+ {
+ dir = m_initialDirH + (m_finalDirH-m_initialDirH)*m_progress;
+ }
+ else
+ {
+ dir = m_finalDirH;
+ }
+ m_object->SetGunGoalH(dir);
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskGunGoal::Start(float dirV, float dirH)
+{
+ float speedV, speedH;
+ int i;
+
+ m_initialDirV = m_object->RetGunGoalV();
+ m_object->SetGunGoalV(dirV);
+ m_finalDirV = m_object->RetGunGoalV(); // possible direction
+ m_object->SetGunGoalV(m_initialDirV); // gives initial direction
+
+ if ( m_finalDirV == m_initialDirV )
+ {
+ speedV = 100.0f;
+ }
+ else
+ {
+ speedV = 1.0f/(fabs(m_finalDirV-m_initialDirV)*1.0f);
+ }
+
+ m_initialDirH = m_object->RetGunGoalH();
+ m_object->SetGunGoalH(dirH);
+ m_finalDirH = m_object->RetGunGoalH(); // possible direction
+ m_object->SetGunGoalH(m_initialDirH); // gives initial direction
+
+ if ( m_finalDirH == m_initialDirH )
+ {
+ speedH = 100.0f;
+ }
+ else
+ {
+ speedH = 1.0f/(fabs(m_finalDirH-m_initialDirH)*1.0f);
+ }
+
+ m_speed = Math::Min(speedV, speedH);
+
+ if ( m_finalDirV != m_initialDirV ||
+ m_finalDirH != m_initialDirH )
+ {
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.3f, 1.5f, true);
+ m_sound->AddEnvelope(i, 0.3f, 1.5f, 1.0f/m_speed, SOPER_STOP);
+ }
+
+ m_progress = 0.0f;
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskGunGoal::IsEnded()
+{
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+
+ if ( m_initialDirV == m_finalDirV &&
+ m_initialDirH == m_finalDirH ) return ERR_STOP;
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ m_object->SetGunGoalV(m_finalDirV);
+ m_object->SetGunGoalH(m_finalDirH);
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskGunGoal::Abort()
+{
+ return true;
+}
+
diff --git a/src/object/task/taskgungoal.h b/src/object/task/taskgungoal.h
index 4759cbc..0c063d1 100644
--- a/src/object/task/taskgungoal.h
+++ b/src/object/task/taskgungoal.h
@@ -1,48 +1,48 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskgungoal.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskGunGoal : public CTask
-{
-public:
- CTaskGunGoal(CInstanceManager* iMan, CObject* object);
- ~CTaskGunGoal();
-
- bool EventProcess(const Event &event);
-
- Error Start(float dirV, float dirH);
- Error IsEnded();
- bool Abort();
-
-protected:
-
-protected:
- float m_progress;
- float m_speed;
- float m_initialDirV; // initial direction
- float m_finalDirV; // direction to reach
- float m_initialDirH; // initial direction
- float m_finalDirH; // direction to reach
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskgungoal.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+
+
+
+class CTaskGunGoal : public CTask
+{
+public:
+ CTaskGunGoal(CInstanceManager* iMan, CObject* object);
+ ~CTaskGunGoal();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(float dirV, float dirH);
+ Error IsEnded();
+ bool Abort();
+
+protected:
+
+protected:
+ float m_progress;
+ float m_speed;
+ float m_initialDirV; // initial direction
+ float m_finalDirV; // direction to reach
+ float m_initialDirH; // initial direction
+ float m_finalDirH; // direction to reach
+};
+
diff --git a/src/object/task/taskinfo.cpp b/src/object/task/taskinfo.cpp
index cfcbe93..6d1f486 100644
--- a/src/object/task/taskinfo.cpp
+++ b/src/object/task/taskinfo.cpp
@@ -1,219 +1,219 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskinfo.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskinfo.h"
-
-#include "common/iman.h"
-#include "old/particule.h"
-#include "object/auto/autoinfo.h"
-
-
-
-
-
-// Object's constructor.
-
-CTaskInfo::CTaskInfo(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskInfo::~CTaskInfo()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskInfo::EventProcess(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_progress += event.rTime*m_speed; // other advance
- m_time += event.rTime;
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskInfo::Start(char *name, float value, float power, bool bSend)
-{
- CObject* pInfo;
- CAutoInfo* pAuto;
- Math::Vector pos, goal;
- Info info;
- int i, total, op;
-
- m_bError = true;
- m_object->SetInfoReturn(NAN);
-
- pInfo = SearchInfo(power); // seeks terminal
- if ( pInfo == 0 )
- {
- return ERR_INFO_NULL;
- }
-
- pAuto = (CAutoInfo*)pInfo->RetAuto();
- if ( pAuto == 0 )
- {
- return ERR_INFO_NULL;
- }
-
- op = 1; // transmission impossible
- if ( bSend ) // send?
- {
- total = pInfo->RetInfoTotal();
- for ( i=0 ; i<total ; i++ )
- {
- info = pInfo->RetInfo(i);
- if ( strcmp(info.name, name) == 0 )
- {
- info.value = value;
- pInfo->SetInfo(i, info);
- break;
- }
- }
- if ( i == total )
- {
- if ( total < OBJECTMAXINFO )
- {
- strcpy(info.name, name);
- info.value = value;
- pInfo->SetInfo(total, info);
- op = 2; // start of reception (for terminal)
- }
- }
- else
- {
- op = 2; // start of reception (for terminal)
- }
- }
- else // receive?
- {
- total = pInfo->RetInfoTotal();
- for ( i=0 ; i<total ; i++ )
- {
- info = pInfo->RetInfo(i);
- if ( strcmp(info.name, name) == 0 )
- {
- m_object->SetInfoReturn(info.value);
- break;
- }
- }
- if ( i < total )
- {
- op = 0; // beginning of transmission (for terminal)
- }
- }
-
- pAuto->Start(op);
-
- if ( op == 0 ) // transmission?
- {
- pos = pInfo->RetPosition(0);
- pos.y += 9.5f;
- goal = m_object->RetPosition(0);
- goal.y += 4.0f;
- m_particule->CreateRay(pos, goal, PARTIRAY3, Math::Point(2.0f, 2.0f), 1.0f);
- }
- if ( op == 2 ) // reception?
- {
- goal = pInfo->RetPosition(0);
- goal.y += 9.5f;
- pos = m_object->RetPosition(0);
- pos.y += 4.0f;
- m_particule->CreateRay(pos, goal, PARTIRAY3, Math::Point(2.0f, 2.0f), 1.0f);
- }
-
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- m_time = 0.0f;
-
- m_bError = false; // ok
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskInfo::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskInfo::Abort()
-{
- return true;
-}
-
-
-// Seeks the nearest information terminal.
-
-CObject* CTaskInfo::SearchInfo(float power)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float dist, min;
- int i;
-
- iPos = m_object->RetPosition(0);
-
- min = 100000.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_INFO ) continue;
-
- if ( !pObj->RetActif() ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, iPos);
- if ( dist > power ) continue; // too far?
- if ( dist < min )
- {
- min = dist;
- pBest = pObj;
- }
- }
-
- return pBest;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskinfo.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskinfo.h"
+
+#include "common/iman.h"
+#include "old/particule.h"
+#include "object/auto/autoinfo.h"
+
+
+
+
+
+// Object's constructor.
+
+CTaskInfo::CTaskInfo(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+}
+
+// Object's destructor.
+
+CTaskInfo::~CTaskInfo()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskInfo::EventProcess(const Event &event)
+{
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ m_progress += event.rTime*m_speed; // other advance
+ m_time += event.rTime;
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskInfo::Start(char *name, float value, float power, bool bSend)
+{
+ CObject* pInfo;
+ CAutoInfo* pAuto;
+ Math::Vector pos, goal;
+ Info info;
+ int i, total, op;
+
+ m_bError = true;
+ m_object->SetInfoReturn(NAN);
+
+ pInfo = SearchInfo(power); // seeks terminal
+ if ( pInfo == 0 )
+ {
+ return ERR_INFO_NULL;
+ }
+
+ pAuto = (CAutoInfo*)pInfo->RetAuto();
+ if ( pAuto == 0 )
+ {
+ return ERR_INFO_NULL;
+ }
+
+ op = 1; // transmission impossible
+ if ( bSend ) // send?
+ {
+ total = pInfo->RetInfoTotal();
+ for ( i=0 ; i<total ; i++ )
+ {
+ info = pInfo->RetInfo(i);
+ if ( strcmp(info.name, name) == 0 )
+ {
+ info.value = value;
+ pInfo->SetInfo(i, info);
+ break;
+ }
+ }
+ if ( i == total )
+ {
+ if ( total < OBJECTMAXINFO )
+ {
+ strcpy(info.name, name);
+ info.value = value;
+ pInfo->SetInfo(total, info);
+ op = 2; // start of reception (for terminal)
+ }
+ }
+ else
+ {
+ op = 2; // start of reception (for terminal)
+ }
+ }
+ else // receive?
+ {
+ total = pInfo->RetInfoTotal();
+ for ( i=0 ; i<total ; i++ )
+ {
+ info = pInfo->RetInfo(i);
+ if ( strcmp(info.name, name) == 0 )
+ {
+ m_object->SetInfoReturn(info.value);
+ break;
+ }
+ }
+ if ( i < total )
+ {
+ op = 0; // beginning of transmission (for terminal)
+ }
+ }
+
+ pAuto->Start(op);
+
+ if ( op == 0 ) // transmission?
+ {
+ pos = pInfo->RetPosition(0);
+ pos.y += 9.5f;
+ goal = m_object->RetPosition(0);
+ goal.y += 4.0f;
+ m_particule->CreateRay(pos, goal, PARTIRAY3, Math::Point(2.0f, 2.0f), 1.0f);
+ }
+ if ( op == 2 ) // reception?
+ {
+ goal = pInfo->RetPosition(0);
+ goal.y += 9.5f;
+ pos = m_object->RetPosition(0);
+ pos.y += 4.0f;
+ m_particule->CreateRay(pos, goal, PARTIRAY3, Math::Point(2.0f, 2.0f), 1.0f);
+ }
+
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ m_time = 0.0f;
+
+ m_bError = false; // ok
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskInfo::IsEnded()
+{
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+ m_progress = 0.0f;
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskInfo::Abort()
+{
+ return true;
+}
+
+
+// Seeks the nearest information terminal.
+
+CObject* CTaskInfo::SearchInfo(float power)
+{
+ CObject *pObj, *pBest;
+ Math::Vector iPos, oPos;
+ ObjectType type;
+ float dist, min;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+
+ min = 100000.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_INFO ) continue;
+
+ if ( !pObj->RetActif() ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, iPos);
+ if ( dist > power ) continue; // too far?
+ if ( dist < min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+
+ return pBest;
+}
+
diff --git a/src/object/task/taskinfo.h b/src/object/task/taskinfo.h
index 8f6e4f2..21a4392 100644
--- a/src/object/task/taskinfo.h
+++ b/src/object/task/taskinfo.h
@@ -1,47 +1,47 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskinfo.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskInfo : public CTask
-{
-public:
- CTaskInfo(CInstanceManager* iMan, CObject* object);
- ~CTaskInfo();
-
- bool EventProcess(const Event &event);
-
- Error Start(char *name, float value, float power, bool bSend);
- Error IsEnded();
- bool Abort();
-
-protected:
- CObject* SearchInfo(float power);
-
-protected:
- float m_progress;
- float m_speed;
- float m_time;
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskinfo.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+
+
+
+class CTaskInfo : public CTask
+{
+public:
+ CTaskInfo(CInstanceManager* iMan, CObject* object);
+ ~CTaskInfo();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(char *name, float value, float power, bool bSend);
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ CObject* SearchInfo(float power);
+
+protected:
+ float m_progress;
+ float m_speed;
+ float m_time;
+ bool m_bError;
+};
+
diff --git a/src/object/task/taskmanager.cpp b/src/object/task/taskmanager.cpp
index f6f8b97..d81fb5b 100644
--- a/src/object/task/taskmanager.cpp
+++ b/src/object/task/taskmanager.cpp
@@ -1,278 +1,278 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskmanager.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskmanager.h"
-
-#include "common/iman.h"
-#include "object/task/taskwait.h"
-#include "object/task/taskadvance.h"
-#include "object/task/taskturn.h"
-#include "object/task/tasktake.h"
-#include "object/task/taskbuild.h"
-#include "object/task/tasksearch.h"
-#include "object/task/taskterraform.h"
-#include "object/task/taskpen.h"
-#include "object/task/taskrecover.h"
-#include "object/task/taskinfo.h"
-#include "object/task/taskfire.h"
-#include "object/task/taskfireant.h"
-#include "object/task/taskgungoal.h"
-#include "object/task/taskspiderexplo.h"
-#include "object/task/taskreset.h"
-
-
-
-
-// Object's constructor.
-
-CTaskManager::CTaskManager(CInstanceManager* iMan, CObject* object)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_TASKMANAGER, this, 100);
-
- m_task = 0;
- m_object = object;
- m_bPilot = false;
-}
-
-// Object's destructor.
-
-CTaskManager::~CTaskManager()
-{
- delete m_task;
-}
-
-
-
-// Waits for a while.
-
-Error CTaskManager::StartTaskWait(float time)
-{
- m_task = new CTaskWait(m_iMan, m_object);
- return ((CTaskWait*)m_task)->Start(time);
-}
-
-// Advance straight ahead a certain distance.
-
-Error CTaskManager::StartTaskAdvance(float length)
-{
- m_task = new CTaskAdvance(m_iMan, m_object);
- return ((CTaskAdvance*)m_task)->Start(length);
-}
-
-// Turns through an certain angle.
-
-Error CTaskManager::StartTaskTurn(float angle)
-{
- m_task = new CTaskTurn(m_iMan, m_object);
- return ((CTaskTurn*)m_task)->Start(angle);
-}
-
-// Reaches a given position.
-
-Error CTaskManager::StartTaskGoto(Math::Vector pos, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode)
-{
- m_task = new CTaskGoto(m_iMan, m_object);
- return ((CTaskGoto*)m_task)->Start(pos, altitude, goalMode, crashMode);
-}
-
-// Move the manipulator arm.
-
-Error CTaskManager::StartTaskTake()
-{
- m_task = new CTaskTake(m_iMan, m_object);
- return ((CTaskTake*)m_task)->Start();
-}
-
-// Move the manipulator arm.
-
-Error CTaskManager::StartTaskManip(TaskManipOrder order, TaskManipArm arm)
-{
- m_task = new CTaskManip(m_iMan, m_object);
- return ((CTaskManip*)m_task)->Start(order, arm);
-}
-
-// Puts or removes a flag.
-
-Error CTaskManager::StartTaskFlag(TaskFlagOrder order, int rank)
-{
- m_task = new CTaskFlag(m_iMan, m_object);
- return ((CTaskFlag*)m_task)->Start(order, rank);
-}
-
-// Builds a building.
-
-Error CTaskManager::StartTaskBuild(ObjectType type)
-{
- m_task = new CTaskBuild(m_iMan, m_object);
- return ((CTaskBuild*)m_task)->Start(type);
-}
-
-// Probe the ground.
-
-Error CTaskManager::StartTaskSearch()
-{
- m_task = new CTaskSearch(m_iMan, m_object);
- return ((CTaskSearch*)m_task)->Start();
-}
-
-// Reads an information terminal.
-
-Error CTaskManager::StartTaskInfo(char *name, float value, float power, bool bSend)
-{
- m_task = new CTaskInfo(m_iMan, m_object);
- return ((CTaskInfo*)m_task)->Start(name, value, power, bSend);
-}
-
-// Terraforms the ground.
-
-Error CTaskManager::StartTaskTerraform()
-{
- m_task = new CTaskTerraform(m_iMan, m_object);
- return ((CTaskTerraform*)m_task)->Start();
-}
-
-// Changes the pencil.
-
-Error CTaskManager::StartTaskPen(bool bDown, int color)
-{
- m_task = new CTaskPen(m_iMan, m_object);
- return ((CTaskPen*)m_task)->Start(bDown, color);
-}
-
-// Recovers a ruin.
-
-Error CTaskManager::StartTaskRecover()
-{
- m_task = new CTaskRecover(m_iMan, m_object);
- return ((CTaskRecover*)m_task)->Start();
-}
-
-// Deploys the shield.
-
-Error CTaskManager::StartTaskShield(TaskShieldMode mode, float delay)
-{
- if ( mode == TSM_UP )
- {
- m_task = new CTaskShield(m_iMan, m_object);
- return ((CTaskShield*)m_task)->Start(mode, delay);
- }
- if ( mode == TSM_DOWN && m_task != 0 )
- {
- return ((CTaskShield*)m_task)->Start(mode, delay);
- }
- if ( mode == TSM_UPDATE && m_task != 0 )
- {
- return ((CTaskShield*)m_task)->Start(mode, delay);
- }
- return ERR_GENERIC;
-}
-
-// Shoots.
-
-Error CTaskManager::StartTaskFire(float delay)
-{
- m_bPilot = true;
- m_task = new CTaskFire(m_iMan, m_object);
- return ((CTaskFire*)m_task)->Start(delay);
-}
-
-// Shoots with the ant.
-
-Error CTaskManager::StartTaskFireAnt(Math::Vector impact)
-{
- m_task = new CTaskFireAnt(m_iMan, m_object);
- return ((CTaskFireAnt*)m_task)->Start(impact);
-}
-
-// Adjusts higher.
-
-Error CTaskManager::StartTaskGunGoal(float dirV, float dirH)
-{
- m_task = new CTaskGunGoal(m_iMan, m_object);
- return ((CTaskGunGoal*)m_task)->Start(dirV, dirH);
-}
-
-// Suicide of the spider.
-
-Error CTaskManager::StartTaskSpiderExplo()
-{
- m_task = new CTaskSpiderExplo(m_iMan, m_object);
- return ((CTaskSpiderExplo*)m_task)->Start();
-}
-
-// Reset.
-
-Error CTaskManager::StartTaskReset(Math::Vector goal, Math::Vector angle)
-{
- m_task = new CTaskReset(m_iMan, m_object);
- return ((CTaskReset*)m_task)->Start(goal, angle);
-}
-
-
-
-
-
-// Management of an event.
-
-bool CTaskManager::EventProcess(const Event &event)
-{
- if ( m_task == 0 ) return false;
- return m_task->EventProcess(event);
-}
-
-
-// Indicates whether the action is finished.
-
-Error CTaskManager::IsEnded()
-{
- if ( m_task == 0 ) return ERR_GENERIC;
- return m_task->IsEnded();
-}
-
-
-// Indicates whether the action is pending.
-
-bool CTaskManager::IsBusy()
-{
- if ( m_task == 0 ) return false;
- return m_task->IsBusy();
-}
-
-
-// Indicates whether it is possible to control the robot
-// during the execution of the current task.
-
-bool CTaskManager::IsPilot()
-{
- return m_bPilot;
-}
-
-
-// Suddenly ends the current action.
-
-bool CTaskManager::Abort()
-{
- if ( m_task == 0 ) return false;
- return m_task->Abort();
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskmanager.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskmanager.h"
+
+#include "common/iman.h"
+#include "object/task/taskwait.h"
+#include "object/task/taskadvance.h"
+#include "object/task/taskturn.h"
+#include "object/task/tasktake.h"
+#include "object/task/taskbuild.h"
+#include "object/task/tasksearch.h"
+#include "object/task/taskterraform.h"
+#include "object/task/taskpen.h"
+#include "object/task/taskrecover.h"
+#include "object/task/taskinfo.h"
+#include "object/task/taskfire.h"
+#include "object/task/taskfireant.h"
+#include "object/task/taskgungoal.h"
+#include "object/task/taskspiderexplo.h"
+#include "object/task/taskreset.h"
+
+
+
+
+// Object's constructor.
+
+CTaskManager::CTaskManager(CInstanceManager* iMan, CObject* object)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_TASKMANAGER, this, 100);
+
+ m_task = 0;
+ m_object = object;
+ m_bPilot = false;
+}
+
+// Object's destructor.
+
+CTaskManager::~CTaskManager()
+{
+ delete m_task;
+}
+
+
+
+// Waits for a while.
+
+Error CTaskManager::StartTaskWait(float time)
+{
+ m_task = new CTaskWait(m_iMan, m_object);
+ return ((CTaskWait*)m_task)->Start(time);
+}
+
+// Advance straight ahead a certain distance.
+
+Error CTaskManager::StartTaskAdvance(float length)
+{
+ m_task = new CTaskAdvance(m_iMan, m_object);
+ return ((CTaskAdvance*)m_task)->Start(length);
+}
+
+// Turns through an certain angle.
+
+Error CTaskManager::StartTaskTurn(float angle)
+{
+ m_task = new CTaskTurn(m_iMan, m_object);
+ return ((CTaskTurn*)m_task)->Start(angle);
+}
+
+// Reaches a given position.
+
+Error CTaskManager::StartTaskGoto(Math::Vector pos, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode)
+{
+ m_task = new CTaskGoto(m_iMan, m_object);
+ return ((CTaskGoto*)m_task)->Start(pos, altitude, goalMode, crashMode);
+}
+
+// Move the manipulator arm.
+
+Error CTaskManager::StartTaskTake()
+{
+ m_task = new CTaskTake(m_iMan, m_object);
+ return ((CTaskTake*)m_task)->Start();
+}
+
+// Move the manipulator arm.
+
+Error CTaskManager::StartTaskManip(TaskManipOrder order, TaskManipArm arm)
+{
+ m_task = new CTaskManip(m_iMan, m_object);
+ return ((CTaskManip*)m_task)->Start(order, arm);
+}
+
+// Puts or removes a flag.
+
+Error CTaskManager::StartTaskFlag(TaskFlagOrder order, int rank)
+{
+ m_task = new CTaskFlag(m_iMan, m_object);
+ return ((CTaskFlag*)m_task)->Start(order, rank);
+}
+
+// Builds a building.
+
+Error CTaskManager::StartTaskBuild(ObjectType type)
+{
+ m_task = new CTaskBuild(m_iMan, m_object);
+ return ((CTaskBuild*)m_task)->Start(type);
+}
+
+// Probe the ground.
+
+Error CTaskManager::StartTaskSearch()
+{
+ m_task = new CTaskSearch(m_iMan, m_object);
+ return ((CTaskSearch*)m_task)->Start();
+}
+
+// Reads an information terminal.
+
+Error CTaskManager::StartTaskInfo(char *name, float value, float power, bool bSend)
+{
+ m_task = new CTaskInfo(m_iMan, m_object);
+ return ((CTaskInfo*)m_task)->Start(name, value, power, bSend);
+}
+
+// Terraforms the ground.
+
+Error CTaskManager::StartTaskTerraform()
+{
+ m_task = new CTaskTerraform(m_iMan, m_object);
+ return ((CTaskTerraform*)m_task)->Start();
+}
+
+// Changes the pencil.
+
+Error CTaskManager::StartTaskPen(bool bDown, int color)
+{
+ m_task = new CTaskPen(m_iMan, m_object);
+ return ((CTaskPen*)m_task)->Start(bDown, color);
+}
+
+// Recovers a ruin.
+
+Error CTaskManager::StartTaskRecover()
+{
+ m_task = new CTaskRecover(m_iMan, m_object);
+ return ((CTaskRecover*)m_task)->Start();
+}
+
+// Deploys the shield.
+
+Error CTaskManager::StartTaskShield(TaskShieldMode mode, float delay)
+{
+ if ( mode == TSM_UP )
+ {
+ m_task = new CTaskShield(m_iMan, m_object);
+ return ((CTaskShield*)m_task)->Start(mode, delay);
+ }
+ if ( mode == TSM_DOWN && m_task != 0 )
+ {
+ return ((CTaskShield*)m_task)->Start(mode, delay);
+ }
+ if ( mode == TSM_UPDATE && m_task != 0 )
+ {
+ return ((CTaskShield*)m_task)->Start(mode, delay);
+ }
+ return ERR_GENERIC;
+}
+
+// Shoots.
+
+Error CTaskManager::StartTaskFire(float delay)
+{
+ m_bPilot = true;
+ m_task = new CTaskFire(m_iMan, m_object);
+ return ((CTaskFire*)m_task)->Start(delay);
+}
+
+// Shoots with the ant.
+
+Error CTaskManager::StartTaskFireAnt(Math::Vector impact)
+{
+ m_task = new CTaskFireAnt(m_iMan, m_object);
+ return ((CTaskFireAnt*)m_task)->Start(impact);
+}
+
+// Adjusts higher.
+
+Error CTaskManager::StartTaskGunGoal(float dirV, float dirH)
+{
+ m_task = new CTaskGunGoal(m_iMan, m_object);
+ return ((CTaskGunGoal*)m_task)->Start(dirV, dirH);
+}
+
+// Suicide of the spider.
+
+Error CTaskManager::StartTaskSpiderExplo()
+{
+ m_task = new CTaskSpiderExplo(m_iMan, m_object);
+ return ((CTaskSpiderExplo*)m_task)->Start();
+}
+
+// Reset.
+
+Error CTaskManager::StartTaskReset(Math::Vector goal, Math::Vector angle)
+{
+ m_task = new CTaskReset(m_iMan, m_object);
+ return ((CTaskReset*)m_task)->Start(goal, angle);
+}
+
+
+
+
+
+// Management of an event.
+
+bool CTaskManager::EventProcess(const Event &event)
+{
+ if ( m_task == 0 ) return false;
+ return m_task->EventProcess(event);
+}
+
+
+// Indicates whether the action is finished.
+
+Error CTaskManager::IsEnded()
+{
+ if ( m_task == 0 ) return ERR_GENERIC;
+ return m_task->IsEnded();
+}
+
+
+// Indicates whether the action is pending.
+
+bool CTaskManager::IsBusy()
+{
+ if ( m_task == 0 ) return false;
+ return m_task->IsBusy();
+}
+
+
+// Indicates whether it is possible to control the robot
+// during the execution of the current task.
+
+bool CTaskManager::IsPilot()
+{
+ return m_bPilot;
+}
+
+
+// Suddenly ends the current action.
+
+bool CTaskManager::Abort()
+{
+ if ( m_task == 0 ) return false;
+ return m_task->Abort();
+}
+
+
diff --git a/src/object/task/taskmanager.h b/src/object/task/taskmanager.h
index 30b6c81..14fc276 100644
--- a/src/object/task/taskmanager.h
+++ b/src/object/task/taskmanager.h
@@ -1,71 +1,71 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskmanager.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-#include "object/task/taskmanip.h"
-#include "object/task/taskgoto.h"
-#include "object/task/taskshield.h"
-#include "object/task/taskflag.h"
-
-
-
-class CTaskManager
-{
-public:
- CTaskManager(CInstanceManager* iMan, CObject* object);
- ~CTaskManager();
-
- Error StartTaskWait(float time);
- Error StartTaskAdvance(float length);
- Error StartTaskTurn(float angle);
- Error StartTaskGoto(Math::Vector pos, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode);
- Error StartTaskTake();
- Error StartTaskManip(TaskManipOrder order, TaskManipArm arm);
- Error StartTaskFlag(TaskFlagOrder order, int rank);
- Error StartTaskBuild(ObjectType type);
- Error StartTaskSearch();
- Error StartTaskInfo(char *name, float value, float power, bool bSend);
- Error StartTaskTerraform();
- Error StartTaskPen(bool bDown, int color);
- Error StartTaskRecover();
- Error StartTaskShield(TaskShieldMode mode, float delay);
- Error StartTaskFire(float delay);
- Error StartTaskFireAnt(Math::Vector impact);
- Error StartTaskGunGoal(float dirV, float dirH);
- Error StartTaskSpiderExplo();
- Error StartTaskReset(Math::Vector goal, Math::Vector angle);
-
- bool EventProcess(const Event &event);
- Error IsEnded();
- bool IsBusy();
- bool IsPilot();
- bool Abort();
-
-protected:
-
-protected:
- CInstanceManager* m_iMan;
- CTask* m_task;
- CObject* m_object;
- bool m_bPilot;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskmanager.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "object/object.h"
+#include "object/task/taskmanip.h"
+#include "object/task/taskgoto.h"
+#include "object/task/taskshield.h"
+#include "object/task/taskflag.h"
+
+
+
+class CTaskManager
+{
+public:
+ CTaskManager(CInstanceManager* iMan, CObject* object);
+ ~CTaskManager();
+
+ Error StartTaskWait(float time);
+ Error StartTaskAdvance(float length);
+ Error StartTaskTurn(float angle);
+ Error StartTaskGoto(Math::Vector pos, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode);
+ Error StartTaskTake();
+ Error StartTaskManip(TaskManipOrder order, TaskManipArm arm);
+ Error StartTaskFlag(TaskFlagOrder order, int rank);
+ Error StartTaskBuild(ObjectType type);
+ Error StartTaskSearch();
+ Error StartTaskInfo(char *name, float value, float power, bool bSend);
+ Error StartTaskTerraform();
+ Error StartTaskPen(bool bDown, int color);
+ Error StartTaskRecover();
+ Error StartTaskShield(TaskShieldMode mode, float delay);
+ Error StartTaskFire(float delay);
+ Error StartTaskFireAnt(Math::Vector impact);
+ Error StartTaskGunGoal(float dirV, float dirH);
+ Error StartTaskSpiderExplo();
+ Error StartTaskReset(Math::Vector goal, Math::Vector angle);
+
+ bool EventProcess(const Event &event);
+ Error IsEnded();
+ bool IsBusy();
+ bool IsPilot();
+ bool Abort();
+
+protected:
+
+protected:
+ CInstanceManager* m_iMan;
+ CTask* m_task;
+ CObject* m_object;
+ bool m_bPilot;
+};
+
diff --git a/src/object/task/taskmanip.cpp b/src/object/task/taskmanip.cpp
index 636031b..456f274 100644
--- a/src/object/task/taskmanip.cpp
+++ b/src/object/task/taskmanip.cpp
@@ -1,1383 +1,1383 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskmanip.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskmanip.h"
-
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "old/pyro.h"
-#include "math/geometry.h"
-#include "object/robotmain.h"
-#include "physics/physics.h"
-
-
-//?const float MARGIN_FRONT = 2.0f;
-//?const float MARGIN_BACK = 2.0f;
-//?const float MARGIN_FRIEND = 2.0f;
-//?const float MARGIN_BEE = 5.0f;
-const float MARGIN_FRONT = 4.0f; //OK 1.9
-const float MARGIN_BACK = 4.0f; //OK 1.9
-const float MARGIN_FRIEND = 4.0f; //OK 1.9
-const float MARGIN_BEE = 5.0f; //OK 1.9
-
-
-
-
-// Object's constructor.
-
-CTaskManip::CTaskManip(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_arm = TMA_NEUTRAL;
- m_hand = TMH_OPEN;
-}
-
-// Object's destructor.
-
-CTaskManip::~CTaskManip()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskManip::EventProcess(const Event &event)
-{
- Math::Vector pos;
- float angle, a, g, cirSpeed, progress;
- int i;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- if ( m_bBee ) // bee?
- {
- return true;
- }
-
- if ( m_bTurn ) // preliminary rotation?
- {
- a = m_object->RetAngleY(0);
- g = m_angle;
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( m_physics->RetType() == TYPE_FLYING ) // flying on the ground?
- {
- cirSpeed *= 4.0f; // more fishing
- }
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- return true;
- }
-
- if ( m_move != 0 ) // preliminary advance?
- {
- m_timeLimit -= event.rTime;
- m_physics->SetMotorSpeedX(m_move); // forward/backward
- return true;
- }
-
- m_progress += event.rTime*m_speed; // others advance
- progress = m_progress;
- if ( progress > 1.0f ) progress = 1.0f;
-
- if ( m_bSubm ) // submarine?
- {
- if ( m_order == TMO_GRAB )
- {
- if ( m_step == 0 ) // fall?
- {
- pos = m_object->RetPosition(1);
- pos.y = 3.0f-progress*2.0f;
- m_object->SetPosition(1, pos);
- }
- if ( m_step == 1 ) // farm?
- {
- pos = m_object->RetPosition(2);
- pos.z = -1.5f+progress*0.5f;
- m_object->SetPosition(2, pos);
-
- pos = m_object->RetPosition(3);
- pos.z = 1.5f-progress*0.5f;
- m_object->SetPosition(3, pos);
- }
- if ( m_step == 2 ) // up?
- {
- pos = m_object->RetPosition(1);
- pos.y = 3.0f-(1.0f-progress)*2.0f;
- m_object->SetPosition(1, pos);
- }
- }
- else
- {
- if ( m_step == 0 ) // fall?
- {
- pos = m_object->RetPosition(1);
- pos.y = 3.0f-progress*2.0f;
- m_object->SetPosition(1, pos);
- }
- if ( m_step == 1 ) // farm?
- {
- pos = m_object->RetPosition(2);
- pos.z = -1.5f+(1.0f-progress)*0.5f;
- m_object->SetPosition(2, pos);
-
- pos = m_object->RetPosition(3);
- pos.z = 1.5f-(1.0f-progress)*0.5f;
- m_object->SetPosition(3, pos);
- }
- if ( m_step == 2 ) // up?
- {
- pos = m_object->RetPosition(1);
- pos.y = 3.0f-(1.0f-progress)*2.0f;
- m_object->SetPosition(1, pos);
- }
- }
- }
- else
- {
- for ( i=0 ; i<5 ; i++ )
- {
- angle = (m_finalAngle[i]-m_initialAngle[i])*progress;
- angle += m_initialAngle[i];
- m_object->SetAngleZ(i+1, angle);
- }
- }
-
- return true;
-}
-
-
-// Initializes the initial and final angles.
-
-void CTaskManip::InitAngle()
-{
- CObject* power;
- float max, energy;
- int i;
-
- if ( m_bSubm || m_bBee ) return;
-
- if ( m_arm == TMA_NEUTRAL ||
- m_arm == TMA_GRAB )
- {
- m_finalAngle[0] = ARM_NEUTRAL_ANGLE1; // arm
- m_finalAngle[1] = ARM_NEUTRAL_ANGLE2; // forearm
- m_finalAngle[2] = ARM_NEUTRAL_ANGLE3; // hand
- }
- if ( m_arm == TMA_STOCK )
- {
- m_finalAngle[0] = ARM_STOCK_ANGLE1; // arm
- m_finalAngle[1] = ARM_STOCK_ANGLE2; // forearm
- m_finalAngle[2] = ARM_STOCK_ANGLE3; // hand
- }
- if ( m_arm == TMA_FFRONT )
- {
- m_finalAngle[0] = 35.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = -95.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = -27.0f*Math::PI/180.0f; // hand
- }
- if ( m_arm == TMA_FBACK )
- {
- m_finalAngle[0] = 145.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = 95.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = 27.0f*Math::PI/180.0f; // hand
- }
- if ( m_arm == TMA_POWER )
- {
- m_finalAngle[0] = 95.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = 125.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = 50.0f*Math::PI/180.0f; // hand
- }
- if ( m_arm == TMA_OTHER )
- {
- if ( m_height <= 3.0f )
- {
- m_finalAngle[0] = 55.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = -90.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = -35.0f*Math::PI/180.0f; // hand
- }
- else
- {
- m_finalAngle[0] = 70.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = -90.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = -50.0f*Math::PI/180.0f; // hand
- }
- }
-
- if ( m_hand == TMH_OPEN ) // open clamp?
- {
- m_finalAngle[3] = -Math::PI*0.10f; // clamp close
- m_finalAngle[4] = Math::PI*0.10f; // clamp remote
- }
- if ( m_hand == TMH_CLOSE ) // clamp closed?
- {
- m_finalAngle[3] = Math::PI*0.05f; // clamp close
- m_finalAngle[4] = -Math::PI*0.05f; // clamp remote
- }
-
- for ( i=0 ; i<5 ; i++ )
- {
- m_initialAngle[i] = m_object->RetAngleZ(i+1);
- }
-
- max = 0.0f;
- for ( i=0 ; i<5 ; i++ )
- {
- max = Math::Max(max, fabs(m_initialAngle[i] - m_finalAngle[i]));
- }
- m_speed = (Math::PI*1.0f)/max;
- if ( m_speed > 3.0f ) m_speed = 3.0f; // piano, ma non troppo (?)
-
- energy = 0.0f;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- }
-
- if ( energy == 0.0f )
- {
- m_speed *= 0.7f; // slower if more energy!
- }
-}
-
-
-// Tests whether an object is compatible with the operation TMA_OTHER.
-
-bool TestFriend(ObjectType oType, ObjectType fType)
-{
- if ( oType == OBJECT_ENERGY )
- {
- return ( fType == OBJECT_METAL );
- }
- if ( oType == OBJECT_LABO )
- {
- return ( fType == OBJECT_BULLET );
- }
- if ( oType == OBJECT_NUCLEAR )
- {
- return ( fType == OBJECT_URANIUM );
- }
-
- return ( fType == OBJECT_POWER ||
- fType == OBJECT_ATOMIC );
-}
-
-// Assigns the goal was achieved.
-
-Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm)
-{
- ObjectType type;
- CObject *front, *other, *power;
- CPyro *pyro;
- float iAngle, dist, len;
- float fDist, fAngle, oDist, oAngle, oHeight;
- Math::Vector pos, fPos, oPos;
-
- m_arm = arm;
- m_height = 0.0f;
- m_step = 0;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
-
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
- oAngle = iAngle;
-
- m_bError = true; // operation impossible
-
- if ( m_arm != TMA_FFRONT &&
- m_arm != TMA_FBACK &&
- m_arm != TMA_POWER &&
- m_arm != TMA_GRAB ) return ERR_MANIP_VEH;
-
- m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));
-
- type = m_object->RetType();
- if ( type == OBJECT_BEE ) // bee?
- {
- if ( m_object->RetFret() == 0 )
- {
- if ( !m_physics->RetLand() ) return ERR_MANIP_FLY;
-
- other = SearchTakeUnderObject(m_targetPos, MARGIN_BEE);
- if ( other == 0 ) return ERR_MANIP_NIL;
- m_object->SetFret(other); // takes the ball
- other->SetTruck(m_object);
- other->SetTruckPart(0); // taken with the base
- other->SetPosition(0, Math::Vector(0.0f, -3.0f, 0.0f));
- }
- else
- {
- other = m_object->RetFret(); // other = ball
- m_object->SetFret(0); // lick the ball
- other->SetTruck(0);
- pos = m_object->RetPosition(0);
- pos.y -= 3.0f;
- other->SetPosition(0, pos);
-
- pos = m_object->RetPosition(0);
- pos.y += 2.0f;
- m_object->SetPosition(0, pos); // against the top of jump
-
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FALL, other); // the ball falls
- }
-
- m_bBee = true;
- m_bError = false; // ok
- return ERR_OK;
- }
- m_bBee = false;
-
- m_bSubm = ( type == OBJECT_MOBILEsa ); // submarine?
-
- if ( m_arm == TMA_GRAB ) // takes immediately?
- {
- TruckTakeObject();
- Abort();
- return ERR_OK;
- }
-
- m_energy = 0.0f;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- m_energy = power->RetEnergy();
- }
-
- if ( !m_physics->RetLand() ) return ERR_MANIP_FLY;
-
- if ( type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEsa ) return ERR_MANIP_VEH;
-
- if ( m_bSubm ) // submarine?
- {
- m_arm = TMA_FFRONT; // only possible in front!
- }
-
- m_move = 0.0f; // advance not necessary
- m_angle = iAngle;
-
- if ( order == TMO_AUTO )
- {
- if ( m_object->RetFret() == 0 )
- {
- m_order = TMO_GRAB;
- }
- else
- {
- m_order = TMO_DROP;
- }
- }
- else
- {
- m_order = order;
- }
-
- if ( m_order == TMO_GRAB && m_object->RetFret() != 0 )
- {
- return ERR_MANIP_BUSY;
- }
- if ( m_order == TMO_DROP && m_object->RetFret() == 0 )
- {
- return ERR_MANIP_EMPTY;
- }
-
-//? speed = m_physics->RetMotorSpeed();
-//? if ( speed.x != 0.0f ||
-//? speed.z != 0.0f ) return ERR_MANIP_MOTOR;
-
- if ( m_order == TMO_GRAB )
- {
- if ( m_arm == TMA_FFRONT )
- {
- front = SearchTakeFrontObject(true, fPos, fDist, fAngle);
- other = SearchOtherObject(true, oPos, oDist, oAngle, oHeight);
-
- if ( front != 0 && fDist < oDist )
- {
- m_targetPos = fPos;
- m_angle = fAngle;
- m_move = 1.0f; // advance required
- }
- else if ( other != 0 && oDist < fDist )
- {
- if ( other->RetPower() == 0 ) return ERR_MANIP_NIL;
- m_targetPos = oPos;
- m_angle = oAngle;
- m_height = oHeight;
- m_move = 1.0f; // advance required
- m_arm = TMA_OTHER;
- }
- else
- {
- return ERR_MANIP_NIL;
- }
- m_main->HideDropZone(front); // hides buildable area
- }
- if ( m_arm == TMA_FBACK )
- {
- if ( SearchTakeBackObject(true, m_targetPos, fDist, m_angle) == 0 )
- {
- return ERR_MANIP_NIL;
- }
- m_angle += Math::PI;
- m_move = -1.0f; // back necessary
- }
- if ( m_arm == TMA_POWER )
- {
- if ( m_object->RetPower() == 0 ) return ERR_MANIP_NIL;
- }
- }
-
- if ( m_order == TMO_DROP )
- {
- if ( m_arm == TMA_FFRONT )
- {
- other = SearchOtherObject(true, oPos, oDist, oAngle, oHeight);
- if ( other != 0 && other->RetPower() == 0 )
- {
- m_targetPos = oPos;
- m_angle = oAngle;
- m_height = oHeight;
- m_move = 1.0f; // advance required
- m_arm = TMA_OTHER;
- }
- else
- {
- if ( !IsFreeDeposeObject(Math::Vector(TAKE_DIST, 0.0f, 0.0f)) ) return ERR_MANIP_OCC;
- }
- }
- if ( m_arm == TMA_FBACK )
- {
- if ( !IsFreeDeposeObject(Math::Vector(-TAKE_DIST, 0.0f, 0.0f)) ) return ERR_MANIP_OCC;
- }
- if ( m_arm == TMA_POWER )
- {
- if ( m_object->RetPower() != 0 ) return ERR_MANIP_OCC;
- }
- }
-
- dist = Math::Distance(m_object->RetPosition(0), m_targetPos);
- len = dist-TAKE_DIST;
- if ( m_arm == TMA_OTHER ) len -= TAKE_DIST_OTHER;
- if ( len < 0.0f ) len = 0.0f;
- if ( m_arm == TMA_FBACK ) len = -len;
- m_advanceLength = dist-m_physics->RetLinLength(len);
- if ( dist <= m_advanceLength+0.2f ) m_move = 0.0f; // not necessary to advance
-
- if ( m_energy == 0.0f ) m_move = 0.0f;
-
- if ( m_move != 0.0f ) // forward or backward?
- {
- m_timeLimit = m_physics->RetLinTimeLength(fabs(len))*1.5f;
- if ( m_timeLimit < 0.5f ) m_timeLimit = 0.5f;
- }
-
- if ( m_object->RetFret() == 0 ) // not carrying anything?
- {
- m_hand = TMH_OPEN; // open clamp
- }
- else
- {
- m_hand = TMH_CLOSE; // closed clamp
- }
-
- InitAngle();
-
- if ( iAngle == m_angle || m_energy == 0.0f )
- {
- m_bTurn = false; // preliminary rotation unnecessary
- SoundManip(1.0f/m_speed);
- }
- else
- {
- m_bTurn = true; // preliminary rotation necessary
- }
-
- if ( m_bSubm )
- {
- m_camera->StartCentering(m_object, Math::PI*0.8f, 99.9f, 0.0f, 0.5f);
- }
-
- m_physics->SetFreeze(true); // it does not move
-
- m_bError = false; // ok
- return ERR_OK;
-}
-
-// Indicates whether the action is complete.
-
-Error CTaskManip::IsEnded()
-{
- CObject* fret;
- Math::Vector pos;
- float angle, dist;
- int i;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_bBee ) // bee?
- {
- return ERR_STOP;
- }
-
- if ( m_bTurn ) // preliminary rotation?
- {
- angle = m_object->RetAngleY(0);
- angle = Math::NormAngle(angle); // 0..2*Math::PI
-
- if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) )
- {
- m_bTurn = false; // rotation ended
- m_physics->SetMotorSpeedZ(0.0f);
- if ( m_move == 0.0f )
- {
- SoundManip(1.0f/m_speed);
- }
- }
- return ERR_CONTINUE;
- }
-
- if ( m_move != 0.0f ) // preliminary advance?
- {
- if ( m_timeLimit <= 0.0f )
- {
-//OK 1.9
- dist = Math::Distance(m_object->RetPosition(0), m_targetPos);
- if ( dist <= m_advanceLength + 2.0f )
- {
- m_move = 0.0f; // advance ended
- m_physics->SetMotorSpeedX(0.0f);
- SoundManip(1.0f/m_speed);
- return ERR_CONTINUE;
- }
- else
- {
-//EOK 1.9
- m_move = 0.0f; // advance ended
- m_physics->SetMotorSpeedX(0.0f); // stops
- Abort();
- return ERR_STOP;
- }
- }
-
- dist = Math::Distance(m_object->RetPosition(0), m_targetPos);
- if ( dist <= m_advanceLength )
- {
- m_move = 0.0f; // advance ended
- m_physics->SetMotorSpeedX(0.0f);
- SoundManip(1.0f/m_speed);
- }
- return ERR_CONTINUE;
- }
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( !m_bSubm )
- {
- for ( i=0 ; i<5 ; i++ )
- {
- m_object->SetAngleZ(i+1, m_finalAngle[i]);
- }
- }
- m_step ++;
-
- if ( m_order == TMO_GRAB )
- {
- if ( m_step == 1 )
- {
- if ( m_bSubm ) m_speed = 1.0f/0.7f;
- m_hand = TMH_CLOSE; // closes the clamp to take
- InitAngle();
- SoundManip(1.0f/m_speed, 0.8f, 1.5f);
- return ERR_CONTINUE;
- }
- if ( m_step == 2 )
- {
- if ( m_bSubm ) m_speed = 1.0f/1.5f;
- if ( !TruckTakeObject() &&
- m_object->RetFret() == 0 )
- {
- m_hand = TMH_OPEN; // reopens the clamp
- m_arm = TMA_NEUTRAL;
- InitAngle();
- SoundManip(1.0f/m_speed, 0.8f, 1.5f);
- }
- else
- {
- if ( (m_arm == TMA_OTHER ||
- m_arm == TMA_POWER ) &&
- (m_fretType == OBJECT_POWER ||
- m_fretType == OBJECT_ATOMIC ) )
- {
- m_sound->Play(SOUND_POWEROFF, m_object->RetPosition(0));
- }
- m_arm = TMA_STOCK;
- InitAngle();
- SoundManip(1.0f/m_speed);
- }
- return ERR_CONTINUE;
- }
- }
-
- if ( m_order == TMO_DROP )
- {
- if ( m_step == 1 )
- {
- if ( m_bSubm ) m_speed = 1.0f/0.7f;
- fret = m_object->RetFret();
- if ( TruckDeposeObject() )
- {
- if ( (m_arm == TMA_OTHER ||
- m_arm == TMA_POWER ) &&
- (m_fretType == OBJECT_POWER ||
- m_fretType == OBJECT_ATOMIC ) )
- {
- m_sound->Play(SOUND_POWERON, m_object->RetPosition(0));
- }
- if ( fret != 0 && m_fretType == OBJECT_METAL && m_arm == TMA_FFRONT )
- {
- m_main->ShowDropZone(fret, m_object); // shows buildable area
- }
- m_hand = TMH_OPEN; // opens the clamp to deposit
- SoundManip(1.0f/m_speed, 0.8f, 1.5f);
- }
- InitAngle();
- return ERR_CONTINUE;
- }
- if ( m_step == 2 )
- {
- if ( m_bSubm ) m_speed = 1.0f/1.5f;
- m_arm = TMA_NEUTRAL;
- InitAngle();
- SoundManip(1.0f/m_speed);
- return ERR_CONTINUE;
- }
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskManip::Abort()
-{
- int i;
-
- if ( m_object->RetFret() == 0 ) // not carrying anything?
- {
- m_hand = TMH_OPEN; // open clamp
- m_arm = TMA_NEUTRAL;
- }
- else
- {
- m_hand = TMH_CLOSE; // closed clamp
- m_arm = TMA_STOCK;
- }
- InitAngle();
-
- if ( !m_bSubm )
- {
- for ( i=0 ; i<5 ; i++ )
- {
- m_object->SetAngleZ(i+1, m_finalAngle[i]);
- }
- }
-
- m_camera->StopCentering(m_object, 2.0f);
- m_physics->SetFreeze(false); // is moving again
- return true;
-}
-
-
-// Seeks the object below to take (for bees).
-
-CObject* CTaskManip::SearchTakeUnderObject(Math::Vector &pos, float dLimit)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float min, distance;
- int i;
-
- iPos = m_object->RetPosition(0);
-
- min = 1000000.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
-
- if ( type != OBJECT_FRET &&
- type != OBJECT_STONE &&
- type != OBJECT_URANIUM &&
- type != OBJECT_BULLET &&
- type != OBJECT_METAL &&
- type != OBJECT_POWER &&
- type != OBJECT_ATOMIC &&
- type != OBJECT_BBOX &&
- type != OBJECT_KEYa &&
- type != OBJECT_KEYb &&
- type != OBJECT_KEYc &&
- type != OBJECT_KEYd &&
- type != OBJECT_TNT ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj->RetLock() ) continue;
- if ( pObj->RetZoomY(0) != 1.0f ) continue;
-
- oPos = pObj->RetPosition(0);
- distance = Math::Distance(oPos, iPos);
- if ( distance <= dLimit &&
- distance < min )
- {
- min = distance;
- pBest = pObj;
- }
- }
- if ( pBest != 0 )
- {
- pos = pBest->RetPosition(0);
- }
- return pBest;
-}
-
-// Seeks the object in front to take.
-
-CObject* CTaskManip::SearchTakeFrontObject(bool bAdvance, Math::Vector &pos,
- float &distance, float &angle)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float min, iAngle, bAngle, aLimit, dLimit, f;
- int i;
-
- iPos = m_object->RetPosition(0);
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- if ( bAdvance && m_energy > 0.0f )
- {
- aLimit = 60.0f*Math::PI/180.0f;
- dLimit = MARGIN_FRONT+10.0f;
- }
- else
- {
-//? aLimit = 7.0f*Math::PI/180.0f;
- aLimit = 15.0f*Math::PI/180.0f; //OK 1.9
- dLimit = MARGIN_FRONT;
- }
-
- min = 1000000.0f;
- pBest = 0;
- bAngle = 0.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
-
- if ( type != OBJECT_FRET &&
- type != OBJECT_STONE &&
- type != OBJECT_URANIUM &&
- type != OBJECT_BULLET &&
- type != OBJECT_METAL &&
- type != OBJECT_POWER &&
- type != OBJECT_ATOMIC &&
- type != OBJECT_BBOX &&
- type != OBJECT_KEYa &&
- type != OBJECT_KEYb &&
- type != OBJECT_KEYc &&
- type != OBJECT_KEYd &&
- type != OBJECT_TNT &&
- type != OBJECT_SCRAP1 &&
- type != OBJECT_SCRAP2 &&
- type != OBJECT_SCRAP3 &&
- type != OBJECT_SCRAP4 &&
- type != OBJECT_SCRAP5 ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj->RetLock() ) continue;
- if ( pObj->RetZoomY(0) != 1.0f ) continue;
-
- oPos = pObj->RetPosition(0);
- distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST);
- f = 1.0f-distance/50.0f;
- if ( f < 0.5f ) f = 0.5f;
-
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( !Math::TestAngle(angle, iAngle-aLimit*f, iAngle+aLimit*f) ) continue;
-
- if ( distance < -dLimit ||
- distance > dLimit ) continue;
-
- if ( distance < min )
- {
- min = distance;
- pBest = pObj;
- bAngle = angle;
- }
- }
- if ( pBest == 0 )
- {
- distance = 1000000.0f;
- angle = 0.0f;
- }
- else
- {
- pos = pBest->RetPosition(0);
- distance = min;
- angle = bAngle;
- }
- return pBest;
-}
-
-// Seeks the object back to take.
-
-CObject* CTaskManip::SearchTakeBackObject(bool bAdvance, Math::Vector &pos,
- float &distance, float &angle)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float min, iAngle, bAngle, aLimit, dLimit, f;
- int i;
-
- iPos = m_object->RetPosition(0);
- iAngle = m_object->RetAngleY(0)+Math::PI;
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- if ( bAdvance && m_energy > 0.0f )
- {
- aLimit = 60.0f*Math::PI/180.0f;
- dLimit = MARGIN_BACK+5.0f;
- }
- else
- {
- aLimit = 7.0f*Math::PI/180.0f;
- dLimit = MARGIN_BACK;
- }
-
- min = 1000000.0f;
- pBest = 0;
- bAngle = 0.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
-
- if ( type != OBJECT_FRET &&
- type != OBJECT_STONE &&
- type != OBJECT_URANIUM &&
- type != OBJECT_BULLET &&
- type != OBJECT_METAL &&
- type != OBJECT_POWER &&
- type != OBJECT_ATOMIC &&
- type != OBJECT_BBOX &&
- type != OBJECT_KEYa &&
- type != OBJECT_KEYb &&
- type != OBJECT_KEYc &&
- type != OBJECT_KEYd &&
- type != OBJECT_TNT &&
- type != OBJECT_SCRAP1 &&
- type != OBJECT_SCRAP2 &&
- type != OBJECT_SCRAP3 &&
- type != OBJECT_SCRAP4 &&
- type != OBJECT_SCRAP5 ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj->RetLock() ) continue;
- if ( pObj->RetZoomY(0) != 1.0f ) continue;
-
- oPos = pObj->RetPosition(0);
- distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST);
- f = 1.0f-distance/50.0f;
- if ( f < 0.5f ) f = 0.5f;
-
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( !Math::TestAngle(angle, iAngle-aLimit*f, iAngle+aLimit*f) ) continue;
-
- if ( distance < -dLimit ||
- distance > dLimit ) continue;
-
- if ( distance < min )
- {
- min = distance;
- pBest = pObj;
- bAngle = angle;
- }
- }
- if ( pBest == 0 )
- {
- distance = 1000000.0f;
- angle = 0.0f;
- }
- else
- {
- pos = pBest->RetPosition(0);
- distance = min;
- angle = bAngle;
- }
- return pBest;
-}
-
-// Seeks the robot or building on which it wants to put a battery or or other object.
-
-CObject* CTaskManip::SearchOtherObject(bool bAdvance, Math::Vector &pos,
- float &distance, float &angle,
- float &height)
-{
- Character* character;
- CObject* pObj;
- CObject* pPower;
- Math::Matrix* mat;
- Math::Vector iPos, oPos;
- ObjectType type, powerType;
- float iAngle, iRad, oAngle, oLimit, aLimit, dLimit;
- int i;
-
- distance = 1000000.0f;
- angle = 0.0f;
-
- if ( m_bSubm ) return 0; // impossible with the submarine
-
- if ( !m_object->GetCrashSphere(0, iPos, iRad) ) return 0;
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- if ( bAdvance && m_energy > 0.0f )
- {
- aLimit = 60.0f*Math::PI/180.0f;
- dLimit = MARGIN_FRIEND+10.0f;
- }
- else
- {
- aLimit = 7.0f*Math::PI/180.0f;
- dLimit = MARGIN_FRIEND;
- }
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue; // yourself?
-
- type = pObj->RetType();
- 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_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_TOWER &&
- type != OBJECT_RESEARCH &&
- type != OBJECT_ENERGY &&
- type != OBJECT_LABO &&
- type != OBJECT_NUCLEAR ) continue;
-
- pPower = pObj->RetPower();
- if ( pPower != 0 )
- {
- if ( pPower->RetLock() ) continue;
- if ( pPower->RetZoomY(0) != 1.0f ) continue;
-
- powerType = pPower->RetType();
- if ( powerType == OBJECT_NULL ||
- powerType == OBJECT_FIX ) continue;
- }
-
- mat = pObj->RetWorldMatrix(0);
- character = pObj->RetCharacter();
- oPos = Transform(*mat, character->posPower);
-
- oAngle = pObj->RetAngleY(0);
- if ( type == OBJECT_TOWER ||
- type == OBJECT_RESEARCH )
- {
- oLimit = 45.0f*Math::PI/180.0f;
- }
- else if ( type == OBJECT_ENERGY )
- {
- oLimit = 90.0f*Math::PI/180.0f;
- }
- else if ( type == OBJECT_LABO )
- {
- oLimit = 120.0f*Math::PI/180.0f;
- }
- else if ( type == OBJECT_NUCLEAR )
- {
- oLimit = 45.0f*Math::PI/180.0f;
- }
- else
- {
- oLimit = 45.0f*Math::PI/180.0f;
- oAngle += Math::PI; // is behind
- }
- oAngle = Math::NormAngle(oAngle); // 0..2*Math::PI
- angle = Math::RotateAngle(iPos.x-oPos.x, oPos.z-iPos.z); // CW !
- if ( !Math::TestAngle(angle, oAngle-oLimit, oAngle+oLimit) ) continue;
-
- distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST);
- if ( distance <= dLimit )
- {
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
- {
- character = pObj->RetCharacter();
- height = character->posPower.y;
- pos = oPos;
- return pObj;
- }
- }
- }
-
- distance = 1000000.0f;
- angle = 0.0f;
- return 0;
-}
-
-// Takes the object placed in front.
-
-bool CTaskManip::TruckTakeObject()
-{
- CObject* fret;
- CObject* other;
- Math::Matrix matRotate;
- Math::Vector pos;
- float angle, dist;
-
- if ( m_arm == TMA_GRAB ) // takes immediately?
- {
- fret = m_object->RetFret();
- if ( fret == 0 ) return false; // nothing to take?
- m_fretType = fret->RetType();
-
- if ( m_object->RetType() == OBJECT_HUMAN ||
- m_object->RetType() == OBJECT_TECH )
- {
- fret->SetTruck(m_object);
- fret->SetTruckPart(4); // takes with the hand
-
- fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f));
- fret->SetAngleY(0, 0.1f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.8f);
- }
- else if ( m_bSubm )
- {
- fret->SetTruck(m_object);
- fret->SetTruckPart(2); // takes with the right claw
-
- pos = Math::Vector(1.1f, -1.0f, 1.0f); // relative
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleY(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- }
- else
- {
- fret->SetTruck(m_object);
- fret->SetTruckPart(3); // takes with the hand
-
- pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, Math::PI/2.0f);
- fret->SetAngleY(0, 0.0f);
- }
-
- m_object->SetFret(fret); // takes
- }
-
- if ( m_arm == TMA_FFRONT ) // takes on the ground in front?
- {
- fret = SearchTakeFrontObject(false, pos, dist, angle);
- if ( fret == 0 ) return false; // nothing to take?
- m_fretType = fret->RetType();
-
- if ( m_bSubm )
- {
- fret->SetTruck(m_object);
- fret->SetTruckPart(2); // takes with the right claw
-
- pos = Math::Vector(1.1f, -1.0f, 1.0f); // relative
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleY(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- }
- else
- {
- fret->SetTruck(m_object);
- fret->SetTruckPart(3); // takes with the hand
-
- pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, Math::PI/2.0f);
- fret->SetAngleY(0, 0.0f);
- }
-
- m_object->SetFret(fret); // takes
- }
-
- if ( m_arm == TMA_FBACK ) // takes on the ground behind?
- {
- fret = SearchTakeBackObject(false, pos, dist, angle);
- if ( fret == 0 ) return false; // nothing to take?
- m_fretType = fret->RetType();
-
- fret->SetTruck(m_object);
- fret->SetTruckPart(3); // takes with the hand
-
- pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, Math::PI/2.0f);
- fret->SetAngleY(0, 0.0f);
-
- m_object->SetFret(fret); // takes
- }
-
- if ( m_arm == TMA_POWER ) // takes battery in the back?
- {
- fret = m_object->RetPower();
- if ( fret == 0 ) return false; // no battery?
- m_fretType = fret->RetType();
-
- pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, Math::PI/2.0f);
- fret->SetAngleY(0, 0.0f);
- fret->SetTruckPart(3); // takes with the hand
-
- m_object->SetPower(0);
- m_object->SetFret(fret); // takes
- }
-
- if ( m_arm == TMA_OTHER ) // battery takes from friend?
- {
- other = SearchOtherObject(false, pos, dist, angle, m_height);
- if ( other == 0 ) return false;
-
- fret = other->RetPower();
- if ( fret == 0 ) return false; // the other does not have a battery?
- m_fretType = fret->RetType();
-
- other->SetPower(0);
- fret->SetTruck(m_object);
- fret->SetTruckPart(3); // takes with the hand
-
- pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
- fret->SetPosition(0, pos);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, Math::PI/2.0f);
- fret->SetAngleY(0, 0.0f);
-
- m_object->SetFret(fret); // takes
- }
-
- return true;
-}
-
-// Deposes the object taken.
-
-bool CTaskManip::TruckDeposeObject()
-{
- Character* character;
- CObject* fret;
- CObject* other;
- Math::Matrix* mat;
- Math::Vector pos;
- float angle, dist;
-
- if ( m_arm == TMA_FFRONT ) // deposits on the ground in front?
- {
- fret = m_object->RetFret();
- if ( fret == 0 ) return false; // nothing transported?
- m_fretType = fret->RetType();
-
- mat = fret->RetWorldMatrix(0);
- pos = Transform(*mat, Math::Vector(0.0f, 1.0f, 0.0f));
- m_terrain->MoveOnFloor(pos);
- fret->SetPosition(0, pos);
- fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- fret->FloorAdjust(); // plate well on the ground
-
- fret->SetTruck(0);
- m_object->SetFret(0); // deposit
- }
-
- if ( m_arm == TMA_FBACK ) // deposited on the ground behind?
- {
- fret = m_object->RetFret();
- if ( fret == 0 ) return false; // nothing transported?
- m_fretType = fret->RetType();
-
- mat = fret->RetWorldMatrix(0);
- pos = Transform(*mat, Math::Vector(0.0f, 1.0f, 0.0f));
- m_terrain->MoveOnFloor(pos);
- fret->SetPosition(0, pos);
- fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
-
- fret->SetTruck(0);
- m_object->SetFret(0); // deposit
- }
-
- if ( m_arm == TMA_POWER ) // deposits battery in the back?
- {
- fret = m_object->RetFret();
- if ( fret == 0 ) return false; // nothing transported?
- m_fretType = fret->RetType();
-
- if ( m_object->RetPower() != 0 ) return false;
-
- fret->SetTruck(m_object);
- fret->SetTruckPart(0); // carried by the base
-
- character = m_object->RetCharacter();
- fret->SetPosition(0, character->posPower);
- fret->SetAngleY(0, 0.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
-
- m_object->SetPower(fret); // uses
- m_object->SetFret(0);
- }
-
- if ( m_arm == TMA_OTHER ) // deposits battery on friend?
- {
- other = SearchOtherObject(false, pos, dist, angle, m_height);
- if ( other == 0 ) return false;
-
- fret = other->RetPower();
- if ( fret != 0 ) return false; // the other already has a battery?
-
- fret = m_object->RetFret();
- if ( fret == 0 ) return false;
- m_fretType = fret->RetType();
-
- other->SetPower(fret);
- fret->SetTruck(other);
-
- character = other->RetCharacter();
- fret->SetPosition(0, character->posPower);
- fret->SetAngleY(0, 0.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- fret->SetTruckPart(0); // carried by the base
-
- m_object->SetFret(0); // deposit
- }
-
- return true;
-}
-
-// Seeks if a location allows to deposit an object.
-
-bool CTaskManip::IsFreeDeposeObject(Math::Vector pos)
-{
- CObject* pObj;
- Math::Matrix* mat;
- Math::Vector iPos, oPos;
- float oRadius;
- int i, j;
-
- mat = m_object->RetWorldMatrix(0);
- iPos = Transform(*mat, pos);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- if ( Math::Distance(iPos, oPos)-(oRadius+1.0f) < 2.0f )
- {
- return false; // location occupied
- }
- }
- }
- return true; // location free
-}
-
-// Plays the sound of the manipulator arm.
-
-void CTaskManip::SoundManip(float time, float amplitude, float frequency)
-{
- int i;
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskmanip.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskmanip.h"
+
+#include "common/iman.h"
+#include "old/terrain.h"
+#include "old/pyro.h"
+#include "math/geometry.h"
+#include "object/robotmain.h"
+#include "physics/physics.h"
+
+
+//?const float MARGIN_FRONT = 2.0f;
+//?const float MARGIN_BACK = 2.0f;
+//?const float MARGIN_FRIEND = 2.0f;
+//?const float MARGIN_BEE = 5.0f;
+const float MARGIN_FRONT = 4.0f; //OK 1.9
+const float MARGIN_BACK = 4.0f; //OK 1.9
+const float MARGIN_FRIEND = 4.0f; //OK 1.9
+const float MARGIN_BEE = 5.0f; //OK 1.9
+
+
+
+
+// Object's constructor.
+
+CTaskManip::CTaskManip(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_arm = TMA_NEUTRAL;
+ m_hand = TMH_OPEN;
+}
+
+// Object's destructor.
+
+CTaskManip::~CTaskManip()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskManip::EventProcess(const Event &event)
+{
+ Math::Vector pos;
+ float angle, a, g, cirSpeed, progress;
+ int i;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ if ( m_bBee ) // bee?
+ {
+ return true;
+ }
+
+ if ( m_bTurn ) // preliminary rotation?
+ {
+ a = m_object->RetAngleY(0);
+ g = m_angle;
+ cirSpeed = Math::Direction(a, g)*1.0f;
+ if ( m_physics->RetType() == TYPE_FLYING ) // flying on the ground?
+ {
+ cirSpeed *= 4.0f; // more fishing
+ }
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
+ return true;
+ }
+
+ if ( m_move != 0 ) // preliminary advance?
+ {
+ m_timeLimit -= event.rTime;
+ m_physics->SetMotorSpeedX(m_move); // forward/backward
+ return true;
+ }
+
+ m_progress += event.rTime*m_speed; // others advance
+ progress = m_progress;
+ if ( progress > 1.0f ) progress = 1.0f;
+
+ if ( m_bSubm ) // submarine?
+ {
+ if ( m_order == TMO_GRAB )
+ {
+ if ( m_step == 0 ) // fall?
+ {
+ pos = m_object->RetPosition(1);
+ pos.y = 3.0f-progress*2.0f;
+ m_object->SetPosition(1, pos);
+ }
+ if ( m_step == 1 ) // farm?
+ {
+ pos = m_object->RetPosition(2);
+ pos.z = -1.5f+progress*0.5f;
+ m_object->SetPosition(2, pos);
+
+ pos = m_object->RetPosition(3);
+ pos.z = 1.5f-progress*0.5f;
+ m_object->SetPosition(3, pos);
+ }
+ if ( m_step == 2 ) // up?
+ {
+ pos = m_object->RetPosition(1);
+ pos.y = 3.0f-(1.0f-progress)*2.0f;
+ m_object->SetPosition(1, pos);
+ }
+ }
+ else
+ {
+ if ( m_step == 0 ) // fall?
+ {
+ pos = m_object->RetPosition(1);
+ pos.y = 3.0f-progress*2.0f;
+ m_object->SetPosition(1, pos);
+ }
+ if ( m_step == 1 ) // farm?
+ {
+ pos = m_object->RetPosition(2);
+ pos.z = -1.5f+(1.0f-progress)*0.5f;
+ m_object->SetPosition(2, pos);
+
+ pos = m_object->RetPosition(3);
+ pos.z = 1.5f-(1.0f-progress)*0.5f;
+ m_object->SetPosition(3, pos);
+ }
+ if ( m_step == 2 ) // up?
+ {
+ pos = m_object->RetPosition(1);
+ pos.y = 3.0f-(1.0f-progress)*2.0f;
+ m_object->SetPosition(1, pos);
+ }
+ }
+ }
+ else
+ {
+ for ( i=0 ; i<5 ; i++ )
+ {
+ angle = (m_finalAngle[i]-m_initialAngle[i])*progress;
+ angle += m_initialAngle[i];
+ m_object->SetAngleZ(i+1, angle);
+ }
+ }
+
+ return true;
+}
+
+
+// Initializes the initial and final angles.
+
+void CTaskManip::InitAngle()
+{
+ CObject* power;
+ float max, energy;
+ int i;
+
+ if ( m_bSubm || m_bBee ) return;
+
+ if ( m_arm == TMA_NEUTRAL ||
+ m_arm == TMA_GRAB )
+ {
+ m_finalAngle[0] = ARM_NEUTRAL_ANGLE1; // arm
+ m_finalAngle[1] = ARM_NEUTRAL_ANGLE2; // forearm
+ m_finalAngle[2] = ARM_NEUTRAL_ANGLE3; // hand
+ }
+ if ( m_arm == TMA_STOCK )
+ {
+ m_finalAngle[0] = ARM_STOCK_ANGLE1; // arm
+ m_finalAngle[1] = ARM_STOCK_ANGLE2; // forearm
+ m_finalAngle[2] = ARM_STOCK_ANGLE3; // hand
+ }
+ if ( m_arm == TMA_FFRONT )
+ {
+ m_finalAngle[0] = 35.0f*Math::PI/180.0f; // arm
+ m_finalAngle[1] = -95.0f*Math::PI/180.0f; // forearm
+ m_finalAngle[2] = -27.0f*Math::PI/180.0f; // hand
+ }
+ if ( m_arm == TMA_FBACK )
+ {
+ m_finalAngle[0] = 145.0f*Math::PI/180.0f; // arm
+ m_finalAngle[1] = 95.0f*Math::PI/180.0f; // forearm
+ m_finalAngle[2] = 27.0f*Math::PI/180.0f; // hand
+ }
+ if ( m_arm == TMA_POWER )
+ {
+ m_finalAngle[0] = 95.0f*Math::PI/180.0f; // arm
+ m_finalAngle[1] = 125.0f*Math::PI/180.0f; // forearm
+ m_finalAngle[2] = 50.0f*Math::PI/180.0f; // hand
+ }
+ if ( m_arm == TMA_OTHER )
+ {
+ if ( m_height <= 3.0f )
+ {
+ m_finalAngle[0] = 55.0f*Math::PI/180.0f; // arm
+ m_finalAngle[1] = -90.0f*Math::PI/180.0f; // forearm
+ m_finalAngle[2] = -35.0f*Math::PI/180.0f; // hand
+ }
+ else
+ {
+ m_finalAngle[0] = 70.0f*Math::PI/180.0f; // arm
+ m_finalAngle[1] = -90.0f*Math::PI/180.0f; // forearm
+ m_finalAngle[2] = -50.0f*Math::PI/180.0f; // hand
+ }
+ }
+
+ if ( m_hand == TMH_OPEN ) // open clamp?
+ {
+ m_finalAngle[3] = -Math::PI*0.10f; // clamp close
+ m_finalAngle[4] = Math::PI*0.10f; // clamp remote
+ }
+ if ( m_hand == TMH_CLOSE ) // clamp closed?
+ {
+ m_finalAngle[3] = Math::PI*0.05f; // clamp close
+ m_finalAngle[4] = -Math::PI*0.05f; // clamp remote
+ }
+
+ for ( i=0 ; i<5 ; i++ )
+ {
+ m_initialAngle[i] = m_object->RetAngleZ(i+1);
+ }
+
+ max = 0.0f;
+ for ( i=0 ; i<5 ; i++ )
+ {
+ max = Math::Max(max, fabs(m_initialAngle[i] - m_finalAngle[i]));
+ }
+ m_speed = (Math::PI*1.0f)/max;
+ if ( m_speed > 3.0f ) m_speed = 3.0f; // piano, ma non troppo (?)
+
+ energy = 0.0f;
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ }
+
+ if ( energy == 0.0f )
+ {
+ m_speed *= 0.7f; // slower if more energy!
+ }
+}
+
+
+// Tests whether an object is compatible with the operation TMA_OTHER.
+
+bool TestFriend(ObjectType oType, ObjectType fType)
+{
+ if ( oType == OBJECT_ENERGY )
+ {
+ return ( fType == OBJECT_METAL );
+ }
+ if ( oType == OBJECT_LABO )
+ {
+ return ( fType == OBJECT_BULLET );
+ }
+ if ( oType == OBJECT_NUCLEAR )
+ {
+ return ( fType == OBJECT_URANIUM );
+ }
+
+ return ( fType == OBJECT_POWER ||
+ fType == OBJECT_ATOMIC );
+}
+
+// Assigns the goal was achieved.
+
+Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm)
+{
+ ObjectType type;
+ CObject *front, *other, *power;
+ CPyro *pyro;
+ float iAngle, dist, len;
+ float fDist, fAngle, oDist, oAngle, oHeight;
+ Math::Vector pos, fPos, oPos;
+
+ m_arm = arm;
+ m_height = 0.0f;
+ m_step = 0;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+ oAngle = iAngle;
+
+ m_bError = true; // operation impossible
+
+ if ( m_arm != TMA_FFRONT &&
+ m_arm != TMA_FBACK &&
+ m_arm != TMA_POWER &&
+ m_arm != TMA_GRAB ) return ERR_MANIP_VEH;
+
+ m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));
+
+ type = m_object->RetType();
+ if ( type == OBJECT_BEE ) // bee?
+ {
+ if ( m_object->RetFret() == 0 )
+ {
+ if ( !m_physics->RetLand() ) return ERR_MANIP_FLY;
+
+ other = SearchTakeUnderObject(m_targetPos, MARGIN_BEE);
+ if ( other == 0 ) return ERR_MANIP_NIL;
+ m_object->SetFret(other); // takes the ball
+ other->SetTruck(m_object);
+ other->SetTruckPart(0); // taken with the base
+ other->SetPosition(0, Math::Vector(0.0f, -3.0f, 0.0f));
+ }
+ else
+ {
+ other = m_object->RetFret(); // other = ball
+ m_object->SetFret(0); // lick the ball
+ other->SetTruck(0);
+ pos = m_object->RetPosition(0);
+ pos.y -= 3.0f;
+ other->SetPosition(0, pos);
+
+ pos = m_object->RetPosition(0);
+ pos.y += 2.0f;
+ m_object->SetPosition(0, pos); // against the top of jump
+
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FALL, other); // the ball falls
+ }
+
+ m_bBee = true;
+ m_bError = false; // ok
+ return ERR_OK;
+ }
+ m_bBee = false;
+
+ m_bSubm = ( type == OBJECT_MOBILEsa ); // submarine?
+
+ if ( m_arm == TMA_GRAB ) // takes immediately?
+ {
+ TruckTakeObject();
+ Abort();
+ return ERR_OK;
+ }
+
+ m_energy = 0.0f;
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ m_energy = power->RetEnergy();
+ }
+
+ if ( !m_physics->RetLand() ) return ERR_MANIP_FLY;
+
+ if ( type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEsa ) return ERR_MANIP_VEH;
+
+ if ( m_bSubm ) // submarine?
+ {
+ m_arm = TMA_FFRONT; // only possible in front!
+ }
+
+ m_move = 0.0f; // advance not necessary
+ m_angle = iAngle;
+
+ if ( order == TMO_AUTO )
+ {
+ if ( m_object->RetFret() == 0 )
+ {
+ m_order = TMO_GRAB;
+ }
+ else
+ {
+ m_order = TMO_DROP;
+ }
+ }
+ else
+ {
+ m_order = order;
+ }
+
+ if ( m_order == TMO_GRAB && m_object->RetFret() != 0 )
+ {
+ return ERR_MANIP_BUSY;
+ }
+ if ( m_order == TMO_DROP && m_object->RetFret() == 0 )
+ {
+ return ERR_MANIP_EMPTY;
+ }
+
+//? speed = m_physics->RetMotorSpeed();
+//? if ( speed.x != 0.0f ||
+//? speed.z != 0.0f ) return ERR_MANIP_MOTOR;
+
+ if ( m_order == TMO_GRAB )
+ {
+ if ( m_arm == TMA_FFRONT )
+ {
+ front = SearchTakeFrontObject(true, fPos, fDist, fAngle);
+ other = SearchOtherObject(true, oPos, oDist, oAngle, oHeight);
+
+ if ( front != 0 && fDist < oDist )
+ {
+ m_targetPos = fPos;
+ m_angle = fAngle;
+ m_move = 1.0f; // advance required
+ }
+ else if ( other != 0 && oDist < fDist )
+ {
+ if ( other->RetPower() == 0 ) return ERR_MANIP_NIL;
+ m_targetPos = oPos;
+ m_angle = oAngle;
+ m_height = oHeight;
+ m_move = 1.0f; // advance required
+ m_arm = TMA_OTHER;
+ }
+ else
+ {
+ return ERR_MANIP_NIL;
+ }
+ m_main->HideDropZone(front); // hides buildable area
+ }
+ if ( m_arm == TMA_FBACK )
+ {
+ if ( SearchTakeBackObject(true, m_targetPos, fDist, m_angle) == 0 )
+ {
+ return ERR_MANIP_NIL;
+ }
+ m_angle += Math::PI;
+ m_move = -1.0f; // back necessary
+ }
+ if ( m_arm == TMA_POWER )
+ {
+ if ( m_object->RetPower() == 0 ) return ERR_MANIP_NIL;
+ }
+ }
+
+ if ( m_order == TMO_DROP )
+ {
+ if ( m_arm == TMA_FFRONT )
+ {
+ other = SearchOtherObject(true, oPos, oDist, oAngle, oHeight);
+ if ( other != 0 && other->RetPower() == 0 )
+ {
+ m_targetPos = oPos;
+ m_angle = oAngle;
+ m_height = oHeight;
+ m_move = 1.0f; // advance required
+ m_arm = TMA_OTHER;
+ }
+ else
+ {
+ if ( !IsFreeDeposeObject(Math::Vector(TAKE_DIST, 0.0f, 0.0f)) ) return ERR_MANIP_OCC;
+ }
+ }
+ if ( m_arm == TMA_FBACK )
+ {
+ if ( !IsFreeDeposeObject(Math::Vector(-TAKE_DIST, 0.0f, 0.0f)) ) return ERR_MANIP_OCC;
+ }
+ if ( m_arm == TMA_POWER )
+ {
+ if ( m_object->RetPower() != 0 ) return ERR_MANIP_OCC;
+ }
+ }
+
+ dist = Math::Distance(m_object->RetPosition(0), m_targetPos);
+ len = dist-TAKE_DIST;
+ if ( m_arm == TMA_OTHER ) len -= TAKE_DIST_OTHER;
+ if ( len < 0.0f ) len = 0.0f;
+ if ( m_arm == TMA_FBACK ) len = -len;
+ m_advanceLength = dist-m_physics->RetLinLength(len);
+ if ( dist <= m_advanceLength+0.2f ) m_move = 0.0f; // not necessary to advance
+
+ if ( m_energy == 0.0f ) m_move = 0.0f;
+
+ if ( m_move != 0.0f ) // forward or backward?
+ {
+ m_timeLimit = m_physics->RetLinTimeLength(fabs(len))*1.5f;
+ if ( m_timeLimit < 0.5f ) m_timeLimit = 0.5f;
+ }
+
+ if ( m_object->RetFret() == 0 ) // not carrying anything?
+ {
+ m_hand = TMH_OPEN; // open clamp
+ }
+ else
+ {
+ m_hand = TMH_CLOSE; // closed clamp
+ }
+
+ InitAngle();
+
+ if ( iAngle == m_angle || m_energy == 0.0f )
+ {
+ m_bTurn = false; // preliminary rotation unnecessary
+ SoundManip(1.0f/m_speed);
+ }
+ else
+ {
+ m_bTurn = true; // preliminary rotation necessary
+ }
+
+ if ( m_bSubm )
+ {
+ m_camera->StartCentering(m_object, Math::PI*0.8f, 99.9f, 0.0f, 0.5f);
+ }
+
+ m_physics->SetFreeze(true); // it does not move
+
+ m_bError = false; // ok
+ return ERR_OK;
+}
+
+// Indicates whether the action is complete.
+
+Error CTaskManip::IsEnded()
+{
+ CObject* fret;
+ Math::Vector pos;
+ float angle, dist;
+ int i;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_bBee ) // bee?
+ {
+ return ERR_STOP;
+ }
+
+ if ( m_bTurn ) // preliminary rotation?
+ {
+ angle = m_object->RetAngleY(0);
+ angle = Math::NormAngle(angle); // 0..2*Math::PI
+
+ if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) )
+ {
+ m_bTurn = false; // rotation ended
+ m_physics->SetMotorSpeedZ(0.0f);
+ if ( m_move == 0.0f )
+ {
+ SoundManip(1.0f/m_speed);
+ }
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_move != 0.0f ) // preliminary advance?
+ {
+ if ( m_timeLimit <= 0.0f )
+ {
+//OK 1.9
+ dist = Math::Distance(m_object->RetPosition(0), m_targetPos);
+ if ( dist <= m_advanceLength + 2.0f )
+ {
+ m_move = 0.0f; // advance ended
+ m_physics->SetMotorSpeedX(0.0f);
+ SoundManip(1.0f/m_speed);
+ return ERR_CONTINUE;
+ }
+ else
+ {
+//EOK 1.9
+ m_move = 0.0f; // advance ended
+ m_physics->SetMotorSpeedX(0.0f); // stops
+ Abort();
+ return ERR_STOP;
+ }
+ }
+
+ dist = Math::Distance(m_object->RetPosition(0), m_targetPos);
+ if ( dist <= m_advanceLength )
+ {
+ m_move = 0.0f; // advance ended
+ m_physics->SetMotorSpeedX(0.0f);
+ SoundManip(1.0f/m_speed);
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+ m_progress = 0.0f;
+
+ if ( !m_bSubm )
+ {
+ for ( i=0 ; i<5 ; i++ )
+ {
+ m_object->SetAngleZ(i+1, m_finalAngle[i]);
+ }
+ }
+ m_step ++;
+
+ if ( m_order == TMO_GRAB )
+ {
+ if ( m_step == 1 )
+ {
+ if ( m_bSubm ) m_speed = 1.0f/0.7f;
+ m_hand = TMH_CLOSE; // closes the clamp to take
+ InitAngle();
+ SoundManip(1.0f/m_speed, 0.8f, 1.5f);
+ return ERR_CONTINUE;
+ }
+ if ( m_step == 2 )
+ {
+ if ( m_bSubm ) m_speed = 1.0f/1.5f;
+ if ( !TruckTakeObject() &&
+ m_object->RetFret() == 0 )
+ {
+ m_hand = TMH_OPEN; // reopens the clamp
+ m_arm = TMA_NEUTRAL;
+ InitAngle();
+ SoundManip(1.0f/m_speed, 0.8f, 1.5f);
+ }
+ else
+ {
+ if ( (m_arm == TMA_OTHER ||
+ m_arm == TMA_POWER ) &&
+ (m_fretType == OBJECT_POWER ||
+ m_fretType == OBJECT_ATOMIC ) )
+ {
+ m_sound->Play(SOUND_POWEROFF, m_object->RetPosition(0));
+ }
+ m_arm = TMA_STOCK;
+ InitAngle();
+ SoundManip(1.0f/m_speed);
+ }
+ return ERR_CONTINUE;
+ }
+ }
+
+ if ( m_order == TMO_DROP )
+ {
+ if ( m_step == 1 )
+ {
+ if ( m_bSubm ) m_speed = 1.0f/0.7f;
+ fret = m_object->RetFret();
+ if ( TruckDeposeObject() )
+ {
+ if ( (m_arm == TMA_OTHER ||
+ m_arm == TMA_POWER ) &&
+ (m_fretType == OBJECT_POWER ||
+ m_fretType == OBJECT_ATOMIC ) )
+ {
+ m_sound->Play(SOUND_POWERON, m_object->RetPosition(0));
+ }
+ if ( fret != 0 && m_fretType == OBJECT_METAL && m_arm == TMA_FFRONT )
+ {
+ m_main->ShowDropZone(fret, m_object); // shows buildable area
+ }
+ m_hand = TMH_OPEN; // opens the clamp to deposit
+ SoundManip(1.0f/m_speed, 0.8f, 1.5f);
+ }
+ InitAngle();
+ return ERR_CONTINUE;
+ }
+ if ( m_step == 2 )
+ {
+ if ( m_bSubm ) m_speed = 1.0f/1.5f;
+ m_arm = TMA_NEUTRAL;
+ InitAngle();
+ SoundManip(1.0f/m_speed);
+ return ERR_CONTINUE;
+ }
+ }
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskManip::Abort()
+{
+ int i;
+
+ if ( m_object->RetFret() == 0 ) // not carrying anything?
+ {
+ m_hand = TMH_OPEN; // open clamp
+ m_arm = TMA_NEUTRAL;
+ }
+ else
+ {
+ m_hand = TMH_CLOSE; // closed clamp
+ m_arm = TMA_STOCK;
+ }
+ InitAngle();
+
+ if ( !m_bSubm )
+ {
+ for ( i=0 ; i<5 ; i++ )
+ {
+ m_object->SetAngleZ(i+1, m_finalAngle[i]);
+ }
+ }
+
+ m_camera->StopCentering(m_object, 2.0f);
+ m_physics->SetFreeze(false); // is moving again
+ return true;
+}
+
+
+// Seeks the object below to take (for bees).
+
+CObject* CTaskManip::SearchTakeUnderObject(Math::Vector &pos, float dLimit)
+{
+ CObject *pObj, *pBest;
+ Math::Vector iPos, oPos;
+ ObjectType type;
+ float min, distance;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+
+ min = 1000000.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+
+ if ( type != OBJECT_FRET &&
+ type != OBJECT_STONE &&
+ type != OBJECT_URANIUM &&
+ type != OBJECT_BULLET &&
+ type != OBJECT_METAL &&
+ type != OBJECT_POWER &&
+ type != OBJECT_ATOMIC &&
+ type != OBJECT_BBOX &&
+ type != OBJECT_KEYa &&
+ type != OBJECT_KEYb &&
+ type != OBJECT_KEYc &&
+ type != OBJECT_KEYd &&
+ type != OBJECT_TNT ) continue;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( pObj->RetLock() ) continue;
+ if ( pObj->RetZoomY(0) != 1.0f ) continue;
+
+ oPos = pObj->RetPosition(0);
+ distance = Math::Distance(oPos, iPos);
+ if ( distance <= dLimit &&
+ distance < min )
+ {
+ min = distance;
+ pBest = pObj;
+ }
+ }
+ if ( pBest != 0 )
+ {
+ pos = pBest->RetPosition(0);
+ }
+ return pBest;
+}
+
+// Seeks the object in front to take.
+
+CObject* CTaskManip::SearchTakeFrontObject(bool bAdvance, Math::Vector &pos,
+ float &distance, float &angle)
+{
+ CObject *pObj, *pBest;
+ Math::Vector iPos, oPos;
+ ObjectType type;
+ float min, iAngle, bAngle, aLimit, dLimit, f;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+
+ if ( bAdvance && m_energy > 0.0f )
+ {
+ aLimit = 60.0f*Math::PI/180.0f;
+ dLimit = MARGIN_FRONT+10.0f;
+ }
+ else
+ {
+//? aLimit = 7.0f*Math::PI/180.0f;
+ aLimit = 15.0f*Math::PI/180.0f; //OK 1.9
+ dLimit = MARGIN_FRONT;
+ }
+
+ min = 1000000.0f;
+ pBest = 0;
+ bAngle = 0.0f;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+
+ if ( type != OBJECT_FRET &&
+ type != OBJECT_STONE &&
+ type != OBJECT_URANIUM &&
+ type != OBJECT_BULLET &&
+ type != OBJECT_METAL &&
+ type != OBJECT_POWER &&
+ type != OBJECT_ATOMIC &&
+ type != OBJECT_BBOX &&
+ type != OBJECT_KEYa &&
+ type != OBJECT_KEYb &&
+ type != OBJECT_KEYc &&
+ type != OBJECT_KEYd &&
+ type != OBJECT_TNT &&
+ type != OBJECT_SCRAP1 &&
+ type != OBJECT_SCRAP2 &&
+ type != OBJECT_SCRAP3 &&
+ type != OBJECT_SCRAP4 &&
+ type != OBJECT_SCRAP5 ) continue;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( pObj->RetLock() ) continue;
+ if ( pObj->RetZoomY(0) != 1.0f ) continue;
+
+ oPos = pObj->RetPosition(0);
+ distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST);
+ f = 1.0f-distance/50.0f;
+ if ( f < 0.5f ) f = 0.5f;
+
+ angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+ if ( !Math::TestAngle(angle, iAngle-aLimit*f, iAngle+aLimit*f) ) continue;
+
+ if ( distance < -dLimit ||
+ distance > dLimit ) continue;
+
+ if ( distance < min )
+ {
+ min = distance;
+ pBest = pObj;
+ bAngle = angle;
+ }
+ }
+ if ( pBest == 0 )
+ {
+ distance = 1000000.0f;
+ angle = 0.0f;
+ }
+ else
+ {
+ pos = pBest->RetPosition(0);
+ distance = min;
+ angle = bAngle;
+ }
+ return pBest;
+}
+
+// Seeks the object back to take.
+
+CObject* CTaskManip::SearchTakeBackObject(bool bAdvance, Math::Vector &pos,
+ float &distance, float &angle)
+{
+ CObject *pObj, *pBest;
+ Math::Vector iPos, oPos;
+ ObjectType type;
+ float min, iAngle, bAngle, aLimit, dLimit, f;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+ iAngle = m_object->RetAngleY(0)+Math::PI;
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+
+ if ( bAdvance && m_energy > 0.0f )
+ {
+ aLimit = 60.0f*Math::PI/180.0f;
+ dLimit = MARGIN_BACK+5.0f;
+ }
+ else
+ {
+ aLimit = 7.0f*Math::PI/180.0f;
+ dLimit = MARGIN_BACK;
+ }
+
+ min = 1000000.0f;
+ pBest = 0;
+ bAngle = 0.0f;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+
+ if ( type != OBJECT_FRET &&
+ type != OBJECT_STONE &&
+ type != OBJECT_URANIUM &&
+ type != OBJECT_BULLET &&
+ type != OBJECT_METAL &&
+ type != OBJECT_POWER &&
+ type != OBJECT_ATOMIC &&
+ type != OBJECT_BBOX &&
+ type != OBJECT_KEYa &&
+ type != OBJECT_KEYb &&
+ type != OBJECT_KEYc &&
+ type != OBJECT_KEYd &&
+ type != OBJECT_TNT &&
+ type != OBJECT_SCRAP1 &&
+ type != OBJECT_SCRAP2 &&
+ type != OBJECT_SCRAP3 &&
+ type != OBJECT_SCRAP4 &&
+ type != OBJECT_SCRAP5 ) continue;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( pObj->RetLock() ) continue;
+ if ( pObj->RetZoomY(0) != 1.0f ) continue;
+
+ oPos = pObj->RetPosition(0);
+ distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST);
+ f = 1.0f-distance/50.0f;
+ if ( f < 0.5f ) f = 0.5f;
+
+ angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+ if ( !Math::TestAngle(angle, iAngle-aLimit*f, iAngle+aLimit*f) ) continue;
+
+ if ( distance < -dLimit ||
+ distance > dLimit ) continue;
+
+ if ( distance < min )
+ {
+ min = distance;
+ pBest = pObj;
+ bAngle = angle;
+ }
+ }
+ if ( pBest == 0 )
+ {
+ distance = 1000000.0f;
+ angle = 0.0f;
+ }
+ else
+ {
+ pos = pBest->RetPosition(0);
+ distance = min;
+ angle = bAngle;
+ }
+ return pBest;
+}
+
+// Seeks the robot or building on which it wants to put a battery or or other object.
+
+CObject* CTaskManip::SearchOtherObject(bool bAdvance, Math::Vector &pos,
+ float &distance, float &angle,
+ float &height)
+{
+ Character* character;
+ CObject* pObj;
+ CObject* pPower;
+ Math::Matrix* mat;
+ Math::Vector iPos, oPos;
+ ObjectType type, powerType;
+ float iAngle, iRad, oAngle, oLimit, aLimit, dLimit;
+ int i;
+
+ distance = 1000000.0f;
+ angle = 0.0f;
+
+ if ( m_bSubm ) return 0; // impossible with the submarine
+
+ if ( !m_object->GetCrashSphere(0, iPos, iRad) ) return 0;
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+
+ if ( bAdvance && m_energy > 0.0f )
+ {
+ aLimit = 60.0f*Math::PI/180.0f;
+ dLimit = MARGIN_FRIEND+10.0f;
+ }
+ else
+ {
+ aLimit = 7.0f*Math::PI/180.0f;
+ dLimit = MARGIN_FRIEND;
+ }
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue; // yourself?
+
+ type = pObj->RetType();
+ 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_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_TOWER &&
+ type != OBJECT_RESEARCH &&
+ type != OBJECT_ENERGY &&
+ type != OBJECT_LABO &&
+ type != OBJECT_NUCLEAR ) continue;
+
+ pPower = pObj->RetPower();
+ if ( pPower != 0 )
+ {
+ if ( pPower->RetLock() ) continue;
+ if ( pPower->RetZoomY(0) != 1.0f ) continue;
+
+ powerType = pPower->RetType();
+ if ( powerType == OBJECT_NULL ||
+ powerType == OBJECT_FIX ) continue;
+ }
+
+ mat = pObj->RetWorldMatrix(0);
+ character = pObj->RetCharacter();
+ oPos = Transform(*mat, character->posPower);
+
+ oAngle = pObj->RetAngleY(0);
+ if ( type == OBJECT_TOWER ||
+ type == OBJECT_RESEARCH )
+ {
+ oLimit = 45.0f*Math::PI/180.0f;
+ }
+ else if ( type == OBJECT_ENERGY )
+ {
+ oLimit = 90.0f*Math::PI/180.0f;
+ }
+ else if ( type == OBJECT_LABO )
+ {
+ oLimit = 120.0f*Math::PI/180.0f;
+ }
+ else if ( type == OBJECT_NUCLEAR )
+ {
+ oLimit = 45.0f*Math::PI/180.0f;
+ }
+ else
+ {
+ oLimit = 45.0f*Math::PI/180.0f;
+ oAngle += Math::PI; // is behind
+ }
+ oAngle = Math::NormAngle(oAngle); // 0..2*Math::PI
+ angle = Math::RotateAngle(iPos.x-oPos.x, oPos.z-iPos.z); // CW !
+ if ( !Math::TestAngle(angle, oAngle-oLimit, oAngle+oLimit) ) continue;
+
+ distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST);
+ if ( distance <= dLimit )
+ {
+ angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+ if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
+ {
+ character = pObj->RetCharacter();
+ height = character->posPower.y;
+ pos = oPos;
+ return pObj;
+ }
+ }
+ }
+
+ distance = 1000000.0f;
+ angle = 0.0f;
+ return 0;
+}
+
+// Takes the object placed in front.
+
+bool CTaskManip::TruckTakeObject()
+{
+ CObject* fret;
+ CObject* other;
+ Math::Matrix matRotate;
+ Math::Vector pos;
+ float angle, dist;
+
+ if ( m_arm == TMA_GRAB ) // takes immediately?
+ {
+ fret = m_object->RetFret();
+ if ( fret == 0 ) return false; // nothing to take?
+ m_fretType = fret->RetType();
+
+ if ( m_object->RetType() == OBJECT_HUMAN ||
+ m_object->RetType() == OBJECT_TECH )
+ {
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(4); // takes with the hand
+
+ fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f));
+ fret->SetAngleY(0, 0.1f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.8f);
+ }
+ else if ( m_bSubm )
+ {
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(2); // takes with the right claw
+
+ pos = Math::Vector(1.1f, -1.0f, 1.0f); // relative
+ fret->SetPosition(0, pos);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleY(0, 0.0f);
+ fret->SetAngleZ(0, 0.0f);
+ }
+ else
+ {
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(3); // takes with the hand
+
+ pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
+ fret->SetPosition(0, pos);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, Math::PI/2.0f);
+ fret->SetAngleY(0, 0.0f);
+ }
+
+ m_object->SetFret(fret); // takes
+ }
+
+ if ( m_arm == TMA_FFRONT ) // takes on the ground in front?
+ {
+ fret = SearchTakeFrontObject(false, pos, dist, angle);
+ if ( fret == 0 ) return false; // nothing to take?
+ m_fretType = fret->RetType();
+
+ if ( m_bSubm )
+ {
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(2); // takes with the right claw
+
+ pos = Math::Vector(1.1f, -1.0f, 1.0f); // relative
+ fret->SetPosition(0, pos);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleY(0, 0.0f);
+ fret->SetAngleZ(0, 0.0f);
+ }
+ else
+ {
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(3); // takes with the hand
+
+ pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
+ fret->SetPosition(0, pos);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, Math::PI/2.0f);
+ fret->SetAngleY(0, 0.0f);
+ }
+
+ m_object->SetFret(fret); // takes
+ }
+
+ if ( m_arm == TMA_FBACK ) // takes on the ground behind?
+ {
+ fret = SearchTakeBackObject(false, pos, dist, angle);
+ if ( fret == 0 ) return false; // nothing to take?
+ m_fretType = fret->RetType();
+
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(3); // takes with the hand
+
+ pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
+ fret->SetPosition(0, pos);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, Math::PI/2.0f);
+ fret->SetAngleY(0, 0.0f);
+
+ m_object->SetFret(fret); // takes
+ }
+
+ if ( m_arm == TMA_POWER ) // takes battery in the back?
+ {
+ fret = m_object->RetPower();
+ if ( fret == 0 ) return false; // no battery?
+ m_fretType = fret->RetType();
+
+ pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
+ fret->SetPosition(0, pos);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, Math::PI/2.0f);
+ fret->SetAngleY(0, 0.0f);
+ fret->SetTruckPart(3); // takes with the hand
+
+ m_object->SetPower(0);
+ m_object->SetFret(fret); // takes
+ }
+
+ if ( m_arm == TMA_OTHER ) // battery takes from friend?
+ {
+ other = SearchOtherObject(false, pos, dist, angle, m_height);
+ if ( other == 0 ) return false;
+
+ fret = other->RetPower();
+ if ( fret == 0 ) return false; // the other does not have a battery?
+ m_fretType = fret->RetType();
+
+ other->SetPower(0);
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(3); // takes with the hand
+
+ pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
+ fret->SetPosition(0, pos);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, Math::PI/2.0f);
+ fret->SetAngleY(0, 0.0f);
+
+ m_object->SetFret(fret); // takes
+ }
+
+ return true;
+}
+
+// Deposes the object taken.
+
+bool CTaskManip::TruckDeposeObject()
+{
+ Character* character;
+ CObject* fret;
+ CObject* other;
+ Math::Matrix* mat;
+ Math::Vector pos;
+ float angle, dist;
+
+ if ( m_arm == TMA_FFRONT ) // deposits on the ground in front?
+ {
+ fret = m_object->RetFret();
+ if ( fret == 0 ) return false; // nothing transported?
+ m_fretType = fret->RetType();
+
+ mat = fret->RetWorldMatrix(0);
+ pos = Transform(*mat, Math::Vector(0.0f, 1.0f, 0.0f));
+ m_terrain->MoveOnFloor(pos);
+ fret->SetPosition(0, pos);
+ fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.0f);
+ fret->FloorAdjust(); // plate well on the ground
+
+ fret->SetTruck(0);
+ m_object->SetFret(0); // deposit
+ }
+
+ if ( m_arm == TMA_FBACK ) // deposited on the ground behind?
+ {
+ fret = m_object->RetFret();
+ if ( fret == 0 ) return false; // nothing transported?
+ m_fretType = fret->RetType();
+
+ mat = fret->RetWorldMatrix(0);
+ pos = Transform(*mat, Math::Vector(0.0f, 1.0f, 0.0f));
+ m_terrain->MoveOnFloor(pos);
+ fret->SetPosition(0, pos);
+ fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.0f);
+
+ fret->SetTruck(0);
+ m_object->SetFret(0); // deposit
+ }
+
+ if ( m_arm == TMA_POWER ) // deposits battery in the back?
+ {
+ fret = m_object->RetFret();
+ if ( fret == 0 ) return false; // nothing transported?
+ m_fretType = fret->RetType();
+
+ if ( m_object->RetPower() != 0 ) return false;
+
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(0); // carried by the base
+
+ character = m_object->RetCharacter();
+ fret->SetPosition(0, character->posPower);
+ fret->SetAngleY(0, 0.0f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.0f);
+
+ m_object->SetPower(fret); // uses
+ m_object->SetFret(0);
+ }
+
+ if ( m_arm == TMA_OTHER ) // deposits battery on friend?
+ {
+ other = SearchOtherObject(false, pos, dist, angle, m_height);
+ if ( other == 0 ) return false;
+
+ fret = other->RetPower();
+ if ( fret != 0 ) return false; // the other already has a battery?
+
+ fret = m_object->RetFret();
+ if ( fret == 0 ) return false;
+ m_fretType = fret->RetType();
+
+ other->SetPower(fret);
+ fret->SetTruck(other);
+
+ character = other->RetCharacter();
+ fret->SetPosition(0, character->posPower);
+ fret->SetAngleY(0, 0.0f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.0f);
+ fret->SetTruckPart(0); // carried by the base
+
+ m_object->SetFret(0); // deposit
+ }
+
+ return true;
+}
+
+// Seeks if a location allows to deposit an object.
+
+bool CTaskManip::IsFreeDeposeObject(Math::Vector pos)
+{
+ CObject* pObj;
+ Math::Matrix* mat;
+ Math::Vector iPos, oPos;
+ float oRadius;
+ int i, j;
+
+ mat = m_object->RetWorldMatrix(0);
+ iPos = Transform(*mat, pos);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue;
+ if ( !pObj->RetActif() ) continue; // inactive?
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ if ( Math::Distance(iPos, oPos)-(oRadius+1.0f) < 2.0f )
+ {
+ return false; // location occupied
+ }
+ }
+ }
+ return true; // location free
+}
+
+// Plays the sound of the manipulator arm.
+
+void CTaskManip::SoundManip(float time, float amplitude, float frequency)
+{
+ int i;
+
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
+ m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
+}
+
diff --git a/src/object/task/taskmanip.h b/src/object/task/taskmanip.h
index d915558..79d9ad5 100644
--- a/src/object/task/taskmanip.h
+++ b/src/object/task/taskmanip.h
@@ -1,99 +1,99 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskmanip.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-#include "math/vector.h"
-
-
-
-enum TaskManipOrder
-{
- TMO_AUTO = 0, // deposits or takes automatically
- TMO_GRAB = 1, // takes an object
- TMO_DROP = 2, // deposits the object
-};
-
-enum TaskManipArm
-{
- TMA_NEUTRAL = 1, // empty arm at rest
- TMA_STOCK = 2, // right arm resting
- TMA_FFRONT = 3, // arm on the ground
- TMA_FBACK = 4, // arm behind the robot
- TMA_POWER = 5, // arm behind the robot
- TMA_OTHER = 6, // arm behind a friend robot
- TMA_GRAB = 7, // takes immediately
-};
-
-enum TaskManipHand
-{
- TMH_OPEN = 1, // open clamp
- TMH_CLOSE = 2, // closed clamp
-};
-
-
-
-class CTaskManip : public CTask
-{
-public:
- CTaskManip(CInstanceManager* iMan, CObject* object);
- ~CTaskManip();
-
- bool EventProcess(const Event &event);
-
- Error Start(TaskManipOrder order, TaskManipArm arm);
- Error IsEnded();
- bool Abort();
-
-protected:
- void InitAngle();
- CObject* SearchTakeUnderObject(Math::Vector &pos, float dLimit);
- CObject* SearchTakeFrontObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle);
- CObject* SearchTakeBackObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle);
- CObject* SearchOtherObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle, float &height);
- bool TruckTakeObject();
- bool TruckDeposeObject();
- bool IsFreeDeposeObject(Math::Vector pos);
- void SoundManip(float time, float amplitude=1.0f, float frequency=1.0f);
-
-protected:
- TaskManipOrder m_order;
- TaskManipArm m_arm;
- TaskManipHand m_hand;
- int m_step;
- float m_speed;
- float m_progress;
- float m_initialAngle[5];
- float m_finalAngle[5];
- float m_height;
- float m_advanceLength;
- float m_energy;
- bool m_bError;
- bool m_bTurn;
- bool m_bSubm;
- bool m_bBee;
- float m_angle;
- float m_move;
- Math::Vector m_targetPos;
- float m_timeLimit;
- ObjectType m_fretType;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskmanip.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "object/object.h"
+#include "math/vector.h"
+
+
+
+enum TaskManipOrder
+{
+ TMO_AUTO = 0, // deposits or takes automatically
+ TMO_GRAB = 1, // takes an object
+ TMO_DROP = 2, // deposits the object
+};
+
+enum TaskManipArm
+{
+ TMA_NEUTRAL = 1, // empty arm at rest
+ TMA_STOCK = 2, // right arm resting
+ TMA_FFRONT = 3, // arm on the ground
+ TMA_FBACK = 4, // arm behind the robot
+ TMA_POWER = 5, // arm behind the robot
+ TMA_OTHER = 6, // arm behind a friend robot
+ TMA_GRAB = 7, // takes immediately
+};
+
+enum TaskManipHand
+{
+ TMH_OPEN = 1, // open clamp
+ TMH_CLOSE = 2, // closed clamp
+};
+
+
+
+class CTaskManip : public CTask
+{
+public:
+ CTaskManip(CInstanceManager* iMan, CObject* object);
+ ~CTaskManip();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(TaskManipOrder order, TaskManipArm arm);
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ void InitAngle();
+ CObject* SearchTakeUnderObject(Math::Vector &pos, float dLimit);
+ CObject* SearchTakeFrontObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle);
+ CObject* SearchTakeBackObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle);
+ CObject* SearchOtherObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle, float &height);
+ bool TruckTakeObject();
+ bool TruckDeposeObject();
+ bool IsFreeDeposeObject(Math::Vector pos);
+ void SoundManip(float time, float amplitude=1.0f, float frequency=1.0f);
+
+protected:
+ TaskManipOrder m_order;
+ TaskManipArm m_arm;
+ TaskManipHand m_hand;
+ int m_step;
+ float m_speed;
+ float m_progress;
+ float m_initialAngle[5];
+ float m_finalAngle[5];
+ float m_height;
+ float m_advanceLength;
+ float m_energy;
+ bool m_bError;
+ bool m_bTurn;
+ bool m_bSubm;
+ bool m_bBee;
+ float m_angle;
+ float m_move;
+ Math::Vector m_targetPos;
+ float m_timeLimit;
+ ObjectType m_fretType;
+};
+
diff --git a/src/object/task/taskpen.cpp b/src/object/task/taskpen.cpp
index ff2f4e0..c3a9aef 100644
--- a/src/object/task/taskpen.cpp
+++ b/src/object/task/taskpen.cpp
@@ -1,287 +1,287 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskpen.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskpen.h"
-
-#include "old/particule.h"
-#include "math/geometry.h"
-#include "object/object.h"
-
-
-
-// Object's constructor.
-
-CTaskPen::CTaskPen(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskPen::~CTaskPen()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskPen::EventProcess(const Event &event)
-{
- Math::Vector pos, speed;
- Math::Point dim;
- int i;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- if ( m_delay == 0.0f )
- {
- m_progress = 1.0f;
- }
- else
- {
- m_progress += event.rTime*(1.0f/m_delay); // others advance
- if ( m_progress > 1.0f ) m_progress = 1.0f;
- }
-
- m_time += event.rTime;
-
- if ( m_phase == TPP_UP ) // back the pencil
- {
- i = AngleToRank(m_object->RetAngleY(1));
- pos = m_object->RetPosition(10+i);
- pos.y = -3.2f*(1.0f-m_progress);
- m_object->SetPosition(10+i, pos);
- }
-
- if ( m_phase == TPP_TURN ) // turns the carousel?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_supportPos;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = (Math::Rand()-0.5f)*3.0f;
- speed.z = (Math::Rand()-0.5f)*3.0f;
- speed.y = Math::Rand()*2.0f;
- dim.x = Math::Rand()*1.5f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
- }
-
- m_object->SetAngleY(1, m_oldAngle+(m_newAngle-m_oldAngle)*m_progress);
- }
-
- if ( m_phase == TPP_DOWN ) // down the pencil?
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_supportPos;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = (Math::Rand()-0.5f)*3.0f;
- speed.z = (Math::Rand()-0.5f)*3.0f;
- speed.y = Math::Rand()*5.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIVAPOR, 4.0f);
- }
-
- i = AngleToRank(m_object->RetAngleY(1));
- pos = m_object->RetPosition(10+i);
- if ( m_timeDown == 0.0f )
- {
- pos.y = 0.0f;
- }
- else
- {
- pos.y = -3.2f*Math::Bounce(Math::Min(m_progress*1.8f, 1.0f));
- }
- m_object->SetPosition(10+i, pos);
- }
-
- return true;
-}
-
-
-// Assigns the goal has achieved.
-
-Error CTaskPen::Start(bool bDown, int color)
-{
- Math::Vector pos;
- Math::Matrix* mat;
- ObjectType type;
- int i;
-
- m_bError = true; // operation impossible
-
- type = m_object->RetType();
- if ( type != OBJECT_MOBILEdr ) return ERR_FIRE_VEH;
-
- m_bError = false; // ok
-
- m_oldAngle = m_object->RetAngleY(1);
- m_newAngle = ColorToAngle(color);
-
- i = AngleToRank(m_oldAngle);
- pos = m_object->RetPosition(10+i);
-
- if ( pos.y == 0.0f ) // pencil at the top?
- {
- m_timeUp = 0.0f;
- }
- else // pencil on the bottom?
- {
- m_timeUp = 1.0f; // must rise up
- }
-
- if ( bDown ) // must go down ?
- {
- m_timeDown = 0.7f;
- }
- else
- {
- m_timeDown = 0.0f;
- }
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(-3.0f, 7.0f, 0.0f);
- pos = Math::Transform(*mat, pos); // position of carousel
- m_supportPos = pos;
-
- m_phase = TPP_UP;
- m_progress = 0.0f;
- m_delay = m_timeUp;
- m_time = 0.0f;
-
- if ( m_timeUp > 0.0f )
- {
- SoundManip(m_timeUp, 1.0f, 0.5f);
- }
-
- m_lastParticule = 0.0f;
-
-//? m_camera->StartCentering(m_object, Math::PI*0.60f, 99.9f, 5.0f, 0.5f);
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskPen::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( m_phase == TPP_UP )
- {
- m_phase = TPP_TURN;
- m_progress = 0.0f;
- m_delay = fabs(m_oldAngle-m_newAngle)/Math::PI;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- if ( m_delay > 0.0f )
- {
- SoundManip(m_delay, 1.0f, 1.0f);
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TPP_TURN )
- {
- m_sound->Play(SOUND_PSHHH2, m_supportPos, 1.0f, 1.4f);
- m_phase = TPP_DOWN;
- m_progress = 0.0f;
- m_delay = m_timeDown;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- return ERR_CONTINUE;
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskPen::Abort()
-{
-//? m_camera->StopCentering(m_object, 0.5f);
- return true;
-}
-
-
-// Plays the sound of the manipulator arm.
-
-void CTaskPen::SoundManip(float time, float amplitude, float frequency)
-{
- int i;
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
-}
-
-
-// Converting a angle to number of pencil.
-
-int CTaskPen::AngleToRank(float angle)
-{
-//? return (int)(angle/(-45.0f*Math::PI/180.0f));
- angle = -angle;
- angle += (45.0f*Math::PI/180.0f)/2.0f;
- return (int)(angle/(45.0f*Math::PI/180.0f));
-}
-
-// Converting a color to the angle of carousel of pencils.
-
-float CTaskPen::ColorToAngle(int color)
-{
- return -45.0f*Math::PI/180.0f*ColorToRank(color);
-}
-
-// Converting a color number to the pencil (0 .. 7).
-
-int CTaskPen::ColorToRank(int color)
-{
- if ( color == 8 ) return 1; // yellow
- if ( color == 7 ) return 2; // orange
- if ( color == 5 ) return 2; // pink
- if ( color == 4 ) return 3; // red
- if ( color == 6 ) return 4; // purple
- if ( color == 14 ) return 5; // blue
- if ( color == 15 ) return 5; // light blue
- if ( color == 12 ) return 6; // green
- if ( color == 13 ) return 6; // light green
- if ( color == 10 ) return 7; // brown
- if ( color == 9 ) return 7; // beige
- return 0; // black
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskpen.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskpen.h"
+
+#include "old/particule.h"
+#include "math/geometry.h"
+#include "object/object.h"
+
+
+
+// Object's constructor.
+
+CTaskPen::CTaskPen(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+}
+
+// Object's destructor.
+
+CTaskPen::~CTaskPen()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskPen::EventProcess(const Event &event)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+ int i;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ if ( m_delay == 0.0f )
+ {
+ m_progress = 1.0f;
+ }
+ else
+ {
+ m_progress += event.rTime*(1.0f/m_delay); // others advance
+ if ( m_progress > 1.0f ) m_progress = 1.0f;
+ }
+
+ m_time += event.rTime;
+
+ if ( m_phase == TPP_UP ) // back the pencil
+ {
+ i = AngleToRank(m_object->RetAngleY(1));
+ pos = m_object->RetPosition(10+i);
+ pos.y = -3.2f*(1.0f-m_progress);
+ m_object->SetPosition(10+i, pos);
+ }
+
+ if ( m_phase == TPP_TURN ) // turns the carousel?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_supportPos;
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ speed.x = (Math::Rand()-0.5f)*3.0f;
+ speed.z = (Math::Rand()-0.5f)*3.0f;
+ speed.y = Math::Rand()*2.0f;
+ dim.x = Math::Rand()*1.5f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
+ }
+
+ m_object->SetAngleY(1, m_oldAngle+(m_newAngle-m_oldAngle)*m_progress);
+ }
+
+ if ( m_phase == TPP_DOWN ) // down the pencil?
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_supportPos;
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ speed.x = (Math::Rand()-0.5f)*3.0f;
+ speed.z = (Math::Rand()-0.5f)*3.0f;
+ speed.y = Math::Rand()*5.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIVAPOR, 4.0f);
+ }
+
+ i = AngleToRank(m_object->RetAngleY(1));
+ pos = m_object->RetPosition(10+i);
+ if ( m_timeDown == 0.0f )
+ {
+ pos.y = 0.0f;
+ }
+ else
+ {
+ pos.y = -3.2f*Math::Bounce(Math::Min(m_progress*1.8f, 1.0f));
+ }
+ m_object->SetPosition(10+i, pos);
+ }
+
+ return true;
+}
+
+
+// Assigns the goal has achieved.
+
+Error CTaskPen::Start(bool bDown, int color)
+{
+ Math::Vector pos;
+ Math::Matrix* mat;
+ ObjectType type;
+ int i;
+
+ m_bError = true; // operation impossible
+
+ type = m_object->RetType();
+ if ( type != OBJECT_MOBILEdr ) return ERR_FIRE_VEH;
+
+ m_bError = false; // ok
+
+ m_oldAngle = m_object->RetAngleY(1);
+ m_newAngle = ColorToAngle(color);
+
+ i = AngleToRank(m_oldAngle);
+ pos = m_object->RetPosition(10+i);
+
+ if ( pos.y == 0.0f ) // pencil at the top?
+ {
+ m_timeUp = 0.0f;
+ }
+ else // pencil on the bottom?
+ {
+ m_timeUp = 1.0f; // must rise up
+ }
+
+ if ( bDown ) // must go down ?
+ {
+ m_timeDown = 0.7f;
+ }
+ else
+ {
+ m_timeDown = 0.0f;
+ }
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(-3.0f, 7.0f, 0.0f);
+ pos = Math::Transform(*mat, pos); // position of carousel
+ m_supportPos = pos;
+
+ m_phase = TPP_UP;
+ m_progress = 0.0f;
+ m_delay = m_timeUp;
+ m_time = 0.0f;
+
+ if ( m_timeUp > 0.0f )
+ {
+ SoundManip(m_timeUp, 1.0f, 0.5f);
+ }
+
+ m_lastParticule = 0.0f;
+
+//? m_camera->StartCentering(m_object, Math::PI*0.60f, 99.9f, 5.0f, 0.5f);
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskPen::IsEnded()
+{
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+ m_progress = 0.0f;
+
+ if ( m_phase == TPP_UP )
+ {
+ m_phase = TPP_TURN;
+ m_progress = 0.0f;
+ m_delay = fabs(m_oldAngle-m_newAngle)/Math::PI;
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+ if ( m_delay > 0.0f )
+ {
+ SoundManip(m_delay, 1.0f, 1.0f);
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TPP_TURN )
+ {
+ m_sound->Play(SOUND_PSHHH2, m_supportPos, 1.0f, 1.4f);
+ m_phase = TPP_DOWN;
+ m_progress = 0.0f;
+ m_delay = m_timeDown;
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+ return ERR_CONTINUE;
+ }
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskPen::Abort()
+{
+//? m_camera->StopCentering(m_object, 0.5f);
+ return true;
+}
+
+
+// Plays the sound of the manipulator arm.
+
+void CTaskPen::SoundManip(float time, float amplitude, float frequency)
+{
+ int i;
+
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f*frequency, true);
+ m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, 0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.5f*amplitude, 1.0f*frequency, time-0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.0f, 0.3f*frequency, 0.1f, SOPER_STOP);
+}
+
+
+// Converting a angle to number of pencil.
+
+int CTaskPen::AngleToRank(float angle)
+{
+//? return (int)(angle/(-45.0f*Math::PI/180.0f));
+ angle = -angle;
+ angle += (45.0f*Math::PI/180.0f)/2.0f;
+ return (int)(angle/(45.0f*Math::PI/180.0f));
+}
+
+// Converting a color to the angle of carousel of pencils.
+
+float CTaskPen::ColorToAngle(int color)
+{
+ return -45.0f*Math::PI/180.0f*ColorToRank(color);
+}
+
+// Converting a color number to the pencil (0 .. 7).
+
+int CTaskPen::ColorToRank(int color)
+{
+ if ( color == 8 ) return 1; // yellow
+ if ( color == 7 ) return 2; // orange
+ if ( color == 5 ) return 2; // pink
+ if ( color == 4 ) return 3; // red
+ if ( color == 6 ) return 4; // purple
+ if ( color == 14 ) return 5; // blue
+ if ( color == 15 ) return 5; // light blue
+ if ( color == 12 ) return 6; // green
+ if ( color == 13 ) return 6; // light green
+ if ( color == 10 ) return 7; // brown
+ if ( color == 9 ) return 7; // beige
+ return 0; // black
+}
+
diff --git a/src/object/task/taskpen.h b/src/object/task/taskpen.h
index 3c65d2e..b41c513 100644
--- a/src/object/task/taskpen.h
+++ b/src/object/task/taskpen.h
@@ -1,68 +1,68 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskpen.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-enum TaskPenPhase
-{
- TPP_UP = 1, // rises the pencil
- TPP_TURN = 2, // turns the carousel
- TPP_DOWN = 3, // descends the pencil
-};
-
-
-
-class CTaskPen : public CTask
-{
-public:
- CTaskPen(CInstanceManager* iMan, CObject* object);
- ~CTaskPen();
-
- bool EventProcess(const Event &event);
-
- Error Start(bool bDown, int color);
- Error IsEnded();
- bool Abort();
-
-protected:
- void SoundManip(float time, float amplitude, float frequency);
- int AngleToRank(float angle);
- float ColorToAngle(int color);
- int ColorToRank(int color);
-
-protected:
- bool m_bError;
- TaskPenPhase m_phase;
- float m_progress;
- float m_delay;
- float m_time;
- float m_lastParticule;
- Math::Vector m_supportPos;
-
- float m_timeUp;
- float m_oldAngle;
- float m_newAngle;
- float m_timeDown;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskpen.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "math/vector.h"
+
+
+
+enum TaskPenPhase
+{
+ TPP_UP = 1, // rises the pencil
+ TPP_TURN = 2, // turns the carousel
+ TPP_DOWN = 3, // descends the pencil
+};
+
+
+
+class CTaskPen : public CTask
+{
+public:
+ CTaskPen(CInstanceManager* iMan, CObject* object);
+ ~CTaskPen();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(bool bDown, int color);
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ void SoundManip(float time, float amplitude, float frequency);
+ int AngleToRank(float angle);
+ float ColorToAngle(int color);
+ int ColorToRank(int color);
+
+protected:
+ bool m_bError;
+ TaskPenPhase m_phase;
+ float m_progress;
+ float m_delay;
+ float m_time;
+ float m_lastParticule;
+ Math::Vector m_supportPos;
+
+ float m_timeUp;
+ float m_oldAngle;
+ float m_newAngle;
+ float m_timeDown;
+};
+
diff --git a/src/object/task/taskrecover.cpp b/src/object/task/taskrecover.cpp
index d91c45d..8f603f7 100644
--- a/src/object/task/taskrecover.cpp
+++ b/src/object/task/taskrecover.cpp
@@ -1,417 +1,417 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskrecover.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskrecover.h"
-
-#include "math/geometry.h"
-#include "common/iman.h"
-#include "old/particule.h"
-#include "physics/physics.h"
-#include "ui/displaytext.h"
-
-
-const float ENERGY_RECOVER = 0.25f; // energy consumed by recovery
-const float RECOVER_DIST = 11.8f;
-
-
-
-// Object's constructor.
-
-CTaskRecover::CTaskRecover(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_ruin = 0;
- m_soundChannel = -1;
-}
-
-// Object's constructor.
-
-CTaskRecover::~CTaskRecover()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskRecover::EventProcess(const Event &event)
-{
- CObject* power;
- Math::Vector pos, speed;
- Math::Point dim;
- float a, g, cirSpeed, angle, energy, dist, linSpeed;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- if ( m_phase == TRP_TURN ) // preliminary rotation?
- {
- a = m_object->RetAngleY(0);
- g = m_angle;
- cirSpeed = Math::Direction(a, g)*1.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- return true;
- }
-
- m_progress += event.rTime*m_speed; // others advance
- m_time += event.rTime;
-
- if ( m_phase == TRP_DOWN )
- {
- angle = Math::PropAngle(126, -10, m_progress);
- m_object->SetAngleZ(2, angle);
- m_object->SetAngleZ(4, angle);
-
- angle = Math::PropAngle(-144, 0, m_progress);
- m_object->SetAngleZ(3, angle);
- m_object->SetAngleZ(5, angle);
- }
-
- if ( m_phase == TRP_MOVE ) // preliminary forward/backward?
- {
- dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0));
- linSpeed = 0.0f;
- if ( dist > RECOVER_DIST ) linSpeed = 1.0f;
- if ( dist < RECOVER_DIST ) linSpeed = -1.0f;
- m_physics->SetMotorSpeedX(linSpeed); // forward/backward
- return true;
- }
-
- if ( m_phase == TRP_OPER )
- {
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- power->SetEnergy(energy-ENERGY_RECOVER*event.rTime*m_speed);
- }
-
- speed.x = (Math::Rand()-0.5f)*0.1f*m_progress;
- speed.y = (Math::Rand()-0.5f)*0.1f*m_progress;
- speed.z = (Math::Rand()-0.5f)*0.1f*m_progress;
- m_ruin->SetCirVibration(speed);
-
- if ( m_progress >= 0.75f )
- {
- m_ruin->SetZoom(0, 1.0f-(m_progress-0.75f)/0.25f);
- }
-
- if ( m_progress > 0.5f && m_progress < 0.8f )
- {
- m_metal->SetZoom(0, (m_progress-0.5f)/0.3f);
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.02f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_recoverPos;
- pos.x += (Math::Rand()-0.5f)*8.0f*(1.0f-m_progress);
- pos.z += (Math::Rand()-0.5f)*8.0f*(1.0f-m_progress);
- pos.y -= 4.0f;
- speed.x = (Math::Rand()-0.5f)*0.0f;
- speed.z = (Math::Rand()-0.5f)*0.0f;
- speed.y = Math::Rand()*15.0f;
- dim.x = Math::Rand()*2.0f+1.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIRECOVER, 1.0f, 0.0f, 0.0f);
- }
- }
-
- if ( m_phase == TRP_UP )
- {
- angle = Math::PropAngle(-10, 126, m_progress);
- m_object->SetAngleZ(2, angle);
- m_object->SetAngleZ(4, angle);
-
- angle = Math::PropAngle(0, -144, m_progress);
- m_object->SetAngleZ(3, angle);
- m_object->SetAngleZ(5, angle);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.02f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_recoverPos;
- pos.y -= 4.0f;
- speed.x = (Math::Rand()-0.5f)*0.0f;
- speed.z = (Math::Rand()-0.5f)*0.0f;
- speed.y = Math::Rand()*15.0f;
- dim.x = Math::Rand()*2.0f+1.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIRECOVER, 1.0f, 0.0f, 0.0f);
- }
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskRecover::Start()
-{
- CObject* power;
- Math::Matrix* mat;
- Math::Vector pos, iPos, oPos;
- float energy;
-
- ObjectType type;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() ) return ERR_RECOVER_VEH;
-
- type = m_object->RetType();
- if ( type != OBJECT_MOBILErr ) return ERR_RECOVER_VEH;
-
- power = m_object->RetPower();
- if ( power == 0 ) return ERR_RECOVER_ENERGY;
- energy = power->RetEnergy();
- if ( energy < ENERGY_RECOVER/power->RetCapacity()+0.05f ) return ERR_RECOVER_ENERGY;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(RECOVER_DIST, 3.3f, 0.0f);
- pos = Transform(*mat, pos); // position in front
- m_recoverPos = pos;
-
- m_ruin = SearchRuin();
- if ( m_ruin == 0 ) return ERR_RECOVER_NULL;
- m_ruin->SetLock(true); // ruin no longer usable
-
- iPos = m_object->RetPosition(0);
- oPos = m_ruin->RetPosition(0);
- m_angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
-
- m_metal = 0;
-
- m_phase = TRP_TURN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
-
- m_bError = false; // ok
-
- m_camera->StartCentering(m_object, Math::PI*0.85f, 99.9f, 10.0f, 3.0f);
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskRecover::IsEnded()
-{
- Math::Matrix* mat;
- Math::Vector pos, speed, goal;
- Math::Point dim;
- float angle, dist, time;
- int i;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_phase == TRP_TURN ) // preliminary rotation?
- {
- angle = m_object->RetAngleY(0);
- angle = Math::NormAngle(angle); // 0..2*Math::PI
-
- if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) )
- {
- m_physics->SetMotorSpeedZ(0.0f);
-
- dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0));
- if ( dist > RECOVER_DIST )
- {
- time = m_physics->RetLinTimeLength(dist-RECOVER_DIST, 1.0f);
- m_speed = 1.0f/time;
- }
- else
- {
- time = m_physics->RetLinTimeLength(RECOVER_DIST-dist, -1.0f);
- m_speed = 1.0f/time;
- }
- m_phase = TRP_MOVE;
- m_progress = 0.0f;
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TRP_MOVE ) // preliminary advance?
- {
- dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0));
-
- if ( dist >= RECOVER_DIST-1.0f &&
- dist <= RECOVER_DIST+1.0f )
- {
- m_physics->SetMotorSpeedX(0.0f);
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(RECOVER_DIST, 3.3f, 0.0f);
- pos = Transform(*mat, pos); // position in front
- m_recoverPos = pos;
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.9f, true);
- m_sound->AddEnvelope(i, 1.0f, 1.5f, 0.3f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 1.0f, 1.5f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.9f, 0.3f, SOPER_STOP);
-
- m_phase = TRP_DOWN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.5f;
- m_time = 0.0f;
- }
- else
- {
- if ( m_progress > 1.0f ) // timeout?
- {
- m_ruin->SetLock(false); // usable again
- m_camera->StopCentering(m_object, 2.0f);
- return ERR_RECOVER_NULL;
- }
- }
- return ERR_CONTINUE;
- }
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( m_phase == TRP_DOWN )
- {
- m_metal = new CObject(m_iMan);
- if ( !m_metal->CreateResource(m_recoverPos, 0.0f, OBJECT_METAL) )
- {
- delete m_metal;
- m_metal = 0;
- Abort();
- m_bError = true;
- m_displayText->DisplayError(ERR_TOOMANY, m_object);
- return ERR_STOP;
- }
- m_metal->SetLock(true); // metal not yet usable
- m_metal->SetZoom(0, 0.0f);
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(RECOVER_DIST, 3.1f, 3.9f);
- pos = Transform(*mat, pos);
- goal = Math::Vector(RECOVER_DIST, 3.1f, -3.9f);
- goal = Transform(*mat, goal);
- m_particule->CreateRay(pos, goal, PARTIRAY2,
- Math::Point(2.0f, 2.0f), 8.0f);
-
- m_soundChannel = m_sound->Play(SOUND_RECOVER, m_ruin->RetPosition(0), 0.0f, 1.0f, true);
- m_sound->AddEnvelope(m_soundChannel, 0.6f, 1.0f, 2.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.6f, 1.0f, 4.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.7f, 2.0f, SOPER_STOP);
-
- m_phase = TRP_OPER;
- m_speed = 1.0f/8.0f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TRP_OPER )
- {
- m_metal->SetZoom(0, 1.0f);
-
- m_ruin->DeleteObject(); // destroys the ruin
- delete m_ruin;
- m_ruin = 0;
-
- m_soundChannel = -1;
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.9f, true);
- m_sound->AddEnvelope(i, 1.0f, 1.5f, 0.3f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 1.0f, 1.5f, 1.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.9f, 0.3f, SOPER_STOP);
-
- m_phase = TRP_UP;
- m_speed = 1.0f/1.5f;
- return ERR_CONTINUE;
- }
-
- m_metal->SetLock(false); // metal usable
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskRecover::Abort()
-{
- m_object->SetAngleZ(2, 126.0f*Math::PI/180.0f);
- m_object->SetAngleZ(4, 126.0f*Math::PI/180.0f);
- m_object->SetAngleZ(3, -144.0f*Math::PI/180.0f);
- m_object->SetAngleZ(5, -144.0f*Math::PI/180.0f); // rest
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- m_camera->StopCentering(m_object, 2.0f);
- return true;
-}
-
-
-// Seeks if a ruin is in front of the vehicle.
-
-CObject* CTaskRecover::SearchRuin()
-{
- CObject *pObj, *pBest;
- Math::Vector oPos;
- ObjectType type;
- float dist, min;
- int i;
-
- pBest = 0;
- min = 100000.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_RUINmobilew1 ||
- type == OBJECT_RUINmobilew2 ||
- type == OBJECT_RUINmobilet1 ||
- type == OBJECT_RUINmobilet2 ||
- type == OBJECT_RUINmobiler1 ||
- type == OBJECT_RUINmobiler2 ) // vehicle in ruin?
- {
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, m_recoverPos);
- if ( dist > 40.0f ) continue;
-
- if ( dist < min )
- {
- min = dist;
- pBest = pObj;
- }
- }
-
- }
- return pBest;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskrecover.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskrecover.h"
+
+#include "math/geometry.h"
+#include "common/iman.h"
+#include "old/particule.h"
+#include "physics/physics.h"
+#include "ui/displaytext.h"
+
+
+const float ENERGY_RECOVER = 0.25f; // energy consumed by recovery
+const float RECOVER_DIST = 11.8f;
+
+
+
+// Object's constructor.
+
+CTaskRecover::CTaskRecover(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_ruin = 0;
+ m_soundChannel = -1;
+}
+
+// Object's constructor.
+
+CTaskRecover::~CTaskRecover()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskRecover::EventProcess(const Event &event)
+{
+ CObject* power;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float a, g, cirSpeed, angle, energy, dist, linSpeed;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ if ( m_phase == TRP_TURN ) // preliminary rotation?
+ {
+ a = m_object->RetAngleY(0);
+ g = m_angle;
+ cirSpeed = Math::Direction(a, g)*1.0f;
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
+ return true;
+ }
+
+ m_progress += event.rTime*m_speed; // others advance
+ m_time += event.rTime;
+
+ if ( m_phase == TRP_DOWN )
+ {
+ angle = Math::PropAngle(126, -10, m_progress);
+ m_object->SetAngleZ(2, angle);
+ m_object->SetAngleZ(4, angle);
+
+ angle = Math::PropAngle(-144, 0, m_progress);
+ m_object->SetAngleZ(3, angle);
+ m_object->SetAngleZ(5, angle);
+ }
+
+ if ( m_phase == TRP_MOVE ) // preliminary forward/backward?
+ {
+ dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0));
+ linSpeed = 0.0f;
+ if ( dist > RECOVER_DIST ) linSpeed = 1.0f;
+ if ( dist < RECOVER_DIST ) linSpeed = -1.0f;
+ m_physics->SetMotorSpeedX(linSpeed); // forward/backward
+ return true;
+ }
+
+ if ( m_phase == TRP_OPER )
+ {
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ power->SetEnergy(energy-ENERGY_RECOVER*event.rTime*m_speed);
+ }
+
+ speed.x = (Math::Rand()-0.5f)*0.1f*m_progress;
+ speed.y = (Math::Rand()-0.5f)*0.1f*m_progress;
+ speed.z = (Math::Rand()-0.5f)*0.1f*m_progress;
+ m_ruin->SetCirVibration(speed);
+
+ if ( m_progress >= 0.75f )
+ {
+ m_ruin->SetZoom(0, 1.0f-(m_progress-0.75f)/0.25f);
+ }
+
+ if ( m_progress > 0.5f && m_progress < 0.8f )
+ {
+ m_metal->SetZoom(0, (m_progress-0.5f)/0.3f);
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.02f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_recoverPos;
+ pos.x += (Math::Rand()-0.5f)*8.0f*(1.0f-m_progress);
+ pos.z += (Math::Rand()-0.5f)*8.0f*(1.0f-m_progress);
+ pos.y -= 4.0f;
+ speed.x = (Math::Rand()-0.5f)*0.0f;
+ speed.z = (Math::Rand()-0.5f)*0.0f;
+ speed.y = Math::Rand()*15.0f;
+ dim.x = Math::Rand()*2.0f+1.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIRECOVER, 1.0f, 0.0f, 0.0f);
+ }
+ }
+
+ if ( m_phase == TRP_UP )
+ {
+ angle = Math::PropAngle(-10, 126, m_progress);
+ m_object->SetAngleZ(2, angle);
+ m_object->SetAngleZ(4, angle);
+
+ angle = Math::PropAngle(0, -144, m_progress);
+ m_object->SetAngleZ(3, angle);
+ m_object->SetAngleZ(5, angle);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.02f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_recoverPos;
+ pos.y -= 4.0f;
+ speed.x = (Math::Rand()-0.5f)*0.0f;
+ speed.z = (Math::Rand()-0.5f)*0.0f;
+ speed.y = Math::Rand()*15.0f;
+ dim.x = Math::Rand()*2.0f+1.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIRECOVER, 1.0f, 0.0f, 0.0f);
+ }
+ }
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskRecover::Start()
+{
+ CObject* power;
+ Math::Matrix* mat;
+ Math::Vector pos, iPos, oPos;
+ float energy;
+
+ ObjectType type;
+
+ m_bError = true; // operation impossible
+ if ( !m_physics->RetLand() ) return ERR_RECOVER_VEH;
+
+ type = m_object->RetType();
+ if ( type != OBJECT_MOBILErr ) return ERR_RECOVER_VEH;
+
+ power = m_object->RetPower();
+ if ( power == 0 ) return ERR_RECOVER_ENERGY;
+ energy = power->RetEnergy();
+ if ( energy < ENERGY_RECOVER/power->RetCapacity()+0.05f ) return ERR_RECOVER_ENERGY;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(RECOVER_DIST, 3.3f, 0.0f);
+ pos = Transform(*mat, pos); // position in front
+ m_recoverPos = pos;
+
+ m_ruin = SearchRuin();
+ if ( m_ruin == 0 ) return ERR_RECOVER_NULL;
+ m_ruin->SetLock(true); // ruin no longer usable
+
+ iPos = m_object->RetPosition(0);
+ oPos = m_ruin->RetPosition(0);
+ m_angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+
+ m_metal = 0;
+
+ m_phase = TRP_TURN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+
+ m_bError = false; // ok
+
+ m_camera->StartCentering(m_object, Math::PI*0.85f, 99.9f, 10.0f, 3.0f);
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskRecover::IsEnded()
+{
+ Math::Matrix* mat;
+ Math::Vector pos, speed, goal;
+ Math::Point dim;
+ float angle, dist, time;
+ int i;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_phase == TRP_TURN ) // preliminary rotation?
+ {
+ angle = m_object->RetAngleY(0);
+ angle = Math::NormAngle(angle); // 0..2*Math::PI
+
+ if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) )
+ {
+ m_physics->SetMotorSpeedZ(0.0f);
+
+ dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0));
+ if ( dist > RECOVER_DIST )
+ {
+ time = m_physics->RetLinTimeLength(dist-RECOVER_DIST, 1.0f);
+ m_speed = 1.0f/time;
+ }
+ else
+ {
+ time = m_physics->RetLinTimeLength(RECOVER_DIST-dist, -1.0f);
+ m_speed = 1.0f/time;
+ }
+ m_phase = TRP_MOVE;
+ m_progress = 0.0f;
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TRP_MOVE ) // preliminary advance?
+ {
+ dist = Math::Distance(m_object->RetPosition(0), m_ruin->RetPosition(0));
+
+ if ( dist >= RECOVER_DIST-1.0f &&
+ dist <= RECOVER_DIST+1.0f )
+ {
+ m_physics->SetMotorSpeedX(0.0f);
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(RECOVER_DIST, 3.3f, 0.0f);
+ pos = Transform(*mat, pos); // position in front
+ m_recoverPos = pos;
+
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.9f, true);
+ m_sound->AddEnvelope(i, 1.0f, 1.5f, 0.3f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 1.0f, 1.5f, 1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.0f, 0.9f, 0.3f, SOPER_STOP);
+
+ m_phase = TRP_DOWN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.5f;
+ m_time = 0.0f;
+ }
+ else
+ {
+ if ( m_progress > 1.0f ) // timeout?
+ {
+ m_ruin->SetLock(false); // usable again
+ m_camera->StopCentering(m_object, 2.0f);
+ return ERR_RECOVER_NULL;
+ }
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+ m_progress = 0.0f;
+
+ if ( m_phase == TRP_DOWN )
+ {
+ m_metal = new CObject(m_iMan);
+ if ( !m_metal->CreateResource(m_recoverPos, 0.0f, OBJECT_METAL) )
+ {
+ delete m_metal;
+ m_metal = 0;
+ Abort();
+ m_bError = true;
+ m_displayText->DisplayError(ERR_TOOMANY, m_object);
+ return ERR_STOP;
+ }
+ m_metal->SetLock(true); // metal not yet usable
+ m_metal->SetZoom(0, 0.0f);
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(RECOVER_DIST, 3.1f, 3.9f);
+ pos = Transform(*mat, pos);
+ goal = Math::Vector(RECOVER_DIST, 3.1f, -3.9f);
+ goal = Transform(*mat, goal);
+ m_particule->CreateRay(pos, goal, PARTIRAY2,
+ Math::Point(2.0f, 2.0f), 8.0f);
+
+ m_soundChannel = m_sound->Play(SOUND_RECOVER, m_ruin->RetPosition(0), 0.0f, 1.0f, true);
+ m_sound->AddEnvelope(m_soundChannel, 0.6f, 1.0f, 2.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.6f, 1.0f, 4.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.7f, 2.0f, SOPER_STOP);
+
+ m_phase = TRP_OPER;
+ m_speed = 1.0f/8.0f;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TRP_OPER )
+ {
+ m_metal->SetZoom(0, 1.0f);
+
+ m_ruin->DeleteObject(); // destroys the ruin
+ delete m_ruin;
+ m_ruin = 0;
+
+ m_soundChannel = -1;
+
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.9f, true);
+ m_sound->AddEnvelope(i, 1.0f, 1.5f, 0.3f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 1.0f, 1.5f, 1.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.0f, 0.9f, 0.3f, SOPER_STOP);
+
+ m_phase = TRP_UP;
+ m_speed = 1.0f/1.5f;
+ return ERR_CONTINUE;
+ }
+
+ m_metal->SetLock(false); // metal usable
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskRecover::Abort()
+{
+ m_object->SetAngleZ(2, 126.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(4, 126.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(3, -144.0f*Math::PI/180.0f);
+ m_object->SetAngleZ(5, -144.0f*Math::PI/180.0f); // rest
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ m_camera->StopCentering(m_object, 2.0f);
+ return true;
+}
+
+
+// Seeks if a ruin is in front of the vehicle.
+
+CObject* CTaskRecover::SearchRuin()
+{
+ CObject *pObj, *pBest;
+ Math::Vector oPos;
+ ObjectType type;
+ float dist, min;
+ int i;
+
+ pBest = 0;
+ min = 100000.0f;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_RUINmobilew1 ||
+ type == OBJECT_RUINmobilew2 ||
+ type == OBJECT_RUINmobilet1 ||
+ type == OBJECT_RUINmobilet2 ||
+ type == OBJECT_RUINmobiler1 ||
+ type == OBJECT_RUINmobiler2 ) // vehicle in ruin?
+ {
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, m_recoverPos);
+ if ( dist > 40.0f ) continue;
+
+ if ( dist < min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+
+ }
+ return pBest;
+}
+
diff --git a/src/object/task/taskrecover.h b/src/object/task/taskrecover.h
index 5ee696a..8af6353 100644
--- a/src/object/task/taskrecover.h
+++ b/src/object/task/taskrecover.h
@@ -1,66 +1,66 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskrecover.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-enum TaskRecoverPhase
-{
- TRP_TURN = 1, // turns
- TRP_MOVE = 2, // advance
- TRP_DOWN = 3, // descends
- TRP_OPER = 4, // operates
- TRP_UP = 5, // back
-};
-
-
-
-class CTaskRecover : public CTask
-{
-public:
- CTaskRecover(CInstanceManager* iMan, CObject* object);
- ~CTaskRecover();
-
- bool EventProcess(const Event &event);
-
- Error Start();
- Error IsEnded();
- bool Abort();
-
-protected:
- CObject* SearchRuin();
-
-protected:
- TaskRecoverPhase m_phase;
- float m_progress;
- float m_speed;
- float m_time;
- float m_angle;
- float m_lastParticule;
- bool m_bError;
- CObject* m_ruin;
- CObject* m_metal;
- Math::Vector m_recoverPos;
- int m_soundChannel;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskrecover.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "math/vector.h"
+
+
+
+enum TaskRecoverPhase
+{
+ TRP_TURN = 1, // turns
+ TRP_MOVE = 2, // advance
+ TRP_DOWN = 3, // descends
+ TRP_OPER = 4, // operates
+ TRP_UP = 5, // back
+};
+
+
+
+class CTaskRecover : public CTask
+{
+public:
+ CTaskRecover(CInstanceManager* iMan, CObject* object);
+ ~CTaskRecover();
+
+ bool EventProcess(const Event &event);
+
+ Error Start();
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ CObject* SearchRuin();
+
+protected:
+ TaskRecoverPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_time;
+ float m_angle;
+ float m_lastParticule;
+ bool m_bError;
+ CObject* m_ruin;
+ CObject* m_metal;
+ Math::Vector m_recoverPos;
+ int m_soundChannel;
+};
+
diff --git a/src/object/task/taskreset.cpp b/src/object/task/taskreset.cpp
index ab41076..2366fea 100644
--- a/src/object/task/taskreset.cpp
+++ b/src/object/task/taskreset.cpp
@@ -1,330 +1,330 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskreset.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskreset.h"
-
-#include "common/iman.h"
-#include "object/brain.h"
-#include "object/robotmain.h"
-
-
-
-const float RESET_DELAY_ZOOM = 0.7f;
-const float RESET_DELAY_MOVE = 0.7f;
-
-
-
-
-// Object's constructor.
-
-CTaskReset::CTaskReset(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskReset::~CTaskReset()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskReset::EventProcess(const Event &event)
-{
- Math::Vector pos, speed;
- Math::Point dim;
- float angle, duration;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_time += event.rTime;
- m_progress += event.rTime*m_speed;
-
- if ( m_phase == TRSP_ZOUT )
- {
- angle = m_iAngle;
- angle += powf(m_progress*5.0f, 2.0f); // accelerates
- m_object->SetAngleY(0, angle);
- m_object->SetZoom(0, 1.0f-m_progress);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_begin;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 5.0f+Math::Rand()*5.0f;
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
-
- pos = m_begin;
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = Math::Rand()*10.0f;
- speed *= 1.0f-m_progress*0.5f;
- pos += speed*1.5f;
- speed = -speed;
- dim.x = 0.6f;
- dim.y = dim.x;
- pos.y += dim.y;
- duration = Math::Rand()*1.5f+1.5f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
- duration, 0.0f,
- duration*0.9f, 0.7f);
- }
- }
-
- if ( m_phase == TRSP_MOVE )
- {
- pos = m_begin+(m_goal-m_begin)*m_progress;
- m_object->SetPosition(0, pos);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 2.0f+Math::Rand()*2.0f;
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
- }
- }
-
- if ( m_phase == TRSP_ZIN )
- {
- angle = m_angle.y;
- angle += -powf((1.0f-m_progress)*5.0f, 2.0f); // slows
- m_object->SetAngleY(0, angle);
- m_object->SetZoom(0, m_progress);
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_goal;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 5.0f+Math::Rand()*5.0f;
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
-
- pos = m_goal;
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = Math::Rand()*10.0f;
- speed *= 0.5f+m_progress*0.5f;
- dim.x = 0.6f;
- dim.y = dim.x;
- pos.y += dim.y;
- duration = Math::Rand()*1.5f+1.5f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
- duration, 0.0f,
- duration*0.9f, 0.7f);
- }
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-// A positive angle makes a turn right.
-
-Error CTaskReset::Start(Math::Vector goal, Math::Vector angle)
-{
- CObject* fret;
- int i;
-
- fret = m_object->RetFret();
- if ( fret != 0 && fret->RetResetCap() == RESET_MOVE )
- {
- fret->SetTruck(0);
- m_object->SetFret(0); // does nothing
- }
-
- if ( !m_main->RetNiceReset() ) // quick return?
- {
- m_object->SetPosition(0, goal);
- m_object->SetAngle(0, angle);
- m_brain->RunProgram(m_object->RetResetRun());
-
- m_bError = false;
- return ERR_OK;
- }
-
- m_begin = m_object->RetPosition(0);
- m_goal = goal;
- m_angle = angle;
-
- if ( SearchVehicle() ) // starting location occupied?
- {
- m_bError = true;
- return ERR_RESET_NEAR;
- }
-
- m_iAngle = m_object->RetAngleY(0);
- m_time = 0.0f;
- m_phase = TRSP_ZOUT;
- m_speed = 1.0f/RESET_DELAY_ZOOM;
- m_progress = 0.0f;
- m_lastParticule = 0.0f;
-
- m_object->SetResetBusy(true);
-
- i = m_sound->Play(SOUND_GGG, m_begin, 1.0f, 2.0f, true);
- m_sound->AddEnvelope(i, 0.0f, 0.5f, RESET_DELAY_ZOOM, SOPER_STOP);
-
- m_bError = false;
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskReset::IsEnded()
-{
- CObject* power;
- float dist;
- int i;
-
- if ( !m_main->RetNiceReset() ) // quick return?
- {
- return ERR_STOP;
- }
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- if ( m_phase == TRSP_ZOUT )
- {
- dist = Math::Distance(m_begin, m_goal);
- m_phase = TRSP_MOVE;
- m_speed = 1.0f/(dist*RESET_DELAY_MOVE/100.0f);
- m_progress = 0.0f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TRSP_MOVE )
- {
- m_object->SetPosition(0, m_goal);
- m_object->SetAngle(0, m_angle);
-
- i = m_sound->Play(SOUND_GGG, m_goal, 1.0f, 0.5f, true);
- m_sound->AddEnvelope(i, 0.0f, 2.0f, RESET_DELAY_ZOOM, SOPER_STOP);
-
- m_phase = TRSP_ZIN;
- m_speed = 1.0f/RESET_DELAY_ZOOM;
- m_progress = 0.0f;
- return ERR_CONTINUE;
- }
-
- m_object->SetAngle(0, m_angle);
- m_object->SetZoom(0, 1.0f);
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- power->SetEnergy(power->RetCapacity()); // refueling
- }
-
- m_brain->RunProgram(m_object->RetResetRun());
- m_object->SetResetBusy(false);
- return ERR_STOP;
-}
-
-
-// Seeks if a vehicle is too close.
-
-bool CTaskReset::SearchVehicle()
-{
- CObject* pObj;
- Math::Vector oPos;
- ObjectType type;
- float oRadius, dist;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
-
- type = pObj->RetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_TECH &&
- type != OBJECT_MOBILEfa &&
- type != OBJECT_MOBILEta &&
- type != OBJECT_MOBILEwa &&
- type != OBJECT_MOBILEia &&
- type != OBJECT_MOBILEfc &&
- type != OBJECT_MOBILEtc &&
- type != OBJECT_MOBILEwc &&
- type != OBJECT_MOBILEic &&
- type != OBJECT_MOBILEfi &&
- type != OBJECT_MOBILEti &&
- type != OBJECT_MOBILEwi &&
- type != OBJECT_MOBILEii &&
- type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis &&
- type != OBJECT_MOBILErt &&
- type != OBJECT_MOBILErc &&
- type != OBJECT_MOBILErr &&
- type != OBJECT_MOBILErs &&
- type != OBJECT_MOBILEsa &&
- type != OBJECT_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_MOBILEdr &&
- type != OBJECT_MOTHER &&
- type != OBJECT_ANT &&
- type != OBJECT_SPIDER &&
- type != OBJECT_BEE &&
- type != OBJECT_WORM ) continue;
-
- if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
- dist = Math::Distance(oPos, m_goal)-oRadius;
-
- if ( dist < 5.0f ) return true;
- }
-
- return false;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskreset.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskreset.h"
+
+#include "common/iman.h"
+#include "object/brain.h"
+#include "object/robotmain.h"
+
+
+
+const float RESET_DELAY_ZOOM = 0.7f;
+const float RESET_DELAY_MOVE = 0.7f;
+
+
+
+
+// Object's constructor.
+
+CTaskReset::CTaskReset(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+}
+
+// Object's destructor.
+
+CTaskReset::~CTaskReset()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskReset::EventProcess(const Event &event)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float angle, duration;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ m_time += event.rTime;
+ m_progress += event.rTime*m_speed;
+
+ if ( m_phase == TRSP_ZOUT )
+ {
+ angle = m_iAngle;
+ angle += powf(m_progress*5.0f, 2.0f); // accelerates
+ m_object->SetAngleY(0, angle);
+ m_object->SetZoom(0, 1.0f-m_progress);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_begin;
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 5.0f+Math::Rand()*5.0f;
+ dim.x = Math::Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
+
+ pos = m_begin;
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ speed.y = Math::Rand()*10.0f;
+ speed *= 1.0f-m_progress*0.5f;
+ pos += speed*1.5f;
+ speed = -speed;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ pos.y += dim.y;
+ duration = Math::Rand()*1.5f+1.5f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
+ duration, 0.0f,
+ duration*0.9f, 0.7f);
+ }
+ }
+
+ if ( m_phase == TRSP_MOVE )
+ {
+ pos = m_begin+(m_goal-m_begin)*m_progress;
+ m_object->SetPosition(0, pos);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 2.0f+Math::Rand()*2.0f;
+ dim.x = Math::Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
+ }
+ }
+
+ if ( m_phase == TRSP_ZIN )
+ {
+ angle = m_angle.y;
+ angle += -powf((1.0f-m_progress)*5.0f, 2.0f); // slows
+ m_object->SetAngleY(0, angle);
+ m_object->SetZoom(0, m_progress);
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_goal;
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 5.0f+Math::Rand()*5.0f;
+ dim.x = Math::Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
+
+ pos = m_goal;
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ speed.y = Math::Rand()*10.0f;
+ speed *= 0.5f+m_progress*0.5f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ pos.y += dim.y;
+ duration = Math::Rand()*1.5f+1.5f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
+ duration, 0.0f,
+ duration*0.9f, 0.7f);
+ }
+ }
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+// A positive angle makes a turn right.
+
+Error CTaskReset::Start(Math::Vector goal, Math::Vector angle)
+{
+ CObject* fret;
+ int i;
+
+ fret = m_object->RetFret();
+ if ( fret != 0 && fret->RetResetCap() == RESET_MOVE )
+ {
+ fret->SetTruck(0);
+ m_object->SetFret(0); // does nothing
+ }
+
+ if ( !m_main->RetNiceReset() ) // quick return?
+ {
+ m_object->SetPosition(0, goal);
+ m_object->SetAngle(0, angle);
+ m_brain->RunProgram(m_object->RetResetRun());
+
+ m_bError = false;
+ return ERR_OK;
+ }
+
+ m_begin = m_object->RetPosition(0);
+ m_goal = goal;
+ m_angle = angle;
+
+ if ( SearchVehicle() ) // starting location occupied?
+ {
+ m_bError = true;
+ return ERR_RESET_NEAR;
+ }
+
+ m_iAngle = m_object->RetAngleY(0);
+ m_time = 0.0f;
+ m_phase = TRSP_ZOUT;
+ m_speed = 1.0f/RESET_DELAY_ZOOM;
+ m_progress = 0.0f;
+ m_lastParticule = 0.0f;
+
+ m_object->SetResetBusy(true);
+
+ i = m_sound->Play(SOUND_GGG, m_begin, 1.0f, 2.0f, true);
+ m_sound->AddEnvelope(i, 0.0f, 0.5f, RESET_DELAY_ZOOM, SOPER_STOP);
+
+ m_bError = false;
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskReset::IsEnded()
+{
+ CObject* power;
+ float dist;
+ int i;
+
+ if ( !m_main->RetNiceReset() ) // quick return?
+ {
+ return ERR_STOP;
+ }
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ if ( m_phase == TRSP_ZOUT )
+ {
+ dist = Math::Distance(m_begin, m_goal);
+ m_phase = TRSP_MOVE;
+ m_speed = 1.0f/(dist*RESET_DELAY_MOVE/100.0f);
+ m_progress = 0.0f;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TRSP_MOVE )
+ {
+ m_object->SetPosition(0, m_goal);
+ m_object->SetAngle(0, m_angle);
+
+ i = m_sound->Play(SOUND_GGG, m_goal, 1.0f, 0.5f, true);
+ m_sound->AddEnvelope(i, 0.0f, 2.0f, RESET_DELAY_ZOOM, SOPER_STOP);
+
+ m_phase = TRSP_ZIN;
+ m_speed = 1.0f/RESET_DELAY_ZOOM;
+ m_progress = 0.0f;
+ return ERR_CONTINUE;
+ }
+
+ m_object->SetAngle(0, m_angle);
+ m_object->SetZoom(0, 1.0f);
+
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ power->SetEnergy(power->RetCapacity()); // refueling
+ }
+
+ m_brain->RunProgram(m_object->RetResetRun());
+ m_object->SetResetBusy(false);
+ return ERR_STOP;
+}
+
+
+// Seeks if a vehicle is too close.
+
+bool CTaskReset::SearchVehicle()
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ ObjectType type;
+ float oRadius, dist;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_HUMAN &&
+ type != OBJECT_TECH &&
+ type != OBJECT_MOBILEfa &&
+ type != OBJECT_MOBILEta &&
+ type != OBJECT_MOBILEwa &&
+ type != OBJECT_MOBILEia &&
+ type != OBJECT_MOBILEfc &&
+ type != OBJECT_MOBILEtc &&
+ type != OBJECT_MOBILEwc &&
+ type != OBJECT_MOBILEic &&
+ type != OBJECT_MOBILEfi &&
+ type != OBJECT_MOBILEti &&
+ type != OBJECT_MOBILEwi &&
+ type != OBJECT_MOBILEii &&
+ type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis &&
+ type != OBJECT_MOBILErt &&
+ type != OBJECT_MOBILErc &&
+ type != OBJECT_MOBILErr &&
+ type != OBJECT_MOBILErs &&
+ type != OBJECT_MOBILEsa &&
+ type != OBJECT_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_MOBILEdr &&
+ type != OBJECT_MOTHER &&
+ type != OBJECT_ANT &&
+ type != OBJECT_SPIDER &&
+ type != OBJECT_BEE &&
+ type != OBJECT_WORM ) continue;
+
+ if ( !pObj->GetCrashSphere(0, oPos, oRadius) ) continue;
+ dist = Math::Distance(oPos, m_goal)-oRadius;
+
+ if ( dist < 5.0f ) return true;
+ }
+
+ return false;
+}
+
diff --git a/src/object/task/taskreset.h b/src/object/task/taskreset.h
index 2c885f9..17a4441 100644
--- a/src/object/task/taskreset.h
+++ b/src/object/task/taskreset.h
@@ -1,63 +1,63 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskreset.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-enum TaskResetPhase
-{
- TRSP_ZOUT = 1, // disappears
- TRSP_MOVE = 2, // moves
- TRSP_ZIN = 3, // reappears
-};
-
-
-
-class CTaskReset : public CTask
-{
-public:
- CTaskReset(CInstanceManager* iMan, CObject* object);
- ~CTaskReset();
-
- bool EventProcess(const Event &event);
-
- Error Start(Math::Vector goal, Math::Vector angle);
- Error IsEnded();
-
-protected:
- bool SearchVehicle();
-
-protected:
- Math::Vector m_begin;
- Math::Vector m_goal;
- Math::Vector m_angle;
-
- TaskResetPhase m_phase;
- bool m_bError;
- float m_time;
- float m_speed;
- float m_progress;
- float m_lastParticule; // time of generation last particle
- float m_iAngle;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskreset.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "math/vector.h"
+
+
+
+enum TaskResetPhase
+{
+ TRSP_ZOUT = 1, // disappears
+ TRSP_MOVE = 2, // moves
+ TRSP_ZIN = 3, // reappears
+};
+
+
+
+class CTaskReset : public CTask
+{
+public:
+ CTaskReset(CInstanceManager* iMan, CObject* object);
+ ~CTaskReset();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(Math::Vector goal, Math::Vector angle);
+ Error IsEnded();
+
+protected:
+ bool SearchVehicle();
+
+protected:
+ Math::Vector m_begin;
+ Math::Vector m_goal;
+ Math::Vector m_angle;
+
+ TaskResetPhase m_phase;
+ bool m_bError;
+ float m_time;
+ float m_speed;
+ float m_progress;
+ float m_lastParticule; // time of generation last particle
+ float m_iAngle;
+};
+
diff --git a/src/object/task/tasksearch.cpp b/src/object/task/tasksearch.cpp
index cf038aa..8c083dd 100644
--- a/src/object/task/tasksearch.cpp
+++ b/src/object/task/tasksearch.cpp
@@ -1,321 +1,321 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// tasksearch.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/tasksearch.h"
-
-#include "math/geometry.h"
-#include "common/iman.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "physics/physics.h"
-#include "ui/displaytext.h"
-
-
-
-
-// Object's constructor.
-
-CTaskSearch::CTaskSearch(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_hand = TSH_UP;
-}
-
-// Object's destructor.
-
-CTaskSearch::~CTaskSearch()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskSearch::EventProcess(const Event &event)
-{
- Math::Matrix* mat;
- Math::Vector pos, speed;
- Math::Point dim;
- float angle;
- int i;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_progress += event.rTime*m_speed; // others advance
- m_time += event.rTime;
-
- if ( m_phase == TSP_DOWN ||
- m_phase == TSP_UP )
- {
- for ( i=0 ; i<3 ; i++ )
- {
- angle = (m_finalAngle[i]-m_initialAngle[i])*m_progress;
- angle += m_initialAngle[i];
- m_object->SetAngleZ(i+1, angle);
- }
- }
-
- if ( m_phase == TSP_SEARCH &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(6.5f, 0.2f, 0.0f);
- pos = Math::Transform(*mat, pos); // sensor position
-
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = 0.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGAS);
- }
-
- return true;
-}
-
-
-// Initializes the initial and final angles.
-
-void CTaskSearch::InitAngle()
-{
- int i;
-
- if ( m_hand == TSH_UP )
- {
- m_finalAngle[0] = 110.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = -110.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = -65.0f*Math::PI/180.0f; // sensor
- }
- if ( m_hand == TSH_DOWN )
- {
- m_finalAngle[0] = 25.0f*Math::PI/180.0f; // arm
- m_finalAngle[1] = -70.0f*Math::PI/180.0f; // forearm
- m_finalAngle[2] = -45.0f*Math::PI/180.0f; // sensor
- }
-
- for ( i=0 ; i<3 ; i++ )
- {
- m_initialAngle[i] = m_object->RetAngleZ(i+1);
- }
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskSearch::Start()
-{
- ObjectType type;
- Math::Vector speed;
- int i;
-
- m_bError = true;
- if ( !m_physics->RetLand() ) return ERR_SEARCH_FLY;
-
- speed = m_physics->RetMotorSpeed();
- if ( speed.x != 0.0f ||
- speed.z != 0.0f ) return ERR_SEARCH_MOTOR;
-
- type = m_object->RetType();
- if ( type != OBJECT_MOBILEfs &&
- type != OBJECT_MOBILEts &&
- type != OBJECT_MOBILEws &&
- type != OBJECT_MOBILEis ) return ERR_SEARCH_VEH;
-
- m_hand = TSH_DOWN;
- m_phase = TSP_DOWN;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
-
- InitAngle();
- m_bError = false; // ok
-
- m_camera->StartCentering(m_object, Math::PI*0.50f, 99.9f, 0.0f, 1.0f);
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, true);
- m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.9f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.3f, 0.1f, SOPER_STOP);
-
- m_physics->SetFreeze(true); // it does not move
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskSearch::IsEnded()
-{
- int i;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( m_phase == TSP_DOWN ||
- m_phase == TSP_UP )
- {
- for ( i=0 ; i<3 ; i++ )
- {
- m_object->SetAngleZ(i+1, m_finalAngle[i]);
- }
- }
-
- if ( m_phase == TSP_DOWN )
- {
- m_sound->Play(SOUND_REPAIR, m_object->RetPosition(0));
-
- m_phase = TSP_SEARCH;
- m_speed = 1.0f/4.0f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TSP_SEARCH )
- {
- CreateMark();
-
- m_hand = TSH_UP;
- InitAngle();
-
- i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, true);
- m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.1f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.9f, SOPER_CONTINUE);
- m_sound->AddEnvelope(i, 0.0f, 0.3f, 0.1f, SOPER_STOP);
-
- m_phase = TSP_UP;
- m_speed = 1.0f/1.0f;
- return ERR_CONTINUE;
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskSearch::Abort()
-{
- m_camera->StopCentering(m_object, 2.0f);
- m_physics->SetFreeze(false); // is moving again
- return true;
-}
-
-
-// Creates a mark if possible.
-
-bool CTaskSearch::CreateMark()
-{
- CObject* fret;
- ObjectType type;
- Math::Matrix* mat;
- Math::Vector pos;
- TerrainRes res;
- Error info;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(7.5f, 0.0f, 0.0f);
- pos = Math::Transform(*mat, pos); // sensor position
-
- res = m_terrain->RetResource(pos);
- if ( res == TR_NULL ) return false;
-
- type = OBJECT_NULL;
- if ( res == TR_STONE )
- {
- type = OBJECT_MARKSTONE;
- info = INFO_MARKSTONE;
- }
- if ( res == TR_URANIUM )
- {
- type = OBJECT_MARKURANIUM;
- info = INFO_MARKURANIUM;
- }
- if ( res == TR_POWER )
- {
- type = OBJECT_MARKPOWER;
- info = INFO_MARKPOWER;
- }
- if ( res == TR_KEYa )
- {
- type = OBJECT_MARKKEYa;
- info = INFO_MARKKEYa;
- }
- if ( res == TR_KEYb )
- {
- type = OBJECT_MARKKEYb;
- info = INFO_MARKKEYb;
- }
- if ( res == TR_KEYc )
- {
- type = OBJECT_MARKKEYc;
- info = INFO_MARKKEYc;
- }
- if ( res == TR_KEYd )
- {
- type = OBJECT_MARKKEYd;
- info = INFO_MARKKEYd;
- }
- if ( type == OBJECT_NULL ) return false;
-
-//? DeleteMark(type);
-
- fret = new CObject(m_iMan);
- if ( !fret->CreateResource(pos, 0.0f, type) )
- {
- delete fret;
- m_displayText->DisplayError(ERR_TOOMANY, m_object);
- return false;
- }
-
- m_displayText->DisplayError(info, pos, 5.0f, 50.0f); // displays the message
-
- return true;
-}
-
-// Destroys the marks of a given type.
-
-void CTaskSearch::DeleteMark(ObjectType type)
-{
- CObject* pObj;
- Math::Vector oPos;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( type == pObj->RetType() )
- {
- pObj->DeleteObject(); // removes the mark
- delete pObj;
- break;
- }
- }
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// tasksearch.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/tasksearch.h"
+
+#include "math/geometry.h"
+#include "common/iman.h"
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "physics/physics.h"
+#include "ui/displaytext.h"
+
+
+
+
+// Object's constructor.
+
+CTaskSearch::CTaskSearch(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_hand = TSH_UP;
+}
+
+// Object's destructor.
+
+CTaskSearch::~CTaskSearch()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskSearch::EventProcess(const Event &event)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float angle;
+ int i;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ m_progress += event.rTime*m_speed; // others advance
+ m_time += event.rTime;
+
+ if ( m_phase == TSP_DOWN ||
+ m_phase == TSP_UP )
+ {
+ for ( i=0 ; i<3 ; i++ )
+ {
+ angle = (m_finalAngle[i]-m_initialAngle[i])*m_progress;
+ angle += m_initialAngle[i];
+ m_object->SetAngleZ(i+1, angle);
+ }
+ }
+
+ if ( m_phase == TSP_SEARCH &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(6.5f, 0.2f, 0.0f);
+ pos = Math::Transform(*mat, pos); // sensor position
+
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ speed.y = 0.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGAS);
+ }
+
+ return true;
+}
+
+
+// Initializes the initial and final angles.
+
+void CTaskSearch::InitAngle()
+{
+ int i;
+
+ if ( m_hand == TSH_UP )
+ {
+ m_finalAngle[0] = 110.0f*Math::PI/180.0f; // arm
+ m_finalAngle[1] = -110.0f*Math::PI/180.0f; // forearm
+ m_finalAngle[2] = -65.0f*Math::PI/180.0f; // sensor
+ }
+ if ( m_hand == TSH_DOWN )
+ {
+ m_finalAngle[0] = 25.0f*Math::PI/180.0f; // arm
+ m_finalAngle[1] = -70.0f*Math::PI/180.0f; // forearm
+ m_finalAngle[2] = -45.0f*Math::PI/180.0f; // sensor
+ }
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ m_initialAngle[i] = m_object->RetAngleZ(i+1);
+ }
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskSearch::Start()
+{
+ ObjectType type;
+ Math::Vector speed;
+ int i;
+
+ m_bError = true;
+ if ( !m_physics->RetLand() ) return ERR_SEARCH_FLY;
+
+ speed = m_physics->RetMotorSpeed();
+ if ( speed.x != 0.0f ||
+ speed.z != 0.0f ) return ERR_SEARCH_MOTOR;
+
+ type = m_object->RetType();
+ if ( type != OBJECT_MOBILEfs &&
+ type != OBJECT_MOBILEts &&
+ type != OBJECT_MOBILEws &&
+ type != OBJECT_MOBILEis ) return ERR_SEARCH_VEH;
+
+ m_hand = TSH_DOWN;
+ m_phase = TSP_DOWN;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+
+ InitAngle();
+ m_bError = false; // ok
+
+ m_camera->StartCentering(m_object, Math::PI*0.50f, 99.9f, 0.0f, 1.0f);
+
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, true);
+ m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.9f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.0f, 0.3f, 0.1f, SOPER_STOP);
+
+ m_physics->SetFreeze(true); // it does not move
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskSearch::IsEnded()
+{
+ int i;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+ m_progress = 0.0f;
+
+ if ( m_phase == TSP_DOWN ||
+ m_phase == TSP_UP )
+ {
+ for ( i=0 ; i<3 ; i++ )
+ {
+ m_object->SetAngleZ(i+1, m_finalAngle[i]);
+ }
+ }
+
+ if ( m_phase == TSP_DOWN )
+ {
+ m_sound->Play(SOUND_REPAIR, m_object->RetPosition(0));
+
+ m_phase = TSP_SEARCH;
+ m_speed = 1.0f/4.0f;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TSP_SEARCH )
+ {
+ CreateMark();
+
+ m_hand = TSH_UP;
+ InitAngle();
+
+ i = m_sound->Play(SOUND_MANIP, m_object->RetPosition(0), 0.0f, 0.3f, true);
+ m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.1f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.9f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(i, 0.0f, 0.3f, 0.1f, SOPER_STOP);
+
+ m_phase = TSP_UP;
+ m_speed = 1.0f/1.0f;
+ return ERR_CONTINUE;
+ }
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskSearch::Abort()
+{
+ m_camera->StopCentering(m_object, 2.0f);
+ m_physics->SetFreeze(false); // is moving again
+ return true;
+}
+
+
+// Creates a mark if possible.
+
+bool CTaskSearch::CreateMark()
+{
+ CObject* fret;
+ ObjectType type;
+ Math::Matrix* mat;
+ Math::Vector pos;
+ TerrainRes res;
+ Error info;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(7.5f, 0.0f, 0.0f);
+ pos = Math::Transform(*mat, pos); // sensor position
+
+ res = m_terrain->RetResource(pos);
+ if ( res == TR_NULL ) return false;
+
+ type = OBJECT_NULL;
+ if ( res == TR_STONE )
+ {
+ type = OBJECT_MARKSTONE;
+ info = INFO_MARKSTONE;
+ }
+ if ( res == TR_URANIUM )
+ {
+ type = OBJECT_MARKURANIUM;
+ info = INFO_MARKURANIUM;
+ }
+ if ( res == TR_POWER )
+ {
+ type = OBJECT_MARKPOWER;
+ info = INFO_MARKPOWER;
+ }
+ if ( res == TR_KEYa )
+ {
+ type = OBJECT_MARKKEYa;
+ info = INFO_MARKKEYa;
+ }
+ if ( res == TR_KEYb )
+ {
+ type = OBJECT_MARKKEYb;
+ info = INFO_MARKKEYb;
+ }
+ if ( res == TR_KEYc )
+ {
+ type = OBJECT_MARKKEYc;
+ info = INFO_MARKKEYc;
+ }
+ if ( res == TR_KEYd )
+ {
+ type = OBJECT_MARKKEYd;
+ info = INFO_MARKKEYd;
+ }
+ if ( type == OBJECT_NULL ) return false;
+
+//? DeleteMark(type);
+
+ fret = new CObject(m_iMan);
+ if ( !fret->CreateResource(pos, 0.0f, type) )
+ {
+ delete fret;
+ m_displayText->DisplayError(ERR_TOOMANY, m_object);
+ return false;
+ }
+
+ m_displayText->DisplayError(info, pos, 5.0f, 50.0f); // displays the message
+
+ return true;
+}
+
+// Destroys the marks of a given type.
+
+void CTaskSearch::DeleteMark(ObjectType type)
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( type == pObj->RetType() )
+ {
+ pObj->DeleteObject(); // removes the mark
+ delete pObj;
+ break;
+ }
+ }
+}
+
+
diff --git a/src/object/task/tasksearch.h b/src/object/task/tasksearch.h
index 040c606..304473d 100644
--- a/src/object/task/tasksearch.h
+++ b/src/object/task/tasksearch.h
@@ -1,70 +1,70 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// tasksearch.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-
-
-
-enum TaskSearchHand
-{
- TSH_UP = 1, // sensor at the top
- TSH_DOWN = 2, // sensor at the bottom
-};
-
-enum TaskSearchPhase
-{
- TSP_DOWN = 1, // descends
- TSP_SEARCH = 2, // seeks
- TSP_UP = 3, // rises
-};
-
-
-
-class CTaskSearch : public CTask
-{
-public:
- CTaskSearch(CInstanceManager* iMan, CObject* object);
- ~CTaskSearch();
-
- bool EventProcess(const Event &event);
-
- Error Start();
- Error IsEnded();
- bool Abort();
-
-protected:
- void InitAngle();
- bool CreateMark();
- void DeleteMark(ObjectType type);
-
-protected:
- TaskSearchHand m_hand;
- TaskSearchPhase m_phase;
- float m_progress;
- float m_speed;
- float m_time;
- float m_lastParticule;
- float m_initialAngle[3];
- float m_finalAngle[3];
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// tasksearch.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "object/object.h"
+
+
+
+enum TaskSearchHand
+{
+ TSH_UP = 1, // sensor at the top
+ TSH_DOWN = 2, // sensor at the bottom
+};
+
+enum TaskSearchPhase
+{
+ TSP_DOWN = 1, // descends
+ TSP_SEARCH = 2, // seeks
+ TSP_UP = 3, // rises
+};
+
+
+
+class CTaskSearch : public CTask
+{
+public:
+ CTaskSearch(CInstanceManager* iMan, CObject* object);
+ ~CTaskSearch();
+
+ bool EventProcess(const Event &event);
+
+ Error Start();
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ void InitAngle();
+ bool CreateMark();
+ void DeleteMark(ObjectType type);
+
+protected:
+ TaskSearchHand m_hand;
+ TaskSearchPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_time;
+ float m_lastParticule;
+ float m_initialAngle[3];
+ float m_finalAngle[3];
+ bool m_bError;
+};
+
diff --git a/src/object/task/taskshield.cpp b/src/object/task/taskshield.cpp
index 7ceb03b..d5265a2 100644
--- a/src/object/task/taskshield.cpp
+++ b/src/object/task/taskshield.cpp
@@ -1,560 +1,560 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskshield.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskshield.h"
-
-#include "common/iman.h"
-#include "old/light.h"
-#include "old/particule.h"
-#include "math/geometry.h"
-#include "object/brain.h"
-#include "physics/physics.h"
-
-
-const float ENERGY_TIME = 20.0f; // maximum duration if full battery
-
-
-
-// Object's constructor.
-
-CTaskShield::CTaskShield(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_rankSphere = -1;
- m_soundChannel = -1;
- m_effectLight = -1;
-}
-
-// Object's destructor.
-
-CTaskShield::~CTaskShield()
-{
- Abort();
-}
-
-
-// Management of an event.
-
-bool CTaskShield::EventProcess(const Event &event)
-{
- CObject* power;
- Math::Matrix* mat;
- Math::Matrix matrix;
- Math::Vector pos, speed, goal, angle;
- D3DCOLORVALUE color;
- Math::Point dim;
- float energy;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_progress += event.rTime*m_speed; // others advance
- m_time += event.rTime;
- m_delay -= event.rTime;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(7.0f, 15.0f, 0.0f);
- pos = Math::Transform(*mat, pos); // sphere position
- m_shieldPos = pos;
-
- if ( m_rankSphere != -1 )
- {
- m_particule->SetPosition(m_rankSphere, m_shieldPos);
- dim.x = RetRadius();
- dim.y = dim.x;
- m_particule->SetDimension(m_rankSphere, dim);
- }
-
- if ( m_phase == TS_UP1 )
- {
- pos.x = 7.0f;
- pos.y = 4.5f+Math::Bounce(m_progress)*3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
- }
-
- if ( m_phase == TS_UP2 )
- {
- pos.x = 0.0f;
- pos.y = 1.0f+Math::Bounce(m_progress)*3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(3, pos);
- }
-
- if ( m_phase == TS_SHIELD )
- {
- energy = (1.0f/ENERGY_TIME)*event.rTime;
- energy *= RetRadius()/RADIUS_SHIELD_MAX;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- power->SetEnergy(power->RetEnergy()-energy/power->RetCapacity());
- }
- m_energyUsed += energy;
-
- if ( m_soundChannel == -1 )
- {
- m_soundChannel = m_sound->Play(SOUND_SHIELD, m_shieldPos, 0.5f, 0.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_LOOP);
- }
- else
- {
- m_sound->Position(m_soundChannel, m_shieldPos);
- }
-
- pos = m_shieldPos;
- pos.y += RetRadius()*(2.0f+sinf(m_time*9.0f)*0.2f);
- if ( m_effectLight == -1 )
- {
- CreateLight(pos);
- }
- else
- {
- m_light->SetLightPos(m_effectLight, pos);
-
- color.r = 0.0f+sinf(m_time*33.2f)*0.2f;
- color.g = 0.5f+sinf(m_time*20.0f)*0.5f;
- color.b = 0.5f+sinf(m_time*21.3f)*1.0f;
- color.a = 0.0f;
- m_light->SetLightColor(m_effectLight, color);
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_shieldPos;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = (Math::Rand()-0.5f)*0.0f;
- speed.z = (Math::Rand()-0.5f)*0.0f;
- speed.y = Math::Rand()*15.0f;
- dim.x = Math::Rand()*6.0f+4.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
- }
-
- if ( m_lastRay+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastRay = m_time;
-
- pos = m_shieldPos;
- dim.x = RetRadius()/20.0f;
- dim.y = dim.x;
- angle.x = (Math::Rand()-0.5f)*Math::PI*1.2f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*Math::PI*1.2f;
- Math::LoadRotationXZYMatrix(matrix, angle);
- goal = Math::Transform(matrix, Math::Vector(0.0f, RetRadius()-dim.x, 0.0f));
- goal += pos;
- m_particule->CreateRay(pos, goal, PARTIRAY2, dim, 0.3f);
- }
-
- if ( m_lastIncrease+0.2f <= m_time )
- {
- m_lastIncrease = m_time;
- IncreaseShield();
- }
- }
-
- if ( m_phase == TS_SMOKE )
- {
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.5f, 2.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_shieldPos;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = (Math::Rand()-0.5f)*3.0f;
- speed.z = (Math::Rand()-0.5f)*3.0f;
- speed.y = (Math::Rand()-0.5f)*3.0f;
- dim.x = Math::Rand()*1.5f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
- }
- }
-
- if ( m_phase == TS_DOWN1 )
- {
- pos.x = 0.0f;
- pos.y = 1.0f+(1.0f-Math::Bounce(m_progress))*3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(3, pos);
- }
-
- if ( m_phase == TS_DOWN2 )
- {
- pos.x = 7.0f;
- pos.y = 4.5f+(1.0f-Math::Bounce(m_progress))*3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
- }
-
- return true;
-}
-
-
-// Deploys the shield.
-// The period is only useful with TSM_UP!
-
-Error CTaskShield::Start(TaskShieldMode mode, float delay)
-{
- CObject* power;
- Math::Matrix* mat;
- Math::Vector pos, iPos, oPos, speed;
- ObjectType type;
- float energy;
-
- if ( mode == TSM_DOWN )
- {
- return Stop();
- }
-
- if ( mode == TSM_UPDATE )
- {
- if ( m_object->RetSelect() )
- {
- m_brain->UpdateInterface();
- }
- return ERR_OK;
- }
-
- type = m_object->RetType();
- if ( type != OBJECT_MOBILErs ) return ERR_SHIELD_VEH;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() ) return ERR_SHIELD_VEH;
-
- power = m_object->RetPower();
- if ( power == 0 ) return ERR_SHIELD_ENERGY;
- energy = power->RetEnergy();
- if ( energy == 0.0f ) return ERR_SHIELD_ENERGY;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(7.0f, 15.0f, 0.0f);
- pos = Transform(*mat, pos); // sphere position
- m_shieldPos = pos;
-
- m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 0.7f);
-
- m_phase = TS_UP1;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- m_time = 0.0f;
- m_delay = delay;
- m_lastParticule = 0.0f;
- m_lastRay = 0.0f;
- m_lastIncrease = 0.0f;
- m_energyUsed = 0.0f;
-
- m_bError = false; // ok
-
- if ( m_object->RetSelect() )
- {
- m_brain->UpdateInterface();
- }
-//? m_camera->StartCentering(m_object, Math::PI*0.85f, -Math::PI*0.15f, RetRadius()+40.0f, 3.0f);
- return ERR_OK;
-}
-
-// Returns the shield.
-
-Error CTaskShield::Stop()
-{
- float time;
-
- if ( m_phase == TS_SHIELD )
- {
- m_object->SetShieldRadius(0.0f);
-
- if ( m_rankSphere != -1 )
- {
- m_particule->SetPhase(m_rankSphere, PARPHEND, 3.0f);
- m_rankSphere = -1;
- }
-
- if ( m_effectLight != -1 )
- {
- m_light->DeleteLight(m_effectLight);
- m_effectLight = -1;
- }
-
- time = m_energyUsed*4.0f;
- if ( time < 1.0f ) time = 1.0f;
- if ( time > 4.0f ) time = 4.0f;
-
- m_phase = TS_SMOKE;
- m_speed = 1.0f/time;
-
- m_camera->StopCentering(m_object, 4.0f);
-
- if ( m_object->RetSelect() )
- {
- m_brain->UpdateInterface();
- }
- return ERR_CONTINUE;
- }
-
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskShield::IsEnded()
-{
- CObject* power;
- Math::Vector pos, speed;
- Math::Point dim;
- float energy;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_phase == TS_SHIELD )
- {
- m_object->SetShieldRadius(RetRadius());
-
- power = m_object->RetPower();
- if ( power == 0 )
- {
- energy = 0.0f;
- }
- else
- {
- energy = power->RetEnergy();
- }
-
- if ( energy == 0.0f || m_delay <= 0.0f )
- {
- Stop();
- }
- return ERR_CONTINUE;
- }
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( m_phase == TS_UP1 )
- {
- pos.x = 7.0f;
- pos.y = 4.5f+3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
-
- m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 1.0f);
-
- m_phase = TS_UP2;
- m_speed = 1.0f/0.8f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TS_UP2 )
- {
- pos.x = 0.0f;
- pos.y = 1.0f+3.0f;
- pos.z = 0.0f;
- m_object->SetPosition(3, pos);
-
- m_object->SetShieldRadius(RetRadius());
-
- pos = m_shieldPos;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = RetRadius();
- dim.y = dim.x;
- m_rankSphere = m_particule->CreateParticule(pos, speed, dim, PARTISPHERE3, 2.0f, 0.0f, 0.0f);
-
- m_phase = TS_SHIELD;
- m_speed = 1.0f/999.9f;
-
- if ( m_object->RetSelect() )
- {
- m_brain->UpdateInterface();
- }
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TS_SMOKE )
- {
- m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 1.0f);
-
- m_phase = TS_DOWN1;
- m_speed = 1.0f/0.8f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TS_DOWN1 )
- {
- m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 0.7f);
-
- m_phase = TS_DOWN2;
- m_speed = 1.0f/1.0f;
- return ERR_CONTINUE;
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Indicates whether the action is pending.
-
-bool CTaskShield::IsBusy()
-{
- if ( m_phase == TS_SHIELD )
- {
- return false;
- }
-
- return true;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskShield::Abort()
-{
- Math::Vector pos;
-
- m_object->SetShieldRadius(0.0f);
-
- pos.x = 7.0f;
- pos.y = 4.5f;
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
-
- pos.x = 0.0f;
- pos.y = 1.0f;
- pos.z = 0.0f;
- m_object->SetPosition(3, pos);
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.5f, 2.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- if ( m_rankSphere != -1 )
- {
- m_particule->SetPhase(m_rankSphere, PARPHEND, 3.0f);
- m_rankSphere = -1;
- }
-
- if ( m_effectLight != -1 )
- {
- m_light->DeleteLight(m_effectLight);
- m_effectLight = -1;
- }
-
- m_camera->StopCentering(m_object, 2.0f);
- return true;
-}
-
-
-// Creates the light to accompany a pyrotechnic effect.
-
-bool CTaskShield::CreateLight(Math::Vector pos)
-{
- D3DLIGHT7 light;
-
- if ( !m_engine->RetLightMode() ) return true;
-
- ZeroMemory( &light, sizeof(light) );
- light.dltType = D3DLIGHT_SPOT;
- light.dcvDiffuse.r = 0.0f;
- light.dcvDiffuse.g = 1.0f;
- light.dcvDiffuse.b = 2.0f;
- light.dvPosition.x = pos.x;
- light.dvPosition.y = pos.y;
- light.dvPosition.z = pos.z;
- light.dvDirection.x = 0.0f;
- light.dvDirection.y = -1.0f; // against the bottom
- light.dvDirection.z = 0.0f;
- light.dvRange = D3DLIGHT_RANGE_MAX;
- light.dvFalloff = 1.0f;
- light.dvAttenuation0 = 1.0f;
- light.dvAttenuation1 = 0.0f;
- light.dvAttenuation2 = 0.0f;
- light.dvTheta = 0.0f;
- light.dvPhi = Math::PI/4.0f;
-
- m_effectLight = m_light->CreateLight();
- if ( m_effectLight == -1 ) return false;
-
- m_light->SetLight(m_effectLight, light);
- m_light->SetLightIntensity(m_effectLight, 1.0f);
-
- return true;
-}
-
-
-// Repaired the shielded objects within the sphere of the shield.
-
-void CTaskShield::IncreaseShield()
-{
- ObjectType type;
- CObject* pObj;
- Math::Vector oPos;
- float dist, shield;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, m_shieldPos);
- if ( dist <= RetRadius()+10.0f )
- {
- shield = pObj->RetShield();
- shield += 0.1f;
- if ( shield > 1.0f ) shield = 1.0f;
- pObj->SetShield(shield);
- }
- }
-}
-
-
-// Returns the radius of the shield.
-
-float CTaskShield::RetRadius()
-{
- return RADIUS_SHIELD_MIN + (RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)*m_object->RetParam();
-}
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskshield.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskshield.h"
+
+#include "common/iman.h"
+#include "old/light.h"
+#include "old/particule.h"
+#include "math/geometry.h"
+#include "object/brain.h"
+#include "physics/physics.h"
+
+
+const float ENERGY_TIME = 20.0f; // maximum duration if full battery
+
+
+
+// Object's constructor.
+
+CTaskShield::CTaskShield(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_rankSphere = -1;
+ m_soundChannel = -1;
+ m_effectLight = -1;
+}
+
+// Object's destructor.
+
+CTaskShield::~CTaskShield()
+{
+ Abort();
+}
+
+
+// Management of an event.
+
+bool CTaskShield::EventProcess(const Event &event)
+{
+ CObject* power;
+ Math::Matrix* mat;
+ Math::Matrix matrix;
+ Math::Vector pos, speed, goal, angle;
+ D3DCOLORVALUE color;
+ Math::Point dim;
+ float energy;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ m_progress += event.rTime*m_speed; // others advance
+ m_time += event.rTime;
+ m_delay -= event.rTime;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(7.0f, 15.0f, 0.0f);
+ pos = Math::Transform(*mat, pos); // sphere position
+ m_shieldPos = pos;
+
+ if ( m_rankSphere != -1 )
+ {
+ m_particule->SetPosition(m_rankSphere, m_shieldPos);
+ dim.x = RetRadius();
+ dim.y = dim.x;
+ m_particule->SetDimension(m_rankSphere, dim);
+ }
+
+ if ( m_phase == TS_UP1 )
+ {
+ pos.x = 7.0f;
+ pos.y = 4.5f+Math::Bounce(m_progress)*3.0f;
+ pos.z = 0.0f;
+ m_object->SetPosition(2, pos);
+ }
+
+ if ( m_phase == TS_UP2 )
+ {
+ pos.x = 0.0f;
+ pos.y = 1.0f+Math::Bounce(m_progress)*3.0f;
+ pos.z = 0.0f;
+ m_object->SetPosition(3, pos);
+ }
+
+ if ( m_phase == TS_SHIELD )
+ {
+ energy = (1.0f/ENERGY_TIME)*event.rTime;
+ energy *= RetRadius()/RADIUS_SHIELD_MAX;
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ power->SetEnergy(power->RetEnergy()-energy/power->RetCapacity());
+ }
+ m_energyUsed += energy;
+
+ if ( m_soundChannel == -1 )
+ {
+ m_soundChannel = m_sound->Play(SOUND_SHIELD, m_shieldPos, 0.5f, 0.5f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 2.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_LOOP);
+ }
+ else
+ {
+ m_sound->Position(m_soundChannel, m_shieldPos);
+ }
+
+ pos = m_shieldPos;
+ pos.y += RetRadius()*(2.0f+sinf(m_time*9.0f)*0.2f);
+ if ( m_effectLight == -1 )
+ {
+ CreateLight(pos);
+ }
+ else
+ {
+ m_light->SetLightPos(m_effectLight, pos);
+
+ color.r = 0.0f+sinf(m_time*33.2f)*0.2f;
+ color.g = 0.5f+sinf(m_time*20.0f)*0.5f;
+ color.b = 0.5f+sinf(m_time*21.3f)*1.0f;
+ color.a = 0.0f;
+ m_light->SetLightColor(m_effectLight, color);
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_shieldPos;
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ speed.x = (Math::Rand()-0.5f)*0.0f;
+ speed.z = (Math::Rand()-0.5f)*0.0f;
+ speed.y = Math::Rand()*15.0f;
+ dim.x = Math::Rand()*6.0f+4.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLUE, 1.0f, 0.0f, 0.0f);
+ }
+
+ if ( m_lastRay+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastRay = m_time;
+
+ pos = m_shieldPos;
+ dim.x = RetRadius()/20.0f;
+ dim.y = dim.x;
+ angle.x = (Math::Rand()-0.5f)*Math::PI*1.2f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*Math::PI*1.2f;
+ Math::LoadRotationXZYMatrix(matrix, angle);
+ goal = Math::Transform(matrix, Math::Vector(0.0f, RetRadius()-dim.x, 0.0f));
+ goal += pos;
+ m_particule->CreateRay(pos, goal, PARTIRAY2, dim, 0.3f);
+ }
+
+ if ( m_lastIncrease+0.2f <= m_time )
+ {
+ m_lastIncrease = m_time;
+ IncreaseShield();
+ }
+ }
+
+ if ( m_phase == TS_SMOKE )
+ {
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.5f, 2.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_shieldPos;
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ speed.x = (Math::Rand()-0.5f)*3.0f;
+ speed.z = (Math::Rand()-0.5f)*3.0f;
+ speed.y = (Math::Rand()-0.5f)*3.0f;
+ dim.x = Math::Rand()*1.5f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
+ }
+ }
+
+ if ( m_phase == TS_DOWN1 )
+ {
+ pos.x = 0.0f;
+ pos.y = 1.0f+(1.0f-Math::Bounce(m_progress))*3.0f;
+ pos.z = 0.0f;
+ m_object->SetPosition(3, pos);
+ }
+
+ if ( m_phase == TS_DOWN2 )
+ {
+ pos.x = 7.0f;
+ pos.y = 4.5f+(1.0f-Math::Bounce(m_progress))*3.0f;
+ pos.z = 0.0f;
+ m_object->SetPosition(2, pos);
+ }
+
+ return true;
+}
+
+
+// Deploys the shield.
+// The period is only useful with TSM_UP!
+
+Error CTaskShield::Start(TaskShieldMode mode, float delay)
+{
+ CObject* power;
+ Math::Matrix* mat;
+ Math::Vector pos, iPos, oPos, speed;
+ ObjectType type;
+ float energy;
+
+ if ( mode == TSM_DOWN )
+ {
+ return Stop();
+ }
+
+ if ( mode == TSM_UPDATE )
+ {
+ if ( m_object->RetSelect() )
+ {
+ m_brain->UpdateInterface();
+ }
+ return ERR_OK;
+ }
+
+ type = m_object->RetType();
+ if ( type != OBJECT_MOBILErs ) return ERR_SHIELD_VEH;
+
+ m_bError = true; // operation impossible
+ if ( !m_physics->RetLand() ) return ERR_SHIELD_VEH;
+
+ power = m_object->RetPower();
+ if ( power == 0 ) return ERR_SHIELD_ENERGY;
+ energy = power->RetEnergy();
+ if ( energy == 0.0f ) return ERR_SHIELD_ENERGY;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(7.0f, 15.0f, 0.0f);
+ pos = Transform(*mat, pos); // sphere position
+ m_shieldPos = pos;
+
+ m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 0.7f);
+
+ m_phase = TS_UP1;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ m_time = 0.0f;
+ m_delay = delay;
+ m_lastParticule = 0.0f;
+ m_lastRay = 0.0f;
+ m_lastIncrease = 0.0f;
+ m_energyUsed = 0.0f;
+
+ m_bError = false; // ok
+
+ if ( m_object->RetSelect() )
+ {
+ m_brain->UpdateInterface();
+ }
+//? m_camera->StartCentering(m_object, Math::PI*0.85f, -Math::PI*0.15f, RetRadius()+40.0f, 3.0f);
+ return ERR_OK;
+}
+
+// Returns the shield.
+
+Error CTaskShield::Stop()
+{
+ float time;
+
+ if ( m_phase == TS_SHIELD )
+ {
+ m_object->SetShieldRadius(0.0f);
+
+ if ( m_rankSphere != -1 )
+ {
+ m_particule->SetPhase(m_rankSphere, PARPHEND, 3.0f);
+ m_rankSphere = -1;
+ }
+
+ if ( m_effectLight != -1 )
+ {
+ m_light->DeleteLight(m_effectLight);
+ m_effectLight = -1;
+ }
+
+ time = m_energyUsed*4.0f;
+ if ( time < 1.0f ) time = 1.0f;
+ if ( time > 4.0f ) time = 4.0f;
+
+ m_phase = TS_SMOKE;
+ m_speed = 1.0f/time;
+
+ m_camera->StopCentering(m_object, 4.0f);
+
+ if ( m_object->RetSelect() )
+ {
+ m_brain->UpdateInterface();
+ }
+ return ERR_CONTINUE;
+ }
+
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskShield::IsEnded()
+{
+ CObject* power;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float energy;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_phase == TS_SHIELD )
+ {
+ m_object->SetShieldRadius(RetRadius());
+
+ power = m_object->RetPower();
+ if ( power == 0 )
+ {
+ energy = 0.0f;
+ }
+ else
+ {
+ energy = power->RetEnergy();
+ }
+
+ if ( energy == 0.0f || m_delay <= 0.0f )
+ {
+ Stop();
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+ m_progress = 0.0f;
+
+ if ( m_phase == TS_UP1 )
+ {
+ pos.x = 7.0f;
+ pos.y = 4.5f+3.0f;
+ pos.z = 0.0f;
+ m_object->SetPosition(2, pos);
+
+ m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 1.0f);
+
+ m_phase = TS_UP2;
+ m_speed = 1.0f/0.8f;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TS_UP2 )
+ {
+ pos.x = 0.0f;
+ pos.y = 1.0f+3.0f;
+ pos.z = 0.0f;
+ m_object->SetPosition(3, pos);
+
+ m_object->SetShieldRadius(RetRadius());
+
+ pos = m_shieldPos;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = RetRadius();
+ dim.y = dim.x;
+ m_rankSphere = m_particule->CreateParticule(pos, speed, dim, PARTISPHERE3, 2.0f, 0.0f, 0.0f);
+
+ m_phase = TS_SHIELD;
+ m_speed = 1.0f/999.9f;
+
+ if ( m_object->RetSelect() )
+ {
+ m_brain->UpdateInterface();
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TS_SMOKE )
+ {
+ m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 1.0f);
+
+ m_phase = TS_DOWN1;
+ m_speed = 1.0f/0.8f;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TS_DOWN1 )
+ {
+ m_sound->Play(SOUND_PSHHH2, m_shieldPos, 1.0f, 0.7f);
+
+ m_phase = TS_DOWN2;
+ m_speed = 1.0f/1.0f;
+ return ERR_CONTINUE;
+ }
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Indicates whether the action is pending.
+
+bool CTaskShield::IsBusy()
+{
+ if ( m_phase == TS_SHIELD )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskShield::Abort()
+{
+ Math::Vector pos;
+
+ m_object->SetShieldRadius(0.0f);
+
+ pos.x = 7.0f;
+ pos.y = 4.5f;
+ pos.z = 0.0f;
+ m_object->SetPosition(2, pos);
+
+ pos.x = 0.0f;
+ pos.y = 1.0f;
+ pos.z = 0.0f;
+ m_object->SetPosition(3, pos);
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.5f, 0.5f, 2.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ if ( m_rankSphere != -1 )
+ {
+ m_particule->SetPhase(m_rankSphere, PARPHEND, 3.0f);
+ m_rankSphere = -1;
+ }
+
+ if ( m_effectLight != -1 )
+ {
+ m_light->DeleteLight(m_effectLight);
+ m_effectLight = -1;
+ }
+
+ m_camera->StopCentering(m_object, 2.0f);
+ return true;
+}
+
+
+// Creates the light to accompany a pyrotechnic effect.
+
+bool CTaskShield::CreateLight(Math::Vector pos)
+{
+ D3DLIGHT7 light;
+
+ if ( !m_engine->RetLightMode() ) return true;
+
+ ZeroMemory( &light, sizeof(light) );
+ light.dltType = D3DLIGHT_SPOT;
+ light.dcvDiffuse.r = 0.0f;
+ light.dcvDiffuse.g = 1.0f;
+ light.dcvDiffuse.b = 2.0f;
+ light.dvPosition.x = pos.x;
+ light.dvPosition.y = pos.y;
+ light.dvPosition.z = pos.z;
+ light.dvDirection.x = 0.0f;
+ light.dvDirection.y = -1.0f; // against the bottom
+ light.dvDirection.z = 0.0f;
+ light.dvRange = D3DLIGHT_RANGE_MAX;
+ light.dvFalloff = 1.0f;
+ light.dvAttenuation0 = 1.0f;
+ light.dvAttenuation1 = 0.0f;
+ light.dvAttenuation2 = 0.0f;
+ light.dvTheta = 0.0f;
+ light.dvPhi = Math::PI/4.0f;
+
+ m_effectLight = m_light->CreateLight();
+ if ( m_effectLight == -1 ) return false;
+
+ m_light->SetLight(m_effectLight, light);
+ m_light->SetLightIntensity(m_effectLight, 1.0f);
+
+ return true;
+}
+
+
+// Repaired the shielded objects within the sphere of the shield.
+
+void CTaskShield::IncreaseShield()
+{
+ ObjectType type;
+ CObject* pObj;
+ Math::Vector oPos;
+ float dist, shield;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, m_shieldPos);
+ if ( dist <= RetRadius()+10.0f )
+ {
+ shield = pObj->RetShield();
+ shield += 0.1f;
+ if ( shield > 1.0f ) shield = 1.0f;
+ pObj->SetShield(shield);
+ }
+ }
+}
+
+
+// Returns the radius of the shield.
+
+float CTaskShield::RetRadius()
+{
+ return RADIUS_SHIELD_MIN + (RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)*m_object->RetParam();
+}
+
+
+
diff --git a/src/object/task/taskshield.h b/src/object/task/taskshield.h
index 7749f52..5842ae0 100644
--- a/src/object/task/taskshield.h
+++ b/src/object/task/taskshield.h
@@ -1,84 +1,84 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskshield.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-const float RADIUS_SHIELD_MIN = 40.0f; // minimum radius of the protected zone
-const float RADIUS_SHIELD_MAX = 100.0f; // maximum radius of the protected zone
-
-
-enum TaskShieldPhase
-{
- TS_UP1 = 1, // up
- TS_UP2 = 2, // up
- TS_SHIELD = 3, // shield deployed
- TS_SMOKE = 4, // smoke
- TS_DOWN1 = 5, // down
- TS_DOWN2 = 6, // down
-};
-
-enum TaskShieldMode
-{
- TSM_UP = 1, // deploys shield
- TSM_DOWN = 2, // returns the shield
- TSM_UPDATE = 3, // radius change
-};
-
-
-
-class CTaskShield : public CTask
-{
-public:
- CTaskShield(CInstanceManager* iMan, CObject* object);
- ~CTaskShield();
-
- bool EventProcess(const Event &event);
-
- Error Start(TaskShieldMode mode, float delay);
- Error IsEnded();
- bool IsBusy();
- bool Abort();
-
-protected:
- Error Stop();
- bool CreateLight(Math::Vector pos);
- void IncreaseShield();
- float RetRadius();
-
-protected:
- TaskShieldPhase m_phase;
- float m_progress;
- float m_speed;
- float m_time;
- float m_delay;
- float m_lastParticule;
- float m_lastRay;
- float m_lastIncrease;
- float m_energyUsed;
- bool m_bError;
- Math::Vector m_shieldPos;
- int m_rankSphere;
- int m_soundChannel;
- int m_effectLight;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskshield.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "math/vector.h"
+
+
+const float RADIUS_SHIELD_MIN = 40.0f; // minimum radius of the protected zone
+const float RADIUS_SHIELD_MAX = 100.0f; // maximum radius of the protected zone
+
+
+enum TaskShieldPhase
+{
+ TS_UP1 = 1, // up
+ TS_UP2 = 2, // up
+ TS_SHIELD = 3, // shield deployed
+ TS_SMOKE = 4, // smoke
+ TS_DOWN1 = 5, // down
+ TS_DOWN2 = 6, // down
+};
+
+enum TaskShieldMode
+{
+ TSM_UP = 1, // deploys shield
+ TSM_DOWN = 2, // returns the shield
+ TSM_UPDATE = 3, // radius change
+};
+
+
+
+class CTaskShield : public CTask
+{
+public:
+ CTaskShield(CInstanceManager* iMan, CObject* object);
+ ~CTaskShield();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(TaskShieldMode mode, float delay);
+ Error IsEnded();
+ bool IsBusy();
+ bool Abort();
+
+protected:
+ Error Stop();
+ bool CreateLight(Math::Vector pos);
+ void IncreaseShield();
+ float RetRadius();
+
+protected:
+ TaskShieldPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_time;
+ float m_delay;
+ float m_lastParticule;
+ float m_lastRay;
+ float m_lastIncrease;
+ float m_energyUsed;
+ bool m_bError;
+ Math::Vector m_shieldPos;
+ int m_rankSphere;
+ int m_soundChannel;
+ int m_effectLight;
+};
+
diff --git a/src/object/task/taskspiderexplo.cpp b/src/object/task/taskspiderexplo.cpp
index 2d6c846..fa505b1 100644
--- a/src/object/task/taskspiderexplo.cpp
+++ b/src/object/task/taskspiderexplo.cpp
@@ -1,110 +1,110 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskspiderexplo.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskspiderexplo.h"
-
-#include "old/pyro.h"
-#include "object/motion/motionspider.h"
-#include "physics/physics.h"
-
-
-
-
-// Object's constructor.
-
-CTaskSpiderExplo::CTaskSpiderExplo(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_time = 0.0f;
- m_bError = false;
-}
-
-// Object's destructor.
-
-CTaskSpiderExplo::~CTaskSpiderExplo()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskSpiderExplo::EventProcess(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- // Momentarily stationary object (ant on the back)?
- if ( m_object->RetFixed() )
- {
- m_bError = true;
- return true;
- }
-
- m_time += event.rTime;
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskSpiderExplo::Start()
-{
- m_motion->SetAction(MSS_EXPLO, 1.0f); // swells abdominal
- m_time = 0.0f;
-
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
-
- m_bError = false;
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskSpiderExplo::IsEnded()
-{
- CPyro* pyro;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
-
- if ( m_bError )
- {
- Abort();
- return ERR_STOP;
- }
-
- if ( m_time < 1.0f ) return ERR_CONTINUE;
-
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_SPIDER, m_object); // the spider explodes (suicide)
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskSpiderExplo::Abort()
-{
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskspiderexplo.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskspiderexplo.h"
+
+#include "old/pyro.h"
+#include "object/motion/motionspider.h"
+#include "physics/physics.h"
+
+
+
+
+// Object's constructor.
+
+CTaskSpiderExplo::CTaskSpiderExplo(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_time = 0.0f;
+ m_bError = false;
+}
+
+// Object's destructor.
+
+CTaskSpiderExplo::~CTaskSpiderExplo()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskSpiderExplo::EventProcess(const Event &event)
+{
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ // Momentarily stationary object (ant on the back)?
+ if ( m_object->RetFixed() )
+ {
+ m_bError = true;
+ return true;
+ }
+
+ m_time += event.rTime;
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskSpiderExplo::Start()
+{
+ m_motion->SetAction(MSS_EXPLO, 1.0f); // swells abdominal
+ m_time = 0.0f;
+
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+
+ m_bError = false;
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskSpiderExplo::IsEnded()
+{
+ CPyro* pyro;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+
+ if ( m_bError )
+ {
+ Abort();
+ return ERR_STOP;
+ }
+
+ if ( m_time < 1.0f ) return ERR_CONTINUE;
+
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_SPIDER, m_object); // the spider explodes (suicide)
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskSpiderExplo::Abort()
+{
+ return true;
+}
+
diff --git a/src/object/task/taskspiderexplo.h b/src/object/task/taskspiderexplo.h
index df77b62..50f3ad2 100644
--- a/src/object/task/taskspiderexplo.h
+++ b/src/object/task/taskspiderexplo.h
@@ -1,44 +1,44 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskspiderexplo.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskSpiderExplo : public CTask
-{
-public:
- CTaskSpiderExplo(CInstanceManager* iMan, CObject* object);
- ~CTaskSpiderExplo();
-
- bool EventProcess(const Event &event);
-
- Error Start();
- Error IsEnded();
- bool Abort();
-
-protected:
-
-protected:
- float m_time;
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskspiderexplo.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+
+
+
+class CTaskSpiderExplo : public CTask
+{
+public:
+ CTaskSpiderExplo(CInstanceManager* iMan, CObject* object);
+ ~CTaskSpiderExplo();
+
+ bool EventProcess(const Event &event);
+
+ Error Start();
+ Error IsEnded();
+ bool Abort();
+
+protected:
+
+protected:
+ float m_time;
+ bool m_bError;
+};
+
diff --git a/src/object/task/tasktake.cpp b/src/object/task/tasktake.cpp
index b6d9e0e..1a50f06 100644
--- a/src/object/task/tasktake.cpp
+++ b/src/object/task/tasktake.cpp
@@ -1,596 +1,596 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// tasktake.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/tasktake.h"
-
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "math/geometry.h"
-#include "object/motion/motionhuman.h"
-#include "object/robotmain.h"
-#include "physics/physics.h"
-
-
-
-
-// Object's constructor.
-
-CTaskTake::CTaskTake(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
-
- m_arm = TTA_NEUTRAL;
-}
-
-// Object's destructor.
-
-CTaskTake::~CTaskTake()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskTake::EventProcess(const Event &event)
-{
- float a, g, cirSpeed;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- if ( m_bTurn ) // preliminary rotation?
- {
- a = m_object->RetAngleY(0);
- g = m_angle;
- cirSpeed = Math::Direction(a, g)*2.0f;
- if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
- if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
-
- m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
- return true;
- }
-
- m_progress += event.rTime*m_speed; // others advance
-
- m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f)); // immobile!
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskTake::Start()
-{
- ObjectType type;
- CObject* other;
- float iAngle, oAngle, h;
- Math::Vector pos;
-
- m_height = 0.0f;
- m_step = 0;
- m_progress = 0.0f;
-
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
- oAngle = iAngle;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() )
- {
- pos = m_object->RetPosition(0);
- h = m_water->RetLevel(m_object);
- if ( pos.y < h ) return ERR_MANIP_WATER; // impossible under water
- return ERR_MANIP_FLY;
- }
-
- type = m_object->RetType();
- if ( type != OBJECT_HUMAN &&
- type != OBJECT_TECH ) return ERR_MANIP_VEH;
-
- m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));
-
- if ( m_object->RetFret() == 0 )
- {
- m_order = TTO_TAKE;
- }
- else
- {
- m_order = TTO_DEPOSE;
- }
-
- if ( m_order == TTO_TAKE )
- {
- pos = m_object->RetPosition(0);
- h = m_water->RetLevel(m_object);
- if ( pos.y < h ) return ERR_MANIP_WATER; // impossible under water
-
- other = SearchFriendObject(oAngle, 1.5f, Math::PI*0.50f);
- if ( other != 0 && other->RetPower() != 0 )
- {
- type = other->RetPower()->RetType();
- if ( type == OBJECT_URANIUM ) return ERR_MANIP_RADIO;
- if ( type != OBJECT_FRET &&
- type != OBJECT_STONE &&
- type != OBJECT_BULLET &&
- type != OBJECT_METAL &&
- type != OBJECT_POWER &&
- type != OBJECT_ATOMIC &&
- type != OBJECT_BBOX &&
- type != OBJECT_KEYa &&
- type != OBJECT_KEYb &&
- type != OBJECT_KEYc &&
- type != OBJECT_KEYd &&
- type != OBJECT_TNT ) return ERR_MANIP_FRIEND;
-//? m_camera->StartCentering(m_object, Math::PI*0.3f, -Math::PI*0.1f, 0.0f, 0.8f);
- m_arm = TTA_FRIEND;
- }
- else
- {
- other = SearchTakeObject(oAngle, 1.5f, Math::PI*0.45f);
- if ( other == 0 ) return ERR_MANIP_NIL;
- type = other->RetType();
- if ( type == OBJECT_URANIUM ) return ERR_MANIP_RADIO;
-//? m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.8f);
- m_arm = TTA_FFRONT;
- m_main->HideDropZone(other); // hides buildable area
- }
- }
-
- if ( m_order == TTO_DEPOSE )
- {
-//? speed = m_physics->RetMotorSpeed();
-//? if ( speed.x != 0.0f ||
-//? speed.z != 0.0f ) return ERR_MANIP_MOTOR;
-
- other = SearchFriendObject(oAngle, 1.5f, Math::PI*0.50f);
- if ( other != 0 && other->RetPower() == 0 )
- {
-//? m_camera->StartCentering(m_object, Math::PI*0.3f, -Math::PI*0.1f, 0.0f, 0.8f);
- m_arm = TTA_FRIEND;
- }
- else
- {
- if ( !IsFreeDeposeObject(Math::Vector(2.5f, 0.0f, 0.0f)) ) return ERR_MANIP_OCC;
-//? m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.8f);
- m_arm = TTA_FFRONT;
- }
- }
-
- m_bTurn = true; // preliminary rotation necessary
- m_angle = oAngle; // angle was reached
-
- m_physics->SetFreeze(true); // it does not move
-
- m_bError = false; // ok
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskTake::IsEnded()
-{
- CObject* fret;
- float angle;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_bTurn ) // preliminary rotation?
- {
- angle = m_object->RetAngleY(0);
- angle = Math::NormAngle(angle); // 0..2*Math::PI
-
- if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) )
- {
- m_bTurn = false; // rotation ended
- m_physics->SetMotorSpeedZ(0.0f);
-
- if ( m_arm == TTA_FFRONT )
- {
- m_motion->SetAction(MHS_TAKE, 0.2f); // will decrease
- }
- if ( m_arm == TTA_FRIEND )
- {
- if ( m_height <= 3.0f )
- {
- m_motion->SetAction(MHS_TAKEOTHER, 0.2f); // will decrease
- }
- else
- {
- m_motion->SetAction(MHS_TAKEHIGH, 0.2f); // will decrease
- }
- }
- m_progress = 0.0f;
- m_speed = 1.0f/0.6f;
- }
- return ERR_CONTINUE;
- }
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- m_step ++;
-
- if ( m_order == TTO_TAKE )
- {
- if ( m_step == 1 )
- {
- if ( TruckTakeObject() )
- {
- if ( m_arm == TTA_FRIEND &&
- (m_fretType == OBJECT_POWER ||
- m_fretType == OBJECT_ATOMIC ) )
- {
- m_sound->Play(SOUND_POWEROFF, m_object->RetPosition(0));
- }
- }
- m_motion->SetAction(MHS_UPRIGHT, 0.4f); // gets up
- m_progress = 0.0f;
- m_speed = 1.0f/0.8f;
- m_camera->StopCentering(m_object, 0.8f);
- return ERR_CONTINUE;
- }
- }
-
- if ( m_order == TTO_DEPOSE )
- {
- if ( m_step == 1 )
- {
- fret = m_object->RetFret();
- TruckDeposeObject();
- if ( m_arm == TTA_FRIEND &&
- (m_fretType == OBJECT_POWER ||
- m_fretType == OBJECT_ATOMIC ) )
- {
- m_sound->Play(SOUND_POWERON, m_object->RetPosition(0));
- }
- if ( fret != 0 && m_fretType == OBJECT_METAL && m_arm == TTA_FFRONT )
- {
- m_main->ShowDropZone(fret, m_object); // shows buildable area
- }
- m_motion->SetAction(-1); // gets up
- m_progress = 0.0f;
- m_speed = 1.0f/0.4f;
- m_camera->StopCentering(m_object, 0.8f);
- return ERR_CONTINUE;
- }
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskTake::Abort()
-{
- m_motion->SetAction(-1);
- m_camera->StopCentering(m_object, 0.8f);
- m_physics->SetFreeze(false); // is moving again
- return true;
-}
-
-
-// Seeks the object to take in front.
-
-CObject* CTaskTake::SearchTakeObject(float &angle,
- float dLimit, float aLimit)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float min, iAngle, bAngle, a, distance;
- int i;
-
- iPos = m_object->RetPosition(0);
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- min = 1000000.0f;
- pBest = 0;
- bAngle = 0.0f;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
-
- if ( type != OBJECT_FRET &&
- type != OBJECT_STONE &&
- type != OBJECT_URANIUM &&
- type != OBJECT_BULLET &&
- type != OBJECT_METAL &&
- type != OBJECT_POWER &&
- type != OBJECT_ATOMIC &&
- type != OBJECT_BBOX &&
- type != OBJECT_KEYa &&
- type != OBJECT_KEYb &&
- type != OBJECT_KEYc &&
- type != OBJECT_KEYd &&
- type != OBJECT_TNT ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( pObj->RetLock() ) continue;
- if ( pObj->RetZoomY(0) != 1.0f ) continue;
-
- oPos = pObj->RetPosition(0);
- distance = Math::Distance(oPos, iPos);
- if ( distance >= 4.0f-dLimit &&
- distance <= 4.0f+dLimit )
- {
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
- {
- a = fabs(angle-iAngle);
- if ( a > Math::PI ) a = Math::PI*2.0f-a;
- if ( a < min )
- {
- min = a;
- pBest = pObj;
- bAngle = angle;
- }
- }
- }
- }
- angle = bAngle;
- return pBest;
-}
-
-// Seeks the robot on which you want take or put a battery.
-
-CObject* CTaskTake::SearchFriendObject(float &angle,
- float dLimit, float aLimit)
-{
- Character* character;
- CObject* pObj;
- CObject* pPower;
- Math::Matrix* mat;
- Math::Vector iPos, oPos;
- ObjectType type, powerType;
- float iAngle, iRad, distance;
- int i;
-
- if ( !m_object->GetCrashSphere(0, iPos, iRad) ) return 0;
- iAngle = m_object->RetAngleY(0);
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue; // yourself?
-
- type = pObj->RetType();
- 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_MOBILEtg &&
- type != OBJECT_MOBILEft &&
- type != OBJECT_MOBILEtt &&
- type != OBJECT_MOBILEwt &&
- type != OBJECT_MOBILEit &&
- type != OBJECT_TOWER &&
- type != OBJECT_RESEARCH &&
- type != OBJECT_ENERGY &&
- type != OBJECT_LABO &&
- type != OBJECT_NUCLEAR ) continue;
-
- pPower = pObj->RetPower();
- if ( pPower != 0 )
- {
- if ( pPower->RetLock() ) continue;
- if ( pPower->RetZoomY(0) != 1.0f ) continue;
-
- powerType = pPower->RetType();
- if ( powerType == OBJECT_NULL ||
- powerType == OBJECT_FIX ) continue;
- }
-
- mat = pObj->RetWorldMatrix(0);
- character = pObj->RetCharacter();
- oPos = Transform(*mat, character->posPower);
-
- distance = fabs(Math::Distance(oPos, iPos) - (iRad+1.0f));
- if ( distance <= dLimit )
- {
- angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
- {
- character = pObj->RetCharacter();
- m_height = character->posPower.y;
- return pObj;
- }
- }
- }
-
- return 0;
-}
-
-// Takes the object in front.
-
-bool CTaskTake::TruckTakeObject()
-{
- CObject* fret;
- CObject* other;
- Math::Matrix matRotate;
- float angle;
-
- if ( m_arm == TTA_FFRONT ) // takes on the ground in front?
- {
-//? fret = SearchTakeObject(angle, 1.5f, Math::PI*0.04f);
- fret = SearchTakeObject(angle, 1.5f, Math::PI*0.15f); //OK 1.9
- if ( fret == 0 ) return false; // rien � prendre ?
- m_fretType = fret->RetType();
-
- fret->SetTruck(m_object);
- fret->SetTruckPart(4); // takes with the hand
-
-//? fret->SetPosition(0, Math::Vector(2.2f, -1.0f, 1.1f));
- fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f));
- fret->SetAngleY(0, 0.1f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.8f);
-
- m_object->SetFret(fret); // takes
- }
-
- if ( m_arm == TTA_FRIEND ) // takes friend's battery?
- {
- other = SearchFriendObject(angle, 1.5f, Math::PI*0.04f);
- if ( other == 0 ) return false;
-
- fret = other->RetPower();
- if ( fret == 0 ) return false; // the other does not have a battery?
- m_fretType = fret->RetType();
-
- other->SetPower(0);
- fret->SetTruck(m_object);
- fret->SetTruckPart(4); // takes with the hand
-
-//? fret->SetPosition(0, Math::Vector(2.2f, -1.0f, 1.1f));
- fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f));
- fret->SetAngleY(0, 0.1f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.8f);
-
- m_object->SetFret(fret); // takes
- }
-
- return true;
-}
-
-// Deposes the object taken.
-
-bool CTaskTake::TruckDeposeObject()
-{
- Character* character;
- CObject* fret;
- CObject* other;
- Math::Matrix* mat;
- Math::Vector pos;
- float angle;
-
- if ( m_arm == TTA_FFRONT ) // deposes on the ground in front?
- {
- fret = m_object->RetFret();
- if ( fret == 0 ) return false; // does nothing?
- m_fretType = fret->RetType();
-
- mat = fret->RetWorldMatrix(0);
- pos = Transform(*mat, Math::Vector(-0.5f, 1.0f, 0.0f));
- m_terrain->MoveOnFloor(pos);
- fret->SetPosition(0, pos);
- fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- fret->FloorAdjust(); // plate well on the ground
-
- fret->SetTruck(0);
- m_object->SetFret(0); // deposit
- }
-
- if ( m_arm == TTA_FRIEND ) // deposes battery on friends?
- {
- other = SearchFriendObject(angle, 1.5f, Math::PI*0.04f);
- if ( other == 0 ) return false;
-
- fret = other->RetPower();
- if ( fret != 0 ) return false; // the other already has a battery?
-
- fret = m_object->RetFret();
- if ( fret == 0 ) return false;
- m_fretType = fret->RetType();
-
- other->SetPower(fret);
- fret->SetTruck(other);
-
- character = other->RetCharacter();
- fret->SetPosition(0, character->posPower);
- fret->SetAngleY(0, 0.0f);
- fret->SetAngleX(0, 0.0f);
- fret->SetAngleZ(0, 0.0f);
- fret->SetTruckPart(0); // carried by the base
-
- m_object->SetFret(0); // deposit
- }
-
- return true;
-}
-
-// Seeks if a location allows to deposit an object.
-
-bool CTaskTake::IsFreeDeposeObject(Math::Vector pos)
-{
- CObject* pObj;
- Math::Matrix* mat;
- Math::Vector iPos, oPos;
- float oRadius;
- int i, j;
-
- mat = m_object->RetWorldMatrix(0);
- iPos = Transform(*mat, pos);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue;
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- if ( Math::Distance(iPos, oPos)-(oRadius+1.0f) < 1.0f )
- {
- return false; // location occupied
- }
- }
- }
- return true; // location free
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// tasktake.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/tasktake.h"
+
+#include "common/iman.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "math/geometry.h"
+#include "object/motion/motionhuman.h"
+#include "object/robotmain.h"
+#include "physics/physics.h"
+
+
+
+
+// Object's constructor.
+
+CTaskTake::CTaskTake(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+
+ m_arm = TTA_NEUTRAL;
+}
+
+// Object's destructor.
+
+CTaskTake::~CTaskTake()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskTake::EventProcess(const Event &event)
+{
+ float a, g, cirSpeed;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ if ( m_bTurn ) // preliminary rotation?
+ {
+ a = m_object->RetAngleY(0);
+ g = m_angle;
+ cirSpeed = Math::Direction(a, g)*2.0f;
+ if ( cirSpeed > 1.0f ) cirSpeed = 1.0f;
+ if ( cirSpeed < -1.0f ) cirSpeed = -1.0f;
+
+ m_physics->SetMotorSpeedZ(cirSpeed); // turns left / right
+ return true;
+ }
+
+ m_progress += event.rTime*m_speed; // others advance
+
+ m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f)); // immobile!
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskTake::Start()
+{
+ ObjectType type;
+ CObject* other;
+ float iAngle, oAngle, h;
+ Math::Vector pos;
+
+ m_height = 0.0f;
+ m_step = 0;
+ m_progress = 0.0f;
+
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+ oAngle = iAngle;
+
+ m_bError = true; // operation impossible
+ if ( !m_physics->RetLand() )
+ {
+ pos = m_object->RetPosition(0);
+ h = m_water->RetLevel(m_object);
+ if ( pos.y < h ) return ERR_MANIP_WATER; // impossible under water
+ return ERR_MANIP_FLY;
+ }
+
+ type = m_object->RetType();
+ if ( type != OBJECT_HUMAN &&
+ type != OBJECT_TECH ) return ERR_MANIP_VEH;
+
+ m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));
+
+ if ( m_object->RetFret() == 0 )
+ {
+ m_order = TTO_TAKE;
+ }
+ else
+ {
+ m_order = TTO_DEPOSE;
+ }
+
+ if ( m_order == TTO_TAKE )
+ {
+ pos = m_object->RetPosition(0);
+ h = m_water->RetLevel(m_object);
+ if ( pos.y < h ) return ERR_MANIP_WATER; // impossible under water
+
+ other = SearchFriendObject(oAngle, 1.5f, Math::PI*0.50f);
+ if ( other != 0 && other->RetPower() != 0 )
+ {
+ type = other->RetPower()->RetType();
+ if ( type == OBJECT_URANIUM ) return ERR_MANIP_RADIO;
+ if ( type != OBJECT_FRET &&
+ type != OBJECT_STONE &&
+ type != OBJECT_BULLET &&
+ type != OBJECT_METAL &&
+ type != OBJECT_POWER &&
+ type != OBJECT_ATOMIC &&
+ type != OBJECT_BBOX &&
+ type != OBJECT_KEYa &&
+ type != OBJECT_KEYb &&
+ type != OBJECT_KEYc &&
+ type != OBJECT_KEYd &&
+ type != OBJECT_TNT ) return ERR_MANIP_FRIEND;
+//? m_camera->StartCentering(m_object, Math::PI*0.3f, -Math::PI*0.1f, 0.0f, 0.8f);
+ m_arm = TTA_FRIEND;
+ }
+ else
+ {
+ other = SearchTakeObject(oAngle, 1.5f, Math::PI*0.45f);
+ if ( other == 0 ) return ERR_MANIP_NIL;
+ type = other->RetType();
+ if ( type == OBJECT_URANIUM ) return ERR_MANIP_RADIO;
+//? m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.8f);
+ m_arm = TTA_FFRONT;
+ m_main->HideDropZone(other); // hides buildable area
+ }
+ }
+
+ if ( m_order == TTO_DEPOSE )
+ {
+//? speed = m_physics->RetMotorSpeed();
+//? if ( speed.x != 0.0f ||
+//? speed.z != 0.0f ) return ERR_MANIP_MOTOR;
+
+ other = SearchFriendObject(oAngle, 1.5f, Math::PI*0.50f);
+ if ( other != 0 && other->RetPower() == 0 )
+ {
+//? m_camera->StartCentering(m_object, Math::PI*0.3f, -Math::PI*0.1f, 0.0f, 0.8f);
+ m_arm = TTA_FRIEND;
+ }
+ else
+ {
+ if ( !IsFreeDeposeObject(Math::Vector(2.5f, 0.0f, 0.0f)) ) return ERR_MANIP_OCC;
+//? m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.8f);
+ m_arm = TTA_FFRONT;
+ }
+ }
+
+ m_bTurn = true; // preliminary rotation necessary
+ m_angle = oAngle; // angle was reached
+
+ m_physics->SetFreeze(true); // it does not move
+
+ m_bError = false; // ok
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskTake::IsEnded()
+{
+ CObject* fret;
+ float angle;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_bTurn ) // preliminary rotation?
+ {
+ angle = m_object->RetAngleY(0);
+ angle = Math::NormAngle(angle); // 0..2*Math::PI
+
+ if ( Math::TestAngle(angle, m_angle-Math::PI*0.01f, m_angle+Math::PI*0.01f) )
+ {
+ m_bTurn = false; // rotation ended
+ m_physics->SetMotorSpeedZ(0.0f);
+
+ if ( m_arm == TTA_FFRONT )
+ {
+ m_motion->SetAction(MHS_TAKE, 0.2f); // will decrease
+ }
+ if ( m_arm == TTA_FRIEND )
+ {
+ if ( m_height <= 3.0f )
+ {
+ m_motion->SetAction(MHS_TAKEOTHER, 0.2f); // will decrease
+ }
+ else
+ {
+ m_motion->SetAction(MHS_TAKEHIGH, 0.2f); // will decrease
+ }
+ }
+ m_progress = 0.0f;
+ m_speed = 1.0f/0.6f;
+ }
+ return ERR_CONTINUE;
+ }
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+ m_progress = 0.0f;
+
+ m_step ++;
+
+ if ( m_order == TTO_TAKE )
+ {
+ if ( m_step == 1 )
+ {
+ if ( TruckTakeObject() )
+ {
+ if ( m_arm == TTA_FRIEND &&
+ (m_fretType == OBJECT_POWER ||
+ m_fretType == OBJECT_ATOMIC ) )
+ {
+ m_sound->Play(SOUND_POWEROFF, m_object->RetPosition(0));
+ }
+ }
+ m_motion->SetAction(MHS_UPRIGHT, 0.4f); // gets up
+ m_progress = 0.0f;
+ m_speed = 1.0f/0.8f;
+ m_camera->StopCentering(m_object, 0.8f);
+ return ERR_CONTINUE;
+ }
+ }
+
+ if ( m_order == TTO_DEPOSE )
+ {
+ if ( m_step == 1 )
+ {
+ fret = m_object->RetFret();
+ TruckDeposeObject();
+ if ( m_arm == TTA_FRIEND &&
+ (m_fretType == OBJECT_POWER ||
+ m_fretType == OBJECT_ATOMIC ) )
+ {
+ m_sound->Play(SOUND_POWERON, m_object->RetPosition(0));
+ }
+ if ( fret != 0 && m_fretType == OBJECT_METAL && m_arm == TTA_FFRONT )
+ {
+ m_main->ShowDropZone(fret, m_object); // shows buildable area
+ }
+ m_motion->SetAction(-1); // gets up
+ m_progress = 0.0f;
+ m_speed = 1.0f/0.4f;
+ m_camera->StopCentering(m_object, 0.8f);
+ return ERR_CONTINUE;
+ }
+ }
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskTake::Abort()
+{
+ m_motion->SetAction(-1);
+ m_camera->StopCentering(m_object, 0.8f);
+ m_physics->SetFreeze(false); // is moving again
+ return true;
+}
+
+
+// Seeks the object to take in front.
+
+CObject* CTaskTake::SearchTakeObject(float &angle,
+ float dLimit, float aLimit)
+{
+ CObject *pObj, *pBest;
+ Math::Vector iPos, oPos;
+ ObjectType type;
+ float min, iAngle, bAngle, a, distance;
+ int i;
+
+ iPos = m_object->RetPosition(0);
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+
+ min = 1000000.0f;
+ pBest = 0;
+ bAngle = 0.0f;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+
+ if ( type != OBJECT_FRET &&
+ type != OBJECT_STONE &&
+ type != OBJECT_URANIUM &&
+ type != OBJECT_BULLET &&
+ type != OBJECT_METAL &&
+ type != OBJECT_POWER &&
+ type != OBJECT_ATOMIC &&
+ type != OBJECT_BBOX &&
+ type != OBJECT_KEYa &&
+ type != OBJECT_KEYb &&
+ type != OBJECT_KEYc &&
+ type != OBJECT_KEYd &&
+ type != OBJECT_TNT ) continue;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( pObj->RetLock() ) continue;
+ if ( pObj->RetZoomY(0) != 1.0f ) continue;
+
+ oPos = pObj->RetPosition(0);
+ distance = Math::Distance(oPos, iPos);
+ if ( distance >= 4.0f-dLimit &&
+ distance <= 4.0f+dLimit )
+ {
+ angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+ if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
+ {
+ a = fabs(angle-iAngle);
+ if ( a > Math::PI ) a = Math::PI*2.0f-a;
+ if ( a < min )
+ {
+ min = a;
+ pBest = pObj;
+ bAngle = angle;
+ }
+ }
+ }
+ }
+ angle = bAngle;
+ return pBest;
+}
+
+// Seeks the robot on which you want take or put a battery.
+
+CObject* CTaskTake::SearchFriendObject(float &angle,
+ float dLimit, float aLimit)
+{
+ Character* character;
+ CObject* pObj;
+ CObject* pPower;
+ Math::Matrix* mat;
+ Math::Vector iPos, oPos;
+ ObjectType type, powerType;
+ float iAngle, iRad, distance;
+ int i;
+
+ if ( !m_object->GetCrashSphere(0, iPos, iRad) ) return 0;
+ iAngle = m_object->RetAngleY(0);
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue; // yourself?
+
+ type = pObj->RetType();
+ 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_MOBILEtg &&
+ type != OBJECT_MOBILEft &&
+ type != OBJECT_MOBILEtt &&
+ type != OBJECT_MOBILEwt &&
+ type != OBJECT_MOBILEit &&
+ type != OBJECT_TOWER &&
+ type != OBJECT_RESEARCH &&
+ type != OBJECT_ENERGY &&
+ type != OBJECT_LABO &&
+ type != OBJECT_NUCLEAR ) continue;
+
+ pPower = pObj->RetPower();
+ if ( pPower != 0 )
+ {
+ if ( pPower->RetLock() ) continue;
+ if ( pPower->RetZoomY(0) != 1.0f ) continue;
+
+ powerType = pPower->RetType();
+ if ( powerType == OBJECT_NULL ||
+ powerType == OBJECT_FIX ) continue;
+ }
+
+ mat = pObj->RetWorldMatrix(0);
+ character = pObj->RetCharacter();
+ oPos = Transform(*mat, character->posPower);
+
+ distance = fabs(Math::Distance(oPos, iPos) - (iRad+1.0f));
+ if ( distance <= dLimit )
+ {
+ angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+ if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
+ {
+ character = pObj->RetCharacter();
+ m_height = character->posPower.y;
+ return pObj;
+ }
+ }
+ }
+
+ return 0;
+}
+
+// Takes the object in front.
+
+bool CTaskTake::TruckTakeObject()
+{
+ CObject* fret;
+ CObject* other;
+ Math::Matrix matRotate;
+ float angle;
+
+ if ( m_arm == TTA_FFRONT ) // takes on the ground in front?
+ {
+//? fret = SearchTakeObject(angle, 1.5f, Math::PI*0.04f);
+ fret = SearchTakeObject(angle, 1.5f, Math::PI*0.15f); //OK 1.9
+ if ( fret == 0 ) return false; // rien � prendre ?
+ m_fretType = fret->RetType();
+
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(4); // takes with the hand
+
+//? fret->SetPosition(0, Math::Vector(2.2f, -1.0f, 1.1f));
+ fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f));
+ fret->SetAngleY(0, 0.1f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.8f);
+
+ m_object->SetFret(fret); // takes
+ }
+
+ if ( m_arm == TTA_FRIEND ) // takes friend's battery?
+ {
+ other = SearchFriendObject(angle, 1.5f, Math::PI*0.04f);
+ if ( other == 0 ) return false;
+
+ fret = other->RetPower();
+ if ( fret == 0 ) return false; // the other does not have a battery?
+ m_fretType = fret->RetType();
+
+ other->SetPower(0);
+ fret->SetTruck(m_object);
+ fret->SetTruckPart(4); // takes with the hand
+
+//? fret->SetPosition(0, Math::Vector(2.2f, -1.0f, 1.1f));
+ fret->SetPosition(0, Math::Vector(1.7f, -0.5f, 1.1f));
+ fret->SetAngleY(0, 0.1f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.8f);
+
+ m_object->SetFret(fret); // takes
+ }
+
+ return true;
+}
+
+// Deposes the object taken.
+
+bool CTaskTake::TruckDeposeObject()
+{
+ Character* character;
+ CObject* fret;
+ CObject* other;
+ Math::Matrix* mat;
+ Math::Vector pos;
+ float angle;
+
+ if ( m_arm == TTA_FFRONT ) // deposes on the ground in front?
+ {
+ fret = m_object->RetFret();
+ if ( fret == 0 ) return false; // does nothing?
+ m_fretType = fret->RetType();
+
+ mat = fret->RetWorldMatrix(0);
+ pos = Transform(*mat, Math::Vector(-0.5f, 1.0f, 0.0f));
+ m_terrain->MoveOnFloor(pos);
+ fret->SetPosition(0, pos);
+ fret->SetAngleY(0, m_object->RetAngleY(0)+Math::PI/2.0f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.0f);
+ fret->FloorAdjust(); // plate well on the ground
+
+ fret->SetTruck(0);
+ m_object->SetFret(0); // deposit
+ }
+
+ if ( m_arm == TTA_FRIEND ) // deposes battery on friends?
+ {
+ other = SearchFriendObject(angle, 1.5f, Math::PI*0.04f);
+ if ( other == 0 ) return false;
+
+ fret = other->RetPower();
+ if ( fret != 0 ) return false; // the other already has a battery?
+
+ fret = m_object->RetFret();
+ if ( fret == 0 ) return false;
+ m_fretType = fret->RetType();
+
+ other->SetPower(fret);
+ fret->SetTruck(other);
+
+ character = other->RetCharacter();
+ fret->SetPosition(0, character->posPower);
+ fret->SetAngleY(0, 0.0f);
+ fret->SetAngleX(0, 0.0f);
+ fret->SetAngleZ(0, 0.0f);
+ fret->SetTruckPart(0); // carried by the base
+
+ m_object->SetFret(0); // deposit
+ }
+
+ return true;
+}
+
+// Seeks if a location allows to deposit an object.
+
+bool CTaskTake::IsFreeDeposeObject(Math::Vector pos)
+{
+ CObject* pObj;
+ Math::Matrix* mat;
+ Math::Vector iPos, oPos;
+ float oRadius;
+ int i, j;
+
+ mat = m_object->RetWorldMatrix(0);
+ iPos = Transform(*mat, pos);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue;
+ if ( !pObj->RetActif() ) continue; // inactive?
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ if ( Math::Distance(iPos, oPos)-(oRadius+1.0f) < 1.0f )
+ {
+ return false; // location occupied
+ }
+ }
+ }
+ return true; // location free
+}
+
+
diff --git a/src/object/task/tasktake.h b/src/object/task/tasktake.h
index b8203a8..b0553a0 100644
--- a/src/object/task/tasktake.h
+++ b/src/object/task/tasktake.h
@@ -1,75 +1,75 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// tasktake.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "object/object.h"
-
-
-
-enum TaskTakeOrder
-{
- TTO_TAKE = 1, // takes an object
- TTO_DEPOSE = 2, // deposes the object
-};
-
-enum TaskTakeArm
-{
- TTA_NEUTRAL = 1, // empty arm at rest
- TTA_FFRONT = 2, // arm on the ground
- TTA_FRIEND = 3, // arm behind a friend robot
-};
-
-
-
-class CTaskTake : public CTask
-{
-public:
- CTaskTake(CInstanceManager* iMan, CObject* object);
- ~CTaskTake();
-
- bool EventProcess(const Event &event);
-
- Error Start();
- Error IsEnded();
- bool Abort();
-
-protected:
- CObject* SearchTakeObject(float &angle, float dLimit, float aLimit);
- CObject* SearchFriendObject(float &angle, float dLimit, float aLimit);
- bool TruckTakeObject();
- bool TruckDeposeObject();
- bool IsFreeDeposeObject(Math::Vector pos);
-
-protected:
- CTerrain* m_terrain;
-
- TaskTakeOrder m_order;
- TaskTakeArm m_arm;
- int m_step;
- float m_speed;
- float m_progress;
- float m_height;
- bool m_bError;
- bool m_bTurn;
- float m_angle;
- ObjectType m_fretType;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// tasktake.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "object/object.h"
+
+
+
+enum TaskTakeOrder
+{
+ TTO_TAKE = 1, // takes an object
+ TTO_DEPOSE = 2, // deposes the object
+};
+
+enum TaskTakeArm
+{
+ TTA_NEUTRAL = 1, // empty arm at rest
+ TTA_FFRONT = 2, // arm on the ground
+ TTA_FRIEND = 3, // arm behind a friend robot
+};
+
+
+
+class CTaskTake : public CTask
+{
+public:
+ CTaskTake(CInstanceManager* iMan, CObject* object);
+ ~CTaskTake();
+
+ bool EventProcess(const Event &event);
+
+ Error Start();
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ CObject* SearchTakeObject(float &angle, float dLimit, float aLimit);
+ CObject* SearchFriendObject(float &angle, float dLimit, float aLimit);
+ bool TruckTakeObject();
+ bool TruckDeposeObject();
+ bool IsFreeDeposeObject(Math::Vector pos);
+
+protected:
+ CTerrain* m_terrain;
+
+ TaskTakeOrder m_order;
+ TaskTakeArm m_arm;
+ int m_step;
+ float m_speed;
+ float m_progress;
+ float m_height;
+ bool m_bError;
+ bool m_bTurn;
+ float m_angle;
+ ObjectType m_fretType;
+};
+
diff --git a/src/object/task/taskterraform.cpp b/src/object/task/taskterraform.cpp
index 58cf347..94e3b75 100644
--- a/src/object/task/taskterraform.cpp
+++ b/src/object/task/taskterraform.cpp
@@ -1,416 +1,416 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskterraform.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskterraform.h"
-
-#include "math/geometry.h"
-#include "common/iman.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "physics/physics.h"
-#include "old/pyro.h"
-#include "object/brain.h"
-#include "object/motion/motionant.h"
-#include "object/motion/motionspider.h"
-
-
-const float ENERGY_TERRA = 0.40f; // energy consumed by blow
-const float ACTION_RADIUS = 400.0f;
-
-
-
-// Object's constructor.
-
-CTaskTerraform::CTaskTerraform(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
- m_lastParticule = 0.0f;
- m_soundChannel = -1;
-}
-
-// Object's destructor.
-
-CTaskTerraform::~CTaskTerraform()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskTerraform::EventProcess(const Event &event)
-{
- CObject* power;
- Math::Matrix* mat;
- Math::Vector pos, dir, speed;
- Math::Point dim;
- float energy;
-
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_bError ) return false;
-
- m_progress += event.rTime*m_speed; // others advance
- m_time += event.rTime;
-
- if ( m_phase == TTP_CHARGE )
- {
- if ( m_soundChannel == -1 )
- {
-#if _TEEN
- m_soundChannel = m_sound->Play(SOUND_GGG, m_object->RetPosition(0), 1.0f, 0.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.0f, 1.5f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP);
-#else
- m_soundChannel = m_sound->Play(SOUND_GGG, m_object->RetPosition(0), 1.0f, 0.5f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.0f, 4.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP);
-#endif
- }
-
- dir.x = 0.0f;
- dir.y = (Math::Rand()-0.5f)*0.2f*m_progress;
- dir.z = 0.0f;
- m_object->SetCirVibration(dir);
-
- m_object->SetZoom(0, 1.0f+m_progress*0.2f);
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- power->SetZoom(0, 1.0f+m_progress*1.0f);
-
- energy = power->RetEnergy();
- energy -= event.rTime*ENERGY_TERRA/power->RetCapacity()/4.0f;
- if ( energy < 0.0f ) energy = 0.0f;
- power->SetEnergy(energy);
- }
- }
-
- if ( m_phase == TTP_DOWN )
- {
- pos.x = 9.0f;
-#if _TEEN
- pos.y = 4.0f-m_progress*4.0f;
-#else
- pos.y = 4.0f-m_progress*5.8f;
-#endif
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
- }
-
- if ( m_phase == TTP_UP )
- {
- pos.x = 9.0f;
-#if _TEEN
- pos.y = 4.0f-(1.0f-m_progress)*4.0f;
-#else
- pos.y = 4.0f-(1.0f-m_progress)*5.8f;
-#endif
- pos.z = 0.0f;
- m_object->SetPosition(2, pos);
- }
-
- dir.x = 0.0f;
- dir.y = 0.0f;
- dir.z = 0.0f;
- pos = m_object->RetPosition(2);
- if ( pos.y < 0.0f )
- {
- dir.z = -atanf((pos.y/2.0f)/9.0f);
- }
- m_object->SetInclinaison(dir);
-
- if ( m_time-m_lastParticule >= m_engine->ParticuleAdapt(0.05f) )
- {
- m_lastParticule = m_time;
-
- mat = m_object->RetWorldMatrix(0);
-
- if ( m_phase == TTP_CHARGE )
- {
- // Battery.
- pos = Math::Vector(-6.0f, 5.5f+2.0f*m_progress, 0.0f);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- pos = Math::Transform(*mat, pos);
- speed.x = (Math::Rand()-0.5f)*6.0f*(1.0f+m_progress*4.0f);
- speed.z = (Math::Rand()-0.5f)*6.0f*(1.0f+m_progress*4.0f);
- speed.y = 6.0f+Math::Rand()*4.0f*(1.0f+m_progress*2.0f);
- dim.x = 0.5f+1.5f*m_progress;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 2.0f, 20.0f);
- }
-
- if ( m_phase != TTP_CHARGE )
- {
- // Left grid.
- pos = Math::Vector(-1.0f, 5.8f, 3.5f);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- pos = Math::Transform(*mat, pos);
- speed.x = Math::Rand()*4.0f;
- speed.z = Math::Rand()*2.0f;
- speed.y = 2.5f+Math::Rand()*1.0f;
- speed = Math::Transform(*mat, speed);
- speed -= m_object->RetPosition(0);
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
-
- // Right grid.
- pos = Math::Vector(-1.0f, 5.8f, -3.5f);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- pos = Math::Transform(*mat, pos);
- speed.x = Math::Rand()*4.0f;
- speed.z = -Math::Rand()*2.0f;
- speed.y = 2.5f+Math::Rand()*1.0f;
- speed = Math::Transform(*mat, speed);
- speed -= m_object->RetPosition(0);
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
- }
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskTerraform::Start()
-{
- CObject* power;
- Math::Matrix* mat;
- Math::Vector pos, speed;
- float energy;
-
- ObjectType type;
-
- m_bError = true; // operation impossible
- if ( !m_physics->RetLand() ) return ERR_TERRA_VEH;
-
- type = m_object->RetType();
- if ( type != OBJECT_MOBILErt ) return ERR_TERRA_VEH;
-
- power = m_object->RetPower();
- if ( power == 0 ) return ERR_TERRA_ENERGY;
- energy = power->RetEnergy();
- if ( energy < ENERGY_TERRA/power->RetCapacity()+0.05f ) return ERR_TERRA_ENERGY;
-
- speed = m_physics->RetMotorSpeed();
- if ( speed.x != 0.0f ||
- speed.z != 0.0f ) return ERR_MANIP_MOTOR;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Math::Vector(9.0f, 0.0f, 0.0f);
- pos = Math::Transform(*mat, pos); // battery position
- m_terraPos = pos;
-
- m_phase = TTP_CHARGE;
- m_progress = 0.0f;
-#if _TEEN
- m_speed = 1.0f/1.5f;
-#else
- m_speed = 1.0f/4.0f;
-#endif
- m_time = 0.0f;
-
- m_bError = false; // ok
-
- m_camera->StartCentering(m_object, Math::PI*0.35f, 99.9f, 20.0f, 2.0f);
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskTerraform::IsEnded()
-{
- CObject* power;
- Math::Vector pos, speed;
- Math::Point dim;
- float dist, duration;
- int i, max;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bError ) return ERR_STOP;
-
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
- m_progress = 0.0f;
-
- if ( m_phase == TTP_CHARGE )
- {
-#if _TEEN
- Terraform(); // changes the terrain.
-#endif
-
- m_phase = TTP_DOWN;
- m_speed = 1.0f/0.2f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TTP_DOWN )
- {
-#if !_TEEN
- Terraform(); // changes the terrain.
-#endif
-
- m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetZoom(0, 1.0f);
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- power->SetZoom(0, 1.0f);
- }
-
- max= (int)(50.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<max ; i++ )
- {
- pos.x = m_terraPos.x+(Math::Rand()-0.5f)*80.0f;
- pos.z = m_terraPos.z+(Math::Rand()-0.5f)*80.0f;
- pos.y = m_terraPos.y;
- m_terrain->MoveOnFloor(pos);
- dist = Math::Distance(pos, m_terraPos);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 2.0f+(40.0f-dist)/(1.0f+Math::Rand()*4.0f);
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
-
- pos = m_terraPos;
- speed.x = (Math::Rand()-0.5f)*40.0f;
- speed.z = (Math::Rand()-0.5f)*40.0f;
- speed.y = Math::Rand()*15.0f+15.0f;
- dim.x = 0.6f;
- dim.y = dim.x;
- pos.y += dim.y;
- duration = Math::Rand()*3.0f+3.0f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK5,
- duration, Math::Rand()*10.0f+15.0f,
- duration*0.2f, 1.0f);
- }
-
- m_phase = TTP_TERRA;
- m_speed = 1.0f/2.0f;
- return ERR_CONTINUE;
- }
-
- if ( m_phase == TTP_TERRA )
- {
- m_phase = TTP_UP;
- m_speed = 1.0f/1.0f;
- return ERR_CONTINUE;
- }
-
- Abort();
- return ERR_STOP;
-}
-
-// Suddenly ends the current action.
-
-bool CTaskTerraform::Abort()
-{
- CObject* power;
-
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.3f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- m_object->SetPosition(2, Math::Vector(9.0f, 4.0f, 0.0f));
- m_object->SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- m_object->SetZoom(0, 1.0f);
-
- power = m_object->RetPower();
- if ( power != 0 )
- {
- power->SetZoom(0, 1.0f);
- }
-
- m_camera->StopCentering(m_object, 2.0f);
- return true;
-}
-
-
-// Returns all the close ants and spiders.
-
-bool CTaskTerraform::Terraform()
-{
- CObject* pObj;
- CBrain* brain;
- CMotion* motion;
- CPyro* pyro;
- ObjectType type;
- float dist;
- int i;
-
- m_camera->StartEffect(CE_TERRAFORM, m_terraPos, 1.0f);
-
- m_sound->Play(SOUND_THUMP, m_terraPos);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_NULL ) continue;
-
- if ( type == OBJECT_TEEN34 ) // stone?
- {
- dist = Math::Distance(m_terraPos, pObj->RetPosition(0));
- if ( dist > 20.0f ) continue;
-
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FRAGT, pObj);
- }
- else
- {
- motion = pObj->RetMotion();
- if ( motion == 0 ) continue;
-
- dist = Math::Distance(m_terraPos, pObj->RetPosition(0));
- if ( dist > ACTION_RADIUS ) continue;
-
- if ( type == OBJECT_ANT )
- {
- brain = pObj->RetBrain();
- if ( brain != 0 ) brain->StopTask();
- motion->SetAction(MAS_BACK1, 0.8f+Math::Rand()*0.3f);
- pObj->SetFixed(true); // not moving
- }
- if ( type == OBJECT_SPIDER )
- {
- brain = pObj->RetBrain();
- if ( brain != 0 ) brain->StopTask();
- motion->SetAction(MSS_BACK1, 0.8f+Math::Rand()*0.3f);
- pObj->SetFixed(true); // not moving
- }
- }
- }
-
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskterraform.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskterraform.h"
+
+#include "math/geometry.h"
+#include "common/iman.h"
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "physics/physics.h"
+#include "old/pyro.h"
+#include "object/brain.h"
+#include "object/motion/motionant.h"
+#include "object/motion/motionspider.h"
+
+
+const float ENERGY_TERRA = 0.40f; // energy consumed by blow
+const float ACTION_RADIUS = 400.0f;
+
+
+
+// Object's constructor.
+
+CTaskTerraform::CTaskTerraform(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+ m_lastParticule = 0.0f;
+ m_soundChannel = -1;
+}
+
+// Object's destructor.
+
+CTaskTerraform::~CTaskTerraform()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskTerraform::EventProcess(const Event &event)
+{
+ CObject* power;
+ Math::Matrix* mat;
+ Math::Vector pos, dir, speed;
+ Math::Point dim;
+ float energy;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_bError ) return false;
+
+ m_progress += event.rTime*m_speed; // others advance
+ m_time += event.rTime;
+
+ if ( m_phase == TTP_CHARGE )
+ {
+ if ( m_soundChannel == -1 )
+ {
+#if _TEEN
+ m_soundChannel = m_sound->Play(SOUND_GGG, m_object->RetPosition(0), 1.0f, 0.5f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.0f, 1.5f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP);
+#else
+ m_soundChannel = m_sound->Play(SOUND_GGG, m_object->RetPosition(0), 1.0f, 0.5f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 2.0f, 4.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.5f, SOPER_STOP);
+#endif
+ }
+
+ dir.x = 0.0f;
+ dir.y = (Math::Rand()-0.5f)*0.2f*m_progress;
+ dir.z = 0.0f;
+ m_object->SetCirVibration(dir);
+
+ m_object->SetZoom(0, 1.0f+m_progress*0.2f);
+
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ power->SetZoom(0, 1.0f+m_progress*1.0f);
+
+ energy = power->RetEnergy();
+ energy -= event.rTime*ENERGY_TERRA/power->RetCapacity()/4.0f;
+ if ( energy < 0.0f ) energy = 0.0f;
+ power->SetEnergy(energy);
+ }
+ }
+
+ if ( m_phase == TTP_DOWN )
+ {
+ pos.x = 9.0f;
+#if _TEEN
+ pos.y = 4.0f-m_progress*4.0f;
+#else
+ pos.y = 4.0f-m_progress*5.8f;
+#endif
+ pos.z = 0.0f;
+ m_object->SetPosition(2, pos);
+ }
+
+ if ( m_phase == TTP_UP )
+ {
+ pos.x = 9.0f;
+#if _TEEN
+ pos.y = 4.0f-(1.0f-m_progress)*4.0f;
+#else
+ pos.y = 4.0f-(1.0f-m_progress)*5.8f;
+#endif
+ pos.z = 0.0f;
+ m_object->SetPosition(2, pos);
+ }
+
+ dir.x = 0.0f;
+ dir.y = 0.0f;
+ dir.z = 0.0f;
+ pos = m_object->RetPosition(2);
+ if ( pos.y < 0.0f )
+ {
+ dir.z = -atanf((pos.y/2.0f)/9.0f);
+ }
+ m_object->SetInclinaison(dir);
+
+ if ( m_time-m_lastParticule >= m_engine->ParticuleAdapt(0.05f) )
+ {
+ m_lastParticule = m_time;
+
+ mat = m_object->RetWorldMatrix(0);
+
+ if ( m_phase == TTP_CHARGE )
+ {
+ // Battery.
+ pos = Math::Vector(-6.0f, 5.5f+2.0f*m_progress, 0.0f);
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ pos = Math::Transform(*mat, pos);
+ speed.x = (Math::Rand()-0.5f)*6.0f*(1.0f+m_progress*4.0f);
+ speed.z = (Math::Rand()-0.5f)*6.0f*(1.0f+m_progress*4.0f);
+ speed.y = 6.0f+Math::Rand()*4.0f*(1.0f+m_progress*2.0f);
+ dim.x = 0.5f+1.5f*m_progress;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 2.0f, 20.0f);
+ }
+
+ if ( m_phase != TTP_CHARGE )
+ {
+ // Left grid.
+ pos = Math::Vector(-1.0f, 5.8f, 3.5f);
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ pos = Math::Transform(*mat, pos);
+ speed.x = Math::Rand()*4.0f;
+ speed.z = Math::Rand()*2.0f;
+ speed.y = 2.5f+Math::Rand()*1.0f;
+ speed = Math::Transform(*mat, speed);
+ speed -= m_object->RetPosition(0);
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
+
+ // Right grid.
+ pos = Math::Vector(-1.0f, 5.8f, -3.5f);
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ pos = Math::Transform(*mat, pos);
+ speed.x = Math::Rand()*4.0f;
+ speed.z = -Math::Rand()*2.0f;
+ speed.y = 2.5f+Math::Rand()*1.0f;
+ speed = Math::Transform(*mat, speed);
+ speed -= m_object->RetPosition(0);
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
+ }
+ }
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskTerraform::Start()
+{
+ CObject* power;
+ Math::Matrix* mat;
+ Math::Vector pos, speed;
+ float energy;
+
+ ObjectType type;
+
+ m_bError = true; // operation impossible
+ if ( !m_physics->RetLand() ) return ERR_TERRA_VEH;
+
+ type = m_object->RetType();
+ if ( type != OBJECT_MOBILErt ) return ERR_TERRA_VEH;
+
+ power = m_object->RetPower();
+ if ( power == 0 ) return ERR_TERRA_ENERGY;
+ energy = power->RetEnergy();
+ if ( energy < ENERGY_TERRA/power->RetCapacity()+0.05f ) return ERR_TERRA_ENERGY;
+
+ speed = m_physics->RetMotorSpeed();
+ if ( speed.x != 0.0f ||
+ speed.z != 0.0f ) return ERR_MANIP_MOTOR;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Math::Vector(9.0f, 0.0f, 0.0f);
+ pos = Math::Transform(*mat, pos); // battery position
+ m_terraPos = pos;
+
+ m_phase = TTP_CHARGE;
+ m_progress = 0.0f;
+#if _TEEN
+ m_speed = 1.0f/1.5f;
+#else
+ m_speed = 1.0f/4.0f;
+#endif
+ m_time = 0.0f;
+
+ m_bError = false; // ok
+
+ m_camera->StartCentering(m_object, Math::PI*0.35f, 99.9f, 20.0f, 2.0f);
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskTerraform::IsEnded()
+{
+ CObject* power;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float dist, duration;
+ int i, max;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bError ) return ERR_STOP;
+
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+ m_progress = 0.0f;
+
+ if ( m_phase == TTP_CHARGE )
+ {
+#if _TEEN
+ Terraform(); // changes the terrain.
+#endif
+
+ m_phase = TTP_DOWN;
+ m_speed = 1.0f/0.2f;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TTP_DOWN )
+ {
+#if !_TEEN
+ Terraform(); // changes the terrain.
+#endif
+
+ m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ m_object->SetZoom(0, 1.0f);
+
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ power->SetZoom(0, 1.0f);
+ }
+
+ max= (int)(50.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<max ; i++ )
+ {
+ pos.x = m_terraPos.x+(Math::Rand()-0.5f)*80.0f;
+ pos.z = m_terraPos.z+(Math::Rand()-0.5f)*80.0f;
+ pos.y = m_terraPos.y;
+ m_terrain->MoveOnFloor(pos);
+ dist = Math::Distance(pos, m_terraPos);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 2.0f+(40.0f-dist)/(1.0f+Math::Rand()*4.0f);
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+
+ pos = m_terraPos;
+ speed.x = (Math::Rand()-0.5f)*40.0f;
+ speed.z = (Math::Rand()-0.5f)*40.0f;
+ speed.y = Math::Rand()*15.0f+15.0f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ pos.y += dim.y;
+ duration = Math::Rand()*3.0f+3.0f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK5,
+ duration, Math::Rand()*10.0f+15.0f,
+ duration*0.2f, 1.0f);
+ }
+
+ m_phase = TTP_TERRA;
+ m_speed = 1.0f/2.0f;
+ return ERR_CONTINUE;
+ }
+
+ if ( m_phase == TTP_TERRA )
+ {
+ m_phase = TTP_UP;
+ m_speed = 1.0f/1.0f;
+ return ERR_CONTINUE;
+ }
+
+ Abort();
+ return ERR_STOP;
+}
+
+// Suddenly ends the current action.
+
+bool CTaskTerraform::Abort()
+{
+ CObject* power;
+
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.3f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ m_object->SetPosition(2, Math::Vector(9.0f, 4.0f, 0.0f));
+ m_object->SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
+ m_object->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ m_object->SetZoom(0, 1.0f);
+
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ power->SetZoom(0, 1.0f);
+ }
+
+ m_camera->StopCentering(m_object, 2.0f);
+ return true;
+}
+
+
+// Returns all the close ants and spiders.
+
+bool CTaskTerraform::Terraform()
+{
+ CObject* pObj;
+ CBrain* brain;
+ CMotion* motion;
+ CPyro* pyro;
+ ObjectType type;
+ float dist;
+ int i;
+
+ m_camera->StartEffect(CE_TERRAFORM, m_terraPos, 1.0f);
+
+ m_sound->Play(SOUND_THUMP, m_terraPos);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_NULL ) continue;
+
+ if ( type == OBJECT_TEEN34 ) // stone?
+ {
+ dist = Math::Distance(m_terraPos, pObj->RetPosition(0));
+ if ( dist > 20.0f ) continue;
+
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FRAGT, pObj);
+ }
+ else
+ {
+ motion = pObj->RetMotion();
+ if ( motion == 0 ) continue;
+
+ dist = Math::Distance(m_terraPos, pObj->RetPosition(0));
+ if ( dist > ACTION_RADIUS ) continue;
+
+ if ( type == OBJECT_ANT )
+ {
+ brain = pObj->RetBrain();
+ if ( brain != 0 ) brain->StopTask();
+ motion->SetAction(MAS_BACK1, 0.8f+Math::Rand()*0.3f);
+ pObj->SetFixed(true); // not moving
+ }
+ if ( type == OBJECT_SPIDER )
+ {
+ brain = pObj->RetBrain();
+ if ( brain != 0 ) brain->StopTask();
+ motion->SetAction(MSS_BACK1, 0.8f+Math::Rand()*0.3f);
+ pObj->SetFixed(true); // not moving
+ }
+ }
+ }
+
+ return true;
+}
+
diff --git a/src/object/task/taskterraform.h b/src/object/task/taskterraform.h
index d4798e6..5c9c114 100644
--- a/src/object/task/taskterraform.h
+++ b/src/object/task/taskterraform.h
@@ -1,62 +1,62 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskterraform.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-#include "math/vector.h"
-
-
-
-enum TaskTerraPhase
-{
- TTP_CHARGE = 1, // charge of energy
- TTP_DOWN = 2, // down
- TTP_TERRA = 3, // strike
- TTP_UP = 4, // up
-};
-
-
-
-class CTaskTerraform : public CTask
-{
-public:
- CTaskTerraform(CInstanceManager* iMan, CObject* object);
- ~CTaskTerraform();
-
- bool EventProcess(const Event &event);
-
- Error Start();
- Error IsEnded();
- bool Abort();
-
-protected:
- bool Terraform();
-
-protected:
- TaskTerraPhase m_phase;
- float m_progress;
- float m_speed;
- float m_time;
- float m_lastParticule;
- int m_soundChannel;
- bool m_bError;
- Math::Vector m_terraPos;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskterraform.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+#include "math/vector.h"
+
+
+
+enum TaskTerraPhase
+{
+ TTP_CHARGE = 1, // charge of energy
+ TTP_DOWN = 2, // down
+ TTP_TERRA = 3, // strike
+ TTP_UP = 4, // up
+};
+
+
+
+class CTaskTerraform : public CTask
+{
+public:
+ CTaskTerraform(CInstanceManager* iMan, CObject* object);
+ ~CTaskTerraform();
+
+ bool EventProcess(const Event &event);
+
+ Error Start();
+ Error IsEnded();
+ bool Abort();
+
+protected:
+ bool Terraform();
+
+protected:
+ TaskTerraPhase m_phase;
+ float m_progress;
+ float m_speed;
+ float m_time;
+ float m_lastParticule;
+ int m_soundChannel;
+ bool m_bError;
+ Math::Vector m_terraPos;
+};
+
diff --git a/src/object/task/taskturn.cpp b/src/object/task/taskturn.cpp
index d29cdaa..f8bf26c 100644
--- a/src/object/task/taskturn.cpp
+++ b/src/object/task/taskturn.cpp
@@ -1,134 +1,134 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskturn.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskturn.h"
-
-#include "old/terrain.h"
-#include "physics/physics.h"
-
-
-
-
-// Object's constructor.
-
-CTaskTurn::CTaskTurn(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskTurn::~CTaskTurn()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskTurn::EventProcess(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- // Momentarily stationary object (ant on the back)?
- if ( m_object->RetFixed() )
- {
- m_physics->SetMotorSpeedX(0.0f); // stops the advance
- m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
- m_bError = true;
- return true;
- }
-
- return true;
-}
-
-
-// Assigns the goal was achieved.
-// A positive angle is turning right.
-
-Error CTaskTurn::Start(float angle)
-{
- m_startAngle = m_object->RetAngleY(0);
- m_finalAngle = m_startAngle+angle;
-
- if ( angle < 0.0f )
- {
- m_angle = angle+m_physics->RetCirStopLength();
- m_physics->SetMotorSpeedZ(-1.0f); // turns left
- m_bLeft = true;
- }
- else
- {
- m_angle = angle-m_physics->RetCirStopLength();
- m_physics->SetMotorSpeedZ(1.0f); // turns right
- m_bLeft = false;
- }
- m_physics->SetMotorSpeedX(0.0f);
- m_physics->SetMotorSpeedY(0.0f);
-
- m_bError = false;
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskTurn::IsEnded()
-{
- float angle;
-
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
-
- if ( m_bError )
- {
- return ERR_STOP;
- }
-
- angle = m_object->RetAngleY(0);
-
- if ( m_bLeft )
- {
- if ( angle <= m_startAngle+m_angle )
- {
- m_physics->SetMotorSpeedZ(0.0f);
-//? m_physics->SetCirMotionY(MO_MOTSPEED, 0.0f);
- m_physics->SetCirMotionY(MO_CURSPEED, 0.0f);
-//? m_physics->SetCirMotionY(MO_REASPEED, 0.0f);
- m_object->SetAngleY(0, m_finalAngle);
- return ERR_STOP;
- }
- }
- else
- {
- if ( angle >= m_startAngle+m_angle )
- {
- m_physics->SetMotorSpeedZ(0.0f);
-//? m_physics->SetCirMotionY(MO_MOTSPEED, 0.0f);
- m_physics->SetCirMotionY(MO_CURSPEED, 0.0f);
-//? m_physics->SetCirMotionY(MO_REASPEED, 0.0f);
- m_object->SetAngleY(0, m_finalAngle);
- return ERR_STOP;
- }
- }
-
- return ERR_CONTINUE;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskturn.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskturn.h"
+
+#include "old/terrain.h"
+#include "physics/physics.h"
+
+
+
+
+// Object's constructor.
+
+CTaskTurn::CTaskTurn(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+}
+
+// Object's destructor.
+
+CTaskTurn::~CTaskTurn()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskTurn::EventProcess(const Event &event)
+{
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ // Momentarily stationary object (ant on the back)?
+ if ( m_object->RetFixed() )
+ {
+ m_physics->SetMotorSpeedX(0.0f); // stops the advance
+ m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
+ m_bError = true;
+ return true;
+ }
+
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+// A positive angle is turning right.
+
+Error CTaskTurn::Start(float angle)
+{
+ m_startAngle = m_object->RetAngleY(0);
+ m_finalAngle = m_startAngle+angle;
+
+ if ( angle < 0.0f )
+ {
+ m_angle = angle+m_physics->RetCirStopLength();
+ m_physics->SetMotorSpeedZ(-1.0f); // turns left
+ m_bLeft = true;
+ }
+ else
+ {
+ m_angle = angle-m_physics->RetCirStopLength();
+ m_physics->SetMotorSpeedZ(1.0f); // turns right
+ m_bLeft = false;
+ }
+ m_physics->SetMotorSpeedX(0.0f);
+ m_physics->SetMotorSpeedY(0.0f);
+
+ m_bError = false;
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskTurn::IsEnded()
+{
+ float angle;
+
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+
+ if ( m_bError )
+ {
+ return ERR_STOP;
+ }
+
+ angle = m_object->RetAngleY(0);
+
+ if ( m_bLeft )
+ {
+ if ( angle <= m_startAngle+m_angle )
+ {
+ m_physics->SetMotorSpeedZ(0.0f);
+//? m_physics->SetCirMotionY(MO_MOTSPEED, 0.0f);
+ m_physics->SetCirMotionY(MO_CURSPEED, 0.0f);
+//? m_physics->SetCirMotionY(MO_REASPEED, 0.0f);
+ m_object->SetAngleY(0, m_finalAngle);
+ return ERR_STOP;
+ }
+ }
+ else
+ {
+ if ( angle >= m_startAngle+m_angle )
+ {
+ m_physics->SetMotorSpeedZ(0.0f);
+//? m_physics->SetCirMotionY(MO_MOTSPEED, 0.0f);
+ m_physics->SetCirMotionY(MO_CURSPEED, 0.0f);
+//? m_physics->SetCirMotionY(MO_REASPEED, 0.0f);
+ m_object->SetAngleY(0, m_finalAngle);
+ return ERR_STOP;
+ }
+ }
+
+ return ERR_CONTINUE;
+}
+
+
diff --git a/src/object/task/taskturn.h b/src/object/task/taskturn.h
index bfbd064..1ee40d9 100644
--- a/src/object/task/taskturn.h
+++ b/src/object/task/taskturn.h
@@ -1,46 +1,46 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskturn.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskTurn : public CTask
-{
-public:
- CTaskTurn(CInstanceManager* iMan, CObject* object);
- ~CTaskTurn();
-
- bool EventProcess(const Event &event);
-
- Error Start(float angle);
- Error IsEnded();
-
-protected:
-
-protected:
- float m_angle;
- float m_startAngle;
- float m_finalAngle;
- bool m_bLeft;
- bool m_bError;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskturn.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+
+
+
+class CTaskTurn : public CTask
+{
+public:
+ CTaskTurn(CInstanceManager* iMan, CObject* object);
+ ~CTaskTurn();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(float angle);
+ Error IsEnded();
+
+protected:
+
+protected:
+ float m_angle;
+ float m_startAngle;
+ float m_finalAngle;
+ bool m_bLeft;
+ bool m_bError;
+};
+
diff --git a/src/object/task/taskwait.cpp b/src/object/task/taskwait.cpp
index f501405..03bddcb 100644
--- a/src/object/task/taskwait.cpp
+++ b/src/object/task/taskwait.cpp
@@ -1,74 +1,74 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskwait.cpp
-
-
-#include <stdio.h>
-
-#include "object/task/taskwait.h"
-
-#include "old/d3dengine.h"
-
-
-
-// Object's constructor.
-
-CTaskWait::CTaskWait(CInstanceManager* iMan, CObject* object)
- : CTask(iMan, object)
-{
-}
-
-// Object's destructor.
-
-CTaskWait::~CTaskWait()
-{
-}
-
-
-// Management of an event.
-
-bool CTaskWait::EventProcess(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
- if ( event.event != EVENT_FRAME ) return true;
-
- m_passTime += event.rTime;
- m_bEnded = (m_passTime >= m_waitTime);
- return true;
-}
-
-
-// Assigns the goal was achieved.
-
-Error CTaskWait::Start(float time)
-{
- m_waitTime = time; // duration to wait
- m_passTime = 0.0f; // time elapsed
- m_bEnded = false;
- return ERR_OK;
-}
-
-// Indicates whether the action is finished.
-
-Error CTaskWait::IsEnded()
-{
- if ( m_engine->RetPause() ) return ERR_CONTINUE;
- if ( m_bEnded ) return ERR_STOP;
- return ERR_CONTINUE;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskwait.cpp
+
+
+#include <stdio.h>
+
+#include "object/task/taskwait.h"
+
+#include "old/d3dengine.h"
+
+
+
+// Object's constructor.
+
+CTaskWait::CTaskWait(CInstanceManager* iMan, CObject* object)
+ : CTask(iMan, object)
+{
+}
+
+// Object's destructor.
+
+CTaskWait::~CTaskWait()
+{
+}
+
+
+// Management of an event.
+
+bool CTaskWait::EventProcess(const Event &event)
+{
+ if ( m_engine->RetPause() ) return true;
+ if ( event.event != EVENT_FRAME ) return true;
+
+ m_passTime += event.rTime;
+ m_bEnded = (m_passTime >= m_waitTime);
+ return true;
+}
+
+
+// Assigns the goal was achieved.
+
+Error CTaskWait::Start(float time)
+{
+ m_waitTime = time; // duration to wait
+ m_passTime = 0.0f; // time elapsed
+ m_bEnded = false;
+ return ERR_OK;
+}
+
+// Indicates whether the action is finished.
+
+Error CTaskWait::IsEnded()
+{
+ if ( m_engine->RetPause() ) return ERR_CONTINUE;
+ if ( m_bEnded ) return ERR_STOP;
+ return ERR_CONTINUE;
+}
+
+
diff --git a/src/object/task/taskwait.h b/src/object/task/taskwait.h
index 3439bc8..3434c36 100644
--- a/src/object/task/taskwait.h
+++ b/src/object/task/taskwait.h
@@ -1,44 +1,44 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// taskwait.h
-
-#pragma once
-
-
-#include "object/task/task.h"
-
-
-
-class CTaskWait : public CTask
-{
-public:
- CTaskWait(CInstanceManager* iMan, CObject* object);
- ~CTaskWait();
-
- bool EventProcess(const Event &event);
-
- Error Start(float time);
- Error IsEnded();
-
-protected:
-
-protected:
- float m_waitTime;
- float m_passTime;
- bool m_bEnded;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// taskwait.h
+
+#pragma once
+
+
+#include "object/task/task.h"
+
+
+
+class CTaskWait : public CTask
+{
+public:
+ CTaskWait(CInstanceManager* iMan, CObject* object);
+ ~CTaskWait();
+
+ bool EventProcess(const Event &event);
+
+ Error Start(float time);
+ Error IsEnded();
+
+protected:
+
+protected:
+ float m_waitTime;
+ float m_passTime;
+ bool m_bEnded;
+};
+
diff --git a/src/old/blitz.cpp b/src/old/blitz.cpp
index 15488d2..b3708bb 100644
--- a/src/old/blitz.cpp
+++ b/src/old/blitz.cpp
@@ -1,475 +1,475 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "math/conv.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "old/d3dutil.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "old/math3d.h"
-#include "object/object.h"
-#include "old/camera.h"
-#include "object/auto/auto.h"
-#include "object/auto/autopara.h"
-#include "old/sound.h"
-#include "old/blitz.h"
-
-
-
-
-// Constructor of the terrain.
-
-CBlitz::CBlitz(CInstanceManager* iMan, CD3DEngine* engine)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_BLITZ, this);
-
- m_engine = engine;
- m_terrain = 0;
- m_camera = 0;
- m_sound = 0;
- Flush();
-}
-
-// Destructor of the terrain.
-
-CBlitz::~CBlitz()
-{
-}
-
-
-// Removes lightning.
-
-void CBlitz::Flush()
-{
- int i;
-
- m_bBlitzExist = false;
- m_time = 0.0f;
- m_phase = BPH_WAIT;
- m_speed = 0.0f;
- m_progress = 0.0f;
-
- for ( i=0 ; i<BLITZMAX ; i++ )
- {
- m_shift[i] = Math::Point(0.0f, 0.0f);
- m_width[i] = 1.0f;
- }
-}
-
-
-// Management of an event
-
-bool CBlitz::EventProcess(const Event &event)
-{
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
- return true;
-}
-
-// Evolved lightning.
-
-bool CBlitz::EventFrame(const Event &event)
-{
- CObject* pObj;
- CAutoPara* automat;
- ObjectType type;
- Math::Vector eye, pos;
- float dist, deep, max;
- int i;
-
- if ( m_engine->RetPause() ) return true;
- if ( m_engine->RetMovieLock() ) return true;
-
- m_time += event.rTime;
- m_progress += event.rTime*m_speed;
-
- if ( m_phase == BPH_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
-#if 1
- m_pos.x = (Math::Rand()-0.5f)*(3200.0f-200.0f);
- m_pos.z = (Math::Rand()-0.5f)*(3200.0f-200.0f);
-#else
- m_pos.x = (Math::Rand()-0.5f)*(3200.0f-2800.0f);
- m_pos.z = (Math::Rand()-0.5f)*(3200.0f-2800.0f);
-#endif
- m_pos.y = 0.0f;
-
- pObj = SearchObject(m_pos);
- if ( pObj == 0 )
- {
- m_terrain->MoveOnFloor(m_pos, true);
- }
- else
- {
- m_pos = pObj->RetPosition(0);
- m_terrain->MoveOnFloor(m_pos, true);
-
- type = pObj->RetType();
- if ( type == OBJECT_BASE )
- {
- m_pos.y += 120.0f; // top of the rocket
- }
- else if ( type == OBJECT_PARA )
- {
- automat = (CAutoPara*)pObj->RetAuto();
- if ( automat != 0 )
- {
- automat->StartBlitz();
- }
- m_pos.y += 67.0f; // top of lightning rod
- }
- else
- {
- pObj->ExploObject(EXPLO_BOUM, 1.0f);
- }
- }
-
- eye = m_engine->RetEyePt();
- dist = Math::Distance(m_pos, eye);
- deep = m_engine->RetDeepView();
-
- if ( dist < deep )
- {
- pos = eye+((m_pos-eye)*0.2f); // like so close!
- m_sound->Play(SOUND_BLITZ, pos);
-
- m_camera->StartOver(OE_BLITZ, m_pos, 1.0f);
-
- m_phase = BPH_BLITZ;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
- }
-
- if ( m_phase == BPH_BLITZ )
- {
- if ( m_progress < 1.0f )
- {
- max = 5.0f;
- for ( i=0 ; i<BLITZMAX ; 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 = BPH_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/(1.0f+Math::Rand()*m_delay);
- }
- }
-
- return true;
-}
-
-
-// Draw lightning.
-
-void CBlitz::Draw()
-{
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Vector corner[4], eye, n, p, p1, p2;
- Math::Matrix matrix;
- Math::Point texInf, texSup, rot;
- float a;
- int i;
-
- if ( !m_bBlitzExist ) return;
- if ( m_phase != BPH_BLITZ ) return;
-
- device = m_engine->RetD3DDevice();
- device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
-
- matrix.LoadIdentity();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- m_engine->SetTexture("effect00.tga");
- m_engine->SetState(D3DSTATETTb);
- texInf.x = 64.5f/256.0f;
- texInf.y = 33.0f/256.0f;
- texSup.x = 95.5f/256.0f;
- texSup.y = 34.0f/256.0f; // blank
-
- p1 = m_pos;
- eye = m_engine->RetEyePt();
- a = Math::RotateAngle(eye.x-p1.x, eye.z-p1.z);
- n = Normalize(p1-eye);
-
- for ( i=0 ; i<BLITZMAX-1 ; i++ )
- {
- p2 = p1;
- p2.y += 8.0f+0.2f*i;
-
- 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] = D3DVERTEX2(corner[1], n, texSup.x, texSup.y);
- vertex[1] = D3DVERTEX2(corner[0], n, texInf.x, texSup.y);
- vertex[2] = D3DVERTEX2(corner[3], n, texSup.x, texInf.y);
- vertex[3] = D3DVERTEX2(corner[2], n, texInf.x, texInf.y);
- }
- else
- {
- vertex[0] = D3DVERTEX2(corner[0], n, texSup.x, texSup.y);
- vertex[1] = D3DVERTEX2(corner[1], n, texInf.x, texSup.y);
- vertex[2] = D3DVERTEX2(corner[2], n, texSup.x, texInf.y);
- vertex[3] = D3DVERTEX2(corner[3], n, texInf.x, texInf.y);
- }
-
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-
- p1 = p2;
- }
-
- device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
-}
-
-
-// Triggers lightning.
-
-bool CBlitz::Create(float sleep, float delay, float magnetic)
-{
- m_bBlitzExist = true;
- if ( sleep < 1.0f ) sleep = 1.0f;
- m_sleep = sleep;
- m_delay = delay;
- m_magnetic = magnetic;
-
- m_phase = BPH_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/m_sleep;
-
- if ( m_terrain == 0 )
- {
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- }
-
- if ( m_camera == 0 )
- {
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- }
-
- if ( m_sound == 0 )
- {
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- }
-
- return false;
-}
-
-
-// Gives the status of lightning.
-
-bool CBlitz::GetStatus(float &sleep, float &delay, float &magnetic, float &progress)
-{
- if ( !m_bBlitzExist ) return false;
-
- sleep = m_sleep;
- delay = m_delay;
- magnetic = m_magnetic;
- progress = m_progress;
-
- return true;
-}
-
-// Specifies the status of lightning.
-
-bool CBlitz::SetStatus(float sleep, float delay, float magnetic, float progress)
-{
- m_bBlitzExist = true;
-
- m_sleep = sleep;
- m_delay = delay;
- m_magnetic = magnetic;
- m_progress = progress;
- m_phase = BPH_WAIT;
- m_speed = 1.0f/m_sleep;
-
- return true;
-}
-
-
-// Seeking the object closest to the lightning.
-
-CObject* CBlitz::SearchObject(Math::Vector pos)
-{
- CObject *pObj, *pBest, *pObjPara[100];
- Math::Vector oPos, pPos[100];
- ObjectType type;
- float min, dist, detect;
- int i, nbPara;
-
- // Seeking the object closest to the point of impact of lightning.
- pBest = 0;
- min = 100000.0f;
- nbPara = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // inactive object?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- type = pObj->RetType();
- if ( type == OBJECT_BASE ||
- type == OBJECT_PARA ) // building a lightning effect?
- {
- pObjPara[nbPara] = pObj;
- pPos[nbPara] = pObj->RetPosition(0);
- nbPara ++;
- }
-
- 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;
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, pos);
- if ( dist > detect ) continue;
- if ( dist < min )
- {
- min = dist;
- pBest = pObj;
- }
- }
- if ( pBest == 0 ) return 0; // nothing found
-
- // Under the protection of a lightning conductor?
- oPos = pBest->RetPosition(0);
- for ( i=nbPara-1 ; i>=0 ; i-- )
- {
- dist = Math::DistanceProjected(oPos, pPos[i]);
- if ( dist <= BLITZPARA )
- {
- return pObjPara[i];
- }
- }
- return pBest;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "math/conv.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "old/d3dutil.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/terrain.h"
+#include "old/math3d.h"
+#include "object/object.h"
+#include "old/camera.h"
+#include "object/auto/auto.h"
+#include "object/auto/autopara.h"
+#include "old/sound.h"
+#include "old/blitz.h"
+
+
+
+
+// Constructor of the terrain.
+
+CBlitz::CBlitz(CInstanceManager* iMan, CD3DEngine* engine)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_BLITZ, this);
+
+ m_engine = engine;
+ m_terrain = 0;
+ m_camera = 0;
+ m_sound = 0;
+ Flush();
+}
+
+// Destructor of the terrain.
+
+CBlitz::~CBlitz()
+{
+}
+
+
+// Removes lightning.
+
+void CBlitz::Flush()
+{
+ int i;
+
+ m_bBlitzExist = false;
+ m_time = 0.0f;
+ m_phase = BPH_WAIT;
+ m_speed = 0.0f;
+ m_progress = 0.0f;
+
+ for ( i=0 ; i<BLITZMAX ; i++ )
+ {
+ m_shift[i] = Math::Point(0.0f, 0.0f);
+ m_width[i] = 1.0f;
+ }
+}
+
+
+// Management of an event
+
+bool CBlitz::EventProcess(const Event &event)
+{
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+ return true;
+}
+
+// Evolved lightning.
+
+bool CBlitz::EventFrame(const Event &event)
+{
+ CObject* pObj;
+ CAutoPara* automat;
+ ObjectType type;
+ Math::Vector eye, pos;
+ float dist, deep, max;
+ int i;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( m_engine->RetMovieLock() ) return true;
+
+ m_time += event.rTime;
+ m_progress += event.rTime*m_speed;
+
+ if ( m_phase == BPH_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+#if 1
+ m_pos.x = (Math::Rand()-0.5f)*(3200.0f-200.0f);
+ m_pos.z = (Math::Rand()-0.5f)*(3200.0f-200.0f);
+#else
+ m_pos.x = (Math::Rand()-0.5f)*(3200.0f-2800.0f);
+ m_pos.z = (Math::Rand()-0.5f)*(3200.0f-2800.0f);
+#endif
+ m_pos.y = 0.0f;
+
+ pObj = SearchObject(m_pos);
+ if ( pObj == 0 )
+ {
+ m_terrain->MoveOnFloor(m_pos, true);
+ }
+ else
+ {
+ m_pos = pObj->RetPosition(0);
+ m_terrain->MoveOnFloor(m_pos, true);
+
+ type = pObj->RetType();
+ if ( type == OBJECT_BASE )
+ {
+ m_pos.y += 120.0f; // top of the rocket
+ }
+ else if ( type == OBJECT_PARA )
+ {
+ automat = (CAutoPara*)pObj->RetAuto();
+ if ( automat != 0 )
+ {
+ automat->StartBlitz();
+ }
+ m_pos.y += 67.0f; // top of lightning rod
+ }
+ else
+ {
+ pObj->ExploObject(EXPLO_BOUM, 1.0f);
+ }
+ }
+
+ eye = m_engine->RetEyePt();
+ dist = Math::Distance(m_pos, eye);
+ deep = m_engine->RetDeepView();
+
+ if ( dist < deep )
+ {
+ pos = eye+((m_pos-eye)*0.2f); // like so close!
+ m_sound->Play(SOUND_BLITZ, pos);
+
+ m_camera->StartOver(OE_BLITZ, m_pos, 1.0f);
+
+ m_phase = BPH_BLITZ;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+ }
+
+ if ( m_phase == BPH_BLITZ )
+ {
+ if ( m_progress < 1.0f )
+ {
+ max = 5.0f;
+ for ( i=0 ; i<BLITZMAX ; 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 = BPH_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/(1.0f+Math::Rand()*m_delay);
+ }
+ }
+
+ return true;
+}
+
+
+// Draw lightning.
+
+void CBlitz::Draw()
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Vector corner[4], eye, n, p, p1, p2;
+ Math::Matrix matrix;
+ Math::Point texInf, texSup, rot;
+ float a;
+ int i;
+
+ if ( !m_bBlitzExist ) return;
+ if ( m_phase != BPH_BLITZ ) return;
+
+ device = m_engine->RetD3DDevice();
+ device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+
+ matrix.LoadIdentity();
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ m_engine->SetTexture("effect00.tga");
+ m_engine->SetState(D3DSTATETTb);
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 33.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 34.0f/256.0f; // blank
+
+ p1 = m_pos;
+ eye = m_engine->RetEyePt();
+ a = Math::RotateAngle(eye.x-p1.x, eye.z-p1.z);
+ n = Normalize(p1-eye);
+
+ for ( i=0 ; i<BLITZMAX-1 ; i++ )
+ {
+ p2 = p1;
+ p2.y += 8.0f+0.2f*i;
+
+ 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] = D3DVERTEX2(corner[1], n, texSup.x, texSup.y);
+ vertex[1] = D3DVERTEX2(corner[0], n, texInf.x, texSup.y);
+ vertex[2] = D3DVERTEX2(corner[3], n, texSup.x, texInf.y);
+ vertex[3] = D3DVERTEX2(corner[2], n, texInf.x, texInf.y);
+ }
+ else
+ {
+ vertex[0] = D3DVERTEX2(corner[0], n, texSup.x, texSup.y);
+ vertex[1] = D3DVERTEX2(corner[1], n, texInf.x, texSup.y);
+ vertex[2] = D3DVERTEX2(corner[2], n, texSup.x, texInf.y);
+ vertex[3] = D3DVERTEX2(corner[3], n, texInf.x, texInf.y);
+ }
+
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+
+ p1 = p2;
+ }
+
+ device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
+}
+
+
+// Triggers lightning.
+
+bool CBlitz::Create(float sleep, float delay, float magnetic)
+{
+ m_bBlitzExist = true;
+ if ( sleep < 1.0f ) sleep = 1.0f;
+ m_sleep = sleep;
+ m_delay = delay;
+ m_magnetic = magnetic;
+
+ m_phase = BPH_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/m_sleep;
+
+ if ( m_terrain == 0 )
+ {
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ }
+
+ if ( m_camera == 0 )
+ {
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ }
+
+ if ( m_sound == 0 )
+ {
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ }
+
+ return false;
+}
+
+
+// Gives the status of lightning.
+
+bool CBlitz::GetStatus(float &sleep, float &delay, float &magnetic, float &progress)
+{
+ if ( !m_bBlitzExist ) return false;
+
+ sleep = m_sleep;
+ delay = m_delay;
+ magnetic = m_magnetic;
+ progress = m_progress;
+
+ return true;
+}
+
+// Specifies the status of lightning.
+
+bool CBlitz::SetStatus(float sleep, float delay, float magnetic, float progress)
+{
+ m_bBlitzExist = true;
+
+ m_sleep = sleep;
+ m_delay = delay;
+ m_magnetic = magnetic;
+ m_progress = progress;
+ m_phase = BPH_WAIT;
+ m_speed = 1.0f/m_sleep;
+
+ return true;
+}
+
+
+// Seeking the object closest to the lightning.
+
+CObject* CBlitz::SearchObject(Math::Vector pos)
+{
+ CObject *pObj, *pBest, *pObjPara[100];
+ Math::Vector oPos, pPos[100];
+ ObjectType type;
+ float min, dist, detect;
+ int i, nbPara;
+
+ // Seeking the object closest to the point of impact of lightning.
+ pBest = 0;
+ min = 100000.0f;
+ nbPara = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue; // inactive object?
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+
+ type = pObj->RetType();
+ if ( type == OBJECT_BASE ||
+ type == OBJECT_PARA ) // building a lightning effect?
+ {
+ pObjPara[nbPara] = pObj;
+ pPos[nbPara] = pObj->RetPosition(0);
+ nbPara ++;
+ }
+
+ 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;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, pos);
+ if ( dist > detect ) continue;
+ if ( dist < min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+ if ( pBest == 0 ) return 0; // nothing found
+
+ // Under the protection of a lightning conductor?
+ oPos = pBest->RetPosition(0);
+ for ( i=nbPara-1 ; i>=0 ; i-- )
+ {
+ dist = Math::DistanceProjected(oPos, pPos[i]);
+ if ( dist <= BLITZPARA )
+ {
+ return pObjPara[i];
+ }
+ }
+ return pBest;
+}
+
diff --git a/src/old/blitz.h b/src/old/blitz.h
index 87e9a76..8289576 100644
--- a/src/old/blitz.h
+++ b/src/old/blitz.h
@@ -1,83 +1,83 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// blitz.h
-
-#pragma once
-
-
-#include "common/misc.h"
-#include "math/point.h"
-#include "old/d3dengine.h"
-
-
-class CObject;
-class CInstanceManager;
-class CD3DEngine;
-class CTerrain;
-class CCamera;
-class CSound;
-
-
-
-const float BLITZPARA = 200.0f; // radius of lightning protection
-const int BLITZMAX = 50;
-
-enum BlitzPhase
-{
- BPH_WAIT,
- BPH_BLITZ,
-};
-
-
-
-class CBlitz
-{
-public:
- CBlitz(CInstanceManager* iMan, CD3DEngine* engine);
- ~CBlitz();
-
- void Flush();
- bool EventProcess(const Event &event);
- bool Create(float sleep, float delay, float magnetic);
- bool GetStatus(float &sleep, float &delay, float &magnetic, float &progress);
- bool SetStatus(float sleep, float delay, float magnetic, float progress);
- void Draw();
-
-protected:
- bool EventFrame(const Event &event);
- CObject* SearchObject(Math::Vector pos);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CTerrain* m_terrain;
- CCamera* m_camera;
- CSound* m_sound;
-
- bool m_bBlitzExist;
- 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];
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// blitz.h
+
+#pragma once
+
+
+#include "common/misc.h"
+#include "math/point.h"
+#include "old/d3dengine.h"
+
+
+class CObject;
+class CInstanceManager;
+class CD3DEngine;
+class CTerrain;
+class CCamera;
+class CSound;
+
+
+
+const float BLITZPARA = 200.0f; // radius of lightning protection
+const int BLITZMAX = 50;
+
+enum BlitzPhase
+{
+ BPH_WAIT,
+ BPH_BLITZ,
+};
+
+
+
+class CBlitz
+{
+public:
+ CBlitz(CInstanceManager* iMan, CD3DEngine* engine);
+ ~CBlitz();
+
+ void Flush();
+ bool EventProcess(const Event &event);
+ bool Create(float sleep, float delay, float magnetic);
+ bool GetStatus(float &sleep, float &delay, float &magnetic, float &progress);
+ bool SetStatus(float sleep, float delay, float magnetic, float progress);
+ void Draw();
+
+protected:
+ bool EventFrame(const Event &event);
+ CObject* SearchObject(Math::Vector pos);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CTerrain* m_terrain;
+ CCamera* m_camera;
+ CSound* m_sound;
+
+ bool m_bBlitzExist;
+ 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];
+};
+
diff --git a/src/old/camera.cpp b/src/old/camera.cpp
index 2c2ffef..cea9113 100644
--- a/src/old/camera.cpp
+++ b/src/old/camera.cpp
@@ -1,2109 +1,2109 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/language.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "object/object.h"
-#include "physics/physics.h"
-#include "old/camera.h"
-
-
-
-
-// Object's constructor.
-
-CCamera::CCamera(CInstanceManager* iMan)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_CAMERA, this);
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
-
- m_type = CAMERA_FREE;
- m_smooth = CS_NORM;
- m_cameraObj = 0;
-
- m_eyeDistance = 10.0f;
- m_initDelay = 0.0f;
-
- m_actualEye = Math::Vector(0.0f, 0.0f, 0.0f);
- m_actualLookat = Math::Vector(0.0f, 0.0f, 0.0f);
- m_finalEye = Math::Vector(0.0f, 0.0f, 0.0f);
- m_finalLookat = Math::Vector(0.0f, 0.0f, 0.0f);
- m_normEye = Math::Vector(0.0f, 0.0f, 0.0f);
- m_normLookat = Math::Vector(0.0f, 0.0f, 0.0f);
- m_focus = 1.0f;
-
- m_bRightDown = false;
- m_rightPosInit = Math::Point(0.5f, 0.5f);
- m_rightPosCenter = Math::Point(0.5f, 0.5f);
- m_rightPosMove = Math::Point(0.5f, 0.5f);
-
- m_eyePt = Math::Vector(0.0f, 0.0f, 0.0f);
- m_directionH = 0.0f;
- m_directionV = 0.0f;
- m_heightEye = 20.0f;
- m_heightLookat = 0.0f;
- m_speed = 2.0f;
-
- m_backDist = 0.0f;
- m_backMin = 0.0f;
- m_addDirectionH = 0.0f;
- m_addDirectionV = 0.0f;
- m_bTransparency = false;
-
- m_fixDist = 0.0f;
- m_fixDirectionH = 0.0f;
- m_fixDirectionV = 0.0f;
-
- m_visitGoal = Math::Vector(0.0f, 0.0f, 0.0f);
- m_visitDist = 0.0f;
- m_visitTime = 0.0f;
- m_visitType = CAMERA_NULL;
- m_visitDirectionH = 0.0f;
- m_visitDirectionV = 0.0f;
-
- m_editHeight = 40.0f;
-
- m_remotePan = 0.0f;
- m_remoteZoom = 0.0f;
-
- m_mouseDirH = 0.0f;
- m_mouseDirV = 0.0f;
- m_mouseMarging = 0.01f;
-
- m_motorTurn = 0.0f;
-
- m_centeringPhase = CP_NULL;
- m_centeringAngleH = 0.0f;
- m_centeringAngleV = 0.0f;
- m_centeringDist = 0.0f;
- m_centeringCurrentH = 0.0f;
- m_centeringCurrentV = 0.0f;
- m_centeringTime = 0.0f;
- m_centeringProgress = 0.0f;
-
- m_effectType = CE_NULL;
- m_effectPos = Math::Vector(0.0f, 0.0f, 0.0f);
- m_effectForce = 0.0f;
- m_effectProgress = 0.0f;
- m_effectOffset = Math::Vector(0.0f, 0.0f, 0.0f);
-
- m_scriptEye = Math::Vector(0.0f, 0.0f, 0.0f);
- m_scriptLookat = Math::Vector(0.0f, 0.0f, 0.0f);
-
- m_bEffect = true;
- m_bCameraScroll = true;
- m_bCameraInvertX = false;
- m_bCameraInvertY = false;
-}
-
-// Object's constructor.
-
-CCamera::~CCamera()
-{
-}
-
-
-void CCamera::SetEffect(bool bEnable)
-{
- m_bEffect = bEnable;
-}
-
-void CCamera::SetCameraScroll(bool bScroll)
-{
- m_bCameraScroll = bScroll;
-}
-
-void CCamera::SetCameraInvertX(bool bInvert)
-{
- m_bCameraInvertX = bInvert;
-}
-
-void CCamera::SetCameraInvertY(bool bInvert)
-{
- m_bCameraInvertY = bInvert;
-}
-
-
-// Returns an additional force to turn.
-
-float CCamera::RetMotorTurn()
-{
- if ( m_type == CAMERA_BACK ) return m_motorTurn;
- return 0.0f;
-}
-
-
-
-// Initializes the camera.
-
-void CCamera::Init(Math::Vector eye, Math::Vector lookat, float delay)
-{
- Math::Vector vUpVec;
-
- m_initDelay = delay;
-
- eye.y += m_terrain->RetFloorLevel(eye, true);
- lookat.y += m_terrain->RetFloorLevel(lookat, true);
-
- m_type = CAMERA_FREE;
- m_eyePt = eye;
-
- m_directionH = Math::RotateAngle(eye.x-lookat.x, eye.z-lookat.z)+Math::PI/2.0f;
- m_directionV = -Math::RotateAngle(Math::DistanceProjected(eye, lookat), eye.y-lookat.y);
-
- m_eyeDistance = 10.0f;
- m_heightLookat = 10.0f;
- m_backDist = 30.0f;
- m_backMin = 10.0f;
- m_addDirectionH = 0.0f;
- m_addDirectionV = -Math::PI*0.05f;
- m_fixDist = 50.0f;
- m_fixDirectionH = Math::PI*0.25f;
- m_fixDirectionV = -Math::PI*0.10f;
- m_centeringPhase = CP_NULL;
- m_actualEye = m_eyePt;
- m_actualLookat = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, 50.0f);
- m_finalEye = m_actualEye;
- m_finalLookat = m_actualLookat;
- m_scriptEye = m_actualEye;
- m_scriptLookat = m_actualLookat;
- m_focus = 1.00f;
- m_remotePan = 0.0f;
- m_remoteZoom = 0.0f;
-
- FlushEffect();
- FlushOver();
- SetType(CAMERA_FREE);
-}
-
-
-// Gives the object controlling the camera.
-
-void CCamera::SetObject(CObject* object)
-{
- m_cameraObj = object;
-}
-
-CObject* CCamera::RetObject()
-{
- return m_cameraObj;
-}
-
-
-// Changes the level of transparency of an object and objects
-// transported (battery & cargo).
-
-void SetTransparency(CObject* pObj, float value)
-{
- CObject* pFret;
-
- pObj->SetTransparency(value);
-
- pFret = pObj->RetFret();
- if ( pFret != 0 )
- {
- pFret->SetTransparency(value);
- }
-
- pFret = pObj->RetPower();
- if ( pFret != 0 )
- {
- pFret->SetTransparency(value);
- }
-}
-
-// Change the type of camera.
-
-void CCamera::SetType(CameraType type)
-{
- CObject* pObj;
- ObjectType oType;
- Math::Vector vUpVec;
- int i;
-
- m_remotePan = 0.0f;
- m_remoteZoom = 0.0f;
-
- if ( m_type == CAMERA_BACK && m_bTransparency )
- {
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetTruck() ) continue; // battery or cargo?
-
- SetTransparency(pObj, 0.0f); // opaque object
- }
- }
- m_bTransparency = false;
-
- if ( type == CAMERA_INFO ||
- type == CAMERA_VISIT ) // xx -> info ?
- {
- m_normEye = m_engine->RetEyePt();
- m_normLookat = m_engine->RetLookatPt();
-
- m_engine->SetFocus(1.00f); // normal
- m_type = type;
- return;
- }
-
- if ( m_type == CAMERA_INFO ||
- m_type == CAMERA_VISIT ) // info -> xx ?
- {
- m_engine->SetFocus(m_focus); // gives initial focus
- m_type = type;
-
- vUpVec = Math::Vector(0.0f, 1.0f, 0.0f);
- SetViewParams(m_normEye, m_normLookat, vUpVec);
- return;
- }
-
- if ( m_type == CAMERA_BACK && type == CAMERA_FREE ) // back -> free ?
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -50.0f);
- }
-
- if ( m_type == CAMERA_BACK && type == CAMERA_EDIT ) // back -> edit ?
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -1.0f);
- }
-
- if ( m_type == CAMERA_ONBOARD && type == CAMERA_FREE ) // onboard -> free ?
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -30.0f);
- }
-
- if ( m_type == CAMERA_ONBOARD && type == CAMERA_EDIT ) // onboard -> edit ?
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -30.0f);
- }
-
- if ( m_type == CAMERA_ONBOARD && type == CAMERA_EXPLO ) // onboard -> explo ?
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -50.0f);
- }
-
- if ( m_type == CAMERA_BACK && type == CAMERA_EXPLO ) // back -> explo ?
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -20.0f);
- }
-
- if ( type == CAMERA_FIX ||
- type == CAMERA_PLANE )
- {
- AbortCentering(); // Special stops framing
- }
-
- m_fixDist = 50.0f;
- if ( type == CAMERA_PLANE )
- {
- m_fixDist = 60.0f;
- }
-
- if ( type == CAMERA_BACK )
- {
- AbortCentering(); // Special stops framing
- m_addDirectionH = 0.0f;
- m_addDirectionV = -Math::PI*0.05f;
-
- if ( m_cameraObj == 0 ) oType = OBJECT_NULL;
- else oType = m_cameraObj->RetType();
-
- m_backDist = 30.0f;
- if ( oType == OBJECT_BASE ) m_backDist = 200.0f;
- if ( oType == OBJECT_HUMAN ) m_backDist = 20.0f;
- if ( oType == OBJECT_TECH ) m_backDist = 20.0f;
- if ( oType == OBJECT_FACTORY ) m_backDist = 50.0f;
- if ( oType == OBJECT_RESEARCH ) m_backDist = 40.0f;
- if ( oType == OBJECT_DERRICK ) m_backDist = 40.0f;
- if ( oType == OBJECT_REPAIR ) m_backDist = 35.0f;
- if ( oType == OBJECT_DESTROYER) m_backDist = 35.0f;
- if ( oType == OBJECT_TOWER ) m_backDist = 45.0f;
- if ( oType == OBJECT_NUCLEAR ) m_backDist = 70.0f;
- if ( oType == OBJECT_PARA ) m_backDist = 180.0f;
- if ( oType == OBJECT_SAFE ) m_backDist = 50.0f;
- if ( oType == OBJECT_HUSTON ) m_backDist = 120.0f;
-
- m_backMin = m_backDist/3.0f;
- if ( oType == OBJECT_HUMAN ) m_backMin = 10.0f;
- if ( oType == OBJECT_TECH ) m_backMin = 10.0f;
- if ( oType == OBJECT_FACTORY ) m_backMin = 30.0f;
- if ( oType == OBJECT_RESEARCH ) m_backMin = 20.0f;
- if ( oType == OBJECT_NUCLEAR ) m_backMin = 32.0f;
- if ( oType == OBJECT_PARA ) m_backMin = 40.0f;
- if ( oType == OBJECT_SAFE ) m_backMin = 25.0f;
- if ( oType == OBJECT_HUSTON ) m_backMin = 80.0f;
- }
-
- if ( type != CAMERA_ONBOARD && m_cameraObj != 0 )
- {
- m_cameraObj->SetGunGoalH(0.0f); // puts the cannon right
- }
-
- if ( type == CAMERA_ONBOARD )
- {
- m_focus = 1.50f; // Wide
- }
- else
- {
- m_focus = 1.00f; // normal
- }
- m_engine->SetFocus(m_focus);
-
- m_type = type;
-
- SetSmooth(CS_NORM);
-}
-
-CameraType CCamera::RetType()
-{
- return m_type;
-}
-
-
-// Management of the smoothing mode.
-
-void CCamera::SetSmooth(CameraSmooth type)
-{
- m_smooth = type;
-}
-
-CameraSmooth CCamera::RetSmoth()
-{
- return m_smooth;
-}
-
-
-// Management of the setback distance.
-
-void CCamera::SetDist(float dist)
-{
- m_fixDist = dist;
-}
-
-float CCamera::RetDist()
-{
- return m_fixDist;
-}
-
-
-// Manage angle mode CAMERA_FIX.
-
-void CCamera::SetFixDirection(float angle)
-{
- m_fixDirectionH = angle;
-}
-
-float CCamera::RetFixDirection()
-{
- return m_fixDirectionH;
-}
-
-
-// Managing the triggering mode of the camera panning.
-
-void CCamera::SetRemotePan(float value)
-{
- m_remotePan = value;
-}
-
-float CCamera::RetRemotePan()
-{
- return m_remotePan;
-}
-
-// Management of the remote zoom (0 .. 1) of the camera.
-
-void CCamera::SetRemoteZoom(float value)
-{
- value = Math::Norm(value);
-
- if ( m_type == CAMERA_BACK )
- {
- m_backDist = m_backMin+(200.0f-m_backMin)*value;
- }
-
- if ( m_type == CAMERA_FIX ||
- m_type == CAMERA_PLANE )
- {
- m_fixDist = 10.0f+(200.0f-10.0f)*value;
- }
-}
-
-float CCamera::RetRemoteZoom()
-{
- if ( m_type == CAMERA_BACK )
- {
- return (m_backDist-m_backMin)/(200.0f-m_backMin);
- }
-
- if ( m_type == CAMERA_FIX ||
- m_type == CAMERA_PLANE )
- {
- return (m_fixDist-10.0f)/(200.0f-10.0f);
- }
- return 0.0f;
-}
-
-
-
-// Start with a tour round the camera.
-
-void CCamera::StartVisit(Math::Vector goal, float dist)
-{
- m_visitType = m_type;
- SetType(CAMERA_VISIT);
- m_visitGoal = goal;
- m_visitDist = dist;
- m_visitTime = 0.0f;
- m_visitDirectionH = 0.0f;
- m_visitDirectionV = -Math::PI*0.10f;
-}
-
-// Circular end of a visit with the camera.
-
-void CCamera::StopVisit()
-{
- SetType(m_visitType); // presents the initial type
-}
-
-
-// Returns the point of view of the camera.
-
-void CCamera::RetCamera(Math::Vector &eye, Math::Vector &lookat)
-{
- eye = m_eyePt;
- lookat = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, 50.0f);
-}
-
-
-// Specifies a special movement of camera to frame action.
-
-bool CCamera::StartCentering(CObject *object, float angleH, float angleV,
- float dist, float time)
-{
- if ( m_type != CAMERA_BACK ) return false;
- if ( object != m_cameraObj ) return false;
-
- if ( m_centeringPhase != CP_NULL ) return false;
-
- if ( m_addDirectionH > Math::PI )
- {
- angleH = Math::PI*2.0f-angleH;
- }
-
- m_centeringPhase = CP_START;
- m_centeringAngleH = angleH;
- m_centeringAngleV = angleV;
- m_centeringDist = dist;
- m_centeringCurrentH = 0.0f;
- m_centeringCurrentV = 0.0f;
- m_centeringTime = time;
- m_centeringProgress = 0.0f;
-
- return true;
-}
-
-// Ends a special movement of camera to frame action.
-
-bool CCamera::StopCentering(CObject *object, float time)
-{
- if ( m_type != CAMERA_BACK ) return false;
- if ( object != m_cameraObj ) return false;
-
- if ( m_centeringPhase != CP_START &&
- m_centeringPhase != CP_WAIT ) return false;
-
- m_centeringPhase = CP_STOP;
-
- if ( m_centeringAngleH != 99.9f )
- {
- m_centeringAngleH = m_centeringCurrentH;
- }
- if ( m_centeringAngleV != 99.9f )
- {
- m_centeringAngleV = m_centeringCurrentV;
- }
-
- m_centeringTime = time;
- m_centeringProgress = 0.0f;
-
- return true;
-}
-
-// Stop framing special in the current position.
-
-void CCamera::AbortCentering()
-{
- if ( m_type == CAMERA_INFO ||
- m_type == CAMERA_VISIT ) return;
-
- if ( m_centeringPhase == CP_NULL ) return;
-
- m_centeringPhase = CP_NULL;
-
- if ( m_centeringAngleH != 99.9f )
- {
- m_addDirectionH = m_centeringCurrentH;
- }
- if ( m_centeringAngleV != 99.9f )
- {
- m_addDirectionV = m_centeringCurrentV;
- }
-}
-
-
-
-// Removes the special effect with the camera
-
-void CCamera::FlushEffect()
-{
- m_effectType = CE_NULL;
- m_effectForce = 0.0f;
- m_effectProgress = 0.0f;
- m_effectOffset = Math::Vector(0.0f, 0.0f, 0.0f);
-}
-
-// Starts a special effect with the camera.
-
-void CCamera::StartEffect(CameraEffect effect, Math::Vector pos, float force)
-{
- if ( !m_bEffect ) return;
-
- m_effectType = effect;
- m_effectPos = pos;
- m_effectForce = force;
- m_effectProgress = 0.0f;
-}
-
-// Advances the effect of the camera.
-
-void CCamera::EffectFrame(const Event &event)
-{
- float dist, force;
-
- if ( m_type == CAMERA_INFO ||
- m_type == CAMERA_VISIT ) return;
-
- if ( m_effectType == CE_NULL ) return;
-
- m_effectOffset = Math::Vector(0.0f, 0.0f, 0.0f);
- force = m_effectForce;
-
- if ( m_effectType == CE_TERRAFORM )
- {
- m_effectProgress += event.rTime*0.7f;
- m_effectOffset.x = (Math::Rand()-0.5f)*10.0f;
- m_effectOffset.y = (Math::Rand()-0.5f)*10.0f;
- m_effectOffset.z = (Math::Rand()-0.5f)*10.0f;
-
- force *= 1.0f-m_effectProgress;
- }
-
- if ( m_effectType == CE_EXPLO )
- {
- m_effectProgress += event.rTime*1.0f;
- m_effectOffset.x = (Math::Rand()-0.5f)*5.0f;
- m_effectOffset.y = (Math::Rand()-0.5f)*5.0f;
- m_effectOffset.z = (Math::Rand()-0.5f)*5.0f;
-
- force *= 1.0f-m_effectProgress;
- }
-
- if ( m_effectType == CE_SHOT )
- {
- m_effectProgress += event.rTime*1.0f;
- m_effectOffset.x = (Math::Rand()-0.5f)*2.0f;
- m_effectOffset.y = (Math::Rand()-0.5f)*2.0f;
- m_effectOffset.z = (Math::Rand()-0.5f)*2.0f;
-
- force *= 1.0f-m_effectProgress;
- }
-
- if ( m_effectType == CE_CRASH )
- {
- m_effectProgress += event.rTime*5.0f;
- m_effectOffset.y = sinf(m_effectProgress*Math::PI)*1.5f;
- m_effectOffset.x = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
- m_effectOffset.z = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
- }
-
- if ( m_effectType == CE_VIBRATION )
- {
- m_effectProgress += event.rTime*0.1f;
- m_effectOffset.y = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
- m_effectOffset.x = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
- m_effectOffset.z = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
- }
-
- if ( m_effectType == CE_PET )
- {
- m_effectProgress += event.rTime*5.0f;
- m_effectOffset.x = (Math::Rand()-0.5f)*0.2f;
- m_effectOffset.y = (Math::Rand()-0.5f)*2.0f;
- m_effectOffset.z = (Math::Rand()-0.5f)*0.2f;
- }
-
- dist = Math::Distance(m_eyePt, m_effectPos);
- dist = Math::Norm((dist-100.f)/100.0f);
-
- force *= 1.0f-dist;
-#if _TEEN
- force *= 2.0f;
-#endif
- m_effectOffset *= force;
-
- if ( m_effectProgress >= 1.0f )
- {
- FlushEffect();
- }
-}
-
-
-// Removes the effect of superposition in the foreground.
-
-void CCamera::FlushOver()
-{
- m_overType = OE_NULL;
- m_overColorBase.r = 0.0f; // black
- m_overColorBase.g = 0.0f;
- m_overColorBase.b = 0.0f;
- m_overColorBase.a = 0.0f;
- m_engine->SetOverColor(); // nothing
-}
-
-// Specifies the base color.
-
-void CCamera::SetOverBaseColor(D3DCOLORVALUE color)
-{
- m_overColorBase = color;
-}
-
-// Starts a layering effect in the foreground.
-
-void CCamera::StartOver(OverEffect effect, Math::Vector pos, float force)
-{
- D3DCOLOR color;
- float dist, decay;
-
- m_overType = effect;
- m_overTime = 0.0f;
-
- if ( m_overType == OE_BLITZ ) decay = 400.0f;
- else decay = 100.0f;
- dist = Math::Distance(m_eyePt, pos);
- dist = (dist-decay)/decay;
- if ( dist < 0.0f ) dist = 0.0f;
- if ( dist > 1.0f ) dist = 1.0f;
-
- m_overForce = force * (1.0f-dist);
-
- if ( m_overType == OE_BLOOD )
- {
- m_overColor.r = 0.8f;
- m_overColor.g = 0.1f;
- m_overColor.b = 0.1f; // red
- m_overMode = D3DSTATETCb;
-
- m_overFadeIn = 0.4f;
- m_overFadeOut = 0.8f;
- m_overForce = 1.0f;
- }
-
- if ( m_overType == OE_FADEINw )
- {
- m_overColor.r = 1.0f;
- m_overColor.g = 1.0f;
- m_overColor.b = 1.0f; // white
- m_overMode = D3DSTATETCb;
-
- m_overFadeIn = 0.0f;
- m_overFadeOut =20.0f;
- m_overForce = 1.0f;
- }
-
- if ( m_overType == OE_FADEOUTw )
- {
- m_overColor.r = 1.0f;
- m_overColor.g = 1.0f;
- m_overColor.b = 1.0f; // white
- m_overMode = D3DSTATETCb;
-
- m_overFadeIn = 6.0f;
- m_overFadeOut = 100000.0f;
- m_overForce = 1.0f;
- }
-
- if ( m_overType == OE_FADEOUTb )
- {
- color = m_engine->RetFogColor(1); // fog color underwater
- m_overColor = RetColor(color);
- m_overMode = D3DSTATETCw;
-
- m_overFadeIn = 4.0f;
- m_overFadeOut = 100000.0f;
- m_overForce = 1.0f;
- }
-
- if ( m_overType == OE_BLITZ )
- {
- m_overColor.r = 0.9f;
- m_overColor.g = 1.0f;
- m_overColor.b = 1.0f; // white-cyan
- m_overMode = D3DSTATETCb;
-
- m_overFadeIn = 0.0f;
- m_overFadeOut = 1.0f;
- }
-}
-
-// Advanced overlay effect in the foreground.
-
-void CCamera::OverFrame(const Event &event)
-{
- D3DCOLORVALUE color;
- float intensity;
-
- if ( m_type == CAMERA_INFO ||
- m_type == CAMERA_VISIT ) return;
-
- if ( m_overType == OE_NULL )
- {
- return;
- }
-
- m_overTime += event.rTime;
-
- if ( m_overType == OE_BLITZ )
- {
- if ( rand()%2 == 0 )
- {
- color.r = m_overColor.r*m_overForce;
- color.g = m_overColor.g*m_overForce;
- color.b = m_overColor.b*m_overForce;
- }
- else
- {
- color.r = 0.0f;
- color.g = 0.0f;
- color.b = 0.0f;
- }
- color.a = 0.0f;
- m_engine->SetOverColor(RetColor(color), m_overMode);
- }
- else
- {
- if ( m_overFadeIn > 0.0f && m_overTime < m_overFadeIn )
- {
- intensity = m_overTime/m_overFadeIn;
- intensity *= m_overForce;
-
- if ( m_overMode == D3DSTATETCw )
- {
- color.r = 1.0f-(1.0f-m_overColor.r)*intensity;
- color.g = 1.0f-(1.0f-m_overColor.g)*intensity;
- color.b = 1.0f-(1.0f-m_overColor.b)*intensity;
- }
- else
- {
- color.r = m_overColor.r*intensity;
- color.g = m_overColor.g*intensity;
- color.b = m_overColor.b*intensity;
-
- color.r = 1.0f-(1.0f-color.r)*(1.0f-m_overColorBase.r);
- color.g = 1.0f-(1.0f-color.g)*(1.0f-m_overColorBase.g);
- color.b = 1.0f-(1.0f-color.b)*(1.0f-m_overColorBase.b);
- }
- color.a = 0.0f;
- m_engine->SetOverColor(RetColor(color), m_overMode);
- }
- else if ( m_overFadeOut > 0.0f && m_overTime-m_overFadeIn < m_overFadeOut )
- {
- intensity = 1.0f-(m_overTime-m_overFadeIn)/m_overFadeOut;
- intensity *= m_overForce;
-
- if ( m_overMode == D3DSTATETCw )
- {
- color.r = 1.0f-(1.0f-m_overColor.r)*intensity;
- color.g = 1.0f-(1.0f-m_overColor.g)*intensity;
- color.b = 1.0f-(1.0f-m_overColor.b)*intensity;
- }
- else
- {
- color.r = m_overColor.r*intensity;
- color.g = m_overColor.g*intensity;
- color.b = m_overColor.b*intensity;
-
- color.r = 1.0f-(1.0f-color.r)*(1.0f-m_overColorBase.r);
- color.g = 1.0f-(1.0f-color.g)*(1.0f-m_overColorBase.g);
- color.b = 1.0f-(1.0f-color.b)*(1.0f-m_overColorBase.b);
- }
- color.a = 0.0f;
- m_engine->SetOverColor(RetColor(color), m_overMode);
- }
- }
-
- if ( m_overTime >= m_overFadeIn+m_overFadeOut )
- {
- FlushOver();
- return;
- }
-}
-
-
-
-// Sets the soft movement of the camera.
-
-void CCamera::FixCamera()
-{
- m_initDelay = 0.0f;
- m_actualEye = m_finalEye = m_scriptEye;
- m_actualLookat = m_finalLookat = m_scriptLookat;
- SetViewTime(m_scriptEye, m_scriptLookat, 0.0f);
-}
-
-// Specifies the location and direction of view to the 3D engine.
-
-void CCamera::SetViewTime(const Math::Vector &vEyePt,
- const Math::Vector &vLookatPt,
- float rTime)
-{
- Math::Vector vUpVec, eye, lookat;
- float prog, dist, h;
-
- if ( m_type == CAMERA_INFO )
- {
- eye = vEyePt;
- lookat = vLookatPt;
- }
- else
- {
- if ( m_initDelay > 0.0f )
- {
- m_initDelay -= rTime;
- if ( m_initDelay < 0.0f ) m_initDelay = 0.0f;
- rTime /= 1.0f+m_initDelay;
- }
-
- eye = vEyePt;
- lookat = vLookatPt;
- if ( !IsCollision(eye, lookat) )
- {
- m_finalEye = eye;
- m_finalLookat = lookat;
- }
-
- dist = Math::Distance(m_finalEye, m_actualEye);
- if ( m_smooth == CS_NONE ) prog = dist;
- if ( m_smooth == CS_NORM ) prog = powf(dist, 1.5f)*rTime*0.5f;
- if ( m_smooth == CS_HARD ) prog = powf(dist, 1.0f)*rTime*4.0f;
- if ( m_smooth == CS_SPEC ) prog = powf(dist, 1.0f)*rTime*0.05f;
- if ( dist == 0.0f )
- {
- m_actualEye = m_finalEye;
- }
- else
- {
- if ( prog > dist ) prog = dist;
- m_actualEye = (m_finalEye-m_actualEye)/dist*prog + m_actualEye;
- }
-
- dist = Math::Distance(m_finalLookat, m_actualLookat);
- if ( m_smooth == CS_NONE ) prog = dist;
- if ( m_smooth == CS_NORM ) prog = powf(dist, 1.5f)*rTime*2.0f;
- if ( m_smooth == CS_HARD ) prog = powf(dist, 1.0f)*rTime*4.0f;
- if ( m_smooth == CS_SPEC ) prog = powf(dist, 1.0f)*rTime*4.0f;
- if ( dist == 0.0f )
- {
- m_actualLookat = m_finalLookat;
- }
- else
- {
- if ( prog > dist ) prog = dist;
- m_actualLookat = (m_finalLookat-m_actualLookat)/dist*prog + m_actualLookat;
- }
-
- eye = m_effectOffset+m_actualEye;
- m_water->AdjustEye(eye);
-
- h = m_terrain->RetFloorLevel(eye);
- if ( eye.y < h+4.0f )
- {
- eye.y = h+4.0f;
- }
-
- lookat = m_effectOffset+m_actualLookat;
- }
-
- vUpVec = Math::Vector(0.0f, 1.0f, 0.0f);
- SetViewParams(eye, lookat, vUpVec);
-}
-
-
-// Avoid the obstacles.
-
-bool CCamera::IsCollision(Math::Vector &eye, Math::Vector lookat)
-{
- if ( m_type == CAMERA_BACK ) return IsCollisionBack(eye, lookat);
- if ( m_type == CAMERA_FIX ) return IsCollisionFix(eye, lookat);
- if ( m_type == CAMERA_PLANE ) return IsCollisionFix(eye, lookat);
- return false;
-}
-
-// Avoid the obstacles.
-
-bool CCamera::IsCollisionBack(Math::Vector &eye, Math::Vector lookat)
-{
-#if 0
- CObject *pObj;
- Math::Vector oPos, min, max, proj;
- ObjectType oType, iType;
- float oRadius, dpp, dpl, del, dist, len, prox;
- int i;
-
- if ( m_cameraObj == 0 )
- {
- iType = OBJECT_NULL;
- }
- else
- {
- iType = m_cameraObj->RetType();
- }
-
- min.x = Math::Min(eye.x, lookat.x);
- min.y = Math::Min(eye.y, lookat.y);
- min.z = Math::Min(eye.z, lookat.z);
-
- max.x = Math::Max(eye.x, lookat.x);
- max.y = Math::Max(eye.y, lookat.y);
- max.z = Math::Max(eye.z, lookat.z);
-
- prox = 8.0f; // maximum proximity of the vehicle
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_cameraObj ) continue;
-
- oType = pObj->RetType();
- if ( oType == OBJECT_TOTO ||
- oType == OBJECT_FIX ||
- oType == OBJECT_FRET ||
- oType == OBJECT_STONE ||
- oType == OBJECT_URANIUM ||
- oType == OBJECT_METAL ||
- oType == OBJECT_POWER ||
- oType == OBJECT_ATOMIC ||
- oType == OBJECT_BULLET ||
- oType == OBJECT_BBOX ||
- oType == OBJECT_TNT ||
- oType == OBJECT_BOMB ||
- oType == OBJECT_WAYPOINTb ||
- oType == OBJECT_WAYPOINTr ||
- oType == OBJECT_WAYPOINTg ||
- oType == OBJECT_WAYPOINTy ||
- oType == OBJECT_WAYPOINTv ||
- oType == OBJECT_FLAGb ||
- oType == OBJECT_FLAGr ||
- oType == OBJECT_FLAGg ||
- oType == OBJECT_FLAGy ||
- oType == OBJECT_FLAGv ||
- oType == OBJECT_ANT ||
- oType == OBJECT_SPIDER ||
- oType == OBJECT_BEE ||
- oType == OBJECT_WORM ) continue;
-
- pObj->GetGlobalSphere(oPos, oRadius);
- if ( oRadius <= 0.0f ) continue;
-
- if ( oPos.x+oRadius < min.x ||
- oPos.y+oRadius < min.y ||
- oPos.z+oRadius < min.z ||
- oPos.x-oRadius > max.x ||
- oPos.y-oRadius > max.y ||
- oPos.z-oRadius > max.z ) continue;
-
- if ( iType == OBJECT_FACTORY )
- {
- dpl = Math::Distance(oPos, lookat);
- if ( dpl < oRadius ) continue;
- }
-
- proj = Projection(eye, lookat, oPos);
- dpp = Math::Distance(proj, oPos);
- if ( dpp > oRadius ) continue;
-
- del = Math::Distance(eye, lookat);
- len = Math::Distance(eye, proj);
- if ( len > del ) continue;
-
- dist = sqrtf(oRadius*oRadius + dpp*dpp)-3.0f;
- if ( dist < 0.0f ) dist = 0.0f;
- proj = (lookat-eye)*dist/del + proj;
- len = Math::Distance(eye, proj);
-
- if ( len < del-prox )
- {
- eye = proj;
- eye.y += len/5.0f;
- return false;
- }
- else
- {
- eye = (eye-lookat)*prox/del + lookat;
- eye.y += (del-prox)/5.0f;
- return false;
- }
- }
- return false;
-#else
- CObject *pObj;
- Math::Vector oPos, min, max, proj;
- ObjectType oType, iType;
- float oRadius, dpp, del, len, angle;
- int i;
-
- if ( m_cameraObj == 0 )
- {
- iType = OBJECT_NULL;
- }
- else
- {
- iType = m_cameraObj->RetType();
- }
-
- min.x = Math::Min(m_actualEye.x, m_actualLookat.x);
- min.y = Math::Min(m_actualEye.y, m_actualLookat.y);
- min.z = Math::Min(m_actualEye.z, m_actualLookat.z);
-
- max.x = Math::Max(m_actualEye.x, m_actualLookat.x);
- max.y = Math::Max(m_actualEye.y, m_actualLookat.y);
- max.z = Math::Max(m_actualEye.z, m_actualLookat.z);
-
- m_bTransparency = false;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetTruck() ) continue; // battery or cargo?
-
- SetTransparency(pObj, 0.0f); // opaque object
-
- if ( pObj == m_cameraObj ) continue;
-
- if ( iType == OBJECT_BASE || // building?
- iType == OBJECT_DERRICK ||
- iType == OBJECT_FACTORY ||
- iType == OBJECT_STATION ||
- iType == OBJECT_CONVERT ||
- iType == OBJECT_REPAIR ||
- iType == OBJECT_DESTROYER||
- iType == OBJECT_TOWER ||
- iType == OBJECT_RESEARCH ||
- iType == OBJECT_RADAR ||
- iType == OBJECT_ENERGY ||
- iType == OBJECT_LABO ||
- iType == OBJECT_NUCLEAR ||
- iType == OBJECT_PARA ||
- iType == OBJECT_SAFE ||
- iType == OBJECT_HUSTON ) continue;
-
- oType = pObj->RetType();
- if ( oType == OBJECT_HUMAN ||
- oType == OBJECT_TECH ||
- oType == OBJECT_TOTO ||
- oType == OBJECT_FIX ||
- oType == OBJECT_FRET ||
- oType == OBJECT_ANT ||
- oType == OBJECT_SPIDER ||
- oType == OBJECT_BEE ||
- oType == OBJECT_WORM ) continue;
-
- pObj->GetGlobalSphere(oPos, oRadius);
- if ( oRadius <= 2.0f ) continue; // ignores small objects
-
- if ( oPos.x+oRadius < min.x ||
- oPos.y+oRadius < min.y ||
- oPos.z+oRadius < min.z ||
- oPos.x-oRadius > max.x ||
- oPos.y-oRadius > max.y ||
- oPos.z-oRadius > max.z ) continue;
-
- proj = Projection(m_actualEye, m_actualLookat, oPos);
- dpp = Math::Distance(proj, oPos);
- if ( dpp > oRadius ) continue;
-
- if ( oType == OBJECT_FACTORY )
- {
- angle = Math::RotateAngle(m_actualEye.x-oPos.x, oPos.z-m_actualEye.z); // CW !
- angle = Math::Direction(angle, pObj->RetAngleY(0));
- if ( fabs(angle) < 30.0f*Math::PI/180.0f ) continue; // in the gate?
- }
-
- del = Math::Distance(m_actualEye, m_actualLookat);
- if ( oType == OBJECT_FACTORY )
- {
- del += oRadius;
- }
-
- len = Math::Distance(m_actualEye, proj);
- if ( len > del ) continue;
-
- SetTransparency(pObj, 1.0f); // transparent object
- m_bTransparency = true;
- }
- return false;
-#endif
-}
-
-// Avoid the obstacles.
-
-bool CCamera::IsCollisionFix(Math::Vector &eye, Math::Vector lookat)
-{
- CObject *pObj;
- Math::Vector oPos, proj;
- ObjectType type;
- float oRadius, dist;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_cameraObj ) continue;
-
- type = pObj->RetType();
- if ( type == OBJECT_TOTO ||
- type == OBJECT_FRET ||
- type == OBJECT_STONE ||
- type == OBJECT_URANIUM ||
- type == OBJECT_METAL ||
- type == OBJECT_POWER ||
- type == OBJECT_ATOMIC ||
- type == OBJECT_BULLET ||
- type == OBJECT_BBOX ||
- type == OBJECT_KEYa ||
- type == OBJECT_KEYb ||
- type == OBJECT_KEYc ||
- type == OBJECT_KEYd ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ) continue;
-
- pObj->GetGlobalSphere(oPos, oRadius);
- if ( oRadius == 0.0f ) continue;
-
- dist = Math::Distance(eye, oPos);
- if ( dist < oRadius )
- {
- dist = Math::Distance(eye, lookat);
- proj = Projection(eye, lookat, oPos);
- eye = (lookat-eye)*oRadius/dist + proj;
- return false;
- }
- }
- return false;
-}
-
-
-// Management of an event.
-
-bool CCamera::EventProcess(const Event &event)
-{
- switch( event.event )
- {
- case EVENT_FRAME:
- EventFrame(event);
- break;
-
-#if 0
- case EVENT_RBUTTONDOWN:
- m_bRightDown = true;
- m_rightPosInit = event.pos;
- m_rightPosCenter = Math::Point(0.5f, 0.5f);
- m_engine->MoveMousePos(m_rightPosCenter);
-//? m_engine->SetMouseHide(true); // cache la souris
- break;
-
- case EVENT_RBUTTONUP:
- m_bRightDown = false;
- m_engine->MoveMousePos(m_rightPosInit);
-//? m_engine->SetMouseHide(false); // remontre la souris
- m_addDirectionH = 0.0f;
- m_addDirectionV = -Math::PI*0.05f;
- break;
-#endif
-
- case EVENT_MOUSEMOVE:
- EventMouseMove(event);
- break;
-
- case EVENT_KEYDOWN:
- if ( event.param == VK_WHEELUP ) EventMouseWheel(+1);
- if ( event.param == VK_WHEELDOWN ) EventMouseWheel(-1);
- break;
- }
- return true;
-}
-
-// Changed the camera according to the mouse moved.
-
-bool CCamera::EventMouseMove(const Event &event)
-{
- m_mousePos = event.pos;
- return true;
-}
-
-// Mouse wheel operated.
-
-void CCamera::EventMouseWheel(int dir)
-{
- if ( m_type == CAMERA_BACK )
- {
- if ( dir > 0 )
- {
- m_backDist -= 8.0f;
- if ( m_backDist < m_backMin ) m_backDist = m_backMin;
- }
- if ( dir < 0 )
- {
- m_backDist += 8.0f;
- if ( m_backDist > 200.0f ) m_backDist = 200.0f;
- }
- }
-
- if ( m_type == CAMERA_FIX ||
- m_type == CAMERA_PLANE )
- {
- if ( dir > 0 )
- {
- m_fixDist -= 8.0f;
- if ( m_fixDist < 10.0f ) m_fixDist = 10.0f;
- }
- if ( dir < 0 )
- {
- m_fixDist += 8.0f;
- if ( m_fixDist > 200.0f ) m_fixDist = 200.0f;
- }
- }
-
- if ( m_type == CAMERA_VISIT )
- {
- if ( dir > 0 )
- {
- m_visitDist -= 8.0f;
- if ( m_visitDist < 20.0f ) m_visitDist = 20.0f;
- }
- if ( dir < 0 )
- {
- m_visitDist += 8.0f;
- if ( m_visitDist > 200.0f ) m_visitDist = 200.0f;
- }
- }
-}
-
-// Changed the camera according to the time elapsed.
-
-bool CCamera::EventFrame(const Event &event)
-{
- EffectFrame(event);
- OverFrame(event);
-
- if ( m_type == CAMERA_FREE )
- {
- return EventFrameFree(event);
- }
- if ( m_type == CAMERA_EDIT )
- {
- return EventFrameEdit(event);
- }
- if ( m_type == CAMERA_DIALOG )
- {
- return EventFrameDialog(event);
- }
- if ( m_type == CAMERA_BACK )
- {
- return EventFrameBack(event);
- }
- if ( m_type == CAMERA_FIX ||
- m_type == CAMERA_PLANE )
- {
- return EventFrameFix(event);
- }
- if ( m_type == CAMERA_EXPLO )
- {
- return EventFrameExplo(event);
- }
- if ( m_type == CAMERA_ONBOARD )
- {
- return EventFrameOnBoard(event);
- }
- if ( m_type == CAMERA_SCRIPT )
- {
- return EventFrameScript(event);
- }
- if ( m_type == CAMERA_INFO )
- {
- return EventFrameInfo(event);
- }
- if ( m_type == CAMERA_VISIT )
- {
- return EventFrameVisit(event);
- }
-
- return true;
-}
-
-
-// Returns the default sprite to use for the mouse.
-
-D3DMouse CCamera::RetMouseDef(Math::Point pos)
-{
- D3DMouse type;
-
- type = D3DMOUSENORM;
- m_mousePos = pos;
-
- if ( m_type == CAMERA_INFO ) return type;
-
- if ( m_bRightDown ) // the right button pressed?
- {
- m_rightPosMove.x = pos.x - m_rightPosCenter.x;
- m_rightPosMove.y = pos.y - m_rightPosCenter.y;
- type = D3DMOUSEMOVE;
- }
- else
- {
- if ( !m_bCameraScroll ) return type;
-
- m_mouseDirH = 0.0f;
- m_mouseDirV = 0.0f;
-
- if ( pos.x < m_mouseMarging )
- {
- m_mouseDirH = pos.x/m_mouseMarging - 1.0f;
- }
-
- if ( pos.x > 1.0f-m_mouseMarging )
- {
- m_mouseDirH = 1.0f - (1.0f-pos.x)/m_mouseMarging;
- }
-
- if ( pos.y < m_mouseMarging )
- {
- m_mouseDirV = pos.y/m_mouseMarging - 1.0f;
- }
-
- if ( pos.y > 1.0f-m_mouseMarging )
- {
- m_mouseDirV = 1.0f - (1.0f-pos.y)/m_mouseMarging;
- }
-
- if ( m_type == CAMERA_FREE ||
- m_type == CAMERA_EDIT ||
- m_type == CAMERA_BACK ||
- m_type == CAMERA_FIX ||
- m_type == CAMERA_PLANE ||
- m_type == CAMERA_EXPLO )
- {
- if ( m_mouseDirH > 0.0f )
- {
- type = D3DMOUSESCROLLR;
- }
- if ( m_mouseDirH < 0.0f )
- {
- type = D3DMOUSESCROLLL;
- }
- }
-
- if ( m_type == CAMERA_FREE ||
- m_type == CAMERA_EDIT )
- {
- if ( m_mouseDirV > 0.0f )
- {
- type = D3DMOUSESCROLLU;
- }
- if ( m_mouseDirV < 0.0f )
- {
- type = D3DMOUSESCROLLD;
- }
- }
-
- if ( m_bCameraInvertX )
- {
- m_mouseDirH = -m_mouseDirH;
- }
- }
-
- return type;
-}
-
-
-
-// Moves the point of view.
-
-bool CCamera::EventFrameFree(const Event &event)
-{
- Math::Vector pos, vLookatPt;
- float factor;
-
- factor = m_heightEye*0.5f+30.0f;
-
- if ( m_mouseDirH != 0.0f )
- {
- m_directionH -= m_mouseDirH*event.rTime*0.7f*m_speed;
- }
- if ( m_mouseDirV != 0.0f )
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, m_mouseDirV*event.rTime*factor*m_speed);
- }
-
- // Up/Down.
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, event.axeY*event.rTime*factor*m_speed);
-
- // Left/Right.
- if ( event.keyState & KS_CONTROL )
- {
- if ( event.axeX < 0.0f )
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH+Math::PI/2.0f, m_directionV, -event.axeX*event.rTime*factor*m_speed);
- }
- if ( event.axeX > 0.0f )
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH-Math::PI/2.0f, m_directionV, event.axeX*event.rTime*factor*m_speed);
- }
- }
- else
- {
- m_directionH -= event.axeX*event.rTime*0.7f*m_speed;
- }
-
- // PageUp/PageDown.
- if ( event.keyState & KS_NUMMINUS )
- {
- if ( m_heightEye < 500.0f )
- {
- m_heightEye += event.rTime*factor*m_speed;
- }
- }
- if ( event.keyState & KS_NUMPLUS )
- {
- if ( m_heightEye > -2.0f )
- {
- m_heightEye -= event.rTime*factor*m_speed;
- }
- }
-
- m_terrain->ValidPosition(m_eyePt, 10.0f);
-
- if ( m_terrain->MoveOnFloor(m_eyePt, true) )
- {
- m_eyePt.y += m_heightEye;
-
- pos = m_eyePt;
- if ( m_terrain->MoveOnFloor(pos, true) )
- {
- pos.y -= 2.0f;
- if ( m_eyePt.y < pos.y )
- {
- m_eyePt.y = pos.y;
- }
- }
-
- }
-
- vLookatPt = Math::LookatPoint( m_eyePt, m_directionH, m_directionV, 50.0f );
-
- if ( m_terrain->MoveOnFloor(vLookatPt, true) )
- {
- vLookatPt.y += m_heightLookat;
- }
-
- SetViewTime(m_eyePt, vLookatPt, event.rTime);
-
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameEdit(const Event &event)
-{
- Math::Vector pos, vLookatPt;
- float factor;
-
- factor = m_editHeight*0.5f+30.0f;
-
- if ( m_mouseDirH != 0.0f )
- {
- m_directionH -= m_mouseDirH*event.rTime*0.7f*m_speed;
- }
- if ( m_mouseDirV != 0.0f )
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, m_mouseDirV*event.rTime*factor*m_speed);
- }
-
- if ( m_bCameraScroll )
- {
- // Left/Right.
- m_fixDirectionH += m_mouseDirH*event.rTime*1.0f*m_speed;
- m_fixDirectionH = Math::NormAngle(m_fixDirectionH);
-
- // Up/Down.
-//? m_fixDirectionV -= m_mouseDirV*event.rTime*0.5f*m_speed;
-//? if ( m_fixDirectionV < -Math::PI*0.40f ) m_fixDirectionV = -Math::PI*0.40f;
-//? if ( m_fixDirectionV > Math::PI*0.20f ) m_fixDirectionV = Math::PI*0.20f;
- }
-
- m_terrain->ValidPosition(m_eyePt, 10.0f);
-
- if ( m_terrain->MoveOnFloor(m_eyePt, false) )
- {
- m_eyePt.y += m_editHeight;
-
- pos = m_eyePt;
- if ( m_terrain->MoveOnFloor(pos, false) )
- {
- pos.y += 2.0f;
- if ( m_eyePt.y < pos.y )
- {
- m_eyePt.y = pos.y;
- }
- }
-
- }
-
- vLookatPt = Math::LookatPoint( m_eyePt, m_directionH, m_directionV, 50.0f );
-
- if ( m_terrain->MoveOnFloor(vLookatPt, true) )
- {
- vLookatPt.y += m_heightLookat;
- }
-
- SetViewTime(m_eyePt, vLookatPt, event.rTime);
-
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameDialog(const Event &event)
-{
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameBack(const Event &event)
-{
- CPhysics* physics;
- ObjectType type;
- Math::Vector pos, vLookatPt;
- Math::Point mouse;
- float centeringH, centeringV, centeringD, h, v, d, floor;
-
- if ( m_cameraObj == 0 )
- {
- type = OBJECT_NULL;
- }
- else
- {
- type = m_cameraObj->RetType();
- }
-
- // +/-.
- if ( event.keyState & KS_NUMPLUS )
- {
- m_backDist -= event.rTime*30.0f*m_speed;
- if ( m_backDist < m_backMin ) m_backDist = m_backMin;
- }
- if ( event.keyState & KS_NUMMINUS )
- {
- m_backDist += event.rTime*30.0f*m_speed;
- if ( m_backDist > 200.0f ) m_backDist = 200.0f;
- }
-
- m_motorTurn = 0.0f;
-
- if ( m_bRightDown )
- {
- m_addDirectionH = m_rightPosMove.x*6.0f;
- m_addDirectionV = -m_rightPosMove.y*2.0f;
- }
- else
- {
- if ( m_bCameraScroll )
- {
-#if 1
- // Left/Right.
- m_addDirectionH += m_mouseDirH*event.rTime*1.0f*m_speed;
- m_addDirectionH = Math::NormAngle(m_addDirectionH);
-
- // Up/Down.
-//? m_backDist -= m_mouseDirV*event.rTime*30.0f*m_speed;
-//? if ( m_backDist < 10.0f ) m_backDist = 10.0f;
-//? if ( m_backDist > 200.0f ) m_backDist = 200.0f;
-#else
- if ( m_mousePos.y >= 0.18f && m_mousePos.y <= 0.93f )
- {
-//? m_addDirectionH = -(m_mousePos.x-0.5f)*4.0f;
- m_addDirectionV = (m_mousePos.y-0.5f)*2.0f;
-//? if ( m_bCameraInvertX ) m_addDirectionH = -m_addDirectionH;
- if ( m_bCameraInvertY ) m_addDirectionV = -m_addDirectionV;
-
- if ( m_mousePos.x < 0.5f ) m_motorTurn = -1.0f;
- if ( m_mousePos.x > 0.5f ) m_motorTurn = 1.0f;
-
- mouse = m_mousePos;
- mouse.x = 0.5f;
- m_engine->MoveMousePos(mouse);
- }
- else
- {
- m_addDirectionH = 0.0f;
- m_addDirectionV = 0.0f;
- }
-#endif
- }
- }
-
- if ( m_mouseDirH != 0 || m_mouseDirV != 0 )
- {
- AbortCentering(); // special stops framing
- }
-
- // Increase the special framework.
- centeringH = 0.0f;
- centeringV = 0.0f;
- centeringD = 0.0f;
-
- if ( m_centeringPhase == CP_START )
- {
- m_centeringProgress += event.rTime/m_centeringTime;
- if ( m_centeringProgress > 1.0f ) m_centeringProgress = 1.0f;
- centeringH = m_centeringProgress;
- centeringV = m_centeringProgress;
- centeringD = m_centeringProgress;
- if ( m_centeringProgress >= 1.0f )
- {
- m_centeringPhase = CP_WAIT;
- }
- }
-
- if ( m_centeringPhase == CP_WAIT )
- {
- centeringH = 1.0f;
- centeringV = 1.0f;
- centeringD = 1.0f;
- }
-
- if ( m_centeringPhase == CP_STOP )
- {
- m_centeringProgress += event.rTime/m_centeringTime;
- if ( m_centeringProgress > 1.0f ) m_centeringProgress = 1.0f;
- centeringH = 1.0f-m_centeringProgress;
- centeringV = 1.0f-m_centeringProgress;
- centeringD = 1.0f-m_centeringProgress;
- if ( m_centeringProgress >= 1.0f )
- {
- m_centeringPhase = CP_NULL;
- }
- }
-
- if ( m_centeringAngleH == 99.9f ) centeringH = 0.0f;
- if ( m_centeringAngleV == 99.9f ) centeringV = 0.0f;
- if ( m_centeringDist == 0.0f ) centeringD = 0.0f;
-
- if ( m_cameraObj != 0 )
- {
- vLookatPt = m_cameraObj->RetPosition(0);
- if ( type == OBJECT_BASE ) vLookatPt.y += 40.0f;
- else if ( type == OBJECT_HUMAN ) vLookatPt.y += 1.0f;
- else if ( type == OBJECT_TECH ) vLookatPt.y += 1.0f;
- else vLookatPt.y += 4.0f;
-
- h = -m_cameraObj->RetAngleY(0); // angle vehicle / building
-
- if ( 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 ||
- type == OBJECT_START ||
- type == OBJECT_END ) // building?
- {
- h += Math::PI*0.20f; // nearly face
- }
- else // vehicle?
- {
- h += Math::PI; // back
- }
- h = Math::NormAngle(h)+m_remotePan;
- v = 0.0f; //?
-
- h += m_centeringCurrentH;
- h += m_addDirectionH*(1.0f-centeringH);
- h = Math::NormAngle(h);
-
- if ( type == OBJECT_MOBILEdr ) // designer?
- {
- v -= 0.3f; // Camera top
- }
-
- v += m_centeringCurrentV;
- v += m_addDirectionV*(1.0f-centeringV);
-
- d = m_backDist;
- d += m_centeringDist*centeringD;
-
- m_centeringCurrentH = m_centeringAngleH*centeringH;
- m_centeringCurrentV = m_centeringAngleV*centeringV;
-
- m_eyePt = RotateView(vLookatPt, h, v, d);
-
- physics = m_cameraObj->RetPhysics();
- if ( physics != 0 && physics->RetLand() ) // ground?
- {
- pos = vLookatPt+(vLookatPt-m_eyePt);
- floor = m_terrain->RetFloorHeight(pos)-4.0f;
- if ( floor > 0.0f )
- {
- m_eyePt.y += floor; // shows the descent in front
- }
- }
-
- m_eyePt = ExcludeTerrain(m_eyePt, vLookatPt, h, v);
- m_eyePt = ExcludeObject(m_eyePt, vLookatPt, h, v);
-
- SetViewTime(m_eyePt, vLookatPt, event.rTime);
-
- m_directionH = h+Math::PI/2.0f;
- m_directionV = v;
- }
-
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameFix(const Event &event)
-{
- Math::Vector pos, vLookatPt;
- float h, v, d;
-
- // +/-.
- if ( event.keyState & KS_NUMPLUS )
- {
- m_fixDist -= event.rTime*30.0f*m_speed;
- if ( m_fixDist < 10.0f ) m_fixDist = 10.0f;
- }
- if ( event.keyState & KS_NUMMINUS )
- {
- m_fixDist += event.rTime*30.0f*m_speed;
- if ( m_fixDist > 200.0f ) m_fixDist = 200.0f;
- }
-
- if ( m_bCameraScroll )
- {
- // Left/Right.
- m_fixDirectionH += m_mouseDirH*event.rTime*1.0f*m_speed;
- m_fixDirectionH = Math::NormAngle(m_fixDirectionH);
-
- // Up/Down.
-//? m_fixDist -= m_mouseDirV*event.rTime*30.0f*m_speed;
-//? if ( m_fixDist < 10.0f ) m_fixDist = 10.0f;
-//? if ( m_fixDist > 200.0f ) m_fixDist = 200.0f;
- }
-
- if ( m_mouseDirH != 0 || m_mouseDirV != 0 )
- {
- AbortCentering(); // special stops framing
- }
-
- if ( m_cameraObj != 0 )
- {
- vLookatPt = m_cameraObj->RetPosition(0);
-
- h = m_fixDirectionH+m_remotePan;
- v = m_fixDirectionV;
-
- d = m_fixDist;
-//- if ( m_type == CAMERA_PLANE ) d += 20.0f;
- m_eyePt = RotateView(vLookatPt, h, v, d);
-//- if ( m_type == CAMERA_PLANE ) m_eyePt.y += 50.0f;
- if ( m_type == CAMERA_PLANE ) m_eyePt.y += m_fixDist/2.0f;
- m_eyePt = ExcludeTerrain(m_eyePt, vLookatPt, h, v);
- m_eyePt = ExcludeObject(m_eyePt, vLookatPt, h, v);
-
- SetViewTime(m_eyePt, vLookatPt, event.rTime);
-
- m_directionH = h+Math::PI/2.0f;
- m_directionV = v;
- }
-
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameExplo(const Event &event)
-{
- Math::Vector pos, vLookatPt;
- float factor;
-
- factor = m_heightEye*0.5f+30.0f;
-
- if ( m_mouseDirH != 0.0f )
- {
- m_directionH -= m_mouseDirH*event.rTime*0.7f*m_speed;
- }
-
- m_terrain->ValidPosition(m_eyePt, 10.0f);
-
- if ( m_terrain->MoveOnFloor(m_eyePt, false) )
- {
- m_eyePt.y += m_heightEye;
-
- pos = m_eyePt;
- if ( m_terrain->MoveOnFloor(pos, false) )
- {
- pos.y += 2.0f;
- if ( m_eyePt.y < pos.y )
- {
- m_eyePt.y = pos.y;
- }
- }
-
- }
-
- vLookatPt = Math::LookatPoint( m_eyePt, m_directionH, m_directionV, 50.0f );
-
- if ( m_terrain->MoveOnFloor(vLookatPt, true) )
- {
- vLookatPt.y += m_heightLookat;
- }
-
- SetViewTime(m_eyePt, vLookatPt, event.rTime);
-
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameOnBoard(const Event &event)
-{
- Math::Vector vLookatPt, vUpVec, eye, lookat, pos;
-
- if ( m_cameraObj != 0 )
- {
- m_cameraObj->SetViewFromHere(m_eyePt, m_directionH, m_directionV,
- vLookatPt, vUpVec, m_type);
- eye = m_effectOffset*0.3f+m_eyePt;
- lookat = m_effectOffset*0.3f+vLookatPt;
-
- SetViewParams(eye, lookat, vUpVec);
- m_actualEye = eye;
- m_actualLookat = lookat;
- }
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameInfo(const Event &event)
-{
- SetViewTime(Math::Vector(0.0f, 0.0f, 0.0f),
- Math::Vector(0.0f, 0.0f, 1.0f),
- event.rTime);
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameVisit(const Event &event)
-{
- Math::Vector eye;
- float angleH, angleV;
-
- m_visitTime += event.rTime;
-
- // +/-.
- if ( event.keyState & KS_NUMPLUS )
- {
- m_visitDist -= event.rTime*50.0f*m_speed;
- if ( m_visitDist < 20.0f ) m_visitDist = 20.0f;
- }
- if ( event.keyState & KS_NUMMINUS )
- {
- m_visitDist += event.rTime*50.0f*m_speed;
- if ( m_visitDist > 200.0f ) m_visitDist = 200.0f;
- }
-
- // PageUp/Down.
- if ( event.keyState & KS_PAGEUP )
- {
- m_visitDirectionV -= event.rTime*1.0f*m_speed;
- if ( m_visitDirectionV < -Math::PI*0.40f ) m_visitDirectionV = -Math::PI*0.40f;
- }
- if ( event.keyState & KS_PAGEDOWN )
- {
- m_visitDirectionV += event.rTime*1.0f*m_speed;
- if ( m_visitDirectionV > 0.0f ) m_visitDirectionV = 0.0f;
- }
-
- if ( m_bCameraScroll )
- {
- m_visitDist -= m_mouseDirV*event.rTime*30.0f*m_speed;
- if ( m_visitDist < 20.0f ) m_visitDist = 20.0f;
- if ( m_visitDist > 200.0f ) m_visitDist = 200.0f;
- }
-
- angleH = (m_visitTime/10.0f)*(Math::PI*2.0f);
- angleV = m_visitDirectionV;
- eye = RotateView(m_visitGoal, angleH, angleV, m_visitDist);
- eye = ExcludeTerrain(eye, m_visitGoal, angleH, angleV);
- eye = ExcludeObject(eye, m_visitGoal, angleH, angleV);
- SetViewTime(eye, m_visitGoal, event.rTime);
-
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameScript(const Event &event)
-{
- SetViewTime(m_scriptEye+m_effectOffset,
- m_scriptLookat+m_effectOffset, event.rTime);
- return true;
-}
-
-void CCamera::SetScriptEye(Math::Vector eye)
-{
- m_scriptEye = eye;
-}
-
-void CCamera::SetScriptLookat(Math::Vector lookat)
-{
- m_scriptLookat = lookat;
-}
-
-
-// Specifies the location and direction of view.
-
-void CCamera::SetViewParams(const Math::Vector &eye, const Math::Vector &lookat,
- const Math::Vector &up)
-{
- bool bUnder;
-
- m_engine->SetViewParams(eye, lookat, up, m_eyeDistance);
-
- bUnder = (eye.y < m_water->RetLevel()); // Is it underwater?
- if ( m_type == CAMERA_INFO ) bUnder = false;
- m_engine->SetRankView(bUnder?1:0);
-}
-
-
-// Adjusts the camera not to enter the field.
-
-Math::Vector CCamera::ExcludeTerrain(Math::Vector eye, Math::Vector lookat,
- float &angleH, float &angleV)
-{
- Math::Vector pos;
- float dist;
-
- pos = eye;
- if ( m_terrain->MoveOnFloor(pos) )
- {
- dist = Math::DistanceProjected(lookat, pos);
- pos.y += 2.0f+dist*0.1f;
- if ( pos.y > eye.y )
- {
- angleV = -Math::RotateAngle(dist, pos.y-lookat.y);
- eye = RotateView(lookat, angleH, angleV, dist);
- }
- }
- return eye;
-}
-
-// Adjusts the camera not to enter an object.
-
-Math::Vector CCamera::ExcludeObject(Math::Vector eye, Math::Vector lookat,
- float &angleH, float &angleV)
-{
- CObject* pObj;
- Math::Vector oPos;
- float oRad, dist;
- int i, j;
-
-return eye;
-//?
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRad) )
- {
- dist = Math::Distance(oPos, eye);
- if ( dist < oRad+2.0f )
- {
- eye.y = oPos.y+oRad+2.0f;
- }
- }
- }
-
- return eye;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/language.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "object/object.h"
+#include "physics/physics.h"
+#include "old/camera.h"
+
+
+
+
+// Object's constructor.
+
+CCamera::CCamera(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_CAMERA, this);
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+
+ m_type = CAMERA_FREE;
+ m_smooth = CS_NORM;
+ m_cameraObj = 0;
+
+ m_eyeDistance = 10.0f;
+ m_initDelay = 0.0f;
+
+ m_actualEye = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_actualLookat = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_finalEye = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_finalLookat = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_normEye = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_normLookat = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_focus = 1.0f;
+
+ m_bRightDown = false;
+ m_rightPosInit = Math::Point(0.5f, 0.5f);
+ m_rightPosCenter = Math::Point(0.5f, 0.5f);
+ m_rightPosMove = Math::Point(0.5f, 0.5f);
+
+ m_eyePt = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_directionH = 0.0f;
+ m_directionV = 0.0f;
+ m_heightEye = 20.0f;
+ m_heightLookat = 0.0f;
+ m_speed = 2.0f;
+
+ m_backDist = 0.0f;
+ m_backMin = 0.0f;
+ m_addDirectionH = 0.0f;
+ m_addDirectionV = 0.0f;
+ m_bTransparency = false;
+
+ m_fixDist = 0.0f;
+ m_fixDirectionH = 0.0f;
+ m_fixDirectionV = 0.0f;
+
+ m_visitGoal = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_visitDist = 0.0f;
+ m_visitTime = 0.0f;
+ m_visitType = CAMERA_NULL;
+ m_visitDirectionH = 0.0f;
+ m_visitDirectionV = 0.0f;
+
+ m_editHeight = 40.0f;
+
+ m_remotePan = 0.0f;
+ m_remoteZoom = 0.0f;
+
+ m_mouseDirH = 0.0f;
+ m_mouseDirV = 0.0f;
+ m_mouseMarging = 0.01f;
+
+ m_motorTurn = 0.0f;
+
+ m_centeringPhase = CP_NULL;
+ m_centeringAngleH = 0.0f;
+ m_centeringAngleV = 0.0f;
+ m_centeringDist = 0.0f;
+ m_centeringCurrentH = 0.0f;
+ m_centeringCurrentV = 0.0f;
+ m_centeringTime = 0.0f;
+ m_centeringProgress = 0.0f;
+
+ m_effectType = CE_NULL;
+ m_effectPos = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_effectForce = 0.0f;
+ m_effectProgress = 0.0f;
+ m_effectOffset = Math::Vector(0.0f, 0.0f, 0.0f);
+
+ m_scriptEye = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_scriptLookat = Math::Vector(0.0f, 0.0f, 0.0f);
+
+ m_bEffect = true;
+ m_bCameraScroll = true;
+ m_bCameraInvertX = false;
+ m_bCameraInvertY = false;
+}
+
+// Object's constructor.
+
+CCamera::~CCamera()
+{
+}
+
+
+void CCamera::SetEffect(bool bEnable)
+{
+ m_bEffect = bEnable;
+}
+
+void CCamera::SetCameraScroll(bool bScroll)
+{
+ m_bCameraScroll = bScroll;
+}
+
+void CCamera::SetCameraInvertX(bool bInvert)
+{
+ m_bCameraInvertX = bInvert;
+}
+
+void CCamera::SetCameraInvertY(bool bInvert)
+{
+ m_bCameraInvertY = bInvert;
+}
+
+
+// Returns an additional force to turn.
+
+float CCamera::RetMotorTurn()
+{
+ if ( m_type == CAMERA_BACK ) return m_motorTurn;
+ return 0.0f;
+}
+
+
+
+// Initializes the camera.
+
+void CCamera::Init(Math::Vector eye, Math::Vector lookat, float delay)
+{
+ Math::Vector vUpVec;
+
+ m_initDelay = delay;
+
+ eye.y += m_terrain->RetFloorLevel(eye, true);
+ lookat.y += m_terrain->RetFloorLevel(lookat, true);
+
+ m_type = CAMERA_FREE;
+ m_eyePt = eye;
+
+ m_directionH = Math::RotateAngle(eye.x-lookat.x, eye.z-lookat.z)+Math::PI/2.0f;
+ m_directionV = -Math::RotateAngle(Math::DistanceProjected(eye, lookat), eye.y-lookat.y);
+
+ m_eyeDistance = 10.0f;
+ m_heightLookat = 10.0f;
+ m_backDist = 30.0f;
+ m_backMin = 10.0f;
+ m_addDirectionH = 0.0f;
+ m_addDirectionV = -Math::PI*0.05f;
+ m_fixDist = 50.0f;
+ m_fixDirectionH = Math::PI*0.25f;
+ m_fixDirectionV = -Math::PI*0.10f;
+ m_centeringPhase = CP_NULL;
+ m_actualEye = m_eyePt;
+ m_actualLookat = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, 50.0f);
+ m_finalEye = m_actualEye;
+ m_finalLookat = m_actualLookat;
+ m_scriptEye = m_actualEye;
+ m_scriptLookat = m_actualLookat;
+ m_focus = 1.00f;
+ m_remotePan = 0.0f;
+ m_remoteZoom = 0.0f;
+
+ FlushEffect();
+ FlushOver();
+ SetType(CAMERA_FREE);
+}
+
+
+// Gives the object controlling the camera.
+
+void CCamera::SetObject(CObject* object)
+{
+ m_cameraObj = object;
+}
+
+CObject* CCamera::RetObject()
+{
+ return m_cameraObj;
+}
+
+
+// Changes the level of transparency of an object and objects
+// transported (battery & cargo).
+
+void SetTransparency(CObject* pObj, float value)
+{
+ CObject* pFret;
+
+ pObj->SetTransparency(value);
+
+ pFret = pObj->RetFret();
+ if ( pFret != 0 )
+ {
+ pFret->SetTransparency(value);
+ }
+
+ pFret = pObj->RetPower();
+ if ( pFret != 0 )
+ {
+ pFret->SetTransparency(value);
+ }
+}
+
+// Change the type of camera.
+
+void CCamera::SetType(CameraType type)
+{
+ CObject* pObj;
+ ObjectType oType;
+ Math::Vector vUpVec;
+ int i;
+
+ m_remotePan = 0.0f;
+ m_remoteZoom = 0.0f;
+
+ if ( m_type == CAMERA_BACK && m_bTransparency )
+ {
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetTruck() ) continue; // battery or cargo?
+
+ SetTransparency(pObj, 0.0f); // opaque object
+ }
+ }
+ m_bTransparency = false;
+
+ if ( type == CAMERA_INFO ||
+ type == CAMERA_VISIT ) // xx -> info ?
+ {
+ m_normEye = m_engine->RetEyePt();
+ m_normLookat = m_engine->RetLookatPt();
+
+ m_engine->SetFocus(1.00f); // normal
+ m_type = type;
+ return;
+ }
+
+ if ( m_type == CAMERA_INFO ||
+ m_type == CAMERA_VISIT ) // info -> xx ?
+ {
+ m_engine->SetFocus(m_focus); // gives initial focus
+ m_type = type;
+
+ vUpVec = Math::Vector(0.0f, 1.0f, 0.0f);
+ SetViewParams(m_normEye, m_normLookat, vUpVec);
+ return;
+ }
+
+ if ( m_type == CAMERA_BACK && type == CAMERA_FREE ) // back -> free ?
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -50.0f);
+ }
+
+ if ( m_type == CAMERA_BACK && type == CAMERA_EDIT ) // back -> edit ?
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -1.0f);
+ }
+
+ if ( m_type == CAMERA_ONBOARD && type == CAMERA_FREE ) // onboard -> free ?
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -30.0f);
+ }
+
+ if ( m_type == CAMERA_ONBOARD && type == CAMERA_EDIT ) // onboard -> edit ?
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -30.0f);
+ }
+
+ if ( m_type == CAMERA_ONBOARD && type == CAMERA_EXPLO ) // onboard -> explo ?
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -50.0f);
+ }
+
+ if ( m_type == CAMERA_BACK && type == CAMERA_EXPLO ) // back -> explo ?
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -20.0f);
+ }
+
+ if ( type == CAMERA_FIX ||
+ type == CAMERA_PLANE )
+ {
+ AbortCentering(); // Special stops framing
+ }
+
+ m_fixDist = 50.0f;
+ if ( type == CAMERA_PLANE )
+ {
+ m_fixDist = 60.0f;
+ }
+
+ if ( type == CAMERA_BACK )
+ {
+ AbortCentering(); // Special stops framing
+ m_addDirectionH = 0.0f;
+ m_addDirectionV = -Math::PI*0.05f;
+
+ if ( m_cameraObj == 0 ) oType = OBJECT_NULL;
+ else oType = m_cameraObj->RetType();
+
+ m_backDist = 30.0f;
+ if ( oType == OBJECT_BASE ) m_backDist = 200.0f;
+ if ( oType == OBJECT_HUMAN ) m_backDist = 20.0f;
+ if ( oType == OBJECT_TECH ) m_backDist = 20.0f;
+ if ( oType == OBJECT_FACTORY ) m_backDist = 50.0f;
+ if ( oType == OBJECT_RESEARCH ) m_backDist = 40.0f;
+ if ( oType == OBJECT_DERRICK ) m_backDist = 40.0f;
+ if ( oType == OBJECT_REPAIR ) m_backDist = 35.0f;
+ if ( oType == OBJECT_DESTROYER) m_backDist = 35.0f;
+ if ( oType == OBJECT_TOWER ) m_backDist = 45.0f;
+ if ( oType == OBJECT_NUCLEAR ) m_backDist = 70.0f;
+ if ( oType == OBJECT_PARA ) m_backDist = 180.0f;
+ if ( oType == OBJECT_SAFE ) m_backDist = 50.0f;
+ if ( oType == OBJECT_HUSTON ) m_backDist = 120.0f;
+
+ m_backMin = m_backDist/3.0f;
+ if ( oType == OBJECT_HUMAN ) m_backMin = 10.0f;
+ if ( oType == OBJECT_TECH ) m_backMin = 10.0f;
+ if ( oType == OBJECT_FACTORY ) m_backMin = 30.0f;
+ if ( oType == OBJECT_RESEARCH ) m_backMin = 20.0f;
+ if ( oType == OBJECT_NUCLEAR ) m_backMin = 32.0f;
+ if ( oType == OBJECT_PARA ) m_backMin = 40.0f;
+ if ( oType == OBJECT_SAFE ) m_backMin = 25.0f;
+ if ( oType == OBJECT_HUSTON ) m_backMin = 80.0f;
+ }
+
+ if ( type != CAMERA_ONBOARD && m_cameraObj != 0 )
+ {
+ m_cameraObj->SetGunGoalH(0.0f); // puts the cannon right
+ }
+
+ if ( type == CAMERA_ONBOARD )
+ {
+ m_focus = 1.50f; // Wide
+ }
+ else
+ {
+ m_focus = 1.00f; // normal
+ }
+ m_engine->SetFocus(m_focus);
+
+ m_type = type;
+
+ SetSmooth(CS_NORM);
+}
+
+CameraType CCamera::RetType()
+{
+ return m_type;
+}
+
+
+// Management of the smoothing mode.
+
+void CCamera::SetSmooth(CameraSmooth type)
+{
+ m_smooth = type;
+}
+
+CameraSmooth CCamera::RetSmoth()
+{
+ return m_smooth;
+}
+
+
+// Management of the setback distance.
+
+void CCamera::SetDist(float dist)
+{
+ m_fixDist = dist;
+}
+
+float CCamera::RetDist()
+{
+ return m_fixDist;
+}
+
+
+// Manage angle mode CAMERA_FIX.
+
+void CCamera::SetFixDirection(float angle)
+{
+ m_fixDirectionH = angle;
+}
+
+float CCamera::RetFixDirection()
+{
+ return m_fixDirectionH;
+}
+
+
+// Managing the triggering mode of the camera panning.
+
+void CCamera::SetRemotePan(float value)
+{
+ m_remotePan = value;
+}
+
+float CCamera::RetRemotePan()
+{
+ return m_remotePan;
+}
+
+// Management of the remote zoom (0 .. 1) of the camera.
+
+void CCamera::SetRemoteZoom(float value)
+{
+ value = Math::Norm(value);
+
+ if ( m_type == CAMERA_BACK )
+ {
+ m_backDist = m_backMin+(200.0f-m_backMin)*value;
+ }
+
+ if ( m_type == CAMERA_FIX ||
+ m_type == CAMERA_PLANE )
+ {
+ m_fixDist = 10.0f+(200.0f-10.0f)*value;
+ }
+}
+
+float CCamera::RetRemoteZoom()
+{
+ if ( m_type == CAMERA_BACK )
+ {
+ return (m_backDist-m_backMin)/(200.0f-m_backMin);
+ }
+
+ if ( m_type == CAMERA_FIX ||
+ m_type == CAMERA_PLANE )
+ {
+ return (m_fixDist-10.0f)/(200.0f-10.0f);
+ }
+ return 0.0f;
+}
+
+
+
+// Start with a tour round the camera.
+
+void CCamera::StartVisit(Math::Vector goal, float dist)
+{
+ m_visitType = m_type;
+ SetType(CAMERA_VISIT);
+ m_visitGoal = goal;
+ m_visitDist = dist;
+ m_visitTime = 0.0f;
+ m_visitDirectionH = 0.0f;
+ m_visitDirectionV = -Math::PI*0.10f;
+}
+
+// Circular end of a visit with the camera.
+
+void CCamera::StopVisit()
+{
+ SetType(m_visitType); // presents the initial type
+}
+
+
+// Returns the point of view of the camera.
+
+void CCamera::RetCamera(Math::Vector &eye, Math::Vector &lookat)
+{
+ eye = m_eyePt;
+ lookat = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, 50.0f);
+}
+
+
+// Specifies a special movement of camera to frame action.
+
+bool CCamera::StartCentering(CObject *object, float angleH, float angleV,
+ float dist, float time)
+{
+ if ( m_type != CAMERA_BACK ) return false;
+ if ( object != m_cameraObj ) return false;
+
+ if ( m_centeringPhase != CP_NULL ) return false;
+
+ if ( m_addDirectionH > Math::PI )
+ {
+ angleH = Math::PI*2.0f-angleH;
+ }
+
+ m_centeringPhase = CP_START;
+ m_centeringAngleH = angleH;
+ m_centeringAngleV = angleV;
+ m_centeringDist = dist;
+ m_centeringCurrentH = 0.0f;
+ m_centeringCurrentV = 0.0f;
+ m_centeringTime = time;
+ m_centeringProgress = 0.0f;
+
+ return true;
+}
+
+// Ends a special movement of camera to frame action.
+
+bool CCamera::StopCentering(CObject *object, float time)
+{
+ if ( m_type != CAMERA_BACK ) return false;
+ if ( object != m_cameraObj ) return false;
+
+ if ( m_centeringPhase != CP_START &&
+ m_centeringPhase != CP_WAIT ) return false;
+
+ m_centeringPhase = CP_STOP;
+
+ if ( m_centeringAngleH != 99.9f )
+ {
+ m_centeringAngleH = m_centeringCurrentH;
+ }
+ if ( m_centeringAngleV != 99.9f )
+ {
+ m_centeringAngleV = m_centeringCurrentV;
+ }
+
+ m_centeringTime = time;
+ m_centeringProgress = 0.0f;
+
+ return true;
+}
+
+// Stop framing special in the current position.
+
+void CCamera::AbortCentering()
+{
+ if ( m_type == CAMERA_INFO ||
+ m_type == CAMERA_VISIT ) return;
+
+ if ( m_centeringPhase == CP_NULL ) return;
+
+ m_centeringPhase = CP_NULL;
+
+ if ( m_centeringAngleH != 99.9f )
+ {
+ m_addDirectionH = m_centeringCurrentH;
+ }
+ if ( m_centeringAngleV != 99.9f )
+ {
+ m_addDirectionV = m_centeringCurrentV;
+ }
+}
+
+
+
+// Removes the special effect with the camera
+
+void CCamera::FlushEffect()
+{
+ m_effectType = CE_NULL;
+ m_effectForce = 0.0f;
+ m_effectProgress = 0.0f;
+ m_effectOffset = Math::Vector(0.0f, 0.0f, 0.0f);
+}
+
+// Starts a special effect with the camera.
+
+void CCamera::StartEffect(CameraEffect effect, Math::Vector pos, float force)
+{
+ if ( !m_bEffect ) return;
+
+ m_effectType = effect;
+ m_effectPos = pos;
+ m_effectForce = force;
+ m_effectProgress = 0.0f;
+}
+
+// Advances the effect of the camera.
+
+void CCamera::EffectFrame(const Event &event)
+{
+ float dist, force;
+
+ if ( m_type == CAMERA_INFO ||
+ m_type == CAMERA_VISIT ) return;
+
+ if ( m_effectType == CE_NULL ) return;
+
+ m_effectOffset = Math::Vector(0.0f, 0.0f, 0.0f);
+ force = m_effectForce;
+
+ if ( m_effectType == CE_TERRAFORM )
+ {
+ m_effectProgress += event.rTime*0.7f;
+ m_effectOffset.x = (Math::Rand()-0.5f)*10.0f;
+ m_effectOffset.y = (Math::Rand()-0.5f)*10.0f;
+ m_effectOffset.z = (Math::Rand()-0.5f)*10.0f;
+
+ force *= 1.0f-m_effectProgress;
+ }
+
+ if ( m_effectType == CE_EXPLO )
+ {
+ m_effectProgress += event.rTime*1.0f;
+ m_effectOffset.x = (Math::Rand()-0.5f)*5.0f;
+ m_effectOffset.y = (Math::Rand()-0.5f)*5.0f;
+ m_effectOffset.z = (Math::Rand()-0.5f)*5.0f;
+
+ force *= 1.0f-m_effectProgress;
+ }
+
+ if ( m_effectType == CE_SHOT )
+ {
+ m_effectProgress += event.rTime*1.0f;
+ m_effectOffset.x = (Math::Rand()-0.5f)*2.0f;
+ m_effectOffset.y = (Math::Rand()-0.5f)*2.0f;
+ m_effectOffset.z = (Math::Rand()-0.5f)*2.0f;
+
+ force *= 1.0f-m_effectProgress;
+ }
+
+ if ( m_effectType == CE_CRASH )
+ {
+ m_effectProgress += event.rTime*5.0f;
+ m_effectOffset.y = sinf(m_effectProgress*Math::PI)*1.5f;
+ m_effectOffset.x = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
+ m_effectOffset.z = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
+ }
+
+ if ( m_effectType == CE_VIBRATION )
+ {
+ m_effectProgress += event.rTime*0.1f;
+ m_effectOffset.y = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
+ m_effectOffset.x = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
+ m_effectOffset.z = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
+ }
+
+ if ( m_effectType == CE_PET )
+ {
+ m_effectProgress += event.rTime*5.0f;
+ m_effectOffset.x = (Math::Rand()-0.5f)*0.2f;
+ m_effectOffset.y = (Math::Rand()-0.5f)*2.0f;
+ m_effectOffset.z = (Math::Rand()-0.5f)*0.2f;
+ }
+
+ dist = Math::Distance(m_eyePt, m_effectPos);
+ dist = Math::Norm((dist-100.f)/100.0f);
+
+ force *= 1.0f-dist;
+#if _TEEN
+ force *= 2.0f;
+#endif
+ m_effectOffset *= force;
+
+ if ( m_effectProgress >= 1.0f )
+ {
+ FlushEffect();
+ }
+}
+
+
+// Removes the effect of superposition in the foreground.
+
+void CCamera::FlushOver()
+{
+ m_overType = OE_NULL;
+ m_overColorBase.r = 0.0f; // black
+ m_overColorBase.g = 0.0f;
+ m_overColorBase.b = 0.0f;
+ m_overColorBase.a = 0.0f;
+ m_engine->SetOverColor(); // nothing
+}
+
+// Specifies the base color.
+
+void CCamera::SetOverBaseColor(D3DCOLORVALUE color)
+{
+ m_overColorBase = color;
+}
+
+// Starts a layering effect in the foreground.
+
+void CCamera::StartOver(OverEffect effect, Math::Vector pos, float force)
+{
+ D3DCOLOR color;
+ float dist, decay;
+
+ m_overType = effect;
+ m_overTime = 0.0f;
+
+ if ( m_overType == OE_BLITZ ) decay = 400.0f;
+ else decay = 100.0f;
+ dist = Math::Distance(m_eyePt, pos);
+ dist = (dist-decay)/decay;
+ if ( dist < 0.0f ) dist = 0.0f;
+ if ( dist > 1.0f ) dist = 1.0f;
+
+ m_overForce = force * (1.0f-dist);
+
+ if ( m_overType == OE_BLOOD )
+ {
+ m_overColor.r = 0.8f;
+ m_overColor.g = 0.1f;
+ m_overColor.b = 0.1f; // red
+ m_overMode = D3DSTATETCb;
+
+ m_overFadeIn = 0.4f;
+ m_overFadeOut = 0.8f;
+ m_overForce = 1.0f;
+ }
+
+ if ( m_overType == OE_FADEINw )
+ {
+ m_overColor.r = 1.0f;
+ m_overColor.g = 1.0f;
+ m_overColor.b = 1.0f; // white
+ m_overMode = D3DSTATETCb;
+
+ m_overFadeIn = 0.0f;
+ m_overFadeOut =20.0f;
+ m_overForce = 1.0f;
+ }
+
+ if ( m_overType == OE_FADEOUTw )
+ {
+ m_overColor.r = 1.0f;
+ m_overColor.g = 1.0f;
+ m_overColor.b = 1.0f; // white
+ m_overMode = D3DSTATETCb;
+
+ m_overFadeIn = 6.0f;
+ m_overFadeOut = 100000.0f;
+ m_overForce = 1.0f;
+ }
+
+ if ( m_overType == OE_FADEOUTb )
+ {
+ color = m_engine->RetFogColor(1); // fog color underwater
+ m_overColor = RetColor(color);
+ m_overMode = D3DSTATETCw;
+
+ m_overFadeIn = 4.0f;
+ m_overFadeOut = 100000.0f;
+ m_overForce = 1.0f;
+ }
+
+ if ( m_overType == OE_BLITZ )
+ {
+ m_overColor.r = 0.9f;
+ m_overColor.g = 1.0f;
+ m_overColor.b = 1.0f; // white-cyan
+ m_overMode = D3DSTATETCb;
+
+ m_overFadeIn = 0.0f;
+ m_overFadeOut = 1.0f;
+ }
+}
+
+// Advanced overlay effect in the foreground.
+
+void CCamera::OverFrame(const Event &event)
+{
+ D3DCOLORVALUE color;
+ float intensity;
+
+ if ( m_type == CAMERA_INFO ||
+ m_type == CAMERA_VISIT ) return;
+
+ if ( m_overType == OE_NULL )
+ {
+ return;
+ }
+
+ m_overTime += event.rTime;
+
+ if ( m_overType == OE_BLITZ )
+ {
+ if ( rand()%2 == 0 )
+ {
+ color.r = m_overColor.r*m_overForce;
+ color.g = m_overColor.g*m_overForce;
+ color.b = m_overColor.b*m_overForce;
+ }
+ else
+ {
+ color.r = 0.0f;
+ color.g = 0.0f;
+ color.b = 0.0f;
+ }
+ color.a = 0.0f;
+ m_engine->SetOverColor(RetColor(color), m_overMode);
+ }
+ else
+ {
+ if ( m_overFadeIn > 0.0f && m_overTime < m_overFadeIn )
+ {
+ intensity = m_overTime/m_overFadeIn;
+ intensity *= m_overForce;
+
+ if ( m_overMode == D3DSTATETCw )
+ {
+ color.r = 1.0f-(1.0f-m_overColor.r)*intensity;
+ color.g = 1.0f-(1.0f-m_overColor.g)*intensity;
+ color.b = 1.0f-(1.0f-m_overColor.b)*intensity;
+ }
+ else
+ {
+ color.r = m_overColor.r*intensity;
+ color.g = m_overColor.g*intensity;
+ color.b = m_overColor.b*intensity;
+
+ color.r = 1.0f-(1.0f-color.r)*(1.0f-m_overColorBase.r);
+ color.g = 1.0f-(1.0f-color.g)*(1.0f-m_overColorBase.g);
+ color.b = 1.0f-(1.0f-color.b)*(1.0f-m_overColorBase.b);
+ }
+ color.a = 0.0f;
+ m_engine->SetOverColor(RetColor(color), m_overMode);
+ }
+ else if ( m_overFadeOut > 0.0f && m_overTime-m_overFadeIn < m_overFadeOut )
+ {
+ intensity = 1.0f-(m_overTime-m_overFadeIn)/m_overFadeOut;
+ intensity *= m_overForce;
+
+ if ( m_overMode == D3DSTATETCw )
+ {
+ color.r = 1.0f-(1.0f-m_overColor.r)*intensity;
+ color.g = 1.0f-(1.0f-m_overColor.g)*intensity;
+ color.b = 1.0f-(1.0f-m_overColor.b)*intensity;
+ }
+ else
+ {
+ color.r = m_overColor.r*intensity;
+ color.g = m_overColor.g*intensity;
+ color.b = m_overColor.b*intensity;
+
+ color.r = 1.0f-(1.0f-color.r)*(1.0f-m_overColorBase.r);
+ color.g = 1.0f-(1.0f-color.g)*(1.0f-m_overColorBase.g);
+ color.b = 1.0f-(1.0f-color.b)*(1.0f-m_overColorBase.b);
+ }
+ color.a = 0.0f;
+ m_engine->SetOverColor(RetColor(color), m_overMode);
+ }
+ }
+
+ if ( m_overTime >= m_overFadeIn+m_overFadeOut )
+ {
+ FlushOver();
+ return;
+ }
+}
+
+
+
+// Sets the soft movement of the camera.
+
+void CCamera::FixCamera()
+{
+ m_initDelay = 0.0f;
+ m_actualEye = m_finalEye = m_scriptEye;
+ m_actualLookat = m_finalLookat = m_scriptLookat;
+ SetViewTime(m_scriptEye, m_scriptLookat, 0.0f);
+}
+
+// Specifies the location and direction of view to the 3D engine.
+
+void CCamera::SetViewTime(const Math::Vector &vEyePt,
+ const Math::Vector &vLookatPt,
+ float rTime)
+{
+ Math::Vector vUpVec, eye, lookat;
+ float prog, dist, h;
+
+ if ( m_type == CAMERA_INFO )
+ {
+ eye = vEyePt;
+ lookat = vLookatPt;
+ }
+ else
+ {
+ if ( m_initDelay > 0.0f )
+ {
+ m_initDelay -= rTime;
+ if ( m_initDelay < 0.0f ) m_initDelay = 0.0f;
+ rTime /= 1.0f+m_initDelay;
+ }
+
+ eye = vEyePt;
+ lookat = vLookatPt;
+ if ( !IsCollision(eye, lookat) )
+ {
+ m_finalEye = eye;
+ m_finalLookat = lookat;
+ }
+
+ dist = Math::Distance(m_finalEye, m_actualEye);
+ if ( m_smooth == CS_NONE ) prog = dist;
+ if ( m_smooth == CS_NORM ) prog = powf(dist, 1.5f)*rTime*0.5f;
+ if ( m_smooth == CS_HARD ) prog = powf(dist, 1.0f)*rTime*4.0f;
+ if ( m_smooth == CS_SPEC ) prog = powf(dist, 1.0f)*rTime*0.05f;
+ if ( dist == 0.0f )
+ {
+ m_actualEye = m_finalEye;
+ }
+ else
+ {
+ if ( prog > dist ) prog = dist;
+ m_actualEye = (m_finalEye-m_actualEye)/dist*prog + m_actualEye;
+ }
+
+ dist = Math::Distance(m_finalLookat, m_actualLookat);
+ if ( m_smooth == CS_NONE ) prog = dist;
+ if ( m_smooth == CS_NORM ) prog = powf(dist, 1.5f)*rTime*2.0f;
+ if ( m_smooth == CS_HARD ) prog = powf(dist, 1.0f)*rTime*4.0f;
+ if ( m_smooth == CS_SPEC ) prog = powf(dist, 1.0f)*rTime*4.0f;
+ if ( dist == 0.0f )
+ {
+ m_actualLookat = m_finalLookat;
+ }
+ else
+ {
+ if ( prog > dist ) prog = dist;
+ m_actualLookat = (m_finalLookat-m_actualLookat)/dist*prog + m_actualLookat;
+ }
+
+ eye = m_effectOffset+m_actualEye;
+ m_water->AdjustEye(eye);
+
+ h = m_terrain->RetFloorLevel(eye);
+ if ( eye.y < h+4.0f )
+ {
+ eye.y = h+4.0f;
+ }
+
+ lookat = m_effectOffset+m_actualLookat;
+ }
+
+ vUpVec = Math::Vector(0.0f, 1.0f, 0.0f);
+ SetViewParams(eye, lookat, vUpVec);
+}
+
+
+// Avoid the obstacles.
+
+bool CCamera::IsCollision(Math::Vector &eye, Math::Vector lookat)
+{
+ if ( m_type == CAMERA_BACK ) return IsCollisionBack(eye, lookat);
+ if ( m_type == CAMERA_FIX ) return IsCollisionFix(eye, lookat);
+ if ( m_type == CAMERA_PLANE ) return IsCollisionFix(eye, lookat);
+ return false;
+}
+
+// Avoid the obstacles.
+
+bool CCamera::IsCollisionBack(Math::Vector &eye, Math::Vector lookat)
+{
+#if 0
+ CObject *pObj;
+ Math::Vector oPos, min, max, proj;
+ ObjectType oType, iType;
+ float oRadius, dpp, dpl, del, dist, len, prox;
+ int i;
+
+ if ( m_cameraObj == 0 )
+ {
+ iType = OBJECT_NULL;
+ }
+ else
+ {
+ iType = m_cameraObj->RetType();
+ }
+
+ min.x = Math::Min(eye.x, lookat.x);
+ min.y = Math::Min(eye.y, lookat.y);
+ min.z = Math::Min(eye.z, lookat.z);
+
+ max.x = Math::Max(eye.x, lookat.x);
+ max.y = Math::Max(eye.y, lookat.y);
+ max.z = Math::Max(eye.z, lookat.z);
+
+ prox = 8.0f; // maximum proximity of the vehicle
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_cameraObj ) continue;
+
+ oType = pObj->RetType();
+ if ( oType == OBJECT_TOTO ||
+ oType == OBJECT_FIX ||
+ oType == OBJECT_FRET ||
+ oType == OBJECT_STONE ||
+ oType == OBJECT_URANIUM ||
+ oType == OBJECT_METAL ||
+ oType == OBJECT_POWER ||
+ oType == OBJECT_ATOMIC ||
+ oType == OBJECT_BULLET ||
+ oType == OBJECT_BBOX ||
+ oType == OBJECT_TNT ||
+ oType == OBJECT_BOMB ||
+ oType == OBJECT_WAYPOINTb ||
+ oType == OBJECT_WAYPOINTr ||
+ oType == OBJECT_WAYPOINTg ||
+ oType == OBJECT_WAYPOINTy ||
+ oType == OBJECT_WAYPOINTv ||
+ oType == OBJECT_FLAGb ||
+ oType == OBJECT_FLAGr ||
+ oType == OBJECT_FLAGg ||
+ oType == OBJECT_FLAGy ||
+ oType == OBJECT_FLAGv ||
+ oType == OBJECT_ANT ||
+ oType == OBJECT_SPIDER ||
+ oType == OBJECT_BEE ||
+ oType == OBJECT_WORM ) continue;
+
+ pObj->GetGlobalSphere(oPos, oRadius);
+ if ( oRadius <= 0.0f ) continue;
+
+ if ( oPos.x+oRadius < min.x ||
+ oPos.y+oRadius < min.y ||
+ oPos.z+oRadius < min.z ||
+ oPos.x-oRadius > max.x ||
+ oPos.y-oRadius > max.y ||
+ oPos.z-oRadius > max.z ) continue;
+
+ if ( iType == OBJECT_FACTORY )
+ {
+ dpl = Math::Distance(oPos, lookat);
+ if ( dpl < oRadius ) continue;
+ }
+
+ proj = Projection(eye, lookat, oPos);
+ dpp = Math::Distance(proj, oPos);
+ if ( dpp > oRadius ) continue;
+
+ del = Math::Distance(eye, lookat);
+ len = Math::Distance(eye, proj);
+ if ( len > del ) continue;
+
+ dist = sqrtf(oRadius*oRadius + dpp*dpp)-3.0f;
+ if ( dist < 0.0f ) dist = 0.0f;
+ proj = (lookat-eye)*dist/del + proj;
+ len = Math::Distance(eye, proj);
+
+ if ( len < del-prox )
+ {
+ eye = proj;
+ eye.y += len/5.0f;
+ return false;
+ }
+ else
+ {
+ eye = (eye-lookat)*prox/del + lookat;
+ eye.y += (del-prox)/5.0f;
+ return false;
+ }
+ }
+ return false;
+#else
+ CObject *pObj;
+ Math::Vector oPos, min, max, proj;
+ ObjectType oType, iType;
+ float oRadius, dpp, del, len, angle;
+ int i;
+
+ if ( m_cameraObj == 0 )
+ {
+ iType = OBJECT_NULL;
+ }
+ else
+ {
+ iType = m_cameraObj->RetType();
+ }
+
+ min.x = Math::Min(m_actualEye.x, m_actualLookat.x);
+ min.y = Math::Min(m_actualEye.y, m_actualLookat.y);
+ min.z = Math::Min(m_actualEye.z, m_actualLookat.z);
+
+ max.x = Math::Max(m_actualEye.x, m_actualLookat.x);
+ max.y = Math::Max(m_actualEye.y, m_actualLookat.y);
+ max.z = Math::Max(m_actualEye.z, m_actualLookat.z);
+
+ m_bTransparency = false;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetTruck() ) continue; // battery or cargo?
+
+ SetTransparency(pObj, 0.0f); // opaque object
+
+ if ( pObj == m_cameraObj ) continue;
+
+ if ( iType == OBJECT_BASE || // building?
+ iType == OBJECT_DERRICK ||
+ iType == OBJECT_FACTORY ||
+ iType == OBJECT_STATION ||
+ iType == OBJECT_CONVERT ||
+ iType == OBJECT_REPAIR ||
+ iType == OBJECT_DESTROYER||
+ iType == OBJECT_TOWER ||
+ iType == OBJECT_RESEARCH ||
+ iType == OBJECT_RADAR ||
+ iType == OBJECT_ENERGY ||
+ iType == OBJECT_LABO ||
+ iType == OBJECT_NUCLEAR ||
+ iType == OBJECT_PARA ||
+ iType == OBJECT_SAFE ||
+ iType == OBJECT_HUSTON ) continue;
+
+ oType = pObj->RetType();
+ if ( oType == OBJECT_HUMAN ||
+ oType == OBJECT_TECH ||
+ oType == OBJECT_TOTO ||
+ oType == OBJECT_FIX ||
+ oType == OBJECT_FRET ||
+ oType == OBJECT_ANT ||
+ oType == OBJECT_SPIDER ||
+ oType == OBJECT_BEE ||
+ oType == OBJECT_WORM ) continue;
+
+ pObj->GetGlobalSphere(oPos, oRadius);
+ if ( oRadius <= 2.0f ) continue; // ignores small objects
+
+ if ( oPos.x+oRadius < min.x ||
+ oPos.y+oRadius < min.y ||
+ oPos.z+oRadius < min.z ||
+ oPos.x-oRadius > max.x ||
+ oPos.y-oRadius > max.y ||
+ oPos.z-oRadius > max.z ) continue;
+
+ proj = Projection(m_actualEye, m_actualLookat, oPos);
+ dpp = Math::Distance(proj, oPos);
+ if ( dpp > oRadius ) continue;
+
+ if ( oType == OBJECT_FACTORY )
+ {
+ angle = Math::RotateAngle(m_actualEye.x-oPos.x, oPos.z-m_actualEye.z); // CW !
+ angle = Math::Direction(angle, pObj->RetAngleY(0));
+ if ( fabs(angle) < 30.0f*Math::PI/180.0f ) continue; // in the gate?
+ }
+
+ del = Math::Distance(m_actualEye, m_actualLookat);
+ if ( oType == OBJECT_FACTORY )
+ {
+ del += oRadius;
+ }
+
+ len = Math::Distance(m_actualEye, proj);
+ if ( len > del ) continue;
+
+ SetTransparency(pObj, 1.0f); // transparent object
+ m_bTransparency = true;
+ }
+ return false;
+#endif
+}
+
+// Avoid the obstacles.
+
+bool CCamera::IsCollisionFix(Math::Vector &eye, Math::Vector lookat)
+{
+ CObject *pObj;
+ Math::Vector oPos, proj;
+ ObjectType type;
+ float oRadius, dist;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_cameraObj ) continue;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_TOTO ||
+ type == OBJECT_FRET ||
+ type == OBJECT_STONE ||
+ type == OBJECT_URANIUM ||
+ type == OBJECT_METAL ||
+ type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC ||
+ type == OBJECT_BULLET ||
+ type == OBJECT_BBOX ||
+ type == OBJECT_KEYa ||
+ type == OBJECT_KEYb ||
+ type == OBJECT_KEYc ||
+ type == OBJECT_KEYd ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ) continue;
+
+ pObj->GetGlobalSphere(oPos, oRadius);
+ if ( oRadius == 0.0f ) continue;
+
+ dist = Math::Distance(eye, oPos);
+ if ( dist < oRadius )
+ {
+ dist = Math::Distance(eye, lookat);
+ proj = Projection(eye, lookat, oPos);
+ eye = (lookat-eye)*oRadius/dist + proj;
+ return false;
+ }
+ }
+ return false;
+}
+
+
+// Management of an event.
+
+bool CCamera::EventProcess(const Event &event)
+{
+ switch( event.event )
+ {
+ case EVENT_FRAME:
+ EventFrame(event);
+ break;
+
+#if 0
+ case EVENT_RBUTTONDOWN:
+ m_bRightDown = true;
+ m_rightPosInit = event.pos;
+ m_rightPosCenter = Math::Point(0.5f, 0.5f);
+ m_engine->MoveMousePos(m_rightPosCenter);
+//? m_engine->SetMouseHide(true); // cache la souris
+ break;
+
+ case EVENT_RBUTTONUP:
+ m_bRightDown = false;
+ m_engine->MoveMousePos(m_rightPosInit);
+//? m_engine->SetMouseHide(false); // remontre la souris
+ m_addDirectionH = 0.0f;
+ m_addDirectionV = -Math::PI*0.05f;
+ break;
+#endif
+
+ case EVENT_MOUSEMOVE:
+ EventMouseMove(event);
+ break;
+
+ case EVENT_KEYDOWN:
+ if ( event.param == VK_WHEELUP ) EventMouseWheel(+1);
+ if ( event.param == VK_WHEELDOWN ) EventMouseWheel(-1);
+ break;
+ }
+ return true;
+}
+
+// Changed the camera according to the mouse moved.
+
+bool CCamera::EventMouseMove(const Event &event)
+{
+ m_mousePos = event.pos;
+ return true;
+}
+
+// Mouse wheel operated.
+
+void CCamera::EventMouseWheel(int dir)
+{
+ if ( m_type == CAMERA_BACK )
+ {
+ if ( dir > 0 )
+ {
+ m_backDist -= 8.0f;
+ if ( m_backDist < m_backMin ) m_backDist = m_backMin;
+ }
+ if ( dir < 0 )
+ {
+ m_backDist += 8.0f;
+ if ( m_backDist > 200.0f ) m_backDist = 200.0f;
+ }
+ }
+
+ if ( m_type == CAMERA_FIX ||
+ m_type == CAMERA_PLANE )
+ {
+ if ( dir > 0 )
+ {
+ m_fixDist -= 8.0f;
+ if ( m_fixDist < 10.0f ) m_fixDist = 10.0f;
+ }
+ if ( dir < 0 )
+ {
+ m_fixDist += 8.0f;
+ if ( m_fixDist > 200.0f ) m_fixDist = 200.0f;
+ }
+ }
+
+ if ( m_type == CAMERA_VISIT )
+ {
+ if ( dir > 0 )
+ {
+ m_visitDist -= 8.0f;
+ if ( m_visitDist < 20.0f ) m_visitDist = 20.0f;
+ }
+ if ( dir < 0 )
+ {
+ m_visitDist += 8.0f;
+ if ( m_visitDist > 200.0f ) m_visitDist = 200.0f;
+ }
+ }
+}
+
+// Changed the camera according to the time elapsed.
+
+bool CCamera::EventFrame(const Event &event)
+{
+ EffectFrame(event);
+ OverFrame(event);
+
+ if ( m_type == CAMERA_FREE )
+ {
+ return EventFrameFree(event);
+ }
+ if ( m_type == CAMERA_EDIT )
+ {
+ return EventFrameEdit(event);
+ }
+ if ( m_type == CAMERA_DIALOG )
+ {
+ return EventFrameDialog(event);
+ }
+ if ( m_type == CAMERA_BACK )
+ {
+ return EventFrameBack(event);
+ }
+ if ( m_type == CAMERA_FIX ||
+ m_type == CAMERA_PLANE )
+ {
+ return EventFrameFix(event);
+ }
+ if ( m_type == CAMERA_EXPLO )
+ {
+ return EventFrameExplo(event);
+ }
+ if ( m_type == CAMERA_ONBOARD )
+ {
+ return EventFrameOnBoard(event);
+ }
+ if ( m_type == CAMERA_SCRIPT )
+ {
+ return EventFrameScript(event);
+ }
+ if ( m_type == CAMERA_INFO )
+ {
+ return EventFrameInfo(event);
+ }
+ if ( m_type == CAMERA_VISIT )
+ {
+ return EventFrameVisit(event);
+ }
+
+ return true;
+}
+
+
+// Returns the default sprite to use for the mouse.
+
+D3DMouse CCamera::RetMouseDef(Math::Point pos)
+{
+ D3DMouse type;
+
+ type = D3DMOUSENORM;
+ m_mousePos = pos;
+
+ if ( m_type == CAMERA_INFO ) return type;
+
+ if ( m_bRightDown ) // the right button pressed?
+ {
+ m_rightPosMove.x = pos.x - m_rightPosCenter.x;
+ m_rightPosMove.y = pos.y - m_rightPosCenter.y;
+ type = D3DMOUSEMOVE;
+ }
+ else
+ {
+ if ( !m_bCameraScroll ) return type;
+
+ m_mouseDirH = 0.0f;
+ m_mouseDirV = 0.0f;
+
+ if ( pos.x < m_mouseMarging )
+ {
+ m_mouseDirH = pos.x/m_mouseMarging - 1.0f;
+ }
+
+ if ( pos.x > 1.0f-m_mouseMarging )
+ {
+ m_mouseDirH = 1.0f - (1.0f-pos.x)/m_mouseMarging;
+ }
+
+ if ( pos.y < m_mouseMarging )
+ {
+ m_mouseDirV = pos.y/m_mouseMarging - 1.0f;
+ }
+
+ if ( pos.y > 1.0f-m_mouseMarging )
+ {
+ m_mouseDirV = 1.0f - (1.0f-pos.y)/m_mouseMarging;
+ }
+
+ if ( m_type == CAMERA_FREE ||
+ m_type == CAMERA_EDIT ||
+ m_type == CAMERA_BACK ||
+ m_type == CAMERA_FIX ||
+ m_type == CAMERA_PLANE ||
+ m_type == CAMERA_EXPLO )
+ {
+ if ( m_mouseDirH > 0.0f )
+ {
+ type = D3DMOUSESCROLLR;
+ }
+ if ( m_mouseDirH < 0.0f )
+ {
+ type = D3DMOUSESCROLLL;
+ }
+ }
+
+ if ( m_type == CAMERA_FREE ||
+ m_type == CAMERA_EDIT )
+ {
+ if ( m_mouseDirV > 0.0f )
+ {
+ type = D3DMOUSESCROLLU;
+ }
+ if ( m_mouseDirV < 0.0f )
+ {
+ type = D3DMOUSESCROLLD;
+ }
+ }
+
+ if ( m_bCameraInvertX )
+ {
+ m_mouseDirH = -m_mouseDirH;
+ }
+ }
+
+ return type;
+}
+
+
+
+// Moves the point of view.
+
+bool CCamera::EventFrameFree(const Event &event)
+{
+ Math::Vector pos, vLookatPt;
+ float factor;
+
+ factor = m_heightEye*0.5f+30.0f;
+
+ if ( m_mouseDirH != 0.0f )
+ {
+ m_directionH -= m_mouseDirH*event.rTime*0.7f*m_speed;
+ }
+ if ( m_mouseDirV != 0.0f )
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, m_mouseDirV*event.rTime*factor*m_speed);
+ }
+
+ // Up/Down.
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, event.axeY*event.rTime*factor*m_speed);
+
+ // Left/Right.
+ if ( event.keyState & KS_CONTROL )
+ {
+ if ( event.axeX < 0.0f )
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH+Math::PI/2.0f, m_directionV, -event.axeX*event.rTime*factor*m_speed);
+ }
+ if ( event.axeX > 0.0f )
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH-Math::PI/2.0f, m_directionV, event.axeX*event.rTime*factor*m_speed);
+ }
+ }
+ else
+ {
+ m_directionH -= event.axeX*event.rTime*0.7f*m_speed;
+ }
+
+ // PageUp/PageDown.
+ if ( event.keyState & KS_NUMMINUS )
+ {
+ if ( m_heightEye < 500.0f )
+ {
+ m_heightEye += event.rTime*factor*m_speed;
+ }
+ }
+ if ( event.keyState & KS_NUMPLUS )
+ {
+ if ( m_heightEye > -2.0f )
+ {
+ m_heightEye -= event.rTime*factor*m_speed;
+ }
+ }
+
+ m_terrain->ValidPosition(m_eyePt, 10.0f);
+
+ if ( m_terrain->MoveOnFloor(m_eyePt, true) )
+ {
+ m_eyePt.y += m_heightEye;
+
+ pos = m_eyePt;
+ if ( m_terrain->MoveOnFloor(pos, true) )
+ {
+ pos.y -= 2.0f;
+ if ( m_eyePt.y < pos.y )
+ {
+ m_eyePt.y = pos.y;
+ }
+ }
+
+ }
+
+ vLookatPt = Math::LookatPoint( m_eyePt, m_directionH, m_directionV, 50.0f );
+
+ if ( m_terrain->MoveOnFloor(vLookatPt, true) )
+ {
+ vLookatPt.y += m_heightLookat;
+ }
+
+ SetViewTime(m_eyePt, vLookatPt, event.rTime);
+
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameEdit(const Event &event)
+{
+ Math::Vector pos, vLookatPt;
+ float factor;
+
+ factor = m_editHeight*0.5f+30.0f;
+
+ if ( m_mouseDirH != 0.0f )
+ {
+ m_directionH -= m_mouseDirH*event.rTime*0.7f*m_speed;
+ }
+ if ( m_mouseDirV != 0.0f )
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, m_mouseDirV*event.rTime*factor*m_speed);
+ }
+
+ if ( m_bCameraScroll )
+ {
+ // Left/Right.
+ m_fixDirectionH += m_mouseDirH*event.rTime*1.0f*m_speed;
+ m_fixDirectionH = Math::NormAngle(m_fixDirectionH);
+
+ // Up/Down.
+//? m_fixDirectionV -= m_mouseDirV*event.rTime*0.5f*m_speed;
+//? if ( m_fixDirectionV < -Math::PI*0.40f ) m_fixDirectionV = -Math::PI*0.40f;
+//? if ( m_fixDirectionV > Math::PI*0.20f ) m_fixDirectionV = Math::PI*0.20f;
+ }
+
+ m_terrain->ValidPosition(m_eyePt, 10.0f);
+
+ if ( m_terrain->MoveOnFloor(m_eyePt, false) )
+ {
+ m_eyePt.y += m_editHeight;
+
+ pos = m_eyePt;
+ if ( m_terrain->MoveOnFloor(pos, false) )
+ {
+ pos.y += 2.0f;
+ if ( m_eyePt.y < pos.y )
+ {
+ m_eyePt.y = pos.y;
+ }
+ }
+
+ }
+
+ vLookatPt = Math::LookatPoint( m_eyePt, m_directionH, m_directionV, 50.0f );
+
+ if ( m_terrain->MoveOnFloor(vLookatPt, true) )
+ {
+ vLookatPt.y += m_heightLookat;
+ }
+
+ SetViewTime(m_eyePt, vLookatPt, event.rTime);
+
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameDialog(const Event &event)
+{
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameBack(const Event &event)
+{
+ CPhysics* physics;
+ ObjectType type;
+ Math::Vector pos, vLookatPt;
+ Math::Point mouse;
+ float centeringH, centeringV, centeringD, h, v, d, floor;
+
+ if ( m_cameraObj == 0 )
+ {
+ type = OBJECT_NULL;
+ }
+ else
+ {
+ type = m_cameraObj->RetType();
+ }
+
+ // +/-.
+ if ( event.keyState & KS_NUMPLUS )
+ {
+ m_backDist -= event.rTime*30.0f*m_speed;
+ if ( m_backDist < m_backMin ) m_backDist = m_backMin;
+ }
+ if ( event.keyState & KS_NUMMINUS )
+ {
+ m_backDist += event.rTime*30.0f*m_speed;
+ if ( m_backDist > 200.0f ) m_backDist = 200.0f;
+ }
+
+ m_motorTurn = 0.0f;
+
+ if ( m_bRightDown )
+ {
+ m_addDirectionH = m_rightPosMove.x*6.0f;
+ m_addDirectionV = -m_rightPosMove.y*2.0f;
+ }
+ else
+ {
+ if ( m_bCameraScroll )
+ {
+#if 1
+ // Left/Right.
+ m_addDirectionH += m_mouseDirH*event.rTime*1.0f*m_speed;
+ m_addDirectionH = Math::NormAngle(m_addDirectionH);
+
+ // Up/Down.
+//? m_backDist -= m_mouseDirV*event.rTime*30.0f*m_speed;
+//? if ( m_backDist < 10.0f ) m_backDist = 10.0f;
+//? if ( m_backDist > 200.0f ) m_backDist = 200.0f;
+#else
+ if ( m_mousePos.y >= 0.18f && m_mousePos.y <= 0.93f )
+ {
+//? m_addDirectionH = -(m_mousePos.x-0.5f)*4.0f;
+ m_addDirectionV = (m_mousePos.y-0.5f)*2.0f;
+//? if ( m_bCameraInvertX ) m_addDirectionH = -m_addDirectionH;
+ if ( m_bCameraInvertY ) m_addDirectionV = -m_addDirectionV;
+
+ if ( m_mousePos.x < 0.5f ) m_motorTurn = -1.0f;
+ if ( m_mousePos.x > 0.5f ) m_motorTurn = 1.0f;
+
+ mouse = m_mousePos;
+ mouse.x = 0.5f;
+ m_engine->MoveMousePos(mouse);
+ }
+ else
+ {
+ m_addDirectionH = 0.0f;
+ m_addDirectionV = 0.0f;
+ }
+#endif
+ }
+ }
+
+ if ( m_mouseDirH != 0 || m_mouseDirV != 0 )
+ {
+ AbortCentering(); // special stops framing
+ }
+
+ // Increase the special framework.
+ centeringH = 0.0f;
+ centeringV = 0.0f;
+ centeringD = 0.0f;
+
+ if ( m_centeringPhase == CP_START )
+ {
+ m_centeringProgress += event.rTime/m_centeringTime;
+ if ( m_centeringProgress > 1.0f ) m_centeringProgress = 1.0f;
+ centeringH = m_centeringProgress;
+ centeringV = m_centeringProgress;
+ centeringD = m_centeringProgress;
+ if ( m_centeringProgress >= 1.0f )
+ {
+ m_centeringPhase = CP_WAIT;
+ }
+ }
+
+ if ( m_centeringPhase == CP_WAIT )
+ {
+ centeringH = 1.0f;
+ centeringV = 1.0f;
+ centeringD = 1.0f;
+ }
+
+ if ( m_centeringPhase == CP_STOP )
+ {
+ m_centeringProgress += event.rTime/m_centeringTime;
+ if ( m_centeringProgress > 1.0f ) m_centeringProgress = 1.0f;
+ centeringH = 1.0f-m_centeringProgress;
+ centeringV = 1.0f-m_centeringProgress;
+ centeringD = 1.0f-m_centeringProgress;
+ if ( m_centeringProgress >= 1.0f )
+ {
+ m_centeringPhase = CP_NULL;
+ }
+ }
+
+ if ( m_centeringAngleH == 99.9f ) centeringH = 0.0f;
+ if ( m_centeringAngleV == 99.9f ) centeringV = 0.0f;
+ if ( m_centeringDist == 0.0f ) centeringD = 0.0f;
+
+ if ( m_cameraObj != 0 )
+ {
+ vLookatPt = m_cameraObj->RetPosition(0);
+ if ( type == OBJECT_BASE ) vLookatPt.y += 40.0f;
+ else if ( type == OBJECT_HUMAN ) vLookatPt.y += 1.0f;
+ else if ( type == OBJECT_TECH ) vLookatPt.y += 1.0f;
+ else vLookatPt.y += 4.0f;
+
+ h = -m_cameraObj->RetAngleY(0); // angle vehicle / building
+
+ if ( 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 ||
+ type == OBJECT_START ||
+ type == OBJECT_END ) // building?
+ {
+ h += Math::PI*0.20f; // nearly face
+ }
+ else // vehicle?
+ {
+ h += Math::PI; // back
+ }
+ h = Math::NormAngle(h)+m_remotePan;
+ v = 0.0f; //?
+
+ h += m_centeringCurrentH;
+ h += m_addDirectionH*(1.0f-centeringH);
+ h = Math::NormAngle(h);
+
+ if ( type == OBJECT_MOBILEdr ) // designer?
+ {
+ v -= 0.3f; // Camera top
+ }
+
+ v += m_centeringCurrentV;
+ v += m_addDirectionV*(1.0f-centeringV);
+
+ d = m_backDist;
+ d += m_centeringDist*centeringD;
+
+ m_centeringCurrentH = m_centeringAngleH*centeringH;
+ m_centeringCurrentV = m_centeringAngleV*centeringV;
+
+ m_eyePt = RotateView(vLookatPt, h, v, d);
+
+ physics = m_cameraObj->RetPhysics();
+ if ( physics != 0 && physics->RetLand() ) // ground?
+ {
+ pos = vLookatPt+(vLookatPt-m_eyePt);
+ floor = m_terrain->RetFloorHeight(pos)-4.0f;
+ if ( floor > 0.0f )
+ {
+ m_eyePt.y += floor; // shows the descent in front
+ }
+ }
+
+ m_eyePt = ExcludeTerrain(m_eyePt, vLookatPt, h, v);
+ m_eyePt = ExcludeObject(m_eyePt, vLookatPt, h, v);
+
+ SetViewTime(m_eyePt, vLookatPt, event.rTime);
+
+ m_directionH = h+Math::PI/2.0f;
+ m_directionV = v;
+ }
+
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameFix(const Event &event)
+{
+ Math::Vector pos, vLookatPt;
+ float h, v, d;
+
+ // +/-.
+ if ( event.keyState & KS_NUMPLUS )
+ {
+ m_fixDist -= event.rTime*30.0f*m_speed;
+ if ( m_fixDist < 10.0f ) m_fixDist = 10.0f;
+ }
+ if ( event.keyState & KS_NUMMINUS )
+ {
+ m_fixDist += event.rTime*30.0f*m_speed;
+ if ( m_fixDist > 200.0f ) m_fixDist = 200.0f;
+ }
+
+ if ( m_bCameraScroll )
+ {
+ // Left/Right.
+ m_fixDirectionH += m_mouseDirH*event.rTime*1.0f*m_speed;
+ m_fixDirectionH = Math::NormAngle(m_fixDirectionH);
+
+ // Up/Down.
+//? m_fixDist -= m_mouseDirV*event.rTime*30.0f*m_speed;
+//? if ( m_fixDist < 10.0f ) m_fixDist = 10.0f;
+//? if ( m_fixDist > 200.0f ) m_fixDist = 200.0f;
+ }
+
+ if ( m_mouseDirH != 0 || m_mouseDirV != 0 )
+ {
+ AbortCentering(); // special stops framing
+ }
+
+ if ( m_cameraObj != 0 )
+ {
+ vLookatPt = m_cameraObj->RetPosition(0);
+
+ h = m_fixDirectionH+m_remotePan;
+ v = m_fixDirectionV;
+
+ d = m_fixDist;
+//- if ( m_type == CAMERA_PLANE ) d += 20.0f;
+ m_eyePt = RotateView(vLookatPt, h, v, d);
+//- if ( m_type == CAMERA_PLANE ) m_eyePt.y += 50.0f;
+ if ( m_type == CAMERA_PLANE ) m_eyePt.y += m_fixDist/2.0f;
+ m_eyePt = ExcludeTerrain(m_eyePt, vLookatPt, h, v);
+ m_eyePt = ExcludeObject(m_eyePt, vLookatPt, h, v);
+
+ SetViewTime(m_eyePt, vLookatPt, event.rTime);
+
+ m_directionH = h+Math::PI/2.0f;
+ m_directionV = v;
+ }
+
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameExplo(const Event &event)
+{
+ Math::Vector pos, vLookatPt;
+ float factor;
+
+ factor = m_heightEye*0.5f+30.0f;
+
+ if ( m_mouseDirH != 0.0f )
+ {
+ m_directionH -= m_mouseDirH*event.rTime*0.7f*m_speed;
+ }
+
+ m_terrain->ValidPosition(m_eyePt, 10.0f);
+
+ if ( m_terrain->MoveOnFloor(m_eyePt, false) )
+ {
+ m_eyePt.y += m_heightEye;
+
+ pos = m_eyePt;
+ if ( m_terrain->MoveOnFloor(pos, false) )
+ {
+ pos.y += 2.0f;
+ if ( m_eyePt.y < pos.y )
+ {
+ m_eyePt.y = pos.y;
+ }
+ }
+
+ }
+
+ vLookatPt = Math::LookatPoint( m_eyePt, m_directionH, m_directionV, 50.0f );
+
+ if ( m_terrain->MoveOnFloor(vLookatPt, true) )
+ {
+ vLookatPt.y += m_heightLookat;
+ }
+
+ SetViewTime(m_eyePt, vLookatPt, event.rTime);
+
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameOnBoard(const Event &event)
+{
+ Math::Vector vLookatPt, vUpVec, eye, lookat, pos;
+
+ if ( m_cameraObj != 0 )
+ {
+ m_cameraObj->SetViewFromHere(m_eyePt, m_directionH, m_directionV,
+ vLookatPt, vUpVec, m_type);
+ eye = m_effectOffset*0.3f+m_eyePt;
+ lookat = m_effectOffset*0.3f+vLookatPt;
+
+ SetViewParams(eye, lookat, vUpVec);
+ m_actualEye = eye;
+ m_actualLookat = lookat;
+ }
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameInfo(const Event &event)
+{
+ SetViewTime(Math::Vector(0.0f, 0.0f, 0.0f),
+ Math::Vector(0.0f, 0.0f, 1.0f),
+ event.rTime);
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameVisit(const Event &event)
+{
+ Math::Vector eye;
+ float angleH, angleV;
+
+ m_visitTime += event.rTime;
+
+ // +/-.
+ if ( event.keyState & KS_NUMPLUS )
+ {
+ m_visitDist -= event.rTime*50.0f*m_speed;
+ if ( m_visitDist < 20.0f ) m_visitDist = 20.0f;
+ }
+ if ( event.keyState & KS_NUMMINUS )
+ {
+ m_visitDist += event.rTime*50.0f*m_speed;
+ if ( m_visitDist > 200.0f ) m_visitDist = 200.0f;
+ }
+
+ // PageUp/Down.
+ if ( event.keyState & KS_PAGEUP )
+ {
+ m_visitDirectionV -= event.rTime*1.0f*m_speed;
+ if ( m_visitDirectionV < -Math::PI*0.40f ) m_visitDirectionV = -Math::PI*0.40f;
+ }
+ if ( event.keyState & KS_PAGEDOWN )
+ {
+ m_visitDirectionV += event.rTime*1.0f*m_speed;
+ if ( m_visitDirectionV > 0.0f ) m_visitDirectionV = 0.0f;
+ }
+
+ if ( m_bCameraScroll )
+ {
+ m_visitDist -= m_mouseDirV*event.rTime*30.0f*m_speed;
+ if ( m_visitDist < 20.0f ) m_visitDist = 20.0f;
+ if ( m_visitDist > 200.0f ) m_visitDist = 200.0f;
+ }
+
+ angleH = (m_visitTime/10.0f)*(Math::PI*2.0f);
+ angleV = m_visitDirectionV;
+ eye = RotateView(m_visitGoal, angleH, angleV, m_visitDist);
+ eye = ExcludeTerrain(eye, m_visitGoal, angleH, angleV);
+ eye = ExcludeObject(eye, m_visitGoal, angleH, angleV);
+ SetViewTime(eye, m_visitGoal, event.rTime);
+
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameScript(const Event &event)
+{
+ SetViewTime(m_scriptEye+m_effectOffset,
+ m_scriptLookat+m_effectOffset, event.rTime);
+ return true;
+}
+
+void CCamera::SetScriptEye(Math::Vector eye)
+{
+ m_scriptEye = eye;
+}
+
+void CCamera::SetScriptLookat(Math::Vector lookat)
+{
+ m_scriptLookat = lookat;
+}
+
+
+// Specifies the location and direction of view.
+
+void CCamera::SetViewParams(const Math::Vector &eye, const Math::Vector &lookat,
+ const Math::Vector &up)
+{
+ bool bUnder;
+
+ m_engine->SetViewParams(eye, lookat, up, m_eyeDistance);
+
+ bUnder = (eye.y < m_water->RetLevel()); // Is it underwater?
+ if ( m_type == CAMERA_INFO ) bUnder = false;
+ m_engine->SetRankView(bUnder?1:0);
+}
+
+
+// Adjusts the camera not to enter the field.
+
+Math::Vector CCamera::ExcludeTerrain(Math::Vector eye, Math::Vector lookat,
+ float &angleH, float &angleV)
+{
+ Math::Vector pos;
+ float dist;
+
+ pos = eye;
+ if ( m_terrain->MoveOnFloor(pos) )
+ {
+ dist = Math::DistanceProjected(lookat, pos);
+ pos.y += 2.0f+dist*0.1f;
+ if ( pos.y > eye.y )
+ {
+ angleV = -Math::RotateAngle(dist, pos.y-lookat.y);
+ eye = RotateView(lookat, angleH, angleV, dist);
+ }
+ }
+ return eye;
+}
+
+// Adjusts the camera not to enter an object.
+
+Math::Vector CCamera::ExcludeObject(Math::Vector eye, Math::Vector lookat,
+ float &angleH, float &angleV)
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ float oRad, dist;
+ int i, j;
+
+return eye;
+//?
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRad) )
+ {
+ dist = Math::Distance(oPos, eye);
+ if ( dist < oRad+2.0f )
+ {
+ eye.y = oPos.y+oRad+2.0f;
+ }
+ }
+ }
+
+ return eye;
+}
+
+
diff --git a/src/old/camera.h b/src/old/camera.h
index f18f765..98e5420 100644
--- a/src/old/camera.h
+++ b/src/old/camera.h
@@ -1,269 +1,269 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// camera.h
-
-#pragma once
-
-
-#include "common/event.h"
-#include "math/point.h"
-#include "old/d3dengine.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CTerrain;
-class CWater;
-class CObject;
-
-
-enum CameraType
-{
- CAMERA_NULL = 0, // camera undefined
- CAMERA_FREE = 1, // camera free (never in principle)
- CAMERA_EDIT = 2, // camera while editing a program
- CAMERA_ONBOARD = 3, // camera on board a robot
- CAMERA_BACK = 4, // camera behind a robot
- CAMERA_FIX = 5, // static camera following robot
- CAMERA_EXPLO = 6, // camera steady after explosion
- CAMERA_SCRIPT = 7, // camera during a film script
- CAMERA_INFO = 8, // camera for displaying information
- CAMERA_VISIT = 9, // visit instead of an error
- CAMERA_DIALOG = 10, // camera for dialogue
- CAMERA_PLANE = 11, // static camera height
-};
-
-enum CameraSmooth
-{
- CS_NONE = 0, // sharp
- CS_NORM = 1, // normal
- CS_HARD = 2, // hard
- CS_SPEC = 3, // special
-};
-
-enum CenteringPhase
-{
- CP_NULL = 0,
- CP_START = 1,
- CP_WAIT = 2,
- CP_STOP = 3,
-};
-
-enum CameraEffect
-{
- CE_NULL = 0, // no effect
- CE_TERRAFORM = 1, // digging in
- CE_CRASH = 2, // Vehicle driving is severely
- CE_EXPLO = 3, // explosion
- CE_SHOT = 4, // not mortal shot
- CE_VIBRATION = 5, // vibration during construction
- CE_PET = 6, // spleen reactor
-};
-
-enum OverEffect
-{
- OE_NULL = 0, // no effect
- OE_BLOOD = 1, // flash red
- OE_FADEINw = 2, // white -> nothing
- OE_FADEOUTw = 3, // nothing -> white
- OE_FADEOUTb = 4, // nothing -> blue
- OE_BLITZ = 5, // lightning
-};
-
-
-
-class CCamera
-{
-public:
- CCamera(CInstanceManager* iMan);
- ~CCamera();
-
- bool EventProcess(const Event &event);
-
- void Init(Math::Vector eye, Math::Vector lookat, float delay);
-
- void SetObject(CObject* object);
- CObject* RetObject();
-
- void SetType(CameraType type);
- CameraType RetType();
-
- void SetSmooth(CameraSmooth type);
- CameraSmooth RetSmoth();
-
- void SetDist(float dist);
- float RetDist();
-
- void SetFixDirection(float angle);
- float RetFixDirection();
-
- void SetRemotePan(float value);
- float RetRemotePan();
-
- void SetRemoteZoom(float value);
- float RetRemoteZoom();
-
- void StartVisit(Math::Vector goal, float dist);
- void StopVisit();
-
- void RetCamera(Math::Vector &eye, Math::Vector &lookat);
-
- bool StartCentering(CObject *object, float angleH, float angleV, float dist, float time);
- bool StopCentering(CObject *object, float time);
- void AbortCentering();
-
- void FlushEffect();
- void StartEffect(CameraEffect effect, Math::Vector pos, float force);
-
- void FlushOver();
- void SetOverBaseColor(D3DCOLORVALUE color);
- void StartOver(OverEffect effect, Math::Vector pos, float force);
-
- void FixCamera();
- void SetScriptEye(Math::Vector eye);
- void SetScriptLookat(Math::Vector lookat);
-
- void SetEffect(bool bEnable);
- void SetCameraScroll(bool bScroll);
- void SetCameraInvertX(bool bInvert);
- void SetCameraInvertY(bool bInvert);
-
- float RetMotorTurn();
- D3DMouse RetMouseDef(Math::Point pos);
-
-protected:
- bool EventMouseMove(const Event &event);
- void EventMouseWheel(int dir);
- bool EventFrame(const Event &event);
- bool EventFrameFree(const Event &event);
- bool EventFrameEdit(const Event &event);
- bool EventFrameDialog(const Event &event);
- bool EventFrameBack(const Event &event);
- bool EventFrameFix(const Event &event);
- bool EventFrameExplo(const Event &event);
- bool EventFrameOnBoard(const Event &event);
- bool EventFrameInfo(const Event &event);
- bool EventFrameVisit(const Event &event);
- bool EventFrameScript(const Event &event);
-
- void SetViewTime(const Math::Vector &vEyePt, const Math::Vector &vLookatPt, float rTime);
- bool IsCollision(Math::Vector &eye, Math::Vector lookat);
- bool IsCollisionBack(Math::Vector &eye, Math::Vector lookat);
- bool IsCollisionFix(Math::Vector &eye, Math::Vector lookat);
-
- Math::Vector ExcludeTerrain(Math::Vector eye, Math::Vector lookat, float &angleH, float &angleV);
- Math::Vector ExcludeObject(Math::Vector eye, Math::Vector lookat, float &angleH, float &angleV);
-
- void SetViewParams(const Math::Vector &eye, const Math::Vector &lookat, const Math::Vector &up);
- void EffectFrame(const Event &event);
- void OverFrame(const Event &event);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CTerrain* m_terrain;
- CWater* m_water;
-
- CameraType m_type; // the type of camera (CAMERA *)
- CameraSmooth m_smooth; // type of smoothing
- CObject* m_cameraObj; // object linked to the camera
-
- float m_eyeDistance; // distance between the eyes
- float m_initDelay; // time of initial centering
-
- Math::Vector m_actualEye; // current eye
- Math::Vector m_actualLookat; // aim current
- Math::Vector m_finalEye; // final eye
- Math::Vector m_finalLookat; // aim final
- Math::Vector m_normEye; // normal eye
- Math::Vector m_normLookat; // aim normal
- float m_focus;
-
- bool m_bRightDown;
- Math::Point m_rightPosInit;
- Math::Point m_rightPosCenter;
- Math::Point m_rightPosMove;
-
- Math::Vector m_eyePt; // CAMERA_FREE: eye
- float m_directionH; // CAMERA_FREE: horizontal direction
- float m_directionV; // CAMERA_FREE: vertical direction
- float m_heightEye; // CAMERA_FREE: height above the ground
- float m_heightLookat; // CAMERA_FREE: height above the ground
- float m_speed; // CAMERA_FREE: speed of movement
-
- float m_backDist; // CAMERA_BACK: distance
- float m_backMin; // CAMERA_BACK: distance minimal
- float m_addDirectionH; // CAMERA_BACK: additional direction
- float m_addDirectionV; // CAMERA_BACK: additional direction
- bool m_bTransparency;
-
- float m_fixDist; // CAMERA_FIX: distance
- float m_fixDirectionH; // CAMERA_FIX: direction
- float m_fixDirectionV; // CAMERA_FIX: direction
-
- Math::Vector m_visitGoal; // CAMERA_VISIT: target position
- float m_visitDist; // CAMERA_VISIT: distance
- float m_visitTime; // CAMERA_VISIT: relative time
- CameraType m_visitType; // CAMERA_VISIT: initial type
- float m_visitDirectionH; // CAMERA_VISIT: direction
- float m_visitDirectionV; // CAMERA_VISIT: direction
-
- float m_editHeight; // CAMERA_EDIT: height
-
- float m_remotePan;
- float m_remoteZoom;
-
- Math::Point m_mousePos;
- float m_mouseDirH;
- float m_mouseDirV;
- float m_mouseMarging;
-
- float m_motorTurn;
-
- CenteringPhase m_centeringPhase;
- float m_centeringAngleH;
- float m_centeringAngleV;
- float m_centeringDist;
- float m_centeringCurrentH;
- float m_centeringCurrentV;
- float m_centeringTime;
- float m_centeringProgress;
-
- CameraEffect m_effectType;
- Math::Vector m_effectPos;
- float m_effectForce;
- float m_effectProgress;
- Math::Vector m_effectOffset;
-
- OverEffect m_overType;
- float m_overForce;
- float m_overTime;
- D3DCOLORVALUE m_overColorBase;
- D3DCOLORVALUE m_overColor;
- int m_overMode;
- float m_overFadeIn;
- float m_overFadeOut;
-
- Math::Vector m_scriptEye;
- Math::Vector m_scriptLookat;
-
- bool m_bEffect; // shocks if explosion?
- bool m_bCameraScroll; // scroll in the edges?
- bool m_bCameraInvertX; // X inversion in the edges?
- bool m_bCameraInvertY; // Y inversion in the edges?
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// camera.h
+
+#pragma once
+
+
+#include "common/event.h"
+#include "math/point.h"
+#include "old/d3dengine.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CTerrain;
+class CWater;
+class CObject;
+
+
+enum CameraType
+{
+ CAMERA_NULL = 0, // camera undefined
+ CAMERA_FREE = 1, // camera free (never in principle)
+ CAMERA_EDIT = 2, // camera while editing a program
+ CAMERA_ONBOARD = 3, // camera on board a robot
+ CAMERA_BACK = 4, // camera behind a robot
+ CAMERA_FIX = 5, // static camera following robot
+ CAMERA_EXPLO = 6, // camera steady after explosion
+ CAMERA_SCRIPT = 7, // camera during a film script
+ CAMERA_INFO = 8, // camera for displaying information
+ CAMERA_VISIT = 9, // visit instead of an error
+ CAMERA_DIALOG = 10, // camera for dialogue
+ CAMERA_PLANE = 11, // static camera height
+};
+
+enum CameraSmooth
+{
+ CS_NONE = 0, // sharp
+ CS_NORM = 1, // normal
+ CS_HARD = 2, // hard
+ CS_SPEC = 3, // special
+};
+
+enum CenteringPhase
+{
+ CP_NULL = 0,
+ CP_START = 1,
+ CP_WAIT = 2,
+ CP_STOP = 3,
+};
+
+enum CameraEffect
+{
+ CE_NULL = 0, // no effect
+ CE_TERRAFORM = 1, // digging in
+ CE_CRASH = 2, // Vehicle driving is severely
+ CE_EXPLO = 3, // explosion
+ CE_SHOT = 4, // not mortal shot
+ CE_VIBRATION = 5, // vibration during construction
+ CE_PET = 6, // spleen reactor
+};
+
+enum OverEffect
+{
+ OE_NULL = 0, // no effect
+ OE_BLOOD = 1, // flash red
+ OE_FADEINw = 2, // white -> nothing
+ OE_FADEOUTw = 3, // nothing -> white
+ OE_FADEOUTb = 4, // nothing -> blue
+ OE_BLITZ = 5, // lightning
+};
+
+
+
+class CCamera
+{
+public:
+ CCamera(CInstanceManager* iMan);
+ ~CCamera();
+
+ bool EventProcess(const Event &event);
+
+ void Init(Math::Vector eye, Math::Vector lookat, float delay);
+
+ void SetObject(CObject* object);
+ CObject* RetObject();
+
+ void SetType(CameraType type);
+ CameraType RetType();
+
+ void SetSmooth(CameraSmooth type);
+ CameraSmooth RetSmoth();
+
+ void SetDist(float dist);
+ float RetDist();
+
+ void SetFixDirection(float angle);
+ float RetFixDirection();
+
+ void SetRemotePan(float value);
+ float RetRemotePan();
+
+ void SetRemoteZoom(float value);
+ float RetRemoteZoom();
+
+ void StartVisit(Math::Vector goal, float dist);
+ void StopVisit();
+
+ void RetCamera(Math::Vector &eye, Math::Vector &lookat);
+
+ bool StartCentering(CObject *object, float angleH, float angleV, float dist, float time);
+ bool StopCentering(CObject *object, float time);
+ void AbortCentering();
+
+ void FlushEffect();
+ void StartEffect(CameraEffect effect, Math::Vector pos, float force);
+
+ void FlushOver();
+ void SetOverBaseColor(D3DCOLORVALUE color);
+ void StartOver(OverEffect effect, Math::Vector pos, float force);
+
+ void FixCamera();
+ void SetScriptEye(Math::Vector eye);
+ void SetScriptLookat(Math::Vector lookat);
+
+ void SetEffect(bool bEnable);
+ void SetCameraScroll(bool bScroll);
+ void SetCameraInvertX(bool bInvert);
+ void SetCameraInvertY(bool bInvert);
+
+ float RetMotorTurn();
+ D3DMouse RetMouseDef(Math::Point pos);
+
+protected:
+ bool EventMouseMove(const Event &event);
+ void EventMouseWheel(int dir);
+ bool EventFrame(const Event &event);
+ bool EventFrameFree(const Event &event);
+ bool EventFrameEdit(const Event &event);
+ bool EventFrameDialog(const Event &event);
+ bool EventFrameBack(const Event &event);
+ bool EventFrameFix(const Event &event);
+ bool EventFrameExplo(const Event &event);
+ bool EventFrameOnBoard(const Event &event);
+ bool EventFrameInfo(const Event &event);
+ bool EventFrameVisit(const Event &event);
+ bool EventFrameScript(const Event &event);
+
+ void SetViewTime(const Math::Vector &vEyePt, const Math::Vector &vLookatPt, float rTime);
+ bool IsCollision(Math::Vector &eye, Math::Vector lookat);
+ bool IsCollisionBack(Math::Vector &eye, Math::Vector lookat);
+ bool IsCollisionFix(Math::Vector &eye, Math::Vector lookat);
+
+ Math::Vector ExcludeTerrain(Math::Vector eye, Math::Vector lookat, float &angleH, float &angleV);
+ Math::Vector ExcludeObject(Math::Vector eye, Math::Vector lookat, float &angleH, float &angleV);
+
+ void SetViewParams(const Math::Vector &eye, const Math::Vector &lookat, const Math::Vector &up);
+ void EffectFrame(const Event &event);
+ void OverFrame(const Event &event);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CTerrain* m_terrain;
+ CWater* m_water;
+
+ CameraType m_type; // the type of camera (CAMERA *)
+ CameraSmooth m_smooth; // type of smoothing
+ CObject* m_cameraObj; // object linked to the camera
+
+ float m_eyeDistance; // distance between the eyes
+ float m_initDelay; // time of initial centering
+
+ Math::Vector m_actualEye; // current eye
+ Math::Vector m_actualLookat; // aim current
+ Math::Vector m_finalEye; // final eye
+ Math::Vector m_finalLookat; // aim final
+ Math::Vector m_normEye; // normal eye
+ Math::Vector m_normLookat; // aim normal
+ float m_focus;
+
+ bool m_bRightDown;
+ Math::Point m_rightPosInit;
+ Math::Point m_rightPosCenter;
+ Math::Point m_rightPosMove;
+
+ Math::Vector m_eyePt; // CAMERA_FREE: eye
+ float m_directionH; // CAMERA_FREE: horizontal direction
+ float m_directionV; // CAMERA_FREE: vertical direction
+ float m_heightEye; // CAMERA_FREE: height above the ground
+ float m_heightLookat; // CAMERA_FREE: height above the ground
+ float m_speed; // CAMERA_FREE: speed of movement
+
+ float m_backDist; // CAMERA_BACK: distance
+ float m_backMin; // CAMERA_BACK: distance minimal
+ float m_addDirectionH; // CAMERA_BACK: additional direction
+ float m_addDirectionV; // CAMERA_BACK: additional direction
+ bool m_bTransparency;
+
+ float m_fixDist; // CAMERA_FIX: distance
+ float m_fixDirectionH; // CAMERA_FIX: direction
+ float m_fixDirectionV; // CAMERA_FIX: direction
+
+ Math::Vector m_visitGoal; // CAMERA_VISIT: target position
+ float m_visitDist; // CAMERA_VISIT: distance
+ float m_visitTime; // CAMERA_VISIT: relative time
+ CameraType m_visitType; // CAMERA_VISIT: initial type
+ float m_visitDirectionH; // CAMERA_VISIT: direction
+ float m_visitDirectionV; // CAMERA_VISIT: direction
+
+ float m_editHeight; // CAMERA_EDIT: height
+
+ float m_remotePan;
+ float m_remoteZoom;
+
+ Math::Point m_mousePos;
+ float m_mouseDirH;
+ float m_mouseDirV;
+ float m_mouseMarging;
+
+ float m_motorTurn;
+
+ CenteringPhase m_centeringPhase;
+ float m_centeringAngleH;
+ float m_centeringAngleV;
+ float m_centeringDist;
+ float m_centeringCurrentH;
+ float m_centeringCurrentV;
+ float m_centeringTime;
+ float m_centeringProgress;
+
+ CameraEffect m_effectType;
+ Math::Vector m_effectPos;
+ float m_effectForce;
+ float m_effectProgress;
+ Math::Vector m_effectOffset;
+
+ OverEffect m_overType;
+ float m_overForce;
+ float m_overTime;
+ D3DCOLORVALUE m_overColorBase;
+ D3DCOLORVALUE m_overColor;
+ int m_overMode;
+ float m_overFadeIn;
+ float m_overFadeOut;
+
+ Math::Vector m_scriptEye;
+ Math::Vector m_scriptLookat;
+
+ bool m_bEffect; // shocks if explosion?
+ bool m_bCameraScroll; // scroll in the edges?
+ bool m_bCameraInvertX; // X inversion in the edges?
+ bool m_bCameraInvertY; // Y inversion in the edges?
+};
+
diff --git a/src/old/cloud.cpp b/src/old/cloud.cpp
index 7c1518c..8661cbd 100644
--- a/src/old/cloud.cpp
+++ b/src/old/cloud.cpp
@@ -1,338 +1,338 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/geometry.h"
-#include "math/conv.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "old/d3dutil.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "old/terrain.h"
-#include "object/object.h"
-#include "old/cloud.h"
-
-
-
-const int DIMEXPAND = 4; // extension of the dimensions
-
-
-
-// Constructor of clouds.
-
-CCloud::CCloud(CInstanceManager* iMan, CD3DEngine* engine)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_CLOUD, this);
-
- m_engine = engine;
- m_terrain = 0;
-
- m_level = 0.0f;
- m_wind = Math::Vector(0.0f, 0.0f, 0.0f);
- m_subdiv = 8;
- m_filename[0] = 0;
- m_bEnable = true;
-}
-
-// Destructor of clouds.
-
-CCloud::~CCloud()
-{
-}
-
-
-bool CCloud::EventProcess(const Event &event)
-{
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- return true;
-}
-
-// Makes the clouds evolve.
-
-bool CCloud::EventFrame(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
-
- m_time += event.rTime;
-
- if ( m_level == 0.0f ) return true;
-
- if ( m_time-m_lastTest < 0.2f ) return true;
- m_lastTest = m_time;
-
- return true;
-}
-
-
-// Adjusts the position to normal, to imitate the clouds
-// at movement.
-
-void CCloud::AdjustLevel(Math::Vector &pos, Math::Vector &eye, float deep,
- Math::Point &uv1, Math::Point &uv2)
-{
- float dist, factor;
-
- uv1.x = (pos.x+20000.0f)/1280.0f;
- uv1.y = (pos.z+20000.0f)/1280.0f;
- uv1.x -= m_time*(m_wind.x/100.0f);
- uv1.y -= m_time*(m_wind.z/100.0f);
-
- uv2.x = 0.0f;
- uv2.y = 0.0f;
-
- dist = Math::DistanceProjected(pos, eye);
- factor = powf(dist/deep, 2.0f);
- pos.y -= m_level*factor*10.0f;
-}
-
-inline DWORD F2DW( FLOAT f )
-{
- return *((DWORD*)&f);
-}
-
-// Draw the clouds.
-
-void CCloud::Draw()
-{
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2* vertex;
- Math::Matrix* matView;
- D3DMATERIAL7 material;
- Math::Matrix matrix;
- Math::Vector n, pos, p, eye;
- Math::Point uv1, uv2;
- float iDeep, deep, size, fogStart, fogEnd;
- int i, j, u;
-
- if ( !m_bEnable ) return;
- if ( m_level == 0.0f ) return;
- if ( m_lineUsed == 0 ) return;
-
- vertex = (D3DVERTEX2*)malloc(sizeof(D3DVERTEX2)*(m_brick+2)*2);
-
- iDeep = m_engine->RetDeepView();
- deep = (m_brick*m_size)/2.0f;
- m_engine->SetDeepView(deep);
- m_engine->SetFocus(m_engine->RetFocus());
- m_engine->UpdateMatProj(); // increases the depth of view
-
-//? fogStart = deep*0.10f;
-//? fogEnd = deep*0.16f;
- fogStart = deep*0.15f;
- fogEnd = deep*0.24f;
-
- device = m_engine->RetD3DDevice();
- device->SetRenderState(D3DRENDERSTATE_AMBIENT, 0x00000000);
- device->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
- device->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
-//? device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
- device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
- device->SetRenderState(D3DRENDERSTATE_FOGSTART, F2DW(fogStart));
- device->SetRenderState(D3DRENDERSTATE_FOGEND, F2DW(fogEnd));
-
- matView = m_engine->RetMatView();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(*matView);
- device->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
-
- ZeroMemory( &material, sizeof(D3DMATERIAL7) );
- material.diffuse = m_diffuse;
- material.ambient = m_ambient;
- m_engine->SetMaterial(material);
-
- m_engine->SetTexture(m_filename, 0);
- m_engine->SetTexture(m_filename, 1);
-
-//? m_engine->SetState(D3DSTATETTb|D3DSTATEDUALw|D3DSTATEWRAP);
- m_engine->SetState(D3DSTATETTb|D3DSTATEFOG|D3DSTATEWRAP);
-//? m_engine->SetState(D3DSTATEWRAP);
-
- matrix.LoadIdentity();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- size = m_size/2.0f;
- eye = m_engine->RetEyePt();
- n = Math::Vector(0.0f, -1.0f, 0.0f);
-
- // Draws all the lines.
- for ( i=0 ; i<m_lineUsed ; i++ )
- {
- pos.y = m_level;
- pos.z = m_line[i].pz;
- pos.x = m_line[i].px1;
-
- u = 0;
- p.x = pos.x-size;
- p.z = pos.z+size;
- p.y = pos.y;
- AdjustLevel(p, eye, deep, uv1, uv2);
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
-
- p.x = pos.x-size;
- p.z = pos.z-size;
- p.y = pos.y;
- AdjustLevel(p, eye, deep, uv1, uv2);
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
-
- for ( j=0 ; j<m_line[i].len ; j++ )
- {
- p.x = pos.x+size;
- p.z = pos.z+size;
- p.y = pos.y;
- AdjustLevel(p, eye, deep, uv1, uv2);
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
-
- p.x = pos.x+size;
- p.z = pos.z-size;
- p.y = pos.y;
- AdjustLevel(p, eye, deep, uv1, uv2);
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
-
- pos.x += size*2.0f;
- }
-
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, u, NULL);
- m_engine->AddStatisticTriangle(u-2);
- }
-
- m_engine->SetDeepView(iDeep);
- m_engine->SetFocus(m_engine->RetFocus());
- m_engine->UpdateMatProj(); // gives depth to initial
-
- free(vertex);
-}
-
-
-// Updates the positions, relative to the ground.
-
-bool CCloud::CreateLine(int x, int y, int len)
-{
- float offset;
-
- m_line[m_lineUsed].x = x;
- m_line[m_lineUsed].y = y;
- m_line[m_lineUsed].len = len;
-
- offset = m_brick*m_size/2.0f - m_size/2.0f;
-
- m_line[m_lineUsed].px1 = m_size* m_line[m_lineUsed].x - offset;
- m_line[m_lineUsed].px2 = m_size*(m_line[m_lineUsed].x+m_line[m_lineUsed].len) - offset;
- m_line[m_lineUsed].pz = m_size* m_line[m_lineUsed].y - offset;
-
- m_lineUsed ++;
-
- return ( m_lineUsed < MAXCLOUDLINE );
-}
-
-// Creates all areas of cloud.
-
-bool CCloud::Create(const char *filename,
- D3DCOLORVALUE diffuse, D3DCOLORVALUE ambient,
- float level)
-{
- int y;
-
- m_diffuse = diffuse;
- m_ambient = ambient;
- m_level = level;
- m_time = 0.0f;
- m_lastTest = 0.0f;
- strcpy(m_filename, filename);
-
- if ( m_filename[0] != 0 )
- {
- m_engine->LoadTexture(m_filename, 0);
- m_engine->LoadTexture(m_filename, 1);
- }
-
- if ( m_terrain == 0 )
- {
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- }
-
- m_wind = m_terrain->RetWind();
-
- m_brick = m_terrain->RetBrick()*m_terrain->RetMosaic()*DIMEXPAND;
- m_size = m_terrain->RetSize();
-
- m_brick /= m_subdiv*DIMEXPAND;
- m_size *= m_subdiv*DIMEXPAND;
-
- if ( m_level == 0.0f ) return true;
-
- m_lineUsed = 0;
- for ( y=0 ; y<m_brick ; y++ )
- {
- CreateLine(0, y, m_brick);
- }
- return true;
-}
-
-// Removes all the clouds.
-
-void CCloud::Flush()
-{
- m_level = 0.0f;
-}
-
-
-// Modifies the cloud level.
-
-bool CCloud::SetLevel(float level)
-{
- m_level = level;
-
- return Create(m_filename, m_diffuse, m_ambient,
- m_level);
-}
-
-// Returns the current level of clouds.
-
-float CCloud::RetLevel()
-{
- return m_level;
-}
-
-
-// Activate management of clouds.
-
-void CCloud::SetEnable(bool bEnable)
-{
- m_bEnable = bEnable;
-}
-
-bool CCloud::RetEnable()
-{
- return m_bEnable;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/geometry.h"
+#include "math/conv.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "old/d3dutil.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "old/terrain.h"
+#include "object/object.h"
+#include "old/cloud.h"
+
+
+
+const int DIMEXPAND = 4; // extension of the dimensions
+
+
+
+// Constructor of clouds.
+
+CCloud::CCloud(CInstanceManager* iMan, CD3DEngine* engine)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_CLOUD, this);
+
+ m_engine = engine;
+ m_terrain = 0;
+
+ m_level = 0.0f;
+ m_wind = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_subdiv = 8;
+ m_filename[0] = 0;
+ m_bEnable = true;
+}
+
+// Destructor of clouds.
+
+CCloud::~CCloud()
+{
+}
+
+
+bool CCloud::EventProcess(const Event &event)
+{
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ return true;
+}
+
+// Makes the clouds evolve.
+
+bool CCloud::EventFrame(const Event &event)
+{
+ if ( m_engine->RetPause() ) return true;
+
+ m_time += event.rTime;
+
+ if ( m_level == 0.0f ) return true;
+
+ if ( m_time-m_lastTest < 0.2f ) return true;
+ m_lastTest = m_time;
+
+ return true;
+}
+
+
+// Adjusts the position to normal, to imitate the clouds
+// at movement.
+
+void CCloud::AdjustLevel(Math::Vector &pos, Math::Vector &eye, float deep,
+ Math::Point &uv1, Math::Point &uv2)
+{
+ float dist, factor;
+
+ uv1.x = (pos.x+20000.0f)/1280.0f;
+ uv1.y = (pos.z+20000.0f)/1280.0f;
+ uv1.x -= m_time*(m_wind.x/100.0f);
+ uv1.y -= m_time*(m_wind.z/100.0f);
+
+ uv2.x = 0.0f;
+ uv2.y = 0.0f;
+
+ dist = Math::DistanceProjected(pos, eye);
+ factor = powf(dist/deep, 2.0f);
+ pos.y -= m_level*factor*10.0f;
+}
+
+inline DWORD F2DW( FLOAT f )
+{
+ return *((DWORD*)&f);
+}
+
+// Draw the clouds.
+
+void CCloud::Draw()
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DVERTEX2* vertex;
+ Math::Matrix* matView;
+ D3DMATERIAL7 material;
+ Math::Matrix matrix;
+ Math::Vector n, pos, p, eye;
+ Math::Point uv1, uv2;
+ float iDeep, deep, size, fogStart, fogEnd;
+ int i, j, u;
+
+ if ( !m_bEnable ) return;
+ if ( m_level == 0.0f ) return;
+ if ( m_lineUsed == 0 ) return;
+
+ vertex = (D3DVERTEX2*)malloc(sizeof(D3DVERTEX2)*(m_brick+2)*2);
+
+ iDeep = m_engine->RetDeepView();
+ deep = (m_brick*m_size)/2.0f;
+ m_engine->SetDeepView(deep);
+ m_engine->SetFocus(m_engine->RetFocus());
+ m_engine->UpdateMatProj(); // increases the depth of view
+
+//? fogStart = deep*0.10f;
+//? fogEnd = deep*0.16f;
+ fogStart = deep*0.15f;
+ fogEnd = deep*0.24f;
+
+ device = m_engine->RetD3DDevice();
+ device->SetRenderState(D3DRENDERSTATE_AMBIENT, 0x00000000);
+ device->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
+ device->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
+//? device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
+ device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
+ device->SetRenderState(D3DRENDERSTATE_FOGSTART, F2DW(fogStart));
+ device->SetRenderState(D3DRENDERSTATE_FOGEND, F2DW(fogEnd));
+
+ matView = m_engine->RetMatView();
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(*matView);
+ device->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+
+ ZeroMemory( &material, sizeof(D3DMATERIAL7) );
+ material.diffuse = m_diffuse;
+ material.ambient = m_ambient;
+ m_engine->SetMaterial(material);
+
+ m_engine->SetTexture(m_filename, 0);
+ m_engine->SetTexture(m_filename, 1);
+
+//? m_engine->SetState(D3DSTATETTb|D3DSTATEDUALw|D3DSTATEWRAP);
+ m_engine->SetState(D3DSTATETTb|D3DSTATEFOG|D3DSTATEWRAP);
+//? m_engine->SetState(D3DSTATEWRAP);
+
+ matrix.LoadIdentity();
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ size = m_size/2.0f;
+ eye = m_engine->RetEyePt();
+ n = Math::Vector(0.0f, -1.0f, 0.0f);
+
+ // Draws all the lines.
+ for ( i=0 ; i<m_lineUsed ; i++ )
+ {
+ pos.y = m_level;
+ pos.z = m_line[i].pz;
+ pos.x = m_line[i].px1;
+
+ u = 0;
+ p.x = pos.x-size;
+ p.z = pos.z+size;
+ p.y = pos.y;
+ AdjustLevel(p, eye, deep, uv1, uv2);
+ vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+
+ p.x = pos.x-size;
+ p.z = pos.z-size;
+ p.y = pos.y;
+ AdjustLevel(p, eye, deep, uv1, uv2);
+ vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+
+ for ( j=0 ; j<m_line[i].len ; j++ )
+ {
+ p.x = pos.x+size;
+ p.z = pos.z+size;
+ p.y = pos.y;
+ AdjustLevel(p, eye, deep, uv1, uv2);
+ vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+
+ p.x = pos.x+size;
+ p.z = pos.z-size;
+ p.y = pos.y;
+ AdjustLevel(p, eye, deep, uv1, uv2);
+ vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+
+ pos.x += size*2.0f;
+ }
+
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, u, NULL);
+ m_engine->AddStatisticTriangle(u-2);
+ }
+
+ m_engine->SetDeepView(iDeep);
+ m_engine->SetFocus(m_engine->RetFocus());
+ m_engine->UpdateMatProj(); // gives depth to initial
+
+ free(vertex);
+}
+
+
+// Updates the positions, relative to the ground.
+
+bool CCloud::CreateLine(int x, int y, int len)
+{
+ float offset;
+
+ m_line[m_lineUsed].x = x;
+ m_line[m_lineUsed].y = y;
+ m_line[m_lineUsed].len = len;
+
+ offset = m_brick*m_size/2.0f - m_size/2.0f;
+
+ m_line[m_lineUsed].px1 = m_size* m_line[m_lineUsed].x - offset;
+ m_line[m_lineUsed].px2 = m_size*(m_line[m_lineUsed].x+m_line[m_lineUsed].len) - offset;
+ m_line[m_lineUsed].pz = m_size* m_line[m_lineUsed].y - offset;
+
+ m_lineUsed ++;
+
+ return ( m_lineUsed < MAXCLOUDLINE );
+}
+
+// Creates all areas of cloud.
+
+bool CCloud::Create(const char *filename,
+ D3DCOLORVALUE diffuse, D3DCOLORVALUE ambient,
+ float level)
+{
+ int y;
+
+ m_diffuse = diffuse;
+ m_ambient = ambient;
+ m_level = level;
+ m_time = 0.0f;
+ m_lastTest = 0.0f;
+ strcpy(m_filename, filename);
+
+ if ( m_filename[0] != 0 )
+ {
+ m_engine->LoadTexture(m_filename, 0);
+ m_engine->LoadTexture(m_filename, 1);
+ }
+
+ if ( m_terrain == 0 )
+ {
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ }
+
+ m_wind = m_terrain->RetWind();
+
+ m_brick = m_terrain->RetBrick()*m_terrain->RetMosaic()*DIMEXPAND;
+ m_size = m_terrain->RetSize();
+
+ m_brick /= m_subdiv*DIMEXPAND;
+ m_size *= m_subdiv*DIMEXPAND;
+
+ if ( m_level == 0.0f ) return true;
+
+ m_lineUsed = 0;
+ for ( y=0 ; y<m_brick ; y++ )
+ {
+ CreateLine(0, y, m_brick);
+ }
+ return true;
+}
+
+// Removes all the clouds.
+
+void CCloud::Flush()
+{
+ m_level = 0.0f;
+}
+
+
+// Modifies the cloud level.
+
+bool CCloud::SetLevel(float level)
+{
+ m_level = level;
+
+ return Create(m_filename, m_diffuse, m_ambient,
+ m_level);
+}
+
+// Returns the current level of clouds.
+
+float CCloud::RetLevel()
+{
+ return m_level;
+}
+
+
+// Activate management of clouds.
+
+void CCloud::SetEnable(bool bEnable)
+{
+ m_bEnable = bEnable;
+}
+
+bool CCloud::RetEnable()
+{
+ return m_bEnable;
+}
+
diff --git a/src/old/cloud.h b/src/old/cloud.h
index 6ff16bb..de6b39e 100644
--- a/src/old/cloud.h
+++ b/src/old/cloud.h
@@ -1,88 +1,88 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// cloud.h
-
-#pragma once
-
-
-#include "common/event.h"
-#include "math/point.h"
-#include "old/d3dengine.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CTerrain;
-
-
-
-const int MAXCLOUDLINE = 100;
-
-struct CloudLine
-{
- short x, y; // beginning
- short len; // in length x
- float px1, px2, pz;
-};
-
-
-class CCloud
-{
-public:
- CCloud(CInstanceManager* iMan, CD3DEngine* engine);
- ~CCloud();
-
- bool EventProcess(const Event &event);
- void Flush();
- bool Create(const char *filename, D3DCOLORVALUE diffuse, D3DCOLORVALUE ambient, float level);
- void Draw();
-
- bool SetLevel(float level);
- float RetLevel();
-
- void SetEnable(bool bEnable);
- bool RetEnable();
-
-protected:
- bool EventFrame(const Event &event);
- void AdjustLevel(Math::Vector &pos, Math::Vector &eye, float deep, Math::Point &uv1, Math::Point &uv2);
- bool CreateLine(int x, int y, int len);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CTerrain* m_terrain;
-
- char m_filename[100];
- float m_level; // overall level
- Math::Point m_speed; // feedrate (wind)
- D3DCOLORVALUE m_diffuse; // diffuse color
- D3DCOLORVALUE m_ambient; // ambient color
- float m_time;
- float m_lastTest;
- int m_subdiv;
-
- Math::Vector m_wind; // wind speed
- int m_brick; // brick mosaic
- float m_size; // size of a brick element
-
- int m_lineUsed;
- CloudLine m_line[MAXCLOUDLINE];
-
- bool m_bEnable;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// cloud.h
+
+#pragma once
+
+
+#include "common/event.h"
+#include "math/point.h"
+#include "old/d3dengine.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CTerrain;
+
+
+
+const int MAXCLOUDLINE = 100;
+
+struct CloudLine
+{
+ short x, y; // beginning
+ short len; // in length x
+ float px1, px2, pz;
+};
+
+
+class CCloud
+{
+public:
+ CCloud(CInstanceManager* iMan, CD3DEngine* engine);
+ ~CCloud();
+
+ bool EventProcess(const Event &event);
+ void Flush();
+ bool Create(const char *filename, D3DCOLORVALUE diffuse, D3DCOLORVALUE ambient, float level);
+ void Draw();
+
+ bool SetLevel(float level);
+ float RetLevel();
+
+ void SetEnable(bool bEnable);
+ bool RetEnable();
+
+protected:
+ bool EventFrame(const Event &event);
+ void AdjustLevel(Math::Vector &pos, Math::Vector &eye, float deep, Math::Point &uv1, Math::Point &uv2);
+ bool CreateLine(int x, int y, int len);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CTerrain* m_terrain;
+
+ char m_filename[100];
+ float m_level; // overall level
+ Math::Point m_speed; // feedrate (wind)
+ D3DCOLORVALUE m_diffuse; // diffuse color
+ D3DCOLORVALUE m_ambient; // ambient color
+ float m_time;
+ float m_lastTest;
+ int m_subdiv;
+
+ Math::Vector m_wind; // wind speed
+ int m_brick; // brick mosaic
+ float m_size; // size of a brick element
+
+ int m_lineUsed;
+ CloudLine m_line[MAXCLOUDLINE];
+
+ bool m_bEnable;
+};
+
diff --git a/src/old/d3dapp.cpp b/src/old/d3dapp.cpp
index 7f04279..351971f 100644
--- a/src/old/d3dapp.cpp
+++ b/src/old/d3dapp.cpp
@@ -1,2451 +1,2451 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <windows.h>
-#include <winuser.h>
-#include <mmsystem.h>
-#include <stdio.h>
-#include <direct.h>
-#include <tchar.h>
-#include <zmouse.h>
-#include <dinput.h>
-
-#include "common/struct.h"
-#include "old/d3dtextr.h"
-#include "old/d3dengine.h"
-#include "common/language.h"
-#include "common/event.h"
-#include "common/profile.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "old/math3d.h"
-#include "old/joystick.h"
-#include "object/robotmain.h"
-#include "old/sound.h"
-#include "old/d3dapp.h"
-
-// fix for "MSH_MOUSEWHEEL undefined" error
-#ifdef UNICODE
-#define MSH_MOUSEWHEEL L"MSWHEEL_ROLLMSG"
-#else
-#define MSH_MOUSEWHEEL "MSWHEEL_ROLLMSG"
-#endif
-
-
-const int AUDIO_TRACK = 13; // total number of audio tracks on the CD
-const float MAX_STEP = 0.2f; // maximum time for a step
-
-const int WINDOW_DX = (640+6); // dimensions in windowed mode
-const int WINDOW_DY = (480+25);
-
-#define USE_THREAD false // true does not work!
-const float TIME_THREAD = 0.02f;
-
-
-
-
-// Limit the use of the controls keyboard & joystick.
-
-float AxeLimit(float value)
-{
- if ( value < -1.0f ) value = -1.0f;
- if ( value > 1.0f ) value = 1.0f;
- return value;
-}
-
-
-// Entry point to the program. Initializes everything, and goes into a
-// message-processing loop. Idle time is used to render the scene.
-
-INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
-{
- Error err;
- char string[100];
-
- CD3DApplication d3dApp; // single instance of the application
-
- err = d3dApp.CheckMistery(strCmdLine);
- if ( err != ERR_OK )
- {
- GetResource(RES_ERR, err, string);
-#if _NEWLOOK
- MessageBox( NULL, string, _T("CeeBot"), MB_ICONERROR|MB_OK );
-#else
- MessageBox( NULL, string, _T("COLOBOT"), MB_ICONERROR|MB_OK );
-#endif
- return 0;
- }
-
- if ( FAILED(d3dApp.Create(hInst, strCmdLine)) )
- {
- return 0;
- }
-
- return d3dApp.Run(); // execution of all
-}
-
-
-// Internal variables and function prototypes.
-
-enum APPMSGTYPE { MSG_NONE, MSGERR_APPMUSTEXIT, MSGWARN_SWITCHEDTOSOFTWARE };
-
-static INT CALLBACK AboutProc( HWND, UINT, WPARAM, LPARAM );
-static LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
-
-static CD3DApplication* g_pD3DApp;
-
-
-
-// Constructor.
-
-CD3DApplication::CD3DApplication()
-{
- int i;
-
- m_iMan = new(CInstanceManager);
- m_event = new CEvent(m_iMan);
-
- m_pD3DEngine = 0;
- m_pRobotMain = 0;
- m_pSound = 0;
- m_pFramework = 0;
- m_instance = 0;
- m_hWnd = 0;
- m_pDD = 0;
- m_pD3D = 0;
- m_pD3DDevice = 0;
-
- m_CDpath[0] = 0;
-
- m_pddsRenderTarget = 0;
- m_pddsDepthBuffer = 0;
-
- m_keyState = 0;
- m_axeKey = Math::Vector(0.0f, 0.0f, 0.0f);
- m_axeJoy = Math::Vector(0.0f, 0.0f, 0.0f);
-
- m_vidMemTotal = 0;
- m_bActive = false;
- m_bActivateApp = false;
- m_bReady = false;
- m_bJoystick = false;
- m_aTime = 0.0f;
-
- for ( i=0 ; i<32 ; i++ )
- {
- m_bJoyButton[i] = false;
- }
-
-#if _NEWLOOK
- m_strWindowTitle = _T("CeeBot");
-#else
- m_strWindowTitle = _T("COLOBOT");
-#endif
- m_bAppUseZBuffer = true;
- m_bAppUseStereo = true;
- m_bShowStats = false;
- m_bDebugMode = false;
- m_bAudioState = true;
- m_bAudioTrack = true;
- m_bNiceMouse = false;
- m_bSetupMode = true;
- m_fnConfirmDevice = 0;
-
- ResetKey();
-
- g_pD3DApp = this;
-
- // Request event sent by Logitech.
- m_mshMouseWheel = RegisterWindowMessage(MSH_MOUSEWHEEL);
-
- _mkdir("files\\");
-}
-
-
-// Destructor.
-
-CD3DApplication::~CD3DApplication()
-{
- delete m_iMan;
-}
-
-
-
-// Returns the path of the CD.
-
-char* CD3DApplication::RetCDpath()
-{
- return m_CDpath;
-}
-
-// Reads the information in the registry.
-
-Error CD3DApplication::RegQuery()
-{
- FILE* file = NULL;
- HKEY key;
- LONG i;
- DWORD type, len;
- char filename[100];
-
-#if _NEWLOOK
- #if _TEEN
- i = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Epsitec\\CeeBot-Teen\\Setup",
- #else
- i = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Epsitec\\CeeBot-A\\Setup",
- #endif
-#else
- i = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Epsitec\\Colobot\\Setup",
-#endif
- 0, KEY_READ, &key);
- if ( i != ERROR_SUCCESS ) return ERR_INSTALL;
-
- type = REG_SZ;
- len = sizeof(m_CDpath);
- i = RegQueryValueEx(key, "CDpath", NULL, &type, (LPBYTE)m_CDpath, &len);
- if ( i != ERROR_SUCCESS || type != REG_SZ ) return ERR_INSTALL;
-
- filename[0] = m_CDpath[0];
- filename[1] = ':';
- filename[2] = '\\';
- filename[3] = 0;
- i = GetDriveType(filename);
- if ( i != DRIVE_CDROM ) return ERR_NOCD;
-
- strcat(filename, "install.ini");
- file = fopen(filename, "rb"); // install.ini file exist?
- if ( file == NULL ) return ERR_NOCD;
- fclose(file);
-
- return ERR_OK;
-}
-
-// Checks for audio tracks on the CD.
-
-Error CD3DApplication::AudioQuery()
-{
- MCI_OPEN_PARMS mciOpenParms;
- MCI_STATUS_PARMS mciStatusParms;
- DWORD dwReturn;
- UINT deviceID;
- char device[10];
-
- // Open the device by specifying the device and filename.
- // MCI will attempt to choose the MIDI mapper as the output port.
- memset(&mciOpenParms, 0, sizeof(MCI_OPEN_PARMS));
- mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
- if ( m_CDpath[0] == 0 )
- {
- dwReturn = mciSendCommand(NULL,
- MCI_OPEN,
- MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,
- (DWORD)(LPVOID)&mciOpenParms);
- }
- else
- {
- device[0] = m_CDpath[0];
- device[1] = ':';
- device[2] = 0;
- mciOpenParms.lpstrElementName = device;
- dwReturn = mciSendCommand(NULL,
- MCI_OPEN,
- MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_OPEN_ELEMENT,
- (DWORD)(LPVOID)&mciOpenParms);
- }
- if ( dwReturn != 0 )
- {
- return ERR_NOCD;
- }
-
- // The device opened successfully; get the device ID.
- deviceID = mciOpenParms.wDeviceID;
-
- memset(&mciStatusParms, 0, sizeof(MCI_STATUS_PARMS));
- mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
- dwReturn = mciSendCommand(deviceID,
- MCI_STATUS,
- MCI_WAIT|MCI_STATUS_ITEM,
- (DWORD)&mciStatusParms);
- if ( dwReturn != 0 )
- {
- mciSendCommand(deviceID, MCI_CLOSE, 0, NULL);
- return ERR_NOCD;
- }
-
- if ( mciStatusParms.dwReturn != AUDIO_TRACK )
- {
- mciSendCommand(deviceID, MCI_CLOSE, 0, NULL);
- return ERR_NOCD;
- }
-
- mciSendCommand(deviceID, MCI_CLOSE, 0, NULL);
- return ERR_OK;
-}
-
-// Checks for the key.
-
-Error CD3DApplication::CheckMistery(char *strCmdLine)
-{
- if ( strstr(strCmdLine, "-debug") != 0 )
- {
- m_bShowStats = true;
- SetDebugMode(true);
- }
-
- if ( strstr(strCmdLine, "-audiostate") != 0 )
- {
- m_bAudioState = false;
- }
-
- if ( strstr(strCmdLine, "-audiotrack") != 0 )
- {
- m_bAudioTrack = false;
- }
-
- m_CDpath[0] = 0;
-#if _FULL
- if ( strstr(strCmdLine, "-nocd") == 0 && !m_bDebugMode )
- {
- Error err;
-
- err = RegQuery();
- if ( err != ERR_OK ) return err;
-
- //?err = AudioQuery();
- //?if ( err != ERR_OK ) return err;
- }
-#endif
-#if _SCHOOL & _EDU
- if ( strstr(strCmdLine, "-nosetup") != 0 )
- {
- m_bSetupMode = false;
- }
- m_bAudioTrack = false;
-#endif
-#if _SCHOOL & _PERSO
- Error err = RegQuery();
- if ( err != ERR_OK ) return err;
- m_bAudioTrack = false;
-#endif
-#if _SCHOOL & _CEEBOTDEMO
- m_bAudioTrack = false;
-#endif
-#if _NET
- m_bAudioTrack = false;
-#endif
-#if _DEMO
- m_bAudioTrack = false;
-#endif
-
- return ERR_OK;
-}
-
-
-// Returns the total amount of video memory for textures.
-
-int CD3DApplication::GetVidMemTotal()
-{
- return m_vidMemTotal;
-}
-
-bool CD3DApplication::IsVideo8MB()
-{
- if ( m_vidMemTotal == 0 ) return false;
- return (m_vidMemTotal <= 8388608L); // 8 Mb or less (2 ^ 23)?
-}
-
-bool CD3DApplication::IsVideo32MB()
-{
- if ( m_vidMemTotal == 0 ) return false;
- return (m_vidMemTotal > 16777216L); // more than 16 Mb (2 ^ 24)?
-}
-
-
-void CD3DApplication::SetShowStat(bool bShow)
-{
- m_bShowStats = bShow;
-}
-
-bool CD3DApplication::RetShowStat()
-{
- return m_bShowStats;
-}
-
-
-void CD3DApplication::SetDebugMode(bool bMode)
-{
- m_bDebugMode = bMode;
- D3DTextr_SetDebugMode(m_bDebugMode);
-}
-
-bool CD3DApplication::RetDebugMode()
-{
- return m_bDebugMode;
-}
-
-bool CD3DApplication::RetSetupMode()
-{
- return m_bSetupMode;
-}
-
-
-
-
-// Son process of time management.
-
-DWORD WINAPI ThreadRoutine(LPVOID)
-{
- Event event;
- float time;
- int ms, start, end, delay;
-
- ms = (int)(TIME_THREAD*1000.0f);
- time = 0.0f;
- while ( true )
- {
- start = timeGetTime();
-
- g_pD3DApp->m_pD3DEngine->FrameMove(TIME_THREAD);
-
- ZeroMemory(&event, sizeof(Event));
- event.event = EVENT_FRAME;
- event.rTime = TIME_THREAD;
- event.axeX = AxeLimit(g_pD3DApp->m_axeKey.x + g_pD3DApp->m_axeJoy.x);
- event.axeY = AxeLimit(g_pD3DApp->m_axeKey.y + g_pD3DApp->m_axeJoy.y);
- event.axeZ = AxeLimit(g_pD3DApp->m_axeKey.z + g_pD3DApp->m_axeJoy.z);
- event.keyState = g_pD3DApp->m_keyState;
-
- if ( g_pD3DApp->m_pRobotMain != 0 )
- {
- g_pD3DApp->m_pRobotMain->EventProcess(event);
- }
-
- end = timeGetTime();
-
- delay = ms-(end-start);
- if ( delay > 0 )
- {
- Sleep(delay); // waiting 20ms-used
- }
- time += TIME_THREAD;
- }
- return 0;
-}
-
-
-// Called during device intialization, this code checks the device
-// for some minimum set of capabilities.
-
-HRESULT CD3DApplication::ConfirmDevice( DDCAPS* pddDriverCaps,
- D3DDEVICEDESC7* pd3dDeviceDesc )
-{
-//? if( pd3dDeviceDesc->wMaxVertexBlendMatrices < 2 )
-//? return E_FAIL;
-
- return S_OK;
-}
-
-// Create the application.
-
-HRESULT CD3DApplication::Create( HINSTANCE hInst, TCHAR* strCmdLine )
-{
- HRESULT hr;
- char deviceName[100];
- char modeName[100];
- int iValue;
- DWORD style;
- bool bFull, b3D;
-
- m_instance = hInst;
-
- InitCurrentDirectory();
-
- // Enumerate available D3D devices. The callback is used so the app can
- // confirm/reject each enumerated device depending on its capabilities.
- if( FAILED( hr = D3DEnum_EnumerateDevices( m_fnConfirmDevice ) ) )
- {
- DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
- return hr;
- }
-
- if( FAILED( hr = D3DEnum_SelectDefaultDevice( &m_pDeviceInfo ) ) )
- {
- DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
- return hr;
- }
-
- if ( !m_bDebugMode )
- {
- m_pDeviceInfo->bWindowed = false; // full screen
- }
- if ( GetProfileInt("Device", "FullScreen", bFull) )
- {
- m_pDeviceInfo->bWindowed = !bFull;
- }
- m_pDeviceInfo->bWindowed = true;
-
- // Create the 3D engine.
- if( (m_pD3DEngine = new CD3DEngine(m_iMan, this)) == NULL )
- {
- DisplayFrameworkError( D3DENUMERR_ENGINE, MSGERR_APPMUSTEXIT );
- return E_OUTOFMEMORY;
- }
- SetEngine(m_pD3DEngine);
-
- // Initialize the app's custom scene stuff
- if( FAILED( hr = m_pD3DEngine->OneTimeSceneInit() ) )
- {
- DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
- return hr;
- }
-
- // Create a new CD3DFramework class. This class does all of our D3D
- // initialization and manages the common D3D objects.
- if( (m_pFramework = new CD3DFramework7()) == NULL )
- {
- DisplayFrameworkError( E_OUTOFMEMORY, MSGERR_APPMUSTEXIT );
- return E_OUTOFMEMORY;
- }
-
- // Create the sound instance.
- if( (m_pSound = new CSound(m_iMan)) == NULL )
- {
- DisplayFrameworkError( D3DENUMERR_SOUND, MSGERR_APPMUSTEXIT );
- return E_OUTOFMEMORY;
- }
-
- // Create the robot application.
- if( (m_pRobotMain = new CRobotMain(m_iMan)) == NULL )
- {
- DisplayFrameworkError( D3DENUMERR_ROBOT, MSGERR_APPMUSTEXIT );
- return E_OUTOFMEMORY;
- }
-
- // Register the window class
- WNDCLASS wndClass = { 0, WndProc, 0, 0, hInst,
- LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN_ICON) ),
- LoadCursor( NULL, IDC_ARROW ),
- (HBRUSH)GetStockObject(WHITE_BRUSH),
- NULL, _T("D3D Window") };
- RegisterClass( &wndClass );
-
- // Create the render window
- style = WS_CAPTION|WS_VISIBLE;
- if ( m_bDebugMode ) style |= WS_SYSMENU; // close box
- m_hWnd = CreateWindow( _T("D3D Window"), m_strWindowTitle,
-//? WS_OVERLAPPEDWINDOW|WS_VISIBLE,
- style, CW_USEDEFAULT, CW_USEDEFAULT,
- WINDOW_DX, WINDOW_DY, 0L,
-//? LoadMenu( hInst, MAKEINTRESOURCE(IDR_MENU) ),
- NULL,
- hInst, 0L );
- UpdateWindow( m_hWnd );
-
- if ( !GetProfileInt("Setup", "Sound3D", b3D) )
- {
- b3D = true;
- }
- m_pSound->SetDebugMode(m_bDebugMode);
- m_pSound->Create(m_hWnd, b3D);
- m_pSound->CacheAll();
- m_pSound->SetState(m_bAudioState);
- m_pSound->SetAudioTrack(m_bAudioTrack);
- m_pSound->SetCDpath(m_CDpath);
-
- // Initialize the 3D environment for the app
- if( FAILED( hr = Initialize3DEnvironment() ) )
- {
- DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
- Cleanup3DEnvironment();
- return E_FAIL;
- }
-
- // Change the display device driver.
- GetProfileString("Device", "Name", deviceName, 100);
- GetProfileString("Device", "Mode", modeName, 100);
- GetProfileInt("Device", "FullScreen", bFull);
- if ( deviceName[0] != 0 && modeName[0] != 0 && bFull )
- {
- ChangeDevice(deviceName, modeName, bFull);
- }
-
- // First execution?
- if ( !GetProfileInt("Setup", "ObjectDirty", iValue) )
- {
- m_pD3DEngine->FirstExecuteAdapt(true);
- }
-
- // Creates the file colobot.ini at the first execution.
- m_pRobotMain->CreateIni();
-
-#if _DEMO
- m_pRobotMain->ChangePhase(PHASE_NAME);
-#else
-#if _NET | _SCHOOL
- m_pRobotMain->ChangePhase(PHASE_WELCOME2);
-#else
-#if _FRENCH
- m_pRobotMain->ChangePhase(PHASE_WELCOME2);
-#endif
-#if _ENGLISH
- m_pRobotMain->ChangePhase(PHASE_WELCOME2);
-#endif
-#if _GERMAN
- m_pRobotMain->ChangePhase(PHASE_WELCOME2);
-#endif
-#if _WG
- m_pRobotMain->ChangePhase(PHASE_WELCOME1);
-#endif
-#if _POLISH
- m_pRobotMain->ChangePhase(PHASE_WELCOME1);
-#endif
-#endif
-#endif
- m_pD3DEngine->TimeInit();
-
-#if USE_THREAD
- m_thread = CreateThread(NULL, 0, ThreadRoutine, this, 0, &m_threadId);
- SetThreadPriority(m_thread, THREAD_PRIORITY_ABOVE_NORMAL);
-#endif
-
- // The app is ready to go
- m_bReady = true;
-
- return S_OK;
-}
-
-
-// Message-processing loop. Idle time is used to render the scene.
-
-INT CD3DApplication::Run()
-{
- // Load keyboard accelerators
- HACCEL hAccel = LoadAccelerators( NULL, MAKEINTRESOURCE(IDR_MAIN_ACCEL) );
-
- // Now we're ready to recieve and process Windows messages.
- bool bGotMsg;
- MSG msg;
- PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE );
-
- while( WM_QUIT != msg.message )
- {
- // Use PeekMessage() if the app is active, so we can use idle time to
- // render the scene. Else, use GetMessage() to avoid eating CPU time.
- if( m_bActive )
- bGotMsg = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE );
- else
- bGotMsg = GetMessage( &msg, NULL, 0U, 0U );
-
- if( bGotMsg )
- {
- // Translate and dispatch the message
- if( TranslateAccelerator( m_hWnd, hAccel, &msg ) == 0 )
- {
- TranslateMessage( &msg );
- DispatchMessage( &msg );
- }
- }
- else
- {
- // Render a frame during idle time (no messages are waiting)
- if( m_bActive && m_bReady )
- {
- Event event;
-
- while ( m_event->GetEvent(event) )
- {
- if ( event.event == EVENT_QUIT )
- {
-//? SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
- m_pSound->StopMusic();
- Cleanup3DEnvironment();
- PostQuitMessage(0);
- return msg.wParam;
- }
- m_pRobotMain->EventProcess(event);
- }
-
- if ( !RetNiceMouse() )
- {
- SetMouseType(m_pD3DEngine->RetMouseType());
- }
-
- if( FAILED( Render3DEnvironment() ) )
- DestroyWindow( m_hWnd );
- }
- }
- }
-
- return msg.wParam;
-}
-
-
-
-// Conversion of the position of the mouse.
-// x: 0=left, 1=right
-// y: 0=down, 1=up
-
-Math::Point CD3DApplication::ConvPosToInterface(HWND hWnd, LPARAM lParam)
-{
- POINT cpos;
- Math::Point pos;
- float px, py, w, h;
-
- cpos.x = (short)LOWORD(lParam);
- cpos.y = (short)HIWORD(lParam);
-
- if ( !m_pDeviceInfo->bWindowed )
- {
- ClientToScreen(hWnd, &cpos);
- }
-
- px = (float)cpos.x;
- py = (float)cpos.y;
- w = (float)m_ddsdRenderTarget.dwWidth;
- h = (float)m_ddsdRenderTarget.dwHeight;
-
- pos.x = px/w;
- pos.y = 1.0f-py/h;
-
- return pos;
-}
-
-// Physically moves the mouse.
-
-void CD3DApplication::SetMousePos(Math::Point pos)
-{
- POINT p;
-
- pos.y = 1.0f-pos.y;
-
- pos.x *= m_ddsdRenderTarget.dwWidth;
- pos.y *= m_ddsdRenderTarget.dwHeight;
-
- p.x = (int)pos.x;
- p.y = (int)pos.y;
- ClientToScreen(m_hWnd, &p);
-
- SetCursorPos(p.x, p.y);
-}
-
-// Choosing the type of cursor for the mouse.
-
-void CD3DApplication::SetMouseType(D3DMouse type)
-{
- HCURSOR hc;
-
- if ( type == D3DMOUSEHAND )
- {
- hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORHAND));
- }
- else if ( type == D3DMOUSECROSS )
- {
- hc = LoadCursor(NULL, IDC_CROSS);
- }
- else if ( type == D3DMOUSEEDIT )
- {
- hc = LoadCursor(NULL, IDC_IBEAM);
- }
- else if ( type == D3DMOUSENO )
- {
- hc = LoadCursor(NULL, IDC_NO);
- }
- else if ( type == D3DMOUSEMOVE )
- {
- hc = LoadCursor(NULL, IDC_SIZEALL);
- }
- else if ( type == D3DMOUSEMOVEH )
- {
- hc = LoadCursor(NULL, IDC_SIZEWE);
- }
- else if ( type == D3DMOUSEMOVEV )
- {
- hc = LoadCursor(NULL, IDC_SIZENS);
- }
- else if ( type == D3DMOUSEMOVED )
- {
- hc = LoadCursor(NULL, IDC_SIZENESW);
- }
- else if ( type == D3DMOUSEMOVEI )
- {
- hc = LoadCursor(NULL, IDC_SIZENWSE);
- }
- else if ( type == D3DMOUSEWAIT )
- {
- hc = LoadCursor(NULL, IDC_WAIT);
- }
- else if ( type == D3DMOUSESCROLLL )
- {
- hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORSCROLLL));
- }
- else if ( type == D3DMOUSESCROLLR )
- {
- hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORSCROLLR));
- }
- else if ( type == D3DMOUSESCROLLU )
- {
- hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORSCROLLU));
- }
- else if ( type == D3DMOUSESCROLLD )
- {
- hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORSCROLLD));
- }
- else if ( type == D3DMOUSETARGET )
- {
- hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORTARGET));
- }
- else
- {
- hc = LoadCursor(NULL, IDC_ARROW);
- }
-
- if ( hc != NULL )
- {
- SetCursor(hc);
- }
-}
-
-// Choice of mode for the mouse.
-
-void CD3DApplication::SetNiceMouse(bool bNice)
-{
- if ( bNice == m_bNiceMouse ) return;
- m_bNiceMouse = bNice;
-
- if ( m_bNiceMouse )
- {
- ShowCursor(false); // hides the ugly windows mouse
- SetCursor(NULL);
- }
- else
- {
- ShowCursor(true); // shows the ugly windows mouse
- SetCursor(LoadCursor(NULL, IDC_ARROW));
- }
-}
-
-// Whether to use the mouse pretty shaded.
-
-bool CD3DApplication::RetNiceMouse()
-{
- if ( m_pDeviceInfo->bWindowed ) return false;
- if ( !m_pDeviceInfo->bHardware ) return false;
-
- return m_bNiceMouse;
-}
-
-// Indicates whether it is possible to use the mouse pretty shaded.
-
-bool CD3DApplication::RetNiceMouseCap()
-{
- if ( m_pDeviceInfo->bWindowed ) return false;
- if ( !m_pDeviceInfo->bHardware ) return false;
-
- return true;
-}
-
-
-// Static msg handler which passes messages to the application class.
-
-LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
-{
- if ( g_pD3DApp != 0 )
- {
- Event event;
- short move;
-
- ZeroMemory(&event, sizeof(Event));
-
-#if 0
- if ( uMsg == WM_KEYDOWN ||
- uMsg == WM_CHAR ||
- uMsg == WM_XBUTTONDOWN ||
- uMsg == WM_XBUTTONUP )
- {
- char s[100];
- sprintf(s, "event: %d %d %d\n", uMsg, wParam, lParam);
- OutputDebugString(s);
- }
-#endif
-
- if ( uMsg == WM_LBUTTONDOWN ) event.event = EVENT_LBUTTONDOWN;
- if ( uMsg == WM_RBUTTONDOWN ) event.event = EVENT_RBUTTONDOWN;
- if ( uMsg == WM_LBUTTONUP ) event.event = EVENT_LBUTTONUP;
- if ( uMsg == WM_RBUTTONUP ) event.event = EVENT_RBUTTONUP;
- if ( uMsg == WM_MOUSEMOVE ) event.event = EVENT_MOUSEMOVE;
- if ( uMsg == WM_KEYDOWN ) event.event = EVENT_KEYDOWN;
- if ( uMsg == WM_KEYUP ) event.event = EVENT_KEYUP;
- if ( uMsg == WM_CHAR ) event.event = EVENT_CHAR;
-
- if ( uMsg == WM_XBUTTONUP )
- {
- if ( (wParam>>16) == XBUTTON1 ) event.event = EVENT_HYPER_PREV;
- if ( (wParam>>16) == XBUTTON2 ) event.event = EVENT_HYPER_NEXT;
- }
-
- event.param = wParam;
- event.axeX = AxeLimit(g_pD3DApp->m_axeKey.x + g_pD3DApp->m_axeJoy.x);
- event.axeY = AxeLimit(g_pD3DApp->m_axeKey.y + g_pD3DApp->m_axeJoy.y);
- event.axeZ = AxeLimit(g_pD3DApp->m_axeKey.z + g_pD3DApp->m_axeJoy.z);
- event.keyState = g_pD3DApp->m_keyState;
-
- if ( uMsg == WM_LBUTTONDOWN ||
- uMsg == WM_RBUTTONDOWN ||
- uMsg == WM_LBUTTONUP ||
- uMsg == WM_RBUTTONUP ||
- uMsg == WM_MOUSEMOVE ) // mouse event?
- {
- event.pos = g_pD3DApp->ConvPosToInterface(hWnd, lParam);
- g_pD3DApp->m_mousePos = event.pos;
- g_pD3DApp->m_pD3DEngine->SetMousePos(event.pos);
- }
-
- if ( uMsg == WM_MOUSEWHEEL ) // mouse wheel?
- {
- event.event = EVENT_KEYDOWN;
- event.pos = g_pD3DApp->m_mousePos;
- move = HIWORD(wParam);
- if ( move/WHEEL_DELTA > 0 ) event.param = VK_WHEELUP;
- if ( move/WHEEL_DELTA < 0 ) event.param = VK_WHEELDOWN;
- }
- if ( g_pD3DApp->m_mshMouseWheel != 0 &&
- uMsg == g_pD3DApp->m_mshMouseWheel ) // Logitech mouse wheel?
- {
- event.event = EVENT_KEYDOWN;
- event.pos = g_pD3DApp->m_mousePos;
- move = LOWORD(wParam);
- if ( move/WHEEL_DELTA > 0 ) event.param = VK_WHEELUP;
- if ( move/WHEEL_DELTA < 0 ) event.param = VK_WHEELDOWN;
- }
-
- if ( event.event == EVENT_KEYDOWN ||
- event.event == EVENT_KEYUP ||
- event.event == EVENT_CHAR )
- {
- if ( event.param == 0 )
- {
- event.event = EVENT_NULL;
- }
- }
-
- if ( g_pD3DApp->m_pRobotMain != 0 && event.event != 0 )
- {
- g_pD3DApp->m_pRobotMain->EventProcess(event);
-//? if ( !g_pD3DApp->RetNiceMouse() )
-//? {
-//? g_pD3DApp->SetMouseType(g_pD3DApp->m_pD3DEngine->RetMouseType());
-//? }
- }
- if ( g_pD3DApp->m_pD3DEngine != 0 )
- {
- g_pD3DApp->m_pD3DEngine->MsgProc( hWnd, uMsg, wParam, lParam );
- }
- return g_pD3DApp->MsgProc( hWnd, uMsg, wParam, lParam );
- }
-
- return DefWindowProc( hWnd, uMsg, wParam, lParam );
-}
-
-
-// Minimal message proc function for the about box.
-
-BOOL CALLBACK AboutProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM )
-{
- if( WM_COMMAND == uMsg )
- if( IDOK == LOWORD(wParam) || IDCANCEL == LOWORD(wParam) )
- EndDialog( hWnd, TRUE );
-
- return WM_INITDIALOG == uMsg ? TRUE : FALSE;
-}
-
-
-
-// Ignore keypresses.
-
-void CD3DApplication::FlushPressKey()
-{
- m_keyState = 0;
- m_axeKey = Math::Vector(0.0f, 0.0f, 0.0f);
- m_axeJoy = Math::Vector(0.0f, 0.0f, 0.0f);
-}
-
-// Resets the default keys.
-
-void CD3DApplication::ResetKey()
-{
- int i;
-
- for ( i=0 ; i<50 ; i++ )
- {
- m_key[i][0] = 0;
- m_key[i][1] = 0;
- }
- m_key[KEYRANK_LEFT ][0] = VK_LEFT;
- m_key[KEYRANK_RIGHT ][0] = VK_RIGHT;
- m_key[KEYRANK_UP ][0] = VK_UP;
- m_key[KEYRANK_DOWN ][0] = VK_DOWN;
- m_key[KEYRANK_GUP ][0] = VK_SHIFT;
- m_key[KEYRANK_GDOWN ][0] = VK_CONTROL;
- m_key[KEYRANK_CAMERA ][0] = VK_SPACE;
- m_key[KEYRANK_CAMERA ][1] = VK_BUTTON2;
- m_key[KEYRANK_DESEL ][0] = VK_NUMPAD0;
- m_key[KEYRANK_DESEL ][1] = VK_BUTTON6;
- m_key[KEYRANK_ACTION ][0] = VK_RETURN;
- m_key[KEYRANK_ACTION ][1] = VK_BUTTON1;
- m_key[KEYRANK_NEAR ][0] = VK_ADD;
- m_key[KEYRANK_NEAR ][1] = VK_BUTTON5;
- m_key[KEYRANK_AWAY ][0] = VK_SUBTRACT;
- m_key[KEYRANK_AWAY ][1] = VK_BUTTON4;
- m_key[KEYRANK_NEXT ][0] = VK_TAB;
- m_key[KEYRANK_NEXT ][1] = VK_BUTTON3;
- m_key[KEYRANK_HUMAN ][0] = VK_HOME;
- m_key[KEYRANK_HUMAN ][1] = VK_BUTTON7;
- m_key[KEYRANK_QUIT ][0] = VK_ESCAPE;
- m_key[KEYRANK_HELP ][0] = VK_F1;
- m_key[KEYRANK_PROG ][0] = VK_F2;
- m_key[KEYRANK_CBOT ][0] = VK_F3;
- m_key[KEYRANK_VISIT ][0] = VK_DECIMAL;
- m_key[KEYRANK_SPEED10][0] = VK_F4;
- m_key[KEYRANK_SPEED15][0] = VK_F5;
- m_key[KEYRANK_SPEED20][0] = VK_F6;
-// m_key[KEYRANK_SPEED30][0] = VK_F7;
-}
-
-// Modifies a button.
-
-void CD3DApplication::SetKey(int keyRank, int option, int key)
-{
- if ( keyRank < 0 ||
- keyRank >= 50 ) return;
-
- if ( option < 0 ||
- option >= 2 ) return;
-
- m_key[keyRank][option] = key;
-}
-
-// Gives a hint.
-
-int CD3DApplication::RetKey(int keyRank, int option)
-{
- if ( keyRank < 0 ||
- keyRank >= 50 ) return 0;
-
- if ( option < 0 ||
- option >= 2 ) return 0;
-
- return m_key[keyRank][option];
-}
-
-
-
-// Use the joystick or keyboard.
-
-void CD3DApplication::SetJoystick(bool bEnable)
-{
- m_bJoystick = bEnable;
-
- if ( m_bJoystick ) // joystick ?
- {
- if ( !InitDirectInput(m_instance, m_hWnd) ) // initialise joystick
- {
- m_bJoystick = false;
- }
- else
- {
- SetAcquire(true);
- SetTimer(m_hWnd, 0, 1000/30, NULL);
- }
- }
- else // keyboard?
- {
- KillTimer(m_hWnd, 0);
- SetAcquire(false);
- FreeDirectInput();
- }
-}
-
-bool CD3DApplication::RetJoystick()
-{
- return m_bJoystick;
-}
-
-
-// Message handling function.
-
-LRESULT CD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam,
- LPARAM lParam )
-{
- HRESULT hr;
- DIJOYSTATE js;
- int i;
-
- // The F10 key sends another message to activate
- // menu in standard Windows applications!
- if ( uMsg == WM_SYSKEYDOWN && wParam == VK_F10 )
- {
- uMsg = WM_KEYDOWN;
- }
- if ( uMsg == WM_SYSKEYUP && wParam == VK_F10 )
- {
- uMsg = WM_KEYUP;
- }
-
- // Mange event "menu" sent by Alt or F10.
- if ( uMsg == WM_SYSCOMMAND && wParam == SC_KEYMENU )
- {
- return 0;
- }
-
- if ( uMsg == WM_KEYDOWN || uMsg == WM_KEYUP )
- {
- if ( GetKeyState(VK_SHIFT) & 0x8000 )
- {
- m_keyState |= KS_SHIFT;
- }
- else
- {
- m_keyState &= ~KS_SHIFT;
- }
-
- if ( GetKeyState(VK_CONTROL) & 0x8000 )
- {
- m_keyState |= KS_CONTROL;
- }
- else
- {
- m_keyState &= ~KS_CONTROL;
- }
- }
-
- switch( uMsg )
- {
- case WM_KEYDOWN:
- if ( wParam == m_key[KEYRANK_UP ][0] ) m_axeKey.y = 1.0f;
- if ( wParam == m_key[KEYRANK_UP ][1] ) m_axeKey.y = 1.0f;
- if ( wParam == m_key[KEYRANK_DOWN ][0] ) m_axeKey.y = -1.0f;
- if ( wParam == m_key[KEYRANK_DOWN ][1] ) m_axeKey.y = -1.0f;
- if ( wParam == m_key[KEYRANK_LEFT ][0] ) m_axeKey.x = -1.0f;
- if ( wParam == m_key[KEYRANK_LEFT ][1] ) m_axeKey.x = -1.0f;
- if ( wParam == m_key[KEYRANK_RIGHT][0] ) m_axeKey.x = 1.0f;
- if ( wParam == m_key[KEYRANK_RIGHT][1] ) m_axeKey.x = 1.0f;
- if ( wParam == m_key[KEYRANK_GUP ][0] ) m_axeKey.z = 1.0f;
- if ( wParam == m_key[KEYRANK_GUP ][1] ) m_axeKey.z = 1.0f;
- if ( wParam == m_key[KEYRANK_GDOWN][0] ) m_axeKey.z = -1.0f;
- if ( wParam == m_key[KEYRANK_GDOWN][1] ) m_axeKey.z = -1.0f;
- if ( wParam == m_key[KEYRANK_NEAR ][0] ) m_keyState |= KS_NUMPLUS;
- if ( wParam == m_key[KEYRANK_NEAR ][1] ) m_keyState |= KS_NUMPLUS;
- if ( wParam == m_key[KEYRANK_AWAY ][0] ) m_keyState |= KS_NUMMINUS;
- if ( wParam == m_key[KEYRANK_AWAY ][1] ) m_keyState |= KS_NUMMINUS;
- if ( wParam == VK_PRIOR ) m_keyState |= KS_PAGEUP;
- if ( wParam == VK_NEXT ) m_keyState |= KS_PAGEDOWN;
-//? if ( wParam == VK_SHIFT ) m_keyState |= KS_SHIFT;
-//? if ( wParam == VK_CONTROL ) m_keyState |= KS_CONTROL;
- if ( wParam == VK_NUMPAD8 ) m_keyState |= KS_NUMUP;
- if ( wParam == VK_NUMPAD2 ) m_keyState |= KS_NUMDOWN;
- if ( wParam == VK_NUMPAD4 ) m_keyState |= KS_NUMLEFT;
- if ( wParam == VK_NUMPAD6 ) m_keyState |= KS_NUMRIGHT;
- break;
-
- case WM_KEYUP:
- if ( wParam == m_key[KEYRANK_UP ][0] ) m_axeKey.y = 0.0f;
- if ( wParam == m_key[KEYRANK_UP ][1] ) m_axeKey.y = 0.0f;
- if ( wParam == m_key[KEYRANK_DOWN ][0] ) m_axeKey.y = 0.0f;
- if ( wParam == m_key[KEYRANK_DOWN ][1] ) m_axeKey.y = 0.0f;
- if ( wParam == m_key[KEYRANK_LEFT ][0] ) m_axeKey.x = 0.0f;
- if ( wParam == m_key[KEYRANK_LEFT ][1] ) m_axeKey.x = 0.0f;
- if ( wParam == m_key[KEYRANK_RIGHT][0] ) m_axeKey.x = 0.0f;
- if ( wParam == m_key[KEYRANK_RIGHT][1] ) m_axeKey.x = 0.0f;
- if ( wParam == m_key[KEYRANK_GUP ][0] ) m_axeKey.z = 0.0f;
- if ( wParam == m_key[KEYRANK_GUP ][1] ) m_axeKey.z = 0.0f;
- if ( wParam == m_key[KEYRANK_GDOWN][0] ) m_axeKey.z = 0.0f;
- if ( wParam == m_key[KEYRANK_GDOWN][1] ) m_axeKey.z = 0.0f;
- if ( wParam == m_key[KEYRANK_NEAR ][0] ) m_keyState &= ~KS_NUMPLUS;
- if ( wParam == m_key[KEYRANK_NEAR ][1] ) m_keyState &= ~KS_NUMPLUS;
- if ( wParam == m_key[KEYRANK_AWAY ][0] ) m_keyState &= ~KS_NUMMINUS;
- if ( wParam == m_key[KEYRANK_AWAY ][1] ) m_keyState &= ~KS_NUMMINUS;
- if ( wParam == VK_PRIOR ) m_keyState &= ~KS_PAGEUP;
- if ( wParam == VK_NEXT ) m_keyState &= ~KS_PAGEDOWN;
-//? if ( wParam == VK_SHIFT ) m_keyState &= ~KS_SHIFT;
-//? if ( wParam == VK_CONTROL ) m_keyState &= ~KS_CONTROL;
- if ( wParam == VK_NUMPAD8 ) m_keyState &= ~KS_NUMUP;
- if ( wParam == VK_NUMPAD2 ) m_keyState &= ~KS_NUMDOWN;
- if ( wParam == VK_NUMPAD4 ) m_keyState &= ~KS_NUMLEFT;
- if ( wParam == VK_NUMPAD6 ) m_keyState &= ~KS_NUMRIGHT;
- break;
-
- case WM_LBUTTONDOWN:
- m_keyState |= KS_MLEFT;
- break;
-
- case WM_RBUTTONDOWN:
- m_keyState |= KS_MRIGHT;
- break;
-
- case WM_LBUTTONUP:
- m_keyState &= ~KS_MLEFT;
- break;
-
- case WM_RBUTTONUP:
- m_keyState &= ~KS_MRIGHT;
- break;
-
- case WM_PAINT:
- // Handle paint messages when the app is not ready
- if( m_pFramework && !m_bReady )
- {
- if( m_pDeviceInfo->bWindowed )
- m_pFramework->ShowFrame();
- else
- m_pFramework->FlipToGDISurface( true );
- }
- break;
-
- case WM_MOVE:
- // If in windowed mode, move the Framework's window
- if( m_pFramework && m_bActive && m_bReady && m_pDeviceInfo->bWindowed )
- m_pFramework->Move( (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam) );
- break;
-
- case WM_SIZE:
- // Check to see if we are losing our window...
- if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam )
- {
- m_bActive = false;
- }
- else
- {
- m_bActive = true;
- }
-//? char s[100];
-//? sprintf(s, "WM_SIZE %d %d %d\n", m_bActive, m_bReady, m_pDeviceInfo->bWindowed);
-//? OutputDebugString(s);
-
- // A new window size will require a new backbuffer
- // size, so the 3D structures must be changed accordingly.
- if( m_bActive && m_bReady && m_pDeviceInfo->bWindowed )
- {
- m_bReady = false;
-
-//? OutputDebugString("WM_SIZE Change3DEnvironment\n");
- if( FAILED( hr = Change3DEnvironment() ) )
- return 0;
-
- m_bReady = true;
- }
- break;
-
- case WM_TIMER:
- if ( m_bActivateApp && m_bJoystick )
- {
- if ( UpdateInputState(js) )
- {
- m_axeJoy.x = js.lX/1000.0f+js.lRz/1000.0f; // tourner
- m_axeJoy.y = -js.lY/1000.0f; // avancer
- m_axeJoy.z = -js.rglSlider[0]/1000.0f; // monter
-
- m_axeJoy.x = Math::Neutral(m_axeJoy.x, 0.2f);
- m_axeJoy.y = Math::Neutral(m_axeJoy.y, 0.2f);
- m_axeJoy.z = Math::Neutral(m_axeJoy.z, 0.2f);
-
-//? char s[100];
-//? sprintf(s, "x=%d y=%d z=% x=%d y=%d z=%d\n", js.lX,js.lY,js.lZ,js.lRx,js.lRy,js.lRz);
-//? OutputDebugString(s);
-
- for ( i=0 ; i<32 ; i++ )
- {
- if ( js.rgbButtons[i] != 0 && !m_bJoyButton[i] )
- {
- m_bJoyButton[i] = true;
- PostMessage(m_hWnd, WM_KEYDOWN, VK_BUTTON1+i, 0);
- }
- if ( js.rgbButtons[i] == 0 && m_bJoyButton[i] )
- {
- m_bJoyButton[i] = false;
- PostMessage(m_hWnd, WM_KEYUP, VK_BUTTON1+i, 0);
- }
- }
- }
- else
- {
- OutputDebugString("UpdateInputState error\n");
- }
- }
- break;
-
- case WM_ACTIVATE:
- if( LOWORD(wParam) == WA_INACTIVE )
- {
- m_bActivateApp = false;
- }
- else
- {
- m_bActivateApp = true;
- }
-
- if ( m_bActivateApp && m_bJoystick )
- {
- SetAcquire(true); // re-enables the joystick
- }
- break;
-
- case MM_MCINOTIFY:
- if ( wParam == MCI_NOTIFY_SUCCESSFUL )
- {
- OutputDebugString("Event MM_MCINOTIFY\n");
- m_pSound->SuspendMusic();
- m_pSound->RestartMusic();
- }
- break;
-
- case WM_SETCURSOR:
- // Prevent a cursor in fullscreen mode
- if( m_bActive && m_bReady && !m_pDeviceInfo->bWindowed )
- {
-//? SetCursor(NULL);
- return 1;
- }
- break;
-
- case WM_ENTERMENULOOP:
- // Pause the app when menus are displayed
- Pause(true);
- break;
- case WM_EXITMENULOOP:
- Pause(false);
- break;
-
- case WM_ENTERSIZEMOVE:
- // Halt frame movement while the app is sizing or moving
- m_pD3DEngine->TimeEnterGel();
- break;
- case WM_EXITSIZEMOVE:
- m_pD3DEngine->TimeExitGel();
- break;
-
- case WM_NCHITTEST:
- // Prevent the user from selecting the menu in fullscreen mode
- if( !m_pDeviceInfo->bWindowed )
- return HTCLIENT;
-
- break;
-
- case WM_POWERBROADCAST:
- switch( wParam )
- {
- case PBT_APMQUERYSUSPEND:
- // At this point, the app should save any data for open
- // network connections, files, etc.., and prepare to go into
- // a suspended mode.
- return OnQuerySuspend( (DWORD)lParam );
-
- case PBT_APMRESUMESUSPEND:
- // At this point, the app should recover any data, network
- // connections, files, etc.., and resume running from when
- // the app was suspended.
- return OnResumeSuspend( (DWORD)lParam );
- }
- break;
-
- case WM_SYSCOMMAND:
- // Prevent moving/sizing and power loss in fullscreen mode
- switch( wParam )
- {
- case SC_MOVE:
- case SC_SIZE:
- case SC_MAXIMIZE:
- case SC_MONITORPOWER:
- if( false == m_pDeviceInfo->bWindowed )
- return 1;
- break;
- }
- break;
-
- case WM_COMMAND:
- switch( LOWORD(wParam) )
- {
- case IDM_CHANGEDEVICE:
- // Display the device-selection dialog box.
- if( m_bActive && m_bReady )
- {
- Pause(true);
-
- if( SUCCEEDED( D3DEnum_UserChangeDevice( &m_pDeviceInfo ) ) )
- {
- if( FAILED( hr = Change3DEnvironment() ) )
- return 0;
- }
- Pause(false);
- }
- return 0;
-
- case IDM_ABOUT:
- // Display the About box
- Pause(true);
- DialogBox( (HINSTANCE)GetWindowLong( hWnd, GWL_HINSTANCE ),
- MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutProc );
- Pause(false);
- return 0;
-
- case IDM_EXIT:
- // Recieved key/menu command to exit app
- SendMessage( hWnd, WM_CLOSE, 0, 0 );
- return 0;
- }
- break;
-
- case WM_GETMINMAXINFO:
- ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
- ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
- break;
-
- case WM_CLOSE:
- DestroyWindow( hWnd );
- return 0;
-
- case WM_DESTROY:
- Cleanup3DEnvironment();
- PostQuitMessage(0);
- return 0;
- }
-
- return DefWindowProc( hWnd, uMsg, wParam, lParam );
-}
-
-
-// Enumeration function to report valid pixel formats for z-buffers.
-
-HRESULT WINAPI EnumZBufferFormatsCallback(DDPIXELFORMAT* pddpf,
- VOID* pContext)
-{
- DDPIXELFORMAT* pddpfOut = (DDPIXELFORMAT*)pContext;
-
- char s[100];
- sprintf(s, "EnumZBufferFormatsCallback %d\n", pddpf->dwRGBBitCount);
- OutputDebugString(s);
-
- if( pddpfOut->dwRGBBitCount == pddpf->dwRGBBitCount )
- {
- (*pddpfOut) = (*pddpf);
- return D3DENUMRET_CANCEL;
- }
-
- return D3DENUMRET_OK;
-}
-
-// Internal function called by Create() to make and attach a zbuffer
-// to the renderer.
-
-HRESULT CD3DApplication::CreateZBuffer(GUID* pDeviceGUID)
-{
- HRESULT hr;
-
- // Check if the device supports z-bufferless hidden surface removal. If so,
- // we don't really need a z-buffer
- D3DDEVICEDESC7 ddDesc;
- m_pD3DDevice->GetCaps( &ddDesc );
- if( ddDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )
- return S_OK;
-
- // Get z-buffer dimensions from the render target
- DDSURFACEDESC2 ddsd;
- ddsd.dwSize = sizeof(ddsd);
- m_pddsRenderTarget->GetSurfaceDesc( &ddsd );
-
- // Setup the surface desc for the z-buffer.
- ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
- ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
- ddsd.ddpfPixelFormat.dwSize = 0; // Tag the pixel format as unitialized
-
- // Get an appropiate pixel format from enumeration of the formats. On the
- // first pass, we look for a zbuffer dpeth which is equal to the frame
- // buffer depth (as some cards unfornately require this).
- m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
- (VOID*)&ddsd.ddpfPixelFormat );
- if( 0 == ddsd.ddpfPixelFormat.dwSize )
- {
- // Try again, just accepting any 16-bit zbuffer
- ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
- m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
- (VOID*)&ddsd.ddpfPixelFormat );
-
- if( 0 == ddsd.ddpfPixelFormat.dwSize )
- {
- DEBUG_MSG( _T("Device doesn't support requested zbuffer format") );
- return D3DFWERR_NOZBUFFER;
- }
- }
-
- // Create and attach a z-buffer
- if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsDepthBuffer, NULL ) ) )
- {
- DEBUG_MSG( _T("Error: Couldn't create a ZBuffer surface") );
- if( hr != DDERR_OUTOFVIDEOMEMORY )
- return D3DFWERR_NOZBUFFER;
- DEBUG_MSG( _T("Error: Out of video memory") );
- return DDERR_OUTOFVIDEOMEMORY;
- }
-
- if( FAILED( m_pddsRenderTarget->AddAttachedSurface( m_pddsDepthBuffer ) ) )
- {
- DEBUG_MSG( _T("Error: Couldn't attach zbuffer to render surface") );
- return D3DFWERR_NOZBUFFER;
- }
-
- // Finally, this call rebuilds internal structures
- if( FAILED( m_pD3DDevice->SetRenderTarget( m_pddsRenderTarget, 0L ) ) )
- {
- DEBUG_MSG( _T("Error: SetRenderTarget() failed after attaching zbuffer!") );
- return D3DFWERR_NOZBUFFER;
- }
-
- return S_OK;
-}
-
-// Initializes the sample framework, then calls the app-specific function
-// to initialize device specific objects. This code is structured to
-// handled any errors that may occur duing initialization.
-
-HRESULT CD3DApplication::Initialize3DEnvironment()
-{
- HRESULT hr;
- DDSCAPS2 ddsCaps2;
- DWORD dwFrameworkFlags = 0L;
- DWORD dwTotal;
- DWORD dwFree;
-
- dwFrameworkFlags |= ( !m_pDeviceInfo->bWindowed ? D3DFW_FULLSCREEN : 0L );
- dwFrameworkFlags |= ( m_pDeviceInfo->bStereo ? D3DFW_STEREO : 0L );
- dwFrameworkFlags |= ( m_bAppUseZBuffer ? D3DFW_ZBUFFER : 0L );
-
- // Initialize the D3D framework
- if( SUCCEEDED( hr = m_pFramework->Initialize( m_hWnd,
- m_pDeviceInfo->pDriverGUID, m_pDeviceInfo->pDeviceGUID,
- &m_pDeviceInfo->ddsdFullscreenMode, dwFrameworkFlags ) ) )
- {
- m_pDD = m_pFramework->GetDirectDraw();
- m_pD3D = m_pFramework->GetDirect3D();
- m_pD3DDevice = m_pFramework->GetD3DDevice();
-
- m_pD3DEngine->SetD3DDevice(m_pD3DDevice);
-
- m_pddsRenderTarget = m_pFramework->GetRenderSurface();
-
- m_ddsdRenderTarget.dwSize = sizeof(m_ddsdRenderTarget);
- m_pddsRenderTarget->GetSurfaceDesc( &m_ddsdRenderTarget );
-
- // Request the amount of video memory.
- ZeroMemory(&ddsCaps2, sizeof(ddsCaps2));
- ddsCaps2.dwCaps = DDSCAPS_TEXTURE;
- dwTotal = 0;
- hr = m_pDD->GetAvailableVidMem(&ddsCaps2, &dwTotal, &dwFree);
- m_vidMemTotal = dwTotal;
-
- // Let the app run its startup code which creates the 3d scene.
- if( SUCCEEDED( hr = m_pD3DEngine->InitDeviceObjects() ) )
- {
-//? CreateZBuffer(m_pDeviceInfo->pDeviceGUID);
- return S_OK;
- }
- else
- {
- DeleteDeviceObjects();
- m_pFramework->DestroyObjects();
- }
- }
-
- // If we get here, the first initialization passed failed. If that was with a
- // hardware device, try again using a software rasterizer instead.
- if( m_pDeviceInfo->bHardware )
- {
- // Try again with a software rasterizer
- DisplayFrameworkError( hr, MSGWARN_SWITCHEDTOSOFTWARE );
- D3DEnum_SelectDefaultDevice( &m_pDeviceInfo, D3DENUM_SOFTWAREONLY );
- return Initialize3DEnvironment();
- }
-
- return hr;
-}
-
-
-// Handles driver, device, and/or mode changes for the app.
-
-HRESULT CD3DApplication::Change3DEnvironment()
-{
-#if 0
- HRESULT hr;
- static bool bOldWindowedState = true;
- static DWORD dwSavedStyle;
- static RECT rcSaved;
-
- // Release all scene objects that will be re-created for the new device
- DeleteDeviceObjects();
-
- // Release framework objects, so a new device can be created
- if( FAILED( hr = m_pFramework->DestroyObjects() ) )
- {
- DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
- SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
- return hr;
- }
-
- // Check if going from fullscreen to windowed mode, or vice versa.
- if( bOldWindowedState != m_pDeviceInfo->bWindowed )
- {
- if( m_pDeviceInfo->bWindowed )
- {
- // Coming from fullscreen mode, so restore window properties
- SetWindowLong( m_hWnd, GWL_STYLE, dwSavedStyle );
- SetWindowPos( m_hWnd, HWND_NOTOPMOST, rcSaved.left, rcSaved.top,
- ( rcSaved.right - rcSaved.left ),
- ( rcSaved.bottom - rcSaved.top ), SWP_SHOWWINDOW );
- }
- else
- {
- // Going to fullscreen mode, save/set window properties as needed
- dwSavedStyle = GetWindowLong( m_hWnd, GWL_STYLE );
- GetWindowRect( m_hWnd, &rcSaved );
- SetWindowLong( m_hWnd, GWL_STYLE, WS_POPUP|WS_SYSMENU|WS_VISIBLE );
- }
-
- bOldWindowedState = m_pDeviceInfo->bWindowed;
- }
-
- // Inform the framework class of the driver change. It will internally
- // re-create valid surfaces, a d3ddevice, etc.
- if( FAILED( hr = Initialize3DEnvironment() ) )
- {
- DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
- SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
- return hr;
- }
-
- return S_OK;
-#else
- HRESULT hr;
-
- // Release all scene objects that will be re-created for the new device
- DeleteDeviceObjects();
-
- // Release framework objects, so a new device can be created
- if( FAILED( hr = m_pFramework->DestroyObjects() ) )
- {
- DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
- SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
- return hr;
- }
-
- if( m_pDeviceInfo->bWindowed )
- {
- SetWindowPos(m_hWnd, HWND_NOTOPMOST, 10, 10, WINDOW_DX, WINDOW_DY, SWP_SHOWWINDOW);
- }
-
- // Inform the framework class of the driver change. It will internally
- // re-create valid surfaces, a d3ddevice, etc.
- if( FAILED( hr = Initialize3DEnvironment() ) )
- {
- DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
- SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
- return hr;
- }
-
- m_pD3DEngine->ChangeLOD();
-
- if( m_pDeviceInfo->bWindowed )
- {
- SetNiceMouse(false); // hides the ugly windows mouse
- }
-
- return S_OK;
-#endif
-}
-
-
-
-// Evolved throughout the game
-
-void CD3DApplication::StepSimul(float rTime)
-{
- Event event;
-
- if ( m_pRobotMain == 0 ) return;
-
- ZeroMemory(&event, sizeof(Event));
- event.event = EVENT_FRAME; // funny bug release "Maximize speed"!
- event.rTime = rTime;
- event.axeX = AxeLimit(m_axeKey.x + m_axeJoy.x);
- event.axeY = AxeLimit(m_axeKey.y + m_axeJoy.y);
- event.axeZ = AxeLimit(m_axeKey.z + m_axeJoy.z);
- event.keyState = m_keyState;
-
-//?char s[100];
-//?sprintf(s, "StepSimul %.3f\n", event.rTime);
-//?OutputDebugString(s);
- m_pRobotMain->EventProcess(event);
-}
-
-
-// Draws the scene.
-
-HRESULT CD3DApplication::Render3DEnvironment()
-{
- HRESULT hr;
- float rTime;
-
- // Check the cooperative level before rendering
- if( FAILED( hr = m_pDD->TestCooperativeLevel() ) )
- {
- switch( hr )
- {
- case DDERR_EXCLUSIVEMODEALREADYSET:
- case DDERR_NOEXCLUSIVEMODE:
- OutputDebugString("DDERR_EXCLUSIVEMODEALREADYSET\n");
- // Do nothing because some other app has exclusive mode
- return S_OK;
-
- case DDERR_WRONGMODE:
- OutputDebugString("DDERR_WRONGMODE\n");
- // The display mode changed on us. Resize accordingly
- if( m_pDeviceInfo->bWindowed )
- return Change3DEnvironment();
- break;
- }
- return hr;
- }
-
- // Get the relative time, in seconds
- rTime = m_pD3DEngine->TimeGet();
- if ( rTime > MAX_STEP ) rTime = MAX_STEP; // never more than 0.5s!
- m_aTime += rTime;
-
-#if !USE_THREAD
- if( FAILED( hr = m_pD3DEngine->FrameMove(rTime) ) )
- return hr;
-
- // FrameMove (animate) the scene
- StepSimul(rTime);
-#endif
-
- // Render the scene.
- if( FAILED( hr = m_pD3DEngine->Render() ) )
- return hr;
-
- DrawSuppl();
-
- // Show the frame rate, etc.
- if( m_bShowStats )
- ShowStats();
-
- // Show the frame on the primary surface.
- if( FAILED( hr = m_pFramework->ShowFrame() ) )
- {
- if( DDERR_SURFACELOST != hr )
- return hr;
-
- m_pFramework->RestoreSurfaces();
- m_pD3DEngine->RestoreSurfaces();
- }
-
- return S_OK;
-}
-
-
-// Cleanup scene objects
-
-VOID CD3DApplication::Cleanup3DEnvironment()
-{
- m_bActive = false;
- m_bReady = false;
-
- if( m_pFramework )
- {
- DeleteDeviceObjects();
- SAFE_DELETE( m_pFramework );
-
- m_pD3DEngine->FinalCleanup();
- }
-
- D3DEnum_FreeResources();
-//? FreeDirectInput();
-}
-
-// Called when the app is exitting, or the device is being changed,
-// this function deletes any device dependant objects.
-
-VOID CD3DApplication::DeleteDeviceObjects()
-{
- if( m_pFramework )
- {
- m_pD3DEngine->DeleteDeviceObjects();
- SAFE_RELEASE( m_pddsDepthBuffer );
- }
-}
-
-
-
-// Called in to toggle the pause state of the app. This function
-// brings the GDI surface to the front of the display, so drawing
-// output like message boxes and menus may be displayed.
-
-VOID CD3DApplication::Pause( bool bPause )
-{
- static DWORD dwAppPausedCount = 0L;
-
- dwAppPausedCount += ( bPause ? +1 : -1 );
- m_bReady = ( dwAppPausedCount ? false : true );
-
- // Handle the first pause request (of many, nestable pause requests)
- if( bPause && ( 1 == dwAppPausedCount ) )
- {
- // Get a surface for the GDI
- if( m_pFramework )
- m_pFramework->FlipToGDISurface( true );
-
- // Stop the scene from animating
- m_pD3DEngine->TimeEnterGel();
- }
-
- if( 0 == dwAppPausedCount )
- {
- // Restart the scene
- m_pD3DEngine->TimeExitGel();
- }
-}
-
-
-// Called when the app receives a PBT_APMQUERYSUSPEND message, meaning
-// the computer is about to be suspended. At this point, the app should
-// save any data for open network connections, files, etc.., and prepare
-// to go into a suspended mode.
-
-LRESULT CD3DApplication::OnQuerySuspend( DWORD dwFlags )
-{
- OutputDebugString("OnQuerySuspend\n");
- Pause(true);
- return true;
-}
-
-
-// Called when the app receives a PBT_APMRESUMESUSPEND message, meaning
-// the computer has just resumed from a suspended state. At this point,
-// the app should recover any data, network connections, files, etc..,
-// and resume running from when the app was suspended.
-
-LRESULT CD3DApplication::OnResumeSuspend( DWORD dwData )
-{
- OutputDebugString("OnResumeSuspend\n");
- Pause(false);
- return true;
-}
-
-
-// Draw all the additional graphic elements.
-
-void CD3DApplication::DrawSuppl()
-{
- HDC hDC;
- Math::Point p1, p2;
- POINT list[3];
- RECT rect;
- HPEN hPen;
- HGDIOBJ old;
- Math::Point pos;
- float d;
- int nbOut;
-
- if ( FAILED(m_pddsRenderTarget->GetDC(&hDC)) ) return;
-
- // Displays the selection rectangle.
- if ( m_pD3DEngine->GetHilite(p1, p2) )
- {
- nbOut = 0;
- if ( p1.x < 0.0f || p1.x > 1.0f ) nbOut ++;
- if ( p1.y < 0.0f || p1.y > 1.0f ) nbOut ++;
- if ( p2.x < 0.0f || p2.x > 1.0f ) nbOut ++;
- if ( p2.y < 0.0f || p2.y > 1.0f ) nbOut ++;
- if ( nbOut <= 2 )
- {
-#if 0
- time = Math::Mod(m_aTime, 0.5f);
- if ( time < 0.25f ) d = time*4.0f;
- else d = (2.0f-time*4.0f);
-#endif
-#if 0
- time = Math::Mod(m_aTime, 0.5f);
- if ( time < 0.4f ) d = time/0.4f;
- else d = 1.0f-(time-0.4f)/0.1f;
-#endif
-#if 1
- d = 0.5f+sinf(m_aTime*6.0f)*0.5f;
-#endif
- d *= (p2.x-p1.x)*0.1f;
- p1.x += d;
- p1.y += d;
- p2.x -= d;
- p2.y -= d;
-
- hPen = CreatePen(PS_SOLID, 1, RGB(255,255,0)); // yellow
- old = SelectObject(hDC, hPen);
-
- rect.left = (int)(p1.x*m_ddsdRenderTarget.dwWidth);
- rect.right = (int)(p2.x*m_ddsdRenderTarget.dwWidth);
- rect.top = (int)((1.0f-p2.y)*m_ddsdRenderTarget.dwHeight);
- rect.bottom = (int)((1.0f-p1.y)*m_ddsdRenderTarget.dwHeight);
-
- list[0].x = rect.left;
- list[0].y = rect.top+(rect.bottom-rect.top)/5;
- list[1].x = rect.left;
- list[1].y = rect.top;
- list[2].x = rect.left+(rect.right-rect.left)/5;
- list[2].y = rect.top;
- Polyline(hDC, list, 3);
-
- list[0].x = rect.right;
- list[0].y = rect.top+(rect.bottom-rect.top)/5;
- list[1].x = rect.right;
- list[1].y = rect.top;
- list[2].x = rect.right+(rect.left-rect.right)/5;
- list[2].y = rect.top;
- Polyline(hDC, list, 3);
-
- list[0].x = rect.left;
- list[0].y = rect.bottom+(rect.top-rect.bottom)/5;
- list[1].x = rect.left;
- list[1].y = rect.bottom;
- list[2].x = rect.left+(rect.right-rect.left)/5;
- list[2].y = rect.bottom;
- Polyline(hDC, list, 3);
-
- list[0].x = rect.right;
- list[0].y = rect.bottom+(rect.top-rect.bottom)/5;
- list[1].x = rect.right;
- list[1].y = rect.bottom;
- list[2].x = rect.right+(rect.left-rect.right)/5;
- list[2].y = rect.bottom;
- Polyline(hDC, list, 3);
-
- if ( old != 0 ) SelectObject(hDC, old);
- DeleteObject(hPen);
- }
- }
-
- m_pddsRenderTarget->ReleaseDC(hDC);
-}
-
-// Shows frame rate and dimensions of the rendering device.
-
-VOID CD3DApplication::ShowStats()
-{
- static FLOAT fFPS = 0.0f;
- static FLOAT fLastTime = 0.0f;
- static DWORD dwFrames = 0L;
-
- // Keep track of the time lapse and frame count
- FLOAT fTime = timeGetTime() * 0.001f; // Get current time in seconds
- ++dwFrames;
-
- // Update the frame rate once per second
- if( fTime - fLastTime > 1.0f )
- {
- fFPS = dwFrames / (fTime - fLastTime);
- fLastTime = fTime;
- dwFrames = 0L;
- }
-
- int t = m_pD3DEngine->RetStatisticTriangle();
-
- // Setup the text buffer to write out dimensions
- TCHAR buffer[100];
- sprintf( buffer, _T("%7.02f fps T=%d (%dx%dx%d)"), fFPS, t,
- m_ddsdRenderTarget.dwWidth, m_ddsdRenderTarget.dwHeight,
- m_ddsdRenderTarget.ddpfPixelFormat.dwRGBBitCount );
- OutputText( 400, 2, buffer );
-
- int x, y, i;
- if ( m_pD3DEngine->GetSpriteCoord(x, y) )
- {
- OutputText( x, y, "+" );
- }
-
- for ( i=0 ; i<10 ; i++ )
- {
- char* info = m_pD3DEngine->RetInfoText(i);
- x = 50;
- y = m_ddsdRenderTarget.dwHeight-20-i*20;
- OutputText( x, y, info );
- }
-}
-
-
-// Draws text on the window.
-
-VOID CD3DApplication::OutputText( DWORD x, DWORD y, TCHAR* str )
-{
- HDC hDC;
-
- // Get a DC for the surface. Then, write out the buffer
- if( m_pddsRenderTarget )
- {
- if( SUCCEEDED( m_pddsRenderTarget->GetDC(&hDC) ) )
- {
- SetTextColor( hDC, RGB(255,255,0) );
- SetBkMode( hDC, TRANSPARENT );
- ExtTextOut( hDC, x, y, 0, NULL, str, lstrlen(str), NULL );
- m_pddsRenderTarget->ReleaseDC(hDC);
- }
- }
-}
-
-
-
-
-// Defines a function that allocates memory for and initializes
-// members within a BITMAPINFOHEADER structure
-
-PBITMAPINFO CD3DApplication::CreateBitmapInfoStruct(HBITMAP hBmp)
-{
- BITMAP bmp;
- PBITMAPINFO pbmi;
- WORD cClrBits;
-
- // Retrieve the bitmap's color format, width, and height.
- if ( !GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp) )
- return 0;
-
- // Convert the color format to a count of bits.
- cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
-
- if ( cClrBits == 1 ) cClrBits = 1;
- else if ( cClrBits <= 4 ) cClrBits = 4;
- else if ( cClrBits <= 8 ) cClrBits = 8;
- else if ( cClrBits <= 16 ) cClrBits = 16;
- else if ( cClrBits <= 24 ) cClrBits = 24;
- else cClrBits = 32;
-
- // Allocate memory for the BITMAPINFO structure. (This structure
- // contains a BITMAPINFOHEADER structure and an array of RGBQUAD data
- // structures.)
- if ( cClrBits != 24 )
- {
- pbmi = (PBITMAPINFO)LocalAlloc(LPTR,
- sizeof(BITMAPINFOHEADER) +
- sizeof(RGBQUAD) * (2^cClrBits));
- }
- // There is no RGBQUAD array for the 24-bit-per-pixel format.
- else
- {
- pbmi = (PBITMAPINFO)LocalAlloc(LPTR,
- sizeof(BITMAPINFOHEADER));
- }
-
- // Initialize the fields in the BITMAPINFO structure.
- pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- pbmi->bmiHeader.biWidth = bmp.bmWidth;
- pbmi->bmiHeader.biHeight = bmp.bmHeight;
- pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
- pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
- if ( cClrBits < 24 )
- pbmi->bmiHeader.biClrUsed = 2^cClrBits;
-
- // If the bitmap is not compressed, set the BI_RGB flag.
- pbmi->bmiHeader.biCompression = BI_RGB;
-
- // Compute the number of bytes in the array of color
- // indices and store the result in biSizeImage.
- pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) /8
- * pbmi->bmiHeader.biHeight
- * cClrBits;
-
- // Set biClrImportant to 0, indicating that all of the
- // device colors are important.
- pbmi->bmiHeader.biClrImportant = 0;
-
- return pbmi;
-}
-
-// Defines a function that initializes the remaining structures,
-// retrieves the array of palette indices, opens the file, copies
-// the data, and closes the file.
-
-bool CD3DApplication::CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC)
-{
- FILE* file; // file handle
- BITMAPFILEHEADER hdr; // bitmap file-header
- PBITMAPINFOHEADER pbih; // bitmap info-header
- LPBYTE lpBits; // memory pointer
- DWORD dwTotal; // total count of bytes
-
- pbih = (PBITMAPINFOHEADER)pbi;
- lpBits = (LPBYTE)GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
- if ( !lpBits ) return false;
-
- // Retrieve the color table (RGBQUAD array) and the bits
- // (array of palette indices) from the DIB.
- if ( !GetDIBits(hDC, hBMP, 0, (WORD)pbih->biHeight,
- lpBits, pbi, DIB_RGB_COLORS) )
- return false;
-
- // Create the .BMP file.
- file = fopen(pszFile, "wb");
- if ( file == NULL ) return false;
-
- hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M"
-
- // Compute the size of the entire file.
- hdr.bfSize = (DWORD)(sizeof(BITMAPFILEHEADER) +
- pbih->biSize + pbih->biClrUsed
- * sizeof(RGBQUAD) + pbih->biSizeImage);
-
- hdr.bfReserved1 = 0;
- hdr.bfReserved2 = 0;
-
- // Compute the offset to the array of color indices.
- hdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) +
- pbih->biSize + pbih->biClrUsed
- * sizeof (RGBQUAD);
-
- // Copy the BITMAPFILEHEADER into the .BMP file.
- fwrite(&hdr, sizeof(BITMAPFILEHEADER), 1, file);
-
- // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
- fwrite(pbih, sizeof(BITMAPINFOHEADER)+pbih->biClrUsed*sizeof(RGBQUAD), 1, file);
-
- // Copy the array of color indices into the .BMP file.
- dwTotal = pbih->biSizeImage;
- fwrite(lpBits, dwTotal, 1, file);
-
- // Close the .BMP file.
- fclose(file);
-
- // Free memory.
- GlobalFree((HGLOBAL)lpBits);
- return true;
-}
-
-// Write a file. BMP screenshot.
-
-bool CD3DApplication::WriteScreenShot(char *filename, int width, int height)
-{
- D3DVIEWPORT7 vp;
- HDC hDC;
- HDC hDCImage;
- HBITMAP hb;
- PBITMAPINFO info;
- int dx, dy;
-
- m_pD3DDevice->GetViewport(&vp);
- dx = vp.dwWidth;
- dy = vp.dwHeight;
-
- if ( FAILED(m_pddsRenderTarget->GetDC(&hDC)) ) return false;
-
- hDCImage = CreateCompatibleDC(hDC);
- if ( hDCImage == 0 )
- {
- m_pddsRenderTarget->ReleaseDC(hDC);
- return false;
- }
-
- hb = CreateCompatibleBitmap(hDC, width, height);
- if ( hb == 0 )
- {
- DeleteDC(hDCImage);
- m_pddsRenderTarget->ReleaseDC(hDC);
- return false;
- }
-
- SelectObject(hDCImage, hb);
- StretchBlt(hDCImage, 0, 0, width, height, hDC, 0, 0, dx, dy, SRCCOPY);
-
- info = CreateBitmapInfoStruct(hb);
- if ( info == 0 )
- {
- DeleteObject(hb);
- DeleteDC(hDCImage);
- m_pddsRenderTarget->ReleaseDC(hDC);
- return false;
- }
-
- CreateBMPFile(filename, info, hb, hDCImage);
-
- DeleteObject(hb);
- DeleteDC(hDCImage);
- m_pddsRenderTarget->ReleaseDC(hDC);
- return true;
-}
-
-
-// Initializes an hDC on the rendering surface.
-
-bool CD3DApplication::GetRenderDC(HDC &hDC)
-{
- if ( FAILED(m_pddsRenderTarget->GetDC(&hDC)) ) return false;
- return true;
-}
-
-// Frees the hDC of the rendering surface.
-
-bool CD3DApplication::ReleaseRenderDC(HDC &hDC)
-{
- m_pddsRenderTarget->ReleaseDC(hDC);
- return true;
-}
-
-
-
-
-// Perform the list of all graphics devices available.
-// For the device selected, lists the full screen modes
-// possible.
-// buf* --> nom1<0> nom2<0> <0>
-
-bool CD3DApplication::EnumDevices(char *bufDevices, int lenDevices,
- char *bufModes, int lenModes,
- int &totalDevices, int &selectDevices,
- int &totalModes, int &selectModes)
-{
- D3DEnum_DeviceInfo* pDeviceList;
- D3DEnum_DeviceInfo* pDevice;
- DDSURFACEDESC2* pddsdMode;
- DWORD numDevices, device, mode;
- int len;
- char text[100];
-
- D3DEnum_GetDevices(&pDeviceList, &numDevices);
-
- selectDevices = -1;
- selectModes = -1;
- totalModes = 0;
- for( device=0 ; device<numDevices ; device++ )
- {
- pDevice = &pDeviceList[device];
-
- len = strlen(pDevice->strDesc)+1;
- if ( len >= lenDevices ) break; // bufDevices full!
- strcpy(bufDevices, pDevice->strDesc);
- bufDevices += len;
- lenDevices -= len;
-
- if ( pDevice == m_pDeviceInfo ) // select device ?
- {
- selectDevices = device;
-
- for( mode=0 ; mode<pDevice->dwNumModes ; mode++ )
- {
- pddsdMode = &pDevice->pddsdModes[mode];
-
- sprintf(text, "%ld x %ld x %ld",
- pddsdMode->dwWidth,
- pddsdMode->dwHeight,
- pddsdMode->ddpfPixelFormat.dwRGBBitCount);
-
- len = strlen(text)+1;
- if ( len >= lenModes ) break; // bufModes full !
- strcpy(bufModes, text);
- bufModes += len;
- lenModes -= len;
-
- if ( mode == m_pDeviceInfo->dwCurrentMode ) // select mode ?
- {
- selectModes = mode;
- }
- }
- bufModes[0] = 0;
- totalModes = pDevice->dwNumModes;
- }
- }
- bufDevices[0] = 0;
- totalDevices = numDevices;
-
- return true;
-}
-
-// Indicates whether it is in full screen mode.
-
-bool CD3DApplication::RetFullScreen()
-{
- return !m_pDeviceInfo->bWindowed;
-}
-
-// Change the graphics mode.
-
-bool CD3DApplication::ChangeDevice(char *deviceName, char *modeName,
- bool bFull)
-{
- D3DEnum_DeviceInfo* pDeviceList;
- D3DEnum_DeviceInfo* pDevice;
- DDSURFACEDESC2* pddsdMode;
- DWORD numDevices, device, mode;
- HRESULT hr;
- char text[100];
-
- D3DEnum_GetDevices(&pDeviceList, &numDevices);
-
- for( device=0 ; device<numDevices ; device++ )
- {
- pDevice = &pDeviceList[device];
-
- if ( strcmp(pDevice->strDesc, deviceName) == 0 ) // device found ?
- {
- for( mode=0 ; mode<pDevice->dwNumModes ; mode++ )
- {
- pddsdMode = &pDevice->pddsdModes[mode];
-
- sprintf(text, "%ld x %ld x %ld",
- pddsdMode->dwWidth,
- pddsdMode->dwHeight,
- pddsdMode->ddpfPixelFormat.dwRGBBitCount);
-
- if ( strcmp(text, modeName) == 0 ) // mode found ?
- {
- m_pDeviceInfo = pDevice;
- pDevice->bWindowed = !bFull;
- pDevice->dwCurrentMode = mode;
- pDevice->ddsdFullscreenMode = pDevice->pddsdModes[mode];
-
- m_bReady = false;
-
- if ( FAILED( hr = Change3DEnvironment() ) )
- {
- return false;
- }
-
- SetProfileString("Device", "Name", deviceName);
- SetProfileString("Device", "Mode", modeName);
- SetProfileInt("Device", "FullScreen", bFull);
- m_bReady = true;
- return true;
- }
- }
- }
- }
-
- return false;
-}
-
-
-
-// Displays error messages in a message box.
-
-VOID CD3DApplication::DisplayFrameworkError( HRESULT hr, DWORD dwType )
-{
- TCHAR strMsg[512];
-
- switch( hr )
- {
- case D3DENUMERR_ENGINE:
- lstrcpy( strMsg, _T("Could not create 3D Engine application!") );
- break;
- case D3DENUMERR_ROBOT:
- lstrcpy( strMsg, _T("Could not create Robot application!") );
- break;
- case D3DENUMERR_NODIRECTDRAW:
- lstrcpy( strMsg, _T("Could not create DirectDraw!") );
- break;
- case D3DENUMERR_NOCOMPATIBLEDEVICES:
- lstrcpy( strMsg, _T("Could not find any compatible Direct3D\n"
- "devices.") );
- break;
- case D3DENUMERR_SUGGESTREFRAST:
- lstrcpy( strMsg, _T("Could not find any compatible devices.\n\n"
- "Try enabling the reference rasterizer using\n"
- "EnableRefRast.reg.") );
- break;
- case D3DENUMERR_ENUMERATIONFAILED:
- lstrcpy( strMsg, _T("Enumeration failed. Your system may be in an\n"
- "unstable state and need to be rebooted") );
- break;
- case D3DFWERR_INITIALIZATIONFAILED:
- lstrcpy( strMsg, _T("Generic initialization error.\n\nEnable "
- "debug output for detailed information.") );
- break;
- case D3DFWERR_NODIRECTDRAW:
- lstrcpy( strMsg, _T("No DirectDraw") );
- break;
- case D3DFWERR_NODIRECT3D:
- lstrcpy( strMsg, _T("No Direct3D") );
- break;
- case D3DFWERR_INVALIDMODE:
- lstrcpy( strMsg, _T("COLOBOT requires a 16-bit (or higher) "
- "display mode\nto run in a window.\n\nPlease "
- "switch your desktop settings accordingly.") );
- break;
- case D3DFWERR_COULDNTSETCOOPLEVEL:
- lstrcpy( strMsg, _T("Could not set Cooperative Level") );
- break;
- case D3DFWERR_NO3DDEVICE:
- lstrcpy( strMsg, _T("Could not create the Direct3DDevice object.") );
-
- if( MSGWARN_SWITCHEDTOSOFTWARE == dwType )
- lstrcat( strMsg, _T("\nThe 3D hardware chipset may not support"
- "\nrendering in the current display mode.") );
- break;
- case D3DFWERR_NOZBUFFER:
- lstrcpy( strMsg, _T("No ZBuffer") );
- break;
- case D3DFWERR_INVALIDZBUFFERDEPTH:
- lstrcpy( strMsg, _T("Invalid Z-buffer depth. Try switching modes\n"
- "from 16- to 32-bit (or vice versa)") );
- break;
- case D3DFWERR_NOVIEWPORT:
- lstrcpy( strMsg, _T("No Viewport") );
- break;
- case D3DFWERR_NOPRIMARY:
- lstrcpy( strMsg, _T("No primary") );
- break;
- case D3DFWERR_NOCLIPPER:
- lstrcpy( strMsg, _T("No Clipper") );
- break;
- case D3DFWERR_BADDISPLAYMODE:
- lstrcpy( strMsg, _T("Bad display mode") );
- break;
- case D3DFWERR_NOBACKBUFFER:
- lstrcpy( strMsg, _T("No backbuffer") );
- break;
- case D3DFWERR_NONZEROREFCOUNT:
- lstrcpy( strMsg, _T("A DDraw object has a non-zero reference\n"
- "count (meaning it was not properly cleaned up)." ) );
- break;
- case D3DFWERR_NORENDERTARGET:
- lstrcpy( strMsg, _T("No render target") );
- break;
- case E_OUTOFMEMORY:
- lstrcpy( strMsg, _T("Not enough memory!") );
- break;
- case DDERR_OUTOFVIDEOMEMORY:
- lstrcpy( strMsg, _T("There was insufficient video memory "
- "to use the\nhardware device.") );
- break;
- default:
- lstrcpy( strMsg, _T("Generic application error.\n\nEnable "
- "debug output for detailed information.") );
- }
-
- if( MSGERR_APPMUSTEXIT == dwType )
- {
- lstrcat( strMsg, _T("\n\nCOLOBOT will now exit.") );
- MessageBox( NULL, strMsg, m_strWindowTitle, MB_ICONERROR|MB_OK );
- }
- else
- {
- if( MSGWARN_SWITCHEDTOSOFTWARE == dwType )
- lstrcat( strMsg, _T("\n\nSwitching to software rasterizer.") );
- MessageBox( NULL, strMsg, m_strWindowTitle, MB_ICONWARNING|MB_OK );
- }
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <windows.h>
+#include <winuser.h>
+#include <mmsystem.h>
+#include <stdio.h>
+#include <direct.h>
+#include <tchar.h>
+#include <zmouse.h>
+#include <dinput.h>
+
+#include "common/struct.h"
+#include "old/d3dtextr.h"
+#include "old/d3dengine.h"
+#include "common/language.h"
+#include "common/event.h"
+#include "common/profile.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "old/math3d.h"
+#include "old/joystick.h"
+#include "object/robotmain.h"
+#include "old/sound.h"
+#include "old/d3dapp.h"
+
+// fix for "MSH_MOUSEWHEEL undefined" error
+#ifdef UNICODE
+#define MSH_MOUSEWHEEL L"MSWHEEL_ROLLMSG"
+#else
+#define MSH_MOUSEWHEEL "MSWHEEL_ROLLMSG"
+#endif
+
+
+const int AUDIO_TRACK = 13; // total number of audio tracks on the CD
+const float MAX_STEP = 0.2f; // maximum time for a step
+
+const int WINDOW_DX = (640+6); // dimensions in windowed mode
+const int WINDOW_DY = (480+25);
+
+#define USE_THREAD false // true does not work!
+const float TIME_THREAD = 0.02f;
+
+
+
+
+// Limit the use of the controls keyboard & joystick.
+
+float AxeLimit(float value)
+{
+ if ( value < -1.0f ) value = -1.0f;
+ if ( value > 1.0f ) value = 1.0f;
+ return value;
+}
+
+
+// Entry point to the program. Initializes everything, and goes into a
+// message-processing loop. Idle time is used to render the scene.
+
+INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
+{
+ Error err;
+ char string[100];
+
+ CD3DApplication d3dApp; // single instance of the application
+
+ err = d3dApp.CheckMistery(strCmdLine);
+ if ( err != ERR_OK )
+ {
+ GetResource(RES_ERR, err, string);
+#if _NEWLOOK
+ MessageBox( NULL, string, _T("CeeBot"), MB_ICONERROR|MB_OK );
+#else
+ MessageBox( NULL, string, _T("COLOBOT"), MB_ICONERROR|MB_OK );
+#endif
+ return 0;
+ }
+
+ if ( FAILED(d3dApp.Create(hInst, strCmdLine)) )
+ {
+ return 0;
+ }
+
+ return d3dApp.Run(); // execution of all
+}
+
+
+// Internal variables and function prototypes.
+
+enum APPMSGTYPE { MSG_NONE, MSGERR_APPMUSTEXIT, MSGWARN_SWITCHEDTOSOFTWARE };
+
+static INT CALLBACK AboutProc( HWND, UINT, WPARAM, LPARAM );
+static LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
+
+static CD3DApplication* g_pD3DApp;
+
+
+
+// Constructor.
+
+CD3DApplication::CD3DApplication()
+{
+ int i;
+
+ m_iMan = new(CInstanceManager);
+ m_event = new CEvent(m_iMan);
+
+ m_pD3DEngine = 0;
+ m_pRobotMain = 0;
+ m_pSound = 0;
+ m_pFramework = 0;
+ m_instance = 0;
+ m_hWnd = 0;
+ m_pDD = 0;
+ m_pD3D = 0;
+ m_pD3DDevice = 0;
+
+ m_CDpath[0] = 0;
+
+ m_pddsRenderTarget = 0;
+ m_pddsDepthBuffer = 0;
+
+ m_keyState = 0;
+ m_axeKey = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_axeJoy = Math::Vector(0.0f, 0.0f, 0.0f);
+
+ m_vidMemTotal = 0;
+ m_bActive = false;
+ m_bActivateApp = false;
+ m_bReady = false;
+ m_bJoystick = false;
+ m_aTime = 0.0f;
+
+ for ( i=0 ; i<32 ; i++ )
+ {
+ m_bJoyButton[i] = false;
+ }
+
+#if _NEWLOOK
+ m_strWindowTitle = _T("CeeBot");
+#else
+ m_strWindowTitle = _T("COLOBOT");
+#endif
+ m_bAppUseZBuffer = true;
+ m_bAppUseStereo = true;
+ m_bShowStats = false;
+ m_bDebugMode = false;
+ m_bAudioState = true;
+ m_bAudioTrack = true;
+ m_bNiceMouse = false;
+ m_bSetupMode = true;
+ m_fnConfirmDevice = 0;
+
+ ResetKey();
+
+ g_pD3DApp = this;
+
+ // Request event sent by Logitech.
+ m_mshMouseWheel = RegisterWindowMessage(MSH_MOUSEWHEEL);
+
+ _mkdir("files\\");
+}
+
+
+// Destructor.
+
+CD3DApplication::~CD3DApplication()
+{
+ delete m_iMan;
+}
+
+
+
+// Returns the path of the CD.
+
+char* CD3DApplication::RetCDpath()
+{
+ return m_CDpath;
+}
+
+// Reads the information in the registry.
+
+Error CD3DApplication::RegQuery()
+{
+ FILE* file = NULL;
+ HKEY key;
+ LONG i;
+ DWORD type, len;
+ char filename[100];
+
+#if _NEWLOOK
+ #if _TEEN
+ i = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Epsitec\\CeeBot-Teen\\Setup",
+ #else
+ i = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Epsitec\\CeeBot-A\\Setup",
+ #endif
+#else
+ i = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Epsitec\\Colobot\\Setup",
+#endif
+ 0, KEY_READ, &key);
+ if ( i != ERROR_SUCCESS ) return ERR_INSTALL;
+
+ type = REG_SZ;
+ len = sizeof(m_CDpath);
+ i = RegQueryValueEx(key, "CDpath", NULL, &type, (LPBYTE)m_CDpath, &len);
+ if ( i != ERROR_SUCCESS || type != REG_SZ ) return ERR_INSTALL;
+
+ filename[0] = m_CDpath[0];
+ filename[1] = ':';
+ filename[2] = '\\';
+ filename[3] = 0;
+ i = GetDriveType(filename);
+ if ( i != DRIVE_CDROM ) return ERR_NOCD;
+
+ strcat(filename, "install.ini");
+ file = fopen(filename, "rb"); // install.ini file exist?
+ if ( file == NULL ) return ERR_NOCD;
+ fclose(file);
+
+ return ERR_OK;
+}
+
+// Checks for audio tracks on the CD.
+
+Error CD3DApplication::AudioQuery()
+{
+ MCI_OPEN_PARMS mciOpenParms;
+ MCI_STATUS_PARMS mciStatusParms;
+ DWORD dwReturn;
+ UINT deviceID;
+ char device[10];
+
+ // Open the device by specifying the device and filename.
+ // MCI will attempt to choose the MIDI mapper as the output port.
+ memset(&mciOpenParms, 0, sizeof(MCI_OPEN_PARMS));
+ mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
+ if ( m_CDpath[0] == 0 )
+ {
+ dwReturn = mciSendCommand(NULL,
+ MCI_OPEN,
+ MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,
+ (DWORD)(LPVOID)&mciOpenParms);
+ }
+ else
+ {
+ device[0] = m_CDpath[0];
+ device[1] = ':';
+ device[2] = 0;
+ mciOpenParms.lpstrElementName = device;
+ dwReturn = mciSendCommand(NULL,
+ MCI_OPEN,
+ MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_OPEN_ELEMENT,
+ (DWORD)(LPVOID)&mciOpenParms);
+ }
+ if ( dwReturn != 0 )
+ {
+ return ERR_NOCD;
+ }
+
+ // The device opened successfully; get the device ID.
+ deviceID = mciOpenParms.wDeviceID;
+
+ memset(&mciStatusParms, 0, sizeof(MCI_STATUS_PARMS));
+ mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
+ dwReturn = mciSendCommand(deviceID,
+ MCI_STATUS,
+ MCI_WAIT|MCI_STATUS_ITEM,
+ (DWORD)&mciStatusParms);
+ if ( dwReturn != 0 )
+ {
+ mciSendCommand(deviceID, MCI_CLOSE, 0, NULL);
+ return ERR_NOCD;
+ }
+
+ if ( mciStatusParms.dwReturn != AUDIO_TRACK )
+ {
+ mciSendCommand(deviceID, MCI_CLOSE, 0, NULL);
+ return ERR_NOCD;
+ }
+
+ mciSendCommand(deviceID, MCI_CLOSE, 0, NULL);
+ return ERR_OK;
+}
+
+// Checks for the key.
+
+Error CD3DApplication::CheckMistery(char *strCmdLine)
+{
+ if ( strstr(strCmdLine, "-debug") != 0 )
+ {
+ m_bShowStats = true;
+ SetDebugMode(true);
+ }
+
+ if ( strstr(strCmdLine, "-audiostate") != 0 )
+ {
+ m_bAudioState = false;
+ }
+
+ if ( strstr(strCmdLine, "-audiotrack") != 0 )
+ {
+ m_bAudioTrack = false;
+ }
+
+ m_CDpath[0] = 0;
+#if _FULL
+ if ( strstr(strCmdLine, "-nocd") == 0 && !m_bDebugMode )
+ {
+ Error err;
+
+ err = RegQuery();
+ if ( err != ERR_OK ) return err;
+
+ //?err = AudioQuery();
+ //?if ( err != ERR_OK ) return err;
+ }
+#endif
+#if _SCHOOL & _EDU
+ if ( strstr(strCmdLine, "-nosetup") != 0 )
+ {
+ m_bSetupMode = false;
+ }
+ m_bAudioTrack = false;
+#endif
+#if _SCHOOL & _PERSO
+ Error err = RegQuery();
+ if ( err != ERR_OK ) return err;
+ m_bAudioTrack = false;
+#endif
+#if _SCHOOL & _CEEBOTDEMO
+ m_bAudioTrack = false;
+#endif
+#if _NET
+ m_bAudioTrack = false;
+#endif
+#if _DEMO
+ m_bAudioTrack = false;
+#endif
+
+ return ERR_OK;
+}
+
+
+// Returns the total amount of video memory for textures.
+
+int CD3DApplication::GetVidMemTotal()
+{
+ return m_vidMemTotal;
+}
+
+bool CD3DApplication::IsVideo8MB()
+{
+ if ( m_vidMemTotal == 0 ) return false;
+ return (m_vidMemTotal <= 8388608L); // 8 Mb or less (2 ^ 23)?
+}
+
+bool CD3DApplication::IsVideo32MB()
+{
+ if ( m_vidMemTotal == 0 ) return false;
+ return (m_vidMemTotal > 16777216L); // more than 16 Mb (2 ^ 24)?
+}
+
+
+void CD3DApplication::SetShowStat(bool bShow)
+{
+ m_bShowStats = bShow;
+}
+
+bool CD3DApplication::RetShowStat()
+{
+ return m_bShowStats;
+}
+
+
+void CD3DApplication::SetDebugMode(bool bMode)
+{
+ m_bDebugMode = bMode;
+ D3DTextr_SetDebugMode(m_bDebugMode);
+}
+
+bool CD3DApplication::RetDebugMode()
+{
+ return m_bDebugMode;
+}
+
+bool CD3DApplication::RetSetupMode()
+{
+ return m_bSetupMode;
+}
+
+
+
+
+// Son process of time management.
+
+DWORD WINAPI ThreadRoutine(LPVOID)
+{
+ Event event;
+ float time;
+ int ms, start, end, delay;
+
+ ms = (int)(TIME_THREAD*1000.0f);
+ time = 0.0f;
+ while ( true )
+ {
+ start = timeGetTime();
+
+ g_pD3DApp->m_pD3DEngine->FrameMove(TIME_THREAD);
+
+ ZeroMemory(&event, sizeof(Event));
+ event.event = EVENT_FRAME;
+ event.rTime = TIME_THREAD;
+ event.axeX = AxeLimit(g_pD3DApp->m_axeKey.x + g_pD3DApp->m_axeJoy.x);
+ event.axeY = AxeLimit(g_pD3DApp->m_axeKey.y + g_pD3DApp->m_axeJoy.y);
+ event.axeZ = AxeLimit(g_pD3DApp->m_axeKey.z + g_pD3DApp->m_axeJoy.z);
+ event.keyState = g_pD3DApp->m_keyState;
+
+ if ( g_pD3DApp->m_pRobotMain != 0 )
+ {
+ g_pD3DApp->m_pRobotMain->EventProcess(event);
+ }
+
+ end = timeGetTime();
+
+ delay = ms-(end-start);
+ if ( delay > 0 )
+ {
+ Sleep(delay); // waiting 20ms-used
+ }
+ time += TIME_THREAD;
+ }
+ return 0;
+}
+
+
+// Called during device intialization, this code checks the device
+// for some minimum set of capabilities.
+
+HRESULT CD3DApplication::ConfirmDevice( DDCAPS* pddDriverCaps,
+ D3DDEVICEDESC7* pd3dDeviceDesc )
+{
+//? if( pd3dDeviceDesc->wMaxVertexBlendMatrices < 2 )
+//? return E_FAIL;
+
+ return S_OK;
+}
+
+// Create the application.
+
+HRESULT CD3DApplication::Create( HINSTANCE hInst, TCHAR* strCmdLine )
+{
+ HRESULT hr;
+ char deviceName[100];
+ char modeName[100];
+ int iValue;
+ DWORD style;
+ bool bFull, b3D;
+
+ m_instance = hInst;
+
+ InitCurrentDirectory();
+
+ // Enumerate available D3D devices. The callback is used so the app can
+ // confirm/reject each enumerated device depending on its capabilities.
+ if( FAILED( hr = D3DEnum_EnumerateDevices( m_fnConfirmDevice ) ) )
+ {
+ DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
+ return hr;
+ }
+
+ if( FAILED( hr = D3DEnum_SelectDefaultDevice( &m_pDeviceInfo ) ) )
+ {
+ DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
+ return hr;
+ }
+
+ if ( !m_bDebugMode )
+ {
+ m_pDeviceInfo->bWindowed = false; // full screen
+ }
+ if ( GetProfileInt("Device", "FullScreen", bFull) )
+ {
+ m_pDeviceInfo->bWindowed = !bFull;
+ }
+ m_pDeviceInfo->bWindowed = true;
+
+ // Create the 3D engine.
+ if( (m_pD3DEngine = new CD3DEngine(m_iMan, this)) == NULL )
+ {
+ DisplayFrameworkError( D3DENUMERR_ENGINE, MSGERR_APPMUSTEXIT );
+ return E_OUTOFMEMORY;
+ }
+ SetEngine(m_pD3DEngine);
+
+ // Initialize the app's custom scene stuff
+ if( FAILED( hr = m_pD3DEngine->OneTimeSceneInit() ) )
+ {
+ DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
+ return hr;
+ }
+
+ // Create a new CD3DFramework class. This class does all of our D3D
+ // initialization and manages the common D3D objects.
+ if( (m_pFramework = new CD3DFramework7()) == NULL )
+ {
+ DisplayFrameworkError( E_OUTOFMEMORY, MSGERR_APPMUSTEXIT );
+ return E_OUTOFMEMORY;
+ }
+
+ // Create the sound instance.
+ if( (m_pSound = new CSound(m_iMan)) == NULL )
+ {
+ DisplayFrameworkError( D3DENUMERR_SOUND, MSGERR_APPMUSTEXIT );
+ return E_OUTOFMEMORY;
+ }
+
+ // Create the robot application.
+ if( (m_pRobotMain = new CRobotMain(m_iMan)) == NULL )
+ {
+ DisplayFrameworkError( D3DENUMERR_ROBOT, MSGERR_APPMUSTEXIT );
+ return E_OUTOFMEMORY;
+ }
+
+ // Register the window class
+ WNDCLASS wndClass = { 0, WndProc, 0, 0, hInst,
+ LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN_ICON) ),
+ LoadCursor( NULL, IDC_ARROW ),
+ (HBRUSH)GetStockObject(WHITE_BRUSH),
+ NULL, _T("D3D Window") };
+ RegisterClass( &wndClass );
+
+ // Create the render window
+ style = WS_CAPTION|WS_VISIBLE;
+ if ( m_bDebugMode ) style |= WS_SYSMENU; // close box
+ m_hWnd = CreateWindow( _T("D3D Window"), m_strWindowTitle,
+//? WS_OVERLAPPEDWINDOW|WS_VISIBLE,
+ style, CW_USEDEFAULT, CW_USEDEFAULT,
+ WINDOW_DX, WINDOW_DY, 0L,
+//? LoadMenu( hInst, MAKEINTRESOURCE(IDR_MENU) ),
+ NULL,
+ hInst, 0L );
+ UpdateWindow( m_hWnd );
+
+ if ( !GetProfileInt("Setup", "Sound3D", b3D) )
+ {
+ b3D = true;
+ }
+ m_pSound->SetDebugMode(m_bDebugMode);
+ m_pSound->Create(m_hWnd, b3D);
+ m_pSound->CacheAll();
+ m_pSound->SetState(m_bAudioState);
+ m_pSound->SetAudioTrack(m_bAudioTrack);
+ m_pSound->SetCDpath(m_CDpath);
+
+ // Initialize the 3D environment for the app
+ if( FAILED( hr = Initialize3DEnvironment() ) )
+ {
+ DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
+ Cleanup3DEnvironment();
+ return E_FAIL;
+ }
+
+ // Change the display device driver.
+ GetProfileString("Device", "Name", deviceName, 100);
+ GetProfileString("Device", "Mode", modeName, 100);
+ GetProfileInt("Device", "FullScreen", bFull);
+ if ( deviceName[0] != 0 && modeName[0] != 0 && bFull )
+ {
+ ChangeDevice(deviceName, modeName, bFull);
+ }
+
+ // First execution?
+ if ( !GetProfileInt("Setup", "ObjectDirty", iValue) )
+ {
+ m_pD3DEngine->FirstExecuteAdapt(true);
+ }
+
+ // Creates the file colobot.ini at the first execution.
+ m_pRobotMain->CreateIni();
+
+#if _DEMO
+ m_pRobotMain->ChangePhase(PHASE_NAME);
+#else
+#if _NET | _SCHOOL
+ m_pRobotMain->ChangePhase(PHASE_WELCOME2);
+#else
+#if _FRENCH
+ m_pRobotMain->ChangePhase(PHASE_WELCOME2);
+#endif
+#if _ENGLISH
+ m_pRobotMain->ChangePhase(PHASE_WELCOME2);
+#endif
+#if _GERMAN
+ m_pRobotMain->ChangePhase(PHASE_WELCOME2);
+#endif
+#if _WG
+ m_pRobotMain->ChangePhase(PHASE_WELCOME1);
+#endif
+#if _POLISH
+ m_pRobotMain->ChangePhase(PHASE_WELCOME1);
+#endif
+#endif
+#endif
+ m_pD3DEngine->TimeInit();
+
+#if USE_THREAD
+ m_thread = CreateThread(NULL, 0, ThreadRoutine, this, 0, &m_threadId);
+ SetThreadPriority(m_thread, THREAD_PRIORITY_ABOVE_NORMAL);
+#endif
+
+ // The app is ready to go
+ m_bReady = true;
+
+ return S_OK;
+}
+
+
+// Message-processing loop. Idle time is used to render the scene.
+
+INT CD3DApplication::Run()
+{
+ // Load keyboard accelerators
+ HACCEL hAccel = LoadAccelerators( NULL, MAKEINTRESOURCE(IDR_MAIN_ACCEL) );
+
+ // Now we're ready to recieve and process Windows messages.
+ bool bGotMsg;
+ MSG msg;
+ PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE );
+
+ while( WM_QUIT != msg.message )
+ {
+ // Use PeekMessage() if the app is active, so we can use idle time to
+ // render the scene. Else, use GetMessage() to avoid eating CPU time.
+ if( m_bActive )
+ bGotMsg = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE );
+ else
+ bGotMsg = GetMessage( &msg, NULL, 0U, 0U );
+
+ if( bGotMsg )
+ {
+ // Translate and dispatch the message
+ if( TranslateAccelerator( m_hWnd, hAccel, &msg ) == 0 )
+ {
+ TranslateMessage( &msg );
+ DispatchMessage( &msg );
+ }
+ }
+ else
+ {
+ // Render a frame during idle time (no messages are waiting)
+ if( m_bActive && m_bReady )
+ {
+ Event event;
+
+ while ( m_event->GetEvent(event) )
+ {
+ if ( event.event == EVENT_QUIT )
+ {
+//? SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
+ m_pSound->StopMusic();
+ Cleanup3DEnvironment();
+ PostQuitMessage(0);
+ return msg.wParam;
+ }
+ m_pRobotMain->EventProcess(event);
+ }
+
+ if ( !RetNiceMouse() )
+ {
+ SetMouseType(m_pD3DEngine->RetMouseType());
+ }
+
+ if( FAILED( Render3DEnvironment() ) )
+ DestroyWindow( m_hWnd );
+ }
+ }
+ }
+
+ return msg.wParam;
+}
+
+
+
+// Conversion of the position of the mouse.
+// x: 0=left, 1=right
+// y: 0=down, 1=up
+
+Math::Point CD3DApplication::ConvPosToInterface(HWND hWnd, LPARAM lParam)
+{
+ POINT cpos;
+ Math::Point pos;
+ float px, py, w, h;
+
+ cpos.x = (short)LOWORD(lParam);
+ cpos.y = (short)HIWORD(lParam);
+
+ if ( !m_pDeviceInfo->bWindowed )
+ {
+ ClientToScreen(hWnd, &cpos);
+ }
+
+ px = (float)cpos.x;
+ py = (float)cpos.y;
+ w = (float)m_ddsdRenderTarget.dwWidth;
+ h = (float)m_ddsdRenderTarget.dwHeight;
+
+ pos.x = px/w;
+ pos.y = 1.0f-py/h;
+
+ return pos;
+}
+
+// Physically moves the mouse.
+
+void CD3DApplication::SetMousePos(Math::Point pos)
+{
+ POINT p;
+
+ pos.y = 1.0f-pos.y;
+
+ pos.x *= m_ddsdRenderTarget.dwWidth;
+ pos.y *= m_ddsdRenderTarget.dwHeight;
+
+ p.x = (int)pos.x;
+ p.y = (int)pos.y;
+ ClientToScreen(m_hWnd, &p);
+
+ SetCursorPos(p.x, p.y);
+}
+
+// Choosing the type of cursor for the mouse.
+
+void CD3DApplication::SetMouseType(D3DMouse type)
+{
+ HCURSOR hc;
+
+ if ( type == D3DMOUSEHAND )
+ {
+ hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORHAND));
+ }
+ else if ( type == D3DMOUSECROSS )
+ {
+ hc = LoadCursor(NULL, IDC_CROSS);
+ }
+ else if ( type == D3DMOUSEEDIT )
+ {
+ hc = LoadCursor(NULL, IDC_IBEAM);
+ }
+ else if ( type == D3DMOUSENO )
+ {
+ hc = LoadCursor(NULL, IDC_NO);
+ }
+ else if ( type == D3DMOUSEMOVE )
+ {
+ hc = LoadCursor(NULL, IDC_SIZEALL);
+ }
+ else if ( type == D3DMOUSEMOVEH )
+ {
+ hc = LoadCursor(NULL, IDC_SIZEWE);
+ }
+ else if ( type == D3DMOUSEMOVEV )
+ {
+ hc = LoadCursor(NULL, IDC_SIZENS);
+ }
+ else if ( type == D3DMOUSEMOVED )
+ {
+ hc = LoadCursor(NULL, IDC_SIZENESW);
+ }
+ else if ( type == D3DMOUSEMOVEI )
+ {
+ hc = LoadCursor(NULL, IDC_SIZENWSE);
+ }
+ else if ( type == D3DMOUSEWAIT )
+ {
+ hc = LoadCursor(NULL, IDC_WAIT);
+ }
+ else if ( type == D3DMOUSESCROLLL )
+ {
+ hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORSCROLLL));
+ }
+ else if ( type == D3DMOUSESCROLLR )
+ {
+ hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORSCROLLR));
+ }
+ else if ( type == D3DMOUSESCROLLU )
+ {
+ hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORSCROLLU));
+ }
+ else if ( type == D3DMOUSESCROLLD )
+ {
+ hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORSCROLLD));
+ }
+ else if ( type == D3DMOUSETARGET )
+ {
+ hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORTARGET));
+ }
+ else
+ {
+ hc = LoadCursor(NULL, IDC_ARROW);
+ }
+
+ if ( hc != NULL )
+ {
+ SetCursor(hc);
+ }
+}
+
+// Choice of mode for the mouse.
+
+void CD3DApplication::SetNiceMouse(bool bNice)
+{
+ if ( bNice == m_bNiceMouse ) return;
+ m_bNiceMouse = bNice;
+
+ if ( m_bNiceMouse )
+ {
+ ShowCursor(false); // hides the ugly windows mouse
+ SetCursor(NULL);
+ }
+ else
+ {
+ ShowCursor(true); // shows the ugly windows mouse
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ }
+}
+
+// Whether to use the mouse pretty shaded.
+
+bool CD3DApplication::RetNiceMouse()
+{
+ if ( m_pDeviceInfo->bWindowed ) return false;
+ if ( !m_pDeviceInfo->bHardware ) return false;
+
+ return m_bNiceMouse;
+}
+
+// Indicates whether it is possible to use the mouse pretty shaded.
+
+bool CD3DApplication::RetNiceMouseCap()
+{
+ if ( m_pDeviceInfo->bWindowed ) return false;
+ if ( !m_pDeviceInfo->bHardware ) return false;
+
+ return true;
+}
+
+
+// Static msg handler which passes messages to the application class.
+
+LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ if ( g_pD3DApp != 0 )
+ {
+ Event event;
+ short move;
+
+ ZeroMemory(&event, sizeof(Event));
+
+#if 0
+ if ( uMsg == WM_KEYDOWN ||
+ uMsg == WM_CHAR ||
+ uMsg == WM_XBUTTONDOWN ||
+ uMsg == WM_XBUTTONUP )
+ {
+ char s[100];
+ sprintf(s, "event: %d %d %d\n", uMsg, wParam, lParam);
+ OutputDebugString(s);
+ }
+#endif
+
+ if ( uMsg == WM_LBUTTONDOWN ) event.event = EVENT_LBUTTONDOWN;
+ if ( uMsg == WM_RBUTTONDOWN ) event.event = EVENT_RBUTTONDOWN;
+ if ( uMsg == WM_LBUTTONUP ) event.event = EVENT_LBUTTONUP;
+ if ( uMsg == WM_RBUTTONUP ) event.event = EVENT_RBUTTONUP;
+ if ( uMsg == WM_MOUSEMOVE ) event.event = EVENT_MOUSEMOVE;
+ if ( uMsg == WM_KEYDOWN ) event.event = EVENT_KEYDOWN;
+ if ( uMsg == WM_KEYUP ) event.event = EVENT_KEYUP;
+ if ( uMsg == WM_CHAR ) event.event = EVENT_CHAR;
+
+ if ( uMsg == WM_XBUTTONUP )
+ {
+ if ( (wParam>>16) == XBUTTON1 ) event.event = EVENT_HYPER_PREV;
+ if ( (wParam>>16) == XBUTTON2 ) event.event = EVENT_HYPER_NEXT;
+ }
+
+ event.param = wParam;
+ event.axeX = AxeLimit(g_pD3DApp->m_axeKey.x + g_pD3DApp->m_axeJoy.x);
+ event.axeY = AxeLimit(g_pD3DApp->m_axeKey.y + g_pD3DApp->m_axeJoy.y);
+ event.axeZ = AxeLimit(g_pD3DApp->m_axeKey.z + g_pD3DApp->m_axeJoy.z);
+ event.keyState = g_pD3DApp->m_keyState;
+
+ if ( uMsg == WM_LBUTTONDOWN ||
+ uMsg == WM_RBUTTONDOWN ||
+ uMsg == WM_LBUTTONUP ||
+ uMsg == WM_RBUTTONUP ||
+ uMsg == WM_MOUSEMOVE ) // mouse event?
+ {
+ event.pos = g_pD3DApp->ConvPosToInterface(hWnd, lParam);
+ g_pD3DApp->m_mousePos = event.pos;
+ g_pD3DApp->m_pD3DEngine->SetMousePos(event.pos);
+ }
+
+ if ( uMsg == WM_MOUSEWHEEL ) // mouse wheel?
+ {
+ event.event = EVENT_KEYDOWN;
+ event.pos = g_pD3DApp->m_mousePos;
+ move = HIWORD(wParam);
+ if ( move/WHEEL_DELTA > 0 ) event.param = VK_WHEELUP;
+ if ( move/WHEEL_DELTA < 0 ) event.param = VK_WHEELDOWN;
+ }
+ if ( g_pD3DApp->m_mshMouseWheel != 0 &&
+ uMsg == g_pD3DApp->m_mshMouseWheel ) // Logitech mouse wheel?
+ {
+ event.event = EVENT_KEYDOWN;
+ event.pos = g_pD3DApp->m_mousePos;
+ move = LOWORD(wParam);
+ if ( move/WHEEL_DELTA > 0 ) event.param = VK_WHEELUP;
+ if ( move/WHEEL_DELTA < 0 ) event.param = VK_WHEELDOWN;
+ }
+
+ if ( event.event == EVENT_KEYDOWN ||
+ event.event == EVENT_KEYUP ||
+ event.event == EVENT_CHAR )
+ {
+ if ( event.param == 0 )
+ {
+ event.event = EVENT_NULL;
+ }
+ }
+
+ if ( g_pD3DApp->m_pRobotMain != 0 && event.event != 0 )
+ {
+ g_pD3DApp->m_pRobotMain->EventProcess(event);
+//? if ( !g_pD3DApp->RetNiceMouse() )
+//? {
+//? g_pD3DApp->SetMouseType(g_pD3DApp->m_pD3DEngine->RetMouseType());
+//? }
+ }
+ if ( g_pD3DApp->m_pD3DEngine != 0 )
+ {
+ g_pD3DApp->m_pD3DEngine->MsgProc( hWnd, uMsg, wParam, lParam );
+ }
+ return g_pD3DApp->MsgProc( hWnd, uMsg, wParam, lParam );
+ }
+
+ return DefWindowProc( hWnd, uMsg, wParam, lParam );
+}
+
+
+// Minimal message proc function for the about box.
+
+BOOL CALLBACK AboutProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM )
+{
+ if( WM_COMMAND == uMsg )
+ if( IDOK == LOWORD(wParam) || IDCANCEL == LOWORD(wParam) )
+ EndDialog( hWnd, TRUE );
+
+ return WM_INITDIALOG == uMsg ? TRUE : FALSE;
+}
+
+
+
+// Ignore keypresses.
+
+void CD3DApplication::FlushPressKey()
+{
+ m_keyState = 0;
+ m_axeKey = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_axeJoy = Math::Vector(0.0f, 0.0f, 0.0f);
+}
+
+// Resets the default keys.
+
+void CD3DApplication::ResetKey()
+{
+ int i;
+
+ for ( i=0 ; i<50 ; i++ )
+ {
+ m_key[i][0] = 0;
+ m_key[i][1] = 0;
+ }
+ m_key[KEYRANK_LEFT ][0] = VK_LEFT;
+ m_key[KEYRANK_RIGHT ][0] = VK_RIGHT;
+ m_key[KEYRANK_UP ][0] = VK_UP;
+ m_key[KEYRANK_DOWN ][0] = VK_DOWN;
+ m_key[KEYRANK_GUP ][0] = VK_SHIFT;
+ m_key[KEYRANK_GDOWN ][0] = VK_CONTROL;
+ m_key[KEYRANK_CAMERA ][0] = VK_SPACE;
+ m_key[KEYRANK_CAMERA ][1] = VK_BUTTON2;
+ m_key[KEYRANK_DESEL ][0] = VK_NUMPAD0;
+ m_key[KEYRANK_DESEL ][1] = VK_BUTTON6;
+ m_key[KEYRANK_ACTION ][0] = VK_RETURN;
+ m_key[KEYRANK_ACTION ][1] = VK_BUTTON1;
+ m_key[KEYRANK_NEAR ][0] = VK_ADD;
+ m_key[KEYRANK_NEAR ][1] = VK_BUTTON5;
+ m_key[KEYRANK_AWAY ][0] = VK_SUBTRACT;
+ m_key[KEYRANK_AWAY ][1] = VK_BUTTON4;
+ m_key[KEYRANK_NEXT ][0] = VK_TAB;
+ m_key[KEYRANK_NEXT ][1] = VK_BUTTON3;
+ m_key[KEYRANK_HUMAN ][0] = VK_HOME;
+ m_key[KEYRANK_HUMAN ][1] = VK_BUTTON7;
+ m_key[KEYRANK_QUIT ][0] = VK_ESCAPE;
+ m_key[KEYRANK_HELP ][0] = VK_F1;
+ m_key[KEYRANK_PROG ][0] = VK_F2;
+ m_key[KEYRANK_CBOT ][0] = VK_F3;
+ m_key[KEYRANK_VISIT ][0] = VK_DECIMAL;
+ m_key[KEYRANK_SPEED10][0] = VK_F4;
+ m_key[KEYRANK_SPEED15][0] = VK_F5;
+ m_key[KEYRANK_SPEED20][0] = VK_F6;
+// m_key[KEYRANK_SPEED30][0] = VK_F7;
+}
+
+// Modifies a button.
+
+void CD3DApplication::SetKey(int keyRank, int option, int key)
+{
+ if ( keyRank < 0 ||
+ keyRank >= 50 ) return;
+
+ if ( option < 0 ||
+ option >= 2 ) return;
+
+ m_key[keyRank][option] = key;
+}
+
+// Gives a hint.
+
+int CD3DApplication::RetKey(int keyRank, int option)
+{
+ if ( keyRank < 0 ||
+ keyRank >= 50 ) return 0;
+
+ if ( option < 0 ||
+ option >= 2 ) return 0;
+
+ return m_key[keyRank][option];
+}
+
+
+
+// Use the joystick or keyboard.
+
+void CD3DApplication::SetJoystick(bool bEnable)
+{
+ m_bJoystick = bEnable;
+
+ if ( m_bJoystick ) // joystick ?
+ {
+ if ( !InitDirectInput(m_instance, m_hWnd) ) // initialise joystick
+ {
+ m_bJoystick = false;
+ }
+ else
+ {
+ SetAcquire(true);
+ SetTimer(m_hWnd, 0, 1000/30, NULL);
+ }
+ }
+ else // keyboard?
+ {
+ KillTimer(m_hWnd, 0);
+ SetAcquire(false);
+ FreeDirectInput();
+ }
+}
+
+bool CD3DApplication::RetJoystick()
+{
+ return m_bJoystick;
+}
+
+
+// Message handling function.
+
+LRESULT CD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam,
+ LPARAM lParam )
+{
+ HRESULT hr;
+ DIJOYSTATE js;
+ int i;
+
+ // The F10 key sends another message to activate
+ // menu in standard Windows applications!
+ if ( uMsg == WM_SYSKEYDOWN && wParam == VK_F10 )
+ {
+ uMsg = WM_KEYDOWN;
+ }
+ if ( uMsg == WM_SYSKEYUP && wParam == VK_F10 )
+ {
+ uMsg = WM_KEYUP;
+ }
+
+ // Mange event "menu" sent by Alt or F10.
+ if ( uMsg == WM_SYSCOMMAND && wParam == SC_KEYMENU )
+ {
+ return 0;
+ }
+
+ if ( uMsg == WM_KEYDOWN || uMsg == WM_KEYUP )
+ {
+ if ( GetKeyState(VK_SHIFT) & 0x8000 )
+ {
+ m_keyState |= KS_SHIFT;
+ }
+ else
+ {
+ m_keyState &= ~KS_SHIFT;
+ }
+
+ if ( GetKeyState(VK_CONTROL) & 0x8000 )
+ {
+ m_keyState |= KS_CONTROL;
+ }
+ else
+ {
+ m_keyState &= ~KS_CONTROL;
+ }
+ }
+
+ switch( uMsg )
+ {
+ case WM_KEYDOWN:
+ if ( wParam == m_key[KEYRANK_UP ][0] ) m_axeKey.y = 1.0f;
+ if ( wParam == m_key[KEYRANK_UP ][1] ) m_axeKey.y = 1.0f;
+ if ( wParam == m_key[KEYRANK_DOWN ][0] ) m_axeKey.y = -1.0f;
+ if ( wParam == m_key[KEYRANK_DOWN ][1] ) m_axeKey.y = -1.0f;
+ if ( wParam == m_key[KEYRANK_LEFT ][0] ) m_axeKey.x = -1.0f;
+ if ( wParam == m_key[KEYRANK_LEFT ][1] ) m_axeKey.x = -1.0f;
+ if ( wParam == m_key[KEYRANK_RIGHT][0] ) m_axeKey.x = 1.0f;
+ if ( wParam == m_key[KEYRANK_RIGHT][1] ) m_axeKey.x = 1.0f;
+ if ( wParam == m_key[KEYRANK_GUP ][0] ) m_axeKey.z = 1.0f;
+ if ( wParam == m_key[KEYRANK_GUP ][1] ) m_axeKey.z = 1.0f;
+ if ( wParam == m_key[KEYRANK_GDOWN][0] ) m_axeKey.z = -1.0f;
+ if ( wParam == m_key[KEYRANK_GDOWN][1] ) m_axeKey.z = -1.0f;
+ if ( wParam == m_key[KEYRANK_NEAR ][0] ) m_keyState |= KS_NUMPLUS;
+ if ( wParam == m_key[KEYRANK_NEAR ][1] ) m_keyState |= KS_NUMPLUS;
+ if ( wParam == m_key[KEYRANK_AWAY ][0] ) m_keyState |= KS_NUMMINUS;
+ if ( wParam == m_key[KEYRANK_AWAY ][1] ) m_keyState |= KS_NUMMINUS;
+ if ( wParam == VK_PRIOR ) m_keyState |= KS_PAGEUP;
+ if ( wParam == VK_NEXT ) m_keyState |= KS_PAGEDOWN;
+//? if ( wParam == VK_SHIFT ) m_keyState |= KS_SHIFT;
+//? if ( wParam == VK_CONTROL ) m_keyState |= KS_CONTROL;
+ if ( wParam == VK_NUMPAD8 ) m_keyState |= KS_NUMUP;
+ if ( wParam == VK_NUMPAD2 ) m_keyState |= KS_NUMDOWN;
+ if ( wParam == VK_NUMPAD4 ) m_keyState |= KS_NUMLEFT;
+ if ( wParam == VK_NUMPAD6 ) m_keyState |= KS_NUMRIGHT;
+ break;
+
+ case WM_KEYUP:
+ if ( wParam == m_key[KEYRANK_UP ][0] ) m_axeKey.y = 0.0f;
+ if ( wParam == m_key[KEYRANK_UP ][1] ) m_axeKey.y = 0.0f;
+ if ( wParam == m_key[KEYRANK_DOWN ][0] ) m_axeKey.y = 0.0f;
+ if ( wParam == m_key[KEYRANK_DOWN ][1] ) m_axeKey.y = 0.0f;
+ if ( wParam == m_key[KEYRANK_LEFT ][0] ) m_axeKey.x = 0.0f;
+ if ( wParam == m_key[KEYRANK_LEFT ][1] ) m_axeKey.x = 0.0f;
+ if ( wParam == m_key[KEYRANK_RIGHT][0] ) m_axeKey.x = 0.0f;
+ if ( wParam == m_key[KEYRANK_RIGHT][1] ) m_axeKey.x = 0.0f;
+ if ( wParam == m_key[KEYRANK_GUP ][0] ) m_axeKey.z = 0.0f;
+ if ( wParam == m_key[KEYRANK_GUP ][1] ) m_axeKey.z = 0.0f;
+ if ( wParam == m_key[KEYRANK_GDOWN][0] ) m_axeKey.z = 0.0f;
+ if ( wParam == m_key[KEYRANK_GDOWN][1] ) m_axeKey.z = 0.0f;
+ if ( wParam == m_key[KEYRANK_NEAR ][0] ) m_keyState &= ~KS_NUMPLUS;
+ if ( wParam == m_key[KEYRANK_NEAR ][1] ) m_keyState &= ~KS_NUMPLUS;
+ if ( wParam == m_key[KEYRANK_AWAY ][0] ) m_keyState &= ~KS_NUMMINUS;
+ if ( wParam == m_key[KEYRANK_AWAY ][1] ) m_keyState &= ~KS_NUMMINUS;
+ if ( wParam == VK_PRIOR ) m_keyState &= ~KS_PAGEUP;
+ if ( wParam == VK_NEXT ) m_keyState &= ~KS_PAGEDOWN;
+//? if ( wParam == VK_SHIFT ) m_keyState &= ~KS_SHIFT;
+//? if ( wParam == VK_CONTROL ) m_keyState &= ~KS_CONTROL;
+ if ( wParam == VK_NUMPAD8 ) m_keyState &= ~KS_NUMUP;
+ if ( wParam == VK_NUMPAD2 ) m_keyState &= ~KS_NUMDOWN;
+ if ( wParam == VK_NUMPAD4 ) m_keyState &= ~KS_NUMLEFT;
+ if ( wParam == VK_NUMPAD6 ) m_keyState &= ~KS_NUMRIGHT;
+ break;
+
+ case WM_LBUTTONDOWN:
+ m_keyState |= KS_MLEFT;
+ break;
+
+ case WM_RBUTTONDOWN:
+ m_keyState |= KS_MRIGHT;
+ break;
+
+ case WM_LBUTTONUP:
+ m_keyState &= ~KS_MLEFT;
+ break;
+
+ case WM_RBUTTONUP:
+ m_keyState &= ~KS_MRIGHT;
+ break;
+
+ case WM_PAINT:
+ // Handle paint messages when the app is not ready
+ if( m_pFramework && !m_bReady )
+ {
+ if( m_pDeviceInfo->bWindowed )
+ m_pFramework->ShowFrame();
+ else
+ m_pFramework->FlipToGDISurface( true );
+ }
+ break;
+
+ case WM_MOVE:
+ // If in windowed mode, move the Framework's window
+ if( m_pFramework && m_bActive && m_bReady && m_pDeviceInfo->bWindowed )
+ m_pFramework->Move( (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam) );
+ break;
+
+ case WM_SIZE:
+ // Check to see if we are losing our window...
+ if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam )
+ {
+ m_bActive = false;
+ }
+ else
+ {
+ m_bActive = true;
+ }
+//? char s[100];
+//? sprintf(s, "WM_SIZE %d %d %d\n", m_bActive, m_bReady, m_pDeviceInfo->bWindowed);
+//? OutputDebugString(s);
+
+ // A new window size will require a new backbuffer
+ // size, so the 3D structures must be changed accordingly.
+ if( m_bActive && m_bReady && m_pDeviceInfo->bWindowed )
+ {
+ m_bReady = false;
+
+//? OutputDebugString("WM_SIZE Change3DEnvironment\n");
+ if( FAILED( hr = Change3DEnvironment() ) )
+ return 0;
+
+ m_bReady = true;
+ }
+ break;
+
+ case WM_TIMER:
+ if ( m_bActivateApp && m_bJoystick )
+ {
+ if ( UpdateInputState(js) )
+ {
+ m_axeJoy.x = js.lX/1000.0f+js.lRz/1000.0f; // tourner
+ m_axeJoy.y = -js.lY/1000.0f; // avancer
+ m_axeJoy.z = -js.rglSlider[0]/1000.0f; // monter
+
+ m_axeJoy.x = Math::Neutral(m_axeJoy.x, 0.2f);
+ m_axeJoy.y = Math::Neutral(m_axeJoy.y, 0.2f);
+ m_axeJoy.z = Math::Neutral(m_axeJoy.z, 0.2f);
+
+//? char s[100];
+//? sprintf(s, "x=%d y=%d z=% x=%d y=%d z=%d\n", js.lX,js.lY,js.lZ,js.lRx,js.lRy,js.lRz);
+//? OutputDebugString(s);
+
+ for ( i=0 ; i<32 ; i++ )
+ {
+ if ( js.rgbButtons[i] != 0 && !m_bJoyButton[i] )
+ {
+ m_bJoyButton[i] = true;
+ PostMessage(m_hWnd, WM_KEYDOWN, VK_BUTTON1+i, 0);
+ }
+ if ( js.rgbButtons[i] == 0 && m_bJoyButton[i] )
+ {
+ m_bJoyButton[i] = false;
+ PostMessage(m_hWnd, WM_KEYUP, VK_BUTTON1+i, 0);
+ }
+ }
+ }
+ else
+ {
+ OutputDebugString("UpdateInputState error\n");
+ }
+ }
+ break;
+
+ case WM_ACTIVATE:
+ if( LOWORD(wParam) == WA_INACTIVE )
+ {
+ m_bActivateApp = false;
+ }
+ else
+ {
+ m_bActivateApp = true;
+ }
+
+ if ( m_bActivateApp && m_bJoystick )
+ {
+ SetAcquire(true); // re-enables the joystick
+ }
+ break;
+
+ case MM_MCINOTIFY:
+ if ( wParam == MCI_NOTIFY_SUCCESSFUL )
+ {
+ OutputDebugString("Event MM_MCINOTIFY\n");
+ m_pSound->SuspendMusic();
+ m_pSound->RestartMusic();
+ }
+ break;
+
+ case WM_SETCURSOR:
+ // Prevent a cursor in fullscreen mode
+ if( m_bActive && m_bReady && !m_pDeviceInfo->bWindowed )
+ {
+//? SetCursor(NULL);
+ return 1;
+ }
+ break;
+
+ case WM_ENTERMENULOOP:
+ // Pause the app when menus are displayed
+ Pause(true);
+ break;
+ case WM_EXITMENULOOP:
+ Pause(false);
+ break;
+
+ case WM_ENTERSIZEMOVE:
+ // Halt frame movement while the app is sizing or moving
+ m_pD3DEngine->TimeEnterGel();
+ break;
+ case WM_EXITSIZEMOVE:
+ m_pD3DEngine->TimeExitGel();
+ break;
+
+ case WM_NCHITTEST:
+ // Prevent the user from selecting the menu in fullscreen mode
+ if( !m_pDeviceInfo->bWindowed )
+ return HTCLIENT;
+
+ break;
+
+ case WM_POWERBROADCAST:
+ switch( wParam )
+ {
+ case PBT_APMQUERYSUSPEND:
+ // At this point, the app should save any data for open
+ // network connections, files, etc.., and prepare to go into
+ // a suspended mode.
+ return OnQuerySuspend( (DWORD)lParam );
+
+ case PBT_APMRESUMESUSPEND:
+ // At this point, the app should recover any data, network
+ // connections, files, etc.., and resume running from when
+ // the app was suspended.
+ return OnResumeSuspend( (DWORD)lParam );
+ }
+ break;
+
+ case WM_SYSCOMMAND:
+ // Prevent moving/sizing and power loss in fullscreen mode
+ switch( wParam )
+ {
+ case SC_MOVE:
+ case SC_SIZE:
+ case SC_MAXIMIZE:
+ case SC_MONITORPOWER:
+ if( false == m_pDeviceInfo->bWindowed )
+ return 1;
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch( LOWORD(wParam) )
+ {
+ case IDM_CHANGEDEVICE:
+ // Display the device-selection dialog box.
+ if( m_bActive && m_bReady )
+ {
+ Pause(true);
+
+ if( SUCCEEDED( D3DEnum_UserChangeDevice( &m_pDeviceInfo ) ) )
+ {
+ if( FAILED( hr = Change3DEnvironment() ) )
+ return 0;
+ }
+ Pause(false);
+ }
+ return 0;
+
+ case IDM_ABOUT:
+ // Display the About box
+ Pause(true);
+ DialogBox( (HINSTANCE)GetWindowLong( hWnd, GWL_HINSTANCE ),
+ MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutProc );
+ Pause(false);
+ return 0;
+
+ case IDM_EXIT:
+ // Recieved key/menu command to exit app
+ SendMessage( hWnd, WM_CLOSE, 0, 0 );
+ return 0;
+ }
+ break;
+
+ case WM_GETMINMAXINFO:
+ ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
+ ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow( hWnd );
+ return 0;
+
+ case WM_DESTROY:
+ Cleanup3DEnvironment();
+ PostQuitMessage(0);
+ return 0;
+ }
+
+ return DefWindowProc( hWnd, uMsg, wParam, lParam );
+}
+
+
+// Enumeration function to report valid pixel formats for z-buffers.
+
+HRESULT WINAPI EnumZBufferFormatsCallback(DDPIXELFORMAT* pddpf,
+ VOID* pContext)
+{
+ DDPIXELFORMAT* pddpfOut = (DDPIXELFORMAT*)pContext;
+
+ char s[100];
+ sprintf(s, "EnumZBufferFormatsCallback %d\n", pddpf->dwRGBBitCount);
+ OutputDebugString(s);
+
+ if( pddpfOut->dwRGBBitCount == pddpf->dwRGBBitCount )
+ {
+ (*pddpfOut) = (*pddpf);
+ return D3DENUMRET_CANCEL;
+ }
+
+ return D3DENUMRET_OK;
+}
+
+// Internal function called by Create() to make and attach a zbuffer
+// to the renderer.
+
+HRESULT CD3DApplication::CreateZBuffer(GUID* pDeviceGUID)
+{
+ HRESULT hr;
+
+ // Check if the device supports z-bufferless hidden surface removal. If so,
+ // we don't really need a z-buffer
+ D3DDEVICEDESC7 ddDesc;
+ m_pD3DDevice->GetCaps( &ddDesc );
+ if( ddDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )
+ return S_OK;
+
+ // Get z-buffer dimensions from the render target
+ DDSURFACEDESC2 ddsd;
+ ddsd.dwSize = sizeof(ddsd);
+ m_pddsRenderTarget->GetSurfaceDesc( &ddsd );
+
+ // Setup the surface desc for the z-buffer.
+ ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
+ ddsd.ddpfPixelFormat.dwSize = 0; // Tag the pixel format as unitialized
+
+ // Get an appropiate pixel format from enumeration of the formats. On the
+ // first pass, we look for a zbuffer dpeth which is equal to the frame
+ // buffer depth (as some cards unfornately require this).
+ m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
+ (VOID*)&ddsd.ddpfPixelFormat );
+ if( 0 == ddsd.ddpfPixelFormat.dwSize )
+ {
+ // Try again, just accepting any 16-bit zbuffer
+ ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
+ m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
+ (VOID*)&ddsd.ddpfPixelFormat );
+
+ if( 0 == ddsd.ddpfPixelFormat.dwSize )
+ {
+ DEBUG_MSG( _T("Device doesn't support requested zbuffer format") );
+ return D3DFWERR_NOZBUFFER;
+ }
+ }
+
+ // Create and attach a z-buffer
+ if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsDepthBuffer, NULL ) ) )
+ {
+ DEBUG_MSG( _T("Error: Couldn't create a ZBuffer surface") );
+ if( hr != DDERR_OUTOFVIDEOMEMORY )
+ return D3DFWERR_NOZBUFFER;
+ DEBUG_MSG( _T("Error: Out of video memory") );
+ return DDERR_OUTOFVIDEOMEMORY;
+ }
+
+ if( FAILED( m_pddsRenderTarget->AddAttachedSurface( m_pddsDepthBuffer ) ) )
+ {
+ DEBUG_MSG( _T("Error: Couldn't attach zbuffer to render surface") );
+ return D3DFWERR_NOZBUFFER;
+ }
+
+ // Finally, this call rebuilds internal structures
+ if( FAILED( m_pD3DDevice->SetRenderTarget( m_pddsRenderTarget, 0L ) ) )
+ {
+ DEBUG_MSG( _T("Error: SetRenderTarget() failed after attaching zbuffer!") );
+ return D3DFWERR_NOZBUFFER;
+ }
+
+ return S_OK;
+}
+
+// Initializes the sample framework, then calls the app-specific function
+// to initialize device specific objects. This code is structured to
+// handled any errors that may occur duing initialization.
+
+HRESULT CD3DApplication::Initialize3DEnvironment()
+{
+ HRESULT hr;
+ DDSCAPS2 ddsCaps2;
+ DWORD dwFrameworkFlags = 0L;
+ DWORD dwTotal;
+ DWORD dwFree;
+
+ dwFrameworkFlags |= ( !m_pDeviceInfo->bWindowed ? D3DFW_FULLSCREEN : 0L );
+ dwFrameworkFlags |= ( m_pDeviceInfo->bStereo ? D3DFW_STEREO : 0L );
+ dwFrameworkFlags |= ( m_bAppUseZBuffer ? D3DFW_ZBUFFER : 0L );
+
+ // Initialize the D3D framework
+ if( SUCCEEDED( hr = m_pFramework->Initialize( m_hWnd,
+ m_pDeviceInfo->pDriverGUID, m_pDeviceInfo->pDeviceGUID,
+ &m_pDeviceInfo->ddsdFullscreenMode, dwFrameworkFlags ) ) )
+ {
+ m_pDD = m_pFramework->GetDirectDraw();
+ m_pD3D = m_pFramework->GetDirect3D();
+ m_pD3DDevice = m_pFramework->GetD3DDevice();
+
+ m_pD3DEngine->SetD3DDevice(m_pD3DDevice);
+
+ m_pddsRenderTarget = m_pFramework->GetRenderSurface();
+
+ m_ddsdRenderTarget.dwSize = sizeof(m_ddsdRenderTarget);
+ m_pddsRenderTarget->GetSurfaceDesc( &m_ddsdRenderTarget );
+
+ // Request the amount of video memory.
+ ZeroMemory(&ddsCaps2, sizeof(ddsCaps2));
+ ddsCaps2.dwCaps = DDSCAPS_TEXTURE;
+ dwTotal = 0;
+ hr = m_pDD->GetAvailableVidMem(&ddsCaps2, &dwTotal, &dwFree);
+ m_vidMemTotal = dwTotal;
+
+ // Let the app run its startup code which creates the 3d scene.
+ if( SUCCEEDED( hr = m_pD3DEngine->InitDeviceObjects() ) )
+ {
+//? CreateZBuffer(m_pDeviceInfo->pDeviceGUID);
+ return S_OK;
+ }
+ else
+ {
+ DeleteDeviceObjects();
+ m_pFramework->DestroyObjects();
+ }
+ }
+
+ // If we get here, the first initialization passed failed. If that was with a
+ // hardware device, try again using a software rasterizer instead.
+ if( m_pDeviceInfo->bHardware )
+ {
+ // Try again with a software rasterizer
+ DisplayFrameworkError( hr, MSGWARN_SWITCHEDTOSOFTWARE );
+ D3DEnum_SelectDefaultDevice( &m_pDeviceInfo, D3DENUM_SOFTWAREONLY );
+ return Initialize3DEnvironment();
+ }
+
+ return hr;
+}
+
+
+// Handles driver, device, and/or mode changes for the app.
+
+HRESULT CD3DApplication::Change3DEnvironment()
+{
+#if 0
+ HRESULT hr;
+ static bool bOldWindowedState = true;
+ static DWORD dwSavedStyle;
+ static RECT rcSaved;
+
+ // Release all scene objects that will be re-created for the new device
+ DeleteDeviceObjects();
+
+ // Release framework objects, so a new device can be created
+ if( FAILED( hr = m_pFramework->DestroyObjects() ) )
+ {
+ DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
+ SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
+ return hr;
+ }
+
+ // Check if going from fullscreen to windowed mode, or vice versa.
+ if( bOldWindowedState != m_pDeviceInfo->bWindowed )
+ {
+ if( m_pDeviceInfo->bWindowed )
+ {
+ // Coming from fullscreen mode, so restore window properties
+ SetWindowLong( m_hWnd, GWL_STYLE, dwSavedStyle );
+ SetWindowPos( m_hWnd, HWND_NOTOPMOST, rcSaved.left, rcSaved.top,
+ ( rcSaved.right - rcSaved.left ),
+ ( rcSaved.bottom - rcSaved.top ), SWP_SHOWWINDOW );
+ }
+ else
+ {
+ // Going to fullscreen mode, save/set window properties as needed
+ dwSavedStyle = GetWindowLong( m_hWnd, GWL_STYLE );
+ GetWindowRect( m_hWnd, &rcSaved );
+ SetWindowLong( m_hWnd, GWL_STYLE, WS_POPUP|WS_SYSMENU|WS_VISIBLE );
+ }
+
+ bOldWindowedState = m_pDeviceInfo->bWindowed;
+ }
+
+ // Inform the framework class of the driver change. It will internally
+ // re-create valid surfaces, a d3ddevice, etc.
+ if( FAILED( hr = Initialize3DEnvironment() ) )
+ {
+ DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
+ SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
+ return hr;
+ }
+
+ return S_OK;
+#else
+ HRESULT hr;
+
+ // Release all scene objects that will be re-created for the new device
+ DeleteDeviceObjects();
+
+ // Release framework objects, so a new device can be created
+ if( FAILED( hr = m_pFramework->DestroyObjects() ) )
+ {
+ DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
+ SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
+ return hr;
+ }
+
+ if( m_pDeviceInfo->bWindowed )
+ {
+ SetWindowPos(m_hWnd, HWND_NOTOPMOST, 10, 10, WINDOW_DX, WINDOW_DY, SWP_SHOWWINDOW);
+ }
+
+ // Inform the framework class of the driver change. It will internally
+ // re-create valid surfaces, a d3ddevice, etc.
+ if( FAILED( hr = Initialize3DEnvironment() ) )
+ {
+ DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
+ SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
+ return hr;
+ }
+
+ m_pD3DEngine->ChangeLOD();
+
+ if( m_pDeviceInfo->bWindowed )
+ {
+ SetNiceMouse(false); // hides the ugly windows mouse
+ }
+
+ return S_OK;
+#endif
+}
+
+
+
+// Evolved throughout the game
+
+void CD3DApplication::StepSimul(float rTime)
+{
+ Event event;
+
+ if ( m_pRobotMain == 0 ) return;
+
+ ZeroMemory(&event, sizeof(Event));
+ event.event = EVENT_FRAME; // funny bug release "Maximize speed"!
+ event.rTime = rTime;
+ event.axeX = AxeLimit(m_axeKey.x + m_axeJoy.x);
+ event.axeY = AxeLimit(m_axeKey.y + m_axeJoy.y);
+ event.axeZ = AxeLimit(m_axeKey.z + m_axeJoy.z);
+ event.keyState = m_keyState;
+
+//?char s[100];
+//?sprintf(s, "StepSimul %.3f\n", event.rTime);
+//?OutputDebugString(s);
+ m_pRobotMain->EventProcess(event);
+}
+
+
+// Draws the scene.
+
+HRESULT CD3DApplication::Render3DEnvironment()
+{
+ HRESULT hr;
+ float rTime;
+
+ // Check the cooperative level before rendering
+ if( FAILED( hr = m_pDD->TestCooperativeLevel() ) )
+ {
+ switch( hr )
+ {
+ case DDERR_EXCLUSIVEMODEALREADYSET:
+ case DDERR_NOEXCLUSIVEMODE:
+ OutputDebugString("DDERR_EXCLUSIVEMODEALREADYSET\n");
+ // Do nothing because some other app has exclusive mode
+ return S_OK;
+
+ case DDERR_WRONGMODE:
+ OutputDebugString("DDERR_WRONGMODE\n");
+ // The display mode changed on us. Resize accordingly
+ if( m_pDeviceInfo->bWindowed )
+ return Change3DEnvironment();
+ break;
+ }
+ return hr;
+ }
+
+ // Get the relative time, in seconds
+ rTime = m_pD3DEngine->TimeGet();
+ if ( rTime > MAX_STEP ) rTime = MAX_STEP; // never more than 0.5s!
+ m_aTime += rTime;
+
+#if !USE_THREAD
+ if( FAILED( hr = m_pD3DEngine->FrameMove(rTime) ) )
+ return hr;
+
+ // FrameMove (animate) the scene
+ StepSimul(rTime);
+#endif
+
+ // Render the scene.
+ if( FAILED( hr = m_pD3DEngine->Render() ) )
+ return hr;
+
+ DrawSuppl();
+
+ // Show the frame rate, etc.
+ if( m_bShowStats )
+ ShowStats();
+
+ // Show the frame on the primary surface.
+ if( FAILED( hr = m_pFramework->ShowFrame() ) )
+ {
+ if( DDERR_SURFACELOST != hr )
+ return hr;
+
+ m_pFramework->RestoreSurfaces();
+ m_pD3DEngine->RestoreSurfaces();
+ }
+
+ return S_OK;
+}
+
+
+// Cleanup scene objects
+
+VOID CD3DApplication::Cleanup3DEnvironment()
+{
+ m_bActive = false;
+ m_bReady = false;
+
+ if( m_pFramework )
+ {
+ DeleteDeviceObjects();
+ SAFE_DELETE( m_pFramework );
+
+ m_pD3DEngine->FinalCleanup();
+ }
+
+ D3DEnum_FreeResources();
+//? FreeDirectInput();
+}
+
+// Called when the app is exitting, or the device is being changed,
+// this function deletes any device dependant objects.
+
+VOID CD3DApplication::DeleteDeviceObjects()
+{
+ if( m_pFramework )
+ {
+ m_pD3DEngine->DeleteDeviceObjects();
+ SAFE_RELEASE( m_pddsDepthBuffer );
+ }
+}
+
+
+
+// Called in to toggle the pause state of the app. This function
+// brings the GDI surface to the front of the display, so drawing
+// output like message boxes and menus may be displayed.
+
+VOID CD3DApplication::Pause( bool bPause )
+{
+ static DWORD dwAppPausedCount = 0L;
+
+ dwAppPausedCount += ( bPause ? +1 : -1 );
+ m_bReady = ( dwAppPausedCount ? false : true );
+
+ // Handle the first pause request (of many, nestable pause requests)
+ if( bPause && ( 1 == dwAppPausedCount ) )
+ {
+ // Get a surface for the GDI
+ if( m_pFramework )
+ m_pFramework->FlipToGDISurface( true );
+
+ // Stop the scene from animating
+ m_pD3DEngine->TimeEnterGel();
+ }
+
+ if( 0 == dwAppPausedCount )
+ {
+ // Restart the scene
+ m_pD3DEngine->TimeExitGel();
+ }
+}
+
+
+// Called when the app receives a PBT_APMQUERYSUSPEND message, meaning
+// the computer is about to be suspended. At this point, the app should
+// save any data for open network connections, files, etc.., and prepare
+// to go into a suspended mode.
+
+LRESULT CD3DApplication::OnQuerySuspend( DWORD dwFlags )
+{
+ OutputDebugString("OnQuerySuspend\n");
+ Pause(true);
+ return true;
+}
+
+
+// Called when the app receives a PBT_APMRESUMESUSPEND message, meaning
+// the computer has just resumed from a suspended state. At this point,
+// the app should recover any data, network connections, files, etc..,
+// and resume running from when the app was suspended.
+
+LRESULT CD3DApplication::OnResumeSuspend( DWORD dwData )
+{
+ OutputDebugString("OnResumeSuspend\n");
+ Pause(false);
+ return true;
+}
+
+
+// Draw all the additional graphic elements.
+
+void CD3DApplication::DrawSuppl()
+{
+ HDC hDC;
+ Math::Point p1, p2;
+ POINT list[3];
+ RECT rect;
+ HPEN hPen;
+ HGDIOBJ old;
+ Math::Point pos;
+ float d;
+ int nbOut;
+
+ if ( FAILED(m_pddsRenderTarget->GetDC(&hDC)) ) return;
+
+ // Displays the selection rectangle.
+ if ( m_pD3DEngine->GetHilite(p1, p2) )
+ {
+ nbOut = 0;
+ if ( p1.x < 0.0f || p1.x > 1.0f ) nbOut ++;
+ if ( p1.y < 0.0f || p1.y > 1.0f ) nbOut ++;
+ if ( p2.x < 0.0f || p2.x > 1.0f ) nbOut ++;
+ if ( p2.y < 0.0f || p2.y > 1.0f ) nbOut ++;
+ if ( nbOut <= 2 )
+ {
+#if 0
+ time = Math::Mod(m_aTime, 0.5f);
+ if ( time < 0.25f ) d = time*4.0f;
+ else d = (2.0f-time*4.0f);
+#endif
+#if 0
+ time = Math::Mod(m_aTime, 0.5f);
+ if ( time < 0.4f ) d = time/0.4f;
+ else d = 1.0f-(time-0.4f)/0.1f;
+#endif
+#if 1
+ d = 0.5f+sinf(m_aTime*6.0f)*0.5f;
+#endif
+ d *= (p2.x-p1.x)*0.1f;
+ p1.x += d;
+ p1.y += d;
+ p2.x -= d;
+ p2.y -= d;
+
+ hPen = CreatePen(PS_SOLID, 1, RGB(255,255,0)); // yellow
+ old = SelectObject(hDC, hPen);
+
+ rect.left = (int)(p1.x*m_ddsdRenderTarget.dwWidth);
+ rect.right = (int)(p2.x*m_ddsdRenderTarget.dwWidth);
+ rect.top = (int)((1.0f-p2.y)*m_ddsdRenderTarget.dwHeight);
+ rect.bottom = (int)((1.0f-p1.y)*m_ddsdRenderTarget.dwHeight);
+
+ list[0].x = rect.left;
+ list[0].y = rect.top+(rect.bottom-rect.top)/5;
+ list[1].x = rect.left;
+ list[1].y = rect.top;
+ list[2].x = rect.left+(rect.right-rect.left)/5;
+ list[2].y = rect.top;
+ Polyline(hDC, list, 3);
+
+ list[0].x = rect.right;
+ list[0].y = rect.top+(rect.bottom-rect.top)/5;
+ list[1].x = rect.right;
+ list[1].y = rect.top;
+ list[2].x = rect.right+(rect.left-rect.right)/5;
+ list[2].y = rect.top;
+ Polyline(hDC, list, 3);
+
+ list[0].x = rect.left;
+ list[0].y = rect.bottom+(rect.top-rect.bottom)/5;
+ list[1].x = rect.left;
+ list[1].y = rect.bottom;
+ list[2].x = rect.left+(rect.right-rect.left)/5;
+ list[2].y = rect.bottom;
+ Polyline(hDC, list, 3);
+
+ list[0].x = rect.right;
+ list[0].y = rect.bottom+(rect.top-rect.bottom)/5;
+ list[1].x = rect.right;
+ list[1].y = rect.bottom;
+ list[2].x = rect.right+(rect.left-rect.right)/5;
+ list[2].y = rect.bottom;
+ Polyline(hDC, list, 3);
+
+ if ( old != 0 ) SelectObject(hDC, old);
+ DeleteObject(hPen);
+ }
+ }
+
+ m_pddsRenderTarget->ReleaseDC(hDC);
+}
+
+// Shows frame rate and dimensions of the rendering device.
+
+VOID CD3DApplication::ShowStats()
+{
+ static FLOAT fFPS = 0.0f;
+ static FLOAT fLastTime = 0.0f;
+ static DWORD dwFrames = 0L;
+
+ // Keep track of the time lapse and frame count
+ FLOAT fTime = timeGetTime() * 0.001f; // Get current time in seconds
+ ++dwFrames;
+
+ // Update the frame rate once per second
+ if( fTime - fLastTime > 1.0f )
+ {
+ fFPS = dwFrames / (fTime - fLastTime);
+ fLastTime = fTime;
+ dwFrames = 0L;
+ }
+
+ int t = m_pD3DEngine->RetStatisticTriangle();
+
+ // Setup the text buffer to write out dimensions
+ TCHAR buffer[100];
+ sprintf( buffer, _T("%7.02f fps T=%d (%dx%dx%d)"), fFPS, t,
+ m_ddsdRenderTarget.dwWidth, m_ddsdRenderTarget.dwHeight,
+ m_ddsdRenderTarget.ddpfPixelFormat.dwRGBBitCount );
+ OutputText( 400, 2, buffer );
+
+ int x, y, i;
+ if ( m_pD3DEngine->GetSpriteCoord(x, y) )
+ {
+ OutputText( x, y, "+" );
+ }
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ char* info = m_pD3DEngine->RetInfoText(i);
+ x = 50;
+ y = m_ddsdRenderTarget.dwHeight-20-i*20;
+ OutputText( x, y, info );
+ }
+}
+
+
+// Draws text on the window.
+
+VOID CD3DApplication::OutputText( DWORD x, DWORD y, TCHAR* str )
+{
+ HDC hDC;
+
+ // Get a DC for the surface. Then, write out the buffer
+ if( m_pddsRenderTarget )
+ {
+ if( SUCCEEDED( m_pddsRenderTarget->GetDC(&hDC) ) )
+ {
+ SetTextColor( hDC, RGB(255,255,0) );
+ SetBkMode( hDC, TRANSPARENT );
+ ExtTextOut( hDC, x, y, 0, NULL, str, lstrlen(str), NULL );
+ m_pddsRenderTarget->ReleaseDC(hDC);
+ }
+ }
+}
+
+
+
+
+// Defines a function that allocates memory for and initializes
+// members within a BITMAPINFOHEADER structure
+
+PBITMAPINFO CD3DApplication::CreateBitmapInfoStruct(HBITMAP hBmp)
+{
+ BITMAP bmp;
+ PBITMAPINFO pbmi;
+ WORD cClrBits;
+
+ // Retrieve the bitmap's color format, width, and height.
+ if ( !GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp) )
+ return 0;
+
+ // Convert the color format to a count of bits.
+ cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
+
+ if ( cClrBits == 1 ) cClrBits = 1;
+ else if ( cClrBits <= 4 ) cClrBits = 4;
+ else if ( cClrBits <= 8 ) cClrBits = 8;
+ else if ( cClrBits <= 16 ) cClrBits = 16;
+ else if ( cClrBits <= 24 ) cClrBits = 24;
+ else cClrBits = 32;
+
+ // Allocate memory for the BITMAPINFO structure. (This structure
+ // contains a BITMAPINFOHEADER structure and an array of RGBQUAD data
+ // structures.)
+ if ( cClrBits != 24 )
+ {
+ pbmi = (PBITMAPINFO)LocalAlloc(LPTR,
+ sizeof(BITMAPINFOHEADER) +
+ sizeof(RGBQUAD) * (2^cClrBits));
+ }
+ // There is no RGBQUAD array for the 24-bit-per-pixel format.
+ else
+ {
+ pbmi = (PBITMAPINFO)LocalAlloc(LPTR,
+ sizeof(BITMAPINFOHEADER));
+ }
+
+ // Initialize the fields in the BITMAPINFO structure.
+ pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pbmi->bmiHeader.biWidth = bmp.bmWidth;
+ pbmi->bmiHeader.biHeight = bmp.bmHeight;
+ pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
+ pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
+ if ( cClrBits < 24 )
+ pbmi->bmiHeader.biClrUsed = 2^cClrBits;
+
+ // If the bitmap is not compressed, set the BI_RGB flag.
+ pbmi->bmiHeader.biCompression = BI_RGB;
+
+ // Compute the number of bytes in the array of color
+ // indices and store the result in biSizeImage.
+ pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) /8
+ * pbmi->bmiHeader.biHeight
+ * cClrBits;
+
+ // Set biClrImportant to 0, indicating that all of the
+ // device colors are important.
+ pbmi->bmiHeader.biClrImportant = 0;
+
+ return pbmi;
+}
+
+// Defines a function that initializes the remaining structures,
+// retrieves the array of palette indices, opens the file, copies
+// the data, and closes the file.
+
+bool CD3DApplication::CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC)
+{
+ FILE* file; // file handle
+ BITMAPFILEHEADER hdr; // bitmap file-header
+ PBITMAPINFOHEADER pbih; // bitmap info-header
+ LPBYTE lpBits; // memory pointer
+ DWORD dwTotal; // total count of bytes
+
+ pbih = (PBITMAPINFOHEADER)pbi;
+ lpBits = (LPBYTE)GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
+ if ( !lpBits ) return false;
+
+ // Retrieve the color table (RGBQUAD array) and the bits
+ // (array of palette indices) from the DIB.
+ if ( !GetDIBits(hDC, hBMP, 0, (WORD)pbih->biHeight,
+ lpBits, pbi, DIB_RGB_COLORS) )
+ return false;
+
+ // Create the .BMP file.
+ file = fopen(pszFile, "wb");
+ if ( file == NULL ) return false;
+
+ hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M"
+
+ // Compute the size of the entire file.
+ hdr.bfSize = (DWORD)(sizeof(BITMAPFILEHEADER) +
+ pbih->biSize + pbih->biClrUsed
+ * sizeof(RGBQUAD) + pbih->biSizeImage);
+
+ hdr.bfReserved1 = 0;
+ hdr.bfReserved2 = 0;
+
+ // Compute the offset to the array of color indices.
+ hdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) +
+ pbih->biSize + pbih->biClrUsed
+ * sizeof (RGBQUAD);
+
+ // Copy the BITMAPFILEHEADER into the .BMP file.
+ fwrite(&hdr, sizeof(BITMAPFILEHEADER), 1, file);
+
+ // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
+ fwrite(pbih, sizeof(BITMAPINFOHEADER)+pbih->biClrUsed*sizeof(RGBQUAD), 1, file);
+
+ // Copy the array of color indices into the .BMP file.
+ dwTotal = pbih->biSizeImage;
+ fwrite(lpBits, dwTotal, 1, file);
+
+ // Close the .BMP file.
+ fclose(file);
+
+ // Free memory.
+ GlobalFree((HGLOBAL)lpBits);
+ return true;
+}
+
+// Write a file. BMP screenshot.
+
+bool CD3DApplication::WriteScreenShot(char *filename, int width, int height)
+{
+ D3DVIEWPORT7 vp;
+ HDC hDC;
+ HDC hDCImage;
+ HBITMAP hb;
+ PBITMAPINFO info;
+ int dx, dy;
+
+ m_pD3DDevice->GetViewport(&vp);
+ dx = vp.dwWidth;
+ dy = vp.dwHeight;
+
+ if ( FAILED(m_pddsRenderTarget->GetDC(&hDC)) ) return false;
+
+ hDCImage = CreateCompatibleDC(hDC);
+ if ( hDCImage == 0 )
+ {
+ m_pddsRenderTarget->ReleaseDC(hDC);
+ return false;
+ }
+
+ hb = CreateCompatibleBitmap(hDC, width, height);
+ if ( hb == 0 )
+ {
+ DeleteDC(hDCImage);
+ m_pddsRenderTarget->ReleaseDC(hDC);
+ return false;
+ }
+
+ SelectObject(hDCImage, hb);
+ StretchBlt(hDCImage, 0, 0, width, height, hDC, 0, 0, dx, dy, SRCCOPY);
+
+ info = CreateBitmapInfoStruct(hb);
+ if ( info == 0 )
+ {
+ DeleteObject(hb);
+ DeleteDC(hDCImage);
+ m_pddsRenderTarget->ReleaseDC(hDC);
+ return false;
+ }
+
+ CreateBMPFile(filename, info, hb, hDCImage);
+
+ DeleteObject(hb);
+ DeleteDC(hDCImage);
+ m_pddsRenderTarget->ReleaseDC(hDC);
+ return true;
+}
+
+
+// Initializes an hDC on the rendering surface.
+
+bool CD3DApplication::GetRenderDC(HDC &hDC)
+{
+ if ( FAILED(m_pddsRenderTarget->GetDC(&hDC)) ) return false;
+ return true;
+}
+
+// Frees the hDC of the rendering surface.
+
+bool CD3DApplication::ReleaseRenderDC(HDC &hDC)
+{
+ m_pddsRenderTarget->ReleaseDC(hDC);
+ return true;
+}
+
+
+
+
+// Perform the list of all graphics devices available.
+// For the device selected, lists the full screen modes
+// possible.
+// buf* --> nom1<0> nom2<0> <0>
+
+bool CD3DApplication::EnumDevices(char *bufDevices, int lenDevices,
+ char *bufModes, int lenModes,
+ int &totalDevices, int &selectDevices,
+ int &totalModes, int &selectModes)
+{
+ D3DEnum_DeviceInfo* pDeviceList;
+ D3DEnum_DeviceInfo* pDevice;
+ DDSURFACEDESC2* pddsdMode;
+ DWORD numDevices, device, mode;
+ int len;
+ char text[100];
+
+ D3DEnum_GetDevices(&pDeviceList, &numDevices);
+
+ selectDevices = -1;
+ selectModes = -1;
+ totalModes = 0;
+ for( device=0 ; device<numDevices ; device++ )
+ {
+ pDevice = &pDeviceList[device];
+
+ len = strlen(pDevice->strDesc)+1;
+ if ( len >= lenDevices ) break; // bufDevices full!
+ strcpy(bufDevices, pDevice->strDesc);
+ bufDevices += len;
+ lenDevices -= len;
+
+ if ( pDevice == m_pDeviceInfo ) // select device ?
+ {
+ selectDevices = device;
+
+ for( mode=0 ; mode<pDevice->dwNumModes ; mode++ )
+ {
+ pddsdMode = &pDevice->pddsdModes[mode];
+
+ sprintf(text, "%ld x %ld x %ld",
+ pddsdMode->dwWidth,
+ pddsdMode->dwHeight,
+ pddsdMode->ddpfPixelFormat.dwRGBBitCount);
+
+ len = strlen(text)+1;
+ if ( len >= lenModes ) break; // bufModes full !
+ strcpy(bufModes, text);
+ bufModes += len;
+ lenModes -= len;
+
+ if ( mode == m_pDeviceInfo->dwCurrentMode ) // select mode ?
+ {
+ selectModes = mode;
+ }
+ }
+ bufModes[0] = 0;
+ totalModes = pDevice->dwNumModes;
+ }
+ }
+ bufDevices[0] = 0;
+ totalDevices = numDevices;
+
+ return true;
+}
+
+// Indicates whether it is in full screen mode.
+
+bool CD3DApplication::RetFullScreen()
+{
+ return !m_pDeviceInfo->bWindowed;
+}
+
+// Change the graphics mode.
+
+bool CD3DApplication::ChangeDevice(char *deviceName, char *modeName,
+ bool bFull)
+{
+ D3DEnum_DeviceInfo* pDeviceList;
+ D3DEnum_DeviceInfo* pDevice;
+ DDSURFACEDESC2* pddsdMode;
+ DWORD numDevices, device, mode;
+ HRESULT hr;
+ char text[100];
+
+ D3DEnum_GetDevices(&pDeviceList, &numDevices);
+
+ for( device=0 ; device<numDevices ; device++ )
+ {
+ pDevice = &pDeviceList[device];
+
+ if ( strcmp(pDevice->strDesc, deviceName) == 0 ) // device found ?
+ {
+ for( mode=0 ; mode<pDevice->dwNumModes ; mode++ )
+ {
+ pddsdMode = &pDevice->pddsdModes[mode];
+
+ sprintf(text, "%ld x %ld x %ld",
+ pddsdMode->dwWidth,
+ pddsdMode->dwHeight,
+ pddsdMode->ddpfPixelFormat.dwRGBBitCount);
+
+ if ( strcmp(text, modeName) == 0 ) // mode found ?
+ {
+ m_pDeviceInfo = pDevice;
+ pDevice->bWindowed = !bFull;
+ pDevice->dwCurrentMode = mode;
+ pDevice->ddsdFullscreenMode = pDevice->pddsdModes[mode];
+
+ m_bReady = false;
+
+ if ( FAILED( hr = Change3DEnvironment() ) )
+ {
+ return false;
+ }
+
+ SetProfileString("Device", "Name", deviceName);
+ SetProfileString("Device", "Mode", modeName);
+ SetProfileInt("Device", "FullScreen", bFull);
+ m_bReady = true;
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+
+
+// Displays error messages in a message box.
+
+VOID CD3DApplication::DisplayFrameworkError( HRESULT hr, DWORD dwType )
+{
+ TCHAR strMsg[512];
+
+ switch( hr )
+ {
+ case D3DENUMERR_ENGINE:
+ lstrcpy( strMsg, _T("Could not create 3D Engine application!") );
+ break;
+ case D3DENUMERR_ROBOT:
+ lstrcpy( strMsg, _T("Could not create Robot application!") );
+ break;
+ case D3DENUMERR_NODIRECTDRAW:
+ lstrcpy( strMsg, _T("Could not create DirectDraw!") );
+ break;
+ case D3DENUMERR_NOCOMPATIBLEDEVICES:
+ lstrcpy( strMsg, _T("Could not find any compatible Direct3D\n"
+ "devices.") );
+ break;
+ case D3DENUMERR_SUGGESTREFRAST:
+ lstrcpy( strMsg, _T("Could not find any compatible devices.\n\n"
+ "Try enabling the reference rasterizer using\n"
+ "EnableRefRast.reg.") );
+ break;
+ case D3DENUMERR_ENUMERATIONFAILED:
+ lstrcpy( strMsg, _T("Enumeration failed. Your system may be in an\n"
+ "unstable state and need to be rebooted") );
+ break;
+ case D3DFWERR_INITIALIZATIONFAILED:
+ lstrcpy( strMsg, _T("Generic initialization error.\n\nEnable "
+ "debug output for detailed information.") );
+ break;
+ case D3DFWERR_NODIRECTDRAW:
+ lstrcpy( strMsg, _T("No DirectDraw") );
+ break;
+ case D3DFWERR_NODIRECT3D:
+ lstrcpy( strMsg, _T("No Direct3D") );
+ break;
+ case D3DFWERR_INVALIDMODE:
+ lstrcpy( strMsg, _T("COLOBOT requires a 16-bit (or higher) "
+ "display mode\nto run in a window.\n\nPlease "
+ "switch your desktop settings accordingly.") );
+ break;
+ case D3DFWERR_COULDNTSETCOOPLEVEL:
+ lstrcpy( strMsg, _T("Could not set Cooperative Level") );
+ break;
+ case D3DFWERR_NO3DDEVICE:
+ lstrcpy( strMsg, _T("Could not create the Direct3DDevice object.") );
+
+ if( MSGWARN_SWITCHEDTOSOFTWARE == dwType )
+ lstrcat( strMsg, _T("\nThe 3D hardware chipset may not support"
+ "\nrendering in the current display mode.") );
+ break;
+ case D3DFWERR_NOZBUFFER:
+ lstrcpy( strMsg, _T("No ZBuffer") );
+ break;
+ case D3DFWERR_INVALIDZBUFFERDEPTH:
+ lstrcpy( strMsg, _T("Invalid Z-buffer depth. Try switching modes\n"
+ "from 16- to 32-bit (or vice versa)") );
+ break;
+ case D3DFWERR_NOVIEWPORT:
+ lstrcpy( strMsg, _T("No Viewport") );
+ break;
+ case D3DFWERR_NOPRIMARY:
+ lstrcpy( strMsg, _T("No primary") );
+ break;
+ case D3DFWERR_NOCLIPPER:
+ lstrcpy( strMsg, _T("No Clipper") );
+ break;
+ case D3DFWERR_BADDISPLAYMODE:
+ lstrcpy( strMsg, _T("Bad display mode") );
+ break;
+ case D3DFWERR_NOBACKBUFFER:
+ lstrcpy( strMsg, _T("No backbuffer") );
+ break;
+ case D3DFWERR_NONZEROREFCOUNT:
+ lstrcpy( strMsg, _T("A DDraw object has a non-zero reference\n"
+ "count (meaning it was not properly cleaned up)." ) );
+ break;
+ case D3DFWERR_NORENDERTARGET:
+ lstrcpy( strMsg, _T("No render target") );
+ break;
+ case E_OUTOFMEMORY:
+ lstrcpy( strMsg, _T("Not enough memory!") );
+ break;
+ case DDERR_OUTOFVIDEOMEMORY:
+ lstrcpy( strMsg, _T("There was insufficient video memory "
+ "to use the\nhardware device.") );
+ break;
+ default:
+ lstrcpy( strMsg, _T("Generic application error.\n\nEnable "
+ "debug output for detailed information.") );
+ }
+
+ if( MSGERR_APPMUSTEXIT == dwType )
+ {
+ lstrcat( strMsg, _T("\n\nCOLOBOT will now exit.") );
+ MessageBox( NULL, strMsg, m_strWindowTitle, MB_ICONERROR|MB_OK );
+ }
+ else
+ {
+ if( MSGWARN_SWITCHEDTOSOFTWARE == dwType )
+ lstrcat( strMsg, _T("\n\nSwitching to software rasterizer.") );
+ MessageBox( NULL, strMsg, m_strWindowTitle, MB_ICONWARNING|MB_OK );
+ }
+}
+
+
diff --git a/src/old/d3dapp.h b/src/old/d3dapp.h
index 1126d69..7e217d4 100644
--- a/src/old/d3dapp.h
+++ b/src/old/d3dapp.h
@@ -1,166 +1,166 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// d3dapp.h
-
-#pragma once
-
-
-#define D3D_OVERLOADS
-#include <d3d.h>
-
-#include "math/vector.h"
-#include "old/d3dengine.h"
-#include "old/d3dframe.h"
-#include "old/d3denum.h"
-#include "old/d3dutil.h"
-#include "old/d3dres.h"
-#include "common/misc.h"
-#include "common/struct.h"
-
-
-class CInstanceManager;
-class CEvent;
-class CRobotMain;
-class CSound;
-
-
-
-class CD3DApplication
-{
-public:
- CD3DApplication();
- ~CD3DApplication();
-
-protected:
- LRESULT OnQuerySuspend( DWORD dwFlags );
- LRESULT OnResumeSuspend( DWORD dwData );
-
-public:
- Error RegQuery();
- Error AudioQuery();
- Error CheckMistery(char *strCmdLine);
- int GetVidMemTotal();
- bool IsVideo8MB();
- bool IsVideo32MB();
- HRESULT Create( HINSTANCE, TCHAR* );
- INT Run();
- LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
- VOID Pause( bool bPause );
- Math::Point ConvPosToInterface(HWND hWnd, LPARAM lParam);
- void SetMousePos(Math::Point pos);
- void StepSimul(float rTime);
- char* RetCDpath();
-
- void SetShowStat(bool bShow);
- bool RetShowStat();
- void SetDebugMode(bool bMode);
- bool RetDebugMode();
- bool RetSetupMode();
-
- bool EnumDevices(char *bufDevices, int lenDevices, char *bufModes, int lenModes, int &totalDevices, int &selectDevices, int &totalModes, int &selectModes);
- bool RetFullScreen();
- bool ChangeDevice(char *device, char *mode, bool bFull);
-
- void FlushPressKey();
- void ResetKey();
- void SetKey(int keyRank, int option, int key);
- int RetKey(int keyRank, int option);
-
- void SetJoystick(bool bEnable);
- bool RetJoystick();
-
- void SetMouseType(D3DMouse type);
- void SetNiceMouse(bool bNice);
- bool RetNiceMouse();
- bool RetNiceMouseCap();
-
- bool WriteScreenShot(char *filename, int width, int height);
-
- bool GetRenderDC(HDC &hDC);
- bool ReleaseRenderDC(HDC &hDC);
- PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp);
- bool CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC);
-
-protected:
- HRESULT ConfirmDevice( DDCAPS* pddDriverCaps, D3DDEVICEDESC7* pd3dDeviceDesc );
- HRESULT Initialize3DEnvironment();
- HRESULT Change3DEnvironment();
- HRESULT CreateZBuffer(GUID* pDeviceGUID);
- HRESULT Render3DEnvironment();
- VOID Cleanup3DEnvironment();
- VOID DeleteDeviceObjects();
- VOID DisplayFrameworkError( HRESULT, DWORD );
-
- void InitText();
- void DrawSuppl();
- VOID ShowStats();
- VOID OutputText( DWORD x, DWORD y, TCHAR* str );
-
-protected:
- CInstanceManager* m_iMan;
- CEvent* m_event;
-
- HINSTANCE m_instance;
- HWND m_hWnd;
- D3DEnum_DeviceInfo* m_pDeviceInfo;
- LPDIRECTDRAW7 m_pDD;
- LPDIRECT3D7 m_pD3D;
- LPDIRECT3DDEVICE7 m_pD3DDevice;
- LPDIRECTDRAWSURFACE7 m_pddsRenderTarget;
- DDSURFACEDESC2 m_ddsdRenderTarget;
- LPDIRECTDRAWSURFACE7 m_pddsDepthBuffer;
-
- HANDLE m_thread;
- DWORD m_threadId;
-
- char m_CDpath[100];
-
- CD3DFramework7* m_pFramework;
- bool m_bActive;
- bool m_bActivateApp;
- bool m_bReady;
- bool m_bJoystick;
-
- DWORD m_vidMemTotal;
- TCHAR* m_strWindowTitle;
- bool m_bAppUseZBuffer;
- bool m_bAppUseStereo;
- bool m_bShowStats;
- bool m_bDebugMode;
- bool m_bAudioState;
- bool m_bAudioTrack;
- bool m_bNiceMouse;
- bool m_bSetupMode;
- HRESULT (*m_fnConfirmDevice)(DDCAPS*, D3DDEVICEDESC7*);
-
-public:
- CD3DEngine* m_pD3DEngine;
- CRobotMain* m_pRobotMain;
- CSound* m_pSound;
-
- int m_keyState;
- Math::Vector m_axeKey;
- Math::Vector m_axeJoy;
- bool m_bJoyButton[32];
- Math::Point m_mousePos;
- DWORD m_mshMouseWheel;
-
- float m_aTime;
- DWORD m_key[50][2];
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// d3dapp.h
+
+#pragma once
+
+
+#define D3D_OVERLOADS
+#include <d3d.h>
+
+#include "math/vector.h"
+#include "old/d3dengine.h"
+#include "old/d3dframe.h"
+#include "old/d3denum.h"
+#include "old/d3dutil.h"
+#include "old/d3dres.h"
+#include "common/misc.h"
+#include "common/struct.h"
+
+
+class CInstanceManager;
+class CEvent;
+class CRobotMain;
+class CSound;
+
+
+
+class CD3DApplication
+{
+public:
+ CD3DApplication();
+ ~CD3DApplication();
+
+protected:
+ LRESULT OnQuerySuspend( DWORD dwFlags );
+ LRESULT OnResumeSuspend( DWORD dwData );
+
+public:
+ Error RegQuery();
+ Error AudioQuery();
+ Error CheckMistery(char *strCmdLine);
+ int GetVidMemTotal();
+ bool IsVideo8MB();
+ bool IsVideo32MB();
+ HRESULT Create( HINSTANCE, TCHAR* );
+ INT Run();
+ LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
+ VOID Pause( bool bPause );
+ Math::Point ConvPosToInterface(HWND hWnd, LPARAM lParam);
+ void SetMousePos(Math::Point pos);
+ void StepSimul(float rTime);
+ char* RetCDpath();
+
+ void SetShowStat(bool bShow);
+ bool RetShowStat();
+ void SetDebugMode(bool bMode);
+ bool RetDebugMode();
+ bool RetSetupMode();
+
+ bool EnumDevices(char *bufDevices, int lenDevices, char *bufModes, int lenModes, int &totalDevices, int &selectDevices, int &totalModes, int &selectModes);
+ bool RetFullScreen();
+ bool ChangeDevice(char *device, char *mode, bool bFull);
+
+ void FlushPressKey();
+ void ResetKey();
+ void SetKey(int keyRank, int option, int key);
+ int RetKey(int keyRank, int option);
+
+ void SetJoystick(bool bEnable);
+ bool RetJoystick();
+
+ void SetMouseType(D3DMouse type);
+ void SetNiceMouse(bool bNice);
+ bool RetNiceMouse();
+ bool RetNiceMouseCap();
+
+ bool WriteScreenShot(char *filename, int width, int height);
+
+ bool GetRenderDC(HDC &hDC);
+ bool ReleaseRenderDC(HDC &hDC);
+ PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp);
+ bool CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC);
+
+protected:
+ HRESULT ConfirmDevice( DDCAPS* pddDriverCaps, D3DDEVICEDESC7* pd3dDeviceDesc );
+ HRESULT Initialize3DEnvironment();
+ HRESULT Change3DEnvironment();
+ HRESULT CreateZBuffer(GUID* pDeviceGUID);
+ HRESULT Render3DEnvironment();
+ VOID Cleanup3DEnvironment();
+ VOID DeleteDeviceObjects();
+ VOID DisplayFrameworkError( HRESULT, DWORD );
+
+ void InitText();
+ void DrawSuppl();
+ VOID ShowStats();
+ VOID OutputText( DWORD x, DWORD y, TCHAR* str );
+
+protected:
+ CInstanceManager* m_iMan;
+ CEvent* m_event;
+
+ HINSTANCE m_instance;
+ HWND m_hWnd;
+ D3DEnum_DeviceInfo* m_pDeviceInfo;
+ LPDIRECTDRAW7 m_pDD;
+ LPDIRECT3D7 m_pD3D;
+ LPDIRECT3DDEVICE7 m_pD3DDevice;
+ LPDIRECTDRAWSURFACE7 m_pddsRenderTarget;
+ DDSURFACEDESC2 m_ddsdRenderTarget;
+ LPDIRECTDRAWSURFACE7 m_pddsDepthBuffer;
+
+ HANDLE m_thread;
+ DWORD m_threadId;
+
+ char m_CDpath[100];
+
+ CD3DFramework7* m_pFramework;
+ bool m_bActive;
+ bool m_bActivateApp;
+ bool m_bReady;
+ bool m_bJoystick;
+
+ DWORD m_vidMemTotal;
+ TCHAR* m_strWindowTitle;
+ bool m_bAppUseZBuffer;
+ bool m_bAppUseStereo;
+ bool m_bShowStats;
+ bool m_bDebugMode;
+ bool m_bAudioState;
+ bool m_bAudioTrack;
+ bool m_bNiceMouse;
+ bool m_bSetupMode;
+ HRESULT (*m_fnConfirmDevice)(DDCAPS*, D3DDEVICEDESC7*);
+
+public:
+ CD3DEngine* m_pD3DEngine;
+ CRobotMain* m_pRobotMain;
+ CSound* m_pSound;
+
+ int m_keyState;
+ Math::Vector m_axeKey;
+ Math::Vector m_axeJoy;
+ bool m_bJoyButton[32];
+ Math::Point m_mousePos;
+ DWORD m_mshMouseWheel;
+
+ float m_aTime;
+ DWORD m_key[50][2];
+};
+
+
diff --git a/src/old/d3dengine.cpp b/src/old/d3dengine.cpp
index e28483d..79e4646 100644
--- a/src/old/d3dengine.cpp
+++ b/src/old/d3dengine.cpp
@@ -1,5825 +1,5825 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// d3dengine.cpp
-
-
-#include <stdio.h>
-#include <math.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "math/conv.h"
-#include "old/d3dapp.h"
-#include "old/d3dtextr.h"
-#include "old/d3dutil.h"
-#include "old/d3dmath.h"
-#include "old/d3dengine.h"
-#include "common/language.h"
-#include "common/iman.h"
-#include "common/event.h"
-#include "common/profile.h"
-#include "old/math3d.h"
-#include "object/object.h"
-#include "ui/interface.h"
-#include "old/light.h"
-#include "old/text.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "old/cloud.h"
-#include "old/blitz.h"
-#include "old/planet.h"
-#include "old/sound.h"
-
-
-
-const int SIZEBLOC_TEXTURE = 50;
-const int SIZEBLOC_TRANSFORM = 100;
-const int SIZEBLOC_MINMAX = 5;
-const int SIZEBLOC_LIGHT = 10;
-const int SIZEBLOC_MATERIAL = 100;
-const int SIZEBLOC_TRIANGLE = 200;
-
-
-
-#if 0
-static int debug_blend1 = 1;
-static int debug_blend2 = 3;
-static int debug_blend3 = 8;
-static int debug_blend4 = 0;
-
-static int table_blend[13] =
-{
- D3DBLEND_ZERO, // 0
- D3DBLEND_ONE, // 1
- D3DBLEND_SRCCOLOR, // 2
- D3DBLEND_INVSRCCOLOR, // 3
- D3DBLEND_SRCALPHA, // 4
- D3DBLEND_INVSRCALPHA, // 5
- D3DBLEND_DESTALPHA, // 6
- D3DBLEND_INVDESTALPHA, // 7
- D3DBLEND_DESTCOLOR, // 8
- D3DBLEND_INVDESTCOLOR, // 9
- D3DBLEND_SRCALPHASAT, // 10
- D3DBLEND_BOTHSRCALPHA, // 11
- D3DBLEND_BOTHINVSRCALPHA, // 12
-};
-#endif
-
-static int s_resol = 0;
-
-
-
-// Converts a FLOAT to a DWORD for use in SetRenderState() calls.
-
-inline DWORD F2DW( FLOAT f )
-{
- return *((DWORD*)&f);
-}
-
-
-
-
-// Application constructor. Sets attributes for the app.
-
-CD3DEngine::CD3DEngine(CInstanceManager *iMan, CD3DApplication *app)
-{
- int i;
-
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_ENGINE, this);
- m_app = app;
-
- m_light = new CLight(m_iMan, this);
- m_text = new CText(m_iMan, this);
- m_particule = new CParticule(m_iMan, this);
- m_water = new CWater(m_iMan, this);
- m_cloud = new CCloud(m_iMan, this);
- m_blitz = new CBlitz(m_iMan, this);
- m_planet = new CPlanet(m_iMan, this);
- m_pD3DDevice = 0;
- m_sound = 0;
- m_terrain = 0;
-
- m_dim.x = 640;
- m_dim.y = 480;
- m_lastDim = m_dim;
- m_focus = 0.75f;
- m_baseTime = 0;
- m_lastTime = 0;
- m_absTime = 0.0f;
- m_rankView = 0;
- m_ambiantColor[0] = 0x80808080;
- m_ambiantColor[1] = 0x80808080;
- m_fogColor[0] = 0xffffffff; // white
- m_fogColor[1] = 0xffffffff; // white
- m_deepView[0] = 1000.0f;
- m_deepView[1] = 1000.0f;
- m_fogStart[0] = 0.75f;
- m_fogStart[1] = 0.75f;
- m_waterAddColor.r = 0.0f;
- m_waterAddColor.g = 0.0f;
- m_waterAddColor.b = 0.0f;
- m_waterAddColor.a = 0.0f;
- m_bPause = false;
- m_bRender = true;
- m_bMovieLock = false;
- m_bShadow = true;
- m_bGroundSpot = true;
- m_bDirty = true;
- m_bFog = true;
- m_speed = 1.0f;
- m_secondTexNum = 0;
- m_eyeDirH = 0.0f;
- m_eyeDirV = 0.0f;
- m_backgroundName[0] = 0; // no background image
- m_backgroundColorUp = 0;
- m_backgroundColorDown = 0;
- m_backgroundCloudUp = 0;
- m_backgroundCloudDown = 0;
- m_bBackgroundFull = false;
- m_bBackgroundQuarter = false;
- m_bOverFront = true;
- m_overColor = 0;
- m_overMode = D3DSTATETCb;
- m_frontsizeName[0] = 0; // no front image
- m_hiliteRank[0] = -1; // empty list
- m_mousePos = Math::Point(0.5f, 0.5f);
- m_mouseType = D3DMOUSENORM;
- m_bMouseHide = false;
- m_imageSurface = 0;
- m_imageCopy = 0;
- m_eyePt = Math::Vector(0.0f, 0.0f, 0.0f);
- m_lookatPt = Math::Vector(0.0f, 0.0f, 1.0f);
- m_bDrawWorld = true;
- m_bDrawFront = false;
- m_limitLOD[0] = 100.0f;
- m_limitLOD[1] = 200.0f;
- m_particuleDensity = 1.0f;
- m_clippingDistance = 1.0f;
- m_lastClippingDistance = m_clippingDistance;
- m_objectDetail = 1.0f;
- m_lastObjectDetail = m_objectDetail;
- m_terrainVision = 1000.0f;
- m_gadgetQuantity = 1.0f;
- m_textureQuality = 1;
- m_bTotoMode = true;
- m_bLensMode = true;
- m_bWaterMode = true;
- m_bSkyMode = true;
- m_bBackForce = true;
- m_bPlanetMode = true;
- m_bLightMode = true;
- m_bEditIndentMode = true;
- m_editIndentValue = 4;
- m_tracePrecision = 1.0f;
-
- m_alphaMode = 1;
- if ( GetProfileInt("Engine", "AlphaMode", i) )
- {
- m_alphaMode = i;
- }
-
- if ( GetProfileInt("Engine", "StateColor", i) && i != -1 )
- {
- m_bForceStateColor = true;
- m_bStateColor = i;
- }
- else
- {
- m_bForceStateColor = false;
- m_bStateColor = false;
- }
-
- m_blackSrcBlend[0] = 0;
- m_blackDestBlend[0] = 0;
- m_whiteSrcBlend[0] = 0;
- m_whiteDestBlend[0] = 0;
- m_diffuseSrcBlend[0] = 0;
- m_diffuseDestBlend[0] = 0;
- m_alphaSrcBlend[0] = 0;
- m_alphaDestBlend[0] = 0;
-
- if ( GetProfileInt("Engine", "BlackSrcBlend", i) ) m_blackSrcBlend[0] = i;
- if ( GetProfileInt("Engine", "BlackDestBlend", i) ) m_blackDestBlend[0] = i;
- if ( GetProfileInt("Engine", "WhiteSrcBlend", i) ) m_whiteSrcBlend[0] = i;
- if ( GetProfileInt("Engine", "WhiteDestBlend", i) ) m_whiteDestBlend[0] = i;
- if ( GetProfileInt("Engine", "DiffuseSrcBlend", i) ) m_diffuseSrcBlend[0] = i;
- if ( GetProfileInt("Engine", "DiffuseDestBlend", i) ) m_diffuseDestBlend[0] = i;
- if ( GetProfileInt("Engine", "AlphaSrcBlend", i) ) m_alphaSrcBlend[0] = i;
- if ( GetProfileInt("Engine", "AlphaDestBlend", i) ) m_alphaDestBlend[0] = i;
-
- m_bUpdateGeometry = false;
-
- for ( i=0 ; i<10 ; i++ )
- {
- m_infoText[i][0] = 0;
- }
-
- m_objectPointer = 0;
- MemSpace1(m_objectPointer, 0);
-
- m_objectParam = (D3DObject*)malloc(sizeof(D3DObject)*D3DMAXOBJECT);
- ZeroMemory(m_objectParam, sizeof(D3DObject)*D3DMAXOBJECT);
- m_objectParamTotal = 0;
-
- m_shadow = (D3DShadow*)malloc(sizeof(D3DShadow)*D3DMAXSHADOW);
- ZeroMemory(m_shadow, sizeof(D3DShadow)*D3DMAXSHADOW);
- m_shadowTotal = 0;
-
- m_groundSpot = (D3DGroundSpot*)malloc(sizeof(D3DGroundSpot)*D3DMAXGROUNDSPOT);
- ZeroMemory(m_groundSpot, sizeof(D3DGroundSpot)*D3DMAXGROUNDSPOT);
-
- ZeroMemory(&m_groundMark, sizeof(D3DGroundMark));
-
- D3DTextr_SetTexturePath("textures\\");
-}
-
-// Application destructor. Free memory.
-
-CD3DEngine::~CD3DEngine()
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- int l1, l2, l3, l4, l5;
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- free(p6);
- }
- free(p5);
- }
- free(p4);
- }
- free(p3);
- }
- free(p2);
- }
- free(p1);
-
- delete m_light;
- delete m_particule;
- delete m_water;
- delete m_cloud;
- delete m_blitz;
- delete m_planet;
-}
-
-
-
-void CD3DEngine::SetD3DDevice(LPDIRECT3DDEVICE7 device)
-{
- D3DDEVICEDESC7 ddDesc;
-
- m_pD3DDevice = device;
- m_light->SetD3DDevice(device);
- m_text->SetD3DDevice(device);
- m_particule->SetD3DDevice(device);
-
- if ( !m_bForceStateColor )
- {
- m_pD3DDevice->GetCaps(&ddDesc);
- if( ddDesc.dpcTriCaps.dwTextureBlendCaps & D3DPTBLENDCAPS_ADD )
- {
- m_bStateColor = true;
- }
- else
- {
- m_bStateColor = false;
- }
- }
-
- m_blackSrcBlend[1] = D3DBLEND_ONE; // = 2
- m_blackDestBlend[1] = D3DBLEND_INVSRCCOLOR; // = 4
- m_whiteSrcBlend[1] = D3DBLEND_DESTCOLOR; // = 9
- m_whiteDestBlend[1] = D3DBLEND_ZERO; // = 1
- m_diffuseSrcBlend[1] = D3DBLEND_SRCALPHA; // = 5
- m_diffuseDestBlend[1] = D3DBLEND_DESTALPHA; // = 7
- m_alphaSrcBlend[1] = D3DBLEND_ONE; // = 2
- m_alphaDestBlend[1] = D3DBLEND_INVSRCCOLOR; // = 4
-
-//? if ( !m_bStateColor ) m_whiteDestBlend[1] = D3DBLEND_INVSRCALPHA; // = 6
-
-// Fix for the graphics bug:
- //if ( m_blackSrcBlend[0] ) m_blackSrcBlend[1] = m_blackSrcBlend[0];
- //if ( m_blackDestBlend[0] ) m_blackDestBlend[1] = m_blackDestBlend[0];
- //if ( m_whiteSrcBlend[0] ) m_whiteSrcBlend[1] = m_whiteSrcBlend[0];
- //if ( m_whiteDestBlend[0] ) m_whiteDestBlend[1] = m_whiteDestBlend[0];
-
- if ( m_diffuseSrcBlend[0] ) m_diffuseSrcBlend[1] = m_diffuseSrcBlend[0];
- if ( m_diffuseDestBlend[0] ) m_diffuseDestBlend[1] = m_diffuseDestBlend[0];
- if ( m_alphaSrcBlend[0] ) m_alphaSrcBlend[1] = m_alphaSrcBlend[0];
- if ( m_alphaDestBlend[0] ) m_alphaDestBlend[1] = m_alphaDestBlend[0];
-
-#if 0
- DWORD pass;
- m_pD3DDevice->ValidateDevice(&pass);
- char s[100];
- sprintf(s, "NbPass=%d", pass);
- SetInfoText(3, s);
-#endif
-}
-
-LPDIRECT3DDEVICE7 CD3DEngine::RetD3DDevice()
-{
- return m_pD3DDevice;
-}
-
-
-// Gives the pointer to the existing terrain.
-
-void CD3DEngine::SetTerrain(CTerrain* terrain)
-{
- m_terrain = terrain;
-}
-
-
-// Saving the state of the graphics engine in COLOBOT.INI.
-
-bool CD3DEngine::WriteProfile()
-{
- SetProfileInt("Engine", "AlphaMode", m_alphaMode);
-
- if ( m_bForceStateColor )
- {
- SetProfileInt("Engine", "StateColor", m_bStateColor);
- }
- else
- {
- SetProfileInt("Engine", "StateColor", -1);
- }
-
- SetProfileInt("Engine", "BlackSrcBlend", m_blackSrcBlend[0]);
- SetProfileInt("Engine", "BlackDestBlend", m_blackDestBlend[0]);
- SetProfileInt("Engine", "WhiteSrcBlend", m_whiteSrcBlend[0]);
- SetProfileInt("Engine", "WhiteDestBlend", m_whiteDestBlend[0]);
- SetProfileInt("Engine", "DiffuseSrcBlend", m_diffuseSrcBlend[0]);
- SetProfileInt("Engine", "DiffuseDestBlend", m_diffuseDestBlend[0]);
- SetProfileInt("Engine", "AlphaSrcBlend", m_alphaSrcBlend[0]);
- SetProfileInt("Engine", "AlphaDestBlend", m_alphaDestBlend[0]);
-
- return true;
-}
-
-
-// Setup the app so it can support single-stepping.
-
-void CD3DEngine::TimeInit()
-{
- m_baseTime = timeGetTime();
- m_lastTime = 0;
- m_absTime = 0.0f;
-}
-
-void CD3DEngine::TimeEnterGel()
-{
- m_stopTime = timeGetTime();
-}
-
-void CD3DEngine::TimeExitGel()
-{
- m_baseTime += timeGetTime() - m_stopTime;
-}
-
-float CD3DEngine::TimeGet()
-{
- float aTime, rTime;
-
- aTime = (timeGetTime()-m_baseTime)*0.001f; // in ms
- rTime = (aTime - m_lastTime)*m_speed;
- m_absTime += rTime;
- m_lastTime = aTime;
-
- return rTime;
-}
-
-
-void CD3DEngine::SetPause(bool bPause)
-{
- m_bPause = bPause;
-}
-
-bool CD3DEngine::RetPause()
-{
- return m_bPause;
-}
-
-
-void CD3DEngine::SetMovieLock(bool bLock)
-{
- m_bMovieLock = bLock;
-}
-
-bool CD3DEngine::RetMovieLock()
-{
- return m_bMovieLock;
-}
-
-
-void CD3DEngine::SetShowStat(bool bShow)
-{
- m_app->SetShowStat(bShow);
-}
-
-bool CD3DEngine::RetShowStat()
-{
- return m_app->RetShowStat();
-}
-
-
-void CD3DEngine::SetRenderEnable(bool bEnable)
-{
- m_bRender = bEnable;
-}
-
-
-// Prepare a structure to add D3DObjLevel6
-// qq D3DVERTEX2 elements.
-
-void CD3DEngine::MemSpace6(D3DObjLevel6 *&p, int nb)
-{
- D3DObjLevel6* pp;
- int total, size;
-
- if ( p == 0 )
- {
- total = SIZEBLOC_TRIANGLE+nb;
- size = sizeof(D3DObjLevel6)+sizeof(D3DVERTEX2)*(total-1);
- p = (D3DObjLevel6*)malloc(size);
- ZeroMemory(p, size);
- p->totalPossible = total;
- return;
- }
-
- if ( p->totalUsed+nb > p->totalPossible )
- {
- total = p->totalPossible+SIZEBLOC_TRIANGLE+nb;
- size = sizeof(D3DObjLevel6)+sizeof(D3DVERTEX2)*(total-1);
- pp = (D3DObjLevel6*)malloc(size);
- ZeroMemory(pp, size);
- CopyMemory(pp, p, sizeof(D3DObjLevel6)+sizeof(D3DVERTEX2)*(p->totalPossible-1));
- pp->totalPossible = total;
- free(p);
- p = pp;
- }
-}
-
-// Prepare a structure to add D3DObjLevel5
-// qq elements D3DObjLevel6.
-
-void CD3DEngine::MemSpace5(D3DObjLevel5 *&p, int nb)
-{
- D3DObjLevel5* pp;
- int total, size;
-
- if ( p == 0 )
- {
- total = SIZEBLOC_MATERIAL+nb;
- size = sizeof(D3DObjLevel5)+sizeof(D3DObjLevel6*)*(total-1);
- p = (D3DObjLevel5*)malloc(size);
- ZeroMemory(p, size);
- p->totalPossible = total;
- return;
- }
-
- if ( p->totalUsed+nb > p->totalPossible )
- {
- total = p->totalPossible+SIZEBLOC_MATERIAL+nb;
- size = sizeof(D3DObjLevel5)+sizeof(D3DObjLevel6*)*(total-1);
- pp = (D3DObjLevel5*)malloc(size);
- ZeroMemory(pp, size);
- CopyMemory(pp, p, sizeof(D3DObjLevel5)+sizeof(D3DObjLevel6*)*(p->totalPossible-1));
- pp->totalPossible = total;
- free(p);
- p = pp;
- }
-}
-
-// Prepare a structure to add D3DObjLevel4
-// qq D3DObjLevel5 elements.
-
-void CD3DEngine::MemSpace4(D3DObjLevel4 *&p, int nb)
-{
- D3DObjLevel4* pp;
- int total, size;
-
- if ( p == 0 )
- {
- total = SIZEBLOC_LIGHT+nb;
- size = sizeof(D3DObjLevel4)+sizeof(D3DObjLevel5*)*(total-1);
- p = (D3DObjLevel4*)malloc(size);
- ZeroMemory(p, size);
- p->totalPossible = total;
- return;
- }
-
- if ( p->totalUsed+nb > p->totalPossible )
- {
- total = p->totalPossible+SIZEBLOC_LIGHT+nb;
- size = sizeof(D3DObjLevel4)+sizeof(D3DObjLevel5*)*(total-1);
- pp = (D3DObjLevel4*)malloc(size);
- ZeroMemory(pp, size);
- CopyMemory(pp, p, sizeof(D3DObjLevel4)+sizeof(D3DObjLevel5*)*(p->totalPossible-1));
- pp->totalPossible = total;
- free(p);
- p = pp;
- }
-}
-
-// Prepare a structure to add D3DObjLevel3
-// qq D3DObjLevel4 elements.
-
-void CD3DEngine::MemSpace3(D3DObjLevel3 *&p, int nb)
-{
- D3DObjLevel3* pp;
- int total, size;
-
- if ( p == 0 )
- {
- total = SIZEBLOC_MINMAX+nb;
- size = sizeof(D3DObjLevel3)+sizeof(D3DObjLevel4*)*(total-1);
- p = (D3DObjLevel3*)malloc(size);
- ZeroMemory(p, size);
- p->totalPossible = total;
- return;
- }
-
- if ( p->totalUsed+nb > p->totalPossible )
- {
- total = p->totalPossible+SIZEBLOC_MINMAX+nb;
- size = sizeof(D3DObjLevel3)+sizeof(D3DObjLevel4*)*(total-1);
- pp = (D3DObjLevel3*)malloc(size);
- ZeroMemory(pp, size);
- CopyMemory(pp, p, sizeof(D3DObjLevel3)+sizeof(D3DObjLevel4*)*(p->totalPossible-1));
- pp->totalPossible = total;
- free(p);
- p = pp;
- }
-}
-
-// Prepare a structure to add D3DObjLevel2
-// qq D3DObjLevel3 elements.
-
-void CD3DEngine::MemSpace2(D3DObjLevel2 *&p, int nb)
-{
- D3DObjLevel2* pp;
- int total, size;
-
- if ( p == 0 )
- {
- total = SIZEBLOC_TRANSFORM+nb;
- size = sizeof(D3DObjLevel2)+sizeof(D3DObjLevel3*)*(total-1);
- p = (D3DObjLevel2*)malloc(size);
- ZeroMemory(p, size);
- p->totalPossible = total;
- return;
- }
-
- if ( p->totalUsed+nb > p->totalPossible )
- {
- total = p->totalPossible+SIZEBLOC_TRANSFORM+nb;
- size = sizeof(D3DObjLevel2)+sizeof(D3DObjLevel3*)*(total-1);
- pp = (D3DObjLevel2*)malloc(size);
- ZeroMemory(pp, size);
- CopyMemory(pp, p, sizeof(D3DObjLevel2)+sizeof(D3DObjLevel3*)*(p->totalPossible-1));
- pp->totalPossible = total;
- free(p);
- p = pp;
- }
-}
-
-// Prepare a structure to add D3DObjLevel1
-// qq D3DObjLevel2 elements.
-
-void CD3DEngine::MemSpace1(D3DObjLevel1 *&p, int nb)
-{
- D3DObjLevel1* pp;
- int total, size;
-
- if ( p == 0 )
- {
- total = SIZEBLOC_TEXTURE+nb;
- size = sizeof(D3DObjLevel1)+sizeof(D3DObjLevel2*)*(total-1);
- p = (D3DObjLevel1*)malloc(size);
- ZeroMemory(p, size);
- p->totalPossible = total;
- return;
- }
-
- if ( p->totalUsed+nb > p->totalPossible )
- {
- total = p->totalPossible+SIZEBLOC_TEXTURE+nb;
- size = sizeof(D3DObjLevel1)+sizeof(D3DObjLevel2*)*(total-1);
- pp = (D3DObjLevel1*)malloc(size);
- ZeroMemory(pp, size);
- CopyMemory(pp, p, sizeof(D3DObjLevel1)+sizeof(D3DObjLevel2*)*(p->totalPossible-1));
- pp->totalPossible = total;
- free(p);
- p = pp;
- }
-}
-
-
-// Returns the number of objects that can still be created.
-
-int CD3DEngine::RetRestCreate()
-{
- return D3DMAXOBJECT-m_objectParamTotal-2;
-}
-
-// Creates a new object. Returns its rank or -1 on error.
-
-int CD3DEngine::CreateObject()
-{
- Math::Matrix mat;
- int i;
-
- for ( i=0 ; i<D3DMAXOBJECT ; i++ )
- {
- if ( m_objectParam[i].bUsed == false )
- {
- ZeroMemory(&m_objectParam[i], sizeof(D3DObject));
- m_objectParam[i].bUsed = true;
-
- mat.LoadIdentity();
- SetObjectTransform(i, mat);
-
- m_objectParam[i].bDrawWorld = true;
- m_objectParam[i].distance = 0.0f;
- m_objectParam[i].bboxMin = Math::Vector(0.0f, 0.0f, 0.0f);
- m_objectParam[i].bboxMax = Math::Vector(0.0f, 0.0f, 0.0f);
- m_objectParam[i].shadowRank = -1;
-
- if ( i >= m_objectParamTotal )
- {
- m_objectParamTotal = i+1;
- }
- return i;
- }
- }
- OutputDebugString("CD3DEngine::CreateObject() -> Too many object\n");
- return -1;
-}
-
-
-// Removes all objects.
-
-void CD3DEngine::FlushObject()
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- int l1, l2, l3, l4, l5, i;
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- free(p6);
- }
- free(p5);
- }
- free(p4);
- }
- free(p3);
- }
- free(p2);
- p1->table[l1] = 0;
- }
- p1->totalUsed = 0;
-
- for ( i=0 ; i<D3DMAXOBJECT ; i++ )
- {
- m_objectParam[i].bUsed = false;
- }
- m_objectParamTotal = 0;
-
- ZeroMemory(m_shadow, sizeof(D3DShadow)*D3DMAXSHADOW);
- m_shadowTotal = 0;
-
- GroundSpotFlush();
-}
-
-// Destroys an existing object.
-
-bool CD3DEngine::DeleteObject(int objRank)
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- int l1, l2, l3, l4, l5, i;
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- if ( p3->objRank != objRank ) continue;
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- free(p6);
- }
- free(p5);
- }
- free(p4);
- }
- free(p3);
- p2->table[l2] = 0;
- }
- }
-
- ShadowDelete(objRank); // removes the shadow
-
- m_objectParam[objRank].bUsed = false;
-
- m_objectParamTotal = 0;
- for ( i=0 ; i<D3DMAXOBJECT ; i++ )
- {
- if ( m_objectParam[i].bUsed )
- {
- m_objectParamTotal = i+1;
- }
- }
-
- return true;
-}
-
-
-// Indicates whether an object should be drawn underneath the interface.
-
-bool CD3DEngine::SetDrawWorld(int objRank, bool bDraw)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- m_objectParam[objRank].bDrawWorld = bDraw;
- return true;
-}
-
-// Indicates whether an object should be drawn over the interface.
-
-bool CD3DEngine::SetDrawFront(int objRank, bool bDraw)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- m_objectParam[objRank].bDrawFront = bDraw;
- return true;
-}
-
-
-// Prepare Level 1 to add a triangle.
-
-D3DObjLevel2* CD3DEngine::AddLevel1(D3DObjLevel1 *&p1, char* texName1, char* texName2)
-{
- D3DObjLevel2* p2;
- int l1;
-
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- if ( strcmp(p2->texName1, texName1) == 0 &&
- strcmp(p2->texName2, texName2) == 0 )
- {
- MemSpace2(p1->table[l1], 1);
- return p1->table[l1];
- }
- }
-
- MemSpace1(p1, 1);
- l1 = p1->totalUsed++;
- p1->table[l1] = 0;
-
- MemSpace2(p1->table[l1], 1);
- strcpy(p1->table[l1]->texName1, texName1);
- strcpy(p1->table[l1]->texName2, texName2);
- return p1->table[l1];
-}
-
-// Prepare Level 2 to add a triangle.
-
-D3DObjLevel3* CD3DEngine::AddLevel2(D3DObjLevel2 *&p2, int objRank)
-{
- D3DObjLevel3* p3;
- int l2;
-
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- if ( p3->objRank == objRank )
- {
- MemSpace3(p2->table[l2], 1);
- return p2->table[l2];
- }
- }
-
- MemSpace2(p2, 1);
- l2 = p2->totalUsed++;
- p2->table[l2] = 0;
-
- MemSpace3(p2->table[l2], 1);
- p2->table[l2]->objRank = objRank;
- return p2->table[l2];
-}
-
-// Prepare Level 3 to add a triangle.
-
-D3DObjLevel4* CD3DEngine::AddLevel3(D3DObjLevel3 *&p3, float min, float max)
-{
- D3DObjLevel4* p4;
- int l3;
-
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( p4->min == min && p4->max == max )
- {
- MemSpace4(p3->table[l3], 1);
- return p3->table[l3];
- }
- }
-
- MemSpace3(p3, 1);
- l3 = p3->totalUsed++;
- p3->table[l3] = 0;
-
- MemSpace4(p3->table[l3], 1);
- p3->table[l3]->min = min;
- p3->table[l3]->max = max;
- return p3->table[l3];
-}
-
-// Prepare Level 4 to add a triangle.
-
-D3DObjLevel5* CD3DEngine::AddLevel4(D3DObjLevel4 *&p4, int reserve)
-{
- D3DObjLevel5* p5;
- int l4;
-
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- if ( p5->reserve == reserve )
- {
- MemSpace5(p4->table[l4], 1);
- return p4->table[l4];
- }
- }
-
- MemSpace4(p4, 1);
- l4 = p4->totalUsed++;
- p4->table[l4] = 0;
-
- MemSpace5(p4->table[l4], 1);
- p4->table[l4]->reserve = reserve;
- return p4->table[l4];
-}
-
-// Prepares Level 5 to add vertices.
-
-D3DObjLevel6* CD3DEngine::AddLevel5(D3DObjLevel5 *&p5, D3DTypeTri type,
- const D3DMATERIAL7 &mat, int state,
- int nb)
-{
- D3DObjLevel6* p6;
- int l5;
-
- if ( type == D3DTYPE6T )
- {
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- if ( p6->type == type &&
- memcmp(&p6->material, &mat, sizeof(D3DMATERIAL7)) == 0 &&
- p6->state == state )
- {
- MemSpace6(p5->table[l5], nb);
- return p5->table[l5];
- }
- }
- }
-
- MemSpace5(p5, 1);
- l5 = p5->totalUsed++;
- p5->table[l5] = 0;
-
- MemSpace6(p5->table[l5], nb);
- p5->table[l5]->type = type;
- p5->table[l5]->material = mat;
- p5->table[l5]->state = state;
- return p5->table[l5];
-}
-
-// Adds one or more triangles to an existing object.
-// The number must be divisible by 3.
-
-bool CD3DEngine::AddTriangle(int objRank, D3DVERTEX2* vertex, int nb,
- const D3DMATERIAL7 &mat, int state,
- char* texName1, char* texName2,
- float min, float max, bool bGlobalUpdate)
-{
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- int i;
-
- m_lastDim = m_dim;
- m_lastObjectDetail = m_objectDetail;
- m_lastClippingDistance = m_clippingDistance;
-
- p2 = AddLevel1(m_objectPointer, texName1, texName2);
- p3 = AddLevel2(p2, objRank);
- p4 = AddLevel3(p3, min, max);
- p5 = AddLevel4(p4, 0);
- p6 = AddLevel5(p5, D3DTYPE6T, mat, state, nb); // place for number of vertex
-
- CopyMemory(&p6->vertex[p6->totalUsed], vertex, sizeof(D3DVERTEX2)*nb);
- p6->totalUsed += nb;
-
- if ( bGlobalUpdate )
- {
- m_bUpdateGeometry = true;
- }
- else
- {
- for ( i=0 ; i<nb ; i++ )
- {
- m_objectParam[objRank].bboxMin.x = Math::Min(vertex[i].x, m_objectParam[objRank].bboxMin.x);
- m_objectParam[objRank].bboxMin.y = Math::Min(vertex[i].y, m_objectParam[objRank].bboxMin.y);
- m_objectParam[objRank].bboxMin.z = Math::Min(vertex[i].z, m_objectParam[objRank].bboxMin.z);
- m_objectParam[objRank].bboxMax.x = Math::Max(vertex[i].x, m_objectParam[objRank].bboxMax.x);
- m_objectParam[objRank].bboxMax.y = Math::Max(vertex[i].y, m_objectParam[objRank].bboxMax.y);
- m_objectParam[objRank].bboxMax.z = Math::Max(vertex[i].z, m_objectParam[objRank].bboxMax.z);
- }
-
- m_objectParam[objRank].radius = Math::Max(m_objectParam[objRank].bboxMin.Length(),
- m_objectParam[objRank].bboxMax.Length());
- }
- m_objectParam[objRank].totalTriangle += nb/3;
-
- return true;
-}
-
-// Adds a surface consisting of triangles joined.
-
-bool CD3DEngine::AddSurface(int objRank, D3DVERTEX2* vertex, int nb,
- const D3DMATERIAL7 &mat, int state,
- char* texName1, char* texName2,
- float min, float max, bool bGlobalUpdate)
-{
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- int i;
-
- p2 = AddLevel1(m_objectPointer, texName1, texName2);
- p3 = AddLevel2(p2, objRank);
- p4 = AddLevel3(p3, min, max);
- p5 = AddLevel4(p4, 0);
- p6 = AddLevel5(p5, D3DTYPE6S, mat, state, nb); // place for number of vertex
-
- CopyMemory(&p6->vertex[p6->totalUsed], vertex, sizeof(D3DVERTEX2)*nb);
- p6->totalUsed += nb;
-
- if ( bGlobalUpdate )
- {
- m_bUpdateGeometry = true;
- }
- else
- {
- for ( i=0 ; i<nb ; i++ )
- {
- m_objectParam[objRank].bboxMin.x = Math::Min(vertex[i].x, m_objectParam[objRank].bboxMin.x);
- m_objectParam[objRank].bboxMin.y = Math::Min(vertex[i].y, m_objectParam[objRank].bboxMin.y);
- m_objectParam[objRank].bboxMin.z = Math::Min(vertex[i].z, m_objectParam[objRank].bboxMin.z);
- m_objectParam[objRank].bboxMax.x = Math::Max(vertex[i].x, m_objectParam[objRank].bboxMax.x);
- m_objectParam[objRank].bboxMax.y = Math::Max(vertex[i].y, m_objectParam[objRank].bboxMax.y);
- m_objectParam[objRank].bboxMax.z = Math::Max(vertex[i].z, m_objectParam[objRank].bboxMax.z);
- }
-
- m_objectParam[objRank].radius = Math::Max(m_objectParam[objRank].bboxMin.Length(),
- m_objectParam[objRank].bboxMax.Length());
- }
- m_objectParam[objRank].totalTriangle += nb-2;
-
- return true;
-}
-
-// Adds a surface consisting of triangles joined.
-// The buffer is not copied.
-
-bool CD3DEngine::AddQuick(int objRank, D3DObjLevel6* buffer,
- char* texName1, char* texName2,
- float min, float max, bool bGlobalUpdate)
-{
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- int l5, i;
-
- p2 = AddLevel1(m_objectPointer, texName1, texName2);
- p3 = AddLevel2(p2, objRank);
- p4 = AddLevel3(p3, min, max);
- p5 = AddLevel4(p4, 0);
-
- MemSpace5(p5, 1);
- l5 = p5->totalUsed++;
- p5->table[l5] = buffer;
-
- if ( bGlobalUpdate )
- {
- m_bUpdateGeometry = true;
- }
- else
- {
- for ( i=0 ; i<buffer->totalUsed ; i++ )
- {
- m_objectParam[objRank].bboxMin.x = Math::Min(buffer->vertex[i].x, m_objectParam[objRank].bboxMin.x);
- m_objectParam[objRank].bboxMin.y = Math::Min(buffer->vertex[i].y, m_objectParam[objRank].bboxMin.y);
- m_objectParam[objRank].bboxMin.z = Math::Min(buffer->vertex[i].z, m_objectParam[objRank].bboxMin.z);
- m_objectParam[objRank].bboxMax.x = Math::Max(buffer->vertex[i].x, m_objectParam[objRank].bboxMax.x);
- m_objectParam[objRank].bboxMax.y = Math::Max(buffer->vertex[i].y, m_objectParam[objRank].bboxMax.y);
- m_objectParam[objRank].bboxMax.z = Math::Max(buffer->vertex[i].z, m_objectParam[objRank].bboxMax.z);
- }
-
- m_objectParam[objRank].radius = Math::Max(m_objectParam[objRank].bboxMin.Length(),
- m_objectParam[objRank].bboxMax.Length());
- }
- m_objectParam[objRank].totalTriangle += buffer->totalUsed-2;
-
- return true;
-}
-
-
-// Looking for a list of triangles.
-
-void CD3DEngine::ChangeLOD()
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- int l1, l2, l3;
- float oldLimit[2], newLimit[2];
- float oldTerrain, newTerrain;
-
- oldLimit[0] = RetLimitLOD(0, true);
- oldLimit[1] = RetLimitLOD(1, true);
-
- newLimit[0] = RetLimitLOD(0, false);
- newLimit[1] = RetLimitLOD(1, false);
-
- oldTerrain = m_terrainVision*m_lastClippingDistance;
- newTerrain = m_terrainVision*m_clippingDistance;
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
-
- if ( Math::IsEqual(p4->min, 0.0f ) &&
- Math::IsEqual(p4->max, oldLimit[0]) )
- {
- p4->max = newLimit[0];
- }
- else if ( Math::IsEqual(p4->min, oldLimit[0]) &&
- Math::IsEqual(p4->max, oldLimit[1]) )
- {
- p4->min = newLimit[0];
- p4->max = newLimit[1];
- }
- else if ( Math::IsEqual(p4->min, oldLimit[1]) &&
- Math::IsEqual(p4->max, 1000000.0f ) )
- {
- p4->min = newLimit[1];
- }
- else if ( Math::IsEqual(p4->min, 0.0f ) &&
- Math::IsEqual(p4->max, oldTerrain) )
- {
- p4->max = newTerrain;
- }
- }
- }
- }
-
- m_lastDim = m_dim;
- m_lastObjectDetail = m_objectDetail;
- m_lastClippingDistance = m_clippingDistance;
-}
-
-// Looking for a list of triangles.
-
-D3DObjLevel6* CD3DEngine::SearchTriangle(int objRank,
- const D3DMATERIAL7 &mat, int state,
- char* texName1, char* texName2,
- float min, float max)
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- int l1, l2, l3, l4, l5;
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
-//? if ( strcmp(p2->texName1, texName1) != 0 ||
-//? strcmp(p2->texName2, texName2) != 0 ) continue;
- if ( strcmp(p2->texName1, texName1) != 0 ) continue;
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- if ( p3->objRank != objRank ) continue;
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( p4->min != min ||
- p4->max != max ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
-//? if ( p6->state != state ||
- if ( (p6->state&(~(D3DSTATEDUALb|D3DSTATEDUALw))) != state ||
- memcmp(&p6->material, &mat, sizeof(D3DMATERIAL7)) != 0 ) continue;
- return p6;
- }
- }
- }
- }
- }
- return 0;
-}
-
-// Secondary changes the texture of an object.
-
-bool CD3DEngine::ChangeSecondTexture(int objRank, char* texName2)
-{
- D3DObjLevel2* newp2;
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- int l1, l2;
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- if ( strcmp(p2->texName2, texName2) == 0 ) continue; // already new
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- if ( p3->objRank != objRank ) continue;
-
- newp2 = AddLevel1(m_objectPointer, p2->texName1, texName2);
-
- if ( newp2->totalUsed >= newp2->totalPossible ) continue; // to do better!!!
- newp2->table[newp2->totalUsed++] = p3;
-
- p2->table[l2] = 0;
- }
- }
- return true;
-}
-
-
-// Returns the number of triangles of the object.
-
-int CD3DEngine::RetTotalTriangles(int objRank)
-{
- return m_objectParam[objRank].totalTriangle;
-}
-
-// Return qq triangles of an object.
-// qq triangles used to extract an object that explodes.
-// "Percent" is between 0 and 1.
-
-int CD3DEngine::GetTriangles(int objRank, float min, float max,
- D3DTriangle* buffer, int size, float percent)
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- D3DVERTEX2* pv;
- int l1, l2, l3, l4, l5, l6, i, rank;
-
- rank = 0;
- i = 0;
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
-//? if ( p2->texName[0] == 0 ) continue;
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- if ( p3->objRank != objRank ) continue;
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( p4->min != min ||
- p4->max != max ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- if ( p6->type == D3DTYPE6T )
- {
- pv = &p6->vertex[0];
- for ( l6=0 ; l6<p6->totalUsed/3 ; l6++ )
- {
- if ( (float)i/rank <= percent )
- {
- if ( i >= size ) break;
- buffer[i].triangle[0] = pv[0];
- buffer[i].triangle[1] = pv[1];
- buffer[i].triangle[2] = pv[2];
- buffer[i].material = p6->material;
- buffer[i].state = p6->state;
- strcpy(buffer[i].texName1, p2->texName1);
- strcpy(buffer[i].texName2, p2->texName2);
- i ++;
- }
- rank ++;
- pv += 3;
- }
- }
- if ( p6->type == D3DTYPE6S )
- {
- pv = &p6->vertex[0];
- for ( l6=0 ; l6<p6->totalUsed-2 ; l6++ )
- {
- if ( (float)i/rank <= percent )
- {
- if ( i >= size ) break;
- buffer[i].triangle[0] = pv[0];
- buffer[i].triangle[1] = pv[1];
- buffer[i].triangle[2] = pv[2];
- buffer[i].material = p6->material;
- buffer[i].state = p6->state;
- strcpy(buffer[i].texName1, p2->texName1);
- strcpy(buffer[i].texName2, p2->texName2);
- i ++;
- }
- rank ++;
- pv += 1;
- }
- }
- }
- }
- }
- }
- }
- return i;
-}
-
-// Give the box of an object.
-
-bool CD3DEngine::GetBBox(int objRank, Math::Vector &min, Math::Vector &max)
-{
- min = m_objectParam[objRank].bboxMin;
- max = m_objectParam[objRank].bboxMax;
- return true;
-}
-
-
-// Change the texture mapping for a list of triangles.
-
-bool CD3DEngine::ChangeTextureMapping(int objRank,
- const D3DMATERIAL7 &mat, int state,
- char* texName1, char* texName2,
- float min, float max,
- D3DMaping mode,
- float au, float bu,
- float av, float bv)
-{
- D3DObjLevel6* p6;
- D3DVERTEX2* pv;
- int l6, nb;
-
- p6 = SearchTriangle(objRank, mat, state, texName1, texName2, min, max);
- if ( p6 == 0 ) return false;
-
- pv = &p6->vertex[0];
- nb = p6->totalUsed;
-
- if ( mode == D3DMAPPINGX )
- {
- for ( l6=0 ; l6<nb ; l6++ )
- {
- pv->tu = pv->z*au+bu;
- pv->tv = pv->y*av+bv;
- pv ++;
- }
- }
-
- if ( mode == D3DMAPPINGY )
- {
- for ( l6=0 ; l6<nb ; l6++ )
- {
- pv->tu = pv->x*au+bu;
- pv->tv = pv->z*av+bv;
- pv ++;
- }
- }
-
- if ( mode == D3DMAPPINGZ )
- {
- for ( l6=0 ; l6<nb ; l6++ )
- {
- pv->tu = pv->x*au+bu;
- pv->tv = pv->y*av+bv;
- pv ++;
- }
- }
-
- if ( mode == D3DMAPPING1X )
- {
- for ( l6=0 ; l6<nb ; l6++ )
- {
- pv->tu = pv->x*au+bu;
- pv ++;
- }
- }
-
- if ( mode == D3DMAPPING1Y )
- {
- for ( l6=0 ; l6<nb ; l6++ )
- {
- pv->tv = pv->y*au+bu;
- pv ++;
- }
- }
-
- if ( mode == D3DMAPPING1Z )
- {
- for ( l6=0 ; l6<nb ; l6++ )
- {
- pv->tu = pv->z*au+bu;
- pv ++;
- }
- }
-
- return true;
-}
-
-// Change the texture mapping for a list of triangles
-// to simulate a caterpillar that turns.
-// Only the mapping as "u" is changed.
-//
-// pos: position on the periphery [p]
-// tl: length repetitive element of the texture [t]
-// ts: beginning of the texture[t]
-// tt: total width of the texture [t]
-//
-// [p] = distance in the 3D world
-// [t] = position in the texture (pixels)
-
-// ^ y 5
-// | 6 o---------o 4
-// | / \
-// | o o
-// | 7 | | 3
-// | o current o
-// | \ | /
-// | 0 o---------o 2
-// | 1
-// -o-----------------------> x
-// |
-//
-// Quand l6=1 :
-// 0 1 2 3 4 ... 7
-// o--o---------o--o--o--o-//-o--o development track
-// |ps| |
-// <--> pe |
-// <------------>
-//
-// Texture :
-// o---------------o
-// | |
-// | o-o-o-o-o |
-// | | | | | |<--- texture of the track
-// | o-o-o-o-o |
-// | | | tl |
-// | ->|-|<--- |
-// | | |
-// o-----|---------o--> u
-// | ts | |
-// <-----> tt |
-// <--------------->
-
-bool CD3DEngine::TrackTextureMapping(int objRank,
- const D3DMATERIAL7 &mat, int state,
- char* texName1, char* texName2,
- float min, float max,
- D3DMaping mode, float pos, float factor,
- float tl, float ts, float tt)
-{
- D3DObjLevel6* p6;
- D3DVERTEX2* pv;
- Math::Vector current;
- float ps, pe, pps, ppe, offset;
- int l6, nb, i, j, s, e;
- int is[6], ie[6];
-
- p6 = SearchTriangle(objRank, mat, state, texName1, texName2, min, max);
- if ( p6 == 0 ) return false;
-
- pv = &p6->vertex[0];
- nb = p6->totalUsed;
-
- if ( nb < 12 || nb%6 != 0 ) return false;
-
- while ( pos < 0.0f )
- {
- pos += 1000000.0f; // never negative!
- }
-
- for ( i=0 ; i<6 ; i++ )
- {
- for ( j=0 ; j<6 ; j++ )
- {
- if ( pv[i].x == pv[j+6].x &&
- pv[i].y == pv[j+6].y )
- {
- current.x = pv[i].x; // position end link
- current.y = pv[i].y;
- break;
- }
- }
- }
-
- ps = 0.0f; // start position on the periphery
- for ( l6=0 ; l6<nb/6 ; l6++ )
- {
- s = e = 0;
- for ( i=0 ; i<6 ; i++ )
- {
- if ( fabs(pv[i].x-current.x) < 0.0001f &&
- fabs(pv[i].y-current.y) < 0.0001f )
- {
- ie[e++] = i;
- }
- else
- {
- is[s++] = i;
- }
- }
- if ( s == 3 && e == 3 )
- {
- pe = ps+Math::Point(pv[is[0]].x-pv[ie[0]].x,
- pv[is[0]].y-pv[ie[0]].y).Length() / factor; // end position on the periphery
-
- pps = ps+pos;
- ppe = pe+pos;
- offset = (float)((int)pps);
- pps -= offset;
- ppe -= offset;
-
- for ( i=0 ; i<3 ; i++ )
- {
- pv[is[i]].tu = ((pps*tl)+ts)/tt;
- pv[ie[i]].tu = ((ppe*tl)+ts)/tt;
- }
- }
-
- if ( l6 >= (nb/6)-1 ) break;
- for ( i=0 ; i<6 ; i++ )
- {
- if ( fabs(pv[i+6].x-current.x) > 0.0001f ||
- fabs(pv[i+6].y-current.y) > 0.0001f )
- {
- current.x = pv[i+6].x; // end next link
- current.y = pv[i+6].y;
- break;
- }
- }
- ps = pe; // following start position on the periphery
- pv += 6;
- }
-
- return true;
-}
-
-
-// Updates all the geometric parameters of objects.
-
-void CD3DEngine::UpdateGeometry()
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- int l1, l2, l3, l4, l5, objRank, i;
-
- if ( !m_bUpdateGeometry ) return;
-
- for ( i=0 ; i<m_objectParamTotal ; i++ )
- {
- m_objectParam[i].bboxMin.x = 0;
- m_objectParam[i].bboxMin.y = 0;
- m_objectParam[i].bboxMin.z = 0;
- m_objectParam[i].bboxMax.x = 0;
- m_objectParam[i].bboxMax.y = 0;
- m_objectParam[i].bboxMax.z = 0;
- m_objectParam[i].radius = 0;
- }
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- objRank = p3->objRank;
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
-
- for ( i=0 ; i<p6->totalUsed ; i++ )
- {
- m_objectParam[objRank].bboxMin.x = Math::Min(p6->vertex[i].x, m_objectParam[objRank].bboxMin.x);
- m_objectParam[objRank].bboxMin.y = Math::Min(p6->vertex[i].y, m_objectParam[objRank].bboxMin.y);
- m_objectParam[objRank].bboxMin.z = Math::Min(p6->vertex[i].z, m_objectParam[objRank].bboxMin.z);
- m_objectParam[objRank].bboxMax.x = Math::Max(p6->vertex[i].x, m_objectParam[objRank].bboxMax.x);
- m_objectParam[objRank].bboxMax.y = Math::Max(p6->vertex[i].y, m_objectParam[objRank].bboxMax.y);
- m_objectParam[objRank].bboxMax.z = Math::Max(p6->vertex[i].z, m_objectParam[objRank].bboxMax.z);
- }
-
- m_objectParam[objRank].radius = Math::Max(m_objectParam[objRank].bboxMin.Length(),
- m_objectParam[objRank].bboxMax.Length());
- }
- }
- }
- }
- }
-
- m_bUpdateGeometry = false;
-}
-
-
-// Determines whether an object is visible, even partially.
-// Transformation of "world" must be done​​!
-
-bool CD3DEngine::IsVisible(int objRank)
-{
- Math::Vector center;
- DWORD flags;
- float radius;
-
- radius = m_objectParam[objRank].radius;
- center = Math::Vector(0.0f, 0.0f, 0.0f);
- {
- D3DVECTOR centerD3D = VEC_TO_D3DVEC(center);
- m_pD3DDevice->ComputeSphereVisibility(&centerD3D, &radius, 1, 0, &flags);
- }
-
- if ( flags & D3DSTATUS_CLIPINTERSECTIONALL )
- {
- m_objectParam[objRank].bVisible = false;
- return false;
- }
- m_objectParam[objRank].bVisible = true;
- return true;
-}
-
-
-// Detects the target object with the mouse.
-// Returns the rank of the object or -1.
-
-int CD3DEngine::DetectObject(Math::Point mouse)
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- D3DVERTEX2* pv;
- int l1, l2, l3, l4, l5, i, objRank, nearest;
- float dist, min;
-
- min = 1000000.0f;
- nearest = -1;
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- objRank = p3->objRank;
- if ( m_objectParam[objRank].type == TYPETERRAIN ) continue;
- if ( !DetectBBox(objRank, mouse) ) continue;
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( p4->min != 0.0f ) continue; // LOD B or C?
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
-
- if ( p6->type == D3DTYPE6T )
- {
- pv = &p6->vertex[0];
- for ( i=0 ; i<p6->totalUsed/3 ; i++ )
- {
- if ( DetectTriangle(mouse, pv, objRank, dist) &&
- dist < min )
- {
- min = dist;
- nearest = objRank;
- }
- pv += 3;
- }
- }
- if ( p6->type == D3DTYPE6S )
- {
- pv = &p6->vertex[0];
- for ( i=0 ; i<p6->totalUsed-2 ; i++ )
- {
- if ( DetectTriangle(mouse, pv, objRank, dist) &&
- dist < min )
- {
- min = dist;
- nearest = objRank;
- }
- pv += 1;
- }
- }
- }
- }
- }
- }
- }
- return nearest;
-}
-
-// Detects whether the mouse is in a triangle.
-
-bool CD3DEngine::DetectTriangle(Math::Point mouse, D3DVERTEX2 *triangle,
- int objRank, float &dist)
-{
- Math::Vector p2D[3], p3D;
- Math::Point a, b, c;
- int i;
-
- for ( i=0 ; i<3 ; i++ )
- {
- p3D.x = triangle[i].x;
- p3D.y = triangle[i].y;
- p3D.z = triangle[i].z;
- if ( !TransformPoint(p2D[i], objRank, p3D) ) return false;
- }
-
- if ( mouse.x < p2D[0].x &&
- mouse.x < p2D[1].x &&
- mouse.x < p2D[2].x ) return false;
- if ( mouse.x > p2D[0].x &&
- mouse.x > p2D[1].x &&
- mouse.x > p2D[2].x ) return false;
- if ( mouse.y < p2D[0].y &&
- mouse.y < p2D[1].y &&
- mouse.y < p2D[2].y ) return false;
- if ( mouse.y > p2D[0].y &&
- mouse.y > p2D[1].y &&
- mouse.y > p2D[2].y ) return false;
-
- a.x = p2D[0].x;
- a.y = p2D[0].y;
- b.x = p2D[1].x;
- b.y = p2D[1].y;
- c.x = p2D[2].x;
- c.y = p2D[2].y;
- if ( !Math::IsInsideTriangle(a, b, c, mouse) ) return false;
-
- dist = (p2D[0].z+p2D[1].z+p2D[2].z)/3.0f;
- return true;
-}
-
-// Detects whether an object is affected by the mouse.
-
-bool CD3DEngine::DetectBBox(int objRank, Math::Point mouse)
-{
- Math::Vector p, pp;
- Math::Point min, max;
- int i;
-
- min.x = 1000000.0f;
- min.y = 1000000.0f;
- max.x = -1000000.0f;
- max.y = -1000000.0f;
-
- for ( i=0 ; i<8 ; i++ )
- {
- if ( i & (1<<0) ) p.x = m_objectParam[objRank].bboxMin.x;
- else p.x = m_objectParam[objRank].bboxMax.x;
- if ( i & (1<<1) ) p.y = m_objectParam[objRank].bboxMin.y;
- else p.y = m_objectParam[objRank].bboxMax.y;
- if ( i & (1<<2) ) p.z = m_objectParam[objRank].bboxMin.z;
- else p.z = m_objectParam[objRank].bboxMax.z;
- if ( TransformPoint(pp, objRank, p) )
- {
- if ( pp.x < min.x ) min.x = pp.x;
- if ( pp.x > max.x ) max.x = pp.x;
- if ( pp.y < min.y ) min.y = pp.y;
- if ( pp.y > max.y ) max.y = pp.y;
- }
- }
-
- return ( mouse.x >= min.x &&
- mouse.x <= max.x &&
- mouse.y >= min.y &&
- mouse.y <= max.y );
-}
-
-// Transforms a 3D point (x, y, z) in 2D space (x, y, -) of the window.
-// The coordinated p2D.z gives the distance.
-
-bool CD3DEngine::TransformPoint(Math::Vector &p2D, int objRank, Math::Vector p3D)
-{
- p3D = Math::Transform(m_objectParam[objRank].transform, p3D);
- p3D = Math::Transform(m_matView, p3D);
-
- if ( p3D.z < 2.0f ) return false; // behind?
-
- p2D.x = (p3D.x/p3D.z)*m_matProj.Get(1,1);
- p2D.y = (p3D.y/p3D.z)*m_matProj.Get(2,2);
- p2D.z = p3D.z;
-
- p2D.x = (p2D.x+1.0f)/2.0f; // [-1..1] -> [0..1]
- p2D.y = (p2D.y+1.0f)/2.0f;
-
- return true;
-}
-
-
-// Calculating the distances between the viewpoint and the origin
-// of different objects.
-
-void CD3DEngine::ComputeDistance()
-{
- Math::Vector v;
- int i;
- float distance;
-
- if ( s_resol == 0 )
- {
- for ( i=0 ; i<m_objectParamTotal ; i++ )
- {
- if ( m_objectParam[i].bUsed == false ) continue;
-
- v.x = m_eyePt.x - m_objectParam[i].transform.Get(1,4);
- v.y = m_eyePt.y - m_objectParam[i].transform.Get(2,4);
- v.z = m_eyePt.z - m_objectParam[i].transform.Get(3,4);
- m_objectParam[i].distance = v.Length();
- }
- }
- else
- {
- if ( s_resol == 1 )
- {
- distance = 100000.0f;
- }
- if ( s_resol == 2 )
- {
- distance = (RetLimitLOD(0)+RetLimitLOD(1))/2.0f;
- }
- if ( s_resol == 3 )
- {
- distance = 0.0f;
- }
-
- for ( i=0 ; i<m_objectParamTotal ; i++ )
- {
- if ( m_objectParam[i].bUsed == false ) continue;
-
- if ( m_objectParam[i].type == TYPETERRAIN )
- {
- v.x = m_eyePt.x - m_objectParam[i].transform.Get(1,4);
- v.y = m_eyePt.y - m_objectParam[i].transform.Get(2,4);
- v.z = m_eyePt.z - m_objectParam[i].transform.Get(3,4);
- m_objectParam[i].distance = v.Length();
- }
- else
- {
- m_objectParam[i].distance = distance;
- }
- }
- }
-}
-
-
-// Adjusts settings when first run.
-
-void CD3DEngine::FirstExecuteAdapt(bool bFirst)
-{
- if ( m_app->IsVideo8MB() )
- {
- SetGroundSpot(false);
- SetSkyMode(false);
- }
-
- if ( m_app->IsVideo32MB() && bFirst )
- {
- SetObjectDetail(2.0f);
- }
-}
-
-// Returns the total amount of video memory for textures.
-
-int CD3DEngine::GetVidMemTotal()
-{
- return m_app->GetVidMemTotal();
-}
-
-bool CD3DEngine::IsVideo8MB()
-{
- return m_app->IsVideo8MB();
-}
-
-bool CD3DEngine::IsVideo32MB()
-{
- return m_app->IsVideo32MB();
-}
-
-
-// Perform the list of all graphics devices available.
-
-bool CD3DEngine::EnumDevices(char *bufDevices, int lenDevices,
- char *bufModes, int lenModes,
- int &totalDevices, int &selectDevices,
- int &totalModes, int &selectModes)
-{
- return m_app->EnumDevices(bufDevices, lenDevices,
- bufModes, lenModes,
- totalDevices, selectDevices,
- totalModes, selectModes);
-}
-
-bool CD3DEngine::RetFullScreen()
-{
- return m_app->RetFullScreen();
-}
-
-bool CD3DEngine::ChangeDevice(char *device, char *mode, bool bFull)
-{
- return m_app->ChangeDevice(device, mode, bFull);
-}
-
-
-
-Math::Matrix* CD3DEngine::RetMatView()
-{
- return &m_matView;
-}
-
-Math::Matrix* CD3DEngine::RetMatLeftView()
-{
- return &m_matLeftView;
-}
-
-Math::Matrix* CD3DEngine::RetMatRightView()
-{
- return &m_matRightView;
-}
-
-
-// Specifies the location and direction of view.
-
-void CD3DEngine::SetViewParams(const Math::Vector &vEyePt,
- const Math::Vector &vLookatPt,
- const Math::Vector &vUpVec,
- FLOAT fEyeDistance)
-{
-#if 0
- m_eyePt = vEyePt;
-
- // Adjust camera position for left or right eye along the axis
- // perpendicular to the view direction vector and the up vector.
- Math::Vector vView = (vLookatPt) - (vEyePt);
- vView = CrossProduct( vView, (vUpVec) );
- vView = Normalize( vView ) * fEyeDistance;
-
- Math::Vector vLeftEyePt = (vEyePt) + vView;
- Math::Vector vRightEyePt = (vEyePt) - vView;
-
- // Set the view matrices
- Math::LoadViewMatrix( m_matLeftView, (Math::Vector)vLeftEyePt, (Math::Vector)vLookatPt, (Math::Vector)vUpVec );
- Math::LoadViewMatrix( m_matRightView, (Math::Vector)vRightEyePt, (Math::Vector)vLookatPt, (Math::Vector)vUpVec );
- Math::LoadViewMatrix( m_matView, (Math::Vector)vEyePt, (Math::Vector)vLookatPt, (Math::Vector)vUpVec );
-#else
- m_eyePt = vEyePt;
- m_lookatPt = vLookatPt;
- m_eyeDirH = Math::RotateAngle(vEyePt.x-vLookatPt.x, vEyePt.z-vLookatPt.z);
- m_eyeDirV = Math::RotateAngle(Math::DistanceProjected(vEyePt, vLookatPt), vEyePt.y-vLookatPt.y);
-
- Math::LoadViewMatrix(m_matView, vEyePt, vLookatPt, vUpVec);
-
- if ( m_sound == 0 )
- {
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- }
- m_sound->SetListener(vEyePt, vLookatPt);
-#endif
-}
-
-
-// Specifies the transformation matrix of an object.
-
-bool CD3DEngine::SetObjectTransform(int objRank, const Math::Matrix &transform)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- m_objectParam[objRank].transform = transform;
- return true;
-}
-
-// Gives the transformation matrix of an object.
-
-bool CD3DEngine::GetObjectTransform(int objRank, Math::Matrix &transform)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- transform = m_objectParam[objRank].transform;
- return true;
-}
-
-// Specifies the type of an object.
-
-bool CD3DEngine::SetObjectType(int objRank, D3DTypeObj type)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- m_objectParam[objRank].type = type;
- return true;
-}
-
-// Returns the type of an object.
-
-D3DTypeObj CD3DEngine::RetObjectType(int objRank)
-{
- return m_objectParam[objRank].type;
-}
-
-// Specifies the transparency of an object.
-
-bool CD3DEngine::SetObjectTransparency(int objRank, float value)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- m_objectParam[objRank].transparency = value;
- return true;
-}
-
-
-// Allocates a table for shade, if necessary.
-
-bool CD3DEngine::ShadowCreate(int objRank)
-{
- int i;
-
- // Already allocated?
- if ( m_objectParam[objRank].shadowRank != -1 ) return true;
-
- for ( i=0 ; i<D3DMAXSHADOW ; i++ )
- {
- if ( m_shadow[i].bUsed == false ) // Free?
- {
- ZeroMemory(&m_shadow[i], sizeof(D3DShadow));
-
- m_shadow[i].bUsed = true;
- m_shadow[i].objRank = objRank;
- m_shadow[i].height = 0.0f;
-
- m_objectParam[objRank].shadowRank = i;
-
- if ( m_shadowTotal < i+1 )
- {
- m_shadowTotal = i+1;
- }
- return true;
- }
- }
- return false; // not found
-}
-
-// Removes the shadow associated with an object.
-
-void CD3DEngine::ShadowDelete(int objRank)
-{
- int i;
-
- if ( objRank == -1 ) return;
-
- i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return;
-
- m_shadow[i].bUsed = false;
- m_shadow[i].objRank = -1;
- m_shadow[i].pos = Math::Vector(0.0f, 0.0f, 0.0f);
- m_shadow[i].type = D3DSHADOWNORM;
-
- m_objectParam[objRank].shadowRank = -1;
-
- m_shadowTotal = 0;
- for ( i=0 ; i<D3DMAXSHADOW ; i++ )
- {
- if ( m_shadow[i].bUsed ) m_shadowTotal = i+1;
- }
-}
-
-// Specifies if the shadow is visible.
-// For example, when an object is carried, he has no shadow.
-
-bool CD3DEngine::SetObjectShadowHide(int objRank, bool bHide)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- m_shadow[i].bHide = bHide;
- return true;
-}
-
-// Specifies the type of the shadow of the object.
-
-bool CD3DEngine::SetObjectShadowType(int objRank, D3DShadowType type)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- m_shadow[i].type = type;
- return true;
-}
-
-// Specifies the position of the shadow of the object.
-
-bool CD3DEngine::SetObjectShadowPos(int objRank, const Math::Vector &pos)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- m_shadow[i].pos = pos;
- return true;
-}
-
-// Specifies the normal shadow to the field of the object.
-
-bool CD3DEngine::SetObjectShadowNormal(int objRank, const Math::Vector &n)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- m_shadow[i].normal = n;
- return true;
-}
-
-// Specifies the angle of the shadow of the object.
-
-bool CD3DEngine::SetObjectShadowAngle(int objRank, float angle)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- m_shadow[i].angle = angle;
- return true;
-}
-
-// Specifies the radius of the shadow of the object.
-
-bool CD3DEngine::SetObjectShadowRadius(int objRank, float radius)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- m_shadow[i].radius = radius;
- return true;
-}
-
-// Returns the radius of the shadow of the object.
-
-float CD3DEngine::RetObjectShadowRadius(int objRank)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return 0.0f;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- return m_shadow[i].radius;
-}
-
-// Specifies the intensity of the shadow of the object.
-
-bool CD3DEngine::SetObjectShadowIntensity(int objRank, float intensity)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- m_shadow[i].intensity = intensity;
- return true;
-}
-
-// Specifies the height of the shadow of the object.
-
-bool CD3DEngine::SetObjectShadowHeight(int objRank, float h)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- m_shadow[i].height = h;
- return true;
-}
-
-
-// Clears all marks on the ground.
-
-void CD3DEngine::GroundSpotFlush()
-{
- LPDIRECTDRAWSURFACE7 surface;
- DDSURFACEDESC2 ddsd;
- WORD* pbSurf;
- char texName[20];
- int s, y;
-
- ZeroMemory(m_groundSpot, sizeof(D3DGroundSpot)*D3DMAXGROUNDSPOT);
- m_bFirstGroundSpot = true; // drawing power first
-
- for ( s=0 ; s<16 ; s++ )
- {
- sprintf(texName, "shadow%.2d.tga", s);
- surface = D3DTextr_GetSurface(texName);
- if ( surface == 0 ) continue;
-
- ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
- ddsd.dwSize = sizeof(DDSURFACEDESC2);
- if ( surface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK ) continue;
-
- if ( ddsd.ddpfPixelFormat.dwRGBBitCount != 16 ) continue;
-
- for ( y=0 ; y<(int)ddsd.dwHeight ; y++ )
- {
- pbSurf = (WORD*)ddsd.lpSurface;
- pbSurf += ddsd.lPitch*y/2;
- memset(pbSurf, -1, ddsd.lPitch); // all blank
- }
-
- surface->Unlock(NULL);
- }
-}
-
-// Allocates a table for a mark on the ground, if necessary.
-
-int CD3DEngine::GroundSpotCreate()
-{
- int i;
-
- for ( i=0 ; i<D3DMAXGROUNDSPOT ; i++ )
- {
- if ( m_groundSpot[i].bUsed == false ) // free?
- {
- ZeroMemory(&m_groundSpot[i], sizeof(D3DGroundSpot));
- m_groundSpot[i].bUsed = true;
- m_groundSpot[i].smooth = 1.0f;
- return i;
- }
- }
- return -1; // not found
-}
-
-// Removes a mark on the ground.
-
-void CD3DEngine::GroundSpotDelete(int rank)
-{
- m_groundSpot[rank].bUsed = false;
- m_groundSpot[rank].pos = Math::Vector(0.0f, 0.0f, 0.0f);
-}
-
-// Specifies the position of surface marking of the object.
-
-bool CD3DEngine::SetObjectGroundSpotPos(int rank, const Math::Vector &pos)
-{
- m_groundSpot[rank].pos = pos;
- return true;
-}
-
-// Specifies the radius of surface marking of the object.
-
-bool CD3DEngine::SetObjectGroundSpotRadius(int rank, float radius)
-{
- m_groundSpot[rank].radius = radius;
- return true;
-}
-
-// Specifies the color of a mark on the ground.
-
-bool CD3DEngine::SetObjectGroundSpotColor(int rank, D3DCOLORVALUE color)
-{
- m_groundSpot[rank].color = color;
- return true;
-}
-
-// Specifies the height min / max.
-
-bool CD3DEngine::SetObjectGroundSpotMinMax(int rank, float min, float max)
-{
- m_groundSpot[rank].min = min;
- m_groundSpot[rank].max = max;
- return true;
-}
-
-// Specifies the transition factor.
-
-bool CD3DEngine::SetObjectGroundSpotSmooth(int rank, float smooth)
-{
- m_groundSpot[rank].smooth = smooth;
- return true;
-}
-
-
-// Creates ground marks.
-
-int CD3DEngine::GroundMarkCreate(Math::Vector pos, float radius,
- float delay1, float delay2, float delay3,
- int dx, int dy, char* table)
-{
- ZeroMemory(&m_groundMark, sizeof(D3DGroundMark));
- m_groundMark.bUsed = true;
- m_groundMark.phase = 1;
- m_groundMark.delay[0] = delay1;
- m_groundMark.delay[1] = delay2;
- m_groundMark.delay[2] = delay3;
- m_groundMark.pos = pos;
- m_groundMark.radius = radius;
- m_groundMark.intensity = 0.0f;
- m_groundMark.dx = dx;
- m_groundMark.dy = dy;
- m_groundMark.table = table;
- return 0;
-}
-
-// Clears the ground.
-
-bool CD3DEngine::GroundMarkDelete(int rank)
-{
- ZeroMemory(&m_groundMark, sizeof(D3DGroundMark));
- return true;
-}
-
-
-// Border management (distance limits) depends of the resolution.
-// LOD = level-of-detail.
-
-void CD3DEngine::SetLimitLOD(int rank, float limit)
-{
- m_limitLOD[rank] = limit;
-}
-
-float CD3DEngine::RetLimitLOD(int rank, bool bLast)
-{
- float limit;
-
- if ( bLast )
- {
- limit = m_limitLOD[rank];
- limit *= m_lastDim.x/640.0f; // limit further if large window!
-//? limit += m_limitLOD[0]*(m_lastObjectDetail*2.0f-1.0f);
- limit += m_limitLOD[0]*(m_lastObjectDetail*2.0f);
- }
- else
- {
- limit = m_limitLOD[rank];
- limit *= m_dim.x/640.0f; // limit further if large window!
-//? limit += m_limitLOD[0]*(m_objectDetail*2.0f-1.0f);
- limit += m_limitLOD[0]*(m_objectDetail*2.0f);
- }
- if ( limit < 0.0f ) limit = 0.0f;
-
- return limit;
-}
-
-
-// Definition of the distance field of vision.
-
-void CD3DEngine::SetTerrainVision(float vision)
-{
- m_terrainVision = vision;
-}
-
-
-// Management of the global mode of shading.
-
-void CD3DEngine::SetShadow(bool bMode)
-{
- m_bShadow = bMode;
-}
-
-bool CD3DEngine::RetShadow()
-{
- return m_bShadow;
-}
-
-
-// Management of the global mode of marking.
-
-void CD3DEngine::SetGroundSpot(bool bMode)
-{
- m_bGroundSpot = bMode;
-}
-
-bool CD3DEngine::RetGroundSpot()
-{
- return m_bGroundSpot;
-}
-
-
-// Management of the global mode of contamination.
-
-void CD3DEngine::SetDirty(bool bMode)
-{
- m_bDirty = bMode;
-}
-
-bool CD3DEngine::RetDirty()
-{
- return m_bDirty;
-}
-
-
-// Management of the global mode of horizontal fog patches.
-
-void CD3DEngine::SetFog(bool bMode)
-{
- m_bFog = bMode;
-}
-
-bool CD3DEngine::RetFog()
-{
- return m_bFog;
-}
-
-
-// ndicates whether it is possible to give a color SetState.
-
-bool CD3DEngine::RetStateColor()
-{
- return m_bStateColor;
-}
-
-
-// Management of the global mode of secondary texturing.
-
-void CD3DEngine::SetSecondTexture(int texNum)
-{
- m_secondTexNum = texNum;
-}
-
-int CD3DEngine::RetSecondTexture()
-{
- return m_secondTexNum;
-}
-
-
-// Choice of the rank of the active view.
-
-void CD3DEngine::SetRankView(int rank)
-{
- if ( rank < 0 ) rank = 0;
- if ( rank > 1 ) rank = 1;
-
- if ( m_rankView == 0 && rank == 1 ) // enters the water?
- {
- m_light->AdaptLightColor(m_waterAddColor, +1.0f);
- }
-
- if ( m_rankView == 1 && rank == 0 ) // out of the water?
- {
- m_light->AdaptLightColor(m_waterAddColor, -1.0f);
- }
-
- m_rankView = rank;
-}
-
-int CD3DEngine::RetRankView()
-{
- return m_rankView;
-}
-
-// Whether to draw the world from the interface.
-
-void CD3DEngine::SetDrawWorld(bool bDraw)
-{
- m_bDrawWorld = bDraw;
-}
-
-// Whether to draw the world on the interface.
-
-void CD3DEngine::SetDrawFront(bool bDraw)
-{
- m_bDrawFront = bDraw;
-}
-
-// Color management ambient.
-// color = 0x00rrggbb
-// rr: red
-// gg: green
-// bb: blue
-
-void CD3DEngine::SetAmbiantColor(D3DCOLOR color, int rank)
-{
- m_ambiantColor[rank] = color;
-}
-
-D3DCOLOR CD3DEngine::RetAmbiantColor(int rank)
-{
- return m_ambiantColor[rank];
-}
-
-
-// Color management under water.
-
-void CD3DEngine::SetWaterAddColor(D3DCOLORVALUE color)
-{
- m_waterAddColor = color;
-}
-
-D3DCOLORVALUE CD3DEngine::RetWaterAddColor()
-{
- return m_waterAddColor;
-}
-
-
-// Management of the fog color.
-
-void CD3DEngine::SetFogColor(D3DCOLOR color, int rank)
-{
- m_fogColor[rank] = color;
-}
-
-D3DCOLOR CD3DEngine::RetFogColor(int rank)
-{
- return m_fogColor[rank];
-}
-
-
-// Management of the depth of field.
-// Beyond this distance, nothing is visible.
-// Shortly (according SetFogStart), one enters the fog.
-
-void CD3DEngine::SetDeepView(float length, int rank, bool bRef)
-{
- if ( bRef )
- {
- length *= m_clippingDistance;
- }
-
- m_deepView[rank] = length;
-}
-
-float CD3DEngine::RetDeepView(int rank)
-{
- return m_deepView[rank];
-}
-
-
-// Management the start of fog.
-// With 0.0, the fog from the point of view (fog max).
-// With 1.0, the fog from the depth of field (no fog).
-
-void CD3DEngine::SetFogStart(float start, int rank)
-{
- m_fogStart[rank] = start;
-}
-
-float CD3DEngine::RetFogStart(int rank)
-{
- return m_fogStart[rank];
-}
-
-
-// Gives the background image to use.
-
-void CD3DEngine::SetBackground(char *name, D3DCOLOR up, D3DCOLOR down,
- D3DCOLOR cloudUp, D3DCOLOR cloudDown,
- bool bFull, bool bQuarter)
-{
- strcpy(m_backgroundName, name);
- m_backgroundColorUp = up;
- m_backgroundColorDown = down;
- m_backgroundCloudUp = cloudUp;
- m_backgroundCloudDown = cloudDown;
- m_bBackgroundFull = bFull;
- m_bBackgroundQuarter = bQuarter;
-}
-
-// Gives the background image used.
-
-void CD3DEngine::RetBackground(char *name, D3DCOLOR &up, D3DCOLOR &down,
- D3DCOLOR &cloudUp, D3DCOLOR &cloudDown,
- bool &bFull, bool &bQuarter)
-{
- strcpy(name, m_backgroundName);
- up = m_backgroundColorUp;
- down = m_backgroundColorDown;
- cloudUp = m_backgroundCloudUp;
- cloudDown = m_backgroundCloudDown;
- bFull = m_bBackgroundFull;
- bQuarter = m_bBackgroundQuarter;
-}
-
-// Gives the foreground image to use.
-
-void CD3DEngine::SetFrontsizeName(char *name)
-{
- if ( m_frontsizeName[0] != 0 )
- {
- FreeTexture(m_frontsizeName);
- }
-
- strcpy(m_frontsizeName, name);
-}
-
-// Specifies whether to draw the foreground.
-
-void CD3DEngine::SetOverFront(bool bFront)
-{
- m_bOverFront = bFront;
-}
-
-// Gives color to the foreground.
-
-void CD3DEngine::SetOverColor(D3DCOLOR color, int mode)
-{
- m_overColor = color;
- m_overMode = mode;
-}
-
-
-
-// Management of the particle density.
-
-void CD3DEngine::SetParticuleDensity(float value)
-{
- if ( value < 0.0f ) value = 0.0f;
- if ( value > 2.0f ) value = 2.0f;
- m_particuleDensity = value;
-}
-
-float CD3DEngine::RetParticuleDensity()
-{
- return m_particuleDensity;
-}
-
-float CD3DEngine::ParticuleAdapt(float factor)
-{
- if ( m_particuleDensity == 0.0f )
- {
- return 1000000.0f;
- }
- return factor/m_particuleDensity;
-}
-
-// Management of the distance of clipping.
-
-void CD3DEngine::SetClippingDistance(float value)
-{
- if ( value < 0.5f ) value = 0.5f;
- if ( value > 2.0f ) value = 2.0f;
- m_clippingDistance = value;
-}
-
-float CD3DEngine::RetClippingDistance()
-{
- return m_clippingDistance;
-}
-
-// Management of objects detals.
-
-void CD3DEngine::SetObjectDetail(float value)
-{
- if ( value < 0.0f ) value = 0.0f;
- if ( value > 2.0f ) value = 2.0f;
- m_objectDetail = value;
-}
-
-float CD3DEngine::RetObjectDetail()
-{
- return m_objectDetail;
-}
-
-// The amount of management objects gadgets.
-
-void CD3DEngine::SetGadgetQuantity(float value)
-{
- if ( value < 0.0f ) value = 0.0f;
- if ( value > 1.0f ) value = 1.0f;
-
- m_gadgetQuantity = value;
-}
-
-float CD3DEngine::RetGadgetQuantity()
-{
- return m_gadgetQuantity;
-}
-
-// Managing the quality of textures.
-
-void CD3DEngine::SetTextureQuality(int value)
-{
- if ( value < 0 ) value = 0;
- if ( value > 2 ) value = 2;
-
- if ( value != m_textureQuality )
- {
- m_textureQuality = value;
- LoadAllTexture();
- }
-}
-
-int CD3DEngine::RetTextureQuality()
-{
- return m_textureQuality;
-}
-
-
-// Management mode of toto.
-
-void CD3DEngine::SetTotoMode(bool bPresent)
-{
- m_bTotoMode = bPresent;
-}
-
-bool CD3DEngine::RetTotoMode()
-{
- return m_bTotoMode;
-}
-
-
-// Managing the mode of foreground.
-
-void CD3DEngine::SetLensMode(bool bPresent)
-{
- m_bLensMode = bPresent;
-}
-
-bool CD3DEngine::RetLensMode()
-{
- return m_bLensMode;
-}
-
-
-// Managing the mode of water.
-
-void CD3DEngine::SetWaterMode(bool bPresent)
-{
- m_bWaterMode = bPresent;
-}
-
-bool CD3DEngine::RetWaterMode()
-{
- return m_bWaterMode;
-}
-
-
-// Managing the mode of sky.
-
-void CD3DEngine::SetSkyMode(bool bPresent)
-{
- m_bSkyMode = bPresent;
-}
-
-bool CD3DEngine::RetSkyMode()
-{
- return m_bSkyMode;
-}
-
-
-// Managing the mode of background.
-
-void CD3DEngine::SetBackForce(bool bPresent)
-{
- m_bBackForce = bPresent;
-}
-
-bool CD3DEngine::RetBackForce()
-{
- return m_bBackForce;
-}
-
-
-// Managing the mode of planets.
-
-void CD3DEngine::SetPlanetMode(bool bPresent)
-{
- m_bPlanetMode = bPresent;
-}
-
-bool CD3DEngine::RetPlanetMode()
-{
- return m_bPlanetMode;
-}
-
-
-// Managing the mode of dymanic lights.
-
-void CD3DEngine::SetLightMode(bool bPresent)
-{
- m_bLightMode = bPresent;
-}
-
-bool CD3DEngine::RetLightMode()
-{
- return m_bLightMode;
-}
-
-
-// Management of the indentation mode while editing (CEdit).
-
-void CD3DEngine::SetEditIndentMode(bool bAuto)
-{
- m_bEditIndentMode = bAuto;
-}
-
-bool CD3DEngine::RetEditIndentMode()
-{
- return m_bEditIndentMode;
-}
-
-
-// Management in advance of a tab when editing (CEdit).
-
-void CD3DEngine::SetEditIndentValue(int value)
-{
- m_editIndentValue = value;
-}
-
-int CD3DEngine::RetEditIndentValue()
-{
- return m_editIndentValue;
-}
-
-
-void CD3DEngine::SetSpeed(float speed)
-{
- m_speed = speed;
-}
-
-float CD3DEngine::RetSpeed()
-{
- return m_speed;
-}
-
-
-void CD3DEngine::SetTracePrecision(float factor)
-{
- m_tracePrecision = factor;
-}
-
-float CD3DEngine::RetTracePrecision()
-{
- return m_tracePrecision;
-}
-
-
-// Updates the scene after a change of parameters.
-
-void CD3DEngine::ApplyChange()
-{
- m_deepView[0] /= m_lastClippingDistance;
- m_deepView[1] /= m_lastClippingDistance;
-
- SetFocus(m_focus);
- ChangeLOD();
-
- m_deepView[0] *= m_clippingDistance;
- m_deepView[1] *= m_clippingDistance;
-}
-
-
-
-// Returns the point of view of the user.
-
-Math::Vector CD3DEngine::RetEyePt()
-{
- return m_eyePt;
-}
-
-Math::Vector CD3DEngine::RetLookatPt()
-{
- return m_lookatPt;
-}
-
-float CD3DEngine::RetEyeDirH()
-{
- return m_eyeDirH;
-}
-
-float CD3DEngine::RetEyeDirV()
-{
- return m_eyeDirV;
-}
-
-POINT CD3DEngine::RetDim()
-{
- return m_dim;
-}
-
-
-// Generates an image name of the watch.
-
-void QuarterName(char *buffer, char *name, int quarter)
-{
- while ( *name != 0 )
- {
- if ( *name == '.' )
- {
- *buffer++ = 'a'+quarter;
- }
- *buffer++ = *name++;
- }
- *buffer++ = 0;
-}
-
-// Frees texture.
-
-bool CD3DEngine::FreeTexture(char* name)
-{
- if ( name[0] == 0 ) return true;
-
- if ( D3DTextr_DestroyTexture(name) != S_OK )
- {
- return false;
- }
- return true;
-}
-
-// Load a texture.
-
-bool CD3DEngine::LoadTexture(char* name, int stage)
-{
- DWORD mode;
-
- if ( name[0] == 0 ) return true;
-
- if ( D3DTextr_GetSurface(name) == NULL )
- {
- if ( strstr(name, ".tga") == 0 )
- {
- mode = 0;
- }
- else
- {
- mode = D3DTEXTR_CREATEWITHALPHA;
- }
-
- if ( D3DTextr_CreateTextureFromFile(name, stage, mode) != S_OK )
- {
- return false;
- }
-
- if ( D3DTextr_Restore(name, m_pD3DDevice) != S_OK )
- {
- return false;
- }
- }
- return true;
-}
-
-// Load all the textures of the scene.
-
-bool CD3DEngine::LoadAllTexture()
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- int l1, i;
- char name[50];
- bool bOK = true;
-
-#if _POLISH
- LoadTexture("textp.tga");
-#else
- LoadTexture("text.tga");
-#endif
- LoadTexture("mouse.tga");
- LoadTexture("button1.tga");
- LoadTexture("button2.tga");
- LoadTexture("button3.tga");
- LoadTexture("effect00.tga");
- LoadTexture("effect01.tga");
- LoadTexture("effect02.tga");
- LoadTexture("map.tga");
-
- if ( m_backgroundName[0] != 0 )
- {
- if ( m_bBackgroundQuarter ) // image into 4 pieces?
- {
- for ( i=0 ; i<4 ; i++ )
- {
- QuarterName(name, m_backgroundName, i);
- LoadTexture(name);
- }
- }
- else
- {
- LoadTexture(m_backgroundName);
- }
- }
- if ( m_frontsizeName[0] != 0 )
- {
- LoadTexture(m_frontsizeName);
- }
-
- m_planet->LoadTexture();
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
-
- if ( p2 == 0 || p2->texName1[0] != 0 )
- {
- if ( !LoadTexture(p2->texName1, 0) ) bOK = false;
- }
-
- if ( p2 == 0 || p2->texName2[0] != 0 )
- {
- if ( !LoadTexture(p2->texName2, 1) ) bOK = false;
- }
- }
- return bOK;
-}
-
-
-// Called during initial app startup, this function performs all the
-// permanent initialization.
-
-HRESULT CD3DEngine::OneTimeSceneInit()
-{
- return S_OK;
-}
-
-
-// Updated after creating objects.
-
-void CD3DEngine::Update()
-{
- ComputeDistance();
- UpdateGeometry();
-}
-
-// Called once per frame, the call is the entry point for animating
-// the scene.
-
-HRESULT CD3DEngine::FrameMove(float rTime)
-{
- m_light->FrameLight(rTime);
- m_particule->FrameParticule(rTime);
- ComputeDistance();
- UpdateGeometry();
-
- if ( m_groundMark.bUsed )
- {
- if ( m_groundMark.phase == 1 ) // growing?
- {
- m_groundMark.intensity += rTime*(1.0f/m_groundMark.delay[0]);
- if ( m_groundMark.intensity >= 1.0f )
- {
- m_groundMark.intensity = 1.0f;
- m_groundMark.fix = 0.0f;
- m_groundMark.phase = 2;
- }
- }
- else if ( m_groundMark.phase == 2 ) // fixed?
- {
- m_groundMark.fix += rTime*(1.0f/m_groundMark.delay[1]);
- if ( m_groundMark.fix >= 1.0f )
- {
- m_groundMark.phase = 3;
- }
- }
- else if ( m_groundMark.phase == 3 ) // decay?
- {
- m_groundMark.intensity -= rTime*(1.0f/m_groundMark.delay[2]);
- if ( m_groundMark.intensity < 0.0f )
- {
- m_groundMark.intensity = 0.0f;
- m_groundMark.phase = 0;
- m_groundMark.bUsed = false;
- }
- }
- }
-
- if ( m_sound == 0 )
- {
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- }
- m_sound->FrameMove(rTime);
-
- return S_OK;
-}
-
-// Evolved throughout the game
-
-void CD3DEngine::StepSimul(float rTime)
-{
- m_app->StepSimul(rTime);
-}
-
-
-
-// Changes the state associated with a material.
-// (*) Does not work without this instruction, mystery!
-
-void CD3DEngine::SetState(int state, D3DCOLOR color)
-{
- bool bSecond;
-
- if ( state == m_lastState &&
- color == m_lastColor ) return;
- m_lastState = state;
- m_lastColor = color;
-
- if ( m_alphaMode != 1 && (state & D3DSTATEALPHA) )
- {
- state &= ~D3DSTATEALPHA;
-
- if ( m_alphaMode == 2 )
- {
- state |= D3DSTATETTb;
- }
- }
-
- if ( state & D3DSTATETTb ) // The transparent black texture?
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_blackSrcBlend[1]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_blackDestBlend[1]);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, table_blend[debug_blend1]);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, table_blend[debug_blend2]);
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); // (*)
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- }
- else if ( state & D3DSTATETTw ) // The transparent white texture?
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_whiteSrcBlend[1]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_whiteDestBlend[1]);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, table_blend[debug_blend3]);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, table_blend[debug_blend4]);
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, ~color);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_ADD);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); // (*)
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- }
- else if ( state & D3DSTATETCb ) // The transparent black color?
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_blackSrcBlend[1]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_blackDestBlend[1]);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, table_blend[debug_blend1]);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, table_blend[debug_blend2]);
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- }
- else if ( state & D3DSTATETCw ) // The transparent white color?
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_whiteSrcBlend[1]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_whiteDestBlend[1]);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, table_blend[debug_blend3]);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, table_blend[debug_blend4]);
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, ~color);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- }
- else if ( state & D3DSTATETD ) // diffuse color as transparent?
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_diffuseSrcBlend[1]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_diffuseDestBlend[1]);
-
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- }
- else if ( state & D3DSTATEALPHA ) // image with alpha channel?
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, D3DCMP_GREATER);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAREF, (DWORD)(128));
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_alphaSrcBlend[1]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_alphaSrcBlend[1]);
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
- }
- else // normal ?
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
-
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- }
-
- if ( state & D3DSTATEFOG )
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
- }
-
- bSecond = m_bGroundSpot|m_bDirty;
- if ( !m_bGroundSpot && (state & D3DSTATESECOND) != 0 ) bSecond = false;
- if ( !m_bDirty && (state & D3DSTATESECOND) == 0 ) bSecond = false;
-
- if ( (state & D3DSTATEDUALb) && bSecond )
- {
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
- }
- else if ( (state & D3DSTATEDUALw) && bSecond )
- {
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
- }
- else
- {
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- }
-
- if ( state & D3DSTATEWRAP )
- {
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_WRAP0, D3DWRAP_U|D3DWRAP_V);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);
- }
- else if ( state & D3DSTATECLAMP )
- {
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_WRAP0, 0);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
- }
- else
- {
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_WRAP0, 0);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
- }
-
- if ( state & D3DSTATE2FACE )
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
- }
- else
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CCW);
- }
-
- if ( state & D3DSTATELIGHT )
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- }
- else
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, m_ambiantColor[m_rankView]);
- }
-}
-
-// Specifies a texture to use.
-
-void CD3DEngine::SetTexture(char *name, int stage)
-{
-//? if ( stage == 1 && !m_bDirty ) return;
-//? if ( stage == 1 && !m_bShadow ) return;
-
- if ( strcmp(name, m_lastTexture[stage]) == 0 ) return;
- strcpy(m_lastTexture[stage], name);
-
- m_pD3DDevice->SetTexture(stage, D3DTextr_GetSurface(name));
-}
-
-// Specifies the material to use.
-
-void CD3DEngine::SetMaterial(const D3DMATERIAL7 &mat)
-{
- if ( memcmp(&mat, &m_lastMaterial, sizeof(D3DMATERIAL7)) == 0 ) return;
- m_lastMaterial = mat;
-
- m_pD3DDevice->SetMaterial(&m_lastMaterial);
-}
-
-
-// Deletes a point in a surface (draw in white).
-
-inline void ClearDot(DDSURFACEDESC2* ddsd, int x, int y)
-{
- WORD* pbSurf;
-
- if ( ddsd->ddpfPixelFormat.dwRGBBitCount != 16 ) return;
-
- pbSurf = (WORD*)ddsd->lpSurface;
- pbSurf += ddsd->lPitch*y/2;
- pbSurf += x;
-
- *pbSurf = 0xffff; // white
-}
-
-// Deletes a point in a surface (draw in white)
-
-void AddDot(DDSURFACEDESC2* ddsd, int x, int y, D3DCOLORVALUE color)
-{
- WORD* pbSurf;
- WORD r,g,b, w;
-
- if ( ddsd->ddpfPixelFormat.dwRGBBitCount != 16 ) return;
-
- if ( color.r < 0.0f ) color.r = 0.0f;
- if ( color.r > 1.0f ) color.r = 1.0f;
- r = (int)(color.r*32.0f);
- if ( r >= 32 ) r = 31; // 5 bits
-
- if ( color.g < 0.0f ) color.g = 0.0f;
- if ( color.g > 1.0f ) color.g = 1.0f;
- g = (int)(color.g*32.0f);
- if ( g >= 32 ) g = 31; // 5 bits
-
- if ( color.b < 0.0f ) color.b = 0.0f;
- if ( color.b > 1.0f ) color.b = 1.0f;
- b = (int)(color.b*32.0f);
- if ( b >= 32 ) b = 31; // 5 bits
-
- if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xf800 ) // 565 ?
- {
- w = (r<<11)|(g<<6)|b;
- }
- else if ( ddsd->ddpfPixelFormat.dwRBitMask == 0x7c00 ) // 555 ?
- {
- w = (r<<10)|(g<<5)|b;
- }
- else
- {
- w = -1; // blank
- }
-
- pbSurf = (WORD*)ddsd->lpSurface;
- pbSurf += ddsd->lPitch*y/2;
- pbSurf += x;
-
- *pbSurf &= w;
-}
-
-// Displays a point in a surface.
-
-void SetDot(DDSURFACEDESC2* ddsd, int x, int y, D3DCOLORVALUE color)
-{
- if ( ddsd->ddpfPixelFormat.dwRGBBitCount == 16 )
- {
- WORD* pbSurf;
- WORD r,g,b, w;
-
- if ( color.r < 0.0f ) color.r = 0.0f;
- if ( color.r > 1.0f ) color.r = 1.0f;
- if ( color.g < 0.0f ) color.g = 0.0f;
- if ( color.g > 1.0f ) color.g = 1.0f;
- if ( color.b < 0.0f ) color.b = 0.0f;
- if ( color.b > 1.0f ) color.b = 1.0f;
-
- r = (int)(color.r*32.0f);
- g = (int)(color.g*32.0f);
- b = (int)(color.b*32.0f);
-
- if ( r >= 32 ) r = 31; // 5 bits
- if ( g >= 32 ) g = 31; // 5 bits
- if ( b >= 32 ) b = 31; // 5 bits
-
- if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xf800 ) // 565 ?
- {
- w = (r<<11)|(g<<6)|b;
- }
- else if ( ddsd->ddpfPixelFormat.dwRBitMask == 0x7c00 ) // 555 ?
- {
- w = (r<<10)|(g<<5)|b;
- }
- else
- {
- w = -1; // blank
- }
-
- pbSurf = (WORD*)ddsd->lpSurface;
- pbSurf += ddsd->lPitch*y/2;
- pbSurf += x;
-
- *pbSurf = w;
- }
-
- if ( ddsd->ddpfPixelFormat.dwRGBBitCount == 32 ) // image .tga ?
- {
- LONG* pbSurf;
- LONG r,g,b, w;
-
- if ( color.r < 0.0f ) color.r = 0.0f;
- if ( color.r > 1.0f ) color.r = 1.0f;
- if ( color.g < 0.0f ) color.g = 0.0f;
- if ( color.g > 1.0f ) color.g = 1.0f;
- if ( color.b < 0.0f ) color.b = 0.0f;
- if ( color.b > 1.0f ) color.b = 1.0f;
-
- r = (int)(color.r*256.0f);
- g = (int)(color.g*256.0f);
- b = (int)(color.b*256.0f);
-
- if ( r >= 256 ) r = 255; // 8 bits
- if ( g >= 256 ) g = 255; // 8 bits
- if ( b >= 256 ) b = 255; // 8 bits
-
- if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xff0000 )
- {
- w = (r<<16)|(g<<8)|b;
-
- pbSurf = (LONG*)ddsd->lpSurface;
- pbSurf += ddsd->lPitch*y/4;
- pbSurf += x;
-
- *pbSurf &= 0xff000000; // keeps alpha channel
- *pbSurf |= w;
- }
- }
-}
-
-// Gives a point in a surface.
-
-D3DCOLORVALUE GetDot(DDSURFACEDESC2* ddsd, int x, int y)
-{
- D3DCOLORVALUE color;
-
- if ( ddsd->ddpfPixelFormat.dwRGBBitCount == 16 )
- {
- WORD* pbSurf;
- WORD r,g,b, w;
-
- pbSurf = (WORD*)ddsd->lpSurface;
- pbSurf += ddsd->lPitch*y/2;
- pbSurf += x;
-
- w = *pbSurf;
-
- if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xf800 ) // 565 ?
- {
- r = (w>>10)&0x003e;
- g = (w>> 5)&0x003f;
- b = (w<< 1)&0x003e;
- }
- else if ( ddsd->ddpfPixelFormat.dwRBitMask == 0x7c00 ) // 555 ?
- {
- r = (w>> 9)&0x003e;
- g = (w>> 4)&0x003e;
- b = (w<< 1)&0x003e;
- }
- else
- {
- r = 0;
- g = 0;
- b = 0; // black
- }
-
- color.r = (float)r/63.0f;
- color.g = (float)g/63.0f;
- color.b = (float)b/63.0f;
- color.a = 0.0f;
- return color;
- }
-
- if ( ddsd->ddpfPixelFormat.dwRGBBitCount == 32 ) // image .tga ?
- {
- LONG* pbSurf;
- LONG r,g,b, w;
-
- pbSurf = (LONG*)ddsd->lpSurface;
- pbSurf += ddsd->lPitch*y/4;
- pbSurf += x;
-
- w = *pbSurf;
-
- if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xff0000 )
- {
- r = (w>>16)&0x00ff;
- g = (w>> 8)&0x00ff;
- b = (w<< 0)&0x00ff;
- }
- else
- {
- r = 0;
- g = 0;
- b = 0; // black
- }
-
- color.r = (float)r/255.0f;
- color.g = (float)g/255.0f;
- color.b = (float)b/255.0f;
- color.a = 0.0f;
- return color;
- }
-
- color.r = 0.0f;
- color.g = 0.0f;
- color.b = 0.0f;
- color.a = 0.0f; // black
- return color;
-}
-
-// Draw all the shadows.
-
-// There is a pixel collection around each of the 16 surfaces:
-//
-// |<----------------------->|<----------------------->|<---- ...
-// 0 | 1 2 253 254|255 |
-// |---|---|---|-- ... --|---|---|---| |
-// 0 | 1 2 253 254|255
-// |---|---|---|-- ... --|---|---|---|
-//
-// So we draw in 254x254 pixels surfaces.
-// The pixel margin around it is drawn twice (in two adjacent surfaces),
-// so that the filter produces the same results!
-
-void CD3DEngine::RenderGroundSpot()
-{
- LPDIRECTDRAWSURFACE7 surface;
- DDSURFACEDESC2 ddsd;
- WORD* pbSurf;
- D3DCOLORVALUE color;
- Math::Vector pos;
- Math::Point min, max;
- int s, i, j, dot, ix, iy, y;
- float tu, tv, cx, cy, px, py, ppx, ppy;
- float intensity, level;
- char texName[20];
- bool bClear, bSet;
-
- if ( !m_bFirstGroundSpot &&
- m_groundMark.drawPos.x == m_groundMark.pos.x &&
- m_groundMark.drawPos.z == m_groundMark.pos.z &&
- m_groundMark.drawRadius == m_groundMark.radius &&
- m_groundMark.drawIntensity == m_groundMark.intensity ) return;
-
- for ( s=0 ; s<16 ; s++ )
- {
- min.x = (s%4)*254.0f-1.0f; // 1 pixel cover
- min.y = (s/4)*254.0f-1.0f;
- max.x = min.x+254.0f+2.0f;
- max.y = min.y+254.0f+2.0f;
-
- bClear = false;
- bSet = false;
-
- // Calculate the area to be erased.
- dot = (int)(m_groundMark.drawRadius/2.0f);
-
- tu = (m_groundMark.drawPos.x+1600.0f)/3200.0f;
- tv = (m_groundMark.drawPos.z+1600.0f)/3200.0f; // 0..1
-
- cx = (tu*254.0f*4.0f)-0.5f;
- cy = (tv*254.0f*4.0f)-0.5f;
-
- if ( dot == 0 )
- {
- cx += 0.5f;
- cy += 0.5f;
- }
-
- px = cx-Math::Mod(cx, 1.0f);
- py = cy-Math::Mod(cy, 1.0f); // multiple of 1
-
- if ( m_bFirstGroundSpot ||
- ( m_groundMark.drawRadius != 0.0f &&
- px+dot >= min.x && py+dot >= min.y &&
- px-dot <= max.x && py-dot <= max.y ) )
- {
- bClear = true;
- }
-
- // Calculate the area to draw.
- dot = (int)(m_groundMark.radius/2.0f);
-
- tu = (m_groundMark.pos.x+1600.0f)/3200.0f;
- tv = (m_groundMark.pos.z+1600.0f)/3200.0f; // 0..1
-
- cx = (tu*254.0f*4.0f)-0.5f;
- cy = (tv*254.0f*4.0f)-0.5f;
-
- if ( dot == 0 )
- {
- cx += 0.5f;
- cy += 0.5f;
- }
-
- px = cx-Math::Mod(cx, 1.0f);
- py = cy-Math::Mod(cy, 1.0f); // multiple of 1
-
- if ( m_groundMark.bUsed &&
- px+dot >= min.x && py+dot >= min.y &&
- px-dot <= max.x && py-dot <= max.y )
- {
- bSet = true;
- }
-
- if ( bClear || bSet )
- {
- // Load the song.
- sprintf(texName, "shadow%.2d.tga", s);
- surface = D3DTextr_GetSurface(texName);
- if ( surface == 0 ) continue;
-
- ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
- ddsd.dwSize = sizeof(DDSURFACEDESC2);
- if ( surface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK ) continue;
-
- // Clears in blank whole piece.
- if ( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 )
- {
- for ( y=0 ; y<(int)ddsd.dwHeight ; y++ )
- {
- pbSurf = (WORD*)ddsd.lpSurface;
- pbSurf += ddsd.lPitch*y/2;
- memset(pbSurf, -1, ddsd.lPitch); // all blank
- }
- }
-
- // Draw the new shadows.
- for ( i=0 ; i<D3DMAXGROUNDSPOT ; i++ )
- {
- if ( m_groundSpot[i].bUsed == false ||
- m_groundSpot[i].radius == 0.0f ) continue;
-
- if ( m_groundSpot[i].min == 0.0f &&
- m_groundSpot[i].max == 0.0f )
- {
- dot = (int)(m_groundSpot[i].radius/2.0f);
-
- tu = (m_groundSpot[i].pos.x+1600.0f)/3200.0f;
- tv = (m_groundSpot[i].pos.z+1600.0f)/3200.0f; // 0..1
-
- cx = (tu*254.0f*4.0f)-0.5f;
- cy = (tv*254.0f*4.0f)-0.5f;
-
- if ( dot == 0 )
- {
- cx += 0.5f;
- cy += 0.5f;
- }
-
- px = cx-Math::Mod(cx, 1.0f);
- py = cy-Math::Mod(cy, 1.0f); // multiple of 1
-
- if ( px+dot < min.x || py+dot < min.y ||
- px-dot > max.x || py-dot > max.y ) continue;
-
- for ( iy=-dot ; iy<=dot ; iy++ )
- {
- for ( ix=-dot ; ix<=dot ; ix++ )
- {
- ppx = px+ix;
- ppy = py+iy;
-
- if ( ppx < min.x || ppy < min.y ||
- ppx >= max.x || ppy >= max.y ) continue;
-
- if ( dot == 0 )
- {
- intensity = 0.0f;
- }
- else
- {
- intensity = Math::Point(ppx-cx, ppy-cy).Length()/dot;
- //? intensity = powf(intensity, m_groundSpot[i].smooth);
- }
-
- color.r = m_groundSpot[i].color.r+intensity;
- color.g = m_groundSpot[i].color.g+intensity;
- color.b = m_groundSpot[i].color.b+intensity;
-
- ppx -= min.x; // on the texture
- ppy -= min.y;
- AddDot(&ddsd, (int)ppx, (int)ppy, color);
- }
- }
- }
- else
- {
- for ( iy=0 ; iy<256 ; iy++ )
- {
- for ( ix=0 ; ix<256 ; ix++ )
- {
- pos.x = (256.0f*(s%4)+ix)*3200.0f/1024.0f - 1600.0f;
- pos.z = (256.0f*(s/4)+iy)*3200.0f/1024.0f - 1600.0f;
- pos.y = 0.0f;
- level = m_terrain->RetFloorLevel(pos, true);
- if ( level < m_groundSpot[i].min ||
- level > m_groundSpot[i].max ) continue;
-
- if ( level > (m_groundSpot[i].max+m_groundSpot[i].min)/2.0f )
- {
- intensity = 1.0f-(m_groundSpot[i].max-level)/m_groundSpot[i].smooth;
- }
- else
- {
- intensity = 1.0f-(level-m_groundSpot[i].min)/m_groundSpot[i].smooth;
- }
- if ( intensity < 0.0f ) intensity = 0.0f;
-
- color.r = m_groundSpot[i].color.r+intensity;
- color.g = m_groundSpot[i].color.g+intensity;
- color.b = m_groundSpot[i].color.b+intensity;
-
- AddDot(&ddsd, ix, iy, color);
- }
- }
- }
- }
-
- if ( bSet )
- {
- dot = (int)(m_groundMark.radius/2.0f);
-
- tu = (m_groundMark.pos.x+1600.0f)/3200.0f;
- tv = (m_groundMark.pos.z+1600.0f)/3200.0f; // 0..1
-
- cx = (tu*254.0f*4.0f)-0.5f;
- cy = (tv*254.0f*4.0f)-0.5f;
-
- if ( dot == 0 )
- {
- cx += 0.5f;
- cy += 0.5f;
- }
-
- px = cx-Math::Mod(cx, 1.0f);
- py = cy-Math::Mod(cy, 1.0f); // multiple of 1
-
- for ( iy=-dot ; iy<=dot ; iy++ )
- {
- for ( ix=-dot ; ix<=dot ; ix++ )
- {
- ppx = px+ix;
- ppy = py+iy;
-
- if ( ppx < min.x || ppy < min.y ||
- ppx >= max.x || ppy >= max.y ) continue;
-
- ppx -= min.x; // on the texture
- ppy -= min.y;
-
- intensity = 1.0f-Math::Point((float)ix, (float)iy).Length()/dot;
- if ( intensity <= 0.0f ) continue;
- intensity *= m_groundMark.intensity;
-
- j = (ix+dot) + (iy+dot)*m_groundMark.dx;
- if ( m_groundMark.table[j] == 1 ) // green ?
- {
- color.r = 1.0f-intensity;
- color.g = 1.0f;
- color.b = 1.0f-intensity;
- AddDot(&ddsd, (int)ppx, (int)ppy, color);
- }
- if ( m_groundMark.table[j] == 2 ) // red ?
- {
- color.r = 1.0f;
- color.g = 1.0f-intensity;
- color.b = 1.0f-intensity;
- AddDot(&ddsd, (int)ppx, (int)ppy, color);
- }
- }
- }
- }
-
- surface->Unlock(NULL);
- }
- }
-
- for ( i=0 ; i<D3DMAXGROUNDSPOT ; i++ )
- {
- if ( m_groundSpot[i].bUsed == false ||
- m_groundSpot[i].radius == 0.0f )
- {
- m_groundSpot[i].drawRadius = 0.0f;
- }
- else
- {
- m_groundSpot[i].drawPos = m_groundSpot[i].pos;
- m_groundSpot[i].drawRadius = m_groundSpot[i].radius;
- }
- }
-
- m_groundMark.drawPos = m_groundMark.pos;
- m_groundMark.drawRadius = m_groundMark.radius;
- m_groundMark.drawIntensity = m_groundMark.intensity;
-
- m_bFirstGroundSpot = false;
-}
-
-// Draw all the shadows.
-
-void CD3DEngine::DrawShadow()
-{
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Vector corner[4], n, pos;
- D3DMATERIAL7 material;
- Math::Matrix matrix;
- Math::Point ts, ti, rot;
- float startDeepView, endDeepView;
- float intensity, lastIntensity, hFactor, radius, max, height;
- float dp, h, d, D;
- int i;
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
-
- matrix.LoadIdentity();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- ZeroMemory( &material, sizeof(D3DMATERIAL7) );
- material.diffuse.r = 1.0f;
- material.diffuse.g = 1.0f;
- material.diffuse.b = 1.0f; // white
- material.ambient.r = 0.5f;
- material.ambient.g = 0.5f;
- material.ambient.b = 0.5f;
- SetMaterial(material);
-
-#if _POLISH
- SetTexture("textp.tga");
-#else
- SetTexture("text.tga");
-#endif
-
- dp = 0.5f/256.0f;
- ts.y = 192.0f/256.0f;
- ti.y = 224.0f/256.0f;
- ts.y += dp;
- ti.y -= dp;
-
- n = Math::Vector(0.0f, 1.0f, 0.0f);
-
- startDeepView = m_deepView[m_rankView]*m_fogStart[m_rankView];
- endDeepView = m_deepView[m_rankView];
-
- lastIntensity = -1.0f;
- for ( i=0 ; i<m_shadowTotal ; i++ )
- {
- if ( !m_shadow[i].bUsed ) continue;
- if ( m_shadow[i].bHide ) continue;
-
- pos = m_shadow[i].pos; // pos = center of the shadow on the ground
-
- if ( m_eyePt.y == pos.y ) continue; // camera at the same level?
-
- // h is the height above the ground to which the shadow
- // will be drawn.
- if ( m_eyePt.y > pos.y ) // camera on?
- {
- height = m_eyePt.y-pos.y;
- h = m_shadow[i].radius;
- max = height*0.5f;
- if ( h > max ) h = max;
- if ( h > 4.0f ) h = 4.0f;
-
- D = Math::Distance(m_eyePt, pos);
- if ( D >= endDeepView ) continue;
- d = D*h/height;
-
- pos.x += (m_eyePt.x-pos.x)*d/D;
- pos.z += (m_eyePt.z-pos.z)*d/D;
- pos.y += h;
- }
- else // camera underneath?
- {
- height = pos.y-m_eyePt.y;
- h = m_shadow[i].radius;
- max = height*0.1f;
- if ( h > max ) h = max;
- if ( h > 4.0f ) h = 4.0f;
-
- D = Math::Distance(m_eyePt, pos);
- if ( D >= endDeepView ) continue;
- d = D*h/height;
-
- pos.x += (m_eyePt.x-pos.x)*d/D;
- pos.z += (m_eyePt.z-pos.z)*d/D;
- pos.y -= h;
- }
-
- // The hFactor decreases the intensity and size increases more
- // the object is high relative to the ground.
- hFactor = m_shadow[i].height/20.0f;
- if ( hFactor < 0.0f ) hFactor = 0.0f;
- if ( hFactor > 1.0f ) hFactor = 1.0f;
- hFactor = powf(1.0f-hFactor, 2.0f);
- if ( hFactor < 0.2f ) hFactor = 0.2f;
-
- radius = m_shadow[i].radius*1.5f;
- radius *= 2.0f-hFactor; // greater if high
- radius *= 1.0f-d/D; // smaller if close
-
- if ( m_shadow[i].type == D3DSHADOWNORM )
- {
- corner[0].x = +radius;
- corner[0].z = +radius;
- corner[0].y = 0.0f;
-
- corner[1].x = -radius;
- corner[1].z = +radius;
- corner[1].y = 0.0f;
-
- corner[2].x = +radius;
- corner[2].z = -radius;
- corner[2].y = 0.0f;
-
- corner[3].x = -radius;
- corner[3].z = -radius;
- corner[3].y = 0.0f;
-
- ts.x = 64.0f/256.0f;
- ti.x = 96.0f/256.0f;
- }
- else
- {
- rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(radius, radius));
- corner[0].x = rot.x;
- corner[0].z = rot.y;
- corner[0].y = 0.0f;
-
- rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(-radius, radius));
- corner[1].x = rot.x;
- corner[1].z = rot.y;
- corner[1].y = 0.0f;
-
- rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(radius, -radius));
- corner[2].x = rot.x;
- corner[2].z = rot.y;
- corner[2].y = 0.0f;
-
- rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(-radius, -radius));
- corner[3].x = rot.x;
- corner[3].z = rot.y;
- corner[3].y = 0.0f;
-
- if ( m_shadow[i].type == D3DSHADOWWORM )
- {
- ts.x = 96.0f/256.0f;
- ti.x = 128.0f/256.0f;
- }
- else
- {
- ts.x = 64.0f/256.0f;
- ti.x = 96.0f/256.0f;
- }
- }
-
- corner[0] = Math::CrossProduct(corner[0], m_shadow[i].normal);
- corner[1] = Math::CrossProduct(corner[1], m_shadow[i].normal);
- corner[2] = Math::CrossProduct(corner[2], m_shadow[i].normal);
- corner[3] = Math::CrossProduct(corner[3], m_shadow[i].normal);
-
- corner[0] += pos;
- corner[1] += pos;
- corner[2] += pos;
- corner[3] += pos;
-
- ts.x += dp;
- ti.x -= dp;
-
- vertex[0] = D3DVERTEX2(corner[1], n, ts.x, ts.y);
- vertex[1] = D3DVERTEX2(corner[0], n, ti.x, ts.y);
- vertex[2] = D3DVERTEX2(corner[3], n, ts.x, ti.y);
- vertex[3] = D3DVERTEX2(corner[2], n, ti.x, ti.y);
-
- intensity = (0.5f+m_shadow[i].intensity*0.5f)*hFactor;
-
- // Decreases the intensity of the shade if you're in the area
- // between the beginning and the end of the fog.
- if ( D > startDeepView )
- {
- intensity *= 1.0f-(D-startDeepView)/(endDeepView-startDeepView);
- }
-
- // Decreases if the intensity is almost horizontal
- // with shade (shade very platte).
-//? if ( height < 4.0f ) intensity *= height/4.0f;
-
- if ( intensity == 0.0f ) continue;
-
- if ( lastIntensity != intensity ) // intensity changed?
- {
- lastIntensity = intensity;
- SetState(D3DSTATETTw, RetColor(intensity));
- }
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- AddStatisticTriangle(2);
- }
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
-}
-
-
-// Called ounces per frame, the call is the entry point for 3d rendering.
-// This function sets up render states, clears the
-// viewport, and renders the scene.
-
-HRESULT CD3DEngine::Render()
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- D3DVERTEX2* pv;
- int l1, l2, l3, l4, l5, objRank, tState;
- CInterface* pInterface;
- bool bTransparent;
- D3DCOLOR color, tColor;
-
- if ( !m_bRender ) return S_OK;
-
- m_statisticTriangle = 0;
- m_lastState = -1;
- m_lastColor = 999;
- m_lastTexture[0][0] = 0;
- m_lastTexture[1][0] = 0;
- ZeroMemory(&m_lastMaterial, sizeof(D3DMATERIAL7));
-
- if ( m_bGroundSpot )
- {
- RenderGroundSpot();
- }
-
- // Clear the viewport
- if ( m_bSkyMode && m_cloud->RetLevel() != 0.0f ) // clouds?
- {
- color = m_backgroundCloudDown;
- }
- else
- {
- color = m_backgroundColorDown;
- }
- m_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
- color, 1.0f, 0L );
-
- m_light->LightUpdate();
-
- // Begin the scene
- if( FAILED( m_pD3DDevice->BeginScene() ) ) return S_OK;
-
- if ( m_bDrawWorld )
- {
- DrawBackground(); // draws the background
- if ( m_bPlanetMode ) DrawPlanet(); // draws the planets
- if ( m_bSkyMode ) m_cloud->Draw(); // draws the clouds
-
- // Display the objects
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, true);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZBIAS, F2DW(16));
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProj);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, m_fogColor[m_rankView]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_LINEAR);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGSTART, F2DW(m_deepView[m_rankView]*m_fogStart[m_rankView]));
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGEND, F2DW(m_deepView[m_rankView]));
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matView);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
-
- if ( m_bWaterMode ) m_water->DrawBack(); // draws water
-
- if ( m_bShadow )
- {
- // Draw the field.
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- SetTexture(p2->texName1, 0);
- SetTexture(p2->texName2, 1);
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- objRank = p3->objRank;
- if ( m_objectParam[objRank].type != TYPETERRAIN ) continue;
- if ( !m_objectParam[objRank].bDrawWorld ) continue;
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- if ( !IsVisible(objRank) ) continue;
- m_light->LightUpdate(m_objectParam[objRank].type);
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( m_objectParam[objRank].distance < p4->min ||
- m_objectParam[objRank].distance >= p4->max ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- SetMaterial(p6->material);
- SetState(p6->state);
- if ( p6->type == D3DTYPE6T )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed/3;
- }
- if ( p6->type == D3DTYPE6S )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed-2;
- }
- }
- }
- }
- }
- }
-
- DrawShadow(); // draws the shadows
- }
-
- // Draw objects.
- bTransparent = false;
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- SetTexture(p2->texName1, 0);
- SetTexture(p2->texName2, 1);
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- objRank = p3->objRank;
- if ( m_bShadow && m_objectParam[objRank].type == TYPETERRAIN ) continue;
- if ( !m_objectParam[objRank].bDrawWorld ) continue;
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- if ( !IsVisible(objRank) ) continue;
- m_light->LightUpdate(m_objectParam[objRank].type);
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( m_objectParam[objRank].distance < p4->min ||
- m_objectParam[objRank].distance >= p4->max ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- SetMaterial(p6->material);
- if ( m_objectParam[objRank].transparency != 0.0f ) // transparent ?
- {
- bTransparent = true;
- continue;
- }
- SetState(p6->state);
- if ( p6->type == D3DTYPE6T )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed/3;
- }
- if ( p6->type == D3DTYPE6S )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed-2;
- }
- }
- }
- }
- }
- }
-
- if ( bTransparent )
- {
- if ( m_bStateColor )
- {
- tState = D3DSTATETTb|D3DSTATE2FACE;
- tColor = 0x44444444;
- }
- else
- {
- tState = D3DSTATETTb;
- tColor = 0x88888888;
- }
-
- // Draw transparent objects.
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- SetTexture(p2->texName1, 0);
- SetTexture(p2->texName2, 1);
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- objRank = p3->objRank;
- if ( m_bShadow && m_objectParam[objRank].type == TYPETERRAIN ) continue;
- if ( !m_objectParam[objRank].bDrawWorld ) continue;
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- if ( !IsVisible(objRank) ) continue;
- m_light->LightUpdate(m_objectParam[objRank].type);
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( m_objectParam[objRank].distance < p4->min ||
- m_objectParam[objRank].distance >= p4->max ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- SetMaterial(p6->material);
- if ( m_objectParam[objRank].transparency == 0.0f ) continue;
- SetState(tState, tColor);
- if ( p6->type == D3DTYPE6T )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed/3;
- }
- if ( p6->type == D3DTYPE6S )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed-2;
- }
- }
- }
- }
- }
- }
- }
-
- m_light->LightUpdate(TYPETERRAIN);
- if ( m_bWaterMode ) m_water->DrawSurf(); // draws water
-//? m_cloud->Draw(); // draws the clouds
-
- m_particule->DrawParticule(SH_WORLD); // draws the particles of the 3D world
- m_blitz->Draw(); // draws lightning
- if ( m_bLensMode ) DrawFrontsize(); // draws the foreground
- if ( !m_bOverFront ) DrawOverColor(); // draws the foreground color
- }
-
- // Draw the user interface over the scene.
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- pInterface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
- if ( pInterface != 0 )
- {
- pInterface->Draw(); // draws the entire interface
- }
- m_particule->DrawParticule(SH_INTERFACE); // draws the particles of the interface
-
- if ( m_bDrawFront )
- {
- // Display the objects
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, true);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZBIAS, F2DW(16));
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProj);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, m_ambiantColor[m_rankView]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, m_fogColor[m_rankView]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_LINEAR);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGSTART, F2DW(m_deepView[m_rankView]*m_fogStart[m_rankView]));
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGEND, F2DW(m_deepView[m_rankView]));
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matView);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- SetTexture(p2->texName1, 0);
- SetTexture(p2->texName2, 1);
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- objRank = p3->objRank;
- if ( !m_objectParam[objRank].bDrawFront ) continue;
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- if ( !IsVisible(objRank) ) continue;
- m_light->LightUpdate(m_objectParam[objRank].type);
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( m_objectParam[objRank].distance < p4->min ||
- m_objectParam[objRank].distance >= p4->max ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- SetMaterial(p6->material);
- SetState(p6->state);
- if ( p6->type == D3DTYPE6T )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed/3;
- }
- if ( p6->type == D3DTYPE6S )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed-2;
- }
- }
- }
- }
- }
- }
-
- m_particule->DrawParticule(SH_FRONT); // draws the particles of the 3D world
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
- }
-
- if ( m_bOverFront ) DrawOverColor(); // draws the foreground color
-
- if ( m_mouseType != D3DMOUSEHIDE )
- {
- DrawMouse();
- }
-
- // End the scene.
- m_pD3DDevice->EndScene();
-
- DrawHilite();
- return S_OK;
-}
-
-
-// Draw the gradient background.
-
-void CD3DEngine::DrawBackground()
-{
- if ( m_bSkyMode && m_cloud->RetLevel() != 0.0f ) // clouds ?
- {
- if ( m_backgroundCloudUp != m_backgroundCloudDown ) // degraded?
- {
- DrawBackgroundGradient(m_backgroundCloudUp, m_backgroundCloudDown);
- }
- }
- else
- {
- if ( m_backgroundColorUp != m_backgroundColorDown ) // degraded?
- {
- DrawBackgroundGradient(m_backgroundColorUp, m_backgroundColorDown);
- }
- }
-
- if ( m_bBackForce || (m_bSkyMode && m_backgroundName[0] != 0) )
- {
- DrawBackgroundImage(); // image
- }
-}
-
-// Draw the gradient background.
-
-void CD3DEngine::DrawBackgroundGradient(D3DCOLOR up, D3DCOLOR down)
-{
- D3DLVERTEX vertex[4]; // 2 triangles
- D3DCOLOR color[3];
- Math::Point p1, p2;
-
- p1.x = 0.0f;
- p1.y = 0.5f;
- p2.x = 1.0f;
- p2.y = 1.0f;
-
- color[0] = up;
- color[1] = down;
- color[2] = 0x00000000;
-
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
-
- SetTexture("xxx.tga"); // no texture
- SetState(D3DSTATENORMAL);
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- vertex[0] = D3DLVERTEX(D3DVECTOR(p1.x, p1.y, 0.0f), color[1],color[2], 0.0f,0.0f);
- vertex[1] = D3DLVERTEX(D3DVECTOR(p1.x, p2.y, 0.0f), color[0],color[2], 0.0f,0.0f);
- vertex[2] = D3DLVERTEX(D3DVECTOR(p2.x, p1.y, 0.0f), color[1],color[2], 0.0f,0.0f);
- vertex[3] = D3DLVERTEX(D3DVECTOR(p2.x, p2.y, 0.0f), color[0],color[2], 0.0f,0.0f);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, vertex, 4, NULL);
- AddStatisticTriangle(2);
-}
-
-// Draws a portion of the image background.
-
-void CD3DEngine::DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, char *name)
-{
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Vector n;
- float u1, u2, v1, v2, h, a;
-
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
-
- if ( m_bBackgroundFull )
- {
- u1 = 0.0f;
- v1 = 0.0f;
- u2 = 1.0f;
- v2 = 1.0f;
-
- if ( m_bBackgroundQuarter )
- {
- u1 += 0.5f/512.0f;
- v1 += 0.5f/384.0f;
- u2 -= 0.5f/512.0f;
- v2 -= 0.5f/384.0f;
- }
- }
- else
- {
- h = 0.5f; // visible area vertically (1=all)
- a = m_eyeDirV-Math::PI*0.15f;
- if ( a > Math::PI ) a -= Math::PI*2.0f; // a = -Math::PI..Math::PI
- if ( a > Math::PI/4.0f ) a = Math::PI/4.0f;
- if ( a < -Math::PI/4.0f ) a = -Math::PI/4.0f;
-
- u1 = -m_eyeDirH/Math::PI;
- u2 = u1+1.0f/Math::PI;
-//? u1 = -m_eyeDirH/(Math::PI*2.0f);
-//? u2 = u1+1.0f/(Math::PI*2.0f);
-
- v1 = (1.0f-h)*(0.5f+a/(2.0f*Math::PI/4.0f))+0.1f;
- v2 = v1+h;
- }
-
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
-
- SetTexture(name);
- SetState(D3DSTATEWRAP);
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- AddStatisticTriangle(2);
-}
-
-// Draws the image background.
-
-void CD3DEngine::DrawBackgroundImage()
-{
- Math::Point p1, p2;
- char name[50];
-
- if ( m_bBackgroundQuarter )
- {
- p1.x = 0.0f;
- p1.y = 0.5f;
- p2.x = 0.5f;
- p2.y = 1.0f;
- QuarterName(name, m_backgroundName, 0);
- DrawBackgroundImageQuarter(p1, p2, name);
-
- p1.x = 0.5f;
- p1.y = 0.5f;
- p2.x = 1.0f;
- p2.y = 1.0f;
- QuarterName(name, m_backgroundName, 1);
- DrawBackgroundImageQuarter(p1, p2, name);
-
- p1.x = 0.0f;
- p1.y = 0.0f;
- p2.x = 0.5f;
- p2.y = 0.5f;
- QuarterName(name, m_backgroundName, 2);
- DrawBackgroundImageQuarter(p1, p2, name);
-
- p1.x = 0.5f;
- p1.y = 0.0f;
- p2.x = 1.0f;
- p2.y = 0.5f;
- QuarterName(name, m_backgroundName, 3);
- DrawBackgroundImageQuarter(p1, p2, name);
- }
- else
- {
- p1.x = 0.0f;
- p1.y = 0.0f;
- p2.x = 1.0f;
- p2.y = 1.0f;
- DrawBackgroundImageQuarter(p1, p2, m_backgroundName);
- }
-}
-
-// Draws all the planets.
-
-void CD3DEngine::DrawPlanet()
-{
- if ( !m_planet->PlanetExist() ) return;
-
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- m_planet->Draw(); // draws the planets
-}
-
-// Draws the image foreground.
-
-void CD3DEngine::DrawFrontsize()
-{
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Vector n;
- Math::Point p1, p2;
- float u1, u2, v1, v2;
-
- if ( m_frontsizeName[0] == 0 ) return;
-
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
-
- p1.x = 0.0f;
- p1.y = 0.0f;
- p2.x = 1.0f;
- p2.y = 1.0f;
-
- u1 = -m_eyeDirH/(Math::PI*0.6f)+Math::PI*0.5f;
- u2 = u1+0.50f;
-
- v1 = 0.2f;
- v2 = 1.0f;
-
-#if 0
- char s[100];
- sprintf(s, "h=%.2f v=%.2f u=%.2f;%.2f v=%.2f;%.2f", m_eyeDirH, m_eyeDirV, u1, u2, v1, v2);
- SetInfoText(3, s);
-#endif
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
-
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
-
- SetTexture(m_frontsizeName);
- SetState(D3DSTATECLAMP|D3DSTATETTb);
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- AddStatisticTriangle(2);
-}
-
-// Draws the foreground color.
-
-void CD3DEngine::DrawOverColor()
-{
- D3DLVERTEX vertex[4]; // 2 triangles
- D3DCOLOR color[3];
- Math::Point p1, p2;
-
- if ( !m_bStateColor ) return;
- if ( (m_overColor == 0x00000000 && m_overMode == D3DSTATETCb) ||
- (m_overColor == 0xffffffff && m_overMode == D3DSTATETCw) ) return;
-
- p1.x = 0.0f;
- p1.y = 0.0f;
- p2.x = 1.0f;
- p2.y = 1.0f;
-
- color[0] = m_overColor;
- color[1] = m_overColor;
- color[2] = 0x00000000;
-
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
-
- SetTexture("xxx.tga"); // no texture
- SetState(m_overMode);
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- vertex[0] = D3DLVERTEX(D3DVECTOR(p1.x, p1.y, 0.0f), color[1],color[2], 0.0f,0.0f);
- vertex[1] = D3DLVERTEX(D3DVECTOR(p1.x, p2.y, 0.0f), color[0],color[2], 0.0f,0.0f);
- vertex[2] = D3DLVERTEX(D3DVECTOR(p2.x, p1.y, 0.0f), color[1],color[2], 0.0f,0.0f);
- vertex[3] = D3DLVERTEX(D3DVECTOR(p2.x, p2.y, 0.0f), color[0],color[2], 0.0f,0.0f);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, vertex, 4, NULL);
- AddStatisticTriangle(2);
-}
-
-
-// Lists the ranks of objects and subobjects selected.
-
-void CD3DEngine::SetHiliteRank(int *rankList)
-{
- int i;
-
- i = 0;
- while ( *rankList != -1 )
- {
- m_hiliteRank[i++] = *rankList++;
- }
- m_hiliteRank[i] = -1; // terminator
-}
-
-// Give the box in the 2D screen of any object.
-
-bool CD3DEngine::GetBBox2D(int objRank, Math::Point &min, Math::Point &max)
-{
- Math::Vector p, pp;
- int i;
-
- min.x = 1000000.0f;
- min.y = 1000000.0f;
- max.x = -1000000.0f;
- max.y = -1000000.0f;
-
- for ( i=0 ; i<8 ; i++ )
- {
- if ( i & (1<<0) ) p.x = m_objectParam[objRank].bboxMin.x;
- else p.x = m_objectParam[objRank].bboxMax.x;
- if ( i & (1<<1) ) p.y = m_objectParam[objRank].bboxMin.y;
- else p.y = m_objectParam[objRank].bboxMax.y;
- if ( i & (1<<2) ) p.z = m_objectParam[objRank].bboxMin.z;
- else p.z = m_objectParam[objRank].bboxMax.z;
- if ( TransformPoint(pp, objRank, p) )
- {
- if ( pp.x < min.x ) min.x = pp.x;
- if ( pp.x > max.x ) max.x = pp.x;
- if ( pp.y < min.y ) min.y = pp.y;
- if ( pp.y > max.y ) max.y = pp.y;
- }
- }
-
- if ( min.x == 1000000.0f ||
- min.y == 1000000.0f ||
- max.x == -1000000.0f ||
- max.y == -1000000.0f ) return false;
-
- return true;
-}
-
-// Determines the rectangle of the object highlighted, which will be designed by CD3DApplication.
-
-void CD3DEngine::DrawHilite()
-{
- Math::Point min, max, omin, omax;
- int i;
-
- min.x = 1000000.0f;
- min.y = 1000000.0f;
- max.x = -1000000.0f;
- max.y = -1000000.0f;
-
- i = 0;
- while ( m_hiliteRank[i] != -1 )
- {
- if ( GetBBox2D(m_hiliteRank[i++], omin, omax) )
- {
- min.x = Math::Min(min.x, omin.x);
- min.y = Math::Min(min.y, omin.y);
- max.x = Math::Max(max.x, omax.x);
- max.y = Math::Max(max.y, omax.y);
- }
- }
-
- if ( min.x == 1000000.0f ||
- min.y == 1000000.0f ||
- max.x == -1000000.0f ||
- max.y == -1000000.0f )
- {
- m_bHilite = false; // not highlighted
- }
- else
- {
- m_hiliteP1 = min;
- m_hiliteP2 = max;
- m_bHilite = true;
- }
-}
-
-// Give the rectangle highlighted by drawing CD3DApplication.
-
-bool CD3DEngine::GetHilite(Math::Point &p1, Math::Point &p2)
-{
- p1 = m_hiliteP1;
- p2 = m_hiliteP2;
- return m_bHilite;
-}
-
-
-// Triangles adds qq records for statistics.
-
-void CD3DEngine::AddStatisticTriangle(int nb)
-{
- m_statisticTriangle += nb;
-}
-
-// Returns the number of triangles rendered.
-
-int CD3DEngine::RetStatisticTriangle()
-{
- return m_statisticTriangle;
-}
-
-bool CD3DEngine::GetSpriteCoord(int &x, int &y)
-{
- D3DVIEWPORT7 vp;
- Math::Vector v, vv;
-
- return false;
- //?
- vv = Math::Vector(0.0f, 0.0f, 0.0f);
- if ( !TransformPoint(v, 20*20+1, vv) ) return false;
-
- m_pD3DDevice->GetViewport(&vp);
- v.x *= vp.dwWidth/2;
- v.y *= vp.dwHeight/2;
- v.x = v.x+vp.dwWidth/2;
- v.y = vp.dwHeight-(v.y+vp.dwHeight/2);
-
- x = (int)v.x;
- y = (int)v.y;
- return true;
-}
-
-
-// Tests whether to exclude a point.
-
-bool IsExcludeColor(Math::Point *pExclu, int x, int y)
-{
- int i;
-
- i = 0;
- while ( pExclu[i+0].x != 0.0f || pExclu[i+0].y != 0.0f ||
- pExclu[i+1].y != 0.0f || pExclu[i+1].y != 0.0f )
- {
- if ( x >= (int)(pExclu[i+0].x*256.0f) &&
- x < (int)(pExclu[i+1].x*256.0f) &&
- y >= (int)(pExclu[i+0].y*256.0f) &&
- y < (int)(pExclu[i+1].y*256.0f) ) return true; // exclude
-
- i += 2;
- }
-
- return false; // point to include
-}
-
-// Change the color of a texture.
-
-bool CD3DEngine::ChangeColor(char *name,
- D3DCOLORVALUE colorRef1, D3DCOLORVALUE colorNew1,
- D3DCOLORVALUE colorRef2, D3DCOLORVALUE colorNew2,
- float tolerance1, float tolerance2,
- Math::Point ts, Math::Point ti,
- Math::Point *pExclu, float shift, bool bHSV)
-{
- LPDIRECTDRAWSURFACE7 surface;
- DDSURFACEDESC2 ddsd;
- D3DCOLORVALUE color;
- ColorHSV cr1, cn1, cr2, cn2, c;
- int dx, dy, x, y, sx, sy, ex, ey;
-
- D3DTextr_Invalidate(name);
- LoadTexture(name); // reloads the initial texture
-
- if ( colorRef1.r == colorNew1.r &&
- colorRef1.g == colorNew1.g &&
- colorRef1.b == colorNew1.b &&
- colorRef2.r == colorNew2.r &&
- colorRef2.g == colorNew2.g &&
- colorRef2.b == colorNew2.b ) return true;
-
- surface = D3DTextr_GetSurface(name);
- if ( surface == 0 ) return false;
-
- ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
- ddsd.dwSize = sizeof(DDSURFACEDESC2);
- if ( surface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK ) return false;
-
- dx = ddsd.dwWidth;
- dy = ddsd.dwHeight;
-
- sx = (int)(ts.x*dx);
- sy = (int)(ts.y*dy);
- ex = (int)(ti.x*dx);
- ey = (int)(ti.y*dy);
-
- RGB2HSV(colorRef1, cr1);
- RGB2HSV(colorNew1, cn1);
- RGB2HSV(colorRef2, cr2);
- RGB2HSV(colorNew2, cn2);
-
- for ( y=sy ; y<ey ; y++ )
- {
- for ( x=sx ; x<ex ; x++ )
- {
- if ( pExclu != 0 && IsExcludeColor(pExclu, x,y) ) continue;
-
- color = GetDot(&ddsd, x, y);
-
- if ( bHSV )
- {
- RGB2HSV(color, c);
- if ( c.s > 0.01f && fabs(c.h-cr1.h) < tolerance1 )
- {
- c.h += cn1.h-cr1.h;
- c.s += cn1.s-cr1.s;
- c.v += cn1.v-cr1.v;
- if ( c.h < 0.0f ) c.h -= 1.0f;
- if ( c.h > 1.0f ) c.h += 1.0f;
- HSV2RGB(c, color);
- color.r += shift;
- color.g += shift;
- color.b += shift;
- ::SetDot(&ddsd, x, y, color);
- }
- else
- if ( tolerance2 != -1.0f &&
- c.s > 0.01f && fabs(c.h-cr2.h) < tolerance2 )
- {
- c.h += cn2.h-cr2.h;
- c.s += cn2.s-cr2.s;
- c.v += cn2.v-cr2.v;
- if ( c.h < 0.0f ) c.h -= 1.0f;
- if ( c.h > 1.0f ) c.h += 1.0f;
- HSV2RGB(c, color);
- color.r += shift;
- color.g += shift;
- color.b += shift;
- ::SetDot(&ddsd, x, y, color);
- }
- }
- else
- {
- if ( fabs(color.r-colorRef1.r)+
- fabs(color.g-colorRef1.g)+
- fabs(color.b-colorRef1.b) < tolerance1*3.0f )
- {
- color.r = colorNew1.r+color.r-colorRef1.r+shift;
- color.g = colorNew1.g+color.g-colorRef1.g+shift;
- color.b = colorNew1.b+color.b-colorRef1.b+shift;
- ::SetDot(&ddsd, x, y, color);
- }
- else
- if ( tolerance2 != -1 &&
- fabs(color.r-colorRef2.r)+
- fabs(color.g-colorRef2.g)+
- fabs(color.b-colorRef2.b) < tolerance2*3.0f )
- {
- color.r = colorNew2.r+color.r-colorRef2.r+shift;
- color.g = colorNew2.g+color.g-colorRef2.g+shift;
- color.b = colorNew2.b+color.b-colorRef2.b+shift;
- ::SetDot(&ddsd, x, y, color);
- }
- }
- }
- }
-
- surface->Unlock(NULL);
- return true;
-}
-
-
-// Open an image to work directly in it.
-
-bool CD3DEngine::OpenImage(char *name)
-{
-//? D3DTextr_Invalidate(name);
-//? LoadTexture(name);
-
- m_imageSurface = D3DTextr_GetSurface(name);
- if ( m_imageSurface == 0 ) return false;
-
- ZeroMemory(&m_imageDDSD, sizeof(DDSURFACEDESC2));
- m_imageDDSD.dwSize = sizeof(DDSURFACEDESC2);
- if ( m_imageSurface->Lock(NULL, &m_imageDDSD, DDLOCK_WAIT, NULL) != DD_OK )
- {
- return false;
- }
-
- if ( m_imageDDSD.ddpfPixelFormat.dwRGBBitCount != 16 )
- {
- m_imageSurface->Unlock(NULL);
- return false;
- }
-
- m_imageDX = m_imageDDSD.dwWidth;
- m_imageDY = m_imageDDSD.dwHeight;
-
- return true;
-}
-
-// Copy the working image.
-
-bool CD3DEngine::CopyImage()
-{
- WORD* pbSurf;
- int y;
-
- if ( m_imageCopy == 0 )
- {
- m_imageCopy = (WORD*)malloc(m_imageDX*m_imageDY*sizeof(WORD));
- }
-
- for ( y=0 ; y<m_imageDY ; y++ )
- {
- pbSurf = (WORD*)m_imageDDSD.lpSurface;
- pbSurf += m_imageDDSD.lPitch*y/2;
- memcpy(m_imageCopy+y*m_imageDX, pbSurf, m_imageDX*sizeof(WORD));
- }
- return true;
-}
-
-// Restores the image work.
-
-bool CD3DEngine::LoadImage()
-{
- WORD* pbSurf;
- int y;
-
- if ( m_imageCopy == 0 ) return false;
-
- for ( y=0 ; y<m_imageDY ; y++ )
- {
- pbSurf = (WORD*)m_imageDDSD.lpSurface;
- pbSurf += m_imageDDSD.lPitch*y/2;
- memcpy(pbSurf, m_imageCopy+y*m_imageDX, m_imageDX*sizeof(WORD));
- }
- return true;
-}
-
-// Scroll the copy of the working image.
-
-bool CD3DEngine::ScrollImage(int dx, int dy)
-{
- int x, y;
-
- if ( dx > 0 )
- {
- for ( y=0 ; y<m_imageDY ; y++ )
- {
- for ( x=0 ; x<m_imageDX-dx ; x++ )
- {
- m_imageCopy[x+y*m_imageDX] = m_imageCopy[x+dx+y*m_imageDX];
- }
- }
- }
-
- if ( dx < 0 )
- {
- for ( y=0 ; y<m_imageDY ; y++ )
- {
- for ( x=m_imageDX-1 ; x>=-dx ; x-- )
- {
- m_imageCopy[x+y*m_imageDX] = m_imageCopy[x+dx+y*m_imageDX];
- }
- }
- }
-
- if ( dy > 0 )
- {
- for ( y=0 ; y<m_imageDY-dy ; y++ )
- {
- memcpy(m_imageCopy+y*m_imageDX, m_imageCopy+(y+dy)*m_imageDX, m_imageDX*sizeof(WORD));
- }
- }
-
- if ( dy < 0 )
- {
- for ( y=m_imageDY-1 ; y>=-dy ; y-- )
- {
- memcpy(m_imageCopy+y*m_imageDX, m_imageCopy+(y+dy)*m_imageDX, m_imageDX*sizeof(WORD));
- }
- }
-
- return true;
-}
-
-// Draws a point in the image work.
-
-bool CD3DEngine::SetDot(int x, int y, D3DCOLORVALUE color)
-{
- WORD* pbSurf;
- WORD r,g,b, w;
-
- if ( x < 0 || x >= m_imageDX ||
- y < 0 || y >= m_imageDY ) return false;
-
-#if 1
- if ( color.r < 0.0f ) color.r = 0.0f;
- if ( color.r > 1.0f ) color.r = 1.0f;
- if ( color.g < 0.0f ) color.g = 0.0f;
- if ( color.g > 1.0f ) color.g = 1.0f;
- if ( color.b < 0.0f ) color.b = 0.0f;
- if ( color.b > 1.0f ) color.b = 1.0f;
-
- r = (int)(color.r*32.0f);
- g = (int)(color.g*32.0f);
- b = (int)(color.b*32.0f);
-
- if ( r >= 32 ) r = 31; // 5 bits
- if ( g >= 32 ) g = 31; // 5 bits
- if ( b >= 32 ) b = 31; // 5 bits
-#else
- r = (int)(color.r*31.0f);
- g = (int)(color.g*31.0f);
- b = (int)(color.b*31.0f);
-#endif
-
- if ( m_imageDDSD.ddpfPixelFormat.dwRBitMask == 0xf800 ) // 565 ?
- {
- w = (r<<11)|(g<<6)|b;
- }
- else if ( m_imageDDSD.ddpfPixelFormat.dwRBitMask == 0x7c00 ) // 555 ?
- {
- w = (r<<10)|(g<<5)|b;
- }
- else
- {
- w = -1; // blank
- }
-
- pbSurf = (WORD*)m_imageDDSD.lpSurface;
- pbSurf += m_imageDDSD.lPitch*y/2;
- pbSurf += x;
-
- *pbSurf = w;
- return true;
-}
-
-// Closes the working image.
-
-bool CD3DEngine::CloseImage()
-{
- m_imageSurface->Unlock(NULL);
- return true;
-}
-
-
-// Writes a .BMP screenshot.
-
-bool CD3DEngine::WriteScreenShot(char *filename, int width, int height)
-{
- return m_app->WriteScreenShot(filename, width, height);
-}
-
-// Initializes an hDC on the rendering surface.
-
-bool CD3DEngine::GetRenderDC(HDC &hDC)
-{
- return m_app->GetRenderDC(hDC);
-}
-
-// Frees the hDC of the rendering surface.
-
-bool CD3DEngine::ReleaseRenderDC(HDC &hDC)
-{
- return m_app->ReleaseRenderDC(hDC);
-}
-
-PBITMAPINFO CD3DEngine::CreateBitmapInfoStruct(HBITMAP hBmp)
-{
- return m_app->CreateBitmapInfoStruct(hBmp);
-}
-
-bool CD3DEngine::CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC)
-{
- return m_app->CreateBMPFile(pszFile, pbi, hBMP, hDC);
-}
-
-// Returns the pointer to the class cText.
-
-CText* CD3DEngine::RetText()
-{
- return m_text;
-}
-
-
-// Managing of information text displayed in the window.
-
-void CD3DEngine::SetInfoText(int line, char* text)
-{
- strcpy(m_infoText[line], text);
-}
-
-char* CD3DEngine::RetInfoText(int line)
-{
- return m_infoText[line];
-}
-
-
-
-// Specifies the length of the camera.
-// 0.75 = normal
-// 1.50 = wide-angle
-
-void CD3DEngine::SetFocus(float focus)
-{
- D3DVIEWPORT7 vp;
- float fAspect;
-
- m_focus = focus;
-
- if ( m_pD3DDevice != 0 )
- {
- m_pD3DDevice->GetViewport(&vp);
- m_dim.x = vp.dwWidth;
- m_dim.y = vp.dwHeight;
- }
-
- fAspect = ((float)m_dim.y) / m_dim.x;
-//? Math::LoadProjectionMatrix(m_matProj, m_focus, fAspect, 0.5f, m_deepView[m_rankView]);
- Math::LoadProjectionMatrix(m_matProj, m_focus, fAspect, 0.5f, m_deepView[0]);
-}
-
-float CD3DEngine::RetFocus()
-{
- return m_focus;
-}
-
-//
-
-void CD3DEngine::UpdateMatProj()
-{
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProj);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
-}
-
-
-
-// Ignores key presses.
-
-void CD3DEngine::FlushPressKey()
-{
- m_app->FlushPressKey();
-}
-
-// Resets the default keys.
-
-void CD3DEngine::ResetKey()
-{
- m_app->ResetKey();
-}
-
-// Modifies a button.
-
-void CD3DEngine::SetKey(int keyRank, int option, int key)
-{
- m_app->SetKey(keyRank, option, key);
-}
-
-// Gives a key.
-
-int CD3DEngine::RetKey(int keyRank, int option)
-{
- return m_app->RetKey(keyRank, option);
-}
-
-
-// Use the joystick or keyboard.
-
-void CD3DEngine::SetJoystick(bool bEnable)
-{
- m_app->SetJoystick(bEnable);
-}
-
-bool CD3DEngine::RetJoystick()
-{
- return m_app->RetJoystick();
-}
-
-
-void CD3DEngine::SetDebugMode(bool bMode)
-{
- m_app->SetDebugMode(bMode);
-}
-
-bool CD3DEngine::RetDebugMode()
-{
- return m_app->RetDebugMode();
-}
-
-bool CD3DEngine::RetSetupMode()
-{
- return m_app->RetSetupMode();
-}
-
-
-// Indicates whether a point is visible.
-
-bool CD3DEngine::IsVisiblePoint(const Math::Vector &pos)
-{
- return ( Math::Distance(m_eyePt, pos) <= m_deepView[0] );
-}
-
-
-// Initialize scene objects.
-
-HRESULT CD3DEngine::InitDeviceObjects()
-{
- // Set miscellaneous render states.
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SPECULARENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID);
-
- // Set up the textures.
- D3DTextr_RestoreAllTextures(m_pD3DDevice);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_MINFILTER, D3DTFN_LINEAR);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
-
- SetFocus(m_focus);
-
- // Definitions of the matrices for the interface.
- m_matWorldInterface.LoadIdentity();
-
- m_matViewInterface.LoadIdentity();
- m_matViewInterface.Set(1, 4, -0.5f);
- m_matViewInterface.Set(2, 4, -0.5f);
- m_matViewInterface.Set(3, 4, 1.0f);
-
- m_matProjInterface.LoadIdentity();
- m_matProjInterface.Set(1, 1, 2.0f);
- m_matProjInterface.Set(2, 2, 2.0f);
- m_matProjInterface.Set(4, 3, 1.0f);
- m_matProjInterface.Set(3, 4, -1.0f);
- m_matProjInterface.Set(4, 4, 0.0f);
-
- return S_OK;
-}
-
-
-// Restore all surfaces.
-
-HRESULT CD3DEngine::RestoreSurfaces()
-{
- return S_OK;
-}
-
-
-// Called when the app is exitting, or the device is being changed,
-// this function deletes any device dependant objects.
-
-HRESULT CD3DEngine::DeleteDeviceObjects()
-{
- D3DTextr_InvalidateAllTextures();
- return S_OK;
-}
-
-
-// Called before the app exits, this function gives the app the chance
-// to cleanup after itself.
-
-HRESULT CD3DEngine::FinalCleanup()
-{
- return S_OK;
-}
-
-
-// Overrrides the main WndProc, so the sample can do custom message
-// handling (e.g. processing mouse, keyboard, or menu commands).
-
-LRESULT CD3DEngine::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
-{
-#if 0
- if ( uMsg == WM_KEYDOWN ) // Alt+key ?
- {
- if ( wParam == 'Q' )
- {
- debug_blend1 ++;
- if ( debug_blend1 > 13 ) debug_blend1 = 0;
- }
- if ( wParam == 'W' )
- {
- debug_blend2 ++;
- if ( debug_blend2 > 13 ) debug_blend2 = 0;
- }
- if ( wParam == 'E' )
- {
- debug_blend3 ++;
- if ( debug_blend3 > 13 ) debug_blend3 = 0;
- }
- if ( wParam == 'R' )
- {
- debug_blend4 ++;
- if ( debug_blend4 > 13 ) debug_blend4 = 0;
- }
- char s[100];
- sprintf(s, "src=%d, dest=%d, src=%d, dest=%d", debug_blend1, debug_blend2, debug_blend3, debug_blend4);
- SetInfoText(4, s);
- }
-#endif
-
-#if 1
- if ( uMsg == WM_SYSKEYDOWN ) // Alt+key ?
- {
- if ( wParam == VK_F7 ) // Alt+F7 ?
- {
- s_resol = 0;
- }
- if ( wParam == VK_F8 ) // Alt+F8 ?
- {
- s_resol = 1;
- }
- if ( wParam == VK_F9 ) // Alt+F9 ?
- {
- s_resol = 2;
- }
- if ( wParam == VK_F10 ) // Alt+F10 ?
- {
- s_resol = 3;
- }
- }
-#endif
-
- return 0;
-}
-
-
-// Mouse control.
-
-void CD3DEngine::MoveMousePos(Math::Point pos)
-{
- m_mousePos = pos;
- m_app->SetMousePos(pos);
-}
-
-void CD3DEngine::SetMousePos(Math::Point pos)
-{
- m_mousePos = pos;
-}
-
-Math::Point CD3DEngine::RetMousePos()
-{
- return m_mousePos;
-}
-
-void CD3DEngine::SetMouseType(D3DMouse type)
-{
- m_mouseType = type;
-}
-
-D3DMouse CD3DEngine::RetMouseType()
-{
- return m_mouseType;
-}
-
-void CD3DEngine::SetMouseHide(bool bHide)
-{
- if ( m_bMouseHide == bHide ) return;
-
- if ( bHide ) // hide the mouse?
- {
- m_bNiceMouse = m_app->RetNiceMouse();
- if ( !m_bNiceMouse )
- {
- m_app->SetNiceMouse(true);
- }
- m_bMouseHide = true;
- }
- else // shows the mouse?
- {
- if ( !m_bNiceMouse )
- {
- m_app->SetNiceMouse(false);
- }
- m_bMouseHide = false;
- }
-}
-
-bool CD3DEngine::RetMouseHide()
-{
- return m_bMouseHide;
-}
-
-void CD3DEngine::SetNiceMouse(bool bNice)
-{
- m_app->SetNiceMouse(bNice);
-}
-
-bool CD3DEngine::RetNiceMouse()
-{
- return m_app->RetNiceMouse();
-}
-
-bool CD3DEngine::RetNiceMouseCap()
-{
- return m_app->RetNiceMouseCap();
-}
-
-// Draws the sprite of the mouse.
-
-void CD3DEngine::DrawMouse()
-{
- D3DMATERIAL7 material;
- Math::Point pos, ppos, dim;
- int i;
-
- struct Mouse
- {
- D3DMouse type;
- int icon1, icon2, iconShadow;
- int mode1, mode2;
- float hotx, hoty;
- };
-
- static Mouse table[] =
- {
- { D3DMOUSENORM, 0, 1,32, D3DSTATETTw, D3DSTATETTb, 1.0f, 1.0f},
- { D3DMOUSEWAIT, 2, 3,33, D3DSTATETTw, D3DSTATETTb, 8.0f, 12.0f},
- { D3DMOUSEHAND, 4, 5,34, D3DSTATETTw, D3DSTATETTb, 7.0f, 2.0f},
- { D3DMOUSENO, 6, 7,35, D3DSTATETTw, D3DSTATETTb, 10.0f, 10.0f},
- { D3DMOUSEEDIT, 8, 9,-1, D3DSTATETTb, D3DSTATETTw, 6.0f, 10.0f},
- { D3DMOUSECROSS, 10,11,-1, D3DSTATETTb, D3DSTATETTw, 10.0f, 10.0f},
- { D3DMOUSEMOVEV, 12,13,-1, D3DSTATETTb, D3DSTATETTw, 5.0f, 11.0f},
- { D3DMOUSEMOVEH, 14,15,-1, D3DSTATETTb, D3DSTATETTw, 11.0f, 5.0f},
- { D3DMOUSEMOVED, 16,17,-1, D3DSTATETTb, D3DSTATETTw, 9.0f, 9.0f},
- { D3DMOUSEMOVEI, 18,19,-1, D3DSTATETTb, D3DSTATETTw, 9.0f, 9.0f},
- { D3DMOUSEMOVE, 20,21,-1, D3DSTATETTb, D3DSTATETTw, 11.0f, 11.0f},
- { D3DMOUSETARGET, 22,23,-1, D3DSTATETTb, D3DSTATETTw, 15.0f, 15.0f},
- { D3DMOUSESCROLLL, 24,25,43, D3DSTATETTb, D3DSTATETTw, 2.0f, 9.0f},
- { D3DMOUSESCROLLR, 26,27,44, D3DSTATETTb, D3DSTATETTw, 17.0f, 9.0f},
- { D3DMOUSESCROLLU, 28,29,45, D3DSTATETTb, D3DSTATETTw, 9.0f, 2.0f},
- { D3DMOUSESCROLLD, 30,31,46, D3DSTATETTb, D3DSTATETTw, 9.0f, 17.0f},
- { D3DMOUSEHIDE },
- };
-
- if ( m_bMouseHide ) return;
- if ( !m_app->RetNiceMouse() ) return; // mouse windows?
-
- ZeroMemory( &material, sizeof(D3DMATERIAL7) );
- material.diffuse.r = 1.0f;
- material.diffuse.g = 1.0f;
- material.diffuse.b = 1.0f;
- material.ambient.r = 0.5f;
- material.ambient.g = 0.5f;
- material.ambient.b = 0.5f;
- SetMaterial(material);
-
- SetTexture("mouse.tga");
-
- i = 0;
- while ( table[i].type != D3DMOUSEHIDE )
- {
- if ( m_mouseType == table[i].type )
- {
- dim.x = 0.05f*0.75f;
- dim.y = 0.05f;
-
- pos.x = m_mousePos.x - (table[i].hotx*dim.x)/32.0f;
- pos.y = m_mousePos.y - ((32.0f-table[i].hoty)*dim.y)/32.0f;
-
- ppos.x = pos.x+(4.0f/640.0f);
- ppos.y = pos.y-(3.0f/480.0f);
- SetState(D3DSTATETTw);
- DrawSprite(ppos, dim, table[i].iconShadow);
-
- SetState(table[i].mode1);
- DrawSprite(pos, dim, table[i].icon1);
-
- SetState(table[i].mode2);
- DrawSprite(pos, dim, table[i].icon2);
- break;
- }
- i ++;
- }
-}
-
-// Draws the sprite of the mouse.
-
-void CD3DEngine::DrawSprite(Math::Point pos, Math::Point dim, int icon)
-{
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Point p1, p2;
- Math::Vector n;
- float u1, u2, v1, v2, dp;
-
- if ( icon == -1 ) return;
-
- p1.x = pos.x;
- p1.y = pos.y;
- p2.x = pos.x + dim.x;
- p2.y = pos.y + dim.y;
-
- u1 = (32.0f/256.0f)*(icon%8);
- v1 = (32.0f/256.0f)*(icon/8); // u-v texture
- u2 = (32.0f/256.0f)+u1;
- v2 = (32.0f/256.0f)+v1;
-
- dp = 0.5f/256.0f;
- u1 += dp;
- v1 += dp;
- u2 -= dp;
- v2 -= dp;
-
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- AddStatisticTriangle(2);
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// d3dengine.cpp
+
+
+#include <stdio.h>
+#include <math.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "math/conv.h"
+#include "old/d3dapp.h"
+#include "old/d3dtextr.h"
+#include "old/d3dutil.h"
+#include "old/d3dmath.h"
+#include "old/d3dengine.h"
+#include "common/language.h"
+#include "common/iman.h"
+#include "common/event.h"
+#include "common/profile.h"
+#include "old/math3d.h"
+#include "object/object.h"
+#include "ui/interface.h"
+#include "old/light.h"
+#include "old/text.h"
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "old/cloud.h"
+#include "old/blitz.h"
+#include "old/planet.h"
+#include "old/sound.h"
+
+
+
+const int SIZEBLOC_TEXTURE = 50;
+const int SIZEBLOC_TRANSFORM = 100;
+const int SIZEBLOC_MINMAX = 5;
+const int SIZEBLOC_LIGHT = 10;
+const int SIZEBLOC_MATERIAL = 100;
+const int SIZEBLOC_TRIANGLE = 200;
+
+
+
+#if 0
+static int debug_blend1 = 1;
+static int debug_blend2 = 3;
+static int debug_blend3 = 8;
+static int debug_blend4 = 0;
+
+static int table_blend[13] =
+{
+ D3DBLEND_ZERO, // 0
+ D3DBLEND_ONE, // 1
+ D3DBLEND_SRCCOLOR, // 2
+ D3DBLEND_INVSRCCOLOR, // 3
+ D3DBLEND_SRCALPHA, // 4
+ D3DBLEND_INVSRCALPHA, // 5
+ D3DBLEND_DESTALPHA, // 6
+ D3DBLEND_INVDESTALPHA, // 7
+ D3DBLEND_DESTCOLOR, // 8
+ D3DBLEND_INVDESTCOLOR, // 9
+ D3DBLEND_SRCALPHASAT, // 10
+ D3DBLEND_BOTHSRCALPHA, // 11
+ D3DBLEND_BOTHINVSRCALPHA, // 12
+};
+#endif
+
+static int s_resol = 0;
+
+
+
+// Converts a FLOAT to a DWORD for use in SetRenderState() calls.
+
+inline DWORD F2DW( FLOAT f )
+{
+ return *((DWORD*)&f);
+}
+
+
+
+
+// Application constructor. Sets attributes for the app.
+
+CD3DEngine::CD3DEngine(CInstanceManager *iMan, CD3DApplication *app)
+{
+ int i;
+
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_ENGINE, this);
+ m_app = app;
+
+ m_light = new CLight(m_iMan, this);
+ m_text = new CText(m_iMan, this);
+ m_particule = new CParticule(m_iMan, this);
+ m_water = new CWater(m_iMan, this);
+ m_cloud = new CCloud(m_iMan, this);
+ m_blitz = new CBlitz(m_iMan, this);
+ m_planet = new CPlanet(m_iMan, this);
+ m_pD3DDevice = 0;
+ m_sound = 0;
+ m_terrain = 0;
+
+ m_dim.x = 640;
+ m_dim.y = 480;
+ m_lastDim = m_dim;
+ m_focus = 0.75f;
+ m_baseTime = 0;
+ m_lastTime = 0;
+ m_absTime = 0.0f;
+ m_rankView = 0;
+ m_ambiantColor[0] = 0x80808080;
+ m_ambiantColor[1] = 0x80808080;
+ m_fogColor[0] = 0xffffffff; // white
+ m_fogColor[1] = 0xffffffff; // white
+ m_deepView[0] = 1000.0f;
+ m_deepView[1] = 1000.0f;
+ m_fogStart[0] = 0.75f;
+ m_fogStart[1] = 0.75f;
+ m_waterAddColor.r = 0.0f;
+ m_waterAddColor.g = 0.0f;
+ m_waterAddColor.b = 0.0f;
+ m_waterAddColor.a = 0.0f;
+ m_bPause = false;
+ m_bRender = true;
+ m_bMovieLock = false;
+ m_bShadow = true;
+ m_bGroundSpot = true;
+ m_bDirty = true;
+ m_bFog = true;
+ m_speed = 1.0f;
+ m_secondTexNum = 0;
+ m_eyeDirH = 0.0f;
+ m_eyeDirV = 0.0f;
+ m_backgroundName[0] = 0; // no background image
+ m_backgroundColorUp = 0;
+ m_backgroundColorDown = 0;
+ m_backgroundCloudUp = 0;
+ m_backgroundCloudDown = 0;
+ m_bBackgroundFull = false;
+ m_bBackgroundQuarter = false;
+ m_bOverFront = true;
+ m_overColor = 0;
+ m_overMode = D3DSTATETCb;
+ m_frontsizeName[0] = 0; // no front image
+ m_hiliteRank[0] = -1; // empty list
+ m_mousePos = Math::Point(0.5f, 0.5f);
+ m_mouseType = D3DMOUSENORM;
+ m_bMouseHide = false;
+ m_imageSurface = 0;
+ m_imageCopy = 0;
+ m_eyePt = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_lookatPt = Math::Vector(0.0f, 0.0f, 1.0f);
+ m_bDrawWorld = true;
+ m_bDrawFront = false;
+ m_limitLOD[0] = 100.0f;
+ m_limitLOD[1] = 200.0f;
+ m_particuleDensity = 1.0f;
+ m_clippingDistance = 1.0f;
+ m_lastClippingDistance = m_clippingDistance;
+ m_objectDetail = 1.0f;
+ m_lastObjectDetail = m_objectDetail;
+ m_terrainVision = 1000.0f;
+ m_gadgetQuantity = 1.0f;
+ m_textureQuality = 1;
+ m_bTotoMode = true;
+ m_bLensMode = true;
+ m_bWaterMode = true;
+ m_bSkyMode = true;
+ m_bBackForce = true;
+ m_bPlanetMode = true;
+ m_bLightMode = true;
+ m_bEditIndentMode = true;
+ m_editIndentValue = 4;
+ m_tracePrecision = 1.0f;
+
+ m_alphaMode = 1;
+ if ( GetProfileInt("Engine", "AlphaMode", i) )
+ {
+ m_alphaMode = i;
+ }
+
+ if ( GetProfileInt("Engine", "StateColor", i) && i != -1 )
+ {
+ m_bForceStateColor = true;
+ m_bStateColor = i;
+ }
+ else
+ {
+ m_bForceStateColor = false;
+ m_bStateColor = false;
+ }
+
+ m_blackSrcBlend[0] = 0;
+ m_blackDestBlend[0] = 0;
+ m_whiteSrcBlend[0] = 0;
+ m_whiteDestBlend[0] = 0;
+ m_diffuseSrcBlend[0] = 0;
+ m_diffuseDestBlend[0] = 0;
+ m_alphaSrcBlend[0] = 0;
+ m_alphaDestBlend[0] = 0;
+
+ if ( GetProfileInt("Engine", "BlackSrcBlend", i) ) m_blackSrcBlend[0] = i;
+ if ( GetProfileInt("Engine", "BlackDestBlend", i) ) m_blackDestBlend[0] = i;
+ if ( GetProfileInt("Engine", "WhiteSrcBlend", i) ) m_whiteSrcBlend[0] = i;
+ if ( GetProfileInt("Engine", "WhiteDestBlend", i) ) m_whiteDestBlend[0] = i;
+ if ( GetProfileInt("Engine", "DiffuseSrcBlend", i) ) m_diffuseSrcBlend[0] = i;
+ if ( GetProfileInt("Engine", "DiffuseDestBlend", i) ) m_diffuseDestBlend[0] = i;
+ if ( GetProfileInt("Engine", "AlphaSrcBlend", i) ) m_alphaSrcBlend[0] = i;
+ if ( GetProfileInt("Engine", "AlphaDestBlend", i) ) m_alphaDestBlend[0] = i;
+
+ m_bUpdateGeometry = false;
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ m_infoText[i][0] = 0;
+ }
+
+ m_objectPointer = 0;
+ MemSpace1(m_objectPointer, 0);
+
+ m_objectParam = (D3DObject*)malloc(sizeof(D3DObject)*D3DMAXOBJECT);
+ ZeroMemory(m_objectParam, sizeof(D3DObject)*D3DMAXOBJECT);
+ m_objectParamTotal = 0;
+
+ m_shadow = (D3DShadow*)malloc(sizeof(D3DShadow)*D3DMAXSHADOW);
+ ZeroMemory(m_shadow, sizeof(D3DShadow)*D3DMAXSHADOW);
+ m_shadowTotal = 0;
+
+ m_groundSpot = (D3DGroundSpot*)malloc(sizeof(D3DGroundSpot)*D3DMAXGROUNDSPOT);
+ ZeroMemory(m_groundSpot, sizeof(D3DGroundSpot)*D3DMAXGROUNDSPOT);
+
+ ZeroMemory(&m_groundMark, sizeof(D3DGroundMark));
+
+ D3DTextr_SetTexturePath("textures\\");
+}
+
+// Application destructor. Free memory.
+
+CD3DEngine::~CD3DEngine()
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ int l1, l2, l3, l4, l5;
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ free(p6);
+ }
+ free(p5);
+ }
+ free(p4);
+ }
+ free(p3);
+ }
+ free(p2);
+ }
+ free(p1);
+
+ delete m_light;
+ delete m_particule;
+ delete m_water;
+ delete m_cloud;
+ delete m_blitz;
+ delete m_planet;
+}
+
+
+
+void CD3DEngine::SetD3DDevice(LPDIRECT3DDEVICE7 device)
+{
+ D3DDEVICEDESC7 ddDesc;
+
+ m_pD3DDevice = device;
+ m_light->SetD3DDevice(device);
+ m_text->SetD3DDevice(device);
+ m_particule->SetD3DDevice(device);
+
+ if ( !m_bForceStateColor )
+ {
+ m_pD3DDevice->GetCaps(&ddDesc);
+ if( ddDesc.dpcTriCaps.dwTextureBlendCaps & D3DPTBLENDCAPS_ADD )
+ {
+ m_bStateColor = true;
+ }
+ else
+ {
+ m_bStateColor = false;
+ }
+ }
+
+ m_blackSrcBlend[1] = D3DBLEND_ONE; // = 2
+ m_blackDestBlend[1] = D3DBLEND_INVSRCCOLOR; // = 4
+ m_whiteSrcBlend[1] = D3DBLEND_DESTCOLOR; // = 9
+ m_whiteDestBlend[1] = D3DBLEND_ZERO; // = 1
+ m_diffuseSrcBlend[1] = D3DBLEND_SRCALPHA; // = 5
+ m_diffuseDestBlend[1] = D3DBLEND_DESTALPHA; // = 7
+ m_alphaSrcBlend[1] = D3DBLEND_ONE; // = 2
+ m_alphaDestBlend[1] = D3DBLEND_INVSRCCOLOR; // = 4
+
+//? if ( !m_bStateColor ) m_whiteDestBlend[1] = D3DBLEND_INVSRCALPHA; // = 6
+
+// Fix for the graphics bug:
+ //if ( m_blackSrcBlend[0] ) m_blackSrcBlend[1] = m_blackSrcBlend[0];
+ //if ( m_blackDestBlend[0] ) m_blackDestBlend[1] = m_blackDestBlend[0];
+ //if ( m_whiteSrcBlend[0] ) m_whiteSrcBlend[1] = m_whiteSrcBlend[0];
+ //if ( m_whiteDestBlend[0] ) m_whiteDestBlend[1] = m_whiteDestBlend[0];
+
+ if ( m_diffuseSrcBlend[0] ) m_diffuseSrcBlend[1] = m_diffuseSrcBlend[0];
+ if ( m_diffuseDestBlend[0] ) m_diffuseDestBlend[1] = m_diffuseDestBlend[0];
+ if ( m_alphaSrcBlend[0] ) m_alphaSrcBlend[1] = m_alphaSrcBlend[0];
+ if ( m_alphaDestBlend[0] ) m_alphaDestBlend[1] = m_alphaDestBlend[0];
+
+#if 0
+ DWORD pass;
+ m_pD3DDevice->ValidateDevice(&pass);
+ char s[100];
+ sprintf(s, "NbPass=%d", pass);
+ SetInfoText(3, s);
+#endif
+}
+
+LPDIRECT3DDEVICE7 CD3DEngine::RetD3DDevice()
+{
+ return m_pD3DDevice;
+}
+
+
+// Gives the pointer to the existing terrain.
+
+void CD3DEngine::SetTerrain(CTerrain* terrain)
+{
+ m_terrain = terrain;
+}
+
+
+// Saving the state of the graphics engine in COLOBOT.INI.
+
+bool CD3DEngine::WriteProfile()
+{
+ SetProfileInt("Engine", "AlphaMode", m_alphaMode);
+
+ if ( m_bForceStateColor )
+ {
+ SetProfileInt("Engine", "StateColor", m_bStateColor);
+ }
+ else
+ {
+ SetProfileInt("Engine", "StateColor", -1);
+ }
+
+ SetProfileInt("Engine", "BlackSrcBlend", m_blackSrcBlend[0]);
+ SetProfileInt("Engine", "BlackDestBlend", m_blackDestBlend[0]);
+ SetProfileInt("Engine", "WhiteSrcBlend", m_whiteSrcBlend[0]);
+ SetProfileInt("Engine", "WhiteDestBlend", m_whiteDestBlend[0]);
+ SetProfileInt("Engine", "DiffuseSrcBlend", m_diffuseSrcBlend[0]);
+ SetProfileInt("Engine", "DiffuseDestBlend", m_diffuseDestBlend[0]);
+ SetProfileInt("Engine", "AlphaSrcBlend", m_alphaSrcBlend[0]);
+ SetProfileInt("Engine", "AlphaDestBlend", m_alphaDestBlend[0]);
+
+ return true;
+}
+
+
+// Setup the app so it can support single-stepping.
+
+void CD3DEngine::TimeInit()
+{
+ m_baseTime = timeGetTime();
+ m_lastTime = 0;
+ m_absTime = 0.0f;
+}
+
+void CD3DEngine::TimeEnterGel()
+{
+ m_stopTime = timeGetTime();
+}
+
+void CD3DEngine::TimeExitGel()
+{
+ m_baseTime += timeGetTime() - m_stopTime;
+}
+
+float CD3DEngine::TimeGet()
+{
+ float aTime, rTime;
+
+ aTime = (timeGetTime()-m_baseTime)*0.001f; // in ms
+ rTime = (aTime - m_lastTime)*m_speed;
+ m_absTime += rTime;
+ m_lastTime = aTime;
+
+ return rTime;
+}
+
+
+void CD3DEngine::SetPause(bool bPause)
+{
+ m_bPause = bPause;
+}
+
+bool CD3DEngine::RetPause()
+{
+ return m_bPause;
+}
+
+
+void CD3DEngine::SetMovieLock(bool bLock)
+{
+ m_bMovieLock = bLock;
+}
+
+bool CD3DEngine::RetMovieLock()
+{
+ return m_bMovieLock;
+}
+
+
+void CD3DEngine::SetShowStat(bool bShow)
+{
+ m_app->SetShowStat(bShow);
+}
+
+bool CD3DEngine::RetShowStat()
+{
+ return m_app->RetShowStat();
+}
+
+
+void CD3DEngine::SetRenderEnable(bool bEnable)
+{
+ m_bRender = bEnable;
+}
+
+
+// Prepare a structure to add D3DObjLevel6
+// qq D3DVERTEX2 elements.
+
+void CD3DEngine::MemSpace6(D3DObjLevel6 *&p, int nb)
+{
+ D3DObjLevel6* pp;
+ int total, size;
+
+ if ( p == 0 )
+ {
+ total = SIZEBLOC_TRIANGLE+nb;
+ size = sizeof(D3DObjLevel6)+sizeof(D3DVERTEX2)*(total-1);
+ p = (D3DObjLevel6*)malloc(size);
+ ZeroMemory(p, size);
+ p->totalPossible = total;
+ return;
+ }
+
+ if ( p->totalUsed+nb > p->totalPossible )
+ {
+ total = p->totalPossible+SIZEBLOC_TRIANGLE+nb;
+ size = sizeof(D3DObjLevel6)+sizeof(D3DVERTEX2)*(total-1);
+ pp = (D3DObjLevel6*)malloc(size);
+ ZeroMemory(pp, size);
+ CopyMemory(pp, p, sizeof(D3DObjLevel6)+sizeof(D3DVERTEX2)*(p->totalPossible-1));
+ pp->totalPossible = total;
+ free(p);
+ p = pp;
+ }
+}
+
+// Prepare a structure to add D3DObjLevel5
+// qq elements D3DObjLevel6.
+
+void CD3DEngine::MemSpace5(D3DObjLevel5 *&p, int nb)
+{
+ D3DObjLevel5* pp;
+ int total, size;
+
+ if ( p == 0 )
+ {
+ total = SIZEBLOC_MATERIAL+nb;
+ size = sizeof(D3DObjLevel5)+sizeof(D3DObjLevel6*)*(total-1);
+ p = (D3DObjLevel5*)malloc(size);
+ ZeroMemory(p, size);
+ p->totalPossible = total;
+ return;
+ }
+
+ if ( p->totalUsed+nb > p->totalPossible )
+ {
+ total = p->totalPossible+SIZEBLOC_MATERIAL+nb;
+ size = sizeof(D3DObjLevel5)+sizeof(D3DObjLevel6*)*(total-1);
+ pp = (D3DObjLevel5*)malloc(size);
+ ZeroMemory(pp, size);
+ CopyMemory(pp, p, sizeof(D3DObjLevel5)+sizeof(D3DObjLevel6*)*(p->totalPossible-1));
+ pp->totalPossible = total;
+ free(p);
+ p = pp;
+ }
+}
+
+// Prepare a structure to add D3DObjLevel4
+// qq D3DObjLevel5 elements.
+
+void CD3DEngine::MemSpace4(D3DObjLevel4 *&p, int nb)
+{
+ D3DObjLevel4* pp;
+ int total, size;
+
+ if ( p == 0 )
+ {
+ total = SIZEBLOC_LIGHT+nb;
+ size = sizeof(D3DObjLevel4)+sizeof(D3DObjLevel5*)*(total-1);
+ p = (D3DObjLevel4*)malloc(size);
+ ZeroMemory(p, size);
+ p->totalPossible = total;
+ return;
+ }
+
+ if ( p->totalUsed+nb > p->totalPossible )
+ {
+ total = p->totalPossible+SIZEBLOC_LIGHT+nb;
+ size = sizeof(D3DObjLevel4)+sizeof(D3DObjLevel5*)*(total-1);
+ pp = (D3DObjLevel4*)malloc(size);
+ ZeroMemory(pp, size);
+ CopyMemory(pp, p, sizeof(D3DObjLevel4)+sizeof(D3DObjLevel5*)*(p->totalPossible-1));
+ pp->totalPossible = total;
+ free(p);
+ p = pp;
+ }
+}
+
+// Prepare a structure to add D3DObjLevel3
+// qq D3DObjLevel4 elements.
+
+void CD3DEngine::MemSpace3(D3DObjLevel3 *&p, int nb)
+{
+ D3DObjLevel3* pp;
+ int total, size;
+
+ if ( p == 0 )
+ {
+ total = SIZEBLOC_MINMAX+nb;
+ size = sizeof(D3DObjLevel3)+sizeof(D3DObjLevel4*)*(total-1);
+ p = (D3DObjLevel3*)malloc(size);
+ ZeroMemory(p, size);
+ p->totalPossible = total;
+ return;
+ }
+
+ if ( p->totalUsed+nb > p->totalPossible )
+ {
+ total = p->totalPossible+SIZEBLOC_MINMAX+nb;
+ size = sizeof(D3DObjLevel3)+sizeof(D3DObjLevel4*)*(total-1);
+ pp = (D3DObjLevel3*)malloc(size);
+ ZeroMemory(pp, size);
+ CopyMemory(pp, p, sizeof(D3DObjLevel3)+sizeof(D3DObjLevel4*)*(p->totalPossible-1));
+ pp->totalPossible = total;
+ free(p);
+ p = pp;
+ }
+}
+
+// Prepare a structure to add D3DObjLevel2
+// qq D3DObjLevel3 elements.
+
+void CD3DEngine::MemSpace2(D3DObjLevel2 *&p, int nb)
+{
+ D3DObjLevel2* pp;
+ int total, size;
+
+ if ( p == 0 )
+ {
+ total = SIZEBLOC_TRANSFORM+nb;
+ size = sizeof(D3DObjLevel2)+sizeof(D3DObjLevel3*)*(total-1);
+ p = (D3DObjLevel2*)malloc(size);
+ ZeroMemory(p, size);
+ p->totalPossible = total;
+ return;
+ }
+
+ if ( p->totalUsed+nb > p->totalPossible )
+ {
+ total = p->totalPossible+SIZEBLOC_TRANSFORM+nb;
+ size = sizeof(D3DObjLevel2)+sizeof(D3DObjLevel3*)*(total-1);
+ pp = (D3DObjLevel2*)malloc(size);
+ ZeroMemory(pp, size);
+ CopyMemory(pp, p, sizeof(D3DObjLevel2)+sizeof(D3DObjLevel3*)*(p->totalPossible-1));
+ pp->totalPossible = total;
+ free(p);
+ p = pp;
+ }
+}
+
+// Prepare a structure to add D3DObjLevel1
+// qq D3DObjLevel2 elements.
+
+void CD3DEngine::MemSpace1(D3DObjLevel1 *&p, int nb)
+{
+ D3DObjLevel1* pp;
+ int total, size;
+
+ if ( p == 0 )
+ {
+ total = SIZEBLOC_TEXTURE+nb;
+ size = sizeof(D3DObjLevel1)+sizeof(D3DObjLevel2*)*(total-1);
+ p = (D3DObjLevel1*)malloc(size);
+ ZeroMemory(p, size);
+ p->totalPossible = total;
+ return;
+ }
+
+ if ( p->totalUsed+nb > p->totalPossible )
+ {
+ total = p->totalPossible+SIZEBLOC_TEXTURE+nb;
+ size = sizeof(D3DObjLevel1)+sizeof(D3DObjLevel2*)*(total-1);
+ pp = (D3DObjLevel1*)malloc(size);
+ ZeroMemory(pp, size);
+ CopyMemory(pp, p, sizeof(D3DObjLevel1)+sizeof(D3DObjLevel2*)*(p->totalPossible-1));
+ pp->totalPossible = total;
+ free(p);
+ p = pp;
+ }
+}
+
+
+// Returns the number of objects that can still be created.
+
+int CD3DEngine::RetRestCreate()
+{
+ return D3DMAXOBJECT-m_objectParamTotal-2;
+}
+
+// Creates a new object. Returns its rank or -1 on error.
+
+int CD3DEngine::CreateObject()
+{
+ Math::Matrix mat;
+ int i;
+
+ for ( i=0 ; i<D3DMAXOBJECT ; i++ )
+ {
+ if ( m_objectParam[i].bUsed == false )
+ {
+ ZeroMemory(&m_objectParam[i], sizeof(D3DObject));
+ m_objectParam[i].bUsed = true;
+
+ mat.LoadIdentity();
+ SetObjectTransform(i, mat);
+
+ m_objectParam[i].bDrawWorld = true;
+ m_objectParam[i].distance = 0.0f;
+ m_objectParam[i].bboxMin = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_objectParam[i].bboxMax = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_objectParam[i].shadowRank = -1;
+
+ if ( i >= m_objectParamTotal )
+ {
+ m_objectParamTotal = i+1;
+ }
+ return i;
+ }
+ }
+ OutputDebugString("CD3DEngine::CreateObject() -> Too many object\n");
+ return -1;
+}
+
+
+// Removes all objects.
+
+void CD3DEngine::FlushObject()
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ int l1, l2, l3, l4, l5, i;
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ free(p6);
+ }
+ free(p5);
+ }
+ free(p4);
+ }
+ free(p3);
+ }
+ free(p2);
+ p1->table[l1] = 0;
+ }
+ p1->totalUsed = 0;
+
+ for ( i=0 ; i<D3DMAXOBJECT ; i++ )
+ {
+ m_objectParam[i].bUsed = false;
+ }
+ m_objectParamTotal = 0;
+
+ ZeroMemory(m_shadow, sizeof(D3DShadow)*D3DMAXSHADOW);
+ m_shadowTotal = 0;
+
+ GroundSpotFlush();
+}
+
+// Destroys an existing object.
+
+bool CD3DEngine::DeleteObject(int objRank)
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ int l1, l2, l3, l4, l5, i;
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ if ( p3->objRank != objRank ) continue;
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ free(p6);
+ }
+ free(p5);
+ }
+ free(p4);
+ }
+ free(p3);
+ p2->table[l2] = 0;
+ }
+ }
+
+ ShadowDelete(objRank); // removes the shadow
+
+ m_objectParam[objRank].bUsed = false;
+
+ m_objectParamTotal = 0;
+ for ( i=0 ; i<D3DMAXOBJECT ; i++ )
+ {
+ if ( m_objectParam[i].bUsed )
+ {
+ m_objectParamTotal = i+1;
+ }
+ }
+
+ return true;
+}
+
+
+// Indicates whether an object should be drawn underneath the interface.
+
+bool CD3DEngine::SetDrawWorld(int objRank, bool bDraw)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ m_objectParam[objRank].bDrawWorld = bDraw;
+ return true;
+}
+
+// Indicates whether an object should be drawn over the interface.
+
+bool CD3DEngine::SetDrawFront(int objRank, bool bDraw)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ m_objectParam[objRank].bDrawFront = bDraw;
+ return true;
+}
+
+
+// Prepare Level 1 to add a triangle.
+
+D3DObjLevel2* CD3DEngine::AddLevel1(D3DObjLevel1 *&p1, char* texName1, char* texName2)
+{
+ D3DObjLevel2* p2;
+ int l1;
+
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ if ( strcmp(p2->texName1, texName1) == 0 &&
+ strcmp(p2->texName2, texName2) == 0 )
+ {
+ MemSpace2(p1->table[l1], 1);
+ return p1->table[l1];
+ }
+ }
+
+ MemSpace1(p1, 1);
+ l1 = p1->totalUsed++;
+ p1->table[l1] = 0;
+
+ MemSpace2(p1->table[l1], 1);
+ strcpy(p1->table[l1]->texName1, texName1);
+ strcpy(p1->table[l1]->texName2, texName2);
+ return p1->table[l1];
+}
+
+// Prepare Level 2 to add a triangle.
+
+D3DObjLevel3* CD3DEngine::AddLevel2(D3DObjLevel2 *&p2, int objRank)
+{
+ D3DObjLevel3* p3;
+ int l2;
+
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ if ( p3->objRank == objRank )
+ {
+ MemSpace3(p2->table[l2], 1);
+ return p2->table[l2];
+ }
+ }
+
+ MemSpace2(p2, 1);
+ l2 = p2->totalUsed++;
+ p2->table[l2] = 0;
+
+ MemSpace3(p2->table[l2], 1);
+ p2->table[l2]->objRank = objRank;
+ return p2->table[l2];
+}
+
+// Prepare Level 3 to add a triangle.
+
+D3DObjLevel4* CD3DEngine::AddLevel3(D3DObjLevel3 *&p3, float min, float max)
+{
+ D3DObjLevel4* p4;
+ int l3;
+
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ if ( p4->min == min && p4->max == max )
+ {
+ MemSpace4(p3->table[l3], 1);
+ return p3->table[l3];
+ }
+ }
+
+ MemSpace3(p3, 1);
+ l3 = p3->totalUsed++;
+ p3->table[l3] = 0;
+
+ MemSpace4(p3->table[l3], 1);
+ p3->table[l3]->min = min;
+ p3->table[l3]->max = max;
+ return p3->table[l3];
+}
+
+// Prepare Level 4 to add a triangle.
+
+D3DObjLevel5* CD3DEngine::AddLevel4(D3DObjLevel4 *&p4, int reserve)
+{
+ D3DObjLevel5* p5;
+ int l4;
+
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ if ( p5->reserve == reserve )
+ {
+ MemSpace5(p4->table[l4], 1);
+ return p4->table[l4];
+ }
+ }
+
+ MemSpace4(p4, 1);
+ l4 = p4->totalUsed++;
+ p4->table[l4] = 0;
+
+ MemSpace5(p4->table[l4], 1);
+ p4->table[l4]->reserve = reserve;
+ return p4->table[l4];
+}
+
+// Prepares Level 5 to add vertices.
+
+D3DObjLevel6* CD3DEngine::AddLevel5(D3DObjLevel5 *&p5, D3DTypeTri type,
+ const D3DMATERIAL7 &mat, int state,
+ int nb)
+{
+ D3DObjLevel6* p6;
+ int l5;
+
+ if ( type == D3DTYPE6T )
+ {
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ if ( p6->type == type &&
+ memcmp(&p6->material, &mat, sizeof(D3DMATERIAL7)) == 0 &&
+ p6->state == state )
+ {
+ MemSpace6(p5->table[l5], nb);
+ return p5->table[l5];
+ }
+ }
+ }
+
+ MemSpace5(p5, 1);
+ l5 = p5->totalUsed++;
+ p5->table[l5] = 0;
+
+ MemSpace6(p5->table[l5], nb);
+ p5->table[l5]->type = type;
+ p5->table[l5]->material = mat;
+ p5->table[l5]->state = state;
+ return p5->table[l5];
+}
+
+// Adds one or more triangles to an existing object.
+// The number must be divisible by 3.
+
+bool CD3DEngine::AddTriangle(int objRank, D3DVERTEX2* vertex, int nb,
+ const D3DMATERIAL7 &mat, int state,
+ char* texName1, char* texName2,
+ float min, float max, bool bGlobalUpdate)
+{
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ int i;
+
+ m_lastDim = m_dim;
+ m_lastObjectDetail = m_objectDetail;
+ m_lastClippingDistance = m_clippingDistance;
+
+ p2 = AddLevel1(m_objectPointer, texName1, texName2);
+ p3 = AddLevel2(p2, objRank);
+ p4 = AddLevel3(p3, min, max);
+ p5 = AddLevel4(p4, 0);
+ p6 = AddLevel5(p5, D3DTYPE6T, mat, state, nb); // place for number of vertex
+
+ CopyMemory(&p6->vertex[p6->totalUsed], vertex, sizeof(D3DVERTEX2)*nb);
+ p6->totalUsed += nb;
+
+ if ( bGlobalUpdate )
+ {
+ m_bUpdateGeometry = true;
+ }
+ else
+ {
+ for ( i=0 ; i<nb ; i++ )
+ {
+ m_objectParam[objRank].bboxMin.x = Math::Min(vertex[i].x, m_objectParam[objRank].bboxMin.x);
+ m_objectParam[objRank].bboxMin.y = Math::Min(vertex[i].y, m_objectParam[objRank].bboxMin.y);
+ m_objectParam[objRank].bboxMin.z = Math::Min(vertex[i].z, m_objectParam[objRank].bboxMin.z);
+ m_objectParam[objRank].bboxMax.x = Math::Max(vertex[i].x, m_objectParam[objRank].bboxMax.x);
+ m_objectParam[objRank].bboxMax.y = Math::Max(vertex[i].y, m_objectParam[objRank].bboxMax.y);
+ m_objectParam[objRank].bboxMax.z = Math::Max(vertex[i].z, m_objectParam[objRank].bboxMax.z);
+ }
+
+ m_objectParam[objRank].radius = Math::Max(m_objectParam[objRank].bboxMin.Length(),
+ m_objectParam[objRank].bboxMax.Length());
+ }
+ m_objectParam[objRank].totalTriangle += nb/3;
+
+ return true;
+}
+
+// Adds a surface consisting of triangles joined.
+
+bool CD3DEngine::AddSurface(int objRank, D3DVERTEX2* vertex, int nb,
+ const D3DMATERIAL7 &mat, int state,
+ char* texName1, char* texName2,
+ float min, float max, bool bGlobalUpdate)
+{
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ int i;
+
+ p2 = AddLevel1(m_objectPointer, texName1, texName2);
+ p3 = AddLevel2(p2, objRank);
+ p4 = AddLevel3(p3, min, max);
+ p5 = AddLevel4(p4, 0);
+ p6 = AddLevel5(p5, D3DTYPE6S, mat, state, nb); // place for number of vertex
+
+ CopyMemory(&p6->vertex[p6->totalUsed], vertex, sizeof(D3DVERTEX2)*nb);
+ p6->totalUsed += nb;
+
+ if ( bGlobalUpdate )
+ {
+ m_bUpdateGeometry = true;
+ }
+ else
+ {
+ for ( i=0 ; i<nb ; i++ )
+ {
+ m_objectParam[objRank].bboxMin.x = Math::Min(vertex[i].x, m_objectParam[objRank].bboxMin.x);
+ m_objectParam[objRank].bboxMin.y = Math::Min(vertex[i].y, m_objectParam[objRank].bboxMin.y);
+ m_objectParam[objRank].bboxMin.z = Math::Min(vertex[i].z, m_objectParam[objRank].bboxMin.z);
+ m_objectParam[objRank].bboxMax.x = Math::Max(vertex[i].x, m_objectParam[objRank].bboxMax.x);
+ m_objectParam[objRank].bboxMax.y = Math::Max(vertex[i].y, m_objectParam[objRank].bboxMax.y);
+ m_objectParam[objRank].bboxMax.z = Math::Max(vertex[i].z, m_objectParam[objRank].bboxMax.z);
+ }
+
+ m_objectParam[objRank].radius = Math::Max(m_objectParam[objRank].bboxMin.Length(),
+ m_objectParam[objRank].bboxMax.Length());
+ }
+ m_objectParam[objRank].totalTriangle += nb-2;
+
+ return true;
+}
+
+// Adds a surface consisting of triangles joined.
+// The buffer is not copied.
+
+bool CD3DEngine::AddQuick(int objRank, D3DObjLevel6* buffer,
+ char* texName1, char* texName2,
+ float min, float max, bool bGlobalUpdate)
+{
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ int l5, i;
+
+ p2 = AddLevel1(m_objectPointer, texName1, texName2);
+ p3 = AddLevel2(p2, objRank);
+ p4 = AddLevel3(p3, min, max);
+ p5 = AddLevel4(p4, 0);
+
+ MemSpace5(p5, 1);
+ l5 = p5->totalUsed++;
+ p5->table[l5] = buffer;
+
+ if ( bGlobalUpdate )
+ {
+ m_bUpdateGeometry = true;
+ }
+ else
+ {
+ for ( i=0 ; i<buffer->totalUsed ; i++ )
+ {
+ m_objectParam[objRank].bboxMin.x = Math::Min(buffer->vertex[i].x, m_objectParam[objRank].bboxMin.x);
+ m_objectParam[objRank].bboxMin.y = Math::Min(buffer->vertex[i].y, m_objectParam[objRank].bboxMin.y);
+ m_objectParam[objRank].bboxMin.z = Math::Min(buffer->vertex[i].z, m_objectParam[objRank].bboxMin.z);
+ m_objectParam[objRank].bboxMax.x = Math::Max(buffer->vertex[i].x, m_objectParam[objRank].bboxMax.x);
+ m_objectParam[objRank].bboxMax.y = Math::Max(buffer->vertex[i].y, m_objectParam[objRank].bboxMax.y);
+ m_objectParam[objRank].bboxMax.z = Math::Max(buffer->vertex[i].z, m_objectParam[objRank].bboxMax.z);
+ }
+
+ m_objectParam[objRank].radius = Math::Max(m_objectParam[objRank].bboxMin.Length(),
+ m_objectParam[objRank].bboxMax.Length());
+ }
+ m_objectParam[objRank].totalTriangle += buffer->totalUsed-2;
+
+ return true;
+}
+
+
+// Looking for a list of triangles.
+
+void CD3DEngine::ChangeLOD()
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ int l1, l2, l3;
+ float oldLimit[2], newLimit[2];
+ float oldTerrain, newTerrain;
+
+ oldLimit[0] = RetLimitLOD(0, true);
+ oldLimit[1] = RetLimitLOD(1, true);
+
+ newLimit[0] = RetLimitLOD(0, false);
+ newLimit[1] = RetLimitLOD(1, false);
+
+ oldTerrain = m_terrainVision*m_lastClippingDistance;
+ newTerrain = m_terrainVision*m_clippingDistance;
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+
+ if ( Math::IsEqual(p4->min, 0.0f ) &&
+ Math::IsEqual(p4->max, oldLimit[0]) )
+ {
+ p4->max = newLimit[0];
+ }
+ else if ( Math::IsEqual(p4->min, oldLimit[0]) &&
+ Math::IsEqual(p4->max, oldLimit[1]) )
+ {
+ p4->min = newLimit[0];
+ p4->max = newLimit[1];
+ }
+ else if ( Math::IsEqual(p4->min, oldLimit[1]) &&
+ Math::IsEqual(p4->max, 1000000.0f ) )
+ {
+ p4->min = newLimit[1];
+ }
+ else if ( Math::IsEqual(p4->min, 0.0f ) &&
+ Math::IsEqual(p4->max, oldTerrain) )
+ {
+ p4->max = newTerrain;
+ }
+ }
+ }
+ }
+
+ m_lastDim = m_dim;
+ m_lastObjectDetail = m_objectDetail;
+ m_lastClippingDistance = m_clippingDistance;
+}
+
+// Looking for a list of triangles.
+
+D3DObjLevel6* CD3DEngine::SearchTriangle(int objRank,
+ const D3DMATERIAL7 &mat, int state,
+ char* texName1, char* texName2,
+ float min, float max)
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ int l1, l2, l3, l4, l5;
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+//? if ( strcmp(p2->texName1, texName1) != 0 ||
+//? strcmp(p2->texName2, texName2) != 0 ) continue;
+ if ( strcmp(p2->texName1, texName1) != 0 ) continue;
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ if ( p3->objRank != objRank ) continue;
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ if ( p4->min != min ||
+ p4->max != max ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+//? if ( p6->state != state ||
+ if ( (p6->state&(~(D3DSTATEDUALb|D3DSTATEDUALw))) != state ||
+ memcmp(&p6->material, &mat, sizeof(D3DMATERIAL7)) != 0 ) continue;
+ return p6;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+// Secondary changes the texture of an object.
+
+bool CD3DEngine::ChangeSecondTexture(int objRank, char* texName2)
+{
+ D3DObjLevel2* newp2;
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ int l1, l2;
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ if ( strcmp(p2->texName2, texName2) == 0 ) continue; // already new
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ if ( p3->objRank != objRank ) continue;
+
+ newp2 = AddLevel1(m_objectPointer, p2->texName1, texName2);
+
+ if ( newp2->totalUsed >= newp2->totalPossible ) continue; // to do better!!!
+ newp2->table[newp2->totalUsed++] = p3;
+
+ p2->table[l2] = 0;
+ }
+ }
+ return true;
+}
+
+
+// Returns the number of triangles of the object.
+
+int CD3DEngine::RetTotalTriangles(int objRank)
+{
+ return m_objectParam[objRank].totalTriangle;
+}
+
+// Return qq triangles of an object.
+// qq triangles used to extract an object that explodes.
+// "Percent" is between 0 and 1.
+
+int CD3DEngine::GetTriangles(int objRank, float min, float max,
+ D3DTriangle* buffer, int size, float percent)
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ D3DVERTEX2* pv;
+ int l1, l2, l3, l4, l5, l6, i, rank;
+
+ rank = 0;
+ i = 0;
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+//? if ( p2->texName[0] == 0 ) continue;
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ if ( p3->objRank != objRank ) continue;
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ if ( p4->min != min ||
+ p4->max != max ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ if ( p6->type == D3DTYPE6T )
+ {
+ pv = &p6->vertex[0];
+ for ( l6=0 ; l6<p6->totalUsed/3 ; l6++ )
+ {
+ if ( (float)i/rank <= percent )
+ {
+ if ( i >= size ) break;
+ buffer[i].triangle[0] = pv[0];
+ buffer[i].triangle[1] = pv[1];
+ buffer[i].triangle[2] = pv[2];
+ buffer[i].material = p6->material;
+ buffer[i].state = p6->state;
+ strcpy(buffer[i].texName1, p2->texName1);
+ strcpy(buffer[i].texName2, p2->texName2);
+ i ++;
+ }
+ rank ++;
+ pv += 3;
+ }
+ }
+ if ( p6->type == D3DTYPE6S )
+ {
+ pv = &p6->vertex[0];
+ for ( l6=0 ; l6<p6->totalUsed-2 ; l6++ )
+ {
+ if ( (float)i/rank <= percent )
+ {
+ if ( i >= size ) break;
+ buffer[i].triangle[0] = pv[0];
+ buffer[i].triangle[1] = pv[1];
+ buffer[i].triangle[2] = pv[2];
+ buffer[i].material = p6->material;
+ buffer[i].state = p6->state;
+ strcpy(buffer[i].texName1, p2->texName1);
+ strcpy(buffer[i].texName2, p2->texName2);
+ i ++;
+ }
+ rank ++;
+ pv += 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return i;
+}
+
+// Give the box of an object.
+
+bool CD3DEngine::GetBBox(int objRank, Math::Vector &min, Math::Vector &max)
+{
+ min = m_objectParam[objRank].bboxMin;
+ max = m_objectParam[objRank].bboxMax;
+ return true;
+}
+
+
+// Change the texture mapping for a list of triangles.
+
+bool CD3DEngine::ChangeTextureMapping(int objRank,
+ const D3DMATERIAL7 &mat, int state,
+ char* texName1, char* texName2,
+ float min, float max,
+ D3DMaping mode,
+ float au, float bu,
+ float av, float bv)
+{
+ D3DObjLevel6* p6;
+ D3DVERTEX2* pv;
+ int l6, nb;
+
+ p6 = SearchTriangle(objRank, mat, state, texName1, texName2, min, max);
+ if ( p6 == 0 ) return false;
+
+ pv = &p6->vertex[0];
+ nb = p6->totalUsed;
+
+ if ( mode == D3DMAPPINGX )
+ {
+ for ( l6=0 ; l6<nb ; l6++ )
+ {
+ pv->tu = pv->z*au+bu;
+ pv->tv = pv->y*av+bv;
+ pv ++;
+ }
+ }
+
+ if ( mode == D3DMAPPINGY )
+ {
+ for ( l6=0 ; l6<nb ; l6++ )
+ {
+ pv->tu = pv->x*au+bu;
+ pv->tv = pv->z*av+bv;
+ pv ++;
+ }
+ }
+
+ if ( mode == D3DMAPPINGZ )
+ {
+ for ( l6=0 ; l6<nb ; l6++ )
+ {
+ pv->tu = pv->x*au+bu;
+ pv->tv = pv->y*av+bv;
+ pv ++;
+ }
+ }
+
+ if ( mode == D3DMAPPING1X )
+ {
+ for ( l6=0 ; l6<nb ; l6++ )
+ {
+ pv->tu = pv->x*au+bu;
+ pv ++;
+ }
+ }
+
+ if ( mode == D3DMAPPING1Y )
+ {
+ for ( l6=0 ; l6<nb ; l6++ )
+ {
+ pv->tv = pv->y*au+bu;
+ pv ++;
+ }
+ }
+
+ if ( mode == D3DMAPPING1Z )
+ {
+ for ( l6=0 ; l6<nb ; l6++ )
+ {
+ pv->tu = pv->z*au+bu;
+ pv ++;
+ }
+ }
+
+ return true;
+}
+
+// Change the texture mapping for a list of triangles
+// to simulate a caterpillar that turns.
+// Only the mapping as "u" is changed.
+//
+// pos: position on the periphery [p]
+// tl: length repetitive element of the texture [t]
+// ts: beginning of the texture[t]
+// tt: total width of the texture [t]
+//
+// [p] = distance in the 3D world
+// [t] = position in the texture (pixels)
+
+// ^ y 5
+// | 6 o---------o 4
+// | / \
+// | o o
+// | 7 | | 3
+// | o current o
+// | \ | /
+// | 0 o---------o 2
+// | 1
+// -o-----------------------> x
+// |
+//
+// Quand l6=1 :
+// 0 1 2 3 4 ... 7
+// o--o---------o--o--o--o-//-o--o development track
+// |ps| |
+// <--> pe |
+// <------------>
+//
+// Texture :
+// o---------------o
+// | |
+// | o-o-o-o-o |
+// | | | | | |<--- texture of the track
+// | o-o-o-o-o |
+// | | | tl |
+// | ->|-|<--- |
+// | | |
+// o-----|---------o--> u
+// | ts | |
+// <-----> tt |
+// <--------------->
+
+bool CD3DEngine::TrackTextureMapping(int objRank,
+ const D3DMATERIAL7 &mat, int state,
+ char* texName1, char* texName2,
+ float min, float max,
+ D3DMaping mode, float pos, float factor,
+ float tl, float ts, float tt)
+{
+ D3DObjLevel6* p6;
+ D3DVERTEX2* pv;
+ Math::Vector current;
+ float ps, pe, pps, ppe, offset;
+ int l6, nb, i, j, s, e;
+ int is[6], ie[6];
+
+ p6 = SearchTriangle(objRank, mat, state, texName1, texName2, min, max);
+ if ( p6 == 0 ) return false;
+
+ pv = &p6->vertex[0];
+ nb = p6->totalUsed;
+
+ if ( nb < 12 || nb%6 != 0 ) return false;
+
+ while ( pos < 0.0f )
+ {
+ pos += 1000000.0f; // never negative!
+ }
+
+ for ( i=0 ; i<6 ; i++ )
+ {
+ for ( j=0 ; j<6 ; j++ )
+ {
+ if ( pv[i].x == pv[j+6].x &&
+ pv[i].y == pv[j+6].y )
+ {
+ current.x = pv[i].x; // position end link
+ current.y = pv[i].y;
+ break;
+ }
+ }
+ }
+
+ ps = 0.0f; // start position on the periphery
+ for ( l6=0 ; l6<nb/6 ; l6++ )
+ {
+ s = e = 0;
+ for ( i=0 ; i<6 ; i++ )
+ {
+ if ( fabs(pv[i].x-current.x) < 0.0001f &&
+ fabs(pv[i].y-current.y) < 0.0001f )
+ {
+ ie[e++] = i;
+ }
+ else
+ {
+ is[s++] = i;
+ }
+ }
+ if ( s == 3 && e == 3 )
+ {
+ pe = ps+Math::Point(pv[is[0]].x-pv[ie[0]].x,
+ pv[is[0]].y-pv[ie[0]].y).Length() / factor; // end position on the periphery
+
+ pps = ps+pos;
+ ppe = pe+pos;
+ offset = (float)((int)pps);
+ pps -= offset;
+ ppe -= offset;
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ pv[is[i]].tu = ((pps*tl)+ts)/tt;
+ pv[ie[i]].tu = ((ppe*tl)+ts)/tt;
+ }
+ }
+
+ if ( l6 >= (nb/6)-1 ) break;
+ for ( i=0 ; i<6 ; i++ )
+ {
+ if ( fabs(pv[i+6].x-current.x) > 0.0001f ||
+ fabs(pv[i+6].y-current.y) > 0.0001f )
+ {
+ current.x = pv[i+6].x; // end next link
+ current.y = pv[i+6].y;
+ break;
+ }
+ }
+ ps = pe; // following start position on the periphery
+ pv += 6;
+ }
+
+ return true;
+}
+
+
+// Updates all the geometric parameters of objects.
+
+void CD3DEngine::UpdateGeometry()
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ int l1, l2, l3, l4, l5, objRank, i;
+
+ if ( !m_bUpdateGeometry ) return;
+
+ for ( i=0 ; i<m_objectParamTotal ; i++ )
+ {
+ m_objectParam[i].bboxMin.x = 0;
+ m_objectParam[i].bboxMin.y = 0;
+ m_objectParam[i].bboxMin.z = 0;
+ m_objectParam[i].bboxMax.x = 0;
+ m_objectParam[i].bboxMax.y = 0;
+ m_objectParam[i].bboxMax.z = 0;
+ m_objectParam[i].radius = 0;
+ }
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ objRank = p3->objRank;
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+
+ for ( i=0 ; i<p6->totalUsed ; i++ )
+ {
+ m_objectParam[objRank].bboxMin.x = Math::Min(p6->vertex[i].x, m_objectParam[objRank].bboxMin.x);
+ m_objectParam[objRank].bboxMin.y = Math::Min(p6->vertex[i].y, m_objectParam[objRank].bboxMin.y);
+ m_objectParam[objRank].bboxMin.z = Math::Min(p6->vertex[i].z, m_objectParam[objRank].bboxMin.z);
+ m_objectParam[objRank].bboxMax.x = Math::Max(p6->vertex[i].x, m_objectParam[objRank].bboxMax.x);
+ m_objectParam[objRank].bboxMax.y = Math::Max(p6->vertex[i].y, m_objectParam[objRank].bboxMax.y);
+ m_objectParam[objRank].bboxMax.z = Math::Max(p6->vertex[i].z, m_objectParam[objRank].bboxMax.z);
+ }
+
+ m_objectParam[objRank].radius = Math::Max(m_objectParam[objRank].bboxMin.Length(),
+ m_objectParam[objRank].bboxMax.Length());
+ }
+ }
+ }
+ }
+ }
+
+ m_bUpdateGeometry = false;
+}
+
+
+// Determines whether an object is visible, even partially.
+// Transformation of "world" must be done​​!
+
+bool CD3DEngine::IsVisible(int objRank)
+{
+ Math::Vector center;
+ DWORD flags;
+ float radius;
+
+ radius = m_objectParam[objRank].radius;
+ center = Math::Vector(0.0f, 0.0f, 0.0f);
+ {
+ D3DVECTOR centerD3D = VEC_TO_D3DVEC(center);
+ m_pD3DDevice->ComputeSphereVisibility(&centerD3D, &radius, 1, 0, &flags);
+ }
+
+ if ( flags & D3DSTATUS_CLIPINTERSECTIONALL )
+ {
+ m_objectParam[objRank].bVisible = false;
+ return false;
+ }
+ m_objectParam[objRank].bVisible = true;
+ return true;
+}
+
+
+// Detects the target object with the mouse.
+// Returns the rank of the object or -1.
+
+int CD3DEngine::DetectObject(Math::Point mouse)
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ D3DVERTEX2* pv;
+ int l1, l2, l3, l4, l5, i, objRank, nearest;
+ float dist, min;
+
+ min = 1000000.0f;
+ nearest = -1;
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ objRank = p3->objRank;
+ if ( m_objectParam[objRank].type == TYPETERRAIN ) continue;
+ if ( !DetectBBox(objRank, mouse) ) continue;
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ if ( p4->min != 0.0f ) continue; // LOD B or C?
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+
+ if ( p6->type == D3DTYPE6T )
+ {
+ pv = &p6->vertex[0];
+ for ( i=0 ; i<p6->totalUsed/3 ; i++ )
+ {
+ if ( DetectTriangle(mouse, pv, objRank, dist) &&
+ dist < min )
+ {
+ min = dist;
+ nearest = objRank;
+ }
+ pv += 3;
+ }
+ }
+ if ( p6->type == D3DTYPE6S )
+ {
+ pv = &p6->vertex[0];
+ for ( i=0 ; i<p6->totalUsed-2 ; i++ )
+ {
+ if ( DetectTriangle(mouse, pv, objRank, dist) &&
+ dist < min )
+ {
+ min = dist;
+ nearest = objRank;
+ }
+ pv += 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return nearest;
+}
+
+// Detects whether the mouse is in a triangle.
+
+bool CD3DEngine::DetectTriangle(Math::Point mouse, D3DVERTEX2 *triangle,
+ int objRank, float &dist)
+{
+ Math::Vector p2D[3], p3D;
+ Math::Point a, b, c;
+ int i;
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ p3D.x = triangle[i].x;
+ p3D.y = triangle[i].y;
+ p3D.z = triangle[i].z;
+ if ( !TransformPoint(p2D[i], objRank, p3D) ) return false;
+ }
+
+ if ( mouse.x < p2D[0].x &&
+ mouse.x < p2D[1].x &&
+ mouse.x < p2D[2].x ) return false;
+ if ( mouse.x > p2D[0].x &&
+ mouse.x > p2D[1].x &&
+ mouse.x > p2D[2].x ) return false;
+ if ( mouse.y < p2D[0].y &&
+ mouse.y < p2D[1].y &&
+ mouse.y < p2D[2].y ) return false;
+ if ( mouse.y > p2D[0].y &&
+ mouse.y > p2D[1].y &&
+ mouse.y > p2D[2].y ) return false;
+
+ a.x = p2D[0].x;
+ a.y = p2D[0].y;
+ b.x = p2D[1].x;
+ b.y = p2D[1].y;
+ c.x = p2D[2].x;
+ c.y = p2D[2].y;
+ if ( !Math::IsInsideTriangle(a, b, c, mouse) ) return false;
+
+ dist = (p2D[0].z+p2D[1].z+p2D[2].z)/3.0f;
+ return true;
+}
+
+// Detects whether an object is affected by the mouse.
+
+bool CD3DEngine::DetectBBox(int objRank, Math::Point mouse)
+{
+ Math::Vector p, pp;
+ Math::Point min, max;
+ int i;
+
+ min.x = 1000000.0f;
+ min.y = 1000000.0f;
+ max.x = -1000000.0f;
+ max.y = -1000000.0f;
+
+ for ( i=0 ; i<8 ; i++ )
+ {
+ if ( i & (1<<0) ) p.x = m_objectParam[objRank].bboxMin.x;
+ else p.x = m_objectParam[objRank].bboxMax.x;
+ if ( i & (1<<1) ) p.y = m_objectParam[objRank].bboxMin.y;
+ else p.y = m_objectParam[objRank].bboxMax.y;
+ if ( i & (1<<2) ) p.z = m_objectParam[objRank].bboxMin.z;
+ else p.z = m_objectParam[objRank].bboxMax.z;
+ if ( TransformPoint(pp, objRank, p) )
+ {
+ if ( pp.x < min.x ) min.x = pp.x;
+ if ( pp.x > max.x ) max.x = pp.x;
+ if ( pp.y < min.y ) min.y = pp.y;
+ if ( pp.y > max.y ) max.y = pp.y;
+ }
+ }
+
+ return ( mouse.x >= min.x &&
+ mouse.x <= max.x &&
+ mouse.y >= min.y &&
+ mouse.y <= max.y );
+}
+
+// Transforms a 3D point (x, y, z) in 2D space (x, y, -) of the window.
+// The coordinated p2D.z gives the distance.
+
+bool CD3DEngine::TransformPoint(Math::Vector &p2D, int objRank, Math::Vector p3D)
+{
+ p3D = Math::Transform(m_objectParam[objRank].transform, p3D);
+ p3D = Math::Transform(m_matView, p3D);
+
+ if ( p3D.z < 2.0f ) return false; // behind?
+
+ p2D.x = (p3D.x/p3D.z)*m_matProj.Get(1,1);
+ p2D.y = (p3D.y/p3D.z)*m_matProj.Get(2,2);
+ p2D.z = p3D.z;
+
+ p2D.x = (p2D.x+1.0f)/2.0f; // [-1..1] -> [0..1]
+ p2D.y = (p2D.y+1.0f)/2.0f;
+
+ return true;
+}
+
+
+// Calculating the distances between the viewpoint and the origin
+// of different objects.
+
+void CD3DEngine::ComputeDistance()
+{
+ Math::Vector v;
+ int i;
+ float distance;
+
+ if ( s_resol == 0 )
+ {
+ for ( i=0 ; i<m_objectParamTotal ; i++ )
+ {
+ if ( m_objectParam[i].bUsed == false ) continue;
+
+ v.x = m_eyePt.x - m_objectParam[i].transform.Get(1,4);
+ v.y = m_eyePt.y - m_objectParam[i].transform.Get(2,4);
+ v.z = m_eyePt.z - m_objectParam[i].transform.Get(3,4);
+ m_objectParam[i].distance = v.Length();
+ }
+ }
+ else
+ {
+ if ( s_resol == 1 )
+ {
+ distance = 100000.0f;
+ }
+ if ( s_resol == 2 )
+ {
+ distance = (RetLimitLOD(0)+RetLimitLOD(1))/2.0f;
+ }
+ if ( s_resol == 3 )
+ {
+ distance = 0.0f;
+ }
+
+ for ( i=0 ; i<m_objectParamTotal ; i++ )
+ {
+ if ( m_objectParam[i].bUsed == false ) continue;
+
+ if ( m_objectParam[i].type == TYPETERRAIN )
+ {
+ v.x = m_eyePt.x - m_objectParam[i].transform.Get(1,4);
+ v.y = m_eyePt.y - m_objectParam[i].transform.Get(2,4);
+ v.z = m_eyePt.z - m_objectParam[i].transform.Get(3,4);
+ m_objectParam[i].distance = v.Length();
+ }
+ else
+ {
+ m_objectParam[i].distance = distance;
+ }
+ }
+ }
+}
+
+
+// Adjusts settings when first run.
+
+void CD3DEngine::FirstExecuteAdapt(bool bFirst)
+{
+ if ( m_app->IsVideo8MB() )
+ {
+ SetGroundSpot(false);
+ SetSkyMode(false);
+ }
+
+ if ( m_app->IsVideo32MB() && bFirst )
+ {
+ SetObjectDetail(2.0f);
+ }
+}
+
+// Returns the total amount of video memory for textures.
+
+int CD3DEngine::GetVidMemTotal()
+{
+ return m_app->GetVidMemTotal();
+}
+
+bool CD3DEngine::IsVideo8MB()
+{
+ return m_app->IsVideo8MB();
+}
+
+bool CD3DEngine::IsVideo32MB()
+{
+ return m_app->IsVideo32MB();
+}
+
+
+// Perform the list of all graphics devices available.
+
+bool CD3DEngine::EnumDevices(char *bufDevices, int lenDevices,
+ char *bufModes, int lenModes,
+ int &totalDevices, int &selectDevices,
+ int &totalModes, int &selectModes)
+{
+ return m_app->EnumDevices(bufDevices, lenDevices,
+ bufModes, lenModes,
+ totalDevices, selectDevices,
+ totalModes, selectModes);
+}
+
+bool CD3DEngine::RetFullScreen()
+{
+ return m_app->RetFullScreen();
+}
+
+bool CD3DEngine::ChangeDevice(char *device, char *mode, bool bFull)
+{
+ return m_app->ChangeDevice(device, mode, bFull);
+}
+
+
+
+Math::Matrix* CD3DEngine::RetMatView()
+{
+ return &m_matView;
+}
+
+Math::Matrix* CD3DEngine::RetMatLeftView()
+{
+ return &m_matLeftView;
+}
+
+Math::Matrix* CD3DEngine::RetMatRightView()
+{
+ return &m_matRightView;
+}
+
+
+// Specifies the location and direction of view.
+
+void CD3DEngine::SetViewParams(const Math::Vector &vEyePt,
+ const Math::Vector &vLookatPt,
+ const Math::Vector &vUpVec,
+ FLOAT fEyeDistance)
+{
+#if 0
+ m_eyePt = vEyePt;
+
+ // Adjust camera position for left or right eye along the axis
+ // perpendicular to the view direction vector and the up vector.
+ Math::Vector vView = (vLookatPt) - (vEyePt);
+ vView = CrossProduct( vView, (vUpVec) );
+ vView = Normalize( vView ) * fEyeDistance;
+
+ Math::Vector vLeftEyePt = (vEyePt) + vView;
+ Math::Vector vRightEyePt = (vEyePt) - vView;
+
+ // Set the view matrices
+ Math::LoadViewMatrix( m_matLeftView, (Math::Vector)vLeftEyePt, (Math::Vector)vLookatPt, (Math::Vector)vUpVec );
+ Math::LoadViewMatrix( m_matRightView, (Math::Vector)vRightEyePt, (Math::Vector)vLookatPt, (Math::Vector)vUpVec );
+ Math::LoadViewMatrix( m_matView, (Math::Vector)vEyePt, (Math::Vector)vLookatPt, (Math::Vector)vUpVec );
+#else
+ m_eyePt = vEyePt;
+ m_lookatPt = vLookatPt;
+ m_eyeDirH = Math::RotateAngle(vEyePt.x-vLookatPt.x, vEyePt.z-vLookatPt.z);
+ m_eyeDirV = Math::RotateAngle(Math::DistanceProjected(vEyePt, vLookatPt), vEyePt.y-vLookatPt.y);
+
+ Math::LoadViewMatrix(m_matView, vEyePt, vLookatPt, vUpVec);
+
+ if ( m_sound == 0 )
+ {
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ }
+ m_sound->SetListener(vEyePt, vLookatPt);
+#endif
+}
+
+
+// Specifies the transformation matrix of an object.
+
+bool CD3DEngine::SetObjectTransform(int objRank, const Math::Matrix &transform)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ m_objectParam[objRank].transform = transform;
+ return true;
+}
+
+// Gives the transformation matrix of an object.
+
+bool CD3DEngine::GetObjectTransform(int objRank, Math::Matrix &transform)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ transform = m_objectParam[objRank].transform;
+ return true;
+}
+
+// Specifies the type of an object.
+
+bool CD3DEngine::SetObjectType(int objRank, D3DTypeObj type)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ m_objectParam[objRank].type = type;
+ return true;
+}
+
+// Returns the type of an object.
+
+D3DTypeObj CD3DEngine::RetObjectType(int objRank)
+{
+ return m_objectParam[objRank].type;
+}
+
+// Specifies the transparency of an object.
+
+bool CD3DEngine::SetObjectTransparency(int objRank, float value)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ m_objectParam[objRank].transparency = value;
+ return true;
+}
+
+
+// Allocates a table for shade, if necessary.
+
+bool CD3DEngine::ShadowCreate(int objRank)
+{
+ int i;
+
+ // Already allocated?
+ if ( m_objectParam[objRank].shadowRank != -1 ) return true;
+
+ for ( i=0 ; i<D3DMAXSHADOW ; i++ )
+ {
+ if ( m_shadow[i].bUsed == false ) // Free?
+ {
+ ZeroMemory(&m_shadow[i], sizeof(D3DShadow));
+
+ m_shadow[i].bUsed = true;
+ m_shadow[i].objRank = objRank;
+ m_shadow[i].height = 0.0f;
+
+ m_objectParam[objRank].shadowRank = i;
+
+ if ( m_shadowTotal < i+1 )
+ {
+ m_shadowTotal = i+1;
+ }
+ return true;
+ }
+ }
+ return false; // not found
+}
+
+// Removes the shadow associated with an object.
+
+void CD3DEngine::ShadowDelete(int objRank)
+{
+ int i;
+
+ if ( objRank == -1 ) return;
+
+ i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return;
+
+ m_shadow[i].bUsed = false;
+ m_shadow[i].objRank = -1;
+ m_shadow[i].pos = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_shadow[i].type = D3DSHADOWNORM;
+
+ m_objectParam[objRank].shadowRank = -1;
+
+ m_shadowTotal = 0;
+ for ( i=0 ; i<D3DMAXSHADOW ; i++ )
+ {
+ if ( m_shadow[i].bUsed ) m_shadowTotal = i+1;
+ }
+}
+
+// Specifies if the shadow is visible.
+// For example, when an object is carried, he has no shadow.
+
+bool CD3DEngine::SetObjectShadowHide(int objRank, bool bHide)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ m_shadow[i].bHide = bHide;
+ return true;
+}
+
+// Specifies the type of the shadow of the object.
+
+bool CD3DEngine::SetObjectShadowType(int objRank, D3DShadowType type)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ m_shadow[i].type = type;
+ return true;
+}
+
+// Specifies the position of the shadow of the object.
+
+bool CD3DEngine::SetObjectShadowPos(int objRank, const Math::Vector &pos)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ m_shadow[i].pos = pos;
+ return true;
+}
+
+// Specifies the normal shadow to the field of the object.
+
+bool CD3DEngine::SetObjectShadowNormal(int objRank, const Math::Vector &n)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ m_shadow[i].normal = n;
+ return true;
+}
+
+// Specifies the angle of the shadow of the object.
+
+bool CD3DEngine::SetObjectShadowAngle(int objRank, float angle)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ m_shadow[i].angle = angle;
+ return true;
+}
+
+// Specifies the radius of the shadow of the object.
+
+bool CD3DEngine::SetObjectShadowRadius(int objRank, float radius)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ m_shadow[i].radius = radius;
+ return true;
+}
+
+// Returns the radius of the shadow of the object.
+
+float CD3DEngine::RetObjectShadowRadius(int objRank)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return 0.0f;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ return m_shadow[i].radius;
+}
+
+// Specifies the intensity of the shadow of the object.
+
+bool CD3DEngine::SetObjectShadowIntensity(int objRank, float intensity)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ m_shadow[i].intensity = intensity;
+ return true;
+}
+
+// Specifies the height of the shadow of the object.
+
+bool CD3DEngine::SetObjectShadowHeight(int objRank, float h)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ m_shadow[i].height = h;
+ return true;
+}
+
+
+// Clears all marks on the ground.
+
+void CD3DEngine::GroundSpotFlush()
+{
+ LPDIRECTDRAWSURFACE7 surface;
+ DDSURFACEDESC2 ddsd;
+ WORD* pbSurf;
+ char texName[20];
+ int s, y;
+
+ ZeroMemory(m_groundSpot, sizeof(D3DGroundSpot)*D3DMAXGROUNDSPOT);
+ m_bFirstGroundSpot = true; // drawing power first
+
+ for ( s=0 ; s<16 ; s++ )
+ {
+ sprintf(texName, "shadow%.2d.tga", s);
+ surface = D3DTextr_GetSurface(texName);
+ if ( surface == 0 ) continue;
+
+ ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
+ ddsd.dwSize = sizeof(DDSURFACEDESC2);
+ if ( surface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK ) continue;
+
+ if ( ddsd.ddpfPixelFormat.dwRGBBitCount != 16 ) continue;
+
+ for ( y=0 ; y<(int)ddsd.dwHeight ; y++ )
+ {
+ pbSurf = (WORD*)ddsd.lpSurface;
+ pbSurf += ddsd.lPitch*y/2;
+ memset(pbSurf, -1, ddsd.lPitch); // all blank
+ }
+
+ surface->Unlock(NULL);
+ }
+}
+
+// Allocates a table for a mark on the ground, if necessary.
+
+int CD3DEngine::GroundSpotCreate()
+{
+ int i;
+
+ for ( i=0 ; i<D3DMAXGROUNDSPOT ; i++ )
+ {
+ if ( m_groundSpot[i].bUsed == false ) // free?
+ {
+ ZeroMemory(&m_groundSpot[i], sizeof(D3DGroundSpot));
+ m_groundSpot[i].bUsed = true;
+ m_groundSpot[i].smooth = 1.0f;
+ return i;
+ }
+ }
+ return -1; // not found
+}
+
+// Removes a mark on the ground.
+
+void CD3DEngine::GroundSpotDelete(int rank)
+{
+ m_groundSpot[rank].bUsed = false;
+ m_groundSpot[rank].pos = Math::Vector(0.0f, 0.0f, 0.0f);
+}
+
+// Specifies the position of surface marking of the object.
+
+bool CD3DEngine::SetObjectGroundSpotPos(int rank, const Math::Vector &pos)
+{
+ m_groundSpot[rank].pos = pos;
+ return true;
+}
+
+// Specifies the radius of surface marking of the object.
+
+bool CD3DEngine::SetObjectGroundSpotRadius(int rank, float radius)
+{
+ m_groundSpot[rank].radius = radius;
+ return true;
+}
+
+// Specifies the color of a mark on the ground.
+
+bool CD3DEngine::SetObjectGroundSpotColor(int rank, D3DCOLORVALUE color)
+{
+ m_groundSpot[rank].color = color;
+ return true;
+}
+
+// Specifies the height min / max.
+
+bool CD3DEngine::SetObjectGroundSpotMinMax(int rank, float min, float max)
+{
+ m_groundSpot[rank].min = min;
+ m_groundSpot[rank].max = max;
+ return true;
+}
+
+// Specifies the transition factor.
+
+bool CD3DEngine::SetObjectGroundSpotSmooth(int rank, float smooth)
+{
+ m_groundSpot[rank].smooth = smooth;
+ return true;
+}
+
+
+// Creates ground marks.
+
+int CD3DEngine::GroundMarkCreate(Math::Vector pos, float radius,
+ float delay1, float delay2, float delay3,
+ int dx, int dy, char* table)
+{
+ ZeroMemory(&m_groundMark, sizeof(D3DGroundMark));
+ m_groundMark.bUsed = true;
+ m_groundMark.phase = 1;
+ m_groundMark.delay[0] = delay1;
+ m_groundMark.delay[1] = delay2;
+ m_groundMark.delay[2] = delay3;
+ m_groundMark.pos = pos;
+ m_groundMark.radius = radius;
+ m_groundMark.intensity = 0.0f;
+ m_groundMark.dx = dx;
+ m_groundMark.dy = dy;
+ m_groundMark.table = table;
+ return 0;
+}
+
+// Clears the ground.
+
+bool CD3DEngine::GroundMarkDelete(int rank)
+{
+ ZeroMemory(&m_groundMark, sizeof(D3DGroundMark));
+ return true;
+}
+
+
+// Border management (distance limits) depends of the resolution.
+// LOD = level-of-detail.
+
+void CD3DEngine::SetLimitLOD(int rank, float limit)
+{
+ m_limitLOD[rank] = limit;
+}
+
+float CD3DEngine::RetLimitLOD(int rank, bool bLast)
+{
+ float limit;
+
+ if ( bLast )
+ {
+ limit = m_limitLOD[rank];
+ limit *= m_lastDim.x/640.0f; // limit further if large window!
+//? limit += m_limitLOD[0]*(m_lastObjectDetail*2.0f-1.0f);
+ limit += m_limitLOD[0]*(m_lastObjectDetail*2.0f);
+ }
+ else
+ {
+ limit = m_limitLOD[rank];
+ limit *= m_dim.x/640.0f; // limit further if large window!
+//? limit += m_limitLOD[0]*(m_objectDetail*2.0f-1.0f);
+ limit += m_limitLOD[0]*(m_objectDetail*2.0f);
+ }
+ if ( limit < 0.0f ) limit = 0.0f;
+
+ return limit;
+}
+
+
+// Definition of the distance field of vision.
+
+void CD3DEngine::SetTerrainVision(float vision)
+{
+ m_terrainVision = vision;
+}
+
+
+// Management of the global mode of shading.
+
+void CD3DEngine::SetShadow(bool bMode)
+{
+ m_bShadow = bMode;
+}
+
+bool CD3DEngine::RetShadow()
+{
+ return m_bShadow;
+}
+
+
+// Management of the global mode of marking.
+
+void CD3DEngine::SetGroundSpot(bool bMode)
+{
+ m_bGroundSpot = bMode;
+}
+
+bool CD3DEngine::RetGroundSpot()
+{
+ return m_bGroundSpot;
+}
+
+
+// Management of the global mode of contamination.
+
+void CD3DEngine::SetDirty(bool bMode)
+{
+ m_bDirty = bMode;
+}
+
+bool CD3DEngine::RetDirty()
+{
+ return m_bDirty;
+}
+
+
+// Management of the global mode of horizontal fog patches.
+
+void CD3DEngine::SetFog(bool bMode)
+{
+ m_bFog = bMode;
+}
+
+bool CD3DEngine::RetFog()
+{
+ return m_bFog;
+}
+
+
+// ndicates whether it is possible to give a color SetState.
+
+bool CD3DEngine::RetStateColor()
+{
+ return m_bStateColor;
+}
+
+
+// Management of the global mode of secondary texturing.
+
+void CD3DEngine::SetSecondTexture(int texNum)
+{
+ m_secondTexNum = texNum;
+}
+
+int CD3DEngine::RetSecondTexture()
+{
+ return m_secondTexNum;
+}
+
+
+// Choice of the rank of the active view.
+
+void CD3DEngine::SetRankView(int rank)
+{
+ if ( rank < 0 ) rank = 0;
+ if ( rank > 1 ) rank = 1;
+
+ if ( m_rankView == 0 && rank == 1 ) // enters the water?
+ {
+ m_light->AdaptLightColor(m_waterAddColor, +1.0f);
+ }
+
+ if ( m_rankView == 1 && rank == 0 ) // out of the water?
+ {
+ m_light->AdaptLightColor(m_waterAddColor, -1.0f);
+ }
+
+ m_rankView = rank;
+}
+
+int CD3DEngine::RetRankView()
+{
+ return m_rankView;
+}
+
+// Whether to draw the world from the interface.
+
+void CD3DEngine::SetDrawWorld(bool bDraw)
+{
+ m_bDrawWorld = bDraw;
+}
+
+// Whether to draw the world on the interface.
+
+void CD3DEngine::SetDrawFront(bool bDraw)
+{
+ m_bDrawFront = bDraw;
+}
+
+// Color management ambient.
+// color = 0x00rrggbb
+// rr: red
+// gg: green
+// bb: blue
+
+void CD3DEngine::SetAmbiantColor(D3DCOLOR color, int rank)
+{
+ m_ambiantColor[rank] = color;
+}
+
+D3DCOLOR CD3DEngine::RetAmbiantColor(int rank)
+{
+ return m_ambiantColor[rank];
+}
+
+
+// Color management under water.
+
+void CD3DEngine::SetWaterAddColor(D3DCOLORVALUE color)
+{
+ m_waterAddColor = color;
+}
+
+D3DCOLORVALUE CD3DEngine::RetWaterAddColor()
+{
+ return m_waterAddColor;
+}
+
+
+// Management of the fog color.
+
+void CD3DEngine::SetFogColor(D3DCOLOR color, int rank)
+{
+ m_fogColor[rank] = color;
+}
+
+D3DCOLOR CD3DEngine::RetFogColor(int rank)
+{
+ return m_fogColor[rank];
+}
+
+
+// Management of the depth of field.
+// Beyond this distance, nothing is visible.
+// Shortly (according SetFogStart), one enters the fog.
+
+void CD3DEngine::SetDeepView(float length, int rank, bool bRef)
+{
+ if ( bRef )
+ {
+ length *= m_clippingDistance;
+ }
+
+ m_deepView[rank] = length;
+}
+
+float CD3DEngine::RetDeepView(int rank)
+{
+ return m_deepView[rank];
+}
+
+
+// Management the start of fog.
+// With 0.0, the fog from the point of view (fog max).
+// With 1.0, the fog from the depth of field (no fog).
+
+void CD3DEngine::SetFogStart(float start, int rank)
+{
+ m_fogStart[rank] = start;
+}
+
+float CD3DEngine::RetFogStart(int rank)
+{
+ return m_fogStart[rank];
+}
+
+
+// Gives the background image to use.
+
+void CD3DEngine::SetBackground(char *name, D3DCOLOR up, D3DCOLOR down,
+ D3DCOLOR cloudUp, D3DCOLOR cloudDown,
+ bool bFull, bool bQuarter)
+{
+ strcpy(m_backgroundName, name);
+ m_backgroundColorUp = up;
+ m_backgroundColorDown = down;
+ m_backgroundCloudUp = cloudUp;
+ m_backgroundCloudDown = cloudDown;
+ m_bBackgroundFull = bFull;
+ m_bBackgroundQuarter = bQuarter;
+}
+
+// Gives the background image used.
+
+void CD3DEngine::RetBackground(char *name, D3DCOLOR &up, D3DCOLOR &down,
+ D3DCOLOR &cloudUp, D3DCOLOR &cloudDown,
+ bool &bFull, bool &bQuarter)
+{
+ strcpy(name, m_backgroundName);
+ up = m_backgroundColorUp;
+ down = m_backgroundColorDown;
+ cloudUp = m_backgroundCloudUp;
+ cloudDown = m_backgroundCloudDown;
+ bFull = m_bBackgroundFull;
+ bQuarter = m_bBackgroundQuarter;
+}
+
+// Gives the foreground image to use.
+
+void CD3DEngine::SetFrontsizeName(char *name)
+{
+ if ( m_frontsizeName[0] != 0 )
+ {
+ FreeTexture(m_frontsizeName);
+ }
+
+ strcpy(m_frontsizeName, name);
+}
+
+// Specifies whether to draw the foreground.
+
+void CD3DEngine::SetOverFront(bool bFront)
+{
+ m_bOverFront = bFront;
+}
+
+// Gives color to the foreground.
+
+void CD3DEngine::SetOverColor(D3DCOLOR color, int mode)
+{
+ m_overColor = color;
+ m_overMode = mode;
+}
+
+
+
+// Management of the particle density.
+
+void CD3DEngine::SetParticuleDensity(float value)
+{
+ if ( value < 0.0f ) value = 0.0f;
+ if ( value > 2.0f ) value = 2.0f;
+ m_particuleDensity = value;
+}
+
+float CD3DEngine::RetParticuleDensity()
+{
+ return m_particuleDensity;
+}
+
+float CD3DEngine::ParticuleAdapt(float factor)
+{
+ if ( m_particuleDensity == 0.0f )
+ {
+ return 1000000.0f;
+ }
+ return factor/m_particuleDensity;
+}
+
+// Management of the distance of clipping.
+
+void CD3DEngine::SetClippingDistance(float value)
+{
+ if ( value < 0.5f ) value = 0.5f;
+ if ( value > 2.0f ) value = 2.0f;
+ m_clippingDistance = value;
+}
+
+float CD3DEngine::RetClippingDistance()
+{
+ return m_clippingDistance;
+}
+
+// Management of objects detals.
+
+void CD3DEngine::SetObjectDetail(float value)
+{
+ if ( value < 0.0f ) value = 0.0f;
+ if ( value > 2.0f ) value = 2.0f;
+ m_objectDetail = value;
+}
+
+float CD3DEngine::RetObjectDetail()
+{
+ return m_objectDetail;
+}
+
+// The amount of management objects gadgets.
+
+void CD3DEngine::SetGadgetQuantity(float value)
+{
+ if ( value < 0.0f ) value = 0.0f;
+ if ( value > 1.0f ) value = 1.0f;
+
+ m_gadgetQuantity = value;
+}
+
+float CD3DEngine::RetGadgetQuantity()
+{
+ return m_gadgetQuantity;
+}
+
+// Managing the quality of textures.
+
+void CD3DEngine::SetTextureQuality(int value)
+{
+ if ( value < 0 ) value = 0;
+ if ( value > 2 ) value = 2;
+
+ if ( value != m_textureQuality )
+ {
+ m_textureQuality = value;
+ LoadAllTexture();
+ }
+}
+
+int CD3DEngine::RetTextureQuality()
+{
+ return m_textureQuality;
+}
+
+
+// Management mode of toto.
+
+void CD3DEngine::SetTotoMode(bool bPresent)
+{
+ m_bTotoMode = bPresent;
+}
+
+bool CD3DEngine::RetTotoMode()
+{
+ return m_bTotoMode;
+}
+
+
+// Managing the mode of foreground.
+
+void CD3DEngine::SetLensMode(bool bPresent)
+{
+ m_bLensMode = bPresent;
+}
+
+bool CD3DEngine::RetLensMode()
+{
+ return m_bLensMode;
+}
+
+
+// Managing the mode of water.
+
+void CD3DEngine::SetWaterMode(bool bPresent)
+{
+ m_bWaterMode = bPresent;
+}
+
+bool CD3DEngine::RetWaterMode()
+{
+ return m_bWaterMode;
+}
+
+
+// Managing the mode of sky.
+
+void CD3DEngine::SetSkyMode(bool bPresent)
+{
+ m_bSkyMode = bPresent;
+}
+
+bool CD3DEngine::RetSkyMode()
+{
+ return m_bSkyMode;
+}
+
+
+// Managing the mode of background.
+
+void CD3DEngine::SetBackForce(bool bPresent)
+{
+ m_bBackForce = bPresent;
+}
+
+bool CD3DEngine::RetBackForce()
+{
+ return m_bBackForce;
+}
+
+
+// Managing the mode of planets.
+
+void CD3DEngine::SetPlanetMode(bool bPresent)
+{
+ m_bPlanetMode = bPresent;
+}
+
+bool CD3DEngine::RetPlanetMode()
+{
+ return m_bPlanetMode;
+}
+
+
+// Managing the mode of dymanic lights.
+
+void CD3DEngine::SetLightMode(bool bPresent)
+{
+ m_bLightMode = bPresent;
+}
+
+bool CD3DEngine::RetLightMode()
+{
+ return m_bLightMode;
+}
+
+
+// Management of the indentation mode while editing (CEdit).
+
+void CD3DEngine::SetEditIndentMode(bool bAuto)
+{
+ m_bEditIndentMode = bAuto;
+}
+
+bool CD3DEngine::RetEditIndentMode()
+{
+ return m_bEditIndentMode;
+}
+
+
+// Management in advance of a tab when editing (CEdit).
+
+void CD3DEngine::SetEditIndentValue(int value)
+{
+ m_editIndentValue = value;
+}
+
+int CD3DEngine::RetEditIndentValue()
+{
+ return m_editIndentValue;
+}
+
+
+void CD3DEngine::SetSpeed(float speed)
+{
+ m_speed = speed;
+}
+
+float CD3DEngine::RetSpeed()
+{
+ return m_speed;
+}
+
+
+void CD3DEngine::SetTracePrecision(float factor)
+{
+ m_tracePrecision = factor;
+}
+
+float CD3DEngine::RetTracePrecision()
+{
+ return m_tracePrecision;
+}
+
+
+// Updates the scene after a change of parameters.
+
+void CD3DEngine::ApplyChange()
+{
+ m_deepView[0] /= m_lastClippingDistance;
+ m_deepView[1] /= m_lastClippingDistance;
+
+ SetFocus(m_focus);
+ ChangeLOD();
+
+ m_deepView[0] *= m_clippingDistance;
+ m_deepView[1] *= m_clippingDistance;
+}
+
+
+
+// Returns the point of view of the user.
+
+Math::Vector CD3DEngine::RetEyePt()
+{
+ return m_eyePt;
+}
+
+Math::Vector CD3DEngine::RetLookatPt()
+{
+ return m_lookatPt;
+}
+
+float CD3DEngine::RetEyeDirH()
+{
+ return m_eyeDirH;
+}
+
+float CD3DEngine::RetEyeDirV()
+{
+ return m_eyeDirV;
+}
+
+POINT CD3DEngine::RetDim()
+{
+ return m_dim;
+}
+
+
+// Generates an image name of the watch.
+
+void QuarterName(char *buffer, char *name, int quarter)
+{
+ while ( *name != 0 )
+ {
+ if ( *name == '.' )
+ {
+ *buffer++ = 'a'+quarter;
+ }
+ *buffer++ = *name++;
+ }
+ *buffer++ = 0;
+}
+
+// Frees texture.
+
+bool CD3DEngine::FreeTexture(char* name)
+{
+ if ( name[0] == 0 ) return true;
+
+ if ( D3DTextr_DestroyTexture(name) != S_OK )
+ {
+ return false;
+ }
+ return true;
+}
+
+// Load a texture.
+
+bool CD3DEngine::LoadTexture(char* name, int stage)
+{
+ DWORD mode;
+
+ if ( name[0] == 0 ) return true;
+
+ if ( D3DTextr_GetSurface(name) == NULL )
+ {
+ if ( strstr(name, ".tga") == 0 )
+ {
+ mode = 0;
+ }
+ else
+ {
+ mode = D3DTEXTR_CREATEWITHALPHA;
+ }
+
+ if ( D3DTextr_CreateTextureFromFile(name, stage, mode) != S_OK )
+ {
+ return false;
+ }
+
+ if ( D3DTextr_Restore(name, m_pD3DDevice) != S_OK )
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Load all the textures of the scene.
+
+bool CD3DEngine::LoadAllTexture()
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ int l1, i;
+ char name[50];
+ bool bOK = true;
+
+#if _POLISH
+ LoadTexture("textp.tga");
+#else
+ LoadTexture("text.tga");
+#endif
+ LoadTexture("mouse.tga");
+ LoadTexture("button1.tga");
+ LoadTexture("button2.tga");
+ LoadTexture("button3.tga");
+ LoadTexture("effect00.tga");
+ LoadTexture("effect01.tga");
+ LoadTexture("effect02.tga");
+ LoadTexture("map.tga");
+
+ if ( m_backgroundName[0] != 0 )
+ {
+ if ( m_bBackgroundQuarter ) // image into 4 pieces?
+ {
+ for ( i=0 ; i<4 ; i++ )
+ {
+ QuarterName(name, m_backgroundName, i);
+ LoadTexture(name);
+ }
+ }
+ else
+ {
+ LoadTexture(m_backgroundName);
+ }
+ }
+ if ( m_frontsizeName[0] != 0 )
+ {
+ LoadTexture(m_frontsizeName);
+ }
+
+ m_planet->LoadTexture();
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+
+ if ( p2 == 0 || p2->texName1[0] != 0 )
+ {
+ if ( !LoadTexture(p2->texName1, 0) ) bOK = false;
+ }
+
+ if ( p2 == 0 || p2->texName2[0] != 0 )
+ {
+ if ( !LoadTexture(p2->texName2, 1) ) bOK = false;
+ }
+ }
+ return bOK;
+}
+
+
+// Called during initial app startup, this function performs all the
+// permanent initialization.
+
+HRESULT CD3DEngine::OneTimeSceneInit()
+{
+ return S_OK;
+}
+
+
+// Updated after creating objects.
+
+void CD3DEngine::Update()
+{
+ ComputeDistance();
+ UpdateGeometry();
+}
+
+// Called once per frame, the call is the entry point for animating
+// the scene.
+
+HRESULT CD3DEngine::FrameMove(float rTime)
+{
+ m_light->FrameLight(rTime);
+ m_particule->FrameParticule(rTime);
+ ComputeDistance();
+ UpdateGeometry();
+
+ if ( m_groundMark.bUsed )
+ {
+ if ( m_groundMark.phase == 1 ) // growing?
+ {
+ m_groundMark.intensity += rTime*(1.0f/m_groundMark.delay[0]);
+ if ( m_groundMark.intensity >= 1.0f )
+ {
+ m_groundMark.intensity = 1.0f;
+ m_groundMark.fix = 0.0f;
+ m_groundMark.phase = 2;
+ }
+ }
+ else if ( m_groundMark.phase == 2 ) // fixed?
+ {
+ m_groundMark.fix += rTime*(1.0f/m_groundMark.delay[1]);
+ if ( m_groundMark.fix >= 1.0f )
+ {
+ m_groundMark.phase = 3;
+ }
+ }
+ else if ( m_groundMark.phase == 3 ) // decay?
+ {
+ m_groundMark.intensity -= rTime*(1.0f/m_groundMark.delay[2]);
+ if ( m_groundMark.intensity < 0.0f )
+ {
+ m_groundMark.intensity = 0.0f;
+ m_groundMark.phase = 0;
+ m_groundMark.bUsed = false;
+ }
+ }
+ }
+
+ if ( m_sound == 0 )
+ {
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ }
+ m_sound->FrameMove(rTime);
+
+ return S_OK;
+}
+
+// Evolved throughout the game
+
+void CD3DEngine::StepSimul(float rTime)
+{
+ m_app->StepSimul(rTime);
+}
+
+
+
+// Changes the state associated with a material.
+// (*) Does not work without this instruction, mystery!
+
+void CD3DEngine::SetState(int state, D3DCOLOR color)
+{
+ bool bSecond;
+
+ if ( state == m_lastState &&
+ color == m_lastColor ) return;
+ m_lastState = state;
+ m_lastColor = color;
+
+ if ( m_alphaMode != 1 && (state & D3DSTATEALPHA) )
+ {
+ state &= ~D3DSTATEALPHA;
+
+ if ( m_alphaMode == 2 )
+ {
+ state |= D3DSTATETTb;
+ }
+ }
+
+ if ( state & D3DSTATETTb ) // The transparent black texture?
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_blackSrcBlend[1]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_blackDestBlend[1]);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, table_blend[debug_blend1]);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, table_blend[debug_blend2]);
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); // (*)
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ }
+ else if ( state & D3DSTATETTw ) // The transparent white texture?
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_whiteSrcBlend[1]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_whiteDestBlend[1]);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, table_blend[debug_blend3]);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, table_blend[debug_blend4]);
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, ~color);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_ADD);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); // (*)
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ }
+ else if ( state & D3DSTATETCb ) // The transparent black color?
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_blackSrcBlend[1]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_blackDestBlend[1]);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, table_blend[debug_blend1]);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, table_blend[debug_blend2]);
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ }
+ else if ( state & D3DSTATETCw ) // The transparent white color?
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_whiteSrcBlend[1]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_whiteDestBlend[1]);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, table_blend[debug_blend3]);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, table_blend[debug_blend4]);
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, ~color);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ }
+ else if ( state & D3DSTATETD ) // diffuse color as transparent?
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_diffuseSrcBlend[1]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_diffuseDestBlend[1]);
+
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ }
+ else if ( state & D3DSTATEALPHA ) // image with alpha channel?
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, D3DCMP_GREATER);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAREF, (DWORD)(128));
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_alphaSrcBlend[1]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_alphaSrcBlend[1]);
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+ }
+ else // normal ?
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
+
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ }
+
+ if ( state & D3DSTATEFOG )
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
+ }
+
+ bSecond = m_bGroundSpot|m_bDirty;
+ if ( !m_bGroundSpot && (state & D3DSTATESECOND) != 0 ) bSecond = false;
+ if ( !m_bDirty && (state & D3DSTATESECOND) == 0 ) bSecond = false;
+
+ if ( (state & D3DSTATEDUALb) && bSecond )
+ {
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
+ }
+ else if ( (state & D3DSTATEDUALw) && bSecond )
+ {
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
+ }
+ else
+ {
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ }
+
+ if ( state & D3DSTATEWRAP )
+ {
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_WRAP0, D3DWRAP_U|D3DWRAP_V);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);
+ }
+ else if ( state & D3DSTATECLAMP )
+ {
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_WRAP0, 0);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
+ }
+ else
+ {
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_WRAP0, 0);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
+ }
+
+ if ( state & D3DSTATE2FACE )
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
+ }
+ else
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CCW);
+ }
+
+ if ( state & D3DSTATELIGHT )
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ }
+ else
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, m_ambiantColor[m_rankView]);
+ }
+}
+
+// Specifies a texture to use.
+
+void CD3DEngine::SetTexture(char *name, int stage)
+{
+//? if ( stage == 1 && !m_bDirty ) return;
+//? if ( stage == 1 && !m_bShadow ) return;
+
+ if ( strcmp(name, m_lastTexture[stage]) == 0 ) return;
+ strcpy(m_lastTexture[stage], name);
+
+ m_pD3DDevice->SetTexture(stage, D3DTextr_GetSurface(name));
+}
+
+// Specifies the material to use.
+
+void CD3DEngine::SetMaterial(const D3DMATERIAL7 &mat)
+{
+ if ( memcmp(&mat, &m_lastMaterial, sizeof(D3DMATERIAL7)) == 0 ) return;
+ m_lastMaterial = mat;
+
+ m_pD3DDevice->SetMaterial(&m_lastMaterial);
+}
+
+
+// Deletes a point in a surface (draw in white).
+
+inline void ClearDot(DDSURFACEDESC2* ddsd, int x, int y)
+{
+ WORD* pbSurf;
+
+ if ( ddsd->ddpfPixelFormat.dwRGBBitCount != 16 ) return;
+
+ pbSurf = (WORD*)ddsd->lpSurface;
+ pbSurf += ddsd->lPitch*y/2;
+ pbSurf += x;
+
+ *pbSurf = 0xffff; // white
+}
+
+// Deletes a point in a surface (draw in white)
+
+void AddDot(DDSURFACEDESC2* ddsd, int x, int y, D3DCOLORVALUE color)
+{
+ WORD* pbSurf;
+ WORD r,g,b, w;
+
+ if ( ddsd->ddpfPixelFormat.dwRGBBitCount != 16 ) return;
+
+ if ( color.r < 0.0f ) color.r = 0.0f;
+ if ( color.r > 1.0f ) color.r = 1.0f;
+ r = (int)(color.r*32.0f);
+ if ( r >= 32 ) r = 31; // 5 bits
+
+ if ( color.g < 0.0f ) color.g = 0.0f;
+ if ( color.g > 1.0f ) color.g = 1.0f;
+ g = (int)(color.g*32.0f);
+ if ( g >= 32 ) g = 31; // 5 bits
+
+ if ( color.b < 0.0f ) color.b = 0.0f;
+ if ( color.b > 1.0f ) color.b = 1.0f;
+ b = (int)(color.b*32.0f);
+ if ( b >= 32 ) b = 31; // 5 bits
+
+ if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xf800 ) // 565 ?
+ {
+ w = (r<<11)|(g<<6)|b;
+ }
+ else if ( ddsd->ddpfPixelFormat.dwRBitMask == 0x7c00 ) // 555 ?
+ {
+ w = (r<<10)|(g<<5)|b;
+ }
+ else
+ {
+ w = -1; // blank
+ }
+
+ pbSurf = (WORD*)ddsd->lpSurface;
+ pbSurf += ddsd->lPitch*y/2;
+ pbSurf += x;
+
+ *pbSurf &= w;
+}
+
+// Displays a point in a surface.
+
+void SetDot(DDSURFACEDESC2* ddsd, int x, int y, D3DCOLORVALUE color)
+{
+ if ( ddsd->ddpfPixelFormat.dwRGBBitCount == 16 )
+ {
+ WORD* pbSurf;
+ WORD r,g,b, w;
+
+ if ( color.r < 0.0f ) color.r = 0.0f;
+ if ( color.r > 1.0f ) color.r = 1.0f;
+ if ( color.g < 0.0f ) color.g = 0.0f;
+ if ( color.g > 1.0f ) color.g = 1.0f;
+ if ( color.b < 0.0f ) color.b = 0.0f;
+ if ( color.b > 1.0f ) color.b = 1.0f;
+
+ r = (int)(color.r*32.0f);
+ g = (int)(color.g*32.0f);
+ b = (int)(color.b*32.0f);
+
+ if ( r >= 32 ) r = 31; // 5 bits
+ if ( g >= 32 ) g = 31; // 5 bits
+ if ( b >= 32 ) b = 31; // 5 bits
+
+ if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xf800 ) // 565 ?
+ {
+ w = (r<<11)|(g<<6)|b;
+ }
+ else if ( ddsd->ddpfPixelFormat.dwRBitMask == 0x7c00 ) // 555 ?
+ {
+ w = (r<<10)|(g<<5)|b;
+ }
+ else
+ {
+ w = -1; // blank
+ }
+
+ pbSurf = (WORD*)ddsd->lpSurface;
+ pbSurf += ddsd->lPitch*y/2;
+ pbSurf += x;
+
+ *pbSurf = w;
+ }
+
+ if ( ddsd->ddpfPixelFormat.dwRGBBitCount == 32 ) // image .tga ?
+ {
+ LONG* pbSurf;
+ LONG r,g,b, w;
+
+ if ( color.r < 0.0f ) color.r = 0.0f;
+ if ( color.r > 1.0f ) color.r = 1.0f;
+ if ( color.g < 0.0f ) color.g = 0.0f;
+ if ( color.g > 1.0f ) color.g = 1.0f;
+ if ( color.b < 0.0f ) color.b = 0.0f;
+ if ( color.b > 1.0f ) color.b = 1.0f;
+
+ r = (int)(color.r*256.0f);
+ g = (int)(color.g*256.0f);
+ b = (int)(color.b*256.0f);
+
+ if ( r >= 256 ) r = 255; // 8 bits
+ if ( g >= 256 ) g = 255; // 8 bits
+ if ( b >= 256 ) b = 255; // 8 bits
+
+ if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xff0000 )
+ {
+ w = (r<<16)|(g<<8)|b;
+
+ pbSurf = (LONG*)ddsd->lpSurface;
+ pbSurf += ddsd->lPitch*y/4;
+ pbSurf += x;
+
+ *pbSurf &= 0xff000000; // keeps alpha channel
+ *pbSurf |= w;
+ }
+ }
+}
+
+// Gives a point in a surface.
+
+D3DCOLORVALUE GetDot(DDSURFACEDESC2* ddsd, int x, int y)
+{
+ D3DCOLORVALUE color;
+
+ if ( ddsd->ddpfPixelFormat.dwRGBBitCount == 16 )
+ {
+ WORD* pbSurf;
+ WORD r,g,b, w;
+
+ pbSurf = (WORD*)ddsd->lpSurface;
+ pbSurf += ddsd->lPitch*y/2;
+ pbSurf += x;
+
+ w = *pbSurf;
+
+ if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xf800 ) // 565 ?
+ {
+ r = (w>>10)&0x003e;
+ g = (w>> 5)&0x003f;
+ b = (w<< 1)&0x003e;
+ }
+ else if ( ddsd->ddpfPixelFormat.dwRBitMask == 0x7c00 ) // 555 ?
+ {
+ r = (w>> 9)&0x003e;
+ g = (w>> 4)&0x003e;
+ b = (w<< 1)&0x003e;
+ }
+ else
+ {
+ r = 0;
+ g = 0;
+ b = 0; // black
+ }
+
+ color.r = (float)r/63.0f;
+ color.g = (float)g/63.0f;
+ color.b = (float)b/63.0f;
+ color.a = 0.0f;
+ return color;
+ }
+
+ if ( ddsd->ddpfPixelFormat.dwRGBBitCount == 32 ) // image .tga ?
+ {
+ LONG* pbSurf;
+ LONG r,g,b, w;
+
+ pbSurf = (LONG*)ddsd->lpSurface;
+ pbSurf += ddsd->lPitch*y/4;
+ pbSurf += x;
+
+ w = *pbSurf;
+
+ if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xff0000 )
+ {
+ r = (w>>16)&0x00ff;
+ g = (w>> 8)&0x00ff;
+ b = (w<< 0)&0x00ff;
+ }
+ else
+ {
+ r = 0;
+ g = 0;
+ b = 0; // black
+ }
+
+ color.r = (float)r/255.0f;
+ color.g = (float)g/255.0f;
+ color.b = (float)b/255.0f;
+ color.a = 0.0f;
+ return color;
+ }
+
+ color.r = 0.0f;
+ color.g = 0.0f;
+ color.b = 0.0f;
+ color.a = 0.0f; // black
+ return color;
+}
+
+// Draw all the shadows.
+
+// There is a pixel collection around each of the 16 surfaces:
+//
+// |<----------------------->|<----------------------->|<---- ...
+// 0 | 1 2 253 254|255 |
+// |---|---|---|-- ... --|---|---|---| |
+// 0 | 1 2 253 254|255
+// |---|---|---|-- ... --|---|---|---|
+//
+// So we draw in 254x254 pixels surfaces.
+// The pixel margin around it is drawn twice (in two adjacent surfaces),
+// so that the filter produces the same results!
+
+void CD3DEngine::RenderGroundSpot()
+{
+ LPDIRECTDRAWSURFACE7 surface;
+ DDSURFACEDESC2 ddsd;
+ WORD* pbSurf;
+ D3DCOLORVALUE color;
+ Math::Vector pos;
+ Math::Point min, max;
+ int s, i, j, dot, ix, iy, y;
+ float tu, tv, cx, cy, px, py, ppx, ppy;
+ float intensity, level;
+ char texName[20];
+ bool bClear, bSet;
+
+ if ( !m_bFirstGroundSpot &&
+ m_groundMark.drawPos.x == m_groundMark.pos.x &&
+ m_groundMark.drawPos.z == m_groundMark.pos.z &&
+ m_groundMark.drawRadius == m_groundMark.radius &&
+ m_groundMark.drawIntensity == m_groundMark.intensity ) return;
+
+ for ( s=0 ; s<16 ; s++ )
+ {
+ min.x = (s%4)*254.0f-1.0f; // 1 pixel cover
+ min.y = (s/4)*254.0f-1.0f;
+ max.x = min.x+254.0f+2.0f;
+ max.y = min.y+254.0f+2.0f;
+
+ bClear = false;
+ bSet = false;
+
+ // Calculate the area to be erased.
+ dot = (int)(m_groundMark.drawRadius/2.0f);
+
+ tu = (m_groundMark.drawPos.x+1600.0f)/3200.0f;
+ tv = (m_groundMark.drawPos.z+1600.0f)/3200.0f; // 0..1
+
+ cx = (tu*254.0f*4.0f)-0.5f;
+ cy = (tv*254.0f*4.0f)-0.5f;
+
+ if ( dot == 0 )
+ {
+ cx += 0.5f;
+ cy += 0.5f;
+ }
+
+ px = cx-Math::Mod(cx, 1.0f);
+ py = cy-Math::Mod(cy, 1.0f); // multiple of 1
+
+ if ( m_bFirstGroundSpot ||
+ ( m_groundMark.drawRadius != 0.0f &&
+ px+dot >= min.x && py+dot >= min.y &&
+ px-dot <= max.x && py-dot <= max.y ) )
+ {
+ bClear = true;
+ }
+
+ // Calculate the area to draw.
+ dot = (int)(m_groundMark.radius/2.0f);
+
+ tu = (m_groundMark.pos.x+1600.0f)/3200.0f;
+ tv = (m_groundMark.pos.z+1600.0f)/3200.0f; // 0..1
+
+ cx = (tu*254.0f*4.0f)-0.5f;
+ cy = (tv*254.0f*4.0f)-0.5f;
+
+ if ( dot == 0 )
+ {
+ cx += 0.5f;
+ cy += 0.5f;
+ }
+
+ px = cx-Math::Mod(cx, 1.0f);
+ py = cy-Math::Mod(cy, 1.0f); // multiple of 1
+
+ if ( m_groundMark.bUsed &&
+ px+dot >= min.x && py+dot >= min.y &&
+ px-dot <= max.x && py-dot <= max.y )
+ {
+ bSet = true;
+ }
+
+ if ( bClear || bSet )
+ {
+ // Load the song.
+ sprintf(texName, "shadow%.2d.tga", s);
+ surface = D3DTextr_GetSurface(texName);
+ if ( surface == 0 ) continue;
+
+ ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
+ ddsd.dwSize = sizeof(DDSURFACEDESC2);
+ if ( surface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK ) continue;
+
+ // Clears in blank whole piece.
+ if ( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 )
+ {
+ for ( y=0 ; y<(int)ddsd.dwHeight ; y++ )
+ {
+ pbSurf = (WORD*)ddsd.lpSurface;
+ pbSurf += ddsd.lPitch*y/2;
+ memset(pbSurf, -1, ddsd.lPitch); // all blank
+ }
+ }
+
+ // Draw the new shadows.
+ for ( i=0 ; i<D3DMAXGROUNDSPOT ; i++ )
+ {
+ if ( m_groundSpot[i].bUsed == false ||
+ m_groundSpot[i].radius == 0.0f ) continue;
+
+ if ( m_groundSpot[i].min == 0.0f &&
+ m_groundSpot[i].max == 0.0f )
+ {
+ dot = (int)(m_groundSpot[i].radius/2.0f);
+
+ tu = (m_groundSpot[i].pos.x+1600.0f)/3200.0f;
+ tv = (m_groundSpot[i].pos.z+1600.0f)/3200.0f; // 0..1
+
+ cx = (tu*254.0f*4.0f)-0.5f;
+ cy = (tv*254.0f*4.0f)-0.5f;
+
+ if ( dot == 0 )
+ {
+ cx += 0.5f;
+ cy += 0.5f;
+ }
+
+ px = cx-Math::Mod(cx, 1.0f);
+ py = cy-Math::Mod(cy, 1.0f); // multiple of 1
+
+ if ( px+dot < min.x || py+dot < min.y ||
+ px-dot > max.x || py-dot > max.y ) continue;
+
+ for ( iy=-dot ; iy<=dot ; iy++ )
+ {
+ for ( ix=-dot ; ix<=dot ; ix++ )
+ {
+ ppx = px+ix;
+ ppy = py+iy;
+
+ if ( ppx < min.x || ppy < min.y ||
+ ppx >= max.x || ppy >= max.y ) continue;
+
+ if ( dot == 0 )
+ {
+ intensity = 0.0f;
+ }
+ else
+ {
+ intensity = Math::Point(ppx-cx, ppy-cy).Length()/dot;
+ //? intensity = powf(intensity, m_groundSpot[i].smooth);
+ }
+
+ color.r = m_groundSpot[i].color.r+intensity;
+ color.g = m_groundSpot[i].color.g+intensity;
+ color.b = m_groundSpot[i].color.b+intensity;
+
+ ppx -= min.x; // on the texture
+ ppy -= min.y;
+ AddDot(&ddsd, (int)ppx, (int)ppy, color);
+ }
+ }
+ }
+ else
+ {
+ for ( iy=0 ; iy<256 ; iy++ )
+ {
+ for ( ix=0 ; ix<256 ; ix++ )
+ {
+ pos.x = (256.0f*(s%4)+ix)*3200.0f/1024.0f - 1600.0f;
+ pos.z = (256.0f*(s/4)+iy)*3200.0f/1024.0f - 1600.0f;
+ pos.y = 0.0f;
+ level = m_terrain->RetFloorLevel(pos, true);
+ if ( level < m_groundSpot[i].min ||
+ level > m_groundSpot[i].max ) continue;
+
+ if ( level > (m_groundSpot[i].max+m_groundSpot[i].min)/2.0f )
+ {
+ intensity = 1.0f-(m_groundSpot[i].max-level)/m_groundSpot[i].smooth;
+ }
+ else
+ {
+ intensity = 1.0f-(level-m_groundSpot[i].min)/m_groundSpot[i].smooth;
+ }
+ if ( intensity < 0.0f ) intensity = 0.0f;
+
+ color.r = m_groundSpot[i].color.r+intensity;
+ color.g = m_groundSpot[i].color.g+intensity;
+ color.b = m_groundSpot[i].color.b+intensity;
+
+ AddDot(&ddsd, ix, iy, color);
+ }
+ }
+ }
+ }
+
+ if ( bSet )
+ {
+ dot = (int)(m_groundMark.radius/2.0f);
+
+ tu = (m_groundMark.pos.x+1600.0f)/3200.0f;
+ tv = (m_groundMark.pos.z+1600.0f)/3200.0f; // 0..1
+
+ cx = (tu*254.0f*4.0f)-0.5f;
+ cy = (tv*254.0f*4.0f)-0.5f;
+
+ if ( dot == 0 )
+ {
+ cx += 0.5f;
+ cy += 0.5f;
+ }
+
+ px = cx-Math::Mod(cx, 1.0f);
+ py = cy-Math::Mod(cy, 1.0f); // multiple of 1
+
+ for ( iy=-dot ; iy<=dot ; iy++ )
+ {
+ for ( ix=-dot ; ix<=dot ; ix++ )
+ {
+ ppx = px+ix;
+ ppy = py+iy;
+
+ if ( ppx < min.x || ppy < min.y ||
+ ppx >= max.x || ppy >= max.y ) continue;
+
+ ppx -= min.x; // on the texture
+ ppy -= min.y;
+
+ intensity = 1.0f-Math::Point((float)ix, (float)iy).Length()/dot;
+ if ( intensity <= 0.0f ) continue;
+ intensity *= m_groundMark.intensity;
+
+ j = (ix+dot) + (iy+dot)*m_groundMark.dx;
+ if ( m_groundMark.table[j] == 1 ) // green ?
+ {
+ color.r = 1.0f-intensity;
+ color.g = 1.0f;
+ color.b = 1.0f-intensity;
+ AddDot(&ddsd, (int)ppx, (int)ppy, color);
+ }
+ if ( m_groundMark.table[j] == 2 ) // red ?
+ {
+ color.r = 1.0f;
+ color.g = 1.0f-intensity;
+ color.b = 1.0f-intensity;
+ AddDot(&ddsd, (int)ppx, (int)ppy, color);
+ }
+ }
+ }
+ }
+
+ surface->Unlock(NULL);
+ }
+ }
+
+ for ( i=0 ; i<D3DMAXGROUNDSPOT ; i++ )
+ {
+ if ( m_groundSpot[i].bUsed == false ||
+ m_groundSpot[i].radius == 0.0f )
+ {
+ m_groundSpot[i].drawRadius = 0.0f;
+ }
+ else
+ {
+ m_groundSpot[i].drawPos = m_groundSpot[i].pos;
+ m_groundSpot[i].drawRadius = m_groundSpot[i].radius;
+ }
+ }
+
+ m_groundMark.drawPos = m_groundMark.pos;
+ m_groundMark.drawRadius = m_groundMark.radius;
+ m_groundMark.drawIntensity = m_groundMark.intensity;
+
+ m_bFirstGroundSpot = false;
+}
+
+// Draw all the shadows.
+
+void CD3DEngine::DrawShadow()
+{
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Vector corner[4], n, pos;
+ D3DMATERIAL7 material;
+ Math::Matrix matrix;
+ Math::Point ts, ti, rot;
+ float startDeepView, endDeepView;
+ float intensity, lastIntensity, hFactor, radius, max, height;
+ float dp, h, d, D;
+ int i;
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
+
+ matrix.LoadIdentity();
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ ZeroMemory( &material, sizeof(D3DMATERIAL7) );
+ material.diffuse.r = 1.0f;
+ material.diffuse.g = 1.0f;
+ material.diffuse.b = 1.0f; // white
+ material.ambient.r = 0.5f;
+ material.ambient.g = 0.5f;
+ material.ambient.b = 0.5f;
+ SetMaterial(material);
+
+#if _POLISH
+ SetTexture("textp.tga");
+#else
+ SetTexture("text.tga");
+#endif
+
+ dp = 0.5f/256.0f;
+ ts.y = 192.0f/256.0f;
+ ti.y = 224.0f/256.0f;
+ ts.y += dp;
+ ti.y -= dp;
+
+ n = Math::Vector(0.0f, 1.0f, 0.0f);
+
+ startDeepView = m_deepView[m_rankView]*m_fogStart[m_rankView];
+ endDeepView = m_deepView[m_rankView];
+
+ lastIntensity = -1.0f;
+ for ( i=0 ; i<m_shadowTotal ; i++ )
+ {
+ if ( !m_shadow[i].bUsed ) continue;
+ if ( m_shadow[i].bHide ) continue;
+
+ pos = m_shadow[i].pos; // pos = center of the shadow on the ground
+
+ if ( m_eyePt.y == pos.y ) continue; // camera at the same level?
+
+ // h is the height above the ground to which the shadow
+ // will be drawn.
+ if ( m_eyePt.y > pos.y ) // camera on?
+ {
+ height = m_eyePt.y-pos.y;
+ h = m_shadow[i].radius;
+ max = height*0.5f;
+ if ( h > max ) h = max;
+ if ( h > 4.0f ) h = 4.0f;
+
+ D = Math::Distance(m_eyePt, pos);
+ if ( D >= endDeepView ) continue;
+ d = D*h/height;
+
+ pos.x += (m_eyePt.x-pos.x)*d/D;
+ pos.z += (m_eyePt.z-pos.z)*d/D;
+ pos.y += h;
+ }
+ else // camera underneath?
+ {
+ height = pos.y-m_eyePt.y;
+ h = m_shadow[i].radius;
+ max = height*0.1f;
+ if ( h > max ) h = max;
+ if ( h > 4.0f ) h = 4.0f;
+
+ D = Math::Distance(m_eyePt, pos);
+ if ( D >= endDeepView ) continue;
+ d = D*h/height;
+
+ pos.x += (m_eyePt.x-pos.x)*d/D;
+ pos.z += (m_eyePt.z-pos.z)*d/D;
+ pos.y -= h;
+ }
+
+ // The hFactor decreases the intensity and size increases more
+ // the object is high relative to the ground.
+ hFactor = m_shadow[i].height/20.0f;
+ if ( hFactor < 0.0f ) hFactor = 0.0f;
+ if ( hFactor > 1.0f ) hFactor = 1.0f;
+ hFactor = powf(1.0f-hFactor, 2.0f);
+ if ( hFactor < 0.2f ) hFactor = 0.2f;
+
+ radius = m_shadow[i].radius*1.5f;
+ radius *= 2.0f-hFactor; // greater if high
+ radius *= 1.0f-d/D; // smaller if close
+
+ if ( m_shadow[i].type == D3DSHADOWNORM )
+ {
+ corner[0].x = +radius;
+ corner[0].z = +radius;
+ corner[0].y = 0.0f;
+
+ corner[1].x = -radius;
+ corner[1].z = +radius;
+ corner[1].y = 0.0f;
+
+ corner[2].x = +radius;
+ corner[2].z = -radius;
+ corner[2].y = 0.0f;
+
+ corner[3].x = -radius;
+ corner[3].z = -radius;
+ corner[3].y = 0.0f;
+
+ ts.x = 64.0f/256.0f;
+ ti.x = 96.0f/256.0f;
+ }
+ else
+ {
+ rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(radius, radius));
+ corner[0].x = rot.x;
+ corner[0].z = rot.y;
+ corner[0].y = 0.0f;
+
+ rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(-radius, radius));
+ corner[1].x = rot.x;
+ corner[1].z = rot.y;
+ corner[1].y = 0.0f;
+
+ rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(radius, -radius));
+ corner[2].x = rot.x;
+ corner[2].z = rot.y;
+ corner[2].y = 0.0f;
+
+ rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(-radius, -radius));
+ corner[3].x = rot.x;
+ corner[3].z = rot.y;
+ corner[3].y = 0.0f;
+
+ if ( m_shadow[i].type == D3DSHADOWWORM )
+ {
+ ts.x = 96.0f/256.0f;
+ ti.x = 128.0f/256.0f;
+ }
+ else
+ {
+ ts.x = 64.0f/256.0f;
+ ti.x = 96.0f/256.0f;
+ }
+ }
+
+ corner[0] = Math::CrossProduct(corner[0], m_shadow[i].normal);
+ corner[1] = Math::CrossProduct(corner[1], m_shadow[i].normal);
+ corner[2] = Math::CrossProduct(corner[2], m_shadow[i].normal);
+ corner[3] = Math::CrossProduct(corner[3], m_shadow[i].normal);
+
+ corner[0] += pos;
+ corner[1] += pos;
+ corner[2] += pos;
+ corner[3] += pos;
+
+ ts.x += dp;
+ ti.x -= dp;
+
+ vertex[0] = D3DVERTEX2(corner[1], n, ts.x, ts.y);
+ vertex[1] = D3DVERTEX2(corner[0], n, ti.x, ts.y);
+ vertex[2] = D3DVERTEX2(corner[3], n, ts.x, ti.y);
+ vertex[3] = D3DVERTEX2(corner[2], n, ti.x, ti.y);
+
+ intensity = (0.5f+m_shadow[i].intensity*0.5f)*hFactor;
+
+ // Decreases the intensity of the shade if you're in the area
+ // between the beginning and the end of the fog.
+ if ( D > startDeepView )
+ {
+ intensity *= 1.0f-(D-startDeepView)/(endDeepView-startDeepView);
+ }
+
+ // Decreases if the intensity is almost horizontal
+ // with shade (shade very platte).
+//? if ( height < 4.0f ) intensity *= height/4.0f;
+
+ if ( intensity == 0.0f ) continue;
+
+ if ( lastIntensity != intensity ) // intensity changed?
+ {
+ lastIntensity = intensity;
+ SetState(D3DSTATETTw, RetColor(intensity));
+ }
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ AddStatisticTriangle(2);
+ }
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
+}
+
+
+// Called ounces per frame, the call is the entry point for 3d rendering.
+// This function sets up render states, clears the
+// viewport, and renders the scene.
+
+HRESULT CD3DEngine::Render()
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ D3DVERTEX2* pv;
+ int l1, l2, l3, l4, l5, objRank, tState;
+ CInterface* pInterface;
+ bool bTransparent;
+ D3DCOLOR color, tColor;
+
+ if ( !m_bRender ) return S_OK;
+
+ m_statisticTriangle = 0;
+ m_lastState = -1;
+ m_lastColor = 999;
+ m_lastTexture[0][0] = 0;
+ m_lastTexture[1][0] = 0;
+ ZeroMemory(&m_lastMaterial, sizeof(D3DMATERIAL7));
+
+ if ( m_bGroundSpot )
+ {
+ RenderGroundSpot();
+ }
+
+ // Clear the viewport
+ if ( m_bSkyMode && m_cloud->RetLevel() != 0.0f ) // clouds?
+ {
+ color = m_backgroundCloudDown;
+ }
+ else
+ {
+ color = m_backgroundColorDown;
+ }
+ m_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
+ color, 1.0f, 0L );
+
+ m_light->LightUpdate();
+
+ // Begin the scene
+ if( FAILED( m_pD3DDevice->BeginScene() ) ) return S_OK;
+
+ if ( m_bDrawWorld )
+ {
+ DrawBackground(); // draws the background
+ if ( m_bPlanetMode ) DrawPlanet(); // draws the planets
+ if ( m_bSkyMode ) m_cloud->Draw(); // draws the clouds
+
+ // Display the objects
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, true);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZBIAS, F2DW(16));
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProj);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, m_fogColor[m_rankView]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_LINEAR);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGSTART, F2DW(m_deepView[m_rankView]*m_fogStart[m_rankView]));
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGEND, F2DW(m_deepView[m_rankView]));
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matView);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+
+ if ( m_bWaterMode ) m_water->DrawBack(); // draws water
+
+ if ( m_bShadow )
+ {
+ // Draw the field.
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ SetTexture(p2->texName1, 0);
+ SetTexture(p2->texName2, 1);
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ objRank = p3->objRank;
+ if ( m_objectParam[objRank].type != TYPETERRAIN ) continue;
+ if ( !m_objectParam[objRank].bDrawWorld ) continue;
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ if ( !IsVisible(objRank) ) continue;
+ m_light->LightUpdate(m_objectParam[objRank].type);
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ if ( m_objectParam[objRank].distance < p4->min ||
+ m_objectParam[objRank].distance >= p4->max ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ SetMaterial(p6->material);
+ SetState(p6->state);
+ if ( p6->type == D3DTYPE6T )
+ {
+ pv = &p6->vertex[0];
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
+ D3DFVF_VERTEX2,
+ pv, p6->totalUsed,
+ NULL);
+ m_statisticTriangle += p6->totalUsed/3;
+ }
+ if ( p6->type == D3DTYPE6S )
+ {
+ pv = &p6->vertex[0];
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
+ D3DFVF_VERTEX2,
+ pv, p6->totalUsed,
+ NULL);
+ m_statisticTriangle += p6->totalUsed-2;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ DrawShadow(); // draws the shadows
+ }
+
+ // Draw objects.
+ bTransparent = false;
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ SetTexture(p2->texName1, 0);
+ SetTexture(p2->texName2, 1);
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ objRank = p3->objRank;
+ if ( m_bShadow && m_objectParam[objRank].type == TYPETERRAIN ) continue;
+ if ( !m_objectParam[objRank].bDrawWorld ) continue;
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ if ( !IsVisible(objRank) ) continue;
+ m_light->LightUpdate(m_objectParam[objRank].type);
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ if ( m_objectParam[objRank].distance < p4->min ||
+ m_objectParam[objRank].distance >= p4->max ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ SetMaterial(p6->material);
+ if ( m_objectParam[objRank].transparency != 0.0f ) // transparent ?
+ {
+ bTransparent = true;
+ continue;
+ }
+ SetState(p6->state);
+ if ( p6->type == D3DTYPE6T )
+ {
+ pv = &p6->vertex[0];
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
+ D3DFVF_VERTEX2,
+ pv, p6->totalUsed,
+ NULL);
+ m_statisticTriangle += p6->totalUsed/3;
+ }
+ if ( p6->type == D3DTYPE6S )
+ {
+ pv = &p6->vertex[0];
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
+ D3DFVF_VERTEX2,
+ pv, p6->totalUsed,
+ NULL);
+ m_statisticTriangle += p6->totalUsed-2;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( bTransparent )
+ {
+ if ( m_bStateColor )
+ {
+ tState = D3DSTATETTb|D3DSTATE2FACE;
+ tColor = 0x44444444;
+ }
+ else
+ {
+ tState = D3DSTATETTb;
+ tColor = 0x88888888;
+ }
+
+ // Draw transparent objects.
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ SetTexture(p2->texName1, 0);
+ SetTexture(p2->texName2, 1);
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ objRank = p3->objRank;
+ if ( m_bShadow && m_objectParam[objRank].type == TYPETERRAIN ) continue;
+ if ( !m_objectParam[objRank].bDrawWorld ) continue;
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ if ( !IsVisible(objRank) ) continue;
+ m_light->LightUpdate(m_objectParam[objRank].type);
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ if ( m_objectParam[objRank].distance < p4->min ||
+ m_objectParam[objRank].distance >= p4->max ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ SetMaterial(p6->material);
+ if ( m_objectParam[objRank].transparency == 0.0f ) continue;
+ SetState(tState, tColor);
+ if ( p6->type == D3DTYPE6T )
+ {
+ pv = &p6->vertex[0];
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
+ D3DFVF_VERTEX2,
+ pv, p6->totalUsed,
+ NULL);
+ m_statisticTriangle += p6->totalUsed/3;
+ }
+ if ( p6->type == D3DTYPE6S )
+ {
+ pv = &p6->vertex[0];
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
+ D3DFVF_VERTEX2,
+ pv, p6->totalUsed,
+ NULL);
+ m_statisticTriangle += p6->totalUsed-2;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ m_light->LightUpdate(TYPETERRAIN);
+ if ( m_bWaterMode ) m_water->DrawSurf(); // draws water
+//? m_cloud->Draw(); // draws the clouds
+
+ m_particule->DrawParticule(SH_WORLD); // draws the particles of the 3D world
+ m_blitz->Draw(); // draws lightning
+ if ( m_bLensMode ) DrawFrontsize(); // draws the foreground
+ if ( !m_bOverFront ) DrawOverColor(); // draws the foreground color
+ }
+
+ // Draw the user interface over the scene.
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ pInterface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+ if ( pInterface != 0 )
+ {
+ pInterface->Draw(); // draws the entire interface
+ }
+ m_particule->DrawParticule(SH_INTERFACE); // draws the particles of the interface
+
+ if ( m_bDrawFront )
+ {
+ // Display the objects
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, true);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZBIAS, F2DW(16));
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProj);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, m_ambiantColor[m_rankView]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, m_fogColor[m_rankView]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_LINEAR);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGSTART, F2DW(m_deepView[m_rankView]*m_fogStart[m_rankView]));
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGEND, F2DW(m_deepView[m_rankView]));
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matView);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ SetTexture(p2->texName1, 0);
+ SetTexture(p2->texName2, 1);
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ objRank = p3->objRank;
+ if ( !m_objectParam[objRank].bDrawFront ) continue;
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ if ( !IsVisible(objRank) ) continue;
+ m_light->LightUpdate(m_objectParam[objRank].type);
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ if ( m_objectParam[objRank].distance < p4->min ||
+ m_objectParam[objRank].distance >= p4->max ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ SetMaterial(p6->material);
+ SetState(p6->state);
+ if ( p6->type == D3DTYPE6T )
+ {
+ pv = &p6->vertex[0];
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
+ D3DFVF_VERTEX2,
+ pv, p6->totalUsed,
+ NULL);
+ m_statisticTriangle += p6->totalUsed/3;
+ }
+ if ( p6->type == D3DTYPE6S )
+ {
+ pv = &p6->vertex[0];
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
+ D3DFVF_VERTEX2,
+ pv, p6->totalUsed,
+ NULL);
+ m_statisticTriangle += p6->totalUsed-2;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ m_particule->DrawParticule(SH_FRONT); // draws the particles of the 3D world
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+ }
+
+ if ( m_bOverFront ) DrawOverColor(); // draws the foreground color
+
+ if ( m_mouseType != D3DMOUSEHIDE )
+ {
+ DrawMouse();
+ }
+
+ // End the scene.
+ m_pD3DDevice->EndScene();
+
+ DrawHilite();
+ return S_OK;
+}
+
+
+// Draw the gradient background.
+
+void CD3DEngine::DrawBackground()
+{
+ if ( m_bSkyMode && m_cloud->RetLevel() != 0.0f ) // clouds ?
+ {
+ if ( m_backgroundCloudUp != m_backgroundCloudDown ) // degraded?
+ {
+ DrawBackgroundGradient(m_backgroundCloudUp, m_backgroundCloudDown);
+ }
+ }
+ else
+ {
+ if ( m_backgroundColorUp != m_backgroundColorDown ) // degraded?
+ {
+ DrawBackgroundGradient(m_backgroundColorUp, m_backgroundColorDown);
+ }
+ }
+
+ if ( m_bBackForce || (m_bSkyMode && m_backgroundName[0] != 0) )
+ {
+ DrawBackgroundImage(); // image
+ }
+}
+
+// Draw the gradient background.
+
+void CD3DEngine::DrawBackgroundGradient(D3DCOLOR up, D3DCOLOR down)
+{
+ D3DLVERTEX vertex[4]; // 2 triangles
+ D3DCOLOR color[3];
+ Math::Point p1, p2;
+
+ p1.x = 0.0f;
+ p1.y = 0.5f;
+ p2.x = 1.0f;
+ p2.y = 1.0f;
+
+ color[0] = up;
+ color[1] = down;
+ color[2] = 0x00000000;
+
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+
+ SetTexture("xxx.tga"); // no texture
+ SetState(D3DSTATENORMAL);
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ vertex[0] = D3DLVERTEX(D3DVECTOR(p1.x, p1.y, 0.0f), color[1],color[2], 0.0f,0.0f);
+ vertex[1] = D3DLVERTEX(D3DVECTOR(p1.x, p2.y, 0.0f), color[0],color[2], 0.0f,0.0f);
+ vertex[2] = D3DLVERTEX(D3DVECTOR(p2.x, p1.y, 0.0f), color[1],color[2], 0.0f,0.0f);
+ vertex[3] = D3DLVERTEX(D3DVECTOR(p2.x, p2.y, 0.0f), color[0],color[2], 0.0f,0.0f);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, vertex, 4, NULL);
+ AddStatisticTriangle(2);
+}
+
+// Draws a portion of the image background.
+
+void CD3DEngine::DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, char *name)
+{
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Vector n;
+ float u1, u2, v1, v2, h, a;
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+
+ if ( m_bBackgroundFull )
+ {
+ u1 = 0.0f;
+ v1 = 0.0f;
+ u2 = 1.0f;
+ v2 = 1.0f;
+
+ if ( m_bBackgroundQuarter )
+ {
+ u1 += 0.5f/512.0f;
+ v1 += 0.5f/384.0f;
+ u2 -= 0.5f/512.0f;
+ v2 -= 0.5f/384.0f;
+ }
+ }
+ else
+ {
+ h = 0.5f; // visible area vertically (1=all)
+ a = m_eyeDirV-Math::PI*0.15f;
+ if ( a > Math::PI ) a -= Math::PI*2.0f; // a = -Math::PI..Math::PI
+ if ( a > Math::PI/4.0f ) a = Math::PI/4.0f;
+ if ( a < -Math::PI/4.0f ) a = -Math::PI/4.0f;
+
+ u1 = -m_eyeDirH/Math::PI;
+ u2 = u1+1.0f/Math::PI;
+//? u1 = -m_eyeDirH/(Math::PI*2.0f);
+//? u2 = u1+1.0f/(Math::PI*2.0f);
+
+ v1 = (1.0f-h)*(0.5f+a/(2.0f*Math::PI/4.0f))+0.1f;
+ v2 = v1+h;
+ }
+
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+
+ SetTexture(name);
+ SetState(D3DSTATEWRAP);
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ AddStatisticTriangle(2);
+}
+
+// Draws the image background.
+
+void CD3DEngine::DrawBackgroundImage()
+{
+ Math::Point p1, p2;
+ char name[50];
+
+ if ( m_bBackgroundQuarter )
+ {
+ p1.x = 0.0f;
+ p1.y = 0.5f;
+ p2.x = 0.5f;
+ p2.y = 1.0f;
+ QuarterName(name, m_backgroundName, 0);
+ DrawBackgroundImageQuarter(p1, p2, name);
+
+ p1.x = 0.5f;
+ p1.y = 0.5f;
+ p2.x = 1.0f;
+ p2.y = 1.0f;
+ QuarterName(name, m_backgroundName, 1);
+ DrawBackgroundImageQuarter(p1, p2, name);
+
+ p1.x = 0.0f;
+ p1.y = 0.0f;
+ p2.x = 0.5f;
+ p2.y = 0.5f;
+ QuarterName(name, m_backgroundName, 2);
+ DrawBackgroundImageQuarter(p1, p2, name);
+
+ p1.x = 0.5f;
+ p1.y = 0.0f;
+ p2.x = 1.0f;
+ p2.y = 0.5f;
+ QuarterName(name, m_backgroundName, 3);
+ DrawBackgroundImageQuarter(p1, p2, name);
+ }
+ else
+ {
+ p1.x = 0.0f;
+ p1.y = 0.0f;
+ p2.x = 1.0f;
+ p2.y = 1.0f;
+ DrawBackgroundImageQuarter(p1, p2, m_backgroundName);
+ }
+}
+
+// Draws all the planets.
+
+void CD3DEngine::DrawPlanet()
+{
+ if ( !m_planet->PlanetExist() ) return;
+
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ m_planet->Draw(); // draws the planets
+}
+
+// Draws the image foreground.
+
+void CD3DEngine::DrawFrontsize()
+{
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Vector n;
+ Math::Point p1, p2;
+ float u1, u2, v1, v2;
+
+ if ( m_frontsizeName[0] == 0 ) return;
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+
+ p1.x = 0.0f;
+ p1.y = 0.0f;
+ p2.x = 1.0f;
+ p2.y = 1.0f;
+
+ u1 = -m_eyeDirH/(Math::PI*0.6f)+Math::PI*0.5f;
+ u2 = u1+0.50f;
+
+ v1 = 0.2f;
+ v2 = 1.0f;
+
+#if 0
+ char s[100];
+ sprintf(s, "h=%.2f v=%.2f u=%.2f;%.2f v=%.2f;%.2f", m_eyeDirH, m_eyeDirV, u1, u2, v1, v2);
+ SetInfoText(3, s);
+#endif
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
+
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+
+ SetTexture(m_frontsizeName);
+ SetState(D3DSTATECLAMP|D3DSTATETTb);
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ AddStatisticTriangle(2);
+}
+
+// Draws the foreground color.
+
+void CD3DEngine::DrawOverColor()
+{
+ D3DLVERTEX vertex[4]; // 2 triangles
+ D3DCOLOR color[3];
+ Math::Point p1, p2;
+
+ if ( !m_bStateColor ) return;
+ if ( (m_overColor == 0x00000000 && m_overMode == D3DSTATETCb) ||
+ (m_overColor == 0xffffffff && m_overMode == D3DSTATETCw) ) return;
+
+ p1.x = 0.0f;
+ p1.y = 0.0f;
+ p2.x = 1.0f;
+ p2.y = 1.0f;
+
+ color[0] = m_overColor;
+ color[1] = m_overColor;
+ color[2] = 0x00000000;
+
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+
+ SetTexture("xxx.tga"); // no texture
+ SetState(m_overMode);
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ vertex[0] = D3DLVERTEX(D3DVECTOR(p1.x, p1.y, 0.0f), color[1],color[2], 0.0f,0.0f);
+ vertex[1] = D3DLVERTEX(D3DVECTOR(p1.x, p2.y, 0.0f), color[0],color[2], 0.0f,0.0f);
+ vertex[2] = D3DLVERTEX(D3DVECTOR(p2.x, p1.y, 0.0f), color[1],color[2], 0.0f,0.0f);
+ vertex[3] = D3DLVERTEX(D3DVECTOR(p2.x, p2.y, 0.0f), color[0],color[2], 0.0f,0.0f);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, vertex, 4, NULL);
+ AddStatisticTriangle(2);
+}
+
+
+// Lists the ranks of objects and subobjects selected.
+
+void CD3DEngine::SetHiliteRank(int *rankList)
+{
+ int i;
+
+ i = 0;
+ while ( *rankList != -1 )
+ {
+ m_hiliteRank[i++] = *rankList++;
+ }
+ m_hiliteRank[i] = -1; // terminator
+}
+
+// Give the box in the 2D screen of any object.
+
+bool CD3DEngine::GetBBox2D(int objRank, Math::Point &min, Math::Point &max)
+{
+ Math::Vector p, pp;
+ int i;
+
+ min.x = 1000000.0f;
+ min.y = 1000000.0f;
+ max.x = -1000000.0f;
+ max.y = -1000000.0f;
+
+ for ( i=0 ; i<8 ; i++ )
+ {
+ if ( i & (1<<0) ) p.x = m_objectParam[objRank].bboxMin.x;
+ else p.x = m_objectParam[objRank].bboxMax.x;
+ if ( i & (1<<1) ) p.y = m_objectParam[objRank].bboxMin.y;
+ else p.y = m_objectParam[objRank].bboxMax.y;
+ if ( i & (1<<2) ) p.z = m_objectParam[objRank].bboxMin.z;
+ else p.z = m_objectParam[objRank].bboxMax.z;
+ if ( TransformPoint(pp, objRank, p) )
+ {
+ if ( pp.x < min.x ) min.x = pp.x;
+ if ( pp.x > max.x ) max.x = pp.x;
+ if ( pp.y < min.y ) min.y = pp.y;
+ if ( pp.y > max.y ) max.y = pp.y;
+ }
+ }
+
+ if ( min.x == 1000000.0f ||
+ min.y == 1000000.0f ||
+ max.x == -1000000.0f ||
+ max.y == -1000000.0f ) return false;
+
+ return true;
+}
+
+// Determines the rectangle of the object highlighted, which will be designed by CD3DApplication.
+
+void CD3DEngine::DrawHilite()
+{
+ Math::Point min, max, omin, omax;
+ int i;
+
+ min.x = 1000000.0f;
+ min.y = 1000000.0f;
+ max.x = -1000000.0f;
+ max.y = -1000000.0f;
+
+ i = 0;
+ while ( m_hiliteRank[i] != -1 )
+ {
+ if ( GetBBox2D(m_hiliteRank[i++], omin, omax) )
+ {
+ min.x = Math::Min(min.x, omin.x);
+ min.y = Math::Min(min.y, omin.y);
+ max.x = Math::Max(max.x, omax.x);
+ max.y = Math::Max(max.y, omax.y);
+ }
+ }
+
+ if ( min.x == 1000000.0f ||
+ min.y == 1000000.0f ||
+ max.x == -1000000.0f ||
+ max.y == -1000000.0f )
+ {
+ m_bHilite = false; // not highlighted
+ }
+ else
+ {
+ m_hiliteP1 = min;
+ m_hiliteP2 = max;
+ m_bHilite = true;
+ }
+}
+
+// Give the rectangle highlighted by drawing CD3DApplication.
+
+bool CD3DEngine::GetHilite(Math::Point &p1, Math::Point &p2)
+{
+ p1 = m_hiliteP1;
+ p2 = m_hiliteP2;
+ return m_bHilite;
+}
+
+
+// Triangles adds qq records for statistics.
+
+void CD3DEngine::AddStatisticTriangle(int nb)
+{
+ m_statisticTriangle += nb;
+}
+
+// Returns the number of triangles rendered.
+
+int CD3DEngine::RetStatisticTriangle()
+{
+ return m_statisticTriangle;
+}
+
+bool CD3DEngine::GetSpriteCoord(int &x, int &y)
+{
+ D3DVIEWPORT7 vp;
+ Math::Vector v, vv;
+
+ return false;
+ //?
+ vv = Math::Vector(0.0f, 0.0f, 0.0f);
+ if ( !TransformPoint(v, 20*20+1, vv) ) return false;
+
+ m_pD3DDevice->GetViewport(&vp);
+ v.x *= vp.dwWidth/2;
+ v.y *= vp.dwHeight/2;
+ v.x = v.x+vp.dwWidth/2;
+ v.y = vp.dwHeight-(v.y+vp.dwHeight/2);
+
+ x = (int)v.x;
+ y = (int)v.y;
+ return true;
+}
+
+
+// Tests whether to exclude a point.
+
+bool IsExcludeColor(Math::Point *pExclu, int x, int y)
+{
+ int i;
+
+ i = 0;
+ while ( pExclu[i+0].x != 0.0f || pExclu[i+0].y != 0.0f ||
+ pExclu[i+1].y != 0.0f || pExclu[i+1].y != 0.0f )
+ {
+ if ( x >= (int)(pExclu[i+0].x*256.0f) &&
+ x < (int)(pExclu[i+1].x*256.0f) &&
+ y >= (int)(pExclu[i+0].y*256.0f) &&
+ y < (int)(pExclu[i+1].y*256.0f) ) return true; // exclude
+
+ i += 2;
+ }
+
+ return false; // point to include
+}
+
+// Change the color of a texture.
+
+bool CD3DEngine::ChangeColor(char *name,
+ D3DCOLORVALUE colorRef1, D3DCOLORVALUE colorNew1,
+ D3DCOLORVALUE colorRef2, D3DCOLORVALUE colorNew2,
+ float tolerance1, float tolerance2,
+ Math::Point ts, Math::Point ti,
+ Math::Point *pExclu, float shift, bool bHSV)
+{
+ LPDIRECTDRAWSURFACE7 surface;
+ DDSURFACEDESC2 ddsd;
+ D3DCOLORVALUE color;
+ ColorHSV cr1, cn1, cr2, cn2, c;
+ int dx, dy, x, y, sx, sy, ex, ey;
+
+ D3DTextr_Invalidate(name);
+ LoadTexture(name); // reloads the initial texture
+
+ if ( colorRef1.r == colorNew1.r &&
+ colorRef1.g == colorNew1.g &&
+ colorRef1.b == colorNew1.b &&
+ colorRef2.r == colorNew2.r &&
+ colorRef2.g == colorNew2.g &&
+ colorRef2.b == colorNew2.b ) return true;
+
+ surface = D3DTextr_GetSurface(name);
+ if ( surface == 0 ) return false;
+
+ ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
+ ddsd.dwSize = sizeof(DDSURFACEDESC2);
+ if ( surface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK ) return false;
+
+ dx = ddsd.dwWidth;
+ dy = ddsd.dwHeight;
+
+ sx = (int)(ts.x*dx);
+ sy = (int)(ts.y*dy);
+ ex = (int)(ti.x*dx);
+ ey = (int)(ti.y*dy);
+
+ RGB2HSV(colorRef1, cr1);
+ RGB2HSV(colorNew1, cn1);
+ RGB2HSV(colorRef2, cr2);
+ RGB2HSV(colorNew2, cn2);
+
+ for ( y=sy ; y<ey ; y++ )
+ {
+ for ( x=sx ; x<ex ; x++ )
+ {
+ if ( pExclu != 0 && IsExcludeColor(pExclu, x,y) ) continue;
+
+ color = GetDot(&ddsd, x, y);
+
+ if ( bHSV )
+ {
+ RGB2HSV(color, c);
+ if ( c.s > 0.01f && fabs(c.h-cr1.h) < tolerance1 )
+ {
+ c.h += cn1.h-cr1.h;
+ c.s += cn1.s-cr1.s;
+ c.v += cn1.v-cr1.v;
+ if ( c.h < 0.0f ) c.h -= 1.0f;
+ if ( c.h > 1.0f ) c.h += 1.0f;
+ HSV2RGB(c, color);
+ color.r += shift;
+ color.g += shift;
+ color.b += shift;
+ ::SetDot(&ddsd, x, y, color);
+ }
+ else
+ if ( tolerance2 != -1.0f &&
+ c.s > 0.01f && fabs(c.h-cr2.h) < tolerance2 )
+ {
+ c.h += cn2.h-cr2.h;
+ c.s += cn2.s-cr2.s;
+ c.v += cn2.v-cr2.v;
+ if ( c.h < 0.0f ) c.h -= 1.0f;
+ if ( c.h > 1.0f ) c.h += 1.0f;
+ HSV2RGB(c, color);
+ color.r += shift;
+ color.g += shift;
+ color.b += shift;
+ ::SetDot(&ddsd, x, y, color);
+ }
+ }
+ else
+ {
+ if ( fabs(color.r-colorRef1.r)+
+ fabs(color.g-colorRef1.g)+
+ fabs(color.b-colorRef1.b) < tolerance1*3.0f )
+ {
+ color.r = colorNew1.r+color.r-colorRef1.r+shift;
+ color.g = colorNew1.g+color.g-colorRef1.g+shift;
+ color.b = colorNew1.b+color.b-colorRef1.b+shift;
+ ::SetDot(&ddsd, x, y, color);
+ }
+ else
+ if ( tolerance2 != -1 &&
+ fabs(color.r-colorRef2.r)+
+ fabs(color.g-colorRef2.g)+
+ fabs(color.b-colorRef2.b) < tolerance2*3.0f )
+ {
+ color.r = colorNew2.r+color.r-colorRef2.r+shift;
+ color.g = colorNew2.g+color.g-colorRef2.g+shift;
+ color.b = colorNew2.b+color.b-colorRef2.b+shift;
+ ::SetDot(&ddsd, x, y, color);
+ }
+ }
+ }
+ }
+
+ surface->Unlock(NULL);
+ return true;
+}
+
+
+// Open an image to work directly in it.
+
+bool CD3DEngine::OpenImage(char *name)
+{
+//? D3DTextr_Invalidate(name);
+//? LoadTexture(name);
+
+ m_imageSurface = D3DTextr_GetSurface(name);
+ if ( m_imageSurface == 0 ) return false;
+
+ ZeroMemory(&m_imageDDSD, sizeof(DDSURFACEDESC2));
+ m_imageDDSD.dwSize = sizeof(DDSURFACEDESC2);
+ if ( m_imageSurface->Lock(NULL, &m_imageDDSD, DDLOCK_WAIT, NULL) != DD_OK )
+ {
+ return false;
+ }
+
+ if ( m_imageDDSD.ddpfPixelFormat.dwRGBBitCount != 16 )
+ {
+ m_imageSurface->Unlock(NULL);
+ return false;
+ }
+
+ m_imageDX = m_imageDDSD.dwWidth;
+ m_imageDY = m_imageDDSD.dwHeight;
+
+ return true;
+}
+
+// Copy the working image.
+
+bool CD3DEngine::CopyImage()
+{
+ WORD* pbSurf;
+ int y;
+
+ if ( m_imageCopy == 0 )
+ {
+ m_imageCopy = (WORD*)malloc(m_imageDX*m_imageDY*sizeof(WORD));
+ }
+
+ for ( y=0 ; y<m_imageDY ; y++ )
+ {
+ pbSurf = (WORD*)m_imageDDSD.lpSurface;
+ pbSurf += m_imageDDSD.lPitch*y/2;
+ memcpy(m_imageCopy+y*m_imageDX, pbSurf, m_imageDX*sizeof(WORD));
+ }
+ return true;
+}
+
+// Restores the image work.
+
+bool CD3DEngine::LoadImage()
+{
+ WORD* pbSurf;
+ int y;
+
+ if ( m_imageCopy == 0 ) return false;
+
+ for ( y=0 ; y<m_imageDY ; y++ )
+ {
+ pbSurf = (WORD*)m_imageDDSD.lpSurface;
+ pbSurf += m_imageDDSD.lPitch*y/2;
+ memcpy(pbSurf, m_imageCopy+y*m_imageDX, m_imageDX*sizeof(WORD));
+ }
+ return true;
+}
+
+// Scroll the copy of the working image.
+
+bool CD3DEngine::ScrollImage(int dx, int dy)
+{
+ int x, y;
+
+ if ( dx > 0 )
+ {
+ for ( y=0 ; y<m_imageDY ; y++ )
+ {
+ for ( x=0 ; x<m_imageDX-dx ; x++ )
+ {
+ m_imageCopy[x+y*m_imageDX] = m_imageCopy[x+dx+y*m_imageDX];
+ }
+ }
+ }
+
+ if ( dx < 0 )
+ {
+ for ( y=0 ; y<m_imageDY ; y++ )
+ {
+ for ( x=m_imageDX-1 ; x>=-dx ; x-- )
+ {
+ m_imageCopy[x+y*m_imageDX] = m_imageCopy[x+dx+y*m_imageDX];
+ }
+ }
+ }
+
+ if ( dy > 0 )
+ {
+ for ( y=0 ; y<m_imageDY-dy ; y++ )
+ {
+ memcpy(m_imageCopy+y*m_imageDX, m_imageCopy+(y+dy)*m_imageDX, m_imageDX*sizeof(WORD));
+ }
+ }
+
+ if ( dy < 0 )
+ {
+ for ( y=m_imageDY-1 ; y>=-dy ; y-- )
+ {
+ memcpy(m_imageCopy+y*m_imageDX, m_imageCopy+(y+dy)*m_imageDX, m_imageDX*sizeof(WORD));
+ }
+ }
+
+ return true;
+}
+
+// Draws a point in the image work.
+
+bool CD3DEngine::SetDot(int x, int y, D3DCOLORVALUE color)
+{
+ WORD* pbSurf;
+ WORD r,g,b, w;
+
+ if ( x < 0 || x >= m_imageDX ||
+ y < 0 || y >= m_imageDY ) return false;
+
+#if 1
+ if ( color.r < 0.0f ) color.r = 0.0f;
+ if ( color.r > 1.0f ) color.r = 1.0f;
+ if ( color.g < 0.0f ) color.g = 0.0f;
+ if ( color.g > 1.0f ) color.g = 1.0f;
+ if ( color.b < 0.0f ) color.b = 0.0f;
+ if ( color.b > 1.0f ) color.b = 1.0f;
+
+ r = (int)(color.r*32.0f);
+ g = (int)(color.g*32.0f);
+ b = (int)(color.b*32.0f);
+
+ if ( r >= 32 ) r = 31; // 5 bits
+ if ( g >= 32 ) g = 31; // 5 bits
+ if ( b >= 32 ) b = 31; // 5 bits
+#else
+ r = (int)(color.r*31.0f);
+ g = (int)(color.g*31.0f);
+ b = (int)(color.b*31.0f);
+#endif
+
+ if ( m_imageDDSD.ddpfPixelFormat.dwRBitMask == 0xf800 ) // 565 ?
+ {
+ w = (r<<11)|(g<<6)|b;
+ }
+ else if ( m_imageDDSD.ddpfPixelFormat.dwRBitMask == 0x7c00 ) // 555 ?
+ {
+ w = (r<<10)|(g<<5)|b;
+ }
+ else
+ {
+ w = -1; // blank
+ }
+
+ pbSurf = (WORD*)m_imageDDSD.lpSurface;
+ pbSurf += m_imageDDSD.lPitch*y/2;
+ pbSurf += x;
+
+ *pbSurf = w;
+ return true;
+}
+
+// Closes the working image.
+
+bool CD3DEngine::CloseImage()
+{
+ m_imageSurface->Unlock(NULL);
+ return true;
+}
+
+
+// Writes a .BMP screenshot.
+
+bool CD3DEngine::WriteScreenShot(char *filename, int width, int height)
+{
+ return m_app->WriteScreenShot(filename, width, height);
+}
+
+// Initializes an hDC on the rendering surface.
+
+bool CD3DEngine::GetRenderDC(HDC &hDC)
+{
+ return m_app->GetRenderDC(hDC);
+}
+
+// Frees the hDC of the rendering surface.
+
+bool CD3DEngine::ReleaseRenderDC(HDC &hDC)
+{
+ return m_app->ReleaseRenderDC(hDC);
+}
+
+PBITMAPINFO CD3DEngine::CreateBitmapInfoStruct(HBITMAP hBmp)
+{
+ return m_app->CreateBitmapInfoStruct(hBmp);
+}
+
+bool CD3DEngine::CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC)
+{
+ return m_app->CreateBMPFile(pszFile, pbi, hBMP, hDC);
+}
+
+// Returns the pointer to the class cText.
+
+CText* CD3DEngine::RetText()
+{
+ return m_text;
+}
+
+
+// Managing of information text displayed in the window.
+
+void CD3DEngine::SetInfoText(int line, char* text)
+{
+ strcpy(m_infoText[line], text);
+}
+
+char* CD3DEngine::RetInfoText(int line)
+{
+ return m_infoText[line];
+}
+
+
+
+// Specifies the length of the camera.
+// 0.75 = normal
+// 1.50 = wide-angle
+
+void CD3DEngine::SetFocus(float focus)
+{
+ D3DVIEWPORT7 vp;
+ float fAspect;
+
+ m_focus = focus;
+
+ if ( m_pD3DDevice != 0 )
+ {
+ m_pD3DDevice->GetViewport(&vp);
+ m_dim.x = vp.dwWidth;
+ m_dim.y = vp.dwHeight;
+ }
+
+ fAspect = ((float)m_dim.y) / m_dim.x;
+//? Math::LoadProjectionMatrix(m_matProj, m_focus, fAspect, 0.5f, m_deepView[m_rankView]);
+ Math::LoadProjectionMatrix(m_matProj, m_focus, fAspect, 0.5f, m_deepView[0]);
+}
+
+float CD3DEngine::RetFocus()
+{
+ return m_focus;
+}
+
+//
+
+void CD3DEngine::UpdateMatProj()
+{
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProj);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+}
+
+
+
+// Ignores key presses.
+
+void CD3DEngine::FlushPressKey()
+{
+ m_app->FlushPressKey();
+}
+
+// Resets the default keys.
+
+void CD3DEngine::ResetKey()
+{
+ m_app->ResetKey();
+}
+
+// Modifies a button.
+
+void CD3DEngine::SetKey(int keyRank, int option, int key)
+{
+ m_app->SetKey(keyRank, option, key);
+}
+
+// Gives a key.
+
+int CD3DEngine::RetKey(int keyRank, int option)
+{
+ return m_app->RetKey(keyRank, option);
+}
+
+
+// Use the joystick or keyboard.
+
+void CD3DEngine::SetJoystick(bool bEnable)
+{
+ m_app->SetJoystick(bEnable);
+}
+
+bool CD3DEngine::RetJoystick()
+{
+ return m_app->RetJoystick();
+}
+
+
+void CD3DEngine::SetDebugMode(bool bMode)
+{
+ m_app->SetDebugMode(bMode);
+}
+
+bool CD3DEngine::RetDebugMode()
+{
+ return m_app->RetDebugMode();
+}
+
+bool CD3DEngine::RetSetupMode()
+{
+ return m_app->RetSetupMode();
+}
+
+
+// Indicates whether a point is visible.
+
+bool CD3DEngine::IsVisiblePoint(const Math::Vector &pos)
+{
+ return ( Math::Distance(m_eyePt, pos) <= m_deepView[0] );
+}
+
+
+// Initialize scene objects.
+
+HRESULT CD3DEngine::InitDeviceObjects()
+{
+ // Set miscellaneous render states.
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SPECULARENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID);
+
+ // Set up the textures.
+ D3DTextr_RestoreAllTextures(m_pD3DDevice);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_MINFILTER, D3DTFN_LINEAR);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
+
+ SetFocus(m_focus);
+
+ // Definitions of the matrices for the interface.
+ m_matWorldInterface.LoadIdentity();
+
+ m_matViewInterface.LoadIdentity();
+ m_matViewInterface.Set(1, 4, -0.5f);
+ m_matViewInterface.Set(2, 4, -0.5f);
+ m_matViewInterface.Set(3, 4, 1.0f);
+
+ m_matProjInterface.LoadIdentity();
+ m_matProjInterface.Set(1, 1, 2.0f);
+ m_matProjInterface.Set(2, 2, 2.0f);
+ m_matProjInterface.Set(4, 3, 1.0f);
+ m_matProjInterface.Set(3, 4, -1.0f);
+ m_matProjInterface.Set(4, 4, 0.0f);
+
+ return S_OK;
+}
+
+
+// Restore all surfaces.
+
+HRESULT CD3DEngine::RestoreSurfaces()
+{
+ return S_OK;
+}
+
+
+// Called when the app is exitting, or the device is being changed,
+// this function deletes any device dependant objects.
+
+HRESULT CD3DEngine::DeleteDeviceObjects()
+{
+ D3DTextr_InvalidateAllTextures();
+ return S_OK;
+}
+
+
+// Called before the app exits, this function gives the app the chance
+// to cleanup after itself.
+
+HRESULT CD3DEngine::FinalCleanup()
+{
+ return S_OK;
+}
+
+
+// Overrrides the main WndProc, so the sample can do custom message
+// handling (e.g. processing mouse, keyboard, or menu commands).
+
+LRESULT CD3DEngine::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+#if 0
+ if ( uMsg == WM_KEYDOWN ) // Alt+key ?
+ {
+ if ( wParam == 'Q' )
+ {
+ debug_blend1 ++;
+ if ( debug_blend1 > 13 ) debug_blend1 = 0;
+ }
+ if ( wParam == 'W' )
+ {
+ debug_blend2 ++;
+ if ( debug_blend2 > 13 ) debug_blend2 = 0;
+ }
+ if ( wParam == 'E' )
+ {
+ debug_blend3 ++;
+ if ( debug_blend3 > 13 ) debug_blend3 = 0;
+ }
+ if ( wParam == 'R' )
+ {
+ debug_blend4 ++;
+ if ( debug_blend4 > 13 ) debug_blend4 = 0;
+ }
+ char s[100];
+ sprintf(s, "src=%d, dest=%d, src=%d, dest=%d", debug_blend1, debug_blend2, debug_blend3, debug_blend4);
+ SetInfoText(4, s);
+ }
+#endif
+
+#if 1
+ if ( uMsg == WM_SYSKEYDOWN ) // Alt+key ?
+ {
+ if ( wParam == VK_F7 ) // Alt+F7 ?
+ {
+ s_resol = 0;
+ }
+ if ( wParam == VK_F8 ) // Alt+F8 ?
+ {
+ s_resol = 1;
+ }
+ if ( wParam == VK_F9 ) // Alt+F9 ?
+ {
+ s_resol = 2;
+ }
+ if ( wParam == VK_F10 ) // Alt+F10 ?
+ {
+ s_resol = 3;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+
+// Mouse control.
+
+void CD3DEngine::MoveMousePos(Math::Point pos)
+{
+ m_mousePos = pos;
+ m_app->SetMousePos(pos);
+}
+
+void CD3DEngine::SetMousePos(Math::Point pos)
+{
+ m_mousePos = pos;
+}
+
+Math::Point CD3DEngine::RetMousePos()
+{
+ return m_mousePos;
+}
+
+void CD3DEngine::SetMouseType(D3DMouse type)
+{
+ m_mouseType = type;
+}
+
+D3DMouse CD3DEngine::RetMouseType()
+{
+ return m_mouseType;
+}
+
+void CD3DEngine::SetMouseHide(bool bHide)
+{
+ if ( m_bMouseHide == bHide ) return;
+
+ if ( bHide ) // hide the mouse?
+ {
+ m_bNiceMouse = m_app->RetNiceMouse();
+ if ( !m_bNiceMouse )
+ {
+ m_app->SetNiceMouse(true);
+ }
+ m_bMouseHide = true;
+ }
+ else // shows the mouse?
+ {
+ if ( !m_bNiceMouse )
+ {
+ m_app->SetNiceMouse(false);
+ }
+ m_bMouseHide = false;
+ }
+}
+
+bool CD3DEngine::RetMouseHide()
+{
+ return m_bMouseHide;
+}
+
+void CD3DEngine::SetNiceMouse(bool bNice)
+{
+ m_app->SetNiceMouse(bNice);
+}
+
+bool CD3DEngine::RetNiceMouse()
+{
+ return m_app->RetNiceMouse();
+}
+
+bool CD3DEngine::RetNiceMouseCap()
+{
+ return m_app->RetNiceMouseCap();
+}
+
+// Draws the sprite of the mouse.
+
+void CD3DEngine::DrawMouse()
+{
+ D3DMATERIAL7 material;
+ Math::Point pos, ppos, dim;
+ int i;
+
+ struct Mouse
+ {
+ D3DMouse type;
+ int icon1, icon2, iconShadow;
+ int mode1, mode2;
+ float hotx, hoty;
+ };
+
+ static Mouse table[] =
+ {
+ { D3DMOUSENORM, 0, 1,32, D3DSTATETTw, D3DSTATETTb, 1.0f, 1.0f},
+ { D3DMOUSEWAIT, 2, 3,33, D3DSTATETTw, D3DSTATETTb, 8.0f, 12.0f},
+ { D3DMOUSEHAND, 4, 5,34, D3DSTATETTw, D3DSTATETTb, 7.0f, 2.0f},
+ { D3DMOUSENO, 6, 7,35, D3DSTATETTw, D3DSTATETTb, 10.0f, 10.0f},
+ { D3DMOUSEEDIT, 8, 9,-1, D3DSTATETTb, D3DSTATETTw, 6.0f, 10.0f},
+ { D3DMOUSECROSS, 10,11,-1, D3DSTATETTb, D3DSTATETTw, 10.0f, 10.0f},
+ { D3DMOUSEMOVEV, 12,13,-1, D3DSTATETTb, D3DSTATETTw, 5.0f, 11.0f},
+ { D3DMOUSEMOVEH, 14,15,-1, D3DSTATETTb, D3DSTATETTw, 11.0f, 5.0f},
+ { D3DMOUSEMOVED, 16,17,-1, D3DSTATETTb, D3DSTATETTw, 9.0f, 9.0f},
+ { D3DMOUSEMOVEI, 18,19,-1, D3DSTATETTb, D3DSTATETTw, 9.0f, 9.0f},
+ { D3DMOUSEMOVE, 20,21,-1, D3DSTATETTb, D3DSTATETTw, 11.0f, 11.0f},
+ { D3DMOUSETARGET, 22,23,-1, D3DSTATETTb, D3DSTATETTw, 15.0f, 15.0f},
+ { D3DMOUSESCROLLL, 24,25,43, D3DSTATETTb, D3DSTATETTw, 2.0f, 9.0f},
+ { D3DMOUSESCROLLR, 26,27,44, D3DSTATETTb, D3DSTATETTw, 17.0f, 9.0f},
+ { D3DMOUSESCROLLU, 28,29,45, D3DSTATETTb, D3DSTATETTw, 9.0f, 2.0f},
+ { D3DMOUSESCROLLD, 30,31,46, D3DSTATETTb, D3DSTATETTw, 9.0f, 17.0f},
+ { D3DMOUSEHIDE },
+ };
+
+ if ( m_bMouseHide ) return;
+ if ( !m_app->RetNiceMouse() ) return; // mouse windows?
+
+ ZeroMemory( &material, sizeof(D3DMATERIAL7) );
+ material.diffuse.r = 1.0f;
+ material.diffuse.g = 1.0f;
+ material.diffuse.b = 1.0f;
+ material.ambient.r = 0.5f;
+ material.ambient.g = 0.5f;
+ material.ambient.b = 0.5f;
+ SetMaterial(material);
+
+ SetTexture("mouse.tga");
+
+ i = 0;
+ while ( table[i].type != D3DMOUSEHIDE )
+ {
+ if ( m_mouseType == table[i].type )
+ {
+ dim.x = 0.05f*0.75f;
+ dim.y = 0.05f;
+
+ pos.x = m_mousePos.x - (table[i].hotx*dim.x)/32.0f;
+ pos.y = m_mousePos.y - ((32.0f-table[i].hoty)*dim.y)/32.0f;
+
+ ppos.x = pos.x+(4.0f/640.0f);
+ ppos.y = pos.y-(3.0f/480.0f);
+ SetState(D3DSTATETTw);
+ DrawSprite(ppos, dim, table[i].iconShadow);
+
+ SetState(table[i].mode1);
+ DrawSprite(pos, dim, table[i].icon1);
+
+ SetState(table[i].mode2);
+ DrawSprite(pos, dim, table[i].icon2);
+ break;
+ }
+ i ++;
+ }
+}
+
+// Draws the sprite of the mouse.
+
+void CD3DEngine::DrawSprite(Math::Point pos, Math::Point dim, int icon)
+{
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Point p1, p2;
+ Math::Vector n;
+ float u1, u2, v1, v2, dp;
+
+ if ( icon == -1 ) return;
+
+ p1.x = pos.x;
+ p1.y = pos.y;
+ p2.x = pos.x + dim.x;
+ p2.y = pos.y + dim.y;
+
+ u1 = (32.0f/256.0f)*(icon%8);
+ v1 = (32.0f/256.0f)*(icon/8); // u-v texture
+ u2 = (32.0f/256.0f)+u1;
+ v2 = (32.0f/256.0f)+v1;
+
+ dp = 0.5f/256.0f;
+ u1 += dp;
+ v1 += dp;
+ u2 -= dp;
+ v2 -= dp;
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ AddStatisticTriangle(2);
+}
+
diff --git a/src/old/d3dengine.h b/src/old/d3dengine.h
index d028d2c..700e7b3 100644
--- a/src/old/d3dengine.h
+++ b/src/old/d3dengine.h
@@ -1,676 +1,678 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// d3dengine.h
-
-#pragma once
-
-
-#include "math/point.h"
-#include "math/vector.h"
-#include "math/matrix.h"
-#include "common/struct.h"
-
-
-class CD3DApplication;
-class CInstanceManager;
-class CObject;
-class CLight;
-class CText;
-class CParticule;
-class CWater;
-class CCloud;
-class CBlitz;
-class CPlanet;
-class CSound;
-class CTerrain;
-
-
-const int D3DMAXOBJECT = 1200;
-const int D3DMAXSHADOW = 500;
-const int D3DMAXGROUNDSPOT = 100;
-
-
-enum D3DTypeObj
-{
- TYPENULL = 0, // object doesn't exist
- TYPETERRAIN = 1, // terrain
- TYPEFIX = 2, // fixed object
- TYPEVEHICULE = 3, // moving object
- TYPEDESCENDANT = 4, // part of a moving object
- TYPEQUARTZ = 5, // fixed object type quartz
- TYPEMETAL = 6, // fixed object type metal
-};
-
-enum D3DTypeTri
-{
- D3DTYPE6T = 1, // triangles
- D3DTYPE6S = 2, // surfaces
-};
-
-enum D3DMaping
-{
- D3DMAPPINGX = 1,
- D3DMAPPINGY = 2,
- D3DMAPPINGZ = 3,
- D3DMAPPING1X = 4,
- D3DMAPPING1Y = 5,
- D3DMAPPING1Z = 6,
-};
-
-enum D3DMouse
-{
- D3DMOUSEHIDE = 0, // no mouse
- D3DMOUSENORM = 1,
- D3DMOUSEWAIT = 2,
- D3DMOUSEEDIT = 3,
- D3DMOUSEHAND = 4,
- D3DMOUSECROSS = 5,
- D3DMOUSESHOW = 6,
- D3DMOUSENO = 7,
- D3DMOUSEMOVE = 8, // +
- D3DMOUSEMOVEH = 9, // -
- D3DMOUSEMOVEV = 10, // |
- D3DMOUSEMOVED = 11, // /
- D3DMOUSEMOVEI = 12, // \ //
- D3DMOUSESCROLLL = 13, // <<
- D3DMOUSESCROLLR = 14, // >>
- D3DMOUSESCROLLU = 15, // ^
- D3DMOUSESCROLLD = 16, // v
- D3DMOUSETARGET = 17,
-};
-
-enum D3DShadowType
-{
- D3DSHADOWNORM = 0,
- D3DSHADOWWORM = 1,
-};
-
-
-const int D3DSTATENORMAL = 0; // normal opaque materials
-const int D3DSTATETTb = (1<<0); // the transparent texture (black = no)
-const int D3DSTATETTw = (1<<1); // the transparent texture (white = no)
-const int D3DSTATETD = (1<<2); // the transparent diffuse color
-const int D3DSTATEWRAP = (1<<3); // texture wrappe
-const int D3DSTATECLAMP = (1<<4); // texture borders with solid color
-const int D3DSTATELIGHT = (1<<5); // light texture (ambient max)
-const int D3DSTATEDUALb = (1<<6); // double black texturing
-const int D3DSTATEDUALw = (1<<7); // double white texturing
-const int D3DSTATEPART1 = (1<<8); // part 1 (no change in. MOD!)
-const int D3DSTATEPART2 = (1<<9); // part 2
-const int D3DSTATEPART3 = (1<<10); // part 3
-const int D3DSTATEPART4 = (1<<11); // part 4
-const int D3DSTATE2FACE = (1<<12); // double-sided face
-const int D3DSTATEALPHA = (1<<13); // image using alpha channel
-const int D3DSTATESECOND = (1<<14); // always use 2nd floor texturing
-const int D3DSTATEFOG = (1<<15); // causes the fog
-const int D3DSTATETCb = (1<<16); // the transparent color (black = no)
-const int D3DSTATETCw = (1<<17); // the transparent color (white = no)
-
-
-struct D3DTriangle
-{
- D3DVERTEX2 triangle[3];
- D3DMATERIAL7 material;
- int state;
- char texName1[20];
- char texName2[20];
-};
-
-
-struct D3DObjLevel6
-{
- int totalPossible;
- int totalUsed;
- D3DMATERIAL7 material;
- int state;
- D3DTypeTri type; // D3DTYPE6x
- D3DVERTEX2 vertex[1];
-};
-
-struct D3DObjLevel5
-{
- int totalPossible;
- int totalUsed;
- int reserve;
- D3DObjLevel6* table[1];
-};
-
-struct D3DObjLevel4
-{
- int totalPossible;
- int totalUsed;
- float min, max;
- D3DObjLevel5* table[1];
-};
-
-struct D3DObjLevel3
-{
- int totalPossible;
- int totalUsed;
- int objRank;
- D3DObjLevel4* table[1];
-};
-
-struct D3DObjLevel2
-{
- int totalPossible;
- int totalUsed;
- char texName1[20];
- char texName2[20];
- D3DObjLevel3* table[1];
-};
-
-struct D3DObjLevel1
-{
- int totalPossible;
- int totalUsed;
- D3DObjLevel2* table[1];
-};
-
-
-struct D3DObject
-{
- char bUsed; // true -> object exists
- char bVisible; // true -> visible object
- char bDrawWorld; // true -> shape behind the interface
- char bDrawFront; // true -> shape before the interface
- int totalTriangle; // number of triangles used
- D3DTypeObj type; // type of the object (TYPE*)
- Math::Matrix transform; // transformation matrix
- float distance; // distance point of view - original
- Math::Vector bboxMin; // bounding box of the object
- Math::Vector bboxMax; // (the origin 0, 0, 0 is always included)
- float radius; // radius of the sphere at the origin
- int shadowRank; // rank of the associated shadow
- float transparency; // transparency of the object (0 .. 1)
-};
-
-struct D3DShadow
-{
- char bUsed; // true -> object exists
- char bHide; // true -> invisible shadow (object carried by ex.)
- int objRank; // rank of the object
- D3DShadowType type; // type of shadow
- Math::Vector pos; // position for the shadow
- Math::Vector normal; // normal terrain
- float angle; // angle of the shadow
- float radius; // radius of the shadow
- float intensity; // intensity of the shadow
- float height; // height from the ground
-};
-
-struct D3DGroundSpot
-{
- char bUsed; // true -> object exists
- D3DCOLORVALUE color; // color of the shadow
- float min, max; // altitudes min / max
- float smooth; // transition area
- Math::Vector pos; // position for the shadow
- float radius; // radius of the shadow
- Math::Vector drawPos; // drawn to position the shade
- float drawRadius; // radius of the shadow drawn
-};
-
-struct D3DGroundMark
-{
- char bUsed; // true -> object exists
- char bDraw; // true -> drawn mark
- int phase; // 1 = increase, 2 = fixed, 3 = decrease
- float delay[3]; // time for 3 phases
- float fix; // fixed time
- Math::Vector pos; // position for marks
- float radius; // radius of marks
- float intensity; // color intensity
- Math::Vector drawPos; // drawn in position marks
- float drawRadius; // radius marks drawn
- float drawIntensity; // current drawn
- int dx, dy; // dimensions table
- char* table; // pointer to the table
-};
-
-
-
-class CD3DEngine
-{
-public:
- CD3DEngine(CInstanceManager *iMan, CD3DApplication *app);
- ~CD3DEngine();
-
- void SetD3DDevice(LPDIRECT3DDEVICE7 device);
- LPDIRECT3DDEVICE7 RetD3DDevice();
-
- void SetTerrain(CTerrain* terrain);
-
- bool WriteProfile();
-
- void SetPause(bool bPause);
- bool RetPause();
-
- void SetMovieLock(bool bLock);
- bool RetMovieLock();
-
- void SetShowStat(bool bShow);
- bool RetShowStat();
-
- void SetRenderEnable(bool bEnable);
-
- HRESULT OneTimeSceneInit();
- HRESULT InitDeviceObjects();
- HRESULT DeleteDeviceObjects();
- HRESULT RestoreSurfaces();
- HRESULT Render();
- HRESULT FrameMove(float rTime);
- void StepSimul(float rTime);
- HRESULT FinalCleanup();
- void AddStatisticTriangle(int nb);
- int RetStatisticTriangle();
- void SetHiliteRank(int *rankList);
- bool GetHilite(Math::Point &p1, Math::Point &p2);
- bool GetSpriteCoord(int &x, int &y);
- void SetInfoText(int line, char* text);
- char* RetInfoText(int line);
- LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
- void FirstExecuteAdapt(bool bFirst);
- int GetVidMemTotal();
- bool IsVideo8MB();
- bool IsVideo32MB();
-
- bool EnumDevices(char *bufDevices, int lenDevices, char *bufModes, int lenModes, int &totalDevices, int &selectDevices, int &totalModes, int &selectModes);
- bool RetFullScreen();
- bool ChangeDevice(char *device, char *mode, bool bFull);
-
- Math::Matrix* RetMatView();
- Math::Matrix* RetMatLeftView();
- Math::Matrix* RetMatRightView();
-
- void TimeInit();
- void TimeEnterGel();
- void TimeExitGel();
- float TimeGet();
-
- int RetRestCreate();
- int CreateObject();
- void FlushObject();
- bool DeleteObject(int objRank);
- bool SetDrawWorld(int objRank, bool bDraw);
- bool SetDrawFront(int objRank, bool bDraw);
- bool AddTriangle(int objRank, D3DVERTEX2* vertex, int nb, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max, bool bGlobalUpdate);
- bool AddSurface(int objRank, D3DVERTEX2* vertex, int nb, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max, bool bGlobalUpdate);
- bool AddQuick(int objRank, D3DObjLevel6* buffer, char* texName1, char* texName2, float min, float max, bool bGlobalUpdate);
- D3DObjLevel6* SearchTriangle(int objRank, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max);
- void ChangeLOD();
- bool ChangeSecondTexture(int objRank, char* texName2);
- int RetTotalTriangles(int objRank);
- int GetTriangles(int objRank, float min, float max, D3DTriangle* buffer, int size, float percent);
- bool GetBBox(int objRank, Math::Vector &min, Math::Vector &max);
- bool ChangeTextureMapping(int objRank, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max, D3DMaping mode, float au, float bu, float av, float bv);
- bool TrackTextureMapping(int objRank, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max, D3DMaping mode, float pos, float factor, float tl, float ts, float tt);
- bool SetObjectTransform(int objRank, const Math::Matrix &transform);
- bool GetObjectTransform(int objRank, Math::Matrix &transform);
- bool SetObjectType(int objRank, D3DTypeObj type);
- D3DTypeObj RetObjectType(int objRank);
- bool SetObjectTransparency(int objRank, float value);
-
- bool ShadowCreate(int objRank);
- void ShadowDelete(int objRank);
- bool SetObjectShadowHide(int objRank, bool bHide);
- bool SetObjectShadowType(int objRank, D3DShadowType type);
- bool SetObjectShadowPos(int objRank, const Math::Vector &pos);
- bool SetObjectShadowNormal(int objRank, const Math::Vector &n);
- bool SetObjectShadowAngle(int objRank, float angle);
- bool SetObjectShadowRadius(int objRank, float radius);
- bool SetObjectShadowIntensity(int objRank, float intensity);
- bool SetObjectShadowHeight(int objRank, float h);
- float RetObjectShadowRadius(int objRank);
-
- void GroundSpotFlush();
- int GroundSpotCreate();
- void GroundSpotDelete(int rank);
- bool SetObjectGroundSpotPos(int rank, const Math::Vector &pos);
- bool SetObjectGroundSpotRadius(int rank, float radius);
- bool SetObjectGroundSpotColor(int rank, D3DCOLORVALUE color);
- bool SetObjectGroundSpotMinMax(int rank, float min, float max);
- bool SetObjectGroundSpotSmooth(int rank, float smooth);
-
- int GroundMarkCreate(Math::Vector pos, float radius, float delay1, float delay2, float delay3, int dx, int dy, char* table);
- bool GroundMarkDelete(int rank);
-
- void Update();
-
- void SetViewParams(const Math::Vector &vEyePt, const Math::Vector &vLookatPt, const Math::Vector &vUpVec, FLOAT fEyeDistance);
-
- bool FreeTexture(char* name);
- bool LoadTexture(char* name, int stage=0);
- bool LoadAllTexture();
-
- void SetLimitLOD(int rank, float limit);
- float RetLimitLOD(int rank, bool bLast=false);
-
- void SetTerrainVision(float vision);
-
- void SetGroundSpot(bool bMode);
- bool RetGroundSpot();
- void SetShadow(bool bMode);
- bool RetShadow();
- void SetDirty(bool bMode);
- bool RetDirty();
- void SetFog(bool bMode);
- bool RetFog();
- bool RetStateColor();
-
- void SetSecondTexture(int texNum);
- int RetSecondTexture();
-
- void SetRankView(int rank);
- int RetRankView();
-
- void SetDrawWorld(bool bDraw);
- void SetDrawFront(bool bDraw);
-
- void SetAmbiantColor(D3DCOLOR color, int rank=0);
- D3DCOLOR RetAmbiantColor(int rank=0);
-
- void SetWaterAddColor(D3DCOLORVALUE color);
- D3DCOLORVALUE RetWaterAddColor();
-
- void SetFogColor(D3DCOLOR color, int rank=0);
- D3DCOLOR RetFogColor(int rank=0);
-
- void SetDeepView(float length, int rank=0, bool bRef=false);
- float RetDeepView(int rank=0);
-
- void SetFogStart(float start, int rank=0);
- float RetFogStart(int rank=0);
-
- void SetBackground(char *name, D3DCOLOR up=0, D3DCOLOR down=0, D3DCOLOR cloudUp=0, D3DCOLOR cloudDown=0, bool bFull=false, bool bQuarter=false);
- void RetBackground(char *name, D3DCOLOR &up, D3DCOLOR &down, D3DCOLOR &cloudUp, D3DCOLOR &cloudDown, bool &bFull, bool &bQuarter);
- void SetFrontsizeName(char *name);
- void SetOverFront(bool bFront);
- void SetOverColor(D3DCOLOR color=0, int mode=D3DSTATETCb);
-
- void SetParticuleDensity(float value);
- float RetParticuleDensity();
- float ParticuleAdapt(float factor);
-
- void SetClippingDistance(float value);
- float RetClippingDistance();
-
- void SetObjectDetail(float value);
- float RetObjectDetail();
-
- void SetGadgetQuantity(float value);
- float RetGadgetQuantity();
-
- void SetTextureQuality(int value);
- int RetTextureQuality();
-
- void SetTotoMode(bool bPresent);
- bool RetTotoMode();
-
- void SetLensMode(bool bPresent);
- bool RetLensMode();
-
- void SetWaterMode(bool bPresent);
- bool RetWaterMode();
-
- void SetBlitzMode(bool bPresent);
- bool RetBlitzMode();
-
- void SetSkyMode(bool bPresent);
- bool RetSkyMode();
-
- void SetBackForce(bool bPresent);
- bool RetBackForce();
-
- void SetPlanetMode(bool bPresent);
- bool RetPlanetMode();
-
- void SetLightMode(bool bPresent);
- bool RetLightMode();
-
- void SetEditIndentMode(bool bAuto);
- bool RetEditIndentMode();
-
- void SetEditIndentValue(int value);
- int RetEditIndentValue();
-
- void SetSpeed(float speed);
- float RetSpeed();
-
- void SetTracePrecision(float factor);
- float RetTracePrecision();
-
- void SetFocus(float focus);
- float RetFocus();
- Math::Vector RetEyePt();
- Math::Vector RetLookatPt();
- float RetEyeDirH();
- float RetEyeDirV();
- POINT RetDim();
- void UpdateMatProj();
-
- void ApplyChange();
-
- void FlushPressKey();
- void ResetKey();
- void SetKey(int keyRank, int option, int key);
- int RetKey(int keyRank, int option);
-
- void SetJoystick(bool bEnable);
- bool RetJoystick();
-
- void SetDebugMode(bool bMode);
- bool RetDebugMode();
- bool RetSetupMode();
-
- bool IsVisiblePoint(const Math::Vector &pos);
-
- int DetectObject(Math::Point mouse);
- void SetState(int state, D3DCOLOR color=0xffffffff);
- void SetTexture(char *name, int stage=0);
- void SetMaterial(const D3DMATERIAL7 &mat);
-
- void MoveMousePos(Math::Point pos);
- void SetMousePos(Math::Point pos);
- Math::Point RetMousePos();
- void SetMouseType(D3DMouse type);
- D3DMouse RetMouseType();
- void SetMouseHide(bool bHide);
- bool RetMouseHide();
- void SetNiceMouse(bool bNice);
- bool RetNiceMouse();
- bool RetNiceMouseCap();
-
- CText* RetText();
-
- bool ChangeColor(char *name, D3DCOLORVALUE colorRef1, D3DCOLORVALUE colorNew1, D3DCOLORVALUE colorRef2, D3DCOLORVALUE colorNew2, float tolerance1, float tolerance2, Math::Point ts, Math::Point ti, Math::Point *pExclu=0, float shift=0.0f, bool bHSV=false);
- bool OpenImage(char *name);
- bool CopyImage();
- bool LoadImage();
- bool ScrollImage(int dx, int dy);
- bool SetDot(int x, int y, D3DCOLORVALUE color);
- bool CloseImage();
- bool WriteScreenShot(char *filename, int width, int height);
- bool GetRenderDC(HDC &hDC);
- bool ReleaseRenderDC(HDC &hDC);
- PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp);
- bool CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC);
-
-protected:
- void MemSpace1(D3DObjLevel1 *&p, int nb);
- void MemSpace2(D3DObjLevel2 *&p, int nb);
- void MemSpace3(D3DObjLevel3 *&p, int nb);
- void MemSpace4(D3DObjLevel4 *&p, int nb);
- void MemSpace5(D3DObjLevel5 *&p, int nb);
- void MemSpace6(D3DObjLevel6 *&p, int nb);
-
- D3DObjLevel2* AddLevel1(D3DObjLevel1 *&p1, char* texName1, char* texName2);
- D3DObjLevel3* AddLevel2(D3DObjLevel2 *&p2, int objRank);
- D3DObjLevel4* AddLevel3(D3DObjLevel3 *&p3, float min, float max);
- D3DObjLevel5* AddLevel4(D3DObjLevel4 *&p4, int reserve);
- D3DObjLevel6* AddLevel5(D3DObjLevel5 *&p5, D3DTypeTri type, const D3DMATERIAL7 &mat, int state, int nb);
-
- bool IsVisible(int objRank);
- bool DetectBBox(int objRank, Math::Point mouse);
- bool DetectTriangle(Math::Point mouse, D3DVERTEX2 *triangle, int objRank, float &dist);
- bool TransformPoint(Math::Vector &p2D, int objRank, Math::Vector p3D);
- void ComputeDistance();
- void UpdateGeometry();
- void RenderGroundSpot();
- void DrawShadow();
- void DrawBackground();
- void DrawBackgroundGradient(D3DCOLOR up, D3DCOLOR down);
- void DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, char *name);
- void DrawBackgroundImage();
- void DrawPlanet();
- void DrawFrontsize();
- void DrawOverColor();
- bool GetBBox2D(int objRank, Math::Point &min, Math::Point &max);
- void DrawHilite();
- void DrawMouse();
- void DrawSprite(Math::Point pos, Math::Point dim, int icon);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DApplication* m_app;
- LPDIRECT3DDEVICE7 m_pD3DDevice;
- CText* m_text;
- CLight* m_light;
- CParticule* m_particule;
- CWater* m_water;
- CCloud* m_cloud;
- CBlitz* m_blitz;
- CPlanet* m_planet;
- CSound* m_sound;
- CTerrain* m_terrain;
-
- int m_blackSrcBlend[2];
- int m_blackDestBlend[2];
- int m_whiteSrcBlend[2];
- int m_whiteDestBlend[2];
- int m_diffuseSrcBlend[2];
- int m_diffuseDestBlend[2];
- int m_alphaSrcBlend[2];
- int m_alphaDestBlend[2];
-
- Math::Matrix m_matProj;
- Math::Matrix m_matLeftView;
- Math::Matrix m_matRightView;
- Math::Matrix m_matView;
- float m_focus;
-
- Math::Matrix m_matWorldInterface;
- Math::Matrix m_matProjInterface;
- Math::Matrix m_matViewInterface;
-
- DWORD m_baseTime;
- DWORD m_stopTime;
- float m_absTime;
- float m_lastTime;
- float m_speed;
- bool m_bPause;
- bool m_bRender;
- bool m_bMovieLock;
-
- POINT m_dim;
- POINT m_lastDim;
- D3DObjLevel1* m_objectPointer;
- int m_objectParamTotal;
- D3DObject* m_objectParam;
- int m_shadowTotal;
- D3DShadow* m_shadow;
- D3DGroundSpot* m_groundSpot;
- D3DGroundMark m_groundMark;
- Math::Vector m_eyePt;
- Math::Vector m_lookatPt;
- float m_eyeDirH;
- float m_eyeDirV;
- int m_rankView;
- D3DCOLOR m_ambiantColor[2];
- D3DCOLOR m_backColor[2];
- D3DCOLOR m_fogColor[2];
- float m_deepView[2];
- float m_fogStart[2];
- D3DCOLORVALUE m_waterAddColor;
- int m_statisticTriangle;
- bool m_bUpdateGeometry;
- char m_infoText[10][200];
- int m_alphaMode;
- bool m_bStateColor;
- bool m_bForceStateColor;
- bool m_bGroundSpot;
- bool m_bShadow;
- bool m_bDirty;
- bool m_bFog;
- bool m_bFirstGroundSpot;
- int m_secondTexNum;
- char m_backgroundName[50];
- D3DCOLOR m_backgroundColorUp;
- D3DCOLOR m_backgroundColorDown;
- D3DCOLOR m_backgroundCloudUp;
- D3DCOLOR m_backgroundCloudDown;
- bool m_bBackgroundFull;
- bool m_bBackgroundQuarter;
- bool m_bOverFront;
- D3DCOLOR m_overColor;
- int m_overMode;
- char m_frontsizeName[50];
- bool m_bDrawWorld;
- bool m_bDrawFront;
- float m_limitLOD[2];
- float m_particuleDensity;
- float m_clippingDistance;
- float m_lastClippingDistance;
- float m_objectDetail;
- float m_lastObjectDetail;
- float m_terrainVision;
- float m_gadgetQuantity;
- int m_textureQuality;
- bool m_bTotoMode;
- bool m_bLensMode;
- bool m_bWaterMode;
- bool m_bSkyMode;
- bool m_bBackForce;
- bool m_bPlanetMode;
- bool m_bLightMode;
- bool m_bEditIndentMode;
- int m_editIndentValue;
- float m_tracePrecision;
-
- int m_hiliteRank[100];
- bool m_bHilite;
- Math::Point m_hiliteP1;
- Math::Point m_hiliteP2;
-
- int m_lastState;
- D3DCOLOR m_lastColor;
- char m_lastTexture[2][50];
- D3DMATERIAL7 m_lastMaterial;
-
- Math::Point m_mousePos;
- D3DMouse m_mouseType;
- bool m_bMouseHide;
- bool m_bNiceMouse;
-
- LPDIRECTDRAWSURFACE7 m_imageSurface;
- DDSURFACEDESC2 m_imageDDSD;
- WORD* m_imageCopy;
- int m_imageDX;
- int m_imageDY;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// d3dengine.h
+
+#pragma once
+
+
+#include <d3d.h>
+
+#include "math/point.h"
+#include "math/vector.h"
+#include "math/matrix.h"
+#include "common/struct.h"
+
+
+class CD3DApplication;
+class CInstanceManager;
+class CObject;
+class CLight;
+class CText;
+class CParticule;
+class CWater;
+class CCloud;
+class CBlitz;
+class CPlanet;
+class CSound;
+class CTerrain;
+
+
+const int D3DMAXOBJECT = 1200;
+const int D3DMAXSHADOW = 500;
+const int D3DMAXGROUNDSPOT = 100;
+
+
+enum D3DTypeObj
+{
+ TYPENULL = 0, // object doesn't exist
+ TYPETERRAIN = 1, // terrain
+ TYPEFIX = 2, // fixed object
+ TYPEVEHICULE = 3, // moving object
+ TYPEDESCENDANT = 4, // part of a moving object
+ TYPEQUARTZ = 5, // fixed object type quartz
+ TYPEMETAL = 6, // fixed object type metal
+};
+
+enum D3DTypeTri
+{
+ D3DTYPE6T = 1, // triangles
+ D3DTYPE6S = 2, // surfaces
+};
+
+enum D3DMaping
+{
+ D3DMAPPINGX = 1,
+ D3DMAPPINGY = 2,
+ D3DMAPPINGZ = 3,
+ D3DMAPPING1X = 4,
+ D3DMAPPING1Y = 5,
+ D3DMAPPING1Z = 6,
+};
+
+enum D3DMouse
+{
+ D3DMOUSEHIDE = 0, // no mouse
+ D3DMOUSENORM = 1,
+ D3DMOUSEWAIT = 2,
+ D3DMOUSEEDIT = 3,
+ D3DMOUSEHAND = 4,
+ D3DMOUSECROSS = 5,
+ D3DMOUSESHOW = 6,
+ D3DMOUSENO = 7,
+ D3DMOUSEMOVE = 8, // +
+ D3DMOUSEMOVEH = 9, // -
+ D3DMOUSEMOVEV = 10, // |
+ D3DMOUSEMOVED = 11, // /
+ D3DMOUSEMOVEI = 12, // \ //
+ D3DMOUSESCROLLL = 13, // <<
+ D3DMOUSESCROLLR = 14, // >>
+ D3DMOUSESCROLLU = 15, // ^
+ D3DMOUSESCROLLD = 16, // v
+ D3DMOUSETARGET = 17,
+};
+
+enum D3DShadowType
+{
+ D3DSHADOWNORM = 0,
+ D3DSHADOWWORM = 1,
+};
+
+
+const int D3DSTATENORMAL = 0; // normal opaque materials
+const int D3DSTATETTb = (1<<0); // the transparent texture (black = no)
+const int D3DSTATETTw = (1<<1); // the transparent texture (white = no)
+const int D3DSTATETD = (1<<2); // the transparent diffuse color
+const int D3DSTATEWRAP = (1<<3); // texture wrappe
+const int D3DSTATECLAMP = (1<<4); // texture borders with solid color
+const int D3DSTATELIGHT = (1<<5); // light texture (ambient max)
+const int D3DSTATEDUALb = (1<<6); // double black texturing
+const int D3DSTATEDUALw = (1<<7); // double white texturing
+const int D3DSTATEPART1 = (1<<8); // part 1 (no change in. MOD!)
+const int D3DSTATEPART2 = (1<<9); // part 2
+const int D3DSTATEPART3 = (1<<10); // part 3
+const int D3DSTATEPART4 = (1<<11); // part 4
+const int D3DSTATE2FACE = (1<<12); // double-sided face
+const int D3DSTATEALPHA = (1<<13); // image using alpha channel
+const int D3DSTATESECOND = (1<<14); // always use 2nd floor texturing
+const int D3DSTATEFOG = (1<<15); // causes the fog
+const int D3DSTATETCb = (1<<16); // the transparent color (black = no)
+const int D3DSTATETCw = (1<<17); // the transparent color (white = no)
+
+
+struct D3DTriangle
+{
+ D3DVERTEX2 triangle[3];
+ D3DMATERIAL7 material;
+ int state;
+ char texName1[20];
+ char texName2[20];
+};
+
+
+struct D3DObjLevel6
+{
+ int totalPossible;
+ int totalUsed;
+ D3DMATERIAL7 material;
+ int state;
+ D3DTypeTri type; // D3DTYPE6x
+ D3DVERTEX2 vertex[1];
+};
+
+struct D3DObjLevel5
+{
+ int totalPossible;
+ int totalUsed;
+ int reserve;
+ D3DObjLevel6* table[1];
+};
+
+struct D3DObjLevel4
+{
+ int totalPossible;
+ int totalUsed;
+ float min, max;
+ D3DObjLevel5* table[1];
+};
+
+struct D3DObjLevel3
+{
+ int totalPossible;
+ int totalUsed;
+ int objRank;
+ D3DObjLevel4* table[1];
+};
+
+struct D3DObjLevel2
+{
+ int totalPossible;
+ int totalUsed;
+ char texName1[20];
+ char texName2[20];
+ D3DObjLevel3* table[1];
+};
+
+struct D3DObjLevel1
+{
+ int totalPossible;
+ int totalUsed;
+ D3DObjLevel2* table[1];
+};
+
+
+struct D3DObject
+{
+ char bUsed; // true -> object exists
+ char bVisible; // true -> visible object
+ char bDrawWorld; // true -> shape behind the interface
+ char bDrawFront; // true -> shape before the interface
+ int totalTriangle; // number of triangles used
+ D3DTypeObj type; // type of the object (TYPE*)
+ Math::Matrix transform; // transformation matrix
+ float distance; // distance point of view - original
+ Math::Vector bboxMin; // bounding box of the object
+ Math::Vector bboxMax; // (the origin 0, 0, 0 is always included)
+ float radius; // radius of the sphere at the origin
+ int shadowRank; // rank of the associated shadow
+ float transparency; // transparency of the object (0 .. 1)
+};
+
+struct D3DShadow
+{
+ char bUsed; // true -> object exists
+ char bHide; // true -> invisible shadow (object carried by ex.)
+ int objRank; // rank of the object
+ D3DShadowType type; // type of shadow
+ Math::Vector pos; // position for the shadow
+ Math::Vector normal; // normal terrain
+ float angle; // angle of the shadow
+ float radius; // radius of the shadow
+ float intensity; // intensity of the shadow
+ float height; // height from the ground
+};
+
+struct D3DGroundSpot
+{
+ char bUsed; // true -> object exists
+ D3DCOLORVALUE color; // color of the shadow
+ float min, max; // altitudes min / max
+ float smooth; // transition area
+ Math::Vector pos; // position for the shadow
+ float radius; // radius of the shadow
+ Math::Vector drawPos; // drawn to position the shade
+ float drawRadius; // radius of the shadow drawn
+};
+
+struct D3DGroundMark
+{
+ char bUsed; // true -> object exists
+ char bDraw; // true -> drawn mark
+ int phase; // 1 = increase, 2 = fixed, 3 = decrease
+ float delay[3]; // time for 3 phases
+ float fix; // fixed time
+ Math::Vector pos; // position for marks
+ float radius; // radius of marks
+ float intensity; // color intensity
+ Math::Vector drawPos; // drawn in position marks
+ float drawRadius; // radius marks drawn
+ float drawIntensity; // current drawn
+ int dx, dy; // dimensions table
+ char* table; // pointer to the table
+};
+
+
+
+class CD3DEngine
+{
+public:
+ CD3DEngine(CInstanceManager *iMan, CD3DApplication *app);
+ ~CD3DEngine();
+
+ void SetD3DDevice(LPDIRECT3DDEVICE7 device);
+ LPDIRECT3DDEVICE7 RetD3DDevice();
+
+ void SetTerrain(CTerrain* terrain);
+
+ bool WriteProfile();
+
+ void SetPause(bool bPause);
+ bool RetPause();
+
+ void SetMovieLock(bool bLock);
+ bool RetMovieLock();
+
+ void SetShowStat(bool bShow);
+ bool RetShowStat();
+
+ void SetRenderEnable(bool bEnable);
+
+ HRESULT OneTimeSceneInit();
+ HRESULT InitDeviceObjects();
+ HRESULT DeleteDeviceObjects();
+ HRESULT RestoreSurfaces();
+ HRESULT Render();
+ HRESULT FrameMove(float rTime);
+ void StepSimul(float rTime);
+ HRESULT FinalCleanup();
+ void AddStatisticTriangle(int nb);
+ int RetStatisticTriangle();
+ void SetHiliteRank(int *rankList);
+ bool GetHilite(Math::Point &p1, Math::Point &p2);
+ bool GetSpriteCoord(int &x, int &y);
+ void SetInfoText(int line, char* text);
+ char* RetInfoText(int line);
+ LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ void FirstExecuteAdapt(bool bFirst);
+ int GetVidMemTotal();
+ bool IsVideo8MB();
+ bool IsVideo32MB();
+
+ bool EnumDevices(char *bufDevices, int lenDevices, char *bufModes, int lenModes, int &totalDevices, int &selectDevices, int &totalModes, int &selectModes);
+ bool RetFullScreen();
+ bool ChangeDevice(char *device, char *mode, bool bFull);
+
+ Math::Matrix* RetMatView();
+ Math::Matrix* RetMatLeftView();
+ Math::Matrix* RetMatRightView();
+
+ void TimeInit();
+ void TimeEnterGel();
+ void TimeExitGel();
+ float TimeGet();
+
+ int RetRestCreate();
+ int CreateObject();
+ void FlushObject();
+ bool DeleteObject(int objRank);
+ bool SetDrawWorld(int objRank, bool bDraw);
+ bool SetDrawFront(int objRank, bool bDraw);
+ bool AddTriangle(int objRank, D3DVERTEX2* vertex, int nb, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max, bool bGlobalUpdate);
+ bool AddSurface(int objRank, D3DVERTEX2* vertex, int nb, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max, bool bGlobalUpdate);
+ bool AddQuick(int objRank, D3DObjLevel6* buffer, char* texName1, char* texName2, float min, float max, bool bGlobalUpdate);
+ D3DObjLevel6* SearchTriangle(int objRank, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max);
+ void ChangeLOD();
+ bool ChangeSecondTexture(int objRank, char* texName2);
+ int RetTotalTriangles(int objRank);
+ int GetTriangles(int objRank, float min, float max, D3DTriangle* buffer, int size, float percent);
+ bool GetBBox(int objRank, Math::Vector &min, Math::Vector &max);
+ bool ChangeTextureMapping(int objRank, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max, D3DMaping mode, float au, float bu, float av, float bv);
+ bool TrackTextureMapping(int objRank, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max, D3DMaping mode, float pos, float factor, float tl, float ts, float tt);
+ bool SetObjectTransform(int objRank, const Math::Matrix &transform);
+ bool GetObjectTransform(int objRank, Math::Matrix &transform);
+ bool SetObjectType(int objRank, D3DTypeObj type);
+ D3DTypeObj RetObjectType(int objRank);
+ bool SetObjectTransparency(int objRank, float value);
+
+ bool ShadowCreate(int objRank);
+ void ShadowDelete(int objRank);
+ bool SetObjectShadowHide(int objRank, bool bHide);
+ bool SetObjectShadowType(int objRank, D3DShadowType type);
+ bool SetObjectShadowPos(int objRank, const Math::Vector &pos);
+ bool SetObjectShadowNormal(int objRank, const Math::Vector &n);
+ bool SetObjectShadowAngle(int objRank, float angle);
+ bool SetObjectShadowRadius(int objRank, float radius);
+ bool SetObjectShadowIntensity(int objRank, float intensity);
+ bool SetObjectShadowHeight(int objRank, float h);
+ float RetObjectShadowRadius(int objRank);
+
+ void GroundSpotFlush();
+ int GroundSpotCreate();
+ void GroundSpotDelete(int rank);
+ bool SetObjectGroundSpotPos(int rank, const Math::Vector &pos);
+ bool SetObjectGroundSpotRadius(int rank, float radius);
+ bool SetObjectGroundSpotColor(int rank, D3DCOLORVALUE color);
+ bool SetObjectGroundSpotMinMax(int rank, float min, float max);
+ bool SetObjectGroundSpotSmooth(int rank, float smooth);
+
+ int GroundMarkCreate(Math::Vector pos, float radius, float delay1, float delay2, float delay3, int dx, int dy, char* table);
+ bool GroundMarkDelete(int rank);
+
+ void Update();
+
+ void SetViewParams(const Math::Vector &vEyePt, const Math::Vector &vLookatPt, const Math::Vector &vUpVec, FLOAT fEyeDistance);
+
+ bool FreeTexture(char* name);
+ bool LoadTexture(char* name, int stage=0);
+ bool LoadAllTexture();
+
+ void SetLimitLOD(int rank, float limit);
+ float RetLimitLOD(int rank, bool bLast=false);
+
+ void SetTerrainVision(float vision);
+
+ void SetGroundSpot(bool bMode);
+ bool RetGroundSpot();
+ void SetShadow(bool bMode);
+ bool RetShadow();
+ void SetDirty(bool bMode);
+ bool RetDirty();
+ void SetFog(bool bMode);
+ bool RetFog();
+ bool RetStateColor();
+
+ void SetSecondTexture(int texNum);
+ int RetSecondTexture();
+
+ void SetRankView(int rank);
+ int RetRankView();
+
+ void SetDrawWorld(bool bDraw);
+ void SetDrawFront(bool bDraw);
+
+ void SetAmbiantColor(D3DCOLOR color, int rank=0);
+ D3DCOLOR RetAmbiantColor(int rank=0);
+
+ void SetWaterAddColor(D3DCOLORVALUE color);
+ D3DCOLORVALUE RetWaterAddColor();
+
+ void SetFogColor(D3DCOLOR color, int rank=0);
+ D3DCOLOR RetFogColor(int rank=0);
+
+ void SetDeepView(float length, int rank=0, bool bRef=false);
+ float RetDeepView(int rank=0);
+
+ void SetFogStart(float start, int rank=0);
+ float RetFogStart(int rank=0);
+
+ void SetBackground(char *name, D3DCOLOR up=0, D3DCOLOR down=0, D3DCOLOR cloudUp=0, D3DCOLOR cloudDown=0, bool bFull=false, bool bQuarter=false);
+ void RetBackground(char *name, D3DCOLOR &up, D3DCOLOR &down, D3DCOLOR &cloudUp, D3DCOLOR &cloudDown, bool &bFull, bool &bQuarter);
+ void SetFrontsizeName(char *name);
+ void SetOverFront(bool bFront);
+ void SetOverColor(D3DCOLOR color=0, int mode=D3DSTATETCb);
+
+ void SetParticuleDensity(float value);
+ float RetParticuleDensity();
+ float ParticuleAdapt(float factor);
+
+ void SetClippingDistance(float value);
+ float RetClippingDistance();
+
+ void SetObjectDetail(float value);
+ float RetObjectDetail();
+
+ void SetGadgetQuantity(float value);
+ float RetGadgetQuantity();
+
+ void SetTextureQuality(int value);
+ int RetTextureQuality();
+
+ void SetTotoMode(bool bPresent);
+ bool RetTotoMode();
+
+ void SetLensMode(bool bPresent);
+ bool RetLensMode();
+
+ void SetWaterMode(bool bPresent);
+ bool RetWaterMode();
+
+ void SetBlitzMode(bool bPresent);
+ bool RetBlitzMode();
+
+ void SetSkyMode(bool bPresent);
+ bool RetSkyMode();
+
+ void SetBackForce(bool bPresent);
+ bool RetBackForce();
+
+ void SetPlanetMode(bool bPresent);
+ bool RetPlanetMode();
+
+ void SetLightMode(bool bPresent);
+ bool RetLightMode();
+
+ void SetEditIndentMode(bool bAuto);
+ bool RetEditIndentMode();
+
+ void SetEditIndentValue(int value);
+ int RetEditIndentValue();
+
+ void SetSpeed(float speed);
+ float RetSpeed();
+
+ void SetTracePrecision(float factor);
+ float RetTracePrecision();
+
+ void SetFocus(float focus);
+ float RetFocus();
+ Math::Vector RetEyePt();
+ Math::Vector RetLookatPt();
+ float RetEyeDirH();
+ float RetEyeDirV();
+ POINT RetDim();
+ void UpdateMatProj();
+
+ void ApplyChange();
+
+ void FlushPressKey();
+ void ResetKey();
+ void SetKey(int keyRank, int option, int key);
+ int RetKey(int keyRank, int option);
+
+ void SetJoystick(bool bEnable);
+ bool RetJoystick();
+
+ void SetDebugMode(bool bMode);
+ bool RetDebugMode();
+ bool RetSetupMode();
+
+ bool IsVisiblePoint(const Math::Vector &pos);
+
+ int DetectObject(Math::Point mouse);
+ void SetState(int state, D3DCOLOR color=0xffffffff);
+ void SetTexture(char *name, int stage=0);
+ void SetMaterial(const D3DMATERIAL7 &mat);
+
+ void MoveMousePos(Math::Point pos);
+ void SetMousePos(Math::Point pos);
+ Math::Point RetMousePos();
+ void SetMouseType(D3DMouse type);
+ D3DMouse RetMouseType();
+ void SetMouseHide(bool bHide);
+ bool RetMouseHide();
+ void SetNiceMouse(bool bNice);
+ bool RetNiceMouse();
+ bool RetNiceMouseCap();
+
+ CText* RetText();
+
+ bool ChangeColor(char *name, D3DCOLORVALUE colorRef1, D3DCOLORVALUE colorNew1, D3DCOLORVALUE colorRef2, D3DCOLORVALUE colorNew2, float tolerance1, float tolerance2, Math::Point ts, Math::Point ti, Math::Point *pExclu=0, float shift=0.0f, bool bHSV=false);
+ bool OpenImage(char *name);
+ bool CopyImage();
+ bool LoadImage();
+ bool ScrollImage(int dx, int dy);
+ bool SetDot(int x, int y, D3DCOLORVALUE color);
+ bool CloseImage();
+ bool WriteScreenShot(char *filename, int width, int height);
+ bool GetRenderDC(HDC &hDC);
+ bool ReleaseRenderDC(HDC &hDC);
+ PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp);
+ bool CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC);
+
+protected:
+ void MemSpace1(D3DObjLevel1 *&p, int nb);
+ void MemSpace2(D3DObjLevel2 *&p, int nb);
+ void MemSpace3(D3DObjLevel3 *&p, int nb);
+ void MemSpace4(D3DObjLevel4 *&p, int nb);
+ void MemSpace5(D3DObjLevel5 *&p, int nb);
+ void MemSpace6(D3DObjLevel6 *&p, int nb);
+
+ D3DObjLevel2* AddLevel1(D3DObjLevel1 *&p1, char* texName1, char* texName2);
+ D3DObjLevel3* AddLevel2(D3DObjLevel2 *&p2, int objRank);
+ D3DObjLevel4* AddLevel3(D3DObjLevel3 *&p3, float min, float max);
+ D3DObjLevel5* AddLevel4(D3DObjLevel4 *&p4, int reserve);
+ D3DObjLevel6* AddLevel5(D3DObjLevel5 *&p5, D3DTypeTri type, const D3DMATERIAL7 &mat, int state, int nb);
+
+ bool IsVisible(int objRank);
+ bool DetectBBox(int objRank, Math::Point mouse);
+ bool DetectTriangle(Math::Point mouse, D3DVERTEX2 *triangle, int objRank, float &dist);
+ bool TransformPoint(Math::Vector &p2D, int objRank, Math::Vector p3D);
+ void ComputeDistance();
+ void UpdateGeometry();
+ void RenderGroundSpot();
+ void DrawShadow();
+ void DrawBackground();
+ void DrawBackgroundGradient(D3DCOLOR up, D3DCOLOR down);
+ void DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, char *name);
+ void DrawBackgroundImage();
+ void DrawPlanet();
+ void DrawFrontsize();
+ void DrawOverColor();
+ bool GetBBox2D(int objRank, Math::Point &min, Math::Point &max);
+ void DrawHilite();
+ void DrawMouse();
+ void DrawSprite(Math::Point pos, Math::Point dim, int icon);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DApplication* m_app;
+ LPDIRECT3DDEVICE7 m_pD3DDevice;
+ CText* m_text;
+ CLight* m_light;
+ CParticule* m_particule;
+ CWater* m_water;
+ CCloud* m_cloud;
+ CBlitz* m_blitz;
+ CPlanet* m_planet;
+ CSound* m_sound;
+ CTerrain* m_terrain;
+
+ int m_blackSrcBlend[2];
+ int m_blackDestBlend[2];
+ int m_whiteSrcBlend[2];
+ int m_whiteDestBlend[2];
+ int m_diffuseSrcBlend[2];
+ int m_diffuseDestBlend[2];
+ int m_alphaSrcBlend[2];
+ int m_alphaDestBlend[2];
+
+ Math::Matrix m_matProj;
+ Math::Matrix m_matLeftView;
+ Math::Matrix m_matRightView;
+ Math::Matrix m_matView;
+ float m_focus;
+
+ Math::Matrix m_matWorldInterface;
+ Math::Matrix m_matProjInterface;
+ Math::Matrix m_matViewInterface;
+
+ DWORD m_baseTime;
+ DWORD m_stopTime;
+ float m_absTime;
+ float m_lastTime;
+ float m_speed;
+ bool m_bPause;
+ bool m_bRender;
+ bool m_bMovieLock;
+
+ POINT m_dim;
+ POINT m_lastDim;
+ D3DObjLevel1* m_objectPointer;
+ int m_objectParamTotal;
+ D3DObject* m_objectParam;
+ int m_shadowTotal;
+ D3DShadow* m_shadow;
+ D3DGroundSpot* m_groundSpot;
+ D3DGroundMark m_groundMark;
+ Math::Vector m_eyePt;
+ Math::Vector m_lookatPt;
+ float m_eyeDirH;
+ float m_eyeDirV;
+ int m_rankView;
+ D3DCOLOR m_ambiantColor[2];
+ D3DCOLOR m_backColor[2];
+ D3DCOLOR m_fogColor[2];
+ float m_deepView[2];
+ float m_fogStart[2];
+ D3DCOLORVALUE m_waterAddColor;
+ int m_statisticTriangle;
+ bool m_bUpdateGeometry;
+ char m_infoText[10][200];
+ int m_alphaMode;
+ bool m_bStateColor;
+ bool m_bForceStateColor;
+ bool m_bGroundSpot;
+ bool m_bShadow;
+ bool m_bDirty;
+ bool m_bFog;
+ bool m_bFirstGroundSpot;
+ int m_secondTexNum;
+ char m_backgroundName[50];
+ D3DCOLOR m_backgroundColorUp;
+ D3DCOLOR m_backgroundColorDown;
+ D3DCOLOR m_backgroundCloudUp;
+ D3DCOLOR m_backgroundCloudDown;
+ bool m_bBackgroundFull;
+ bool m_bBackgroundQuarter;
+ bool m_bOverFront;
+ D3DCOLOR m_overColor;
+ int m_overMode;
+ char m_frontsizeName[50];
+ bool m_bDrawWorld;
+ bool m_bDrawFront;
+ float m_limitLOD[2];
+ float m_particuleDensity;
+ float m_clippingDistance;
+ float m_lastClippingDistance;
+ float m_objectDetail;
+ float m_lastObjectDetail;
+ float m_terrainVision;
+ float m_gadgetQuantity;
+ int m_textureQuality;
+ bool m_bTotoMode;
+ bool m_bLensMode;
+ bool m_bWaterMode;
+ bool m_bSkyMode;
+ bool m_bBackForce;
+ bool m_bPlanetMode;
+ bool m_bLightMode;
+ bool m_bEditIndentMode;
+ int m_editIndentValue;
+ float m_tracePrecision;
+
+ int m_hiliteRank[100];
+ bool m_bHilite;
+ Math::Point m_hiliteP1;
+ Math::Point m_hiliteP2;
+
+ int m_lastState;
+ D3DCOLOR m_lastColor;
+ char m_lastTexture[2][50];
+ D3DMATERIAL7 m_lastMaterial;
+
+ Math::Point m_mousePos;
+ D3DMouse m_mouseType;
+ bool m_bMouseHide;
+ bool m_bNiceMouse;
+
+ LPDIRECTDRAWSURFACE7 m_imageSurface;
+ DDSURFACEDESC2 m_imageDDSD;
+ WORD* m_imageCopy;
+ int m_imageDX;
+ int m_imageDY;
+};
+
+
diff --git a/src/old/d3denum.cpp b/src/old/d3denum.cpp
index 5bce9ab..234ce5a 100644
--- a/src/old/d3denum.cpp
+++ b/src/old/d3denum.cpp
@@ -1,620 +1,620 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-//-----------------------------------------------------------------------------
-// File: D3DEnum.cpp
-//
-// Desc: Functions to enumerate DDraw/D3D drivers, devices, and modes.
-//
-// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-#include <windowsx.h>
-#include <stdio.h>
-#include <tchar.h>
-#include "old/d3denum.h"
-#include "old/d3dutil.h" // For DEBUG_MSG
-#include "old/d3dres.h" // For dialog controls
-
-
-
-
-//-----------------------------------------------------------------------------
-// Global data for the enumerator functions
-//-----------------------------------------------------------------------------
-static HRESULT (*g_fnAppConfirmFn)(DDCAPS*, D3DDEVICEDESC7*) = NULL;
-
-static D3DEnum_DeviceInfo g_pDeviceList[20];
-static DWORD g_dwNumDevicesEnumerated = 0L;
-static DWORD g_dwNumDevices = 0L;
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: SortModesCallback()
-// Desc: Callback function for sorting display modes.
-//-----------------------------------------------------------------------------
-int SortModesCallback( const VOID* arg1, const VOID* arg2 )
-{
- DDSURFACEDESC2* p1 = (DDSURFACEDESC2*)arg1;
- DDSURFACEDESC2* p2 = (DDSURFACEDESC2*)arg2;
-
- if( p1->dwWidth < p2->dwWidth )
- return -1;
- if( p1->dwWidth > p2->dwWidth )
- return +1;
-
- if( p1->dwHeight < p2->dwHeight )
- return -1;
- if( p1->dwHeight > p2->dwHeight )
- return +1;
-
- if( p1->ddpfPixelFormat.dwRGBBitCount < p2->ddpfPixelFormat.dwRGBBitCount )
- return -1;
- if( p1->ddpfPixelFormat.dwRGBBitCount > p2->ddpfPixelFormat.dwRGBBitCount )
- return +1;
-
- return 0;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: ModeEnumCallback()
-// Desc: Callback function for enumerating display modes.
-//-----------------------------------------------------------------------------
-static HRESULT WINAPI ModeEnumCallback( DDSURFACEDESC2* pddsd,
- VOID* pParentInfo )
-{
- D3DEnum_DeviceInfo* pDevice = (D3DEnum_DeviceInfo*)pParentInfo;
-
- // Reallocate storage for the modes
- DDSURFACEDESC2* pddsdNewModes = new DDSURFACEDESC2[pDevice->dwNumModes+1];
- memcpy( pddsdNewModes, pDevice->pddsdModes,
- pDevice->dwNumModes * sizeof(DDSURFACEDESC2) );
- delete pDevice->pddsdModes;
- pDevice->pddsdModes = pddsdNewModes;
-
- // Add the new mode
- pDevice->pddsdModes[pDevice->dwNumModes++] = (*pddsd);
-
- return DDENUMRET_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: DeviceEnumCallback()
-// Desc: Callback function for enumerating devices
-//-----------------------------------------------------------------------------
-static HRESULT WINAPI DeviceEnumCallback( TCHAR* strDesc, TCHAR* strName,
- D3DDEVICEDESC7* pDesc,
- VOID* pParentInfo )
-{
- DWORD i;
-
- // Keep track of # of devices that were enumerated
- g_dwNumDevicesEnumerated++;
-
- D3DEnum_DeviceInfo* pDriverInfo = (D3DEnum_DeviceInfo*)pParentInfo;
- D3DEnum_DeviceInfo* pDeviceInfo = &g_pDeviceList[g_dwNumDevices];
- ZeroMemory( pDeviceInfo, sizeof(D3DEnum_DeviceInfo) );
-
- // Select either the HAL or HEL device desc:
- pDeviceInfo->bHardware = pDesc->dwDevCaps & D3DDEVCAPS_HWRASTERIZATION;
- memcpy( &pDeviceInfo->ddDeviceDesc, pDesc, sizeof(D3DDEVICEDESC7) );
-
- // Set up device info for this device
- pDeviceInfo->bDesktopCompatible = pDriverInfo->bDesktopCompatible;
- pDeviceInfo->ddDriverCaps = pDriverInfo->ddDriverCaps;
- pDeviceInfo->ddHELCaps = pDriverInfo->ddHELCaps;
- pDeviceInfo->guidDevice = pDesc->deviceGUID;
- pDeviceInfo->pDeviceGUID = &pDeviceInfo->guidDevice;
- pDeviceInfo->pddsdModes = new DDSURFACEDESC2[pDriverInfo->dwNumModes];
-
- // Copy the driver GUID and description for the device
- if( pDriverInfo->pDriverGUID )
- {
- pDeviceInfo->guidDriver = pDriverInfo->guidDriver;
- pDeviceInfo->pDriverGUID = &pDeviceInfo->guidDriver;
- lstrcpyn( pDeviceInfo->strDesc, pDriverInfo->strDesc, 39 );
- }
- else
- {
- pDeviceInfo->pDriverGUID = NULL;
- lstrcpyn( pDeviceInfo->strDesc, strName, 39 );
- }
-
-//? if( strstr(strName, "T&L") != 0 ) return D3DENUMRET_OK;
-
- // Avoid duplicates: only enum HW devices for secondary DDraw drivers.
- if( NULL != pDeviceInfo->pDriverGUID && false == pDeviceInfo->bHardware )
- return D3DENUMRET_OK;
-
- // Give the app a chance to accept or reject this device.
- if( g_fnAppConfirmFn )
- if( FAILED( g_fnAppConfirmFn( &pDeviceInfo->ddDriverCaps,
- &pDeviceInfo->ddDeviceDesc ) ) )
- return D3DENUMRET_OK;
-
- // Build list of supported modes for the device
- for( i=0; i<pDriverInfo->dwNumModes; i++ )
- {
- DDSURFACEDESC2 ddsdMode = pDriverInfo->pddsdModes[i];
- DWORD dwRenderDepths = pDeviceInfo->ddDeviceDesc.dwDeviceRenderBitDepth;
- DWORD dwDepth = ddsdMode.ddpfPixelFormat.dwRGBBitCount;
-
- // Accept modes that are compatable with the device
- if( ( ( dwDepth == 32 ) && ( dwRenderDepths & DDBD_32 ) ) ||
- ( ( dwDepth == 24 ) && ( dwRenderDepths & DDBD_24 ) ) ||
- ( ( dwDepth == 16 ) && ( dwRenderDepths & DDBD_16 ) ) )
- {
- // Copy compatible modes to the list of device-supported modes
- pDeviceInfo->pddsdModes[pDeviceInfo->dwNumModes++] = ddsdMode;
-
- // Record whether the device has any stereo modes
- if( ddsdMode.ddsCaps.dwCaps2 & DDSCAPS2_STEREOSURFACELEFT )
- pDeviceInfo->bStereoCompatible = true;
- }
- }
-
- // Bail if the device has no supported modes
- if( 0 == pDeviceInfo->dwNumModes )
- return D3DENUMRET_OK;
-
- // Find a 640x480x16 mode for the default fullscreen mode
- for( i=0; i<pDeviceInfo->dwNumModes; i++ )
- {
- if( ( pDeviceInfo->pddsdModes[i].dwWidth == 640 ) &&
- ( pDeviceInfo->pddsdModes[i].dwHeight == 480 ) &&
- ( pDeviceInfo->pddsdModes[i].ddpfPixelFormat.dwRGBBitCount == 16 ) )
- {
- pDeviceInfo->ddsdFullscreenMode = pDeviceInfo->pddsdModes[i];
- pDeviceInfo->dwCurrentMode = i;
- }
- }
-
- // Select whether the device is initially windowed
- pDeviceInfo->bWindowed = pDeviceInfo->bDesktopCompatible;
-
- // Accept the device and return
- g_dwNumDevices++;
-
- return D3DENUMRET_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: DriverEnumCallback()
-// Desc: Callback function for enumerating drivers.
-//-----------------------------------------------------------------------------
-static bool WINAPI DriverEnumCallback( GUID* pGUID, TCHAR* strDesc,
- TCHAR* strName, VOID*, HMONITOR )
-{
- D3DEnum_DeviceInfo d3dDeviceInfo;
- LPDIRECTDRAW7 pDD;
- LPDIRECT3D7 pD3D;
- HRESULT hr;
-
- // Use the GUID to create the DirectDraw object
- hr = DirectDrawCreateEx( pGUID, (VOID**)&pDD, IID_IDirectDraw7, NULL );
- if( FAILED(hr) )
- {
- DEBUG_MSG( _T("Can't create DDraw during enumeration!") );
- return D3DENUMRET_OK;
- }
-
- // Create a D3D object, to enumerate the d3d devices
- hr = pDD->QueryInterface( IID_IDirect3D7, (VOID**)&pD3D );
- if( FAILED(hr) )
- {
- pDD->Release();
- DEBUG_MSG( _T("Can't query IDirect3D7 during enumeration!") );
- return D3DENUMRET_OK;
- }
-
- // Copy data to a device info structure
- ZeroMemory( &d3dDeviceInfo, sizeof(d3dDeviceInfo) );
- lstrcpyn( d3dDeviceInfo.strDesc, strDesc, 39 );
- d3dDeviceInfo.ddDriverCaps.dwSize = sizeof(DDCAPS);
- d3dDeviceInfo.ddHELCaps.dwSize = sizeof(DDCAPS);
- pDD->GetCaps( &d3dDeviceInfo.ddDriverCaps, &d3dDeviceInfo.ddHELCaps );
- if( pGUID )
- {
- d3dDeviceInfo.guidDriver = (*pGUID);
- d3dDeviceInfo.pDriverGUID = &d3dDeviceInfo.guidDriver;
- }
-
- // Record whether the device can render into a desktop window
- if( d3dDeviceInfo.ddDriverCaps.dwCaps2 & DDCAPS2_CANRENDERWINDOWED )
- if( NULL == d3dDeviceInfo.pDriverGUID )
- d3dDeviceInfo.bDesktopCompatible = true;
-
- // Enumerate the fullscreen display modes.
- pDD->EnumDisplayModes( 0, NULL, &d3dDeviceInfo, ModeEnumCallback );
-
- // Sort list of display modes
- qsort( d3dDeviceInfo.pddsdModes, d3dDeviceInfo.dwNumModes,
- sizeof(DDSURFACEDESC2), SortModesCallback );
-
- // Now, enumerate all the 3D devices
- pD3D->EnumDevices( DeviceEnumCallback, &d3dDeviceInfo );
-
- // Clean up and return
- SAFE_DELETE( d3dDeviceInfo.pddsdModes );
- pD3D->Release();
- pDD->Release();
-
- return DDENUMRET_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_EnumerateDevices()
-// Desc: Enumerates all drivers, devices, and modes. The callback function is
-// called each device, to confirm that the device supports the feature
-// set required by the app.
-//-----------------------------------------------------------------------------
-HRESULT D3DEnum_EnumerateDevices( HRESULT (*AppConfirmFn)(DDCAPS*, D3DDEVICEDESC7*) )
-{
- // Store the device enumeration callback function
- g_fnAppConfirmFn = AppConfirmFn;
-
- // Enumerate drivers, devices, and modes
- DirectDrawEnumerateEx( DriverEnumCallback, NULL,
- DDENUM_ATTACHEDSECONDARYDEVICES |
- DDENUM_DETACHEDSECONDARYDEVICES |
- DDENUM_NONDISPLAYDEVICES );
-
- // Make sure devices were actually enumerated
- if( 0 == g_dwNumDevicesEnumerated )
- {
- DEBUG_MSG( _T("No devices and/or modes were enumerated!") );
- return D3DENUMERR_ENUMERATIONFAILED;
- }
- if( 0 == g_dwNumDevices )
- {
- DEBUG_MSG( _T("No enumerated devices were accepted!") );
- DEBUG_MSG( _T("Try enabling the D3D Reference Rasterizer.") );
- return D3DENUMERR_SUGGESTREFRAST;
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_FreeResources()
-// Desc: Cleans up any memory allocated during device enumeration
-//-----------------------------------------------------------------------------
-VOID D3DEnum_FreeResources()
-{
- for( DWORD i=0; i<g_dwNumDevices; i++ )
- {
- SAFE_DELETE( g_pDeviceList[i].pddsdModes );
- }
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_GetDevices()
-// Desc: Returns a ptr to the array of D3DEnum_DeviceInfo structures.
-//-----------------------------------------------------------------------------
-VOID D3DEnum_GetDevices( D3DEnum_DeviceInfo** ppDevices, DWORD* pdwCount )
-{
- if( ppDevices )
- (*ppDevices) = g_pDeviceList;
- if( pdwCount )
- (*pdwCount) = g_dwNumDevices;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: UpdateDialogControls()
-// Desc: Builds the list of devices and modes for the combo boxes in the device
-// select dialog box.
-//-----------------------------------------------------------------------------
-static VOID UpdateDialogControls( HWND hDlg, D3DEnum_DeviceInfo* pCurrentDevice,
- DWORD dwCurrentMode, bool bWindowed,
- bool bStereo )
-{
- // Get access to the enumerated device list
- D3DEnum_DeviceInfo* pDeviceList;
- DWORD dwNumDevices;
- D3DEnum_GetDevices( &pDeviceList, &dwNumDevices );
-
- // Access to UI controls
- HWND hwndDevice = GetDlgItem( hDlg, IDC_DEVICE_COMBO );
- HWND hwndMode = GetDlgItem( hDlg, IDC_MODE_COMBO );
- HWND hwndWindowed = GetDlgItem( hDlg, IDC_WINDOWED_CHECKBOX );
- HWND hwndStereo = GetDlgItem( hDlg, IDC_STEREO_CHECKBOX );
- HWND hwndFullscreenText = GetDlgItem( hDlg, IDC_FULLSCREEN_TEXT );
-
- // Reset the content in each of the combo boxes
- ComboBox_ResetContent( hwndDevice );
- ComboBox_ResetContent( hwndMode );
-
- // Don't let non-GDI devices be windowed
- if( false == pCurrentDevice->bDesktopCompatible )
- bWindowed = false;
-
- // Add a list of devices to the device combo box
- for( DWORD device = 0; device < dwNumDevices; device++ )
- {
- D3DEnum_DeviceInfo* pDevice = &pDeviceList[device];
-
- // Add device name to the combo box
- DWORD dwItem = ComboBox_AddString( hwndDevice, pDevice->strDesc );
-
- // Set the remaining UI states for the current device
- if( pDevice == pCurrentDevice )
- {
- // Set the combobox selection on the current device
- ComboBox_SetCurSel( hwndDevice, dwItem );
-
- // Enable/set the fullscreen checkbox, as appropriate
- if( hwndWindowed )
- {
- EnableWindow( hwndWindowed, pDevice->bDesktopCompatible );
- Button_SetCheck( hwndWindowed, bWindowed );
- }
-
- // Enable/set the stereo checkbox, as appropriate
- if( hwndStereo )
- {
- EnableWindow( hwndStereo, pDevice->bStereoCompatible && !bWindowed );
- Button_SetCheck( hwndStereo, bStereo );
- }
-
- // Enable/set the fullscreen modes combo, as appropriate
- EnableWindow( hwndMode, !bWindowed );
- EnableWindow( hwndFullscreenText, !bWindowed );
-
- // Build the list of fullscreen modes
- for( DWORD mode = 0; mode < pDevice->dwNumModes; mode++ )
- {
- DDSURFACEDESC2* pddsdMode = &pDevice->pddsdModes[mode];
-
- // Skip non-stereo modes, if the device is in stereo mode
- if( 0 == (pddsdMode->ddsCaps.dwCaps2&DDSCAPS2_STEREOSURFACELEFT) )
- if( bStereo )
- continue;
-
- TCHAR strMode[80];
- wsprintf( strMode, _T("%ld x %ld x %ld"),
- pddsdMode->dwWidth, pddsdMode->dwHeight,
- pddsdMode->ddpfPixelFormat.dwRGBBitCount );
-
- // Add mode desc to the combo box
- DWORD dwItem = ComboBox_AddString( hwndMode, strMode );
-
- // Set the item data to identify this mode
- ComboBox_SetItemData( hwndMode, dwItem, mode );
-
- // Set the combobox selection on the current mode
- if( mode == dwCurrentMode )
- ComboBox_SetCurSel( hwndMode, dwItem );
-
- // Since not all modes support stereo, select a default mode in
- // case none was chosen yet.
- if( bStereo && ( CB_ERR == ComboBox_GetCurSel( hwndMode ) ) )
- ComboBox_SetCurSel( hwndMode, dwItem );
- }
- }
- }
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: ChangeDeviceProc()
-// Desc: Windows message handling function for the device select dialog
-//-----------------------------------------------------------------------------
-static INT_PTR CALLBACK ChangeDeviceProc( HWND hDlg, UINT uiMsg, WPARAM wParam,
- LPARAM lParam )
-{
- static D3DEnum_DeviceInfo** ppDeviceArg;
- static D3DEnum_DeviceInfo* pCurrentDevice;
- static DWORD dwCurrentMode;
- static bool bCurrentWindowed;
- static bool bCurrentStereo;
-
- // Get access to the enumerated device list
- D3DEnum_DeviceInfo* pDeviceList;
- DWORD dwNumDevices;
- D3DEnum_GetDevices( &pDeviceList, &dwNumDevices );
-
- // Handle the initialization message
- if( WM_INITDIALOG == uiMsg )
- {
- // Get the app's current device, passed in as an lParam argument
- ppDeviceArg = (D3DEnum_DeviceInfo**)lParam;
- if( NULL == ppDeviceArg )
- return false;
-
- // Setup temp storage pointers for dialog
- pCurrentDevice = (*ppDeviceArg);
- dwCurrentMode = pCurrentDevice->dwCurrentMode;
- bCurrentWindowed = pCurrentDevice->bWindowed;
- bCurrentStereo = pCurrentDevice->bStereo;
-
- UpdateDialogControls( hDlg, pCurrentDevice, dwCurrentMode,
- bCurrentWindowed, bCurrentStereo );
-
- return true;
- }
- else if( WM_COMMAND == uiMsg )
- {
- HWND hwndDevice = GetDlgItem( hDlg, IDC_DEVICE_COMBO );
- HWND hwndMode = GetDlgItem( hDlg, IDC_MODE_COMBO );
- HWND hwndWindowed = GetDlgItem( hDlg, IDC_WINDOWED_CHECKBOX );
- HWND hwndStereo = GetDlgItem( hDlg, IDC_STEREO_CHECKBOX );
-
- // Get current UI state
- DWORD dwDevice = ComboBox_GetCurSel( hwndDevice );
- DWORD dwModeItem = ComboBox_GetCurSel( hwndMode );
- DWORD dwMode = ComboBox_GetItemData( hwndMode, dwModeItem );
- bool bWindowed = hwndWindowed ? Button_GetCheck( hwndWindowed ) : 0;
- bool bStereo = hwndStereo ? Button_GetCheck( hwndStereo ) : 0;
-
- D3DEnum_DeviceInfo* pDevice = &pDeviceList[dwDevice];
-
- if( IDOK == LOWORD(wParam) )
- {
- // Handle the case when the user hits the OK button. Check if any
- // of the options were changed
- if( pDevice != pCurrentDevice || dwMode != dwCurrentMode ||
- bWindowed != bCurrentWindowed || bStereo != bCurrentStereo )
- {
- // Return the newly selected device and its new properties
- (*ppDeviceArg) = pDevice;
- pDevice->bWindowed = bWindowed;
- pDevice->bStereo = bStereo;
- pDevice->dwCurrentMode = dwMode;
- pDevice->ddsdFullscreenMode = pDevice->pddsdModes[dwMode];
-
- EndDialog( hDlg, IDOK );
- }
- else
- EndDialog( hDlg, IDCANCEL );
-
- return true;
- }
- else if( IDCANCEL == LOWORD(wParam) )
- {
- // Handle the case when the user hits the Cancel button
- EndDialog( hDlg, IDCANCEL );
- return true;
- }
- else if( CBN_SELENDOK == HIWORD(wParam) )
- {
- if( LOWORD(wParam) == IDC_DEVICE_COMBO )
- {
- // Handle the case when the user chooses the device combo
- dwMode = pDeviceList[dwDevice].dwCurrentMode;
- bWindowed = pDeviceList[dwDevice].bWindowed;
- bStereo = pDeviceList[dwDevice].bStereo;
- }
- }
-
- // Keep the UI current
- UpdateDialogControls( hDlg, &pDeviceList[dwDevice], dwMode, bWindowed, bStereo );
- return true;
- }
-
- return false;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_UserChangeDevice()
-// Desc: Pops up a dialog which allows the user to select a new device.
-//-----------------------------------------------------------------------------
-HRESULT D3DEnum_UserChangeDevice( D3DEnum_DeviceInfo** ppDevice )
-{
- if( IDOK == DialogBoxParam( (HINSTANCE)GetModuleHandle(NULL),
- MAKEINTRESOURCE(IDD_CHANGEDEVICE),
- GetForegroundWindow(),
- ChangeDeviceProc, (LPARAM)ppDevice ) )
- return S_OK;
-
- return E_FAIL;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_SelectDefaultDevice()
-// Desc: Pick a default device, preferably hardware and desktop compatible.
-//-----------------------------------------------------------------------------
-HRESULT D3DEnum_SelectDefaultDevice( D3DEnum_DeviceInfo** ppDevice,
- DWORD dwFlags )
-{
- // Check arguments
- if( NULL == ppDevice )
- return E_INVALIDARG;
-
- // Get access to the enumerated device list
- D3DEnum_DeviceInfo* pDeviceList;
- DWORD dwNumDevices;
- D3DEnum_GetDevices( &pDeviceList, &dwNumDevices );
-
- // Look for windowable software, hardware, and hardware TnL devices
- D3DEnum_DeviceInfo* pRefRastDevice = NULL;
- D3DEnum_DeviceInfo* pSoftwareDevice = NULL;
- D3DEnum_DeviceInfo* pHardwareDevice = NULL;
- D3DEnum_DeviceInfo* pHardwareTnLDevice = NULL;
-
- for( DWORD i=0; i<dwNumDevices; i++ )
- {
- if( pDeviceList[i].bDesktopCompatible )
- {
- if( pDeviceList[i].bHardware )
- {
- if( (*pDeviceList[i].pDeviceGUID) == IID_IDirect3DTnLHalDevice )
- pHardwareTnLDevice = &pDeviceList[i];
- else
- pHardwareDevice = &pDeviceList[i];
- }
- else
- {
- if( (*pDeviceList[i].pDeviceGUID) == IID_IDirect3DRefDevice )
- pRefRastDevice = &pDeviceList[i];
- else
- pSoftwareDevice = &pDeviceList[i];
- }
- }
- }
-
- // Prefer a hardware non-TnL device first, then a TnL hardware device, and
- // finally, a software device.
- if( 0 == ( dwFlags & D3DENUM_SOFTWAREONLY ) && pHardwareDevice )
- (*ppDevice) = pHardwareDevice;
- else if( 0 == ( dwFlags & D3DENUM_SOFTWAREONLY ) && pHardwareTnLDevice )
- (*ppDevice) = pHardwareTnLDevice;
- else if( pSoftwareDevice )
- (*ppDevice) = pSoftwareDevice;
- else if( pRefRastDevice )
- (*ppDevice) = pRefRastDevice;
- else
- return D3DENUMERR_NOCOMPATIBLEDEVICES;
-
- // Set the windowed state of the newly selected device
- (*ppDevice)->bWindowed = true;
-
- return S_OK;
-}
-
-
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+//-----------------------------------------------------------------------------
+// File: D3DEnum.cpp
+//
+// Desc: Functions to enumerate DDraw/D3D drivers, devices, and modes.
+//
+// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+#include <windowsx.h>
+#include <stdio.h>
+#include <tchar.h>
+#include "old/d3denum.h"
+#include "old/d3dutil.h" // For DEBUG_MSG
+#include "old/d3dres.h" // For dialog controls
+
+
+
+
+//-----------------------------------------------------------------------------
+// Global data for the enumerator functions
+//-----------------------------------------------------------------------------
+static HRESULT (*g_fnAppConfirmFn)(DDCAPS*, D3DDEVICEDESC7*) = NULL;
+
+static D3DEnum_DeviceInfo g_pDeviceList[20];
+static DWORD g_dwNumDevicesEnumerated = 0L;
+static DWORD g_dwNumDevices = 0L;
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: SortModesCallback()
+// Desc: Callback function for sorting display modes.
+//-----------------------------------------------------------------------------
+int SortModesCallback( const VOID* arg1, const VOID* arg2 )
+{
+ DDSURFACEDESC2* p1 = (DDSURFACEDESC2*)arg1;
+ DDSURFACEDESC2* p2 = (DDSURFACEDESC2*)arg2;
+
+ if( p1->dwWidth < p2->dwWidth )
+ return -1;
+ if( p1->dwWidth > p2->dwWidth )
+ return +1;
+
+ if( p1->dwHeight < p2->dwHeight )
+ return -1;
+ if( p1->dwHeight > p2->dwHeight )
+ return +1;
+
+ if( p1->ddpfPixelFormat.dwRGBBitCount < p2->ddpfPixelFormat.dwRGBBitCount )
+ return -1;
+ if( p1->ddpfPixelFormat.dwRGBBitCount > p2->ddpfPixelFormat.dwRGBBitCount )
+ return +1;
+
+ return 0;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: ModeEnumCallback()
+// Desc: Callback function for enumerating display modes.
+//-----------------------------------------------------------------------------
+static HRESULT WINAPI ModeEnumCallback( DDSURFACEDESC2* pddsd,
+ VOID* pParentInfo )
+{
+ D3DEnum_DeviceInfo* pDevice = (D3DEnum_DeviceInfo*)pParentInfo;
+
+ // Reallocate storage for the modes
+ DDSURFACEDESC2* pddsdNewModes = new DDSURFACEDESC2[pDevice->dwNumModes+1];
+ memcpy( pddsdNewModes, pDevice->pddsdModes,
+ pDevice->dwNumModes * sizeof(DDSURFACEDESC2) );
+ delete pDevice->pddsdModes;
+ pDevice->pddsdModes = pddsdNewModes;
+
+ // Add the new mode
+ pDevice->pddsdModes[pDevice->dwNumModes++] = (*pddsd);
+
+ return DDENUMRET_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: DeviceEnumCallback()
+// Desc: Callback function for enumerating devices
+//-----------------------------------------------------------------------------
+static HRESULT WINAPI DeviceEnumCallback( TCHAR* strDesc, TCHAR* strName,
+ D3DDEVICEDESC7* pDesc,
+ VOID* pParentInfo )
+{
+ DWORD i;
+
+ // Keep track of # of devices that were enumerated
+ g_dwNumDevicesEnumerated++;
+
+ D3DEnum_DeviceInfo* pDriverInfo = (D3DEnum_DeviceInfo*)pParentInfo;
+ D3DEnum_DeviceInfo* pDeviceInfo = &g_pDeviceList[g_dwNumDevices];
+ ZeroMemory( pDeviceInfo, sizeof(D3DEnum_DeviceInfo) );
+
+ // Select either the HAL or HEL device desc:
+ pDeviceInfo->bHardware = pDesc->dwDevCaps & D3DDEVCAPS_HWRASTERIZATION;
+ memcpy( &pDeviceInfo->ddDeviceDesc, pDesc, sizeof(D3DDEVICEDESC7) );
+
+ // Set up device info for this device
+ pDeviceInfo->bDesktopCompatible = pDriverInfo->bDesktopCompatible;
+ pDeviceInfo->ddDriverCaps = pDriverInfo->ddDriverCaps;
+ pDeviceInfo->ddHELCaps = pDriverInfo->ddHELCaps;
+ pDeviceInfo->guidDevice = pDesc->deviceGUID;
+ pDeviceInfo->pDeviceGUID = &pDeviceInfo->guidDevice;
+ pDeviceInfo->pddsdModes = new DDSURFACEDESC2[pDriverInfo->dwNumModes];
+
+ // Copy the driver GUID and description for the device
+ if( pDriverInfo->pDriverGUID )
+ {
+ pDeviceInfo->guidDriver = pDriverInfo->guidDriver;
+ pDeviceInfo->pDriverGUID = &pDeviceInfo->guidDriver;
+ lstrcpyn( pDeviceInfo->strDesc, pDriverInfo->strDesc, 39 );
+ }
+ else
+ {
+ pDeviceInfo->pDriverGUID = NULL;
+ lstrcpyn( pDeviceInfo->strDesc, strName, 39 );
+ }
+
+//? if( strstr(strName, "T&L") != 0 ) return D3DENUMRET_OK;
+
+ // Avoid duplicates: only enum HW devices for secondary DDraw drivers.
+ if( NULL != pDeviceInfo->pDriverGUID && false == pDeviceInfo->bHardware )
+ return D3DENUMRET_OK;
+
+ // Give the app a chance to accept or reject this device.
+ if( g_fnAppConfirmFn )
+ if( FAILED( g_fnAppConfirmFn( &pDeviceInfo->ddDriverCaps,
+ &pDeviceInfo->ddDeviceDesc ) ) )
+ return D3DENUMRET_OK;
+
+ // Build list of supported modes for the device
+ for( i=0; i<pDriverInfo->dwNumModes; i++ )
+ {
+ DDSURFACEDESC2 ddsdMode = pDriverInfo->pddsdModes[i];
+ DWORD dwRenderDepths = pDeviceInfo->ddDeviceDesc.dwDeviceRenderBitDepth;
+ DWORD dwDepth = ddsdMode.ddpfPixelFormat.dwRGBBitCount;
+
+ // Accept modes that are compatable with the device
+ if( ( ( dwDepth == 32 ) && ( dwRenderDepths & DDBD_32 ) ) ||
+ ( ( dwDepth == 24 ) && ( dwRenderDepths & DDBD_24 ) ) ||
+ ( ( dwDepth == 16 ) && ( dwRenderDepths & DDBD_16 ) ) )
+ {
+ // Copy compatible modes to the list of device-supported modes
+ pDeviceInfo->pddsdModes[pDeviceInfo->dwNumModes++] = ddsdMode;
+
+ // Record whether the device has any stereo modes
+ if( ddsdMode.ddsCaps.dwCaps2 & DDSCAPS2_STEREOSURFACELEFT )
+ pDeviceInfo->bStereoCompatible = true;
+ }
+ }
+
+ // Bail if the device has no supported modes
+ if( 0 == pDeviceInfo->dwNumModes )
+ return D3DENUMRET_OK;
+
+ // Find a 640x480x16 mode for the default fullscreen mode
+ for( i=0; i<pDeviceInfo->dwNumModes; i++ )
+ {
+ if( ( pDeviceInfo->pddsdModes[i].dwWidth == 640 ) &&
+ ( pDeviceInfo->pddsdModes[i].dwHeight == 480 ) &&
+ ( pDeviceInfo->pddsdModes[i].ddpfPixelFormat.dwRGBBitCount == 16 ) )
+ {
+ pDeviceInfo->ddsdFullscreenMode = pDeviceInfo->pddsdModes[i];
+ pDeviceInfo->dwCurrentMode = i;
+ }
+ }
+
+ // Select whether the device is initially windowed
+ pDeviceInfo->bWindowed = pDeviceInfo->bDesktopCompatible;
+
+ // Accept the device and return
+ g_dwNumDevices++;
+
+ return D3DENUMRET_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: DriverEnumCallback()
+// Desc: Callback function for enumerating drivers.
+//-----------------------------------------------------------------------------
+static bool WINAPI DriverEnumCallback( GUID* pGUID, TCHAR* strDesc,
+ TCHAR* strName, VOID*, HMONITOR )
+{
+ D3DEnum_DeviceInfo d3dDeviceInfo;
+ LPDIRECTDRAW7 pDD;
+ LPDIRECT3D7 pD3D;
+ HRESULT hr;
+
+ // Use the GUID to create the DirectDraw object
+ hr = DirectDrawCreateEx( pGUID, (VOID**)&pDD, IID_IDirectDraw7, NULL );
+ if( FAILED(hr) )
+ {
+ DEBUG_MSG( _T("Can't create DDraw during enumeration!") );
+ return D3DENUMRET_OK;
+ }
+
+ // Create a D3D object, to enumerate the d3d devices
+ hr = pDD->QueryInterface( IID_IDirect3D7, (VOID**)&pD3D );
+ if( FAILED(hr) )
+ {
+ pDD->Release();
+ DEBUG_MSG( _T("Can't query IDirect3D7 during enumeration!") );
+ return D3DENUMRET_OK;
+ }
+
+ // Copy data to a device info structure
+ ZeroMemory( &d3dDeviceInfo, sizeof(d3dDeviceInfo) );
+ lstrcpyn( d3dDeviceInfo.strDesc, strDesc, 39 );
+ d3dDeviceInfo.ddDriverCaps.dwSize = sizeof(DDCAPS);
+ d3dDeviceInfo.ddHELCaps.dwSize = sizeof(DDCAPS);
+ pDD->GetCaps( &d3dDeviceInfo.ddDriverCaps, &d3dDeviceInfo.ddHELCaps );
+ if( pGUID )
+ {
+ d3dDeviceInfo.guidDriver = (*pGUID);
+ d3dDeviceInfo.pDriverGUID = &d3dDeviceInfo.guidDriver;
+ }
+
+ // Record whether the device can render into a desktop window
+ if( d3dDeviceInfo.ddDriverCaps.dwCaps2 & DDCAPS2_CANRENDERWINDOWED )
+ if( NULL == d3dDeviceInfo.pDriverGUID )
+ d3dDeviceInfo.bDesktopCompatible = true;
+
+ // Enumerate the fullscreen display modes.
+ pDD->EnumDisplayModes( 0, NULL, &d3dDeviceInfo, ModeEnumCallback );
+
+ // Sort list of display modes
+ qsort( d3dDeviceInfo.pddsdModes, d3dDeviceInfo.dwNumModes,
+ sizeof(DDSURFACEDESC2), SortModesCallback );
+
+ // Now, enumerate all the 3D devices
+ pD3D->EnumDevices( DeviceEnumCallback, &d3dDeviceInfo );
+
+ // Clean up and return
+ SAFE_DELETE( d3dDeviceInfo.pddsdModes );
+ pD3D->Release();
+ pDD->Release();
+
+ return DDENUMRET_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_EnumerateDevices()
+// Desc: Enumerates all drivers, devices, and modes. The callback function is
+// called each device, to confirm that the device supports the feature
+// set required by the app.
+//-----------------------------------------------------------------------------
+HRESULT D3DEnum_EnumerateDevices( HRESULT (*AppConfirmFn)(DDCAPS*, D3DDEVICEDESC7*) )
+{
+ // Store the device enumeration callback function
+ g_fnAppConfirmFn = AppConfirmFn;
+
+ // Enumerate drivers, devices, and modes
+ DirectDrawEnumerateEx( DriverEnumCallback, NULL,
+ DDENUM_ATTACHEDSECONDARYDEVICES |
+ DDENUM_DETACHEDSECONDARYDEVICES |
+ DDENUM_NONDISPLAYDEVICES );
+
+ // Make sure devices were actually enumerated
+ if( 0 == g_dwNumDevicesEnumerated )
+ {
+ DEBUG_MSG( _T("No devices and/or modes were enumerated!") );
+ return D3DENUMERR_ENUMERATIONFAILED;
+ }
+ if( 0 == g_dwNumDevices )
+ {
+ DEBUG_MSG( _T("No enumerated devices were accepted!") );
+ DEBUG_MSG( _T("Try enabling the D3D Reference Rasterizer.") );
+ return D3DENUMERR_SUGGESTREFRAST;
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_FreeResources()
+// Desc: Cleans up any memory allocated during device enumeration
+//-----------------------------------------------------------------------------
+VOID D3DEnum_FreeResources()
+{
+ for( DWORD i=0; i<g_dwNumDevices; i++ )
+ {
+ SAFE_DELETE( g_pDeviceList[i].pddsdModes );
+ }
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_GetDevices()
+// Desc: Returns a ptr to the array of D3DEnum_DeviceInfo structures.
+//-----------------------------------------------------------------------------
+VOID D3DEnum_GetDevices( D3DEnum_DeviceInfo** ppDevices, DWORD* pdwCount )
+{
+ if( ppDevices )
+ (*ppDevices) = g_pDeviceList;
+ if( pdwCount )
+ (*pdwCount) = g_dwNumDevices;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: UpdateDialogControls()
+// Desc: Builds the list of devices and modes for the combo boxes in the device
+// select dialog box.
+//-----------------------------------------------------------------------------
+static VOID UpdateDialogControls( HWND hDlg, D3DEnum_DeviceInfo* pCurrentDevice,
+ DWORD dwCurrentMode, bool bWindowed,
+ bool bStereo )
+{
+ // Get access to the enumerated device list
+ D3DEnum_DeviceInfo* pDeviceList;
+ DWORD dwNumDevices;
+ D3DEnum_GetDevices( &pDeviceList, &dwNumDevices );
+
+ // Access to UI controls
+ HWND hwndDevice = GetDlgItem( hDlg, IDC_DEVICE_COMBO );
+ HWND hwndMode = GetDlgItem( hDlg, IDC_MODE_COMBO );
+ HWND hwndWindowed = GetDlgItem( hDlg, IDC_WINDOWED_CHECKBOX );
+ HWND hwndStereo = GetDlgItem( hDlg, IDC_STEREO_CHECKBOX );
+ HWND hwndFullscreenText = GetDlgItem( hDlg, IDC_FULLSCREEN_TEXT );
+
+ // Reset the content in each of the combo boxes
+ ComboBox_ResetContent( hwndDevice );
+ ComboBox_ResetContent( hwndMode );
+
+ // Don't let non-GDI devices be windowed
+ if( false == pCurrentDevice->bDesktopCompatible )
+ bWindowed = false;
+
+ // Add a list of devices to the device combo box
+ for( DWORD device = 0; device < dwNumDevices; device++ )
+ {
+ D3DEnum_DeviceInfo* pDevice = &pDeviceList[device];
+
+ // Add device name to the combo box
+ DWORD dwItem = ComboBox_AddString( hwndDevice, pDevice->strDesc );
+
+ // Set the remaining UI states for the current device
+ if( pDevice == pCurrentDevice )
+ {
+ // Set the combobox selection on the current device
+ ComboBox_SetCurSel( hwndDevice, dwItem );
+
+ // Enable/set the fullscreen checkbox, as appropriate
+ if( hwndWindowed )
+ {
+ EnableWindow( hwndWindowed, pDevice->bDesktopCompatible );
+ Button_SetCheck( hwndWindowed, bWindowed );
+ }
+
+ // Enable/set the stereo checkbox, as appropriate
+ if( hwndStereo )
+ {
+ EnableWindow( hwndStereo, pDevice->bStereoCompatible && !bWindowed );
+ Button_SetCheck( hwndStereo, bStereo );
+ }
+
+ // Enable/set the fullscreen modes combo, as appropriate
+ EnableWindow( hwndMode, !bWindowed );
+ EnableWindow( hwndFullscreenText, !bWindowed );
+
+ // Build the list of fullscreen modes
+ for( DWORD mode = 0; mode < pDevice->dwNumModes; mode++ )
+ {
+ DDSURFACEDESC2* pddsdMode = &pDevice->pddsdModes[mode];
+
+ // Skip non-stereo modes, if the device is in stereo mode
+ if( 0 == (pddsdMode->ddsCaps.dwCaps2&DDSCAPS2_STEREOSURFACELEFT) )
+ if( bStereo )
+ continue;
+
+ TCHAR strMode[80];
+ wsprintf( strMode, _T("%ld x %ld x %ld"),
+ pddsdMode->dwWidth, pddsdMode->dwHeight,
+ pddsdMode->ddpfPixelFormat.dwRGBBitCount );
+
+ // Add mode desc to the combo box
+ DWORD dwItem = ComboBox_AddString( hwndMode, strMode );
+
+ // Set the item data to identify this mode
+ ComboBox_SetItemData( hwndMode, dwItem, mode );
+
+ // Set the combobox selection on the current mode
+ if( mode == dwCurrentMode )
+ ComboBox_SetCurSel( hwndMode, dwItem );
+
+ // Since not all modes support stereo, select a default mode in
+ // case none was chosen yet.
+ if( bStereo && ( CB_ERR == ComboBox_GetCurSel( hwndMode ) ) )
+ ComboBox_SetCurSel( hwndMode, dwItem );
+ }
+ }
+ }
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: ChangeDeviceProc()
+// Desc: Windows message handling function for the device select dialog
+//-----------------------------------------------------------------------------
+static INT_PTR CALLBACK ChangeDeviceProc( HWND hDlg, UINT uiMsg, WPARAM wParam,
+ LPARAM lParam )
+{
+ static D3DEnum_DeviceInfo** ppDeviceArg;
+ static D3DEnum_DeviceInfo* pCurrentDevice;
+ static DWORD dwCurrentMode;
+ static bool bCurrentWindowed;
+ static bool bCurrentStereo;
+
+ // Get access to the enumerated device list
+ D3DEnum_DeviceInfo* pDeviceList;
+ DWORD dwNumDevices;
+ D3DEnum_GetDevices( &pDeviceList, &dwNumDevices );
+
+ // Handle the initialization message
+ if( WM_INITDIALOG == uiMsg )
+ {
+ // Get the app's current device, passed in as an lParam argument
+ ppDeviceArg = (D3DEnum_DeviceInfo**)lParam;
+ if( NULL == ppDeviceArg )
+ return false;
+
+ // Setup temp storage pointers for dialog
+ pCurrentDevice = (*ppDeviceArg);
+ dwCurrentMode = pCurrentDevice->dwCurrentMode;
+ bCurrentWindowed = pCurrentDevice->bWindowed;
+ bCurrentStereo = pCurrentDevice->bStereo;
+
+ UpdateDialogControls( hDlg, pCurrentDevice, dwCurrentMode,
+ bCurrentWindowed, bCurrentStereo );
+
+ return true;
+ }
+ else if( WM_COMMAND == uiMsg )
+ {
+ HWND hwndDevice = GetDlgItem( hDlg, IDC_DEVICE_COMBO );
+ HWND hwndMode = GetDlgItem( hDlg, IDC_MODE_COMBO );
+ HWND hwndWindowed = GetDlgItem( hDlg, IDC_WINDOWED_CHECKBOX );
+ HWND hwndStereo = GetDlgItem( hDlg, IDC_STEREO_CHECKBOX );
+
+ // Get current UI state
+ DWORD dwDevice = ComboBox_GetCurSel( hwndDevice );
+ DWORD dwModeItem = ComboBox_GetCurSel( hwndMode );
+ DWORD dwMode = ComboBox_GetItemData( hwndMode, dwModeItem );
+ bool bWindowed = hwndWindowed ? Button_GetCheck( hwndWindowed ) : 0;
+ bool bStereo = hwndStereo ? Button_GetCheck( hwndStereo ) : 0;
+
+ D3DEnum_DeviceInfo* pDevice = &pDeviceList[dwDevice];
+
+ if( IDOK == LOWORD(wParam) )
+ {
+ // Handle the case when the user hits the OK button. Check if any
+ // of the options were changed
+ if( pDevice != pCurrentDevice || dwMode != dwCurrentMode ||
+ bWindowed != bCurrentWindowed || bStereo != bCurrentStereo )
+ {
+ // Return the newly selected device and its new properties
+ (*ppDeviceArg) = pDevice;
+ pDevice->bWindowed = bWindowed;
+ pDevice->bStereo = bStereo;
+ pDevice->dwCurrentMode = dwMode;
+ pDevice->ddsdFullscreenMode = pDevice->pddsdModes[dwMode];
+
+ EndDialog( hDlg, IDOK );
+ }
+ else
+ EndDialog( hDlg, IDCANCEL );
+
+ return true;
+ }
+ else if( IDCANCEL == LOWORD(wParam) )
+ {
+ // Handle the case when the user hits the Cancel button
+ EndDialog( hDlg, IDCANCEL );
+ return true;
+ }
+ else if( CBN_SELENDOK == HIWORD(wParam) )
+ {
+ if( LOWORD(wParam) == IDC_DEVICE_COMBO )
+ {
+ // Handle the case when the user chooses the device combo
+ dwMode = pDeviceList[dwDevice].dwCurrentMode;
+ bWindowed = pDeviceList[dwDevice].bWindowed;
+ bStereo = pDeviceList[dwDevice].bStereo;
+ }
+ }
+
+ // Keep the UI current
+ UpdateDialogControls( hDlg, &pDeviceList[dwDevice], dwMode, bWindowed, bStereo );
+ return true;
+ }
+
+ return false;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_UserChangeDevice()
+// Desc: Pops up a dialog which allows the user to select a new device.
+//-----------------------------------------------------------------------------
+HRESULT D3DEnum_UserChangeDevice( D3DEnum_DeviceInfo** ppDevice )
+{
+ if( IDOK == DialogBoxParam( (HINSTANCE)GetModuleHandle(NULL),
+ MAKEINTRESOURCE(IDD_CHANGEDEVICE),
+ GetForegroundWindow(),
+ ChangeDeviceProc, (LPARAM)ppDevice ) )
+ return S_OK;
+
+ return E_FAIL;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_SelectDefaultDevice()
+// Desc: Pick a default device, preferably hardware and desktop compatible.
+//-----------------------------------------------------------------------------
+HRESULT D3DEnum_SelectDefaultDevice( D3DEnum_DeviceInfo** ppDevice,
+ DWORD dwFlags )
+{
+ // Check arguments
+ if( NULL == ppDevice )
+ return E_INVALIDARG;
+
+ // Get access to the enumerated device list
+ D3DEnum_DeviceInfo* pDeviceList;
+ DWORD dwNumDevices;
+ D3DEnum_GetDevices( &pDeviceList, &dwNumDevices );
+
+ // Look for windowable software, hardware, and hardware TnL devices
+ D3DEnum_DeviceInfo* pRefRastDevice = NULL;
+ D3DEnum_DeviceInfo* pSoftwareDevice = NULL;
+ D3DEnum_DeviceInfo* pHardwareDevice = NULL;
+ D3DEnum_DeviceInfo* pHardwareTnLDevice = NULL;
+
+ for( DWORD i=0; i<dwNumDevices; i++ )
+ {
+ if( pDeviceList[i].bDesktopCompatible )
+ {
+ if( pDeviceList[i].bHardware )
+ {
+ if( (*pDeviceList[i].pDeviceGUID) == IID_IDirect3DTnLHalDevice )
+ pHardwareTnLDevice = &pDeviceList[i];
+ else
+ pHardwareDevice = &pDeviceList[i];
+ }
+ else
+ {
+ if( (*pDeviceList[i].pDeviceGUID) == IID_IDirect3DRefDevice )
+ pRefRastDevice = &pDeviceList[i];
+ else
+ pSoftwareDevice = &pDeviceList[i];
+ }
+ }
+ }
+
+ // Prefer a hardware non-TnL device first, then a TnL hardware device, and
+ // finally, a software device.
+ if( 0 == ( dwFlags & D3DENUM_SOFTWAREONLY ) && pHardwareDevice )
+ (*ppDevice) = pHardwareDevice;
+ else if( 0 == ( dwFlags & D3DENUM_SOFTWAREONLY ) && pHardwareTnLDevice )
+ (*ppDevice) = pHardwareTnLDevice;
+ else if( pSoftwareDevice )
+ (*ppDevice) = pSoftwareDevice;
+ else if( pRefRastDevice )
+ (*ppDevice) = pRefRastDevice;
+ else
+ return D3DENUMERR_NOCOMPATIBLEDEVICES;
+
+ // Set the windowed state of the newly selected device
+ (*ppDevice)->bWindowed = true;
+
+ return S_OK;
+}
+
+
+
+
+
diff --git a/src/old/d3denum.h b/src/old/d3denum.h
index 4f1edfc..fe49249 100644
--- a/src/old/d3denum.h
+++ b/src/old/d3denum.h
@@ -1,133 +1,133 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-//-----------------------------------------------------------------------------
-// File: D3DEnum.h
-//
-// Desc: Functions to enumerate DDraw/D3D drivers, devices, and modes.
-//
-// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-
-#pragma once
-
-#include <d3d.h>
-
-
-//-----------------------------------------------------------------------------
-// Flag and error definitions
-//-----------------------------------------------------------------------------
-#define D3DENUM_SOFTWAREONLY 0x00000001 // Software-devices only flag
-
-#define D3DENUMERR_NODIRECTDRAW 0x81000001 // Could not create DDraw
-#define D3DENUMERR_ENUMERATIONFAILED 0x81000002 // Enumeration failed
-#define D3DENUMERR_SUGGESTREFRAST 0x81000003 // Suggest using the RefRast
-#define D3DENUMERR_NOCOMPATIBLEDEVICES 0x81000004 // No devices were found that
- // meet the app's desired
- // capabilities
-#define D3DENUMERR_ENGINE 0x81000005 // 3D engine error
-#define D3DENUMERR_ROBOT 0x81000006 // robot error
-#define D3DENUMERR_SOUND 0x81000007 // sound error
-
-
-//-----------------------------------------------------------------------------
-// Name: struct D3DEnum_DeviceInfo
-// Desc: Structure to hold info about the enumerated Direct3D devices.
-//-----------------------------------------------------------------------------
-struct D3DEnum_DeviceInfo
-{
- // D3D Device info
- TCHAR strDesc[40];
- GUID* pDeviceGUID;
- D3DDEVICEDESC7 ddDeviceDesc;
- bool bHardware;
-
- // DDraw Driver info
- GUID* pDriverGUID;
- DDCAPS ddDriverCaps;
- DDCAPS ddHELCaps;
-
- // DDraw Mode Info
- DDSURFACEDESC2 ddsdFullscreenMode;
- bool bWindowed;
- bool bStereo;
-
- // For internal use (apps should not need to use these)
- GUID guidDevice;
- GUID guidDriver;
- DDSURFACEDESC2* pddsdModes;
- DWORD dwNumModes;
- DWORD dwCurrentMode;
- bool bDesktopCompatible;
- bool bStereoCompatible;
-};
-
-
-// For code not yet switched to new struct name
-typedef D3DEnum_DeviceInfo D3DDEVICEINFO;
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_EnumerateDevices()
-// Desc: Enumerates all drivers, devices, and modes. The callback function is
-// called each device, to confirm that the device supports the feature
-// set required by the app.
-//-----------------------------------------------------------------------------
-HRESULT D3DEnum_EnumerateDevices( HRESULT (*fn)(DDCAPS*, D3DDEVICEDESC7*) );
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_FreeResources()
-// Desc: Cleans up any memory allocated during device enumeration
-//-----------------------------------------------------------------------------
-VOID D3DEnum_FreeResources();
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_GetDevices()
-// Desc: Returns a ptr to the array of enumerated D3DDEVICEINFO structures.
-//-----------------------------------------------------------------------------
-VOID D3DEnum_GetDevices( D3DEnum_DeviceInfo** ppDevices, DWORD* pdwCount );
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_SelectDefaultDevice()
-// Desc: Picks a driver based on a set of passed in criteria. The
-// D3DENUM_SOFTWAREONLY flag can be used to pick a software device.
-//-----------------------------------------------------------------------------
-HRESULT D3DEnum_SelectDefaultDevice( D3DEnum_DeviceInfo** pDevice,
- DWORD dwFlags = 0L );
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_UserChangeDevice()
-// Desc: Pops up a dialog which allows the user to select a new device.
-//-----------------------------------------------------------------------------
-HRESULT D3DEnum_UserChangeDevice( D3DEnum_DeviceInfo** ppDevice );
-
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+//-----------------------------------------------------------------------------
+// File: D3DEnum.h
+//
+// Desc: Functions to enumerate DDraw/D3D drivers, devices, and modes.
+//
+// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+#include <d3d.h>
+
+
+//-----------------------------------------------------------------------------
+// Flag and error definitions
+//-----------------------------------------------------------------------------
+#define D3DENUM_SOFTWAREONLY 0x00000001 // Software-devices only flag
+
+#define D3DENUMERR_NODIRECTDRAW 0x81000001 // Could not create DDraw
+#define D3DENUMERR_ENUMERATIONFAILED 0x81000002 // Enumeration failed
+#define D3DENUMERR_SUGGESTREFRAST 0x81000003 // Suggest using the RefRast
+#define D3DENUMERR_NOCOMPATIBLEDEVICES 0x81000004 // No devices were found that
+ // meet the app's desired
+ // capabilities
+#define D3DENUMERR_ENGINE 0x81000005 // 3D engine error
+#define D3DENUMERR_ROBOT 0x81000006 // robot error
+#define D3DENUMERR_SOUND 0x81000007 // sound error
+
+
+//-----------------------------------------------------------------------------
+// Name: struct D3DEnum_DeviceInfo
+// Desc: Structure to hold info about the enumerated Direct3D devices.
+//-----------------------------------------------------------------------------
+struct D3DEnum_DeviceInfo
+{
+ // D3D Device info
+ TCHAR strDesc[40];
+ GUID* pDeviceGUID;
+ D3DDEVICEDESC7 ddDeviceDesc;
+ bool bHardware;
+
+ // DDraw Driver info
+ GUID* pDriverGUID;
+ DDCAPS ddDriverCaps;
+ DDCAPS ddHELCaps;
+
+ // DDraw Mode Info
+ DDSURFACEDESC2 ddsdFullscreenMode;
+ bool bWindowed;
+ bool bStereo;
+
+ // For internal use (apps should not need to use these)
+ GUID guidDevice;
+ GUID guidDriver;
+ DDSURFACEDESC2* pddsdModes;
+ DWORD dwNumModes;
+ DWORD dwCurrentMode;
+ bool bDesktopCompatible;
+ bool bStereoCompatible;
+};
+
+
+// For code not yet switched to new struct name
+typedef D3DEnum_DeviceInfo D3DDEVICEINFO;
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_EnumerateDevices()
+// Desc: Enumerates all drivers, devices, and modes. The callback function is
+// called each device, to confirm that the device supports the feature
+// set required by the app.
+//-----------------------------------------------------------------------------
+HRESULT D3DEnum_EnumerateDevices( HRESULT (*fn)(DDCAPS*, D3DDEVICEDESC7*) );
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_FreeResources()
+// Desc: Cleans up any memory allocated during device enumeration
+//-----------------------------------------------------------------------------
+VOID D3DEnum_FreeResources();
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_GetDevices()
+// Desc: Returns a ptr to the array of enumerated D3DDEVICEINFO structures.
+//-----------------------------------------------------------------------------
+VOID D3DEnum_GetDevices( D3DEnum_DeviceInfo** ppDevices, DWORD* pdwCount );
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_SelectDefaultDevice()
+// Desc: Picks a driver based on a set of passed in criteria. The
+// D3DENUM_SOFTWAREONLY flag can be used to pick a software device.
+//-----------------------------------------------------------------------------
+HRESULT D3DEnum_SelectDefaultDevice( D3DEnum_DeviceInfo** pDevice,
+ DWORD dwFlags = 0L );
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_UserChangeDevice()
+// Desc: Pops up a dialog which allows the user to select a new device.
+//-----------------------------------------------------------------------------
+HRESULT D3DEnum_UserChangeDevice( D3DEnum_DeviceInfo** ppDevice );
+
+
+
+
diff --git a/src/old/d3dframe.cpp b/src/old/d3dframe.cpp
index 3f984bd..370babb 100644
--- a/src/old/d3dframe.cpp
+++ b/src/old/d3dframe.cpp
@@ -1,622 +1,622 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-//-----------------------------------------------------------------------------
-// File: D3DFrame.cpp
-//
-// Desc: Class functions to implement a Direct3D app framework.
-//
-// Copyright (c) 1995-1999 by Microsoft, all rights reserved
-//-----------------------------------------------------------------------------
-#include <windows.h>
-#include <stdio.h>
-#include <tchar.h>
-#include "old/d3dframe.h"
-#include "old/d3dutil.h"
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CD3DFramework7()
-// Desc: The constructor. Clears static variables
-//-----------------------------------------------------------------------------
-CD3DFramework7::CD3DFramework7()
-{
- m_hWnd = NULL;
- m_bIsFullscreen = false;
- m_bIsStereo = false;
- m_dwRenderWidth = 0L;
- m_dwRenderHeight = 0L;
-
- m_pddsFrontBuffer = NULL;
- m_pddsBackBuffer = NULL;
- m_pddsBackBufferLeft = NULL;
-
- m_pddsZBuffer = NULL;
- m_pd3dDevice = NULL;
- m_pDD = NULL;
- m_pD3D = NULL;
- m_dwDeviceMemType = NULL;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: ~CD3DFramework7()
-// Desc: The destructor. Deletes all objects
-//-----------------------------------------------------------------------------
-CD3DFramework7::~CD3DFramework7()
-{
- DestroyObjects();
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: DestroyObjects()
-// Desc: Cleans everything up upon deletion. This code returns an error
-// if any of the objects have remaining reference counts.
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::DestroyObjects()
-{
- LONG nDD = 0L; // Number of outstanding DDraw references
- LONG nD3D = 0L; // Number of outstanding D3DDevice references
-
- if( m_pDD )
- {
- HRESULT err = m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL );
- char s[100];
- sprintf(s, "SetCooperativeLevel error=%d\n", err);
- OutputDebugString(s);
- }
-
- // Do a safe check for releasing the D3DDEVICE. RefCount must be zero.
- if( m_pd3dDevice )
- if( 0 < ( nD3D = m_pd3dDevice->Release() ) )
- DEBUG_MSG( _T("Error: D3DDevice object is still referenced!") );
- m_pd3dDevice = NULL;
-
- SAFE_RELEASE( m_pddsBackBuffer );
- SAFE_RELEASE( m_pddsBackBufferLeft );
- SAFE_RELEASE( m_pddsZBuffer );
- SAFE_RELEASE( m_pddsFrontBuffer );
- SAFE_RELEASE( m_pD3D );
-
- if( m_pDD )
- {
- // Do a safe check for releasing DDRAW. RefCount must be zero.
- if( 0 < ( nDD = m_pDD->Release() ) )
- DEBUG_MSG( _T("Error: DDraw object is still referenced!") );
- }
- m_pDD = NULL;
-
- // Return successful, unless there are outstanding DD or D3DDevice refs.
- return ( nDD==0 && nD3D==0 ) ? S_OK : D3DFWERR_NONZEROREFCOUNT;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: Initialize()
-// Desc: Creates the internal objects for the framework
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::Initialize( HWND hWnd, GUID* pDriverGUID,
- GUID* pDeviceGUID, DDSURFACEDESC2* pMode,
- DWORD dwFlags )
-{
- HRESULT hr;
-
- // Check params. Note: A NULL mode is valid for windowed modes only.
- if( ( NULL==hWnd ) || ( NULL==pDeviceGUID ) ||
- ( NULL==pMode && (dwFlags&D3DFW_FULLSCREEN) ) )
- return E_INVALIDARG;
-
- // Setup state for windowed/fullscreen mode
- m_hWnd = hWnd;
- m_bIsStereo = false;
- m_bIsFullscreen = ( dwFlags & D3DFW_FULLSCREEN ) ? true : false;
-
- // Support stereoscopic viewing for fullscreen modes which support it
- if( ( dwFlags & D3DFW_STEREO ) && ( dwFlags & D3DFW_FULLSCREEN ) )
- if( pMode->ddsCaps.dwCaps2 & DDSCAPS2_STEREOSURFACELEFT )
- m_bIsStereo = true;
-
- // Create the D3D rendering environment (surfaces, device, viewport, etc.)
- if( FAILED( hr = CreateEnvironment( pDriverGUID, pDeviceGUID, pMode,
- dwFlags ) ) )
- {
- DestroyObjects();
- return hr;
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CreateEnvironment()
-// Desc: Creates the internal objects for the framework
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::CreateEnvironment( GUID* pDriverGUID, GUID* pDeviceGUID,
- DDSURFACEDESC2* pMode, DWORD dwFlags )
-{
- HRESULT hr;
-
- // Select the default memory type, for whether the device is HW or SW
- if( IsEqualIID( *pDeviceGUID, IID_IDirect3DHALDevice) )
- m_dwDeviceMemType = DDSCAPS_VIDEOMEMORY;
- else if( IsEqualIID( *pDeviceGUID, IID_IDirect3DTnLHalDevice) )
- m_dwDeviceMemType = DDSCAPS_VIDEOMEMORY;
- else
- m_dwDeviceMemType = DDSCAPS_SYSTEMMEMORY;
-
- // Create the DDraw object
- hr = CreateDirectDraw( pDriverGUID, dwFlags );
- if( FAILED( hr ) )
- return hr;
-
- // Create the front and back buffers, and attach a clipper
- if( dwFlags & D3DFW_FULLSCREEN )
- hr = CreateFullscreenBuffers( pMode );
- else
- hr = CreateWindowedBuffers();
- if( FAILED( hr ) )
- return hr;
-
- // Create the Direct3D object and the Direct3DDevice object
- hr = CreateDirect3D( pDeviceGUID );
- if( FAILED( hr ) )
- return hr;
-
- // Create and attach the zbuffer
- if( dwFlags & D3DFW_ZBUFFER )
- hr = CreateZBuffer( pDeviceGUID );
- if( FAILED( hr ) )
- return hr;
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: EnumZBufferFormatsCallback()
-// Desc: Simply returns the first matching enumerated z-buffer format
-//-----------------------------------------------------------------------------
-static HRESULT WINAPI EnumZBufferFormatsCallback( DDPIXELFORMAT* pddpf,
- VOID* pContext )
-{
- DDPIXELFORMAT* pddpfOut = (DDPIXELFORMAT*)pContext;
-
- if( pddpfOut->dwRGBBitCount == pddpf->dwRGBBitCount )
- {
- (*pddpfOut) = (*pddpf);
- return D3DENUMRET_CANCEL;
- }
-
- return D3DENUMRET_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CreateDirectDraw()
-// Desc: Create the DirectDraw interface
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::CreateDirectDraw( GUID* pDriverGUID, DWORD dwFlags )
-{
- // Create the DirectDraw interface, and query for the DD7 interface
- if( FAILED( DirectDrawCreateEx( pDriverGUID, (VOID**)&m_pDD,
- IID_IDirectDraw7, NULL ) ) )
- {
- DEBUG_MSG( _T("Could not create DirectDraw") );
- return D3DFWERR_NODIRECTDRAW;
- }
-
- // Set the Windows cooperative level
- DWORD dwCoopFlags = DDSCL_NORMAL;
- if( m_bIsFullscreen )
- dwCoopFlags = DDSCL_ALLOWREBOOT|DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN;
-
- // By defualt, set the flag to allow D3D to optimize floating point calcs
- if( 0L == ( dwFlags & D3DFW_NO_FPUSETUP ) )
- dwCoopFlags |= DDSCL_FPUSETUP;
-
- if( FAILED( m_pDD->SetCooperativeLevel( m_hWnd, dwCoopFlags ) ) )
- {
- DEBUG_MSG( _T("Couldn't set coop level") );
- return D3DFWERR_COULDNTSETCOOPLEVEL;
- }
-
- // Check that we are NOT in a palettized display. That case will fail,
- // since the framework doesn't use palettes.
- DDSURFACEDESC2 ddsd;
- ddsd.dwSize = sizeof(ddsd);
- m_pDD->GetDisplayMode( &ddsd );
- if( ddsd.ddpfPixelFormat.dwRGBBitCount <= 8 )
- return D3DFWERR_INVALIDMODE;
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CreateFullscreenBuffers()
-// Desc: Creates the primary and (optional) backbuffer for rendering.
-// Windowed mode and fullscreen mode are handled differently.
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::CreateFullscreenBuffers( DDSURFACEDESC2* pddsd )
-{
- HRESULT hr;
-
- // Get the dimensions of the screen bounds
- // Store the rectangle which contains the renderer
- SetRect( &m_rcScreenRect, 0, 0, pddsd->dwWidth, pddsd->dwHeight );
- m_dwRenderWidth = m_rcScreenRect.right - m_rcScreenRect.left;
- m_dwRenderHeight = m_rcScreenRect.bottom - m_rcScreenRect.top;
-
- // Set the display mode to the requested dimensions. Check for
- // 320x200x8 modes, and set flag to avoid using ModeX
- DWORD dwModeFlags = 0;
-
- if( (320==m_dwRenderWidth) && (200==m_dwRenderHeight) &&
- (8==pddsd->ddpfPixelFormat.dwRGBBitCount) )
- dwModeFlags |= DDSDM_STANDARDVGAMODE;
-
- if( FAILED( m_pDD->SetDisplayMode( m_dwRenderWidth, m_dwRenderHeight,
- pddsd->ddpfPixelFormat.dwRGBBitCount,
- pddsd->dwRefreshRate, dwModeFlags ) ) )
- {
- DEBUG_MSG( _T("Can't set display mode") );
- return D3DFWERR_BADDISPLAYMODE;
- }
-
- // Setup to create the primary surface w/backbuffer
- DDSURFACEDESC2 ddsd;
- ZeroMemory( &ddsd, sizeof(ddsd) );
- ddsd.dwSize = sizeof(ddsd);
- ddsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
- ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE |
- DDSCAPS_FLIP | DDSCAPS_COMPLEX;
- ddsd.dwBackBufferCount = 1;
-
- // Support for stereoscopic viewing
- if( m_bIsStereo )
- {
- ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
- ddsd.ddsCaps.dwCaps2 |= DDSCAPS2_STEREOSURFACELEFT;
- }
-
- // Create the primary surface
- if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) )
- {
- DEBUG_MSG( _T("Error: Can't create primary surface") );
- if( hr != DDERR_OUTOFVIDEOMEMORY )
- return D3DFWERR_NOPRIMARY;
- DEBUG_MSG( _T("Error: Out of video memory") );
- return DDERR_OUTOFVIDEOMEMORY;
- }
-
- // Get the backbuffer, which was created along with the primary.
- DDSCAPS2 ddscaps = { DDSCAPS_BACKBUFFER, 0, 0, 0 };
- if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps,
- &m_pddsBackBuffer ) ) )
- {
- DEBUG_ERR( hr, _T("Error: Can't get the backbuffer") );
- return D3DFWERR_NOBACKBUFFER;
- }
-
- // Increment the backbuffer count (for consistency with windowed mode)
- m_pddsBackBuffer->AddRef();
-
- // Support for stereoscopic viewing
- if( m_bIsStereo )
- {
- // Get the left backbuffer, which was created along with the primary.
- DDSCAPS2 ddscaps = { 0, DDSCAPS2_STEREOSURFACELEFT, 0, 0 };
- if( FAILED( hr = m_pddsBackBuffer->GetAttachedSurface( &ddscaps,
- &m_pddsBackBufferLeft ) ) )
- {
- DEBUG_ERR( hr, _T("Error: Can't get the left backbuffer") );
- return D3DFWERR_NOBACKBUFFER;
- }
- m_pddsBackBufferLeft->AddRef();
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CreateWindowedBuffers()
-// Desc: Creates the primary and (optional) backbuffer for rendering.
-// Windowed mode and fullscreen mode are handled differently.
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::CreateWindowedBuffers()
-{
- HRESULT hr;
-
- // Get the dimensions of the viewport and screen bounds
- GetClientRect( m_hWnd, &m_rcScreenRect );
- ClientToScreen( m_hWnd, (POINT*)&m_rcScreenRect.left );
- ClientToScreen( m_hWnd, (POINT*)&m_rcScreenRect.right );
- m_dwRenderWidth = m_rcScreenRect.right - m_rcScreenRect.left;
- m_dwRenderHeight = m_rcScreenRect.bottom - m_rcScreenRect.top;
-
- // Create the primary surface
- DDSURFACEDESC2 ddsd;
- ZeroMemory( &ddsd, sizeof(ddsd) );
- ddsd.dwSize = sizeof(ddsd);
- ddsd.dwFlags = DDSD_CAPS;
- ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
-
- if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) )
- {
- DEBUG_MSG( _T("Error: Can't create primary surface") );
- if( hr != DDERR_OUTOFVIDEOMEMORY )
- return D3DFWERR_NOPRIMARY;
- DEBUG_MSG( _T("Error: Out of video memory") );
- return DDERR_OUTOFVIDEOMEMORY;
- }
-
- // If in windowed-mode, create a clipper object
- LPDIRECTDRAWCLIPPER pcClipper;
- if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) )
- {
- DEBUG_MSG( _T("Error: Couldn't create clipper") );
- return D3DFWERR_NOCLIPPER;
- }
-
- // Associate the clipper with the window
- pcClipper->SetHWnd( 0, m_hWnd );
- m_pddsFrontBuffer->SetClipper( pcClipper );
- SAFE_RELEASE( pcClipper );
-
- // Create a backbuffer
- ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
- ddsd.dwWidth = m_dwRenderWidth;
- ddsd.dwHeight = m_dwRenderHeight;
- ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
-
- if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) )
- {
- DEBUG_ERR( hr, _T("Error: Couldn't create the backbuffer") );
- if( hr != DDERR_OUTOFVIDEOMEMORY )
- return D3DFWERR_NOBACKBUFFER;
- DEBUG_MSG( _T("Error: Out of video memory") );
- return DDERR_OUTOFVIDEOMEMORY;
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CreateDirect3D()
-// Desc: Create the Direct3D interface
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::CreateDirect3D( GUID* pDeviceGUID )
-{
- // Query DirectDraw for access to Direct3D
- if( FAILED( m_pDD->QueryInterface( IID_IDirect3D7, (VOID**)&m_pD3D ) ) )
- {
- DEBUG_MSG( _T("Couldn't get the Direct3D interface") );
- return D3DFWERR_NODIRECT3D;
- }
-
- // Create the device
- if( FAILED( m_pD3D->CreateDevice( *pDeviceGUID, m_pddsBackBuffer,
- &m_pd3dDevice) ) )
- {
- DEBUG_MSG( _T("Couldn't create the D3DDevice") );
- return D3DFWERR_NO3DDEVICE;
- }
-
- // Finally, set the viewport for the newly created device
- D3DVIEWPORT7 vp = { 0, 0, m_dwRenderWidth, m_dwRenderHeight, 0.0f, 1.0f };
-
- if( FAILED( m_pd3dDevice->SetViewport( &vp ) ) )
- {
- DEBUG_MSG( _T("Error: Couldn't set current viewport to device") );
- return D3DFWERR_NOVIEWPORT;
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CreateZBuffer()
-// Desc: Internal function called by Create() to make and attach a zbuffer
-// to the renderer
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::CreateZBuffer( GUID* pDeviceGUID )
-{
- HRESULT hr;
-
- // Check if the device supports z-bufferless hidden surface removal. If so,
- // we don't really need a z-buffer
- D3DDEVICEDESC7 ddDesc;
- m_pd3dDevice->GetCaps( &ddDesc );
- if( ddDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )
- return S_OK;
-
- // Get z-buffer dimensions from the render target
- DDSURFACEDESC2 ddsd;
- ddsd.dwSize = sizeof(ddsd);
- m_pddsBackBuffer->GetSurfaceDesc( &ddsd );
-
- // Setup the surface desc for the z-buffer.
- ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
- ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | m_dwDeviceMemType;
- ddsd.ddpfPixelFormat.dwSize = 0; // Tag the pixel format as unitialized
-
- // Get an appropiate pixel format from enumeration of the formats. On the
- // first pass, we look for a zbuffer dpeth which is equal to the frame
- // buffer depth (as some cards unfornately require this).
- m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
- (VOID*)&ddsd.ddpfPixelFormat );
- if( 0 == ddsd.ddpfPixelFormat.dwSize )
- {
- // Try again, just accepting any 16-bit zbuffer
- ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
- m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
- (VOID*)&ddsd.ddpfPixelFormat );
-
- if( 0 == ddsd.ddpfPixelFormat.dwSize )
- {
- DEBUG_MSG( _T("Device doesn't support requested zbuffer format") );
- return D3DFWERR_NOZBUFFER;
- }
- }
-
- // Create and attach a z-buffer
- if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsZBuffer, NULL ) ) )
- {
- DEBUG_MSG( _T("Error: Couldn't create a ZBuffer surface") );
- if( hr != DDERR_OUTOFVIDEOMEMORY )
- return D3DFWERR_NOZBUFFER;
- DEBUG_MSG( _T("Error: Out of video memory") );
- return DDERR_OUTOFVIDEOMEMORY;
- }
-
- if( FAILED( m_pddsBackBuffer->AddAttachedSurface( m_pddsZBuffer ) ) )
- {
- DEBUG_MSG( _T("Error: Couldn't attach zbuffer to render surface") );
- return D3DFWERR_NOZBUFFER;
- }
-
- // For stereoscopic viewing, attach zbuffer to left surface as well
- if( m_bIsStereo )
- {
- if( FAILED( m_pddsBackBufferLeft->AddAttachedSurface( m_pddsZBuffer ) ) )
- {
- DEBUG_MSG( _T("Error: Couldn't attach zbuffer to left render surface") );
- return D3DFWERR_NOZBUFFER;
- }
- }
-
- // Finally, this call rebuilds internal structures
- if( FAILED( m_pd3dDevice->SetRenderTarget( m_pddsBackBuffer, 0L ) ) )
- {
- DEBUG_MSG( _T("Error: SetRenderTarget() failed after attaching zbuffer!") );
- return D3DFWERR_NOZBUFFER;
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: RestoreSurfaces()
-// Desc: Checks for lost surfaces and restores them if lost. Note: Don't
-// restore render surface, since it's just a duplicate ptr.
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::RestoreSurfaces()
-{
- // Restore all surfaces (including video memory vertex buffers)
- m_pDD->RestoreAllSurfaces();
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: Move()
-// Desc: Moves the screen rect for windowed renderers
-//-----------------------------------------------------------------------------
-VOID CD3DFramework7::Move( INT x, INT y )
-{
- if( true == m_bIsFullscreen )
- return;
-
- SetRect( &m_rcScreenRect, x, y, x + m_dwRenderWidth, y + m_dwRenderHeight );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: FlipToGDISurface()
-// Desc: Puts the GDI surface in front of the primary, so that dialog
-// boxes and other windows drawing funcs may happen.
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::FlipToGDISurface( bool bDrawFrame )
-{
- if( m_pDD && m_bIsFullscreen )
- {
- m_pDD->FlipToGDISurface();
-
- if( bDrawFrame )
- {
- DrawMenuBar( m_hWnd );
- RedrawWindow( m_hWnd, NULL, NULL, RDW_FRAME );
- }
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: ShowFrame()
-// Desc: Show the frame on the primary surface, via a blt or a flip.
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::ShowFrame()
-{
- if( NULL == m_pddsFrontBuffer )
- return D3DFWERR_NOTINITIALIZED;
-
- if( m_bIsFullscreen )
- {
- // We are in fullscreen mode, so perform a flip.
- if( m_bIsStereo )
- return m_pddsFrontBuffer->Flip( NULL, DDFLIP_WAIT | DDFLIP_STEREO );
- else
- return m_pddsFrontBuffer->Flip( NULL, DDFLIP_WAIT );
- }
- else
- {
- // We are in windowed mode, so perform a blit.
- return m_pddsFrontBuffer->Blt( &m_rcScreenRect, m_pddsBackBuffer,
- NULL, DDBLT_WAIT, NULL );
- }
-}
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+//-----------------------------------------------------------------------------
+// File: D3DFrame.cpp
+//
+// Desc: Class functions to implement a Direct3D app framework.
+//
+// Copyright (c) 1995-1999 by Microsoft, all rights reserved
+//-----------------------------------------------------------------------------
+#include <windows.h>
+#include <stdio.h>
+#include <tchar.h>
+#include "old/d3dframe.h"
+#include "old/d3dutil.h"
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CD3DFramework7()
+// Desc: The constructor. Clears static variables
+//-----------------------------------------------------------------------------
+CD3DFramework7::CD3DFramework7()
+{
+ m_hWnd = NULL;
+ m_bIsFullscreen = false;
+ m_bIsStereo = false;
+ m_dwRenderWidth = 0L;
+ m_dwRenderHeight = 0L;
+
+ m_pddsFrontBuffer = NULL;
+ m_pddsBackBuffer = NULL;
+ m_pddsBackBufferLeft = NULL;
+
+ m_pddsZBuffer = NULL;
+ m_pd3dDevice = NULL;
+ m_pDD = NULL;
+ m_pD3D = NULL;
+ m_dwDeviceMemType = NULL;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: ~CD3DFramework7()
+// Desc: The destructor. Deletes all objects
+//-----------------------------------------------------------------------------
+CD3DFramework7::~CD3DFramework7()
+{
+ DestroyObjects();
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: DestroyObjects()
+// Desc: Cleans everything up upon deletion. This code returns an error
+// if any of the objects have remaining reference counts.
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::DestroyObjects()
+{
+ LONG nDD = 0L; // Number of outstanding DDraw references
+ LONG nD3D = 0L; // Number of outstanding D3DDevice references
+
+ if( m_pDD )
+ {
+ HRESULT err = m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL );
+ char s[100];
+ sprintf(s, "SetCooperativeLevel error=%d\n", err);
+ OutputDebugString(s);
+ }
+
+ // Do a safe check for releasing the D3DDEVICE. RefCount must be zero.
+ if( m_pd3dDevice )
+ if( 0 < ( nD3D = m_pd3dDevice->Release() ) )
+ DEBUG_MSG( _T("Error: D3DDevice object is still referenced!") );
+ m_pd3dDevice = NULL;
+
+ SAFE_RELEASE( m_pddsBackBuffer );
+ SAFE_RELEASE( m_pddsBackBufferLeft );
+ SAFE_RELEASE( m_pddsZBuffer );
+ SAFE_RELEASE( m_pddsFrontBuffer );
+ SAFE_RELEASE( m_pD3D );
+
+ if( m_pDD )
+ {
+ // Do a safe check for releasing DDRAW. RefCount must be zero.
+ if( 0 < ( nDD = m_pDD->Release() ) )
+ DEBUG_MSG( _T("Error: DDraw object is still referenced!") );
+ }
+ m_pDD = NULL;
+
+ // Return successful, unless there are outstanding DD or D3DDevice refs.
+ return ( nDD==0 && nD3D==0 ) ? S_OK : D3DFWERR_NONZEROREFCOUNT;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: Initialize()
+// Desc: Creates the internal objects for the framework
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::Initialize( HWND hWnd, GUID* pDriverGUID,
+ GUID* pDeviceGUID, DDSURFACEDESC2* pMode,
+ DWORD dwFlags )
+{
+ HRESULT hr;
+
+ // Check params. Note: A NULL mode is valid for windowed modes only.
+ if( ( NULL==hWnd ) || ( NULL==pDeviceGUID ) ||
+ ( NULL==pMode && (dwFlags&D3DFW_FULLSCREEN) ) )
+ return E_INVALIDARG;
+
+ // Setup state for windowed/fullscreen mode
+ m_hWnd = hWnd;
+ m_bIsStereo = false;
+ m_bIsFullscreen = ( dwFlags & D3DFW_FULLSCREEN ) ? true : false;
+
+ // Support stereoscopic viewing for fullscreen modes which support it
+ if( ( dwFlags & D3DFW_STEREO ) && ( dwFlags & D3DFW_FULLSCREEN ) )
+ if( pMode->ddsCaps.dwCaps2 & DDSCAPS2_STEREOSURFACELEFT )
+ m_bIsStereo = true;
+
+ // Create the D3D rendering environment (surfaces, device, viewport, etc.)
+ if( FAILED( hr = CreateEnvironment( pDriverGUID, pDeviceGUID, pMode,
+ dwFlags ) ) )
+ {
+ DestroyObjects();
+ return hr;
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CreateEnvironment()
+// Desc: Creates the internal objects for the framework
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::CreateEnvironment( GUID* pDriverGUID, GUID* pDeviceGUID,
+ DDSURFACEDESC2* pMode, DWORD dwFlags )
+{
+ HRESULT hr;
+
+ // Select the default memory type, for whether the device is HW or SW
+ if( IsEqualIID( *pDeviceGUID, IID_IDirect3DHALDevice) )
+ m_dwDeviceMemType = DDSCAPS_VIDEOMEMORY;
+ else if( IsEqualIID( *pDeviceGUID, IID_IDirect3DTnLHalDevice) )
+ m_dwDeviceMemType = DDSCAPS_VIDEOMEMORY;
+ else
+ m_dwDeviceMemType = DDSCAPS_SYSTEMMEMORY;
+
+ // Create the DDraw object
+ hr = CreateDirectDraw( pDriverGUID, dwFlags );
+ if( FAILED( hr ) )
+ return hr;
+
+ // Create the front and back buffers, and attach a clipper
+ if( dwFlags & D3DFW_FULLSCREEN )
+ hr = CreateFullscreenBuffers( pMode );
+ else
+ hr = CreateWindowedBuffers();
+ if( FAILED( hr ) )
+ return hr;
+
+ // Create the Direct3D object and the Direct3DDevice object
+ hr = CreateDirect3D( pDeviceGUID );
+ if( FAILED( hr ) )
+ return hr;
+
+ // Create and attach the zbuffer
+ if( dwFlags & D3DFW_ZBUFFER )
+ hr = CreateZBuffer( pDeviceGUID );
+ if( FAILED( hr ) )
+ return hr;
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: EnumZBufferFormatsCallback()
+// Desc: Simply returns the first matching enumerated z-buffer format
+//-----------------------------------------------------------------------------
+static HRESULT WINAPI EnumZBufferFormatsCallback( DDPIXELFORMAT* pddpf,
+ VOID* pContext )
+{
+ DDPIXELFORMAT* pddpfOut = (DDPIXELFORMAT*)pContext;
+
+ if( pddpfOut->dwRGBBitCount == pddpf->dwRGBBitCount )
+ {
+ (*pddpfOut) = (*pddpf);
+ return D3DENUMRET_CANCEL;
+ }
+
+ return D3DENUMRET_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CreateDirectDraw()
+// Desc: Create the DirectDraw interface
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::CreateDirectDraw( GUID* pDriverGUID, DWORD dwFlags )
+{
+ // Create the DirectDraw interface, and query for the DD7 interface
+ if( FAILED( DirectDrawCreateEx( pDriverGUID, (VOID**)&m_pDD,
+ IID_IDirectDraw7, NULL ) ) )
+ {
+ DEBUG_MSG( _T("Could not create DirectDraw") );
+ return D3DFWERR_NODIRECTDRAW;
+ }
+
+ // Set the Windows cooperative level
+ DWORD dwCoopFlags = DDSCL_NORMAL;
+ if( m_bIsFullscreen )
+ dwCoopFlags = DDSCL_ALLOWREBOOT|DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN;
+
+ // By defualt, set the flag to allow D3D to optimize floating point calcs
+ if( 0L == ( dwFlags & D3DFW_NO_FPUSETUP ) )
+ dwCoopFlags |= DDSCL_FPUSETUP;
+
+ if( FAILED( m_pDD->SetCooperativeLevel( m_hWnd, dwCoopFlags ) ) )
+ {
+ DEBUG_MSG( _T("Couldn't set coop level") );
+ return D3DFWERR_COULDNTSETCOOPLEVEL;
+ }
+
+ // Check that we are NOT in a palettized display. That case will fail,
+ // since the framework doesn't use palettes.
+ DDSURFACEDESC2 ddsd;
+ ddsd.dwSize = sizeof(ddsd);
+ m_pDD->GetDisplayMode( &ddsd );
+ if( ddsd.ddpfPixelFormat.dwRGBBitCount <= 8 )
+ return D3DFWERR_INVALIDMODE;
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CreateFullscreenBuffers()
+// Desc: Creates the primary and (optional) backbuffer for rendering.
+// Windowed mode and fullscreen mode are handled differently.
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::CreateFullscreenBuffers( DDSURFACEDESC2* pddsd )
+{
+ HRESULT hr;
+
+ // Get the dimensions of the screen bounds
+ // Store the rectangle which contains the renderer
+ SetRect( &m_rcScreenRect, 0, 0, pddsd->dwWidth, pddsd->dwHeight );
+ m_dwRenderWidth = m_rcScreenRect.right - m_rcScreenRect.left;
+ m_dwRenderHeight = m_rcScreenRect.bottom - m_rcScreenRect.top;
+
+ // Set the display mode to the requested dimensions. Check for
+ // 320x200x8 modes, and set flag to avoid using ModeX
+ DWORD dwModeFlags = 0;
+
+ if( (320==m_dwRenderWidth) && (200==m_dwRenderHeight) &&
+ (8==pddsd->ddpfPixelFormat.dwRGBBitCount) )
+ dwModeFlags |= DDSDM_STANDARDVGAMODE;
+
+ if( FAILED( m_pDD->SetDisplayMode( m_dwRenderWidth, m_dwRenderHeight,
+ pddsd->ddpfPixelFormat.dwRGBBitCount,
+ pddsd->dwRefreshRate, dwModeFlags ) ) )
+ {
+ DEBUG_MSG( _T("Can't set display mode") );
+ return D3DFWERR_BADDISPLAYMODE;
+ }
+
+ // Setup to create the primary surface w/backbuffer
+ DDSURFACEDESC2 ddsd;
+ ZeroMemory( &ddsd, sizeof(ddsd) );
+ ddsd.dwSize = sizeof(ddsd);
+ ddsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE |
+ DDSCAPS_FLIP | DDSCAPS_COMPLEX;
+ ddsd.dwBackBufferCount = 1;
+
+ // Support for stereoscopic viewing
+ if( m_bIsStereo )
+ {
+ ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
+ ddsd.ddsCaps.dwCaps2 |= DDSCAPS2_STEREOSURFACELEFT;
+ }
+
+ // Create the primary surface
+ if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) )
+ {
+ DEBUG_MSG( _T("Error: Can't create primary surface") );
+ if( hr != DDERR_OUTOFVIDEOMEMORY )
+ return D3DFWERR_NOPRIMARY;
+ DEBUG_MSG( _T("Error: Out of video memory") );
+ return DDERR_OUTOFVIDEOMEMORY;
+ }
+
+ // Get the backbuffer, which was created along with the primary.
+ DDSCAPS2 ddscaps = { DDSCAPS_BACKBUFFER, 0, 0, 0 };
+ if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps,
+ &m_pddsBackBuffer ) ) )
+ {
+ DEBUG_ERR( hr, _T("Error: Can't get the backbuffer") );
+ return D3DFWERR_NOBACKBUFFER;
+ }
+
+ // Increment the backbuffer count (for consistency with windowed mode)
+ m_pddsBackBuffer->AddRef();
+
+ // Support for stereoscopic viewing
+ if( m_bIsStereo )
+ {
+ // Get the left backbuffer, which was created along with the primary.
+ DDSCAPS2 ddscaps = { 0, DDSCAPS2_STEREOSURFACELEFT, 0, 0 };
+ if( FAILED( hr = m_pddsBackBuffer->GetAttachedSurface( &ddscaps,
+ &m_pddsBackBufferLeft ) ) )
+ {
+ DEBUG_ERR( hr, _T("Error: Can't get the left backbuffer") );
+ return D3DFWERR_NOBACKBUFFER;
+ }
+ m_pddsBackBufferLeft->AddRef();
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CreateWindowedBuffers()
+// Desc: Creates the primary and (optional) backbuffer for rendering.
+// Windowed mode and fullscreen mode are handled differently.
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::CreateWindowedBuffers()
+{
+ HRESULT hr;
+
+ // Get the dimensions of the viewport and screen bounds
+ GetClientRect( m_hWnd, &m_rcScreenRect );
+ ClientToScreen( m_hWnd, (POINT*)&m_rcScreenRect.left );
+ ClientToScreen( m_hWnd, (POINT*)&m_rcScreenRect.right );
+ m_dwRenderWidth = m_rcScreenRect.right - m_rcScreenRect.left;
+ m_dwRenderHeight = m_rcScreenRect.bottom - m_rcScreenRect.top;
+
+ // Create the primary surface
+ DDSURFACEDESC2 ddsd;
+ ZeroMemory( &ddsd, sizeof(ddsd) );
+ ddsd.dwSize = sizeof(ddsd);
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) )
+ {
+ DEBUG_MSG( _T("Error: Can't create primary surface") );
+ if( hr != DDERR_OUTOFVIDEOMEMORY )
+ return D3DFWERR_NOPRIMARY;
+ DEBUG_MSG( _T("Error: Out of video memory") );
+ return DDERR_OUTOFVIDEOMEMORY;
+ }
+
+ // If in windowed-mode, create a clipper object
+ LPDIRECTDRAWCLIPPER pcClipper;
+ if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) )
+ {
+ DEBUG_MSG( _T("Error: Couldn't create clipper") );
+ return D3DFWERR_NOCLIPPER;
+ }
+
+ // Associate the clipper with the window
+ pcClipper->SetHWnd( 0, m_hWnd );
+ m_pddsFrontBuffer->SetClipper( pcClipper );
+ SAFE_RELEASE( pcClipper );
+
+ // Create a backbuffer
+ ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
+ ddsd.dwWidth = m_dwRenderWidth;
+ ddsd.dwHeight = m_dwRenderHeight;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
+
+ if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) )
+ {
+ DEBUG_ERR( hr, _T("Error: Couldn't create the backbuffer") );
+ if( hr != DDERR_OUTOFVIDEOMEMORY )
+ return D3DFWERR_NOBACKBUFFER;
+ DEBUG_MSG( _T("Error: Out of video memory") );
+ return DDERR_OUTOFVIDEOMEMORY;
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CreateDirect3D()
+// Desc: Create the Direct3D interface
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::CreateDirect3D( GUID* pDeviceGUID )
+{
+ // Query DirectDraw for access to Direct3D
+ if( FAILED( m_pDD->QueryInterface( IID_IDirect3D7, (VOID**)&m_pD3D ) ) )
+ {
+ DEBUG_MSG( _T("Couldn't get the Direct3D interface") );
+ return D3DFWERR_NODIRECT3D;
+ }
+
+ // Create the device
+ if( FAILED( m_pD3D->CreateDevice( *pDeviceGUID, m_pddsBackBuffer,
+ &m_pd3dDevice) ) )
+ {
+ DEBUG_MSG( _T("Couldn't create the D3DDevice") );
+ return D3DFWERR_NO3DDEVICE;
+ }
+
+ // Finally, set the viewport for the newly created device
+ D3DVIEWPORT7 vp = { 0, 0, m_dwRenderWidth, m_dwRenderHeight, 0.0f, 1.0f };
+
+ if( FAILED( m_pd3dDevice->SetViewport( &vp ) ) )
+ {
+ DEBUG_MSG( _T("Error: Couldn't set current viewport to device") );
+ return D3DFWERR_NOVIEWPORT;
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CreateZBuffer()
+// Desc: Internal function called by Create() to make and attach a zbuffer
+// to the renderer
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::CreateZBuffer( GUID* pDeviceGUID )
+{
+ HRESULT hr;
+
+ // Check if the device supports z-bufferless hidden surface removal. If so,
+ // we don't really need a z-buffer
+ D3DDEVICEDESC7 ddDesc;
+ m_pd3dDevice->GetCaps( &ddDesc );
+ if( ddDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )
+ return S_OK;
+
+ // Get z-buffer dimensions from the render target
+ DDSURFACEDESC2 ddsd;
+ ddsd.dwSize = sizeof(ddsd);
+ m_pddsBackBuffer->GetSurfaceDesc( &ddsd );
+
+ // Setup the surface desc for the z-buffer.
+ ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | m_dwDeviceMemType;
+ ddsd.ddpfPixelFormat.dwSize = 0; // Tag the pixel format as unitialized
+
+ // Get an appropiate pixel format from enumeration of the formats. On the
+ // first pass, we look for a zbuffer dpeth which is equal to the frame
+ // buffer depth (as some cards unfornately require this).
+ m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
+ (VOID*)&ddsd.ddpfPixelFormat );
+ if( 0 == ddsd.ddpfPixelFormat.dwSize )
+ {
+ // Try again, just accepting any 16-bit zbuffer
+ ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
+ m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
+ (VOID*)&ddsd.ddpfPixelFormat );
+
+ if( 0 == ddsd.ddpfPixelFormat.dwSize )
+ {
+ DEBUG_MSG( _T("Device doesn't support requested zbuffer format") );
+ return D3DFWERR_NOZBUFFER;
+ }
+ }
+
+ // Create and attach a z-buffer
+ if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsZBuffer, NULL ) ) )
+ {
+ DEBUG_MSG( _T("Error: Couldn't create a ZBuffer surface") );
+ if( hr != DDERR_OUTOFVIDEOMEMORY )
+ return D3DFWERR_NOZBUFFER;
+ DEBUG_MSG( _T("Error: Out of video memory") );
+ return DDERR_OUTOFVIDEOMEMORY;
+ }
+
+ if( FAILED( m_pddsBackBuffer->AddAttachedSurface( m_pddsZBuffer ) ) )
+ {
+ DEBUG_MSG( _T("Error: Couldn't attach zbuffer to render surface") );
+ return D3DFWERR_NOZBUFFER;
+ }
+
+ // For stereoscopic viewing, attach zbuffer to left surface as well
+ if( m_bIsStereo )
+ {
+ if( FAILED( m_pddsBackBufferLeft->AddAttachedSurface( m_pddsZBuffer ) ) )
+ {
+ DEBUG_MSG( _T("Error: Couldn't attach zbuffer to left render surface") );
+ return D3DFWERR_NOZBUFFER;
+ }
+ }
+
+ // Finally, this call rebuilds internal structures
+ if( FAILED( m_pd3dDevice->SetRenderTarget( m_pddsBackBuffer, 0L ) ) )
+ {
+ DEBUG_MSG( _T("Error: SetRenderTarget() failed after attaching zbuffer!") );
+ return D3DFWERR_NOZBUFFER;
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: RestoreSurfaces()
+// Desc: Checks for lost surfaces and restores them if lost. Note: Don't
+// restore render surface, since it's just a duplicate ptr.
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::RestoreSurfaces()
+{
+ // Restore all surfaces (including video memory vertex buffers)
+ m_pDD->RestoreAllSurfaces();
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: Move()
+// Desc: Moves the screen rect for windowed renderers
+//-----------------------------------------------------------------------------
+VOID CD3DFramework7::Move( INT x, INT y )
+{
+ if( true == m_bIsFullscreen )
+ return;
+
+ SetRect( &m_rcScreenRect, x, y, x + m_dwRenderWidth, y + m_dwRenderHeight );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: FlipToGDISurface()
+// Desc: Puts the GDI surface in front of the primary, so that dialog
+// boxes and other windows drawing funcs may happen.
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::FlipToGDISurface( bool bDrawFrame )
+{
+ if( m_pDD && m_bIsFullscreen )
+ {
+ m_pDD->FlipToGDISurface();
+
+ if( bDrawFrame )
+ {
+ DrawMenuBar( m_hWnd );
+ RedrawWindow( m_hWnd, NULL, NULL, RDW_FRAME );
+ }
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: ShowFrame()
+// Desc: Show the frame on the primary surface, via a blt or a flip.
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::ShowFrame()
+{
+ if( NULL == m_pddsFrontBuffer )
+ return D3DFWERR_NOTINITIALIZED;
+
+ if( m_bIsFullscreen )
+ {
+ // We are in fullscreen mode, so perform a flip.
+ if( m_bIsStereo )
+ return m_pddsFrontBuffer->Flip( NULL, DDFLIP_WAIT | DDFLIP_STEREO );
+ else
+ return m_pddsFrontBuffer->Flip( NULL, DDFLIP_WAIT );
+ }
+ else
+ {
+ // We are in windowed mode, so perform a blit.
+ return m_pddsFrontBuffer->Blt( &m_rcScreenRect, m_pddsBackBuffer,
+ NULL, DDBLT_WAIT, NULL );
+ }
+}
+
+
+
diff --git a/src/old/d3dframe.h b/src/old/d3dframe.h
index 1c02e04..10eee57 100644
--- a/src/old/d3dframe.h
+++ b/src/old/d3dframe.h
@@ -1,141 +1,141 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-//-----------------------------------------------------------------------------
-// File: D3DFrame.h
-//
-// Desc: Class to manage the Direct3D environment objects such as buffers,
-// viewports, and 3D devices.
-//
-// The class is initialized with the Initialize() function, after which
-// the Get????() functions can be used to access the objects needed for
-// rendering. If the device or display needs to be changed, the
-// ChangeDevice() function can be called. If the display window is moved
-// the changes need to be reported with the Move() function.
-//
-// After rendering a frame, the ShowFrame() function filps or blits the
-// backbuffer contents to the primary. If surfaces are lost, they can be
-// restored with the RestoreSurfaces() function. Finally, if normal
-// Windows output is needed, the FlipToGDISurface() provides a GDI
-// surface to draw on.
-//
-// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-
-#pragma once
-
-#include <ddraw.h>
-#include <d3d.h>
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CD3DFramework7
-// Desc: The Direct3D sample framework class for DX7. Maintains the D3D
-// surfaces and device used for 3D rendering.
-//-----------------------------------------------------------------------------
-class CD3DFramework7
-{
- // Internal variables for the framework class
- HWND m_hWnd; // The window object
- bool m_bIsFullscreen; // Fullscreen vs. windowed
- bool m_bIsStereo; // Stereo view mode
- DWORD m_dwRenderWidth; // Dimensions of the render target
- DWORD m_dwRenderHeight;
- RECT m_rcScreenRect; // Screen rect for window
- LPDIRECTDRAW7 m_pDD; // The DirectDraw object
- LPDIRECT3D7 m_pD3D; // The Direct3D object
- LPDIRECT3DDEVICE7 m_pd3dDevice; // The D3D device
- LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; // The primary surface
- LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; // The backbuffer surface
- LPDIRECTDRAWSURFACE7 m_pddsBackBufferLeft; // For stereo modes
- LPDIRECTDRAWSURFACE7 m_pddsZBuffer; // The zbuffer surface
- DWORD m_dwDeviceMemType;
-
- // Internal functions for the framework class
- HRESULT CreateZBuffer( GUID* );
- HRESULT CreateFullscreenBuffers( DDSURFACEDESC2* );
- HRESULT CreateWindowedBuffers();
- HRESULT CreateDirectDraw( GUID*, DWORD );
- HRESULT CreateDirect3D( GUID* );
- HRESULT CreateEnvironment( GUID*, GUID*, DDSURFACEDESC2*, DWORD );
-
-public:
- // Access functions for DirectX objects
- LPDIRECTDRAW7 GetDirectDraw() { return m_pDD; }
- LPDIRECT3D7 GetDirect3D() { return m_pD3D; }
- LPDIRECT3DDEVICE7 GetD3DDevice() { return m_pd3dDevice; }
- LPDIRECTDRAWSURFACE7 GetFrontBuffer() { return m_pddsFrontBuffer; }
- LPDIRECTDRAWSURFACE7 GetBackBuffer() { return m_pddsBackBuffer; }
- LPDIRECTDRAWSURFACE7 GetRenderSurface() { return m_pddsBackBuffer; }
- LPDIRECTDRAWSURFACE7 GetRenderSurfaceLeft() { return m_pddsBackBufferLeft; }
-
- // Functions to aid rendering
- HRESULT RestoreSurfaces();
- HRESULT ShowFrame();
- HRESULT FlipToGDISurface( bool bDrawFrame = false );
-
- // Functions for managing screen and viewport bounds
- bool IsFullscreen() { return m_bIsFullscreen; }
- bool IsStereo() { return m_bIsStereo; }
- VOID Move( INT x, INT y );
-
- // Creates the Framework
- HRESULT Initialize( HWND hWnd, GUID* pDriverGUID, GUID* pDeviceGUID,
- DDSURFACEDESC2* pddsd, DWORD dwFlags );
- HRESULT DestroyObjects();
-
- CD3DFramework7();
- ~CD3DFramework7();
-};
-
-
-
-
-//-----------------------------------------------------------------------------
-// Flags used for the Initialize() method of a CD3DFramework object
-//-----------------------------------------------------------------------------
-#define D3DFW_FULLSCREEN 0x00000001 // Use fullscreen mode
-#define D3DFW_STEREO 0x00000002 // Use stereo-scopic viewing
-#define D3DFW_ZBUFFER 0x00000004 // Create and use a zbuffer
-#define D3DFW_NO_FPUSETUP 0x00000008 // Don't use default DDSCL_FPUSETUP flag
-
-
-
-
-//-----------------------------------------------------------------------------
-// Errors that the Initialize() and ChangeDriver() calls may return
-//-----------------------------------------------------------------------------
-#define D3DFWERR_INITIALIZATIONFAILED 0x82000000
-#define D3DFWERR_NODIRECTDRAW 0x82000001
-#define D3DFWERR_COULDNTSETCOOPLEVEL 0x82000002
-#define D3DFWERR_NODIRECT3D 0x82000003
-#define D3DFWERR_NO3DDEVICE 0x82000004
-#define D3DFWERR_NOZBUFFER 0x82000005
-#define D3DFWERR_INVALIDZBUFFERDEPTH 0x82000006
-#define D3DFWERR_NOVIEWPORT 0x82000007
-#define D3DFWERR_NOPRIMARY 0x82000008
-#define D3DFWERR_NOCLIPPER 0x82000009
-#define D3DFWERR_BADDISPLAYMODE 0x8200000a
-#define D3DFWERR_NOBACKBUFFER 0x8200000b
-#define D3DFWERR_NONZEROREFCOUNT 0x8200000c
-#define D3DFWERR_NORENDERTARGET 0x8200000d
-#define D3DFWERR_INVALIDMODE 0x8200000e
-#define D3DFWERR_NOTINITIALIZED 0x8200000f
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+//-----------------------------------------------------------------------------
+// File: D3DFrame.h
+//
+// Desc: Class to manage the Direct3D environment objects such as buffers,
+// viewports, and 3D devices.
+//
+// The class is initialized with the Initialize() function, after which
+// the Get????() functions can be used to access the objects needed for
+// rendering. If the device or display needs to be changed, the
+// ChangeDevice() function can be called. If the display window is moved
+// the changes need to be reported with the Move() function.
+//
+// After rendering a frame, the ShowFrame() function filps or blits the
+// backbuffer contents to the primary. If surfaces are lost, they can be
+// restored with the RestoreSurfaces() function. Finally, if normal
+// Windows output is needed, the FlipToGDISurface() provides a GDI
+// surface to draw on.
+//
+// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+#include <ddraw.h>
+#include <d3d.h>
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CD3DFramework7
+// Desc: The Direct3D sample framework class for DX7. Maintains the D3D
+// surfaces and device used for 3D rendering.
+//-----------------------------------------------------------------------------
+class CD3DFramework7
+{
+ // Internal variables for the framework class
+ HWND m_hWnd; // The window object
+ bool m_bIsFullscreen; // Fullscreen vs. windowed
+ bool m_bIsStereo; // Stereo view mode
+ DWORD m_dwRenderWidth; // Dimensions of the render target
+ DWORD m_dwRenderHeight;
+ RECT m_rcScreenRect; // Screen rect for window
+ LPDIRECTDRAW7 m_pDD; // The DirectDraw object
+ LPDIRECT3D7 m_pD3D; // The Direct3D object
+ LPDIRECT3DDEVICE7 m_pd3dDevice; // The D3D device
+ LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; // The primary surface
+ LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; // The backbuffer surface
+ LPDIRECTDRAWSURFACE7 m_pddsBackBufferLeft; // For stereo modes
+ LPDIRECTDRAWSURFACE7 m_pddsZBuffer; // The zbuffer surface
+ DWORD m_dwDeviceMemType;
+
+ // Internal functions for the framework class
+ HRESULT CreateZBuffer( GUID* );
+ HRESULT CreateFullscreenBuffers( DDSURFACEDESC2* );
+ HRESULT CreateWindowedBuffers();
+ HRESULT CreateDirectDraw( GUID*, DWORD );
+ HRESULT CreateDirect3D( GUID* );
+ HRESULT CreateEnvironment( GUID*, GUID*, DDSURFACEDESC2*, DWORD );
+
+public:
+ // Access functions for DirectX objects
+ LPDIRECTDRAW7 GetDirectDraw() { return m_pDD; }
+ LPDIRECT3D7 GetDirect3D() { return m_pD3D; }
+ LPDIRECT3DDEVICE7 GetD3DDevice() { return m_pd3dDevice; }
+ LPDIRECTDRAWSURFACE7 GetFrontBuffer() { return m_pddsFrontBuffer; }
+ LPDIRECTDRAWSURFACE7 GetBackBuffer() { return m_pddsBackBuffer; }
+ LPDIRECTDRAWSURFACE7 GetRenderSurface() { return m_pddsBackBuffer; }
+ LPDIRECTDRAWSURFACE7 GetRenderSurfaceLeft() { return m_pddsBackBufferLeft; }
+
+ // Functions to aid rendering
+ HRESULT RestoreSurfaces();
+ HRESULT ShowFrame();
+ HRESULT FlipToGDISurface( bool bDrawFrame = false );
+
+ // Functions for managing screen and viewport bounds
+ bool IsFullscreen() { return m_bIsFullscreen; }
+ bool IsStereo() { return m_bIsStereo; }
+ VOID Move( INT x, INT y );
+
+ // Creates the Framework
+ HRESULT Initialize( HWND hWnd, GUID* pDriverGUID, GUID* pDeviceGUID,
+ DDSURFACEDESC2* pddsd, DWORD dwFlags );
+ HRESULT DestroyObjects();
+
+ CD3DFramework7();
+ ~CD3DFramework7();
+};
+
+
+
+
+//-----------------------------------------------------------------------------
+// Flags used for the Initialize() method of a CD3DFramework object
+//-----------------------------------------------------------------------------
+#define D3DFW_FULLSCREEN 0x00000001 // Use fullscreen mode
+#define D3DFW_STEREO 0x00000002 // Use stereo-scopic viewing
+#define D3DFW_ZBUFFER 0x00000004 // Create and use a zbuffer
+#define D3DFW_NO_FPUSETUP 0x00000008 // Don't use default DDSCL_FPUSETUP flag
+
+
+
+
+//-----------------------------------------------------------------------------
+// Errors that the Initialize() and ChangeDriver() calls may return
+//-----------------------------------------------------------------------------
+#define D3DFWERR_INITIALIZATIONFAILED 0x82000000
+#define D3DFWERR_NODIRECTDRAW 0x82000001
+#define D3DFWERR_COULDNTSETCOOPLEVEL 0x82000002
+#define D3DFWERR_NODIRECT3D 0x82000003
+#define D3DFWERR_NO3DDEVICE 0x82000004
+#define D3DFWERR_NOZBUFFER 0x82000005
+#define D3DFWERR_INVALIDZBUFFERDEPTH 0x82000006
+#define D3DFWERR_NOVIEWPORT 0x82000007
+#define D3DFWERR_NOPRIMARY 0x82000008
+#define D3DFWERR_NOCLIPPER 0x82000009
+#define D3DFWERR_BADDISPLAYMODE 0x8200000a
+#define D3DFWERR_NOBACKBUFFER 0x8200000b
+#define D3DFWERR_NONZEROREFCOUNT 0x8200000c
+#define D3DFWERR_NORENDERTARGET 0x8200000d
+#define D3DFWERR_INVALIDMODE 0x8200000e
+#define D3DFWERR_NOTINITIALIZED 0x8200000f
+
+
+
diff --git a/src/old/d3dmath.cpp b/src/old/d3dmath.cpp
index 2686215..15308fe 100644
--- a/src/old/d3dmath.cpp
+++ b/src/old/d3dmath.cpp
@@ -1,343 +1,343 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-//-----------------------------------------------------------------------------
-// File: D3DMath.cpp
-//
-// Desc: Shortcut macros and functions for using DX objects
-//
-// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-#define D3D_OVERLOADS
-#define STRICT
-#include <math.h>
-#include <stdio.h>
-#include "d3dmath.h"
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_MatrixMultiply()
-// Desc: Does the matrix operation: [Q] = [A] * [B]. Note that the order of
-// this operation was changed from the previous version of the DXSDK.
-//-----------------------------------------------------------------------------
-VOID D3DMath_MatrixMultiply( D3DMATRIX& q, D3DMATRIX& a, D3DMATRIX& b )
-{
- FLOAT* pA = (FLOAT*)&a;
- FLOAT* pB = (FLOAT*)&b;
- FLOAT pM[16];
-
- ZeroMemory( pM, sizeof(D3DMATRIX) );
-
- for( WORD i=0; i<4; i++ )
- for( WORD j=0; j<4; j++ )
- for( WORD k=0; k<4; k++ )
- pM[4*i+j] += pA[4*i+k] * pB[4*k+j];
-
- memcpy( &q, pM, sizeof(D3DMATRIX) );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_MatrixInvert()
-// Desc: Does the matrix operation: [Q] = inv[A]. Note: this function only
-// works for matrices with [0 0 0 1] for the 4th column.
-//-----------------------------------------------------------------------------
-HRESULT D3DMath_MatrixInvert( D3DMATRIX& q, D3DMATRIX& a )
-{
- if( fabs(a._44 - 1.0f) > .001f)
- return E_INVALIDARG;
- if( fabs(a._14) > .001f || fabs(a._24) > .001f || fabs(a._34) > .001f )
- return E_INVALIDARG;
-
- FLOAT fDetInv = 1.0f / ( a._11 * ( a._22 * a._33 - a._23 * a._32 ) -
- a._12 * ( a._21 * a._33 - a._23 * a._31 ) +
- a._13 * ( a._21 * a._32 - a._22 * a._31 ) );
-
- q._11 = fDetInv * ( a._22 * a._33 - a._23 * a._32 );
- q._12 = -fDetInv * ( a._12 * a._33 - a._13 * a._32 );
- q._13 = fDetInv * ( a._12 * a._23 - a._13 * a._22 );
- q._14 = 0.0f;
-
- q._21 = -fDetInv * ( a._21 * a._33 - a._23 * a._31 );
- q._22 = fDetInv * ( a._11 * a._33 - a._13 * a._31 );
- q._23 = -fDetInv * ( a._11 * a._23 - a._13 * a._21 );
- q._24 = 0.0f;
-
- q._31 = fDetInv * ( a._21 * a._32 - a._22 * a._31 );
- q._32 = -fDetInv * ( a._11 * a._32 - a._12 * a._31 );
- q._33 = fDetInv * ( a._11 * a._22 - a._12 * a._21 );
- q._34 = 0.0f;
-
- q._41 = -( a._41 * q._11 + a._42 * q._21 + a._43 * q._31 );
- q._42 = -( a._41 * q._12 + a._42 * q._22 + a._43 * q._32 );
- q._43 = -( a._41 * q._13 + a._42 * q._23 + a._43 * q._33 );
- q._44 = 1.0f;
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_VectorMatrixMultiply()
-// Desc: Multiplies a vector by a matrix
-//-----------------------------------------------------------------------------
-HRESULT D3DMath_VectorMatrixMultiply( D3DVECTOR& vDest, D3DVECTOR& vSrc,
- D3DMATRIX& mat)
-{
- FLOAT x = vSrc.x*mat._11 + vSrc.y*mat._21 + vSrc.z* mat._31 + mat._41;
- FLOAT y = vSrc.x*mat._12 + vSrc.y*mat._22 + vSrc.z* mat._32 + mat._42;
- FLOAT z = vSrc.x*mat._13 + vSrc.y*mat._23 + vSrc.z* mat._33 + mat._43;
- FLOAT w = vSrc.x*mat._14 + vSrc.y*mat._24 + vSrc.z* mat._34 + mat._44;
-
- if( fabs( w ) < g_EPSILON )
- return E_INVALIDARG;
-
- vDest.x = x/w;
- vDest.y = y/w;
- vDest.z = z/w;
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_VertexMatrixMultiply()
-// Desc: Multiplies a vertex by a matrix
-//-----------------------------------------------------------------------------
-HRESULT D3DMath_VertexMatrixMultiply( D3DVERTEX& vDest, D3DVERTEX& vSrc,
- D3DMATRIX& mat )
-{
- HRESULT hr;
- D3DVECTOR* pSrcVec = (D3DVECTOR*)&vSrc.x;
- D3DVECTOR* pDestVec = (D3DVECTOR*)&vDest.x;
-
- if( SUCCEEDED( hr = D3DMath_VectorMatrixMultiply( *pDestVec, *pSrcVec,
- mat ) ) )
- {
- pSrcVec = (D3DVECTOR*)&vSrc.nx;
- pDestVec = (D3DVECTOR*)&vDest.nx;
- hr = D3DMath_VectorMatrixMultiply( *pDestVec, *pSrcVec, mat );
- }
- return hr;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_QuaternionFromRotation()
-// Desc: Converts a normalized axis and angle to a unit quaternion.
-//-----------------------------------------------------------------------------
-VOID D3DMath_QuaternionFromRotation( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
- D3DVECTOR& v, FLOAT fTheta )
-{
- x = sinf( fTheta/2.0f ) * v.x;
- y = sinf( fTheta/2.0f ) * v.y;
- z = sinf( fTheta/2.0f ) * v.z;
- w = cosf( fTheta/2.0f );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_RotationFromQuaternion()
-// Desc: Converts a normalized axis and angle to a unit quaternion.
-//-----------------------------------------------------------------------------
-VOID D3DMath_RotationFromQuaternion( D3DVECTOR& v, FLOAT& fTheta,
- FLOAT x, FLOAT y, FLOAT z, FLOAT w )
-
-{
- fTheta = acosf(w) * 2.0f;
- v.x = x / sinf( fTheta/2.0f );
- v.y = y / sinf( fTheta/2.0f );
- v.z = z / sinf( fTheta/2.0f );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_QuaternionFromAngles()
-// Desc: Converts euler angles to a unit quaternion.
-//-----------------------------------------------------------------------------
-VOID D3DMath_QuaternionFromAngles( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
- FLOAT fYaw, FLOAT fPitch, FLOAT fRoll )
-
-{
- FLOAT fSinYaw = sinf( fYaw/2.0f );
- FLOAT fSinPitch = sinf( fPitch/2.0f );
- FLOAT fSinRoll = sinf( fRoll/2.0f );
- FLOAT fCosYaw = cosf( fYaw/2.0f );
- FLOAT fCosPitch = cosf( fPitch/2.0f );
- FLOAT fCosRoll = cosf( fRoll/2.0f );
-
- x = fSinRoll * fCosPitch * fCosYaw - fCosRoll * fSinPitch * fSinYaw;
- y = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw;
- z = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw;
- w = fCosRoll * fCosPitch * fCosYaw + fSinRoll * fSinPitch * fSinYaw;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_MatrixFromQuaternion()
-// Desc: Converts a unit quaternion into a rotation matrix.
-//-----------------------------------------------------------------------------
-VOID D3DMath_MatrixFromQuaternion( D3DMATRIX& mat, FLOAT x, FLOAT y, FLOAT z,
- FLOAT w )
-{
- FLOAT xx = x*x; FLOAT yy = y*y; FLOAT zz = z*z;
- FLOAT xy = x*y; FLOAT xz = x*z; FLOAT yz = y*z;
- FLOAT wx = w*x; FLOAT wy = w*y; FLOAT wz = w*z;
-
- mat._11 = 1 - 2 * ( yy + zz );
- mat._12 = 2 * ( xy - wz );
- mat._13 = 2 * ( xz + wy );
-
- mat._21 = 2 * ( xy + wz );
- mat._22 = 1 - 2 * ( xx + zz );
- mat._23 = 2 * ( yz - wx );
-
- mat._31 = 2 * ( xz - wy );
- mat._32 = 2 * ( yz + wx );
- mat._33 = 1 - 2 * ( xx + yy );
-
- mat._14 = mat._24 = mat._34 = 0.0f;
- mat._41 = mat._42 = mat._43 = 0.0f;
- mat._44 = 1.0f;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_QuaternionFromMatrix()
-// Desc: Converts a rotation matrix into a unit quaternion.
-//-----------------------------------------------------------------------------
-VOID D3DMath_QuaternionFromMatrix( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
- D3DMATRIX& mat )
-{
- if( mat._11 + mat._22 + mat._33 > 0.0f )
- {
- FLOAT s = sqrtf( mat._11 + mat._22 + mat._33 + mat._44 );
-
- x = (mat._23-mat._32) / (2*s);
- y = (mat._31-mat._13) / (2*s);
- z = (mat._12-mat._21) / (2*s);
- w = 0.5f * s;
- }
- else
- {
-
-
- }
- FLOAT xx = x*x; FLOAT yy = y*y; FLOAT zz = z*z;
- FLOAT xy = x*y; FLOAT xz = x*z; FLOAT yz = y*z;
- FLOAT wx = w*x; FLOAT wy = w*y; FLOAT wz = w*z;
-
- mat._11 = 1 - 2 * ( yy + zz );
- mat._12 = 2 * ( xy - wz );
- mat._13 = 2 * ( xz + wy );
-
- mat._21 = 2 * ( xy + wz );
- mat._22 = 1 - 2 * ( xx + zz );
- mat._23 = 2 * ( yz - wx );
-
- mat._31 = 2 * ( xz - wy );
- mat._32 = 2 * ( yz + wx );
- mat._33 = 1 - 2 * ( xx + yy );
-
- mat._14 = mat._24 = mat._34 = 0.0f;
- mat._41 = mat._42 = mat._43 = 0.0f;
- mat._44 = 1.0f;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_QuaternionMultiply()
-// Desc: Mulitples two quaternions together as in {Q} = {A} * {B}.
-//-----------------------------------------------------------------------------
-VOID D3DMath_QuaternionMultiply( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
- FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
- FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw )
-{
- FLOAT Dx = Ax*Bw + Ay*Bz - Az*By + Aw*Bx;
- FLOAT Dy = -Ax*Bz + Ay*Bw + Az*Bx + Aw*By;
- FLOAT Dz = Ax*By - Ay*Bx + Az*Bw + Aw*Bz;
- FLOAT Dw = -Ax*Bx - Ay*By - Az*Bz + Aw*Bw;
-
- Qx = Dx; Qy = Dy; Qz = Dz; Qw = Dw;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_SlerpQuaternions()
-// Desc: Compute a quaternion which is the spherical linear interpolation
-// between two other quaternions by dvFraction.
-//-----------------------------------------------------------------------------
-VOID D3DMath_QuaternionSlerp( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
- FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
- FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw,
- FLOAT fAlpha )
-{
- // Compute dot product (equal to cosine of the angle between quaternions)
- FLOAT fCosTheta = Ax*Bx + Ay*By + Az*Bz + Aw*Bw;
-
- // Check angle to see if quaternions are in opposite hemispheres
- if( fCosTheta < 0.0f )
- {
- // If so, flip one of the quaterions
- fCosTheta = -fCosTheta;
- Bx = -Bx; By = -By; Bz = -Bz; Bw = -Bw;
- }
-
- // Set factors to do linear interpolation, as a special case where the
- // quaternions are close together.
- FLOAT fBeta = 1.0f - fAlpha;
-
- // If the quaternions aren't close, proceed with spherical interpolation
- if( 1.0f - fCosTheta > 0.001f )
- {
- FLOAT fTheta = acosf( fCosTheta );
-
- fBeta = sinf( fTheta*fBeta ) / sinf( fTheta);
- fAlpha = sinf( fTheta*fAlpha ) / sinf( fTheta);
- }
-
- // Do the interpolation
- Qx = fBeta*Ax + fAlpha*Bx;
- Qy = fBeta*Ay + fAlpha*By;
- Qz = fBeta*Az + fAlpha*Bz;
- Qw = fBeta*Aw + fAlpha*Bw;
-}
-
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+//-----------------------------------------------------------------------------
+// File: D3DMath.cpp
+//
+// Desc: Shortcut macros and functions for using DX objects
+//
+// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+#define D3D_OVERLOADS
+#define STRICT
+#include <math.h>
+#include <stdio.h>
+#include "d3dmath.h"
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_MatrixMultiply()
+// Desc: Does the matrix operation: [Q] = [A] * [B]. Note that the order of
+// this operation was changed from the previous version of the DXSDK.
+//-----------------------------------------------------------------------------
+VOID D3DMath_MatrixMultiply( D3DMATRIX& q, D3DMATRIX& a, D3DMATRIX& b )
+{
+ FLOAT* pA = (FLOAT*)&a;
+ FLOAT* pB = (FLOAT*)&b;
+ FLOAT pM[16];
+
+ ZeroMemory( pM, sizeof(D3DMATRIX) );
+
+ for( WORD i=0; i<4; i++ )
+ for( WORD j=0; j<4; j++ )
+ for( WORD k=0; k<4; k++ )
+ pM[4*i+j] += pA[4*i+k] * pB[4*k+j];
+
+ memcpy( &q, pM, sizeof(D3DMATRIX) );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_MatrixInvert()
+// Desc: Does the matrix operation: [Q] = inv[A]. Note: this function only
+// works for matrices with [0 0 0 1] for the 4th column.
+//-----------------------------------------------------------------------------
+HRESULT D3DMath_MatrixInvert( D3DMATRIX& q, D3DMATRIX& a )
+{
+ if( fabs(a._44 - 1.0f) > .001f)
+ return E_INVALIDARG;
+ if( fabs(a._14) > .001f || fabs(a._24) > .001f || fabs(a._34) > .001f )
+ return E_INVALIDARG;
+
+ FLOAT fDetInv = 1.0f / ( a._11 * ( a._22 * a._33 - a._23 * a._32 ) -
+ a._12 * ( a._21 * a._33 - a._23 * a._31 ) +
+ a._13 * ( a._21 * a._32 - a._22 * a._31 ) );
+
+ q._11 = fDetInv * ( a._22 * a._33 - a._23 * a._32 );
+ q._12 = -fDetInv * ( a._12 * a._33 - a._13 * a._32 );
+ q._13 = fDetInv * ( a._12 * a._23 - a._13 * a._22 );
+ q._14 = 0.0f;
+
+ q._21 = -fDetInv * ( a._21 * a._33 - a._23 * a._31 );
+ q._22 = fDetInv * ( a._11 * a._33 - a._13 * a._31 );
+ q._23 = -fDetInv * ( a._11 * a._23 - a._13 * a._21 );
+ q._24 = 0.0f;
+
+ q._31 = fDetInv * ( a._21 * a._32 - a._22 * a._31 );
+ q._32 = -fDetInv * ( a._11 * a._32 - a._12 * a._31 );
+ q._33 = fDetInv * ( a._11 * a._22 - a._12 * a._21 );
+ q._34 = 0.0f;
+
+ q._41 = -( a._41 * q._11 + a._42 * q._21 + a._43 * q._31 );
+ q._42 = -( a._41 * q._12 + a._42 * q._22 + a._43 * q._32 );
+ q._43 = -( a._41 * q._13 + a._42 * q._23 + a._43 * q._33 );
+ q._44 = 1.0f;
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_VectorMatrixMultiply()
+// Desc: Multiplies a vector by a matrix
+//-----------------------------------------------------------------------------
+HRESULT D3DMath_VectorMatrixMultiply( D3DVECTOR& vDest, D3DVECTOR& vSrc,
+ D3DMATRIX& mat)
+{
+ FLOAT x = vSrc.x*mat._11 + vSrc.y*mat._21 + vSrc.z* mat._31 + mat._41;
+ FLOAT y = vSrc.x*mat._12 + vSrc.y*mat._22 + vSrc.z* mat._32 + mat._42;
+ FLOAT z = vSrc.x*mat._13 + vSrc.y*mat._23 + vSrc.z* mat._33 + mat._43;
+ FLOAT w = vSrc.x*mat._14 + vSrc.y*mat._24 + vSrc.z* mat._34 + mat._44;
+
+ if( fabs( w ) < g_EPSILON )
+ return E_INVALIDARG;
+
+ vDest.x = x/w;
+ vDest.y = y/w;
+ vDest.z = z/w;
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_VertexMatrixMultiply()
+// Desc: Multiplies a vertex by a matrix
+//-----------------------------------------------------------------------------
+HRESULT D3DMath_VertexMatrixMultiply( D3DVERTEX& vDest, D3DVERTEX& vSrc,
+ D3DMATRIX& mat )
+{
+ HRESULT hr;
+ D3DVECTOR* pSrcVec = (D3DVECTOR*)&vSrc.x;
+ D3DVECTOR* pDestVec = (D3DVECTOR*)&vDest.x;
+
+ if( SUCCEEDED( hr = D3DMath_VectorMatrixMultiply( *pDestVec, *pSrcVec,
+ mat ) ) )
+ {
+ pSrcVec = (D3DVECTOR*)&vSrc.nx;
+ pDestVec = (D3DVECTOR*)&vDest.nx;
+ hr = D3DMath_VectorMatrixMultiply( *pDestVec, *pSrcVec, mat );
+ }
+ return hr;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_QuaternionFromRotation()
+// Desc: Converts a normalized axis and angle to a unit quaternion.
+//-----------------------------------------------------------------------------
+VOID D3DMath_QuaternionFromRotation( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
+ D3DVECTOR& v, FLOAT fTheta )
+{
+ x = sinf( fTheta/2.0f ) * v.x;
+ y = sinf( fTheta/2.0f ) * v.y;
+ z = sinf( fTheta/2.0f ) * v.z;
+ w = cosf( fTheta/2.0f );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_RotationFromQuaternion()
+// Desc: Converts a normalized axis and angle to a unit quaternion.
+//-----------------------------------------------------------------------------
+VOID D3DMath_RotationFromQuaternion( D3DVECTOR& v, FLOAT& fTheta,
+ FLOAT x, FLOAT y, FLOAT z, FLOAT w )
+
+{
+ fTheta = acosf(w) * 2.0f;
+ v.x = x / sinf( fTheta/2.0f );
+ v.y = y / sinf( fTheta/2.0f );
+ v.z = z / sinf( fTheta/2.0f );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_QuaternionFromAngles()
+// Desc: Converts euler angles to a unit quaternion.
+//-----------------------------------------------------------------------------
+VOID D3DMath_QuaternionFromAngles( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
+ FLOAT fYaw, FLOAT fPitch, FLOAT fRoll )
+
+{
+ FLOAT fSinYaw = sinf( fYaw/2.0f );
+ FLOAT fSinPitch = sinf( fPitch/2.0f );
+ FLOAT fSinRoll = sinf( fRoll/2.0f );
+ FLOAT fCosYaw = cosf( fYaw/2.0f );
+ FLOAT fCosPitch = cosf( fPitch/2.0f );
+ FLOAT fCosRoll = cosf( fRoll/2.0f );
+
+ x = fSinRoll * fCosPitch * fCosYaw - fCosRoll * fSinPitch * fSinYaw;
+ y = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw;
+ z = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw;
+ w = fCosRoll * fCosPitch * fCosYaw + fSinRoll * fSinPitch * fSinYaw;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_MatrixFromQuaternion()
+// Desc: Converts a unit quaternion into a rotation matrix.
+//-----------------------------------------------------------------------------
+VOID D3DMath_MatrixFromQuaternion( D3DMATRIX& mat, FLOAT x, FLOAT y, FLOAT z,
+ FLOAT w )
+{
+ FLOAT xx = x*x; FLOAT yy = y*y; FLOAT zz = z*z;
+ FLOAT xy = x*y; FLOAT xz = x*z; FLOAT yz = y*z;
+ FLOAT wx = w*x; FLOAT wy = w*y; FLOAT wz = w*z;
+
+ mat._11 = 1 - 2 * ( yy + zz );
+ mat._12 = 2 * ( xy - wz );
+ mat._13 = 2 * ( xz + wy );
+
+ mat._21 = 2 * ( xy + wz );
+ mat._22 = 1 - 2 * ( xx + zz );
+ mat._23 = 2 * ( yz - wx );
+
+ mat._31 = 2 * ( xz - wy );
+ mat._32 = 2 * ( yz + wx );
+ mat._33 = 1 - 2 * ( xx + yy );
+
+ mat._14 = mat._24 = mat._34 = 0.0f;
+ mat._41 = mat._42 = mat._43 = 0.0f;
+ mat._44 = 1.0f;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_QuaternionFromMatrix()
+// Desc: Converts a rotation matrix into a unit quaternion.
+//-----------------------------------------------------------------------------
+VOID D3DMath_QuaternionFromMatrix( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
+ D3DMATRIX& mat )
+{
+ if( mat._11 + mat._22 + mat._33 > 0.0f )
+ {
+ FLOAT s = sqrtf( mat._11 + mat._22 + mat._33 + mat._44 );
+
+ x = (mat._23-mat._32) / (2*s);
+ y = (mat._31-mat._13) / (2*s);
+ z = (mat._12-mat._21) / (2*s);
+ w = 0.5f * s;
+ }
+ else
+ {
+
+
+ }
+ FLOAT xx = x*x; FLOAT yy = y*y; FLOAT zz = z*z;
+ FLOAT xy = x*y; FLOAT xz = x*z; FLOAT yz = y*z;
+ FLOAT wx = w*x; FLOAT wy = w*y; FLOAT wz = w*z;
+
+ mat._11 = 1 - 2 * ( yy + zz );
+ mat._12 = 2 * ( xy - wz );
+ mat._13 = 2 * ( xz + wy );
+
+ mat._21 = 2 * ( xy + wz );
+ mat._22 = 1 - 2 * ( xx + zz );
+ mat._23 = 2 * ( yz - wx );
+
+ mat._31 = 2 * ( xz - wy );
+ mat._32 = 2 * ( yz + wx );
+ mat._33 = 1 - 2 * ( xx + yy );
+
+ mat._14 = mat._24 = mat._34 = 0.0f;
+ mat._41 = mat._42 = mat._43 = 0.0f;
+ mat._44 = 1.0f;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_QuaternionMultiply()
+// Desc: Mulitples two quaternions together as in {Q} = {A} * {B}.
+//-----------------------------------------------------------------------------
+VOID D3DMath_QuaternionMultiply( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
+ FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
+ FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw )
+{
+ FLOAT Dx = Ax*Bw + Ay*Bz - Az*By + Aw*Bx;
+ FLOAT Dy = -Ax*Bz + Ay*Bw + Az*Bx + Aw*By;
+ FLOAT Dz = Ax*By - Ay*Bx + Az*Bw + Aw*Bz;
+ FLOAT Dw = -Ax*Bx - Ay*By - Az*Bz + Aw*Bw;
+
+ Qx = Dx; Qy = Dy; Qz = Dz; Qw = Dw;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_SlerpQuaternions()
+// Desc: Compute a quaternion which is the spherical linear interpolation
+// between two other quaternions by dvFraction.
+//-----------------------------------------------------------------------------
+VOID D3DMath_QuaternionSlerp( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
+ FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
+ FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw,
+ FLOAT fAlpha )
+{
+ // Compute dot product (equal to cosine of the angle between quaternions)
+ FLOAT fCosTheta = Ax*Bx + Ay*By + Az*Bz + Aw*Bw;
+
+ // Check angle to see if quaternions are in opposite hemispheres
+ if( fCosTheta < 0.0f )
+ {
+ // If so, flip one of the quaterions
+ fCosTheta = -fCosTheta;
+ Bx = -Bx; By = -By; Bz = -Bz; Bw = -Bw;
+ }
+
+ // Set factors to do linear interpolation, as a special case where the
+ // quaternions are close together.
+ FLOAT fBeta = 1.0f - fAlpha;
+
+ // If the quaternions aren't close, proceed with spherical interpolation
+ if( 1.0f - fCosTheta > 0.001f )
+ {
+ FLOAT fTheta = acosf( fCosTheta );
+
+ fBeta = sinf( fTheta*fBeta ) / sinf( fTheta);
+ fAlpha = sinf( fTheta*fAlpha ) / sinf( fTheta);
+ }
+
+ // Do the interpolation
+ Qx = fBeta*Ax + fAlpha*Bx;
+ Qy = fBeta*Ay + fAlpha*By;
+ Qz = fBeta*Az + fAlpha*Bz;
+ Qw = fBeta*Aw + fAlpha*Bw;
+}
+
+
+
+
diff --git a/src/old/d3dmath.h b/src/old/d3dmath.h
index 5d95290..6e98e18 100644
--- a/src/old/d3dmath.h
+++ b/src/old/d3dmath.h
@@ -1,107 +1,107 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-//-----------------------------------------------------------------------------
-// File: D3DMath.h
-//
-// Desc: Math functions and shortcuts for Direct3D programming.
-//
-// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-
-#pragma once
-
-#include <ddraw.h>
-#include <d3d.h>
-
-
-//-----------------------------------------------------------------------------
-// Useful Math constants
-//-----------------------------------------------------------------------------
-const FLOAT g_PI = 3.14159265358979323846f; // Pi
-const FLOAT g_2_PI = 6.28318530717958623200f; // 2 * Pi
-const FLOAT g_PI_DIV_2 = 1.57079632679489655800f; // Pi / 2
-const FLOAT g_PI_DIV_4 = 0.78539816339744827900f; // Pi / 4
-const FLOAT g_INV_PI = 0.31830988618379069122f; // 1 / Pi
-const FLOAT g_DEGTORAD = 0.01745329251994329547f; // Degrees to Radians
-const FLOAT g_RADTODEG = 57.29577951308232286465f; // Radians to Degrees
-const FLOAT g_HUGE = 1.0e+38f; // Huge number for FLOAT
-const FLOAT g_EPSILON = 1.0e-5f; // Tolerance for FLOATs
-
-
-
-
-//-----------------------------------------------------------------------------
-// Fuzzy compares (within tolerance)
-//-----------------------------------------------------------------------------
-//>>> func.h IsZero()
-inline bool D3DMath_IsZero( FLOAT a, FLOAT fTol = g_EPSILON )
-{ return ( a <= 0.0f ) ? ( a >= -fTol ) : ( a <= fTol ); }
-
-
-
-
-//-----------------------------------------------------------------------------
-// Matrix functions
-//-----------------------------------------------------------------------------
-//>>> matrix.h MultiplyMatrices()
-VOID D3DMath_MatrixMultiply( D3DMATRIX& q, D3DMATRIX& a, D3DMATRIX& b );
-//>>> matrix.h Matrix::Invert()
-HRESULT D3DMath_MatrixInvert( D3DMATRIX& q, D3DMATRIX& a );
-
-
-
-
-//-----------------------------------------------------------------------------
-// Vector functions
-//-----------------------------------------------------------------------------
-
-//>>> matrix.h MatrixVectorMultiply()
-HRESULT D3DMath_VectorMatrixMultiply( D3DVECTOR& vDest, D3DVECTOR& vSrc,
- D3DMATRIX& mat);
-// TODO
-HRESULT D3DMath_VertexMatrixMultiply( D3DVERTEX& vDest, D3DVERTEX& vSrc,
- D3DMATRIX& mat );
-
-
-
-
-//-----------------------------------------------------------------------------
-// Quaternion functions
-//-----------------------------------------------------------------------------
-
-// UNUSED
-
-
-VOID D3DMath_QuaternionFromRotation( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
- D3DVECTOR& v, FLOAT fTheta );
-VOID D3DMath_RotationFromQuaternion( D3DVECTOR& v, FLOAT& fTheta,
- FLOAT x, FLOAT y, FLOAT z, FLOAT w );
-VOID D3DMath_QuaternionFromAngles( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
- FLOAT fYaw, FLOAT fPitch, FLOAT fRoll );
-VOID D3DMath_MatrixFromQuaternion( D3DMATRIX& mat, FLOAT x, FLOAT y, FLOAT z,
- FLOAT w );
-VOID D3DMath_QuaternionFromMatrix( FLOAT &x, FLOAT &y, FLOAT &z, FLOAT &w,
- D3DMATRIX& mat );
-VOID D3DMath_QuaternionMultiply( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
- FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
- FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw );
-VOID D3DMath_QuaternionSlerp( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
- FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
- FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw,
- FLOAT fAlpha );
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+//-----------------------------------------------------------------------------
+// File: D3DMath.h
+//
+// Desc: Math functions and shortcuts for Direct3D programming.
+//
+// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+#include <ddraw.h>
+#include <d3d.h>
+
+
+//-----------------------------------------------------------------------------
+// Useful Math constants
+//-----------------------------------------------------------------------------
+const FLOAT g_PI = 3.14159265358979323846f; // Pi
+const FLOAT g_2_PI = 6.28318530717958623200f; // 2 * Pi
+const FLOAT g_PI_DIV_2 = 1.57079632679489655800f; // Pi / 2
+const FLOAT g_PI_DIV_4 = 0.78539816339744827900f; // Pi / 4
+const FLOAT g_INV_PI = 0.31830988618379069122f; // 1 / Pi
+const FLOAT g_DEGTORAD = 0.01745329251994329547f; // Degrees to Radians
+const FLOAT g_RADTODEG = 57.29577951308232286465f; // Radians to Degrees
+const FLOAT g_HUGE = 1.0e+38f; // Huge number for FLOAT
+const FLOAT g_EPSILON = 1.0e-5f; // Tolerance for FLOATs
+
+
+
+
+//-----------------------------------------------------------------------------
+// Fuzzy compares (within tolerance)
+//-----------------------------------------------------------------------------
+//>>> func.h IsZero()
+inline bool D3DMath_IsZero( FLOAT a, FLOAT fTol = g_EPSILON )
+{ return ( a <= 0.0f ) ? ( a >= -fTol ) : ( a <= fTol ); }
+
+
+
+
+//-----------------------------------------------------------------------------
+// Matrix functions
+//-----------------------------------------------------------------------------
+//>>> matrix.h MultiplyMatrices()
+VOID D3DMath_MatrixMultiply( D3DMATRIX& q, D3DMATRIX& a, D3DMATRIX& b );
+//>>> matrix.h Matrix::Invert()
+HRESULT D3DMath_MatrixInvert( D3DMATRIX& q, D3DMATRIX& a );
+
+
+
+
+//-----------------------------------------------------------------------------
+// Vector functions
+//-----------------------------------------------------------------------------
+
+//>>> matrix.h MatrixVectorMultiply()
+HRESULT D3DMath_VectorMatrixMultiply( D3DVECTOR& vDest, D3DVECTOR& vSrc,
+ D3DMATRIX& mat);
+// TODO
+HRESULT D3DMath_VertexMatrixMultiply( D3DVERTEX& vDest, D3DVERTEX& vSrc,
+ D3DMATRIX& mat );
+
+
+
+
+//-----------------------------------------------------------------------------
+// Quaternion functions
+//-----------------------------------------------------------------------------
+
+// UNUSED
+
+
+VOID D3DMath_QuaternionFromRotation( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
+ D3DVECTOR& v, FLOAT fTheta );
+VOID D3DMath_RotationFromQuaternion( D3DVECTOR& v, FLOAT& fTheta,
+ FLOAT x, FLOAT y, FLOAT z, FLOAT w );
+VOID D3DMath_QuaternionFromAngles( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
+ FLOAT fYaw, FLOAT fPitch, FLOAT fRoll );
+VOID D3DMath_MatrixFromQuaternion( D3DMATRIX& mat, FLOAT x, FLOAT y, FLOAT z,
+ FLOAT w );
+VOID D3DMath_QuaternionFromMatrix( FLOAT &x, FLOAT &y, FLOAT &z, FLOAT &w,
+ D3DMATRIX& mat );
+VOID D3DMath_QuaternionMultiply( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
+ FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
+ FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw );
+VOID D3DMath_QuaternionSlerp( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
+ FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
+ FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw,
+ FLOAT fAlpha );
+
+
diff --git a/src/old/d3dres.h b/src/old/d3dres.h
index 79ba76e..0259d86 100644
--- a/src/old/d3dres.h
+++ b/src/old/d3dres.h
@@ -1,55 +1,55 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-//-----------------------------------------------------------------------------
-// File: D3DRes.h
-//
-// Desc: Resource definitions required by the CD3DApplication class.
-// Any application using the CD3DApplication class must include resources
-// with the following identifiers.
-//
-// Copyright (c) 1999 Microsoft Corporation. All rights reserved.
-//-----------------------------------------------------------------------------
-
-#pragma once
-
-#define IDI_MAIN_ICON 101 // Application icon
-#define IDR_MAIN_ACCEL 113 // Keyboard accelerator
-#define IDR_MENU 141 // Application menu
-#define IDR_POPUP 142 // Popup menu
-#define IDD_ABOUT 143 // About dialog box
-#define IDD_CHANGEDEVICE 144 // "Change Device" dialog box
-#define IDC_CURSORHAND 149
-#define IDC_CURSORSCROLLL 150
-#define IDC_CURSORSCROLLR 151
-#define IDC_CURSORSCROLLU 152
-#define IDC_CURSORSCROLLD 153
-#define IDC_CURSORTARGET 154
-
-#define IDC_DEVICE_COMBO 1000 // Device combobox for "Change Device" dlg
-#define IDC_MODE_COMBO 1001 // Mode combobox for "Change Device" dlg
-#define IDC_WINDOWED_CHECKBOX 1012 // Checkbox for windowed-mode
-#define IDC_STEREO_CHECKBOX 1013 // Checkbox for stereo modes
-#define IDC_FULLSCREEN_TEXT 1014 // Group box text label
-
-#define IDM_ABOUT 40001 // Command to invoke About dlg
-#define IDM_CHANGEDEVICE 40002 // Command to invoke "Change Device" dlg
-#define IDM_TOGGLEFULLSCREEN 40003 // Command to toggle fullscreen mode
-#define IDM_TOGGLESTART 40004 // Command to toggle frame animation
-#define IDM_SINGLESTEP 40005 // Command to single step frame animation
-#define IDM_EXIT 40006 // Command to exit the application
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+//-----------------------------------------------------------------------------
+// File: D3DRes.h
+//
+// Desc: Resource definitions required by the CD3DApplication class.
+// Any application using the CD3DApplication class must include resources
+// with the following identifiers.
+//
+// Copyright (c) 1999 Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+#define IDI_MAIN_ICON 101 // Application icon
+#define IDR_MAIN_ACCEL 113 // Keyboard accelerator
+#define IDR_MENU 141 // Application menu
+#define IDR_POPUP 142 // Popup menu
+#define IDD_ABOUT 143 // About dialog box
+#define IDD_CHANGEDEVICE 144 // "Change Device" dialog box
+#define IDC_CURSORHAND 149
+#define IDC_CURSORSCROLLL 150
+#define IDC_CURSORSCROLLR 151
+#define IDC_CURSORSCROLLU 152
+#define IDC_CURSORSCROLLD 153
+#define IDC_CURSORTARGET 154
+
+#define IDC_DEVICE_COMBO 1000 // Device combobox for "Change Device" dlg
+#define IDC_MODE_COMBO 1001 // Mode combobox for "Change Device" dlg
+#define IDC_WINDOWED_CHECKBOX 1012 // Checkbox for windowed-mode
+#define IDC_STEREO_CHECKBOX 1013 // Checkbox for stereo modes
+#define IDC_FULLSCREEN_TEXT 1014 // Group box text label
+
+#define IDM_ABOUT 40001 // Command to invoke About dlg
+#define IDM_CHANGEDEVICE 40002 // Command to invoke "Change Device" dlg
+#define IDM_TOGGLEFULLSCREEN 40003 // Command to toggle fullscreen mode
+#define IDM_TOGGLESTART 40004 // Command to toggle frame animation
+#define IDM_SINGLESTEP 40005 // Command to single step frame animation
+#define IDM_EXIT 40006 // Command to exit the application
+
+
diff --git a/src/old/d3dtextr.cpp b/src/old/d3dtextr.cpp
index 39be603..f035e65 100644
--- a/src/old/d3dtextr.cpp
+++ b/src/old/d3dtextr.cpp
@@ -1,1081 +1,1081 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-//-----------------------------------------------------------------------------
-// File: D3DTextr.cpp
-//
-// Desc: Functions to manage textures, including creating (loading from a
-// file), restoring lost surfaces, invalidating, and destroying.
-//
-// Note: the implementation of these fucntions maintain an internal list
-// of loaded textures. After creation, individual textures are referenced
-// via their ASCII names.
-//
-// Copyright (c) 1996-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-#include <tchar.h>
-#include <stdio.h>
-#include <algorithm>
-using std::min;
-#include "old/d3dtextr.h"
-#include "old/d3dutil.h"
-#include "common/language.h"
-#include "common/misc.h"
-
-
-
-
-//-----------------------------------------------------------------------------
-// Macros, function prototypes and static variable
-//-----------------------------------------------------------------------------
-static TCHAR g_strTexturePath[512] = _T(""); // Path for files
-static bool g_bDebugMode = false;
-
-
-
-void D3DTextr_SetDebugMode(bool bDebug)
-{
- g_bDebugMode = bDebug;
-}
-
-
-
-//-----------------------------------------------------------------------------
-// Name: TextureContainer
-// Desc: Linked list structure to hold info per texture
-//-----------------------------------------------------------------------------
-struct TextureContainer
-{
- TextureContainer* m_pNext; // Linked list ptr
-
- TCHAR m_strName[80]; // Name of texture (doubles as image filename)
- DWORD m_dwWidth;
- DWORD m_dwHeight;
- DWORD m_dwStage; // Texture stage (for multitexture devices)
- DWORD m_dwBPP;
- DWORD m_dwFlags;
- bool m_bHasAlpha;
-
- LPDIRECTDRAWSURFACE7 m_pddsSurface; // Surface of the texture
- HBITMAP m_hbmBitmap; // Bitmap containing texture image
- DWORD* m_pRGBAData;
-
-public:
- HRESULT LoadImageData();
- HRESULT LoadBitmapFile( TCHAR* strPathname );
- HRESULT LoadTargaFile( TCHAR* strPathname, TCHAR* strFilename );
- HRESULT Restore( LPDIRECT3DDEVICE7 pd3dDevice );
- HRESULT CopyBitmapToSurface();
- HRESULT CopyRGBADataToSurface();
-
- TextureContainer( TCHAR* strName, DWORD dwStage, DWORD dwFlags );
- ~TextureContainer();
-};
-
-// Local list of textures
-static TextureContainer* g_ptcTextureList = NULL;
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CD3DTextureManager
-// Desc: Class used to automatically construct and destruct the static
-// texture engine class.
-//-----------------------------------------------------------------------------
-class CD3DTextureManager
-{
-public:
- CD3DTextureManager() {}
- ~CD3DTextureManager() { if( g_ptcTextureList ) delete g_ptcTextureList; }
-};
-
-// Global instance
-CD3DTextureManager g_StaticTextureEngine;
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: struct TEXTURESEARCHINFO
-// Desc: Structure used to search for texture formats
-//-----------------------------------------------------------------------------
-struct TEXTURESEARCHINFO
-{
- DWORD dwDesiredBPP; // Input for texture format search
- bool bUseAlpha;
- bool bUsePalette;
- bool bFoundGoodFormat;
-
- DDPIXELFORMAT* pddpf; // Output of texture format search
-};
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: TextureSearchCallback()
-// Desc: Enumeration callback routine to find a best-matching texture format.
-// The param data is the DDPIXELFORMAT of the best-so-far matching
-// texture. Note: the desired BPP is passed in the dwSize field, and the
-// default BPP is passed in the dwFlags field.
-//-----------------------------------------------------------------------------
-static HRESULT CALLBACK TextureSearchCallback( DDPIXELFORMAT* pddpf,
- VOID* param )
-{
- if( NULL==pddpf || NULL==param )
- return DDENUMRET_OK;
-
- TEXTURESEARCHINFO* ptsi = (TEXTURESEARCHINFO*)param;
-
- // Skip any funky modes
- if( pddpf->dwFlags & (DDPF_LUMINANCE|DDPF_BUMPLUMINANCE|DDPF_BUMPDUDV) )
- return DDENUMRET_OK;
-
- // Check for palettized formats
- if( ptsi->bUsePalette )
- {
- if( !( pddpf->dwFlags & DDPF_PALETTEINDEXED8 ) )
- return DDENUMRET_OK;
-
- // Accept the first 8-bit palettized format we get
- memcpy( ptsi->pddpf, pddpf, sizeof(DDPIXELFORMAT) );
- ptsi->bFoundGoodFormat = true;
- return DDENUMRET_CANCEL;
- }
-
- // Else, skip any paletized formats (all modes under 16bpp)
- if( pddpf->dwRGBBitCount < 16 )
- return DDENUMRET_OK;
-
- // Skip any FourCC formats
- if( pddpf->dwFourCC != 0 )
- return DDENUMRET_OK;
-
- // Skip any ARGB 4444 formats (which are best used for pre-authored
- // content designed speciafically for an ARGB 4444 format).
- if( pddpf->dwRGBAlphaBitMask == 0x0000f000 )
- return DDENUMRET_OK;
-
- // Make sure current alpha format agrees with requested format type
- if( (ptsi->bUseAlpha==true) && !(pddpf->dwFlags&DDPF_ALPHAPIXELS) )
- return DDENUMRET_OK;
- if( (ptsi->bUseAlpha==false) && (pddpf->dwFlags&DDPF_ALPHAPIXELS) )
- return DDENUMRET_OK;
-
- // Check if we found a good match
- if( pddpf->dwRGBBitCount == ptsi->dwDesiredBPP )
- {
- memcpy( ptsi->pddpf, pddpf, sizeof(DDPIXELFORMAT) );
- ptsi->bFoundGoodFormat = true;
- return DDENUMRET_CANCEL;
- }
-
- return DDENUMRET_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: FindTexture()
-// Desc: Searches the internal list of textures for a texture specified by
-// its name. Returns the structure associated with that texture.
-//-----------------------------------------------------------------------------
-static TextureContainer* FindTexture( TCHAR* strTextureName )
-{
- TextureContainer* ptcTexture = g_ptcTextureList;
-
- while( ptcTexture )
- {
- if( !lstrcmpi( strTextureName, ptcTexture->m_strName ) )
- return ptcTexture;
- ptcTexture = ptcTexture->m_pNext;
- }
-
- return NULL;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: TextureContainer()
-// Desc: Constructor for a texture object
-//-----------------------------------------------------------------------------
-TextureContainer::TextureContainer( TCHAR* strName, DWORD dwStage,
- DWORD dwFlags )
-{
- lstrcpy( m_strName, strName );
- m_dwWidth = 0;
- m_dwHeight = 0;
- m_dwStage = dwStage;
- m_dwBPP = 0;
- m_dwFlags = dwFlags;
- m_bHasAlpha = 0;
-
- m_pddsSurface = NULL;
- m_hbmBitmap = NULL;
- m_pRGBAData = NULL;
-
- // Add the texture to the head of the global texture list
- m_pNext = g_ptcTextureList;
- g_ptcTextureList = this;
-
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: ~TextureContainer()
-// Desc: Destructs the contents of the texture container
-//-----------------------------------------------------------------------------
-TextureContainer::~TextureContainer()
-{
- SAFE_RELEASE( m_pddsSurface );
- SAFE_DELETE( m_pRGBAData );
- DeleteObject( m_hbmBitmap );
-
- // Remove the texture container from the global list
- if( g_ptcTextureList == this )
- g_ptcTextureList = m_pNext;
- else
- {
- for( TextureContainer* ptc=g_ptcTextureList; ptc; ptc=ptc->m_pNext )
- if( ptc->m_pNext == this )
- ptc->m_pNext = m_pNext;
- }
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: LoadImageData()
-// Desc: Loads the texture map's image data
-//-----------------------------------------------------------------------------
-HRESULT TextureContainer::LoadImageData()
-{
- TCHAR* strExtension;
- TCHAR strMetaname[256];
- TCHAR strFilename[256];
-
- if ( g_bDebugMode )
- {
- if ( _tcsrchr( m_strName, _T('\\') ) == 0 )
- {
- lstrcpy( strMetaname, "" );
- lstrcpy( strFilename, g_strTexturePath );
- lstrcat( strFilename, m_strName );
- }
- else
- {
- lstrcpy( strMetaname, "" );
- lstrcpy( strFilename, m_strName );
- }
- }
- else
- {
- if ( _tcsrchr( m_strName, _T('\\') ) == 0 )
- {
-#if _SCHOOL
- lstrcpy( strMetaname, "ceebot1.dat" );
-#else
- lstrcpy( strMetaname, "colobot1.dat" );
-#endif
- lstrcpy( strFilename, m_strName );
- }
- else
- {
- lstrcpy( strMetaname, "" );
- lstrcpy( strFilename, m_strName );
- }
- }
-
- if ( !g_metafile.IsExist(strMetaname, strFilename) )
- {
- return DDERR_NOTFOUND;
- }
-
- // Get the filename extension
- if ( NULL == ( strExtension = _tcsrchr( m_strName, _T('.') ) ) )
- {
- return DDERR_UNSUPPORTED;
- }
-
- // Load bitmap files
- if ( strMetaname[0] == 0 && !lstrcmpi( strExtension, _T(".bmp") ) )
- {
- return LoadBitmapFile( strFilename );
- }
-
- // Load targa files
- if ( !lstrcmpi( strExtension, _T(".tga") ) )
- {
- return LoadTargaFile( strMetaname, strFilename );
- }
-
- // Can add code here to check for other file formats before failing
- return DDERR_UNSUPPORTED;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: LoadBitmapFile()
-// Desc: Loads data from a .bmp file, and stores it in a bitmap structure.
-//-----------------------------------------------------------------------------
-HRESULT TextureContainer::LoadBitmapFile( TCHAR* strPathname )
-{
- // Try to load the bitmap as a file
- m_hbmBitmap = (HBITMAP)LoadImage( NULL, strPathname, IMAGE_BITMAP, 0, 0,
- LR_LOADFROMFILE|LR_CREATEDIBSECTION );
- if( m_hbmBitmap )
- return S_OK;
-
- return DDERR_NOTFOUND;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: LoadTargaFile()
-// Desc: Loads RGBA data from a .tga file, and stores it in allocated memory
-// for the specified texture container
-//-----------------------------------------------------------------------------
-HRESULT TextureContainer::LoadTargaFile( TCHAR* strMetaname, TCHAR* strFilename )
-{
- if( g_metafile.Open(strMetaname, strFilename) != 0 )
- return E_FAIL;
-
- struct TargaHeader
- {
- BYTE IDLength;
- BYTE ColormapType;
- BYTE ImageType;
- BYTE ColormapSpecification[5];
- WORD XOrigin;
- WORD YOrigin;
- WORD ImageWidth;
- WORD ImageHeight;
- BYTE PixelDepth;
- BYTE ImageDescriptor;
- } tga;
-
- g_metafile.Read(&tga, sizeof(TargaHeader));
-
- // Only true color, non-mapped images are supported
- if( ( 0 != tga.ColormapType ) ||
- ( tga.ImageType != 10 && tga.ImageType != 2 ) )
- {
- g_metafile.Close();
- return E_FAIL;
- }
-
- // Skip the ID field. The first byte of the header is the length of this field
- if( tga.IDLength )
- {
- g_metafile.Seek(tga.IDLength);
- }
-
- m_dwWidth = tga.ImageWidth;
- m_dwHeight = tga.ImageHeight;
- m_dwBPP = tga.PixelDepth;
- m_pRGBAData = new DWORD[m_dwWidth*m_dwHeight];
-
- if( m_pRGBAData == NULL )
- {
- g_metafile.Close();
- return E_FAIL;
- }
-
- for( DWORD y=0; y<m_dwHeight; y++ )
- {
- DWORD dwOffset = y*m_dwWidth;
-
- if( 0 == ( tga.ImageDescriptor & 0x0010 ) )
- dwOffset = (m_dwHeight-y-1)*m_dwWidth;
-
- for( DWORD x=0; x<m_dwWidth; x )
- {
- if( tga.ImageType == 10 )
- {
- BYTE PacketInfo = g_metafile.GetByte();
- WORD PacketType = 0x80 & PacketInfo;
- WORD PixelCount = ( 0x007f & PacketInfo ) + 1;
-
- if( PacketType )
- {
- DWORD b = g_metafile.GetWord();
- DWORD g = g_metafile.GetWord();
- DWORD r = g_metafile.GetWord();
- DWORD a = 0xff;
- if( m_dwBPP == 32 )
- a = g_metafile.GetWord();
-
- while( PixelCount-- )
- {
- m_pRGBAData[dwOffset+x] = (r<<24L)+(g<<16L)+(b<<8L)+(a);
- x++;
- }
- }
- else
- {
- while( PixelCount-- )
- {
- BYTE b = g_metafile.GetByte();
- BYTE g = g_metafile.GetByte();
- BYTE r = g_metafile.GetByte();
- BYTE a = 0xff;
- if( m_dwBPP == 32 )
- a = g_metafile.GetByte();
-
- m_pRGBAData[dwOffset+x] = (r<<24L)+(g<<16L)+(b<<8L)+(a);
- x++;
- }
- }
- }
- else
- {
- BYTE b = g_metafile.GetByte();
- BYTE g = g_metafile.GetByte();
- BYTE r = g_metafile.GetByte();
- BYTE a = 0xff;
- if( m_dwBPP == 32 )
- a = g_metafile.GetByte();
-
- m_pRGBAData[dwOffset+x] = (r<<24L)+(g<<16L)+(b<<8L)+(a);
- x++;
- }
- }
- }
-
- g_metafile.Close();
-
- // Check for alpha content
- for( DWORD i=0; i<(m_dwWidth*m_dwHeight); i++ )
- {
-//? if( m_pRGBAData[i] & 0x000000ff != 0xff )
- if( (m_pRGBAData[i] & 0x000000ff) != 0xff ) // erreur corrig�e !
- {
- m_bHasAlpha = true;
- break;
- }
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: Restore()
-// Desc: Rebuilds the texture surface using the new device.
-//-----------------------------------------------------------------------------
-HRESULT TextureContainer::Restore( LPDIRECT3DDEVICE7 pd3dDevice )
-{
- // Release any previously created objects
- SAFE_RELEASE( m_pddsSurface );
-
- // Check params
- if( NULL == pd3dDevice )
- return DDERR_INVALIDPARAMS;
-
- // Get the device caps
- D3DDEVICEDESC7 ddDesc;
- if( FAILED( pd3dDevice->GetCaps( &ddDesc) ) )
- return E_FAIL;
-
- // Setup the new surface desc
- DDSURFACEDESC2 ddsd;
- D3DUtil_InitSurfaceDesc( ddsd );
- ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|
- DDSD_PIXELFORMAT|DDSD_TEXTURESTAGE;
- ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
- ddsd.dwTextureStage = m_dwStage;
- ddsd.dwWidth = m_dwWidth;
- ddsd.dwHeight = m_dwHeight;
-
- // Turn on texture management for hardware devices
- if( ddDesc.deviceGUID == IID_IDirect3DHALDevice )
- ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
- else if( ddDesc.deviceGUID == IID_IDirect3DTnLHalDevice )
- ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
- else
- ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
-
- // Adjust width and height to be powers of 2, if the device requires it
- if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 )
- {
- for( ddsd.dwWidth=1; m_dwWidth>ddsd.dwWidth; ddsd.dwWidth<<=1 );
- for( ddsd.dwHeight=1; m_dwHeight>ddsd.dwHeight; ddsd.dwHeight<<=1 );
- }
-
- // Limit max texture sizes, if the driver can't handle large textures
- DWORD dwMaxWidth = ddDesc.dwMaxTextureWidth;
- DWORD dwMaxHeight = ddDesc.dwMaxTextureHeight;
- ddsd.dwWidth = min( ddsd.dwWidth, ( dwMaxWidth ? dwMaxWidth : 256 ) );
- ddsd.dwHeight = min( ddsd.dwHeight, ( dwMaxHeight ? dwMaxHeight : 256 ) );
-
- // Make the texture square, if the driver requires it
- if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )
- {
- if( ddsd.dwWidth > ddsd.dwHeight ) ddsd.dwHeight = ddsd.dwWidth;
- else ddsd.dwWidth = ddsd.dwHeight;
- }
-
- // Setup the structure to be used for texture enumration.
- TEXTURESEARCHINFO tsi;
- tsi.bFoundGoodFormat = false;
- tsi.pddpf = &ddsd.ddpfPixelFormat;
- tsi.dwDesiredBPP = m_dwBPP;
- tsi.bUsePalette = ( m_dwBPP <= 8 );
- tsi.bUseAlpha = m_bHasAlpha;
- if( m_dwFlags & D3DTEXTR_16BITSPERPIXEL )
- tsi.dwDesiredBPP = 16;
- else if( m_dwFlags & D3DTEXTR_32BITSPERPIXEL )
- tsi.dwDesiredBPP = 32;
-
- if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
- {
- if( tsi.bUsePalette )
- {
- if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE )
- {
- tsi.bUseAlpha = true;
- tsi.bUsePalette = true;
- }
- else
- {
- tsi.bUseAlpha = true;
- tsi.bUsePalette = false;
- }
- }
- }
-
- // Enumerate the texture formats, and find the closest device-supported
- // texture pixel format
- pd3dDevice->EnumTextureFormats( TextureSearchCallback, &tsi );
-
- // If we couldn't find a format, let's try a default format
- if( false == tsi.bFoundGoodFormat )
- {
- tsi.bUsePalette = false;
- tsi.dwDesiredBPP = 16;
- pd3dDevice->EnumTextureFormats( TextureSearchCallback, &tsi );
-
- // If we still fail, we cannot create this texture
- if( false == tsi.bFoundGoodFormat )
- return E_FAIL;
- }
-
- // Get the DirectDraw interface for creating surfaces
- LPDIRECTDRAW7 pDD;
- LPDIRECTDRAWSURFACE7 pddsRender;
- pd3dDevice->GetRenderTarget( &pddsRender );
- pddsRender->GetDDInterface( (VOID**)&pDD );
- pddsRender->Release();
-
- // Create a new surface for the texture
- HRESULT hr = pDD->CreateSurface( &ddsd, &m_pddsSurface, NULL );
-
- // Done with DDraw
- pDD->Release();
-
- if( FAILED(hr) )
- return hr;
-
- // For bitmap-based textures, copy the bitmap image.
- if( m_hbmBitmap )
- return CopyBitmapToSurface();
-
- if( m_pRGBAData )
- return CopyRGBADataToSurface();
-
- // At this point, code can be added to handle other file formats (such as
- // .dds files, .jpg files, etc.).
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CopyBitmapToSurface()
-// Desc: Copies the image of a bitmap into a surface
-//-----------------------------------------------------------------------------
-HRESULT TextureContainer::CopyBitmapToSurface()
-{
- // Get a DDraw object to create a temporary surface
- LPDIRECTDRAW7 pDD;
- m_pddsSurface->GetDDInterface( (VOID**)&pDD );
-
- // Get the bitmap structure (to extract width, height, and bpp)
- BITMAP bm;
- GetObject( m_hbmBitmap, sizeof(BITMAP), &bm );
-
- // Setup the new surface desc
- DDSURFACEDESC2 ddsd;
- ddsd.dwSize = sizeof(ddsd);
- m_pddsSurface->GetSurfaceDesc( &ddsd );
- ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|
- DDSD_TEXTURESTAGE;
- ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_SYSTEMMEMORY;
- ddsd.ddsCaps.dwCaps2 = 0L;
- ddsd.dwWidth = bm.bmWidth;
- ddsd.dwHeight = bm.bmHeight;
-
- // Create a new surface for the texture
- LPDIRECTDRAWSURFACE7 pddsTempSurface;
- HRESULT hr;
- if( FAILED( hr = pDD->CreateSurface( &ddsd, &pddsTempSurface, NULL ) ) )
- {
- pDD->Release();
- return hr;
- }
-
- // Get a DC for the bitmap
- HDC hdcBitmap = CreateCompatibleDC( NULL );
- if( NULL == hdcBitmap )
- {
- pddsTempSurface->Release();
- pDD->Release();
- return hr;
- }
- SelectObject( hdcBitmap, m_hbmBitmap );
-
- // Handle palettized textures. Need to attach a palette
- if( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 )
- {
- LPDIRECTDRAWPALETTE pPalette;
- DWORD dwPaletteFlags = DDPCAPS_8BIT|DDPCAPS_ALLOW256;
- DWORD pe[256];
- WORD wNumColors = GetDIBColorTable( hdcBitmap, 0, 256, (RGBQUAD*)pe );
-
- // Create the color table
- for( WORD i=0; i<wNumColors; i++ )
- {
- pe[i] = RGB( GetBValue(pe[i]), GetGValue(pe[i]), GetRValue(pe[i]) );
-
- // Handle textures with transparent pixels
- if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
- {
- // Set alpha for opaque pixels
- if( m_dwFlags & D3DTEXTR_TRANSPARENTBLACK )
- {
- if( pe[i] != 0x00000000 )
- pe[i] |= 0xff000000;
- }
- else if( m_dwFlags & D3DTEXTR_TRANSPARENTWHITE )
- {
- if( pe[i] != 0x00ffffff )
- pe[i] |= 0xff000000;
- }
- }
- }
- // Add DDPCAPS_ALPHA flag for textures with transparent pixels
- if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
- dwPaletteFlags |= DDPCAPS_ALPHA;
-
- // Create & attach a palette
- pDD->CreatePalette( dwPaletteFlags, (PALETTEENTRY*)pe, &pPalette, NULL );
- pddsTempSurface->SetPalette( pPalette );
- m_pddsSurface->SetPalette( pPalette );
- SAFE_RELEASE( pPalette );
- }
-
- // Copy the bitmap image to the surface.
- HDC hdcSurface;
- if( SUCCEEDED( pddsTempSurface->GetDC( &hdcSurface ) ) )
- {
- BitBlt( hdcSurface, 0, 0, bm.bmWidth, bm.bmHeight, hdcBitmap, 0, 0,
- SRCCOPY );
- pddsTempSurface->ReleaseDC( hdcSurface );
- }
- DeleteDC( hdcBitmap );
-
- // Copy the temp surface to the real texture surface
- m_pddsSurface->Blt( NULL, pddsTempSurface, NULL, DDBLT_WAIT, NULL );
-
- // Done with the temp surface
- pddsTempSurface->Release();
-
- // For textures with real alpha (not palettized), set transparent bits
- if( ddsd.ddpfPixelFormat.dwRGBAlphaBitMask )
- {
- if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
- {
- // Lock the texture surface
- DDSURFACEDESC2 ddsd;
- ddsd.dwSize = sizeof(ddsd);
- while( m_pddsSurface->Lock( NULL, &ddsd, 0, NULL ) ==
- DDERR_WASSTILLDRAWING );
-
- DWORD dwAlphaMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask;
- DWORD dwRGBMask = ( ddsd.ddpfPixelFormat.dwRBitMask |
- ddsd.ddpfPixelFormat.dwGBitMask |
- ddsd.ddpfPixelFormat.dwBBitMask );
- DWORD dwColorkey = 0x00000000; // Colorkey on black
- if( m_dwFlags & D3DTEXTR_TRANSPARENTWHITE )
- dwColorkey = dwRGBMask; // Colorkey on white
-
- // Add an opaque alpha value to each non-colorkeyed pixel
- for( DWORD y=0; y<ddsd.dwHeight; y++ )
- {
- WORD* p16 = (WORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch);
- DWORD* p32 = (DWORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch);
-
- for( DWORD x=0; x<ddsd.dwWidth; x++ )
- {
- if( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 )
- {
- if( ( *p16 &= dwRGBMask ) != dwColorkey )
- *p16 |= dwAlphaMask;
- p16++;
- }
- if( ddsd.ddpfPixelFormat.dwRGBBitCount == 32 )
- {
- if( ( *p32 &= dwRGBMask ) != dwColorkey )
- *p32 |= dwAlphaMask;
- p32++;
- }
- }
- }
- m_pddsSurface->Unlock( NULL );
- }
- }
-
- pDD->Release();
-
- return S_OK;;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CopyRGBADataToSurface()
-// Desc: Invalidates the current texture objects and rebuilds new ones
-// using the new device.
-//-----------------------------------------------------------------------------
-HRESULT TextureContainer::CopyRGBADataToSurface()
-{
- // Get a DDraw object to create a temporary surface
- LPDIRECTDRAW7 pDD;
- m_pddsSurface->GetDDInterface( (VOID**)&pDD );
-
- // Setup the new surface desc
- DDSURFACEDESC2 ddsd;
- ddsd.dwSize = sizeof(ddsd);
- m_pddsSurface->GetSurfaceDesc( &ddsd );
- ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|
- DDSD_TEXTURESTAGE;
- ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_SYSTEMMEMORY;
- ddsd.ddsCaps.dwCaps2 = 0L;
- ddsd.dwWidth = m_dwWidth;
- ddsd.dwHeight = m_dwHeight;
-
- // Create a new surface for the texture
- LPDIRECTDRAWSURFACE7 pddsTempSurface;
- HRESULT hr;
- if( FAILED( hr = pDD->CreateSurface( &ddsd, &pddsTempSurface, NULL ) ) )
- {
- pDD->Release();
- return NULL;
- }
-
- while( pddsTempSurface->Lock( NULL, &ddsd, 0, 0 ) == DDERR_WASSTILLDRAWING );
- DWORD lPitch = ddsd.lPitch;
- BYTE* pBytes = (BYTE*)ddsd.lpSurface;
-
- DWORD dwRMask = ddsd.ddpfPixelFormat.dwRBitMask;
- DWORD dwGMask = ddsd.ddpfPixelFormat.dwGBitMask;
- DWORD dwBMask = ddsd.ddpfPixelFormat.dwBBitMask;
- DWORD dwAMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask;
-
- DWORD dwRShiftL = 8, dwRShiftR = 0;
- DWORD dwGShiftL = 8, dwGShiftR = 0;
- DWORD dwBShiftL = 8, dwBShiftR = 0;
- DWORD dwAShiftL = 8, dwAShiftR = 0;
-
- DWORD dwMask;
- for( dwMask=dwRMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwRShiftR++;
- for( ; dwMask; dwMask>>=1 ) dwRShiftL--;
-
- for( dwMask=dwGMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwGShiftR++;
- for( ; dwMask; dwMask>>=1 ) dwGShiftL--;
-
- for( dwMask=dwBMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwBShiftR++;
- for( ; dwMask; dwMask>>=1 ) dwBShiftL--;
-
- for( dwMask=dwAMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwAShiftR++;
- for( ; dwMask; dwMask>>=1 ) dwAShiftL--;
-
- for( DWORD y=0; y<ddsd.dwHeight; y++ )
- {
- DWORD* pDstData32 = (DWORD*)pBytes;
- WORD* pDstData16 = (WORD*)pBytes;
-
- for( DWORD x=0; x<ddsd.dwWidth; x++ )
- {
- DWORD dwPixel = m_pRGBAData[y*ddsd.dwWidth+x];
-
- BYTE r = (BYTE)((dwPixel>>24)&0x000000ff);
- BYTE g = (BYTE)((dwPixel>>16)&0x000000ff);
- BYTE b = (BYTE)((dwPixel>> 8)&0x000000ff);
- BYTE a = (BYTE)((dwPixel>> 0)&0x000000ff);
-
- DWORD dr = ((r>>(dwRShiftL))<<dwRShiftR)&dwRMask;
- DWORD dg = ((g>>(dwGShiftL))<<dwGShiftR)&dwGMask;
- DWORD db = ((b>>(dwBShiftL))<<dwBShiftR)&dwBMask;
- DWORD da = ((a>>(dwAShiftL))<<dwAShiftR)&dwAMask;
-
- if( 32 == ddsd.ddpfPixelFormat.dwRGBBitCount )
- pDstData32[x] = (DWORD)(dr+dg+db+da);
- else
- pDstData16[x] = (WORD)(dr+dg+db+da);
- }
-
- pBytes += ddsd.lPitch;
- }
-
- pddsTempSurface->Unlock(0);
-
- // Copy the temp surface to the real texture surface
- m_pddsSurface->Blt( NULL, pddsTempSurface, NULL, DDBLT_WAIT, NULL );
-
- // Done with the temp objects
- pddsTempSurface->Release();
- pDD->Release();
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_SetTexturePath()
-// Desc: Enumeration callback routine to find a best-matching texture format.
-//-----------------------------------------------------------------------------
-VOID D3DTextr_SetTexturePath( TCHAR* strTexturePath )
-{
- if( NULL == strTexturePath )
- strTexturePath = _T("");
- lstrcpy( g_strTexturePath, strTexturePath );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_CreateTextureFromFile()
-// Desc: Is passed a filename and creates a local Bitmap from that file.
-// The texture can not be used until it is restored, however.
-//-----------------------------------------------------------------------------
-HRESULT D3DTextr_CreateTextureFromFile( TCHAR* strName, DWORD dwStage,
- DWORD dwFlags )
-{
- // Check parameters
- if( NULL == strName )
- return E_INVALIDARG;
-
- // Check first to see if the texture is already loaded
- if( NULL != FindTexture( strName ) )
- return S_OK;
-
- // Allocate and add the texture to the linked list of textures;
- TextureContainer* ptcTexture = new TextureContainer( strName, dwStage,
- dwFlags );
- if( NULL == ptcTexture )
- return E_OUTOFMEMORY;
-
- // Create a bitmap and load the texture file into it,
- if( FAILED( ptcTexture->LoadImageData() ) )
- {
- delete ptcTexture;
- return E_FAIL;
- }
-
- // Save the image's dimensions
- if( ptcTexture->m_hbmBitmap )
- {
- BITMAP bm;
- GetObject( ptcTexture->m_hbmBitmap, sizeof(BITMAP), &bm );
- ptcTexture->m_dwWidth = (DWORD)bm.bmWidth;
- ptcTexture->m_dwHeight = (DWORD)bm.bmHeight;
- ptcTexture->m_dwBPP = (DWORD)bm.bmBitsPixel;
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_CreateEmptyTexture()
-// Desc: Creates an empty texture.
-//-----------------------------------------------------------------------------
-HRESULT D3DTextr_CreateEmptyTexture( TCHAR* strName, DWORD dwWidth,
- DWORD dwHeight, DWORD dwStage,
- DWORD dwFlags )
-{
- // Check parameters
- if( NULL == strName )
- return E_INVALIDARG;
-
- // Check first to see if the texture is already loaded
- if( NULL != FindTexture( strName ) )
- return E_FAIL;
-
- // Allocate and add the texture to the linked list of textures;
- TextureContainer* ptcTexture = new TextureContainer( strName, dwStage,
- dwFlags );
- if( NULL == ptcTexture )
- return E_OUTOFMEMORY;
-
- // Save dimensions
- ptcTexture->m_dwWidth = dwWidth;
- ptcTexture->m_dwHeight = dwHeight;
- ptcTexture->m_dwBPP = 16;
- if( ptcTexture->m_dwFlags & D3DTEXTR_32BITSPERPIXEL )
- ptcTexture->m_dwBPP = 32;
-
- // Save alpha usage flag
- if( dwFlags & D3DTEXTR_CREATEWITHALPHA )
- ptcTexture->m_bHasAlpha = true;
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_Restore()
-// Desc: Invalidates the current texture objects and rebuilds new ones
-// using the new device.
-//-----------------------------------------------------------------------------
-HRESULT D3DTextr_Restore( TCHAR* strName, LPDIRECT3DDEVICE7 pd3dDevice )
-{
- TextureContainer* ptcTexture = FindTexture( strName );
- if( NULL == ptcTexture )
- return DDERR_NOTFOUND;
-
- // Restore the texture (this recreates the new surface for this device).
- return ptcTexture->Restore( pd3dDevice );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_RestoreAllTextures()
-// Desc: This function is called when a mode is changed. It updates all
-// texture objects to be valid with the new device.
-//-----------------------------------------------------------------------------
-HRESULT D3DTextr_RestoreAllTextures( LPDIRECT3DDEVICE7 pd3dDevice )
-{
- TextureContainer* ptcTexture = g_ptcTextureList;
-
- while( ptcTexture )
- {
- D3DTextr_Restore( ptcTexture->m_strName, pd3dDevice );
- ptcTexture = ptcTexture->m_pNext;
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_Invalidate()
-// Desc: Used to bump a texture out of (video) memory, this function
-// actually destroys the d3dtexture and ddsurface of the texture
-//-----------------------------------------------------------------------------
-HRESULT D3DTextr_Invalidate( TCHAR* strName )
-{
- TextureContainer* ptcTexture = FindTexture( strName );
- if( NULL == ptcTexture )
- return DDERR_NOTFOUND;
-
- SAFE_RELEASE( ptcTexture->m_pddsSurface );
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_InvalidateAllTextures()
-// Desc: This function is called when a mode is changed. It invalidates
-// all texture objects so their device can be safely released.
-//-----------------------------------------------------------------------------
-HRESULT D3DTextr_InvalidateAllTextures()
-{
- TextureContainer* ptcTexture = g_ptcTextureList;
-
- while( ptcTexture )
- {
- SAFE_RELEASE( ptcTexture->m_pddsSurface );
- ptcTexture = ptcTexture->m_pNext;
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_DestroyTexture()
-// Desc: Frees the resources for the specified texture container
-//-----------------------------------------------------------------------------
-HRESULT D3DTextr_DestroyTexture( TCHAR* strName )
-{
- TextureContainer* ptcTexture = FindTexture( strName );
-
- SAFE_DELETE( ptcTexture );
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_GetSurface()
-// Desc: Returns a pointer to a d3dSurface from the name of the texture
-//-----------------------------------------------------------------------------
-LPDIRECTDRAWSURFACE7 D3DTextr_GetSurface( TCHAR* strName )
-{
- TextureContainer* ptcTexture = FindTexture( strName );
-
- return ptcTexture ? ptcTexture->m_pddsSurface : NULL;
-}
-
-
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+//-----------------------------------------------------------------------------
+// File: D3DTextr.cpp
+//
+// Desc: Functions to manage textures, including creating (loading from a
+// file), restoring lost surfaces, invalidating, and destroying.
+//
+// Note: the implementation of these fucntions maintain an internal list
+// of loaded textures. After creation, individual textures are referenced
+// via their ASCII names.
+//
+// Copyright (c) 1996-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+#include <tchar.h>
+#include <stdio.h>
+#include <algorithm>
+using std::min;
+#include "old/d3dtextr.h"
+#include "old/d3dutil.h"
+#include "common/language.h"
+#include "common/misc.h"
+
+
+
+
+//-----------------------------------------------------------------------------
+// Macros, function prototypes and static variable
+//-----------------------------------------------------------------------------
+static TCHAR g_strTexturePath[512] = _T(""); // Path for files
+static bool g_bDebugMode = false;
+
+
+
+void D3DTextr_SetDebugMode(bool bDebug)
+{
+ g_bDebugMode = bDebug;
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Name: TextureContainer
+// Desc: Linked list structure to hold info per texture
+//-----------------------------------------------------------------------------
+struct TextureContainer
+{
+ TextureContainer* m_pNext; // Linked list ptr
+
+ TCHAR m_strName[80]; // Name of texture (doubles as image filename)
+ DWORD m_dwWidth;
+ DWORD m_dwHeight;
+ DWORD m_dwStage; // Texture stage (for multitexture devices)
+ DWORD m_dwBPP;
+ DWORD m_dwFlags;
+ bool m_bHasAlpha;
+
+ LPDIRECTDRAWSURFACE7 m_pddsSurface; // Surface of the texture
+ HBITMAP m_hbmBitmap; // Bitmap containing texture image
+ DWORD* m_pRGBAData;
+
+public:
+ HRESULT LoadImageData();
+ HRESULT LoadBitmapFile( TCHAR* strPathname );
+ HRESULT LoadTargaFile( TCHAR* strPathname, TCHAR* strFilename );
+ HRESULT Restore( LPDIRECT3DDEVICE7 pd3dDevice );
+ HRESULT CopyBitmapToSurface();
+ HRESULT CopyRGBADataToSurface();
+
+ TextureContainer( TCHAR* strName, DWORD dwStage, DWORD dwFlags );
+ ~TextureContainer();
+};
+
+// Local list of textures
+static TextureContainer* g_ptcTextureList = NULL;
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CD3DTextureManager
+// Desc: Class used to automatically construct and destruct the static
+// texture engine class.
+//-----------------------------------------------------------------------------
+class CD3DTextureManager
+{
+public:
+ CD3DTextureManager() {}
+ ~CD3DTextureManager() { if( g_ptcTextureList ) delete g_ptcTextureList; }
+};
+
+// Global instance
+CD3DTextureManager g_StaticTextureEngine;
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: struct TEXTURESEARCHINFO
+// Desc: Structure used to search for texture formats
+//-----------------------------------------------------------------------------
+struct TEXTURESEARCHINFO
+{
+ DWORD dwDesiredBPP; // Input for texture format search
+ bool bUseAlpha;
+ bool bUsePalette;
+ bool bFoundGoodFormat;
+
+ DDPIXELFORMAT* pddpf; // Output of texture format search
+};
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: TextureSearchCallback()
+// Desc: Enumeration callback routine to find a best-matching texture format.
+// The param data is the DDPIXELFORMAT of the best-so-far matching
+// texture. Note: the desired BPP is passed in the dwSize field, and the
+// default BPP is passed in the dwFlags field.
+//-----------------------------------------------------------------------------
+static HRESULT CALLBACK TextureSearchCallback( DDPIXELFORMAT* pddpf,
+ VOID* param )
+{
+ if( NULL==pddpf || NULL==param )
+ return DDENUMRET_OK;
+
+ TEXTURESEARCHINFO* ptsi = (TEXTURESEARCHINFO*)param;
+
+ // Skip any funky modes
+ if( pddpf->dwFlags & (DDPF_LUMINANCE|DDPF_BUMPLUMINANCE|DDPF_BUMPDUDV) )
+ return DDENUMRET_OK;
+
+ // Check for palettized formats
+ if( ptsi->bUsePalette )
+ {
+ if( !( pddpf->dwFlags & DDPF_PALETTEINDEXED8 ) )
+ return DDENUMRET_OK;
+
+ // Accept the first 8-bit palettized format we get
+ memcpy( ptsi->pddpf, pddpf, sizeof(DDPIXELFORMAT) );
+ ptsi->bFoundGoodFormat = true;
+ return DDENUMRET_CANCEL;
+ }
+
+ // Else, skip any paletized formats (all modes under 16bpp)
+ if( pddpf->dwRGBBitCount < 16 )
+ return DDENUMRET_OK;
+
+ // Skip any FourCC formats
+ if( pddpf->dwFourCC != 0 )
+ return DDENUMRET_OK;
+
+ // Skip any ARGB 4444 formats (which are best used for pre-authored
+ // content designed speciafically for an ARGB 4444 format).
+ if( pddpf->dwRGBAlphaBitMask == 0x0000f000 )
+ return DDENUMRET_OK;
+
+ // Make sure current alpha format agrees with requested format type
+ if( (ptsi->bUseAlpha==true) && !(pddpf->dwFlags&DDPF_ALPHAPIXELS) )
+ return DDENUMRET_OK;
+ if( (ptsi->bUseAlpha==false) && (pddpf->dwFlags&DDPF_ALPHAPIXELS) )
+ return DDENUMRET_OK;
+
+ // Check if we found a good match
+ if( pddpf->dwRGBBitCount == ptsi->dwDesiredBPP )
+ {
+ memcpy( ptsi->pddpf, pddpf, sizeof(DDPIXELFORMAT) );
+ ptsi->bFoundGoodFormat = true;
+ return DDENUMRET_CANCEL;
+ }
+
+ return DDENUMRET_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: FindTexture()
+// Desc: Searches the internal list of textures for a texture specified by
+// its name. Returns the structure associated with that texture.
+//-----------------------------------------------------------------------------
+static TextureContainer* FindTexture( TCHAR* strTextureName )
+{
+ TextureContainer* ptcTexture = g_ptcTextureList;
+
+ while( ptcTexture )
+ {
+ if( !lstrcmpi( strTextureName, ptcTexture->m_strName ) )
+ return ptcTexture;
+ ptcTexture = ptcTexture->m_pNext;
+ }
+
+ return NULL;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: TextureContainer()
+// Desc: Constructor for a texture object
+//-----------------------------------------------------------------------------
+TextureContainer::TextureContainer( TCHAR* strName, DWORD dwStage,
+ DWORD dwFlags )
+{
+ lstrcpy( m_strName, strName );
+ m_dwWidth = 0;
+ m_dwHeight = 0;
+ m_dwStage = dwStage;
+ m_dwBPP = 0;
+ m_dwFlags = dwFlags;
+ m_bHasAlpha = 0;
+
+ m_pddsSurface = NULL;
+ m_hbmBitmap = NULL;
+ m_pRGBAData = NULL;
+
+ // Add the texture to the head of the global texture list
+ m_pNext = g_ptcTextureList;
+ g_ptcTextureList = this;
+
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: ~TextureContainer()
+// Desc: Destructs the contents of the texture container
+//-----------------------------------------------------------------------------
+TextureContainer::~TextureContainer()
+{
+ SAFE_RELEASE( m_pddsSurface );
+ SAFE_DELETE( m_pRGBAData );
+ DeleteObject( m_hbmBitmap );
+
+ // Remove the texture container from the global list
+ if( g_ptcTextureList == this )
+ g_ptcTextureList = m_pNext;
+ else
+ {
+ for( TextureContainer* ptc=g_ptcTextureList; ptc; ptc=ptc->m_pNext )
+ if( ptc->m_pNext == this )
+ ptc->m_pNext = m_pNext;
+ }
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: LoadImageData()
+// Desc: Loads the texture map's image data
+//-----------------------------------------------------------------------------
+HRESULT TextureContainer::LoadImageData()
+{
+ TCHAR* strExtension;
+ TCHAR strMetaname[256];
+ TCHAR strFilename[256];
+
+ if ( g_bDebugMode )
+ {
+ if ( _tcsrchr( m_strName, _T('\\') ) == 0 )
+ {
+ lstrcpy( strMetaname, "" );
+ lstrcpy( strFilename, g_strTexturePath );
+ lstrcat( strFilename, m_strName );
+ }
+ else
+ {
+ lstrcpy( strMetaname, "" );
+ lstrcpy( strFilename, m_strName );
+ }
+ }
+ else
+ {
+ if ( _tcsrchr( m_strName, _T('\\') ) == 0 )
+ {
+#if _SCHOOL
+ lstrcpy( strMetaname, "ceebot1.dat" );
+#else
+ lstrcpy( strMetaname, "colobot1.dat" );
+#endif
+ lstrcpy( strFilename, m_strName );
+ }
+ else
+ {
+ lstrcpy( strMetaname, "" );
+ lstrcpy( strFilename, m_strName );
+ }
+ }
+
+ if ( !g_metafile.IsExist(strMetaname, strFilename) )
+ {
+ return DDERR_NOTFOUND;
+ }
+
+ // Get the filename extension
+ if ( NULL == ( strExtension = _tcsrchr( m_strName, _T('.') ) ) )
+ {
+ return DDERR_UNSUPPORTED;
+ }
+
+ // Load bitmap files
+ if ( strMetaname[0] == 0 && !lstrcmpi( strExtension, _T(".bmp") ) )
+ {
+ return LoadBitmapFile( strFilename );
+ }
+
+ // Load targa files
+ if ( !lstrcmpi( strExtension, _T(".tga") ) )
+ {
+ return LoadTargaFile( strMetaname, strFilename );
+ }
+
+ // Can add code here to check for other file formats before failing
+ return DDERR_UNSUPPORTED;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: LoadBitmapFile()
+// Desc: Loads data from a .bmp file, and stores it in a bitmap structure.
+//-----------------------------------------------------------------------------
+HRESULT TextureContainer::LoadBitmapFile( TCHAR* strPathname )
+{
+ // Try to load the bitmap as a file
+ m_hbmBitmap = (HBITMAP)LoadImage( NULL, strPathname, IMAGE_BITMAP, 0, 0,
+ LR_LOADFROMFILE|LR_CREATEDIBSECTION );
+ if( m_hbmBitmap )
+ return S_OK;
+
+ return DDERR_NOTFOUND;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: LoadTargaFile()
+// Desc: Loads RGBA data from a .tga file, and stores it in allocated memory
+// for the specified texture container
+//-----------------------------------------------------------------------------
+HRESULT TextureContainer::LoadTargaFile( TCHAR* strMetaname, TCHAR* strFilename )
+{
+ if( g_metafile.Open(strMetaname, strFilename) != 0 )
+ return E_FAIL;
+
+ struct TargaHeader
+ {
+ BYTE IDLength;
+ BYTE ColormapType;
+ BYTE ImageType;
+ BYTE ColormapSpecification[5];
+ WORD XOrigin;
+ WORD YOrigin;
+ WORD ImageWidth;
+ WORD ImageHeight;
+ BYTE PixelDepth;
+ BYTE ImageDescriptor;
+ } tga;
+
+ g_metafile.Read(&tga, sizeof(TargaHeader));
+
+ // Only true color, non-mapped images are supported
+ if( ( 0 != tga.ColormapType ) ||
+ ( tga.ImageType != 10 && tga.ImageType != 2 ) )
+ {
+ g_metafile.Close();
+ return E_FAIL;
+ }
+
+ // Skip the ID field. The first byte of the header is the length of this field
+ if( tga.IDLength )
+ {
+ g_metafile.Seek(tga.IDLength);
+ }
+
+ m_dwWidth = tga.ImageWidth;
+ m_dwHeight = tga.ImageHeight;
+ m_dwBPP = tga.PixelDepth;
+ m_pRGBAData = new DWORD[m_dwWidth*m_dwHeight];
+
+ if( m_pRGBAData == NULL )
+ {
+ g_metafile.Close();
+ return E_FAIL;
+ }
+
+ for( DWORD y=0; y<m_dwHeight; y++ )
+ {
+ DWORD dwOffset = y*m_dwWidth;
+
+ if( 0 == ( tga.ImageDescriptor & 0x0010 ) )
+ dwOffset = (m_dwHeight-y-1)*m_dwWidth;
+
+ for( DWORD x=0; x<m_dwWidth; x )
+ {
+ if( tga.ImageType == 10 )
+ {
+ BYTE PacketInfo = g_metafile.GetByte();
+ WORD PacketType = 0x80 & PacketInfo;
+ WORD PixelCount = ( 0x007f & PacketInfo ) + 1;
+
+ if( PacketType )
+ {
+ DWORD b = g_metafile.GetWord();
+ DWORD g = g_metafile.GetWord();
+ DWORD r = g_metafile.GetWord();
+ DWORD a = 0xff;
+ if( m_dwBPP == 32 )
+ a = g_metafile.GetWord();
+
+ while( PixelCount-- )
+ {
+ m_pRGBAData[dwOffset+x] = (r<<24L)+(g<<16L)+(b<<8L)+(a);
+ x++;
+ }
+ }
+ else
+ {
+ while( PixelCount-- )
+ {
+ BYTE b = g_metafile.GetByte();
+ BYTE g = g_metafile.GetByte();
+ BYTE r = g_metafile.GetByte();
+ BYTE a = 0xff;
+ if( m_dwBPP == 32 )
+ a = g_metafile.GetByte();
+
+ m_pRGBAData[dwOffset+x] = (r<<24L)+(g<<16L)+(b<<8L)+(a);
+ x++;
+ }
+ }
+ }
+ else
+ {
+ BYTE b = g_metafile.GetByte();
+ BYTE g = g_metafile.GetByte();
+ BYTE r = g_metafile.GetByte();
+ BYTE a = 0xff;
+ if( m_dwBPP == 32 )
+ a = g_metafile.GetByte();
+
+ m_pRGBAData[dwOffset+x] = (r<<24L)+(g<<16L)+(b<<8L)+(a);
+ x++;
+ }
+ }
+ }
+
+ g_metafile.Close();
+
+ // Check for alpha content
+ for( DWORD i=0; i<(m_dwWidth*m_dwHeight); i++ )
+ {
+//? if( m_pRGBAData[i] & 0x000000ff != 0xff )
+ if( (m_pRGBAData[i] & 0x000000ff) != 0xff ) // erreur corrig�e !
+ {
+ m_bHasAlpha = true;
+ break;
+ }
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: Restore()
+// Desc: Rebuilds the texture surface using the new device.
+//-----------------------------------------------------------------------------
+HRESULT TextureContainer::Restore( LPDIRECT3DDEVICE7 pd3dDevice )
+{
+ // Release any previously created objects
+ SAFE_RELEASE( m_pddsSurface );
+
+ // Check params
+ if( NULL == pd3dDevice )
+ return DDERR_INVALIDPARAMS;
+
+ // Get the device caps
+ D3DDEVICEDESC7 ddDesc;
+ if( FAILED( pd3dDevice->GetCaps( &ddDesc) ) )
+ return E_FAIL;
+
+ // Setup the new surface desc
+ DDSURFACEDESC2 ddsd;
+ D3DUtil_InitSurfaceDesc( ddsd );
+ ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|
+ DDSD_PIXELFORMAT|DDSD_TEXTURESTAGE;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
+ ddsd.dwTextureStage = m_dwStage;
+ ddsd.dwWidth = m_dwWidth;
+ ddsd.dwHeight = m_dwHeight;
+
+ // Turn on texture management for hardware devices
+ if( ddDesc.deviceGUID == IID_IDirect3DHALDevice )
+ ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
+ else if( ddDesc.deviceGUID == IID_IDirect3DTnLHalDevice )
+ ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
+ else
+ ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
+
+ // Adjust width and height to be powers of 2, if the device requires it
+ if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 )
+ {
+ for( ddsd.dwWidth=1; m_dwWidth>ddsd.dwWidth; ddsd.dwWidth<<=1 );
+ for( ddsd.dwHeight=1; m_dwHeight>ddsd.dwHeight; ddsd.dwHeight<<=1 );
+ }
+
+ // Limit max texture sizes, if the driver can't handle large textures
+ DWORD dwMaxWidth = ddDesc.dwMaxTextureWidth;
+ DWORD dwMaxHeight = ddDesc.dwMaxTextureHeight;
+ ddsd.dwWidth = min( ddsd.dwWidth, ( dwMaxWidth ? dwMaxWidth : 256 ) );
+ ddsd.dwHeight = min( ddsd.dwHeight, ( dwMaxHeight ? dwMaxHeight : 256 ) );
+
+ // Make the texture square, if the driver requires it
+ if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )
+ {
+ if( ddsd.dwWidth > ddsd.dwHeight ) ddsd.dwHeight = ddsd.dwWidth;
+ else ddsd.dwWidth = ddsd.dwHeight;
+ }
+
+ // Setup the structure to be used for texture enumration.
+ TEXTURESEARCHINFO tsi;
+ tsi.bFoundGoodFormat = false;
+ tsi.pddpf = &ddsd.ddpfPixelFormat;
+ tsi.dwDesiredBPP = m_dwBPP;
+ tsi.bUsePalette = ( m_dwBPP <= 8 );
+ tsi.bUseAlpha = m_bHasAlpha;
+ if( m_dwFlags & D3DTEXTR_16BITSPERPIXEL )
+ tsi.dwDesiredBPP = 16;
+ else if( m_dwFlags & D3DTEXTR_32BITSPERPIXEL )
+ tsi.dwDesiredBPP = 32;
+
+ if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
+ {
+ if( tsi.bUsePalette )
+ {
+ if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE )
+ {
+ tsi.bUseAlpha = true;
+ tsi.bUsePalette = true;
+ }
+ else
+ {
+ tsi.bUseAlpha = true;
+ tsi.bUsePalette = false;
+ }
+ }
+ }
+
+ // Enumerate the texture formats, and find the closest device-supported
+ // texture pixel format
+ pd3dDevice->EnumTextureFormats( TextureSearchCallback, &tsi );
+
+ // If we couldn't find a format, let's try a default format
+ if( false == tsi.bFoundGoodFormat )
+ {
+ tsi.bUsePalette = false;
+ tsi.dwDesiredBPP = 16;
+ pd3dDevice->EnumTextureFormats( TextureSearchCallback, &tsi );
+
+ // If we still fail, we cannot create this texture
+ if( false == tsi.bFoundGoodFormat )
+ return E_FAIL;
+ }
+
+ // Get the DirectDraw interface for creating surfaces
+ LPDIRECTDRAW7 pDD;
+ LPDIRECTDRAWSURFACE7 pddsRender;
+ pd3dDevice->GetRenderTarget( &pddsRender );
+ pddsRender->GetDDInterface( (VOID**)&pDD );
+ pddsRender->Release();
+
+ // Create a new surface for the texture
+ HRESULT hr = pDD->CreateSurface( &ddsd, &m_pddsSurface, NULL );
+
+ // Done with DDraw
+ pDD->Release();
+
+ if( FAILED(hr) )
+ return hr;
+
+ // For bitmap-based textures, copy the bitmap image.
+ if( m_hbmBitmap )
+ return CopyBitmapToSurface();
+
+ if( m_pRGBAData )
+ return CopyRGBADataToSurface();
+
+ // At this point, code can be added to handle other file formats (such as
+ // .dds files, .jpg files, etc.).
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CopyBitmapToSurface()
+// Desc: Copies the image of a bitmap into a surface
+//-----------------------------------------------------------------------------
+HRESULT TextureContainer::CopyBitmapToSurface()
+{
+ // Get a DDraw object to create a temporary surface
+ LPDIRECTDRAW7 pDD;
+ m_pddsSurface->GetDDInterface( (VOID**)&pDD );
+
+ // Get the bitmap structure (to extract width, height, and bpp)
+ BITMAP bm;
+ GetObject( m_hbmBitmap, sizeof(BITMAP), &bm );
+
+ // Setup the new surface desc
+ DDSURFACEDESC2 ddsd;
+ ddsd.dwSize = sizeof(ddsd);
+ m_pddsSurface->GetSurfaceDesc( &ddsd );
+ ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|
+ DDSD_TEXTURESTAGE;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_SYSTEMMEMORY;
+ ddsd.ddsCaps.dwCaps2 = 0L;
+ ddsd.dwWidth = bm.bmWidth;
+ ddsd.dwHeight = bm.bmHeight;
+
+ // Create a new surface for the texture
+ LPDIRECTDRAWSURFACE7 pddsTempSurface;
+ HRESULT hr;
+ if( FAILED( hr = pDD->CreateSurface( &ddsd, &pddsTempSurface, NULL ) ) )
+ {
+ pDD->Release();
+ return hr;
+ }
+
+ // Get a DC for the bitmap
+ HDC hdcBitmap = CreateCompatibleDC( NULL );
+ if( NULL == hdcBitmap )
+ {
+ pddsTempSurface->Release();
+ pDD->Release();
+ return hr;
+ }
+ SelectObject( hdcBitmap, m_hbmBitmap );
+
+ // Handle palettized textures. Need to attach a palette
+ if( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 )
+ {
+ LPDIRECTDRAWPALETTE pPalette;
+ DWORD dwPaletteFlags = DDPCAPS_8BIT|DDPCAPS_ALLOW256;
+ DWORD pe[256];
+ WORD wNumColors = GetDIBColorTable( hdcBitmap, 0, 256, (RGBQUAD*)pe );
+
+ // Create the color table
+ for( WORD i=0; i<wNumColors; i++ )
+ {
+ pe[i] = RGB( GetBValue(pe[i]), GetGValue(pe[i]), GetRValue(pe[i]) );
+
+ // Handle textures with transparent pixels
+ if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
+ {
+ // Set alpha for opaque pixels
+ if( m_dwFlags & D3DTEXTR_TRANSPARENTBLACK )
+ {
+ if( pe[i] != 0x00000000 )
+ pe[i] |= 0xff000000;
+ }
+ else if( m_dwFlags & D3DTEXTR_TRANSPARENTWHITE )
+ {
+ if( pe[i] != 0x00ffffff )
+ pe[i] |= 0xff000000;
+ }
+ }
+ }
+ // Add DDPCAPS_ALPHA flag for textures with transparent pixels
+ if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
+ dwPaletteFlags |= DDPCAPS_ALPHA;
+
+ // Create & attach a palette
+ pDD->CreatePalette( dwPaletteFlags, (PALETTEENTRY*)pe, &pPalette, NULL );
+ pddsTempSurface->SetPalette( pPalette );
+ m_pddsSurface->SetPalette( pPalette );
+ SAFE_RELEASE( pPalette );
+ }
+
+ // Copy the bitmap image to the surface.
+ HDC hdcSurface;
+ if( SUCCEEDED( pddsTempSurface->GetDC( &hdcSurface ) ) )
+ {
+ BitBlt( hdcSurface, 0, 0, bm.bmWidth, bm.bmHeight, hdcBitmap, 0, 0,
+ SRCCOPY );
+ pddsTempSurface->ReleaseDC( hdcSurface );
+ }
+ DeleteDC( hdcBitmap );
+
+ // Copy the temp surface to the real texture surface
+ m_pddsSurface->Blt( NULL, pddsTempSurface, NULL, DDBLT_WAIT, NULL );
+
+ // Done with the temp surface
+ pddsTempSurface->Release();
+
+ // For textures with real alpha (not palettized), set transparent bits
+ if( ddsd.ddpfPixelFormat.dwRGBAlphaBitMask )
+ {
+ if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
+ {
+ // Lock the texture surface
+ DDSURFACEDESC2 ddsd;
+ ddsd.dwSize = sizeof(ddsd);
+ while( m_pddsSurface->Lock( NULL, &ddsd, 0, NULL ) ==
+ DDERR_WASSTILLDRAWING );
+
+ DWORD dwAlphaMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask;
+ DWORD dwRGBMask = ( ddsd.ddpfPixelFormat.dwRBitMask |
+ ddsd.ddpfPixelFormat.dwGBitMask |
+ ddsd.ddpfPixelFormat.dwBBitMask );
+ DWORD dwColorkey = 0x00000000; // Colorkey on black
+ if( m_dwFlags & D3DTEXTR_TRANSPARENTWHITE )
+ dwColorkey = dwRGBMask; // Colorkey on white
+
+ // Add an opaque alpha value to each non-colorkeyed pixel
+ for( DWORD y=0; y<ddsd.dwHeight; y++ )
+ {
+ WORD* p16 = (WORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch);
+ DWORD* p32 = (DWORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch);
+
+ for( DWORD x=0; x<ddsd.dwWidth; x++ )
+ {
+ if( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 )
+ {
+ if( ( *p16 &= dwRGBMask ) != dwColorkey )
+ *p16 |= dwAlphaMask;
+ p16++;
+ }
+ if( ddsd.ddpfPixelFormat.dwRGBBitCount == 32 )
+ {
+ if( ( *p32 &= dwRGBMask ) != dwColorkey )
+ *p32 |= dwAlphaMask;
+ p32++;
+ }
+ }
+ }
+ m_pddsSurface->Unlock( NULL );
+ }
+ }
+
+ pDD->Release();
+
+ return S_OK;;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CopyRGBADataToSurface()
+// Desc: Invalidates the current texture objects and rebuilds new ones
+// using the new device.
+//-----------------------------------------------------------------------------
+HRESULT TextureContainer::CopyRGBADataToSurface()
+{
+ // Get a DDraw object to create a temporary surface
+ LPDIRECTDRAW7 pDD;
+ m_pddsSurface->GetDDInterface( (VOID**)&pDD );
+
+ // Setup the new surface desc
+ DDSURFACEDESC2 ddsd;
+ ddsd.dwSize = sizeof(ddsd);
+ m_pddsSurface->GetSurfaceDesc( &ddsd );
+ ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|
+ DDSD_TEXTURESTAGE;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_SYSTEMMEMORY;
+ ddsd.ddsCaps.dwCaps2 = 0L;
+ ddsd.dwWidth = m_dwWidth;
+ ddsd.dwHeight = m_dwHeight;
+
+ // Create a new surface for the texture
+ LPDIRECTDRAWSURFACE7 pddsTempSurface;
+ HRESULT hr;
+ if( FAILED( hr = pDD->CreateSurface( &ddsd, &pddsTempSurface, NULL ) ) )
+ {
+ pDD->Release();
+ return NULL;
+ }
+
+ while( pddsTempSurface->Lock( NULL, &ddsd, 0, 0 ) == DDERR_WASSTILLDRAWING );
+ DWORD lPitch = ddsd.lPitch;
+ BYTE* pBytes = (BYTE*)ddsd.lpSurface;
+
+ DWORD dwRMask = ddsd.ddpfPixelFormat.dwRBitMask;
+ DWORD dwGMask = ddsd.ddpfPixelFormat.dwGBitMask;
+ DWORD dwBMask = ddsd.ddpfPixelFormat.dwBBitMask;
+ DWORD dwAMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask;
+
+ DWORD dwRShiftL = 8, dwRShiftR = 0;
+ DWORD dwGShiftL = 8, dwGShiftR = 0;
+ DWORD dwBShiftL = 8, dwBShiftR = 0;
+ DWORD dwAShiftL = 8, dwAShiftR = 0;
+
+ DWORD dwMask;
+ for( dwMask=dwRMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwRShiftR++;
+ for( ; dwMask; dwMask>>=1 ) dwRShiftL--;
+
+ for( dwMask=dwGMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwGShiftR++;
+ for( ; dwMask; dwMask>>=1 ) dwGShiftL--;
+
+ for( dwMask=dwBMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwBShiftR++;
+ for( ; dwMask; dwMask>>=1 ) dwBShiftL--;
+
+ for( dwMask=dwAMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwAShiftR++;
+ for( ; dwMask; dwMask>>=1 ) dwAShiftL--;
+
+ for( DWORD y=0; y<ddsd.dwHeight; y++ )
+ {
+ DWORD* pDstData32 = (DWORD*)pBytes;
+ WORD* pDstData16 = (WORD*)pBytes;
+
+ for( DWORD x=0; x<ddsd.dwWidth; x++ )
+ {
+ DWORD dwPixel = m_pRGBAData[y*ddsd.dwWidth+x];
+
+ BYTE r = (BYTE)((dwPixel>>24)&0x000000ff);
+ BYTE g = (BYTE)((dwPixel>>16)&0x000000ff);
+ BYTE b = (BYTE)((dwPixel>> 8)&0x000000ff);
+ BYTE a = (BYTE)((dwPixel>> 0)&0x000000ff);
+
+ DWORD dr = ((r>>(dwRShiftL))<<dwRShiftR)&dwRMask;
+ DWORD dg = ((g>>(dwGShiftL))<<dwGShiftR)&dwGMask;
+ DWORD db = ((b>>(dwBShiftL))<<dwBShiftR)&dwBMask;
+ DWORD da = ((a>>(dwAShiftL))<<dwAShiftR)&dwAMask;
+
+ if( 32 == ddsd.ddpfPixelFormat.dwRGBBitCount )
+ pDstData32[x] = (DWORD)(dr+dg+db+da);
+ else
+ pDstData16[x] = (WORD)(dr+dg+db+da);
+ }
+
+ pBytes += ddsd.lPitch;
+ }
+
+ pddsTempSurface->Unlock(0);
+
+ // Copy the temp surface to the real texture surface
+ m_pddsSurface->Blt( NULL, pddsTempSurface, NULL, DDBLT_WAIT, NULL );
+
+ // Done with the temp objects
+ pddsTempSurface->Release();
+ pDD->Release();
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_SetTexturePath()
+// Desc: Enumeration callback routine to find a best-matching texture format.
+//-----------------------------------------------------------------------------
+VOID D3DTextr_SetTexturePath( TCHAR* strTexturePath )
+{
+ if( NULL == strTexturePath )
+ strTexturePath = _T("");
+ lstrcpy( g_strTexturePath, strTexturePath );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_CreateTextureFromFile()
+// Desc: Is passed a filename and creates a local Bitmap from that file.
+// The texture can not be used until it is restored, however.
+//-----------------------------------------------------------------------------
+HRESULT D3DTextr_CreateTextureFromFile( TCHAR* strName, DWORD dwStage,
+ DWORD dwFlags )
+{
+ // Check parameters
+ if( NULL == strName )
+ return E_INVALIDARG;
+
+ // Check first to see if the texture is already loaded
+ if( NULL != FindTexture( strName ) )
+ return S_OK;
+
+ // Allocate and add the texture to the linked list of textures;
+ TextureContainer* ptcTexture = new TextureContainer( strName, dwStage,
+ dwFlags );
+ if( NULL == ptcTexture )
+ return E_OUTOFMEMORY;
+
+ // Create a bitmap and load the texture file into it,
+ if( FAILED( ptcTexture->LoadImageData() ) )
+ {
+ delete ptcTexture;
+ return E_FAIL;
+ }
+
+ // Save the image's dimensions
+ if( ptcTexture->m_hbmBitmap )
+ {
+ BITMAP bm;
+ GetObject( ptcTexture->m_hbmBitmap, sizeof(BITMAP), &bm );
+ ptcTexture->m_dwWidth = (DWORD)bm.bmWidth;
+ ptcTexture->m_dwHeight = (DWORD)bm.bmHeight;
+ ptcTexture->m_dwBPP = (DWORD)bm.bmBitsPixel;
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_CreateEmptyTexture()
+// Desc: Creates an empty texture.
+//-----------------------------------------------------------------------------
+HRESULT D3DTextr_CreateEmptyTexture( TCHAR* strName, DWORD dwWidth,
+ DWORD dwHeight, DWORD dwStage,
+ DWORD dwFlags )
+{
+ // Check parameters
+ if( NULL == strName )
+ return E_INVALIDARG;
+
+ // Check first to see if the texture is already loaded
+ if( NULL != FindTexture( strName ) )
+ return E_FAIL;
+
+ // Allocate and add the texture to the linked list of textures;
+ TextureContainer* ptcTexture = new TextureContainer( strName, dwStage,
+ dwFlags );
+ if( NULL == ptcTexture )
+ return E_OUTOFMEMORY;
+
+ // Save dimensions
+ ptcTexture->m_dwWidth = dwWidth;
+ ptcTexture->m_dwHeight = dwHeight;
+ ptcTexture->m_dwBPP = 16;
+ if( ptcTexture->m_dwFlags & D3DTEXTR_32BITSPERPIXEL )
+ ptcTexture->m_dwBPP = 32;
+
+ // Save alpha usage flag
+ if( dwFlags & D3DTEXTR_CREATEWITHALPHA )
+ ptcTexture->m_bHasAlpha = true;
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_Restore()
+// Desc: Invalidates the current texture objects and rebuilds new ones
+// using the new device.
+//-----------------------------------------------------------------------------
+HRESULT D3DTextr_Restore( TCHAR* strName, LPDIRECT3DDEVICE7 pd3dDevice )
+{
+ TextureContainer* ptcTexture = FindTexture( strName );
+ if( NULL == ptcTexture )
+ return DDERR_NOTFOUND;
+
+ // Restore the texture (this recreates the new surface for this device).
+ return ptcTexture->Restore( pd3dDevice );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_RestoreAllTextures()
+// Desc: This function is called when a mode is changed. It updates all
+// texture objects to be valid with the new device.
+//-----------------------------------------------------------------------------
+HRESULT D3DTextr_RestoreAllTextures( LPDIRECT3DDEVICE7 pd3dDevice )
+{
+ TextureContainer* ptcTexture = g_ptcTextureList;
+
+ while( ptcTexture )
+ {
+ D3DTextr_Restore( ptcTexture->m_strName, pd3dDevice );
+ ptcTexture = ptcTexture->m_pNext;
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_Invalidate()
+// Desc: Used to bump a texture out of (video) memory, this function
+// actually destroys the d3dtexture and ddsurface of the texture
+//-----------------------------------------------------------------------------
+HRESULT D3DTextr_Invalidate( TCHAR* strName )
+{
+ TextureContainer* ptcTexture = FindTexture( strName );
+ if( NULL == ptcTexture )
+ return DDERR_NOTFOUND;
+
+ SAFE_RELEASE( ptcTexture->m_pddsSurface );
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_InvalidateAllTextures()
+// Desc: This function is called when a mode is changed. It invalidates
+// all texture objects so their device can be safely released.
+//-----------------------------------------------------------------------------
+HRESULT D3DTextr_InvalidateAllTextures()
+{
+ TextureContainer* ptcTexture = g_ptcTextureList;
+
+ while( ptcTexture )
+ {
+ SAFE_RELEASE( ptcTexture->m_pddsSurface );
+ ptcTexture = ptcTexture->m_pNext;
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_DestroyTexture()
+// Desc: Frees the resources for the specified texture container
+//-----------------------------------------------------------------------------
+HRESULT D3DTextr_DestroyTexture( TCHAR* strName )
+{
+ TextureContainer* ptcTexture = FindTexture( strName );
+
+ SAFE_DELETE( ptcTexture );
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_GetSurface()
+// Desc: Returns a pointer to a d3dSurface from the name of the texture
+//-----------------------------------------------------------------------------
+LPDIRECTDRAWSURFACE7 D3DTextr_GetSurface( TCHAR* strName )
+{
+ TextureContainer* ptcTexture = FindTexture( strName );
+
+ return ptcTexture ? ptcTexture->m_pddsSurface : NULL;
+}
+
+
+
+
+
diff --git a/src/old/d3dtextr.h b/src/old/d3dtextr.h
index 842fa58..ec0dc47 100644
--- a/src/old/d3dtextr.h
+++ b/src/old/d3dtextr.h
@@ -1,79 +1,79 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-//-----------------------------------------------------------------------------
-// File: D3DTextr.h
-//
-// Desc: Functions to manage textures, including creating (loading from a
-// file), restoring lost surfaces, invalidating, and destroying.
-//
-// Note: the implementation of these fucntions maintain an internal list
-// of loaded textures. After creation, individual textures are referenced
-// via their ASCII names.
-//
-// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-
-#pragma once
-
-#include <ddraw.h>
-#include <d3d.h>
-
-
-
-
-//-----------------------------------------------------------------------------
-// Access functions for loaded textures. Note: these functions search
-// an internal list of the textures, and use the texture associated with the
-// ASCII name.
-//-----------------------------------------------------------------------------
-LPDIRECTDRAWSURFACE7 D3DTextr_GetSurface( TCHAR* strName );
-
-
-
-
-//-----------------------------------------------------------------------------
-// Texture invalidation and restoration functions
-//-----------------------------------------------------------------------------
-HRESULT D3DTextr_Invalidate( TCHAR* strName );
-HRESULT D3DTextr_Restore( TCHAR* strName, LPDIRECT3DDEVICE7 pd3dDevice );
-HRESULT D3DTextr_InvalidateAllTextures();
-HRESULT D3DTextr_RestoreAllTextures( LPDIRECT3DDEVICE7 pd3dDevice );
-
-
-
-
-//-----------------------------------------------------------------------------
-// Texture creation and deletion functions
-//-----------------------------------------------------------------------------
-#define D3DTEXTR_TRANSPARENTWHITE 0x00000001
-#define D3DTEXTR_TRANSPARENTBLACK 0x00000002
-#define D3DTEXTR_32BITSPERPIXEL 0x00000004
-#define D3DTEXTR_16BITSPERPIXEL 0x00000008
-#define D3DTEXTR_CREATEWITHALPHA 0x00000010
-
-
-HRESULT D3DTextr_CreateTextureFromFile( TCHAR* strName, DWORD dwStage=0L,
- DWORD dwFlags=0L );
-HRESULT D3DTextr_CreateEmptyTexture( TCHAR* strName, DWORD dwWidth,
- DWORD dwHeight, DWORD dwStage,
- DWORD dwFlags );
-HRESULT D3DTextr_DestroyTexture( TCHAR* strName );
-VOID D3DTextr_SetTexturePath( TCHAR* strTexturePath );
-
-void D3DTextr_SetDebugMode(bool bDebug);
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+//-----------------------------------------------------------------------------
+// File: D3DTextr.h
+//
+// Desc: Functions to manage textures, including creating (loading from a
+// file), restoring lost surfaces, invalidating, and destroying.
+//
+// Note: the implementation of these fucntions maintain an internal list
+// of loaded textures. After creation, individual textures are referenced
+// via their ASCII names.
+//
+// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+#include <ddraw.h>
+#include <d3d.h>
+
+
+
+
+//-----------------------------------------------------------------------------
+// Access functions for loaded textures. Note: these functions search
+// an internal list of the textures, and use the texture associated with the
+// ASCII name.
+//-----------------------------------------------------------------------------
+LPDIRECTDRAWSURFACE7 D3DTextr_GetSurface( TCHAR* strName );
+
+
+
+
+//-----------------------------------------------------------------------------
+// Texture invalidation and restoration functions
+//-----------------------------------------------------------------------------
+HRESULT D3DTextr_Invalidate( TCHAR* strName );
+HRESULT D3DTextr_Restore( TCHAR* strName, LPDIRECT3DDEVICE7 pd3dDevice );
+HRESULT D3DTextr_InvalidateAllTextures();
+HRESULT D3DTextr_RestoreAllTextures( LPDIRECT3DDEVICE7 pd3dDevice );
+
+
+
+
+//-----------------------------------------------------------------------------
+// Texture creation and deletion functions
+//-----------------------------------------------------------------------------
+#define D3DTEXTR_TRANSPARENTWHITE 0x00000001
+#define D3DTEXTR_TRANSPARENTBLACK 0x00000002
+#define D3DTEXTR_32BITSPERPIXEL 0x00000004
+#define D3DTEXTR_16BITSPERPIXEL 0x00000008
+#define D3DTEXTR_CREATEWITHALPHA 0x00000010
+
+
+HRESULT D3DTextr_CreateTextureFromFile( TCHAR* strName, DWORD dwStage=0L,
+ DWORD dwFlags=0L );
+HRESULT D3DTextr_CreateEmptyTexture( TCHAR* strName, DWORD dwWidth,
+ DWORD dwHeight, DWORD dwStage,
+ DWORD dwFlags );
+HRESULT D3DTextr_DestroyTexture( TCHAR* strName );
+VOID D3DTextr_SetTexturePath( TCHAR* strTexturePath );
+
+void D3DTextr_SetDebugMode(bool bDebug);
+
+
diff --git a/src/old/d3dutil.cpp b/src/old/d3dutil.cpp
index d8fd03e..bd4c7ac 100644
--- a/src/old/d3dutil.cpp
+++ b/src/old/d3dutil.cpp
@@ -1,325 +1,325 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-//-----------------------------------------------------------------------------
-// File: D3DUtil.cpp
-//
-// Desc: Shortcut macros and functions for using DX objects
-//
-//
-// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-#include <math.h>
-#include <stdio.h>
-#include <tchar.h>
-#include "old/d3dutil.h"
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_GetDXSDKMediaPath()
-// Desc: Returns the DirectX SDK media path, as stored in the system registry
-// during the SDK install.
-//-----------------------------------------------------------------------------
-const TCHAR* D3DUtil_GetDXSDKMediaPath()
-{
- static TCHAR strNull[2] = _T("");
- static TCHAR strPath[512];
- HKEY key;
- DWORD type, size = 512;
-
- // Open the appropriate registry key
- LONG result = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
- _T("Software\\Microsoft\\DirectX"),
- 0, KEY_READ, &key );
- if( ERROR_SUCCESS != result )
- return strNull;
-
- result = RegQueryValueEx( key, _T("DXSDK Samples Path"), NULL,
- &type, (BYTE*)strPath, &size );
- RegCloseKey( key );
-
- if( ERROR_SUCCESS != result )
- return strNull;
-
- lstrcat( strPath, _T("\\D3DIM\\Media\\") );
-
- return strPath;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_InitSurfaceDesc()
-// Desc: Helper function called to build a DDSURFACEDESC2 structure,
-// typically before calling CreateSurface() or GetSurfaceDesc()
-//-----------------------------------------------------------------------------
-VOID D3DUtil_InitSurfaceDesc( DDSURFACEDESC2& ddsd, DWORD dwFlags,
- DWORD dwCaps )
-{
- ZeroMemory( &ddsd, sizeof(ddsd) );
- ddsd.dwSize = sizeof(ddsd);
- ddsd.dwFlags = dwFlags;
- ddsd.ddsCaps.dwCaps = dwCaps;
- ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_InitMaterial()
-// Desc: Helper function called to build a D3DMATERIAL7 structure
-//-----------------------------------------------------------------------------
-VOID D3DUtil_InitMaterial( D3DMATERIAL7& mtrl, FLOAT r, FLOAT g, FLOAT b,
- FLOAT a )
-{
- ZeroMemory( &mtrl, sizeof(D3DMATERIAL7) );
- mtrl.dcvDiffuse.r = mtrl.dcvAmbient.r = r;
- mtrl.dcvDiffuse.g = mtrl.dcvAmbient.g = g;
- mtrl.dcvDiffuse.b = mtrl.dcvAmbient.b = b;
- mtrl.dcvDiffuse.a = mtrl.dcvAmbient.a = a;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_InitLight()
-// Desc: Initializes a D3DLIGHT7 structure
-//-----------------------------------------------------------------------------
-VOID D3DUtil_InitLight( D3DLIGHT7& light, D3DLIGHTTYPE ltType,
- FLOAT x, FLOAT y, FLOAT z )
-{
- ZeroMemory( &light, sizeof(D3DLIGHT7) );
- light.dltType = ltType;
- light.dcvDiffuse.r = 1.0f;
- light.dcvDiffuse.g = 1.0f;
- light.dcvDiffuse.b = 1.0f;
- light.dcvSpecular = light.dcvDiffuse;
- light.dvPosition.x = light.dvDirection.x = x;
- light.dvPosition.y = light.dvDirection.y = y;
- light.dvPosition.z = light.dvDirection.z = z;
- light.dvAttenuation0 = 1.0f;
- light.dvRange = D3DLIGHT_RANGE_MAX;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_SetViewMatrix()
-// Desc: Given an eye point, a lookat point, and an up vector, this
-// function builds a 4x4 view matrix.
-//-----------------------------------------------------------------------------
-HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom,
- D3DVECTOR& vAt, D3DVECTOR& vWorldUp )
-{
- // Get the z basis vector, which points straight ahead. This is the
- // difference from the eyepoint to the lookat point.
- D3DVECTOR vView = vAt - vFrom;
-
- FLOAT fLength = Magnitude( vView );
- if( fLength < 1e-6f )
- return E_INVALIDARG;
-
- // Normalize the z basis vector
- vView /= fLength;
-
- // Get the dot product, and calculate the projection of the z basis
- // vector onto the up vector. The projection is the y basis vector.
- FLOAT fDotProduct = DotProduct( vWorldUp, vView );
-
- D3DVECTOR vUp = vWorldUp - fDotProduct * vView;
-
- // If this vector has near-zero length because the input specified a
- // bogus up vector, let's try a default up vector
- if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
- {
- vUp = D3DVECTOR( 0.0f, 1.0f, 0.0f ) - vView.y * vView;
-
- // If we still have near-zero length, resort to a different axis.
- if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
- {
- vUp = D3DVECTOR( 0.0f, 0.0f, 1.0f ) - vView.z * vView;
-
- if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
- return E_INVALIDARG;
- }
- }
-
- // Normalize the y basis vector
- vUp /= fLength;
-
- // The x basis vector is found simply with the cross product of the y
- // and z basis vectors
- D3DVECTOR vRight = CrossProduct( vUp, vView );
-
- // Start building the matrix. The first three rows contains the basis
- // vectors used to rotate the view to point at the lookat point
- D3DUtil_SetIdentityMatrix( mat );
- mat._11 = vRight.x; mat._12 = vUp.x; mat._13 = vView.x;
- mat._21 = vRight.y; mat._22 = vUp.y; mat._23 = vView.y;
- mat._31 = vRight.z; mat._32 = vUp.z; mat._33 = vView.z;
-
- // Do the translation values (rotations are still about the eyepoint)
- mat._41 = - DotProduct( vFrom, vRight );
- mat._42 = - DotProduct( vFrom, vUp );
- mat._43 = - DotProduct( vFrom, vView );
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_SetProjectionMatrix()
-// Desc: Sets the passed in 4x4 matrix to a perpsective projection matrix built
-// from the field-of-view (fov, in y), aspect ratio, near plane (D),
-// and far plane (F). Note that the projection matrix is normalized for
-// element [3][4] to be 1.0. This is performed so that W-based range fog
-// will work correctly.
-//-----------------------------------------------------------------------------
-HRESULT D3DUtil_SetProjectionMatrix( D3DMATRIX& mat, FLOAT fFOV, FLOAT fAspect,
- FLOAT fNearPlane, FLOAT fFarPlane )
-{
- if( fabs(fFarPlane-fNearPlane) < 0.01f )
- return E_INVALIDARG;
- if( fabs(sin(fFOV/2)) < 0.01f )
- return E_INVALIDARG;
-
- FLOAT w = fAspect * ( cosf(fFOV/2)/sinf(fFOV/2) );
- FLOAT h = 1.0f * ( cosf(fFOV/2)/sinf(fFOV/2) );
- FLOAT Q = fFarPlane / ( fFarPlane - fNearPlane );
-
- ZeroMemory( &mat, sizeof(D3DMATRIX) );
- mat._11 = w;
- mat._22 = h;
- mat._33 = Q;
- mat._34 = 1.0f;
- mat._43 = -Q*fNearPlane;
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_SetRotateXMatrix()
-// Desc: Create Rotation matrix about X axis
-//-----------------------------------------------------------------------------
-VOID D3DUtil_SetRotateXMatrix( D3DMATRIX& mat, FLOAT fRads )
-{
- D3DUtil_SetIdentityMatrix( mat );
- mat._22 = cosf( fRads );
- mat._23 = sinf( fRads );
- mat._32 = -sinf( fRads );
- mat._33 = cosf( fRads );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_SetRotateYMatrix()
-// Desc: Create Rotation matrix about Y axis
-//-----------------------------------------------------------------------------
-VOID D3DUtil_SetRotateYMatrix( D3DMATRIX& mat, FLOAT fRads )
-{
- D3DUtil_SetIdentityMatrix( mat );
- mat._11 = cosf( fRads );
- mat._13 = -sinf( fRads );
- mat._31 = sinf( fRads );
- mat._33 = cosf( fRads );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_SetRotateZMatrix()
-// Desc: Create Rotation matrix about Z axis
-//-----------------------------------------------------------------------------
-VOID D3DUtil_SetRotateZMatrix( D3DMATRIX& mat, FLOAT fRads )
-{
- D3DUtil_SetIdentityMatrix( mat );
- mat._11 = cosf( fRads );
- mat._12 = sinf( fRads );
- mat._21 = -sinf( fRads );
- mat._22 = cosf( fRads );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_SetRotationMatrix
-// Desc: Create a Rotation matrix about vector direction
-//-----------------------------------------------------------------------------
-VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir, FLOAT fRads )
-{
- FLOAT fCos = cosf( fRads );
- FLOAT fSin = sinf( fRads );
- D3DVECTOR v = Normalize( vDir );
-
- mat._11 = ( v.x * v.x ) * ( 1.0f - fCos ) + fCos;
- mat._12 = ( v.x * v.y ) * ( 1.0f - fCos ) - (v.z * fSin);
- mat._13 = ( v.x * v.z ) * ( 1.0f - fCos ) + (v.y * fSin);
-
- mat._21 = ( v.y * v.x ) * ( 1.0f - fCos ) + (v.z * fSin);
- mat._22 = ( v.y * v.y ) * ( 1.0f - fCos ) + fCos ;
- mat._23 = ( v.y * v.z ) * ( 1.0f - fCos ) - (v.x * fSin);
-
- mat._31 = ( v.z * v.x ) * ( 1.0f - fCos ) - (v.y * fSin);
- mat._32 = ( v.z * v.y ) * ( 1.0f - fCos ) + (v.x * fSin);
- mat._33 = ( v.z * v.z ) * ( 1.0f - fCos ) + fCos;
-
- mat._14 = mat._24 = mat._34 = 0.0f;
- mat._41 = mat._42 = mat._43 = 0.0f;
- mat._44 = 1.0f;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: _DbgOut()
-// Desc: Outputs a message to the debug stream
-//-----------------------------------------------------------------------------
-HRESULT _DbgOut( TCHAR* strFile, DWORD dwLine, HRESULT hr, TCHAR* strMsg )
-{
- TCHAR buffer[256];
- wsprintf( buffer, _T("%s(%ld): "), strFile, dwLine );
- OutputDebugString( buffer );
- OutputDebugString( strMsg );
-
- if( hr )
- {
- wsprintf( buffer, _T("(hr=%08lx)\n"), hr );
- OutputDebugString( buffer );
- }
-
- OutputDebugString( _T("\n") );
-
- return hr;
-}
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+//-----------------------------------------------------------------------------
+// File: D3DUtil.cpp
+//
+// Desc: Shortcut macros and functions for using DX objects
+//
+//
+// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+#include <math.h>
+#include <stdio.h>
+#include <tchar.h>
+#include "old/d3dutil.h"
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_GetDXSDKMediaPath()
+// Desc: Returns the DirectX SDK media path, as stored in the system registry
+// during the SDK install.
+//-----------------------------------------------------------------------------
+const TCHAR* D3DUtil_GetDXSDKMediaPath()
+{
+ static TCHAR strNull[2] = _T("");
+ static TCHAR strPath[512];
+ HKEY key;
+ DWORD type, size = 512;
+
+ // Open the appropriate registry key
+ LONG result = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ _T("Software\\Microsoft\\DirectX"),
+ 0, KEY_READ, &key );
+ if( ERROR_SUCCESS != result )
+ return strNull;
+
+ result = RegQueryValueEx( key, _T("DXSDK Samples Path"), NULL,
+ &type, (BYTE*)strPath, &size );
+ RegCloseKey( key );
+
+ if( ERROR_SUCCESS != result )
+ return strNull;
+
+ lstrcat( strPath, _T("\\D3DIM\\Media\\") );
+
+ return strPath;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_InitSurfaceDesc()
+// Desc: Helper function called to build a DDSURFACEDESC2 structure,
+// typically before calling CreateSurface() or GetSurfaceDesc()
+//-----------------------------------------------------------------------------
+VOID D3DUtil_InitSurfaceDesc( DDSURFACEDESC2& ddsd, DWORD dwFlags,
+ DWORD dwCaps )
+{
+ ZeroMemory( &ddsd, sizeof(ddsd) );
+ ddsd.dwSize = sizeof(ddsd);
+ ddsd.dwFlags = dwFlags;
+ ddsd.ddsCaps.dwCaps = dwCaps;
+ ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_InitMaterial()
+// Desc: Helper function called to build a D3DMATERIAL7 structure
+//-----------------------------------------------------------------------------
+VOID D3DUtil_InitMaterial( D3DMATERIAL7& mtrl, FLOAT r, FLOAT g, FLOAT b,
+ FLOAT a )
+{
+ ZeroMemory( &mtrl, sizeof(D3DMATERIAL7) );
+ mtrl.dcvDiffuse.r = mtrl.dcvAmbient.r = r;
+ mtrl.dcvDiffuse.g = mtrl.dcvAmbient.g = g;
+ mtrl.dcvDiffuse.b = mtrl.dcvAmbient.b = b;
+ mtrl.dcvDiffuse.a = mtrl.dcvAmbient.a = a;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_InitLight()
+// Desc: Initializes a D3DLIGHT7 structure
+//-----------------------------------------------------------------------------
+VOID D3DUtil_InitLight( D3DLIGHT7& light, D3DLIGHTTYPE ltType,
+ FLOAT x, FLOAT y, FLOAT z )
+{
+ ZeroMemory( &light, sizeof(D3DLIGHT7) );
+ light.dltType = ltType;
+ light.dcvDiffuse.r = 1.0f;
+ light.dcvDiffuse.g = 1.0f;
+ light.dcvDiffuse.b = 1.0f;
+ light.dcvSpecular = light.dcvDiffuse;
+ light.dvPosition.x = light.dvDirection.x = x;
+ light.dvPosition.y = light.dvDirection.y = y;
+ light.dvPosition.z = light.dvDirection.z = z;
+ light.dvAttenuation0 = 1.0f;
+ light.dvRange = D3DLIGHT_RANGE_MAX;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_SetViewMatrix()
+// Desc: Given an eye point, a lookat point, and an up vector, this
+// function builds a 4x4 view matrix.
+//-----------------------------------------------------------------------------
+HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom,
+ D3DVECTOR& vAt, D3DVECTOR& vWorldUp )
+{
+ // Get the z basis vector, which points straight ahead. This is the
+ // difference from the eyepoint to the lookat point.
+ D3DVECTOR vView = vAt - vFrom;
+
+ FLOAT fLength = Magnitude( vView );
+ if( fLength < 1e-6f )
+ return E_INVALIDARG;
+
+ // Normalize the z basis vector
+ vView /= fLength;
+
+ // Get the dot product, and calculate the projection of the z basis
+ // vector onto the up vector. The projection is the y basis vector.
+ FLOAT fDotProduct = DotProduct( vWorldUp, vView );
+
+ D3DVECTOR vUp = vWorldUp - fDotProduct * vView;
+
+ // If this vector has near-zero length because the input specified a
+ // bogus up vector, let's try a default up vector
+ if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
+ {
+ vUp = D3DVECTOR( 0.0f, 1.0f, 0.0f ) - vView.y * vView;
+
+ // If we still have near-zero length, resort to a different axis.
+ if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
+ {
+ vUp = D3DVECTOR( 0.0f, 0.0f, 1.0f ) - vView.z * vView;
+
+ if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
+ return E_INVALIDARG;
+ }
+ }
+
+ // Normalize the y basis vector
+ vUp /= fLength;
+
+ // The x basis vector is found simply with the cross product of the y
+ // and z basis vectors
+ D3DVECTOR vRight = CrossProduct( vUp, vView );
+
+ // Start building the matrix. The first three rows contains the basis
+ // vectors used to rotate the view to point at the lookat point
+ D3DUtil_SetIdentityMatrix( mat );
+ mat._11 = vRight.x; mat._12 = vUp.x; mat._13 = vView.x;
+ mat._21 = vRight.y; mat._22 = vUp.y; mat._23 = vView.y;
+ mat._31 = vRight.z; mat._32 = vUp.z; mat._33 = vView.z;
+
+ // Do the translation values (rotations are still about the eyepoint)
+ mat._41 = - DotProduct( vFrom, vRight );
+ mat._42 = - DotProduct( vFrom, vUp );
+ mat._43 = - DotProduct( vFrom, vView );
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_SetProjectionMatrix()
+// Desc: Sets the passed in 4x4 matrix to a perpsective projection matrix built
+// from the field-of-view (fov, in y), aspect ratio, near plane (D),
+// and far plane (F). Note that the projection matrix is normalized for
+// element [3][4] to be 1.0. This is performed so that W-based range fog
+// will work correctly.
+//-----------------------------------------------------------------------------
+HRESULT D3DUtil_SetProjectionMatrix( D3DMATRIX& mat, FLOAT fFOV, FLOAT fAspect,
+ FLOAT fNearPlane, FLOAT fFarPlane )
+{
+ if( fabs(fFarPlane-fNearPlane) < 0.01f )
+ return E_INVALIDARG;
+ if( fabs(sin(fFOV/2)) < 0.01f )
+ return E_INVALIDARG;
+
+ FLOAT w = fAspect * ( cosf(fFOV/2)/sinf(fFOV/2) );
+ FLOAT h = 1.0f * ( cosf(fFOV/2)/sinf(fFOV/2) );
+ FLOAT Q = fFarPlane / ( fFarPlane - fNearPlane );
+
+ ZeroMemory( &mat, sizeof(D3DMATRIX) );
+ mat._11 = w;
+ mat._22 = h;
+ mat._33 = Q;
+ mat._34 = 1.0f;
+ mat._43 = -Q*fNearPlane;
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_SetRotateXMatrix()
+// Desc: Create Rotation matrix about X axis
+//-----------------------------------------------------------------------------
+VOID D3DUtil_SetRotateXMatrix( D3DMATRIX& mat, FLOAT fRads )
+{
+ D3DUtil_SetIdentityMatrix( mat );
+ mat._22 = cosf( fRads );
+ mat._23 = sinf( fRads );
+ mat._32 = -sinf( fRads );
+ mat._33 = cosf( fRads );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_SetRotateYMatrix()
+// Desc: Create Rotation matrix about Y axis
+//-----------------------------------------------------------------------------
+VOID D3DUtil_SetRotateYMatrix( D3DMATRIX& mat, FLOAT fRads )
+{
+ D3DUtil_SetIdentityMatrix( mat );
+ mat._11 = cosf( fRads );
+ mat._13 = -sinf( fRads );
+ mat._31 = sinf( fRads );
+ mat._33 = cosf( fRads );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_SetRotateZMatrix()
+// Desc: Create Rotation matrix about Z axis
+//-----------------------------------------------------------------------------
+VOID D3DUtil_SetRotateZMatrix( D3DMATRIX& mat, FLOAT fRads )
+{
+ D3DUtil_SetIdentityMatrix( mat );
+ mat._11 = cosf( fRads );
+ mat._12 = sinf( fRads );
+ mat._21 = -sinf( fRads );
+ mat._22 = cosf( fRads );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_SetRotationMatrix
+// Desc: Create a Rotation matrix about vector direction
+//-----------------------------------------------------------------------------
+VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir, FLOAT fRads )
+{
+ FLOAT fCos = cosf( fRads );
+ FLOAT fSin = sinf( fRads );
+ D3DVECTOR v = Normalize( vDir );
+
+ mat._11 = ( v.x * v.x ) * ( 1.0f - fCos ) + fCos;
+ mat._12 = ( v.x * v.y ) * ( 1.0f - fCos ) - (v.z * fSin);
+ mat._13 = ( v.x * v.z ) * ( 1.0f - fCos ) + (v.y * fSin);
+
+ mat._21 = ( v.y * v.x ) * ( 1.0f - fCos ) + (v.z * fSin);
+ mat._22 = ( v.y * v.y ) * ( 1.0f - fCos ) + fCos ;
+ mat._23 = ( v.y * v.z ) * ( 1.0f - fCos ) - (v.x * fSin);
+
+ mat._31 = ( v.z * v.x ) * ( 1.0f - fCos ) - (v.y * fSin);
+ mat._32 = ( v.z * v.y ) * ( 1.0f - fCos ) + (v.x * fSin);
+ mat._33 = ( v.z * v.z ) * ( 1.0f - fCos ) + fCos;
+
+ mat._14 = mat._24 = mat._34 = 0.0f;
+ mat._41 = mat._42 = mat._43 = 0.0f;
+ mat._44 = 1.0f;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: _DbgOut()
+// Desc: Outputs a message to the debug stream
+//-----------------------------------------------------------------------------
+HRESULT _DbgOut( TCHAR* strFile, DWORD dwLine, HRESULT hr, TCHAR* strMsg )
+{
+ TCHAR buffer[256];
+ wsprintf( buffer, _T("%s(%ld): "), strFile, dwLine );
+ OutputDebugString( buffer );
+ OutputDebugString( strMsg );
+
+ if( hr )
+ {
+ wsprintf( buffer, _T("(hr=%08lx)\n"), hr );
+ OutputDebugString( buffer );
+ }
+
+ OutputDebugString( _T("\n") );
+
+ return hr;
+}
+
+
+
diff --git a/src/old/d3dutil.h b/src/old/d3dutil.h
index 8fe88c9..369c7db 100644
--- a/src/old/d3dutil.h
+++ b/src/old/d3dutil.h
@@ -1,113 +1,113 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-//-----------------------------------------------------------------------------
-// File: D3DUtil.h
-//
-// Desc: Helper functions and typing shortcuts for Direct3D programming.
-//
-// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-
-#pragma once
-
-#include <ddraw.h>
-#include <d3d.h>
-
-
-
-
-//-----------------------------------------------------------------------------
-// Miscellaneous helper functions
-//-----------------------------------------------------------------------------
-const TCHAR* D3DUtil_GetDXSDKMediaPath();
-
-#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
-#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
-
-
-
-
-//-----------------------------------------------------------------------------
-// Short cut functions for creating and using DX structures
-//-----------------------------------------------------------------------------
-VOID D3DUtil_InitDeviceDesc( D3DDEVICEDESC7& ddDevDesc );
-VOID D3DUtil_InitSurfaceDesc( DDSURFACEDESC2& ddsd, DWORD dwFlags=0,
- DWORD dwCaps=0 );
-VOID D3DUtil_InitMaterial( D3DMATERIAL7& mtrl, FLOAT r=0.0f, FLOAT g=0.0f,
- FLOAT b=0.0f, FLOAT a=1.0f );
-VOID D3DUtil_InitLight( D3DLIGHT7& light, D3DLIGHTTYPE ltType,
- FLOAT x=0.0f, FLOAT y=0.0f, FLOAT z=0.0f );
-
-
-
-
-//-----------------------------------------------------------------------------
-// D3D Matrix functions. For performance reasons, some functions are inline.
-//-----------------------------------------------------------------------------
-HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom,
- D3DVECTOR& vAt, D3DVECTOR& vUp );
-HRESULT D3DUtil_SetProjectionMatrix( D3DMATRIX& mat, FLOAT fFOV = 1.570795f,
- FLOAT fAspect = 1.0f,
- FLOAT fNearPlane = 1.0f,
- FLOAT fFarPlane = 1000.0f );
-
-inline VOID D3DUtil_SetIdentityMatrix( D3DMATRIX& m )
-{
- m._12 = m._13 = m._14 = m._21 = m._23 = m._24 = 0.0f;
- m._31 = m._32 = m._34 = m._41 = m._42 = m._43 = 0.0f;
- m._11 = m._22 = m._33 = m._44 = 1.0f;
-}
-
-inline VOID D3DUtil_SetTranslateMatrix( D3DMATRIX& m, FLOAT tx, FLOAT ty,
- FLOAT tz )
-{ D3DUtil_SetIdentityMatrix( m ); m._41 = tx; m._42 = ty; m._43 = tz; }
-
-inline VOID D3DUtil_SetTranslateMatrix( D3DMATRIX& m, D3DVECTOR& v )
-{ D3DUtil_SetTranslateMatrix( m, v.x, v.y, v.z ); }
-
-inline VOID D3DUtil_SetScaleMatrix( D3DMATRIX& m, FLOAT sx, FLOAT sy,
- FLOAT sz )
-{ D3DUtil_SetIdentityMatrix( m ); m._11 = sx; m._22 = sy; m._33 = sz; }
-
-inline VOID SetScaleMatrix( D3DMATRIX& m, D3DVECTOR& v )
-{ D3DUtil_SetScaleMatrix( m, v.x, v.y, v.z ); }
-
-VOID D3DUtil_SetRotateXMatrix( D3DMATRIX& mat, FLOAT fRads );
-VOID D3DUtil_SetRotateYMatrix( D3DMATRIX& mat, FLOAT fRads );
-VOID D3DUtil_SetRotateZMatrix( D3DMATRIX& mat, FLOAT fRads );
-VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir,
- FLOAT fRads );
-
-
-
-
-//-----------------------------------------------------------------------------
-// Debug printing support
-//-----------------------------------------------------------------------------
-
-HRESULT _DbgOut( TCHAR*, DWORD, HRESULT, TCHAR* );
-
-#if defined(DEBUG) | defined(_DEBUG)
- #define DEBUG_MSG(str) _DbgOut( __FILE__, (DWORD)__LINE__, 0, str )
- #define DEBUG_ERR(hr,str) _DbgOut( __FILE__, (DWORD)__LINE__, hr, str )
-#else
- #define DEBUG_MSG(str) (0L)
- #define DEBUG_ERR(hr,str) (hr)
-#endif
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+//-----------------------------------------------------------------------------
+// File: D3DUtil.h
+//
+// Desc: Helper functions and typing shortcuts for Direct3D programming.
+//
+// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+#include <ddraw.h>
+#include <d3d.h>
+
+
+
+
+//-----------------------------------------------------------------------------
+// Miscellaneous helper functions
+//-----------------------------------------------------------------------------
+const TCHAR* D3DUtil_GetDXSDKMediaPath();
+
+#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
+#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
+
+
+
+
+//-----------------------------------------------------------------------------
+// Short cut functions for creating and using DX structures
+//-----------------------------------------------------------------------------
+VOID D3DUtil_InitDeviceDesc( D3DDEVICEDESC7& ddDevDesc );
+VOID D3DUtil_InitSurfaceDesc( DDSURFACEDESC2& ddsd, DWORD dwFlags=0,
+ DWORD dwCaps=0 );
+VOID D3DUtil_InitMaterial( D3DMATERIAL7& mtrl, FLOAT r=0.0f, FLOAT g=0.0f,
+ FLOAT b=0.0f, FLOAT a=1.0f );
+VOID D3DUtil_InitLight( D3DLIGHT7& light, D3DLIGHTTYPE ltType,
+ FLOAT x=0.0f, FLOAT y=0.0f, FLOAT z=0.0f );
+
+
+
+
+//-----------------------------------------------------------------------------
+// D3D Matrix functions. For performance reasons, some functions are inline.
+//-----------------------------------------------------------------------------
+HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom,
+ D3DVECTOR& vAt, D3DVECTOR& vUp );
+HRESULT D3DUtil_SetProjectionMatrix( D3DMATRIX& mat, FLOAT fFOV = 1.570795f,
+ FLOAT fAspect = 1.0f,
+ FLOAT fNearPlane = 1.0f,
+ FLOAT fFarPlane = 1000.0f );
+
+inline VOID D3DUtil_SetIdentityMatrix( D3DMATRIX& m )
+{
+ m._12 = m._13 = m._14 = m._21 = m._23 = m._24 = 0.0f;
+ m._31 = m._32 = m._34 = m._41 = m._42 = m._43 = 0.0f;
+ m._11 = m._22 = m._33 = m._44 = 1.0f;
+}
+
+inline VOID D3DUtil_SetTranslateMatrix( D3DMATRIX& m, FLOAT tx, FLOAT ty,
+ FLOAT tz )
+{ D3DUtil_SetIdentityMatrix( m ); m._41 = tx; m._42 = ty; m._43 = tz; }
+
+inline VOID D3DUtil_SetTranslateMatrix( D3DMATRIX& m, D3DVECTOR& v )
+{ D3DUtil_SetTranslateMatrix( m, v.x, v.y, v.z ); }
+
+inline VOID D3DUtil_SetScaleMatrix( D3DMATRIX& m, FLOAT sx, FLOAT sy,
+ FLOAT sz )
+{ D3DUtil_SetIdentityMatrix( m ); m._11 = sx; m._22 = sy; m._33 = sz; }
+
+inline VOID SetScaleMatrix( D3DMATRIX& m, D3DVECTOR& v )
+{ D3DUtil_SetScaleMatrix( m, v.x, v.y, v.z ); }
+
+VOID D3DUtil_SetRotateXMatrix( D3DMATRIX& mat, FLOAT fRads );
+VOID D3DUtil_SetRotateYMatrix( D3DMATRIX& mat, FLOAT fRads );
+VOID D3DUtil_SetRotateZMatrix( D3DMATRIX& mat, FLOAT fRads );
+VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir,
+ FLOAT fRads );
+
+
+
+
+//-----------------------------------------------------------------------------
+// Debug printing support
+//-----------------------------------------------------------------------------
+
+HRESULT _DbgOut( TCHAR*, DWORD, HRESULT, TCHAR* );
+
+#if defined(DEBUG) | defined(_DEBUG)
+ #define DEBUG_MSG(str) _DbgOut( __FILE__, (DWORD)__LINE__, 0, str )
+ #define DEBUG_ERR(hr,str) _DbgOut( __FILE__, (DWORD)__LINE__, hr, str )
+#else
+ #define DEBUG_MSG(str) (0L)
+ #define DEBUG_ERR(hr,str) (hr)
+#endif
+
+
+
diff --git a/src/old/joystick.cpp b/src/old/joystick.cpp
index c08a252..3415047 100644
--- a/src/old/joystick.cpp
+++ b/src/old/joystick.cpp
@@ -1,244 +1,244 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// joystick.cpp
-
-#define DIRECTINPUT_VERSION 0x0700
-
-#include <windows.h>
-#include <dinput.h>
-#include <stdio.h>
-
-#include "old/joystick.h"
-
-
-
-
-// Global variables.
-
-LPDIRECTINPUT7 g_pDI = NULL;
-LPDIRECTINPUTDEVICE2 g_pJoystick = NULL;
-DIDEVCAPS g_diDevCaps;
-
-
-
-
-
-// Called once for each enumerated joystick. If we find one, create a
-// device interface on it so we can play with it.
-
-bool CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance,
- VOID* pContext )
-{
- HRESULT hr;
-
- // Obtain an interface to the enumerated joystick.
- hr = g_pDI->CreateDeviceEx( pdidInstance->guidInstance, IID_IDirectInputDevice2,
- (VOID**)&g_pJoystick, NULL );
-
- // If it failed, then we can't use this joystick. (Maybe the user unplugged
- // it while we were in the middle of enumerating it.)
- if( FAILED(hr) )
- return DIENUM_CONTINUE;
-
-
- // Stop enumeration. Note: we're just taking the first joystick we get. You
- // could store all the enumerated joysticks and let the user pick.
- return DIENUM_STOP;
-}
-
-
-// Callback function for enumerating the axes on a joystick.
-
-bool CALLBACK EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
- VOID* pContext )
-{
- DIPROPRANGE diprg;
- diprg.diph.dwSize = sizeof(DIPROPRANGE);
- diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
- diprg.diph.dwHow = DIPH_BYOFFSET;
- diprg.diph.dwObj = pdidoi->dwOfs; // Specify the enumerated axis
- diprg.lMin = -1000;
- diprg.lMax = +1000;
-
- // Set the range for the axis
- if( FAILED( g_pJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) )
- return DIENUM_STOP;
-
-#ifndef __MINGW32__ // FIXME Doesn't work under MinGW
- // Set the UI to reflect what axes the joystick supports
- switch( pdidoi->dwOfs )
- {
- case DIJOFS_X:
- OutputDebugString("EnumAxesCallback -x\n");
- break;
- case DIJOFS_Y:
- OutputDebugString("EnumAxesCallback -y\n");
- break;
- case DIJOFS_Z:
- OutputDebugString("EnumAxesCallback -z\n");
- break;
- case DIJOFS_RX:
- OutputDebugString("EnumAxesCallback -rx\n");
- break;
- case DIJOFS_RY:
- OutputDebugString("EnumAxesCallback -ry\n");
- break;
- case DIJOFS_RZ:
- OutputDebugString("EnumAxesCallback -rz\n");
- break;
- case DIJOFS_SLIDER(0):
- OutputDebugString("EnumAxesCallback -s0\n");
- break;
- case DIJOFS_SLIDER(1):
- OutputDebugString("EnumAxesCallback -s1\n");
- break;
- }
-#endif
-
- return DIENUM_CONTINUE;
-}
-
-
-// Initialize the DirectInput variables.
-
-bool InitDirectInput(HINSTANCE hInst, HWND hWnd)
-{
- HRESULT hr;
-
- // Register with the DirectInput subsystem and get a pointer
- // to a IDirectInput interface we can use.
-#ifndef __MINGW32__ // FIXME Doesn't work under MinGW
- hr = DirectInputCreateEx( hInst, DIRECTINPUT_VERSION,IID_IDirectInput7, (LPVOID*)&g_pDI, NULL );
- if( FAILED(hr) ) return false;
-#else
- return false;
-#endif
-
- // Look for a simple joystick we can use for this sample program.
- hr = g_pDI->EnumDevices( DIDEVTYPE_JOYSTICK, EnumJoysticksCallback,
- NULL, DIEDFL_ATTACHEDONLY );
- if( FAILED(hr) ) return false;
-
- // Make sure we got a joystick
- if( NULL == g_pJoystick )
- {
-//? MessageBox( NULL, "Joystick not found", "DInput Sample",
-//? MB_ICONERROR | MB_OK );
- return false;
- }
-
- // Set the data format to "simple joystick" - a predefined data format
- //
- // A data format specifies which controls on a device we are interested in,
- // and how they should be reported. This tells DInput that we will be
- // passing a DIJOYSTATE structure to IDirectInputDevice::GetDeviceState().
- hr = g_pJoystick->SetDataFormat( &c_dfDIJoystick );
- if( FAILED(hr) ) return false;
-
- // Set the cooperative level to let DInput know how this device should
- // interact with the system and with other DInput applications.
- hr = g_pJoystick->SetCooperativeLevel( hWnd, DISCL_EXCLUSIVE|DISCL_FOREGROUND );
- if( FAILED(hr) ) return false;
-
- // Determine how many axis the joystick has (so we don't error out setting
- // properties for unavailable axis)
- g_diDevCaps.dwSize = sizeof(DIDEVCAPS);
- hr = g_pJoystick->GetCapabilities(&g_diDevCaps);
- if( FAILED(hr) ) return false;
-
-
- // Enumerate the axes of the joyctick and set the range of each axis. Note:
- // we could just use the defaults, but we're just trying to show an example
- // of enumerating device objects (axes, buttons, etc.).
- g_pJoystick->EnumObjects( EnumAxesCallback, (VOID*)g_pJoystick, DIDFT_AXIS );
-
- return true;
-}
-
-// Acquire or unacquire the keyboard, depending on if the app is active
-// Input device must be acquired before the GetDeviceState is called.
-
-bool SetAcquire(bool bActive)
-{
- if ( g_pJoystick )
- {
- if( bActive ) g_pJoystick->Acquire();
- else g_pJoystick->Unacquire();
- }
- return true;
-}
-
-
-// Get the input device's state and display it.
-
-bool UpdateInputState( DIJOYSTATE &js )
-{
- HRESULT hr;
-
- if ( g_pJoystick )
- {
- do
- {
- // Poll the device to read the current state
- hr = g_pJoystick->Poll();
- if ( FAILED(hr) ) return false;
-
- // Get the input's device state
- hr = g_pJoystick->GetDeviceState( sizeof(DIJOYSTATE), &js );
-
- if( hr == DIERR_INPUTLOST )
- {
- // DInput is telling us that the input stream has been
- // interrupted. We aren't tracking any state between polls, so
- // we don't have any special reset that needs to be done. We
- // just re-acquire and try again.
- hr = g_pJoystick->Acquire();
- if ( FAILED(hr) ) return false;
- }
- }
- while ( DIERR_INPUTLOST == hr );
- if ( FAILED(hr) ) return false;
- }
- return true;
-}
-
-
-// Initialize the DirectInput variables.
-
-bool FreeDirectInput()
-{
- // Unacquire and release any DirectInputDevice objects.
- if( NULL != g_pJoystick )
- {
- // Unacquire the device one last time just in case
- // the app tried to exit while the device is still acquired.
- g_pJoystick->Unacquire();
- g_pJoystick->Release();
- g_pJoystick = NULL;
- }
-
-
- // Release any DirectInput objects.
- if( g_pDI )
- {
- g_pDI->Release();
- g_pDI = NULL;
- }
-
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// joystick.cpp
+
+#define DIRECTINPUT_VERSION 0x0700
+
+#include <windows.h>
+#include <dinput.h>
+#include <stdio.h>
+
+#include "old/joystick.h"
+
+
+
+
+// Global variables.
+
+LPDIRECTINPUT7 g_pDI = NULL;
+LPDIRECTINPUTDEVICE2 g_pJoystick = NULL;
+DIDEVCAPS g_diDevCaps;
+
+
+
+
+
+// Called once for each enumerated joystick. If we find one, create a
+// device interface on it so we can play with it.
+
+bool CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance,
+ VOID* pContext )
+{
+ HRESULT hr;
+
+ // Obtain an interface to the enumerated joystick.
+ hr = g_pDI->CreateDeviceEx( pdidInstance->guidInstance, IID_IDirectInputDevice2,
+ (VOID**)&g_pJoystick, NULL );
+
+ // If it failed, then we can't use this joystick. (Maybe the user unplugged
+ // it while we were in the middle of enumerating it.)
+ if( FAILED(hr) )
+ return DIENUM_CONTINUE;
+
+
+ // Stop enumeration. Note: we're just taking the first joystick we get. You
+ // could store all the enumerated joysticks and let the user pick.
+ return DIENUM_STOP;
+}
+
+
+// Callback function for enumerating the axes on a joystick.
+
+bool CALLBACK EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
+ VOID* pContext )
+{
+ DIPROPRANGE diprg;
+ diprg.diph.dwSize = sizeof(DIPROPRANGE);
+ diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+ diprg.diph.dwHow = DIPH_BYOFFSET;
+ diprg.diph.dwObj = pdidoi->dwOfs; // Specify the enumerated axis
+ diprg.lMin = -1000;
+ diprg.lMax = +1000;
+
+ // Set the range for the axis
+ if( FAILED( g_pJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) )
+ return DIENUM_STOP;
+
+#ifndef __MINGW32__ // FIXME Doesn't work under MinGW
+ // Set the UI to reflect what axes the joystick supports
+ switch( pdidoi->dwOfs )
+ {
+ case DIJOFS_X:
+ OutputDebugString("EnumAxesCallback -x\n");
+ break;
+ case DIJOFS_Y:
+ OutputDebugString("EnumAxesCallback -y\n");
+ break;
+ case DIJOFS_Z:
+ OutputDebugString("EnumAxesCallback -z\n");
+ break;
+ case DIJOFS_RX:
+ OutputDebugString("EnumAxesCallback -rx\n");
+ break;
+ case DIJOFS_RY:
+ OutputDebugString("EnumAxesCallback -ry\n");
+ break;
+ case DIJOFS_RZ:
+ OutputDebugString("EnumAxesCallback -rz\n");
+ break;
+ case DIJOFS_SLIDER(0):
+ OutputDebugString("EnumAxesCallback -s0\n");
+ break;
+ case DIJOFS_SLIDER(1):
+ OutputDebugString("EnumAxesCallback -s1\n");
+ break;
+ }
+#endif
+
+ return DIENUM_CONTINUE;
+}
+
+
+// Initialize the DirectInput variables.
+
+bool InitDirectInput(HINSTANCE hInst, HWND hWnd)
+{
+ HRESULT hr;
+
+ // Register with the DirectInput subsystem and get a pointer
+ // to a IDirectInput interface we can use.
+#ifndef __MINGW32__ // FIXME Doesn't work under MinGW
+ hr = DirectInputCreateEx( hInst, DIRECTINPUT_VERSION,IID_IDirectInput7, (LPVOID*)&g_pDI, NULL );
+ if( FAILED(hr) ) return false;
+#else
+ return false;
+#endif
+
+ // Look for a simple joystick we can use for this sample program.
+ hr = g_pDI->EnumDevices( DIDEVTYPE_JOYSTICK, EnumJoysticksCallback,
+ NULL, DIEDFL_ATTACHEDONLY );
+ if( FAILED(hr) ) return false;
+
+ // Make sure we got a joystick
+ if( NULL == g_pJoystick )
+ {
+//? MessageBox( NULL, "Joystick not found", "DInput Sample",
+//? MB_ICONERROR | MB_OK );
+ return false;
+ }
+
+ // Set the data format to "simple joystick" - a predefined data format
+ //
+ // A data format specifies which controls on a device we are interested in,
+ // and how they should be reported. This tells DInput that we will be
+ // passing a DIJOYSTATE structure to IDirectInputDevice::GetDeviceState().
+ hr = g_pJoystick->SetDataFormat( &c_dfDIJoystick );
+ if( FAILED(hr) ) return false;
+
+ // Set the cooperative level to let DInput know how this device should
+ // interact with the system and with other DInput applications.
+ hr = g_pJoystick->SetCooperativeLevel( hWnd, DISCL_EXCLUSIVE|DISCL_FOREGROUND );
+ if( FAILED(hr) ) return false;
+
+ // Determine how many axis the joystick has (so we don't error out setting
+ // properties for unavailable axis)
+ g_diDevCaps.dwSize = sizeof(DIDEVCAPS);
+ hr = g_pJoystick->GetCapabilities(&g_diDevCaps);
+ if( FAILED(hr) ) return false;
+
+
+ // Enumerate the axes of the joyctick and set the range of each axis. Note:
+ // we could just use the defaults, but we're just trying to show an example
+ // of enumerating device objects (axes, buttons, etc.).
+ g_pJoystick->EnumObjects( EnumAxesCallback, (VOID*)g_pJoystick, DIDFT_AXIS );
+
+ return true;
+}
+
+// Acquire or unacquire the keyboard, depending on if the app is active
+// Input device must be acquired before the GetDeviceState is called.
+
+bool SetAcquire(bool bActive)
+{
+ if ( g_pJoystick )
+ {
+ if( bActive ) g_pJoystick->Acquire();
+ else g_pJoystick->Unacquire();
+ }
+ return true;
+}
+
+
+// Get the input device's state and display it.
+
+bool UpdateInputState( DIJOYSTATE &js )
+{
+ HRESULT hr;
+
+ if ( g_pJoystick )
+ {
+ do
+ {
+ // Poll the device to read the current state
+ hr = g_pJoystick->Poll();
+ if ( FAILED(hr) ) return false;
+
+ // Get the input's device state
+ hr = g_pJoystick->GetDeviceState( sizeof(DIJOYSTATE), &js );
+
+ if( hr == DIERR_INPUTLOST )
+ {
+ // DInput is telling us that the input stream has been
+ // interrupted. We aren't tracking any state between polls, so
+ // we don't have any special reset that needs to be done. We
+ // just re-acquire and try again.
+ hr = g_pJoystick->Acquire();
+ if ( FAILED(hr) ) return false;
+ }
+ }
+ while ( DIERR_INPUTLOST == hr );
+ if ( FAILED(hr) ) return false;
+ }
+ return true;
+}
+
+
+// Initialize the DirectInput variables.
+
+bool FreeDirectInput()
+{
+ // Unacquire and release any DirectInputDevice objects.
+ if( NULL != g_pJoystick )
+ {
+ // Unacquire the device one last time just in case
+ // the app tried to exit while the device is still acquired.
+ g_pJoystick->Unacquire();
+ g_pJoystick->Release();
+ g_pJoystick = NULL;
+ }
+
+
+ // Release any DirectInput objects.
+ if( g_pDI )
+ {
+ g_pDI->Release();
+ g_pDI = NULL;
+ }
+
+ return true;
+}
+
diff --git a/src/old/joystick.h b/src/old/joystick.h
index 44fd1c3..5b4e517 100644
--- a/src/old/joystick.h
+++ b/src/old/joystick.h
@@ -1,27 +1,27 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// joystick.h
-
-#pragma once
-
-
-extern bool InitDirectInput(HINSTANCE hInst, HWND hWnd);
-extern bool SetAcquire(bool bActive);
-extern bool UpdateInputState(DIJOYSTATE &js);
-extern bool FreeDirectInput();
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// joystick.h
+
+#pragma once
+
+
+extern bool InitDirectInput(HINSTANCE hInst, HWND hWnd);
+extern bool SetAcquire(bool bActive);
+extern bool UpdateInputState(DIJOYSTATE &js);
+extern bool FreeDirectInput();
+
+
diff --git a/src/old/light.cpp b/src/old/light.cpp
index 0589141..811a824 100644
--- a/src/old/light.cpp
+++ b/src/old/light.cpp
@@ -1,504 +1,504 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// light.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "math/conv.h"
-#include "old/d3dengine.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "old/light.h"
-
-
-
-
-
-// Initializes a progression.
-
-void ProgInit(LightProg &p, float value)
-{
- p.starting = value;
- p.ending = value;
- p.current = value;
- p.progress = 0.0f;
- p.speed = 100.0f;
-}
-
-// Makes evolve a progression.
-
-void ProgFrame(LightProg &p, float rTime)
-{
- if ( p.speed < 100.0f )
- {
- if ( p.progress < 1.0f )
- {
- p.progress += p.speed*rTime;
- if ( p.progress > 1.0f )
- {
- p.progress = 1.0f;
- }
- }
-
- p.current = (p.ending-p.starting)*p.progress + p.starting;
- }
- else
- {
- p.current = p.ending;
- }
-}
-
-// Change the current value.
-
-void ProgSet(LightProg &p, float value)
-{
- p.starting = p.current;
- p.ending = value;
- p.progress = 0.0f;
-}
-
-
-
-
-
-// Object's constructor.
-
-CLight::CLight(CInstanceManager* iMan, CD3DEngine* engine)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_LIGHT, this);
-
- m_pD3DDevice = 0;
- m_engine = engine;
-
- m_lightUsed = 0;
- m_lightTable = (Light*)malloc(sizeof(Light)*D3DMAXLIGHT);
- ZeroMemory(m_lightTable, sizeof(Light)*D3DMAXLIGHT);
-
- m_time = 0.0f;
-}
-
-// Object's destructor.
-
-CLight::~CLight()
-{
- free(m_lightTable);
- m_iMan->DeleteInstance(CLASS_LIGHT, this);
-}
-
-
-void CLight::SetD3DDevice(LPDIRECT3DDEVICE7 device)
-{
- m_pD3DDevice = device;
-}
-
-
-// Removes all the lights.
-
-void CLight::FlushLight()
-{
- int i;
-
- for ( i=0 ; i<D3DMAXLIGHT ; i++ )
- {
- m_lightTable[i].bUsed = false;
- m_pD3DDevice->LightEnable(i, false);
- }
- m_lightUsed = 0;
-}
-
-
-// Creates a new light. Returns its rank or -1 on error.
-
-int CLight::CreateLight()
-{
- int i;
-
- for ( i=0 ; i<D3DMAXLIGHT ; i++ )
- {
- if ( m_lightTable[i].bUsed == false )
- {
- ZeroMemory(&m_lightTable[i], sizeof(Light));
- m_lightTable[i].bUsed = true;
- m_lightTable[i].bEnable = true;
-
- m_lightTable[i].incluType = TYPENULL;
- m_lightTable[i].excluType = TYPENULL;
-
- m_lightTable[i].light.dltType = D3DLIGHT_DIRECTIONAL;
- m_lightTable[i].light.dcvDiffuse.r = 0.5f;
- m_lightTable[i].light.dcvDiffuse.g = 0.5f;
- m_lightTable[i].light.dcvDiffuse.b = 0.5f; // white
- m_lightTable[i].light.dvPosition.x =-100.0f;
- m_lightTable[i].light.dvPosition.y = 100.0f;
- m_lightTable[i].light.dvPosition.z =-100.0f;
- m_lightTable[i].light.dvDirection.x = 1.0f;
- m_lightTable[i].light.dvDirection.y = -1.0f;
- m_lightTable[i].light.dvDirection.z = 1.0f;
-
- ProgInit(m_lightTable[i].intensity, 1.0f); // maximum
- ProgInit(m_lightTable[i].colorRed, 0.5f);
- ProgInit(m_lightTable[i].colorGreen, 0.5f);
- ProgInit(m_lightTable[i].colorBlue, 0.5f); // gray
-
- if ( m_lightUsed < i+1 )
- {
- m_lightUsed = i+1;
- }
- return i;
- }
- }
- return -1;
-}
-
-// Deletes a light.
-
-bool CLight::DeleteLight(int lightRank)
-{
- int i;
-
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].bUsed = false;
- m_pD3DDevice->LightEnable(lightRank, false);
-
- m_lightUsed = 0;
- for ( i=0 ; i<D3DMAXLIGHT ; i++ )
- {
- if ( m_lightTable[i].bUsed == true )
- {
- m_lightUsed = i+1;
- }
- }
-
- return true;
-}
-
-
-// Specifies a light.
-
-bool CLight::SetLight(int lightRank, const D3DLIGHT7 &light)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].light = light;
-
- ProgInit(m_lightTable[lightRank].colorRed, m_lightTable[lightRank].light.dcvDiffuse.r);
- ProgInit(m_lightTable[lightRank].colorGreen, m_lightTable[lightRank].light.dcvDiffuse.g);
- ProgInit(m_lightTable[lightRank].colorBlue, m_lightTable[lightRank].light.dcvDiffuse.b);
-
- return true;
-}
-
-// Gives the specifications of a light.
-
-bool CLight::GetLight(int lightRank, D3DLIGHT7 &light)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- light = m_lightTable[lightRank].light;
- return true;
-}
-
-
-// Lights up or put out a light.
-
-bool CLight::LightEnable(int lightRank, bool bEnable)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].bEnable = bEnable;
- return true;
-}
-
-
-// Specifies the type (TYPE *) items included in this light.
-// This light does not light up so that this type of objects.
-
-bool CLight::SetLightIncluType(int lightRank, D3DTypeObj type)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].incluType = type;
- return true;
-}
-
-// Specifies the type (TYPE *) items excluded by this light.
-// This light does not illuminate then ever these objects.
-
-bool CLight::SetLightExcluType(int lightRank, D3DTypeObj type)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].excluType = type;
- return true;
-}
-
-
-// Management of the position of the light.
-
-bool CLight::SetLightPos(int lightRank, Math::Vector pos)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].light.dvPosition = VEC_TO_D3DVEC(pos);
- return true;
-}
-
-Math::Vector CLight::RetLightPos(int lightRank)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return Math::Vector(0.0f, 0.0f, 0.0f);
-
- return D3DVEC_TO_VEC(m_lightTable[lightRank].light.dvPosition);
-}
-
-
-// Management direction of the light.
-
-bool CLight::SetLightDir(int lightRank, Math::Vector dir)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].light.dvDirection = VEC_TO_D3DVEC(dir);
- return true;
-}
-
-Math::Vector CLight::RetLightDir(int lightRank)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return Math::Vector(0.0f, 0.0f, 0.0f);
-
- return D3DVEC_TO_VEC(m_lightTable[lightRank].light.dvDirection);
-}
-
-
-// Specifies the rate of change.
-
-bool CLight::SetLightIntensitySpeed(int lightRank, float speed)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].intensity.speed = speed;
- return true;
-}
-
-// Management of the intensity of light.
-
-bool CLight::SetLightIntensity(int lightRank, float value)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- ProgSet(m_lightTable[lightRank].intensity, value);
- return true;
-}
-
-float CLight::RetLightIntensity(int lightRank)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return 0.0f;
-
- return m_lightTable[lightRank].intensity.current;
-}
-
-
-// Specifies the rate of change.
-
-bool CLight::SetLightColorSpeed(int lightRank, float speed)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].colorRed.speed = speed;
- m_lightTable[lightRank].colorGreen.speed = speed;
- m_lightTable[lightRank].colorBlue.speed = speed;
- return true;
-}
-
-// Color management for light.
-
-bool CLight::SetLightColor(int lightRank, D3DCOLORVALUE color)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- ProgSet(m_lightTable[lightRank].colorRed, color.r);
- ProgSet(m_lightTable[lightRank].colorGreen, color.g);
- ProgSet(m_lightTable[lightRank].colorBlue, color.b);
- return true;
-}
-
-D3DCOLORVALUE CLight::RetLightColor(int lightRank)
-{
- D3DCOLORVALUE color;
-
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT )
- {
- color.r = 0.5f;
- color.g = 0.5f;
- color.b = 0.5f;
- color.a = 0.5f;
- return color;
- }
-
- color.r = m_lightTable[lightRank].colorRed.current;
- color.g = m_lightTable[lightRank].colorGreen.current;
- color.b = m_lightTable[lightRank].colorBlue.current;
- return color;
-}
-
-
-// Adjusts the color of all lights.
-
-void CLight::AdaptLightColor(D3DCOLORVALUE color, float factor)
-{
- D3DCOLORVALUE value;
- int i;
-
- for ( i=0 ; i<m_lightUsed ; i++ )
- {
- if ( m_lightTable[i].bUsed == false ) continue;
-
- value.r = m_lightTable[i].colorRed.current;
- value.g = m_lightTable[i].colorGreen.current;
- value.b = m_lightTable[i].colorBlue.current;
-
- value.r += color.r*factor;
- value.g += color.g*factor;
- value.b += color.b*factor;
-
- ProgInit(m_lightTable[i].colorRed, value.r);
- ProgInit(m_lightTable[i].colorGreen, value.g);
- ProgInit(m_lightTable[i].colorBlue, value.b);
- }
-
- LightUpdate();
-}
-
-
-
-// Makes all the lights evolve.
-
-void CLight::FrameLight(float rTime)
-{
- Math::Vector dir;
- float angle;
- int i;
-
- if ( m_engine->RetPause() ) return;
-
- m_time += rTime;
-
- for ( i=0 ; i<m_lightUsed ; i++ )
- {
- if ( m_lightTable[i].bUsed == false ) continue;
-
- ProgFrame(m_lightTable[i].intensity, rTime);
- ProgFrame(m_lightTable[i].colorRed, rTime);
- ProgFrame(m_lightTable[i].colorGreen, rTime);
- ProgFrame(m_lightTable[i].colorBlue, rTime);
-
- if ( m_lightTable[i].incluType == TYPEQUARTZ )
- {
- m_lightTable[i].light.dvDirection.x = sinf((m_time+i*Math::PI*0.5f)*1.0f);
- m_lightTable[i].light.dvDirection.z = cosf((m_time+i*Math::PI*0.5f)*1.1f);
- m_lightTable[i].light.dvDirection.y = -1.0f+cosf((m_time+i*Math::PI*0.5f)*2.7f)*0.5f;
- }
-
- if ( m_lightTable[i].incluType == TYPEMETAL )
- {
- dir = m_engine->RetEyePt()-m_engine->RetLookatPt();
- angle = Math::RotateAngle(dir.x, dir.z);
- angle += Math::PI*0.5f*i;
- m_lightTable[i].light.dvDirection.x = sinf(angle*2.0f);
- m_lightTable[i].light.dvDirection.z = cosf(angle*2.0f);
- }
- }
-}
-
-
-// Updates all the lights.
-
-void CLight::LightUpdate()
-{
- bool bEnable;
- float value;
- int i;
-
- for ( i=0 ; i<m_lightUsed ; i++ )
- {
- if ( m_lightTable[i].bUsed == false ) continue;
-
- bEnable = m_lightTable[i].bEnable;
- if ( m_lightTable[i].intensity.current == 0.0f ) bEnable = false;
-
- if ( bEnable )
- {
- value = m_lightTable[i].colorRed.current * m_lightTable[i].intensity.current;
- m_lightTable[i].light.dcvDiffuse.r = value;
-
- value = m_lightTable[i].colorGreen.current * m_lightTable[i].intensity.current;
- m_lightTable[i].light.dcvDiffuse.g = value;
-
- value = m_lightTable[i].colorBlue.current * m_lightTable[i].intensity.current;
- m_lightTable[i].light.dcvDiffuse.b = value;
-
- m_pD3DDevice->SetLight(i, &m_lightTable[i].light);
- m_pD3DDevice->LightEnable(i, bEnable);
- }
- else
- {
- m_lightTable[i].light.dcvDiffuse.r = 0.0f;
- m_lightTable[i].light.dcvDiffuse.g = 0.0f;
- m_lightTable[i].light.dcvDiffuse.b = 0.0f;
-
- m_pD3DDevice->LightEnable(i, bEnable);
- }
- }
-}
-
-// Updates the lights for a given type.
-
-void CLight::LightUpdate(D3DTypeObj type)
-{
- bool bEnable;
- int i;
-
- for ( i=0 ; i<m_lightUsed ; i++ )
- {
- if ( m_lightTable[i].bUsed == false ) continue;
- if ( m_lightTable[i].bEnable == false ) continue;
- if ( m_lightTable[i].intensity.current == 0.0f ) continue;
-
- if ( m_lightTable[i].incluType != TYPENULL )
- {
- bEnable = (m_lightTable[i].incluType == type);
- m_pD3DDevice->LightEnable(i, bEnable);
- }
-
- if ( m_lightTable[i].excluType != TYPENULL )
- {
- bEnable = (m_lightTable[i].excluType != type);
- m_pD3DDevice->LightEnable(i, bEnable);
- }
- }
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// light.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "math/conv.h"
+#include "old/d3dengine.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "old/light.h"
+
+
+
+
+
+// Initializes a progression.
+
+void ProgInit(LightProg &p, float value)
+{
+ p.starting = value;
+ p.ending = value;
+ p.current = value;
+ p.progress = 0.0f;
+ p.speed = 100.0f;
+}
+
+// Makes evolve a progression.
+
+void ProgFrame(LightProg &p, float rTime)
+{
+ if ( p.speed < 100.0f )
+ {
+ if ( p.progress < 1.0f )
+ {
+ p.progress += p.speed*rTime;
+ if ( p.progress > 1.0f )
+ {
+ p.progress = 1.0f;
+ }
+ }
+
+ p.current = (p.ending-p.starting)*p.progress + p.starting;
+ }
+ else
+ {
+ p.current = p.ending;
+ }
+}
+
+// Change the current value.
+
+void ProgSet(LightProg &p, float value)
+{
+ p.starting = p.current;
+ p.ending = value;
+ p.progress = 0.0f;
+}
+
+
+
+
+
+// Object's constructor.
+
+CLight::CLight(CInstanceManager* iMan, CD3DEngine* engine)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_LIGHT, this);
+
+ m_pD3DDevice = 0;
+ m_engine = engine;
+
+ m_lightUsed = 0;
+ m_lightTable = (Light*)malloc(sizeof(Light)*D3DMAXLIGHT);
+ ZeroMemory(m_lightTable, sizeof(Light)*D3DMAXLIGHT);
+
+ m_time = 0.0f;
+}
+
+// Object's destructor.
+
+CLight::~CLight()
+{
+ free(m_lightTable);
+ m_iMan->DeleteInstance(CLASS_LIGHT, this);
+}
+
+
+void CLight::SetD3DDevice(LPDIRECT3DDEVICE7 device)
+{
+ m_pD3DDevice = device;
+}
+
+
+// Removes all the lights.
+
+void CLight::FlushLight()
+{
+ int i;
+
+ for ( i=0 ; i<D3DMAXLIGHT ; i++ )
+ {
+ m_lightTable[i].bUsed = false;
+ m_pD3DDevice->LightEnable(i, false);
+ }
+ m_lightUsed = 0;
+}
+
+
+// Creates a new light. Returns its rank or -1 on error.
+
+int CLight::CreateLight()
+{
+ int i;
+
+ for ( i=0 ; i<D3DMAXLIGHT ; i++ )
+ {
+ if ( m_lightTable[i].bUsed == false )
+ {
+ ZeroMemory(&m_lightTable[i], sizeof(Light));
+ m_lightTable[i].bUsed = true;
+ m_lightTable[i].bEnable = true;
+
+ m_lightTable[i].incluType = TYPENULL;
+ m_lightTable[i].excluType = TYPENULL;
+
+ m_lightTable[i].light.dltType = D3DLIGHT_DIRECTIONAL;
+ m_lightTable[i].light.dcvDiffuse.r = 0.5f;
+ m_lightTable[i].light.dcvDiffuse.g = 0.5f;
+ m_lightTable[i].light.dcvDiffuse.b = 0.5f; // white
+ m_lightTable[i].light.dvPosition.x =-100.0f;
+ m_lightTable[i].light.dvPosition.y = 100.0f;
+ m_lightTable[i].light.dvPosition.z =-100.0f;
+ m_lightTable[i].light.dvDirection.x = 1.0f;
+ m_lightTable[i].light.dvDirection.y = -1.0f;
+ m_lightTable[i].light.dvDirection.z = 1.0f;
+
+ ProgInit(m_lightTable[i].intensity, 1.0f); // maximum
+ ProgInit(m_lightTable[i].colorRed, 0.5f);
+ ProgInit(m_lightTable[i].colorGreen, 0.5f);
+ ProgInit(m_lightTable[i].colorBlue, 0.5f); // gray
+
+ if ( m_lightUsed < i+1 )
+ {
+ m_lightUsed = i+1;
+ }
+ return i;
+ }
+ }
+ return -1;
+}
+
+// Deletes a light.
+
+bool CLight::DeleteLight(int lightRank)
+{
+ int i;
+
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].bUsed = false;
+ m_pD3DDevice->LightEnable(lightRank, false);
+
+ m_lightUsed = 0;
+ for ( i=0 ; i<D3DMAXLIGHT ; i++ )
+ {
+ if ( m_lightTable[i].bUsed == true )
+ {
+ m_lightUsed = i+1;
+ }
+ }
+
+ return true;
+}
+
+
+// Specifies a light.
+
+bool CLight::SetLight(int lightRank, const D3DLIGHT7 &light)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].light = light;
+
+ ProgInit(m_lightTable[lightRank].colorRed, m_lightTable[lightRank].light.dcvDiffuse.r);
+ ProgInit(m_lightTable[lightRank].colorGreen, m_lightTable[lightRank].light.dcvDiffuse.g);
+ ProgInit(m_lightTable[lightRank].colorBlue, m_lightTable[lightRank].light.dcvDiffuse.b);
+
+ return true;
+}
+
+// Gives the specifications of a light.
+
+bool CLight::GetLight(int lightRank, D3DLIGHT7 &light)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ light = m_lightTable[lightRank].light;
+ return true;
+}
+
+
+// Lights up or put out a light.
+
+bool CLight::LightEnable(int lightRank, bool bEnable)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].bEnable = bEnable;
+ return true;
+}
+
+
+// Specifies the type (TYPE *) items included in this light.
+// This light does not light up so that this type of objects.
+
+bool CLight::SetLightIncluType(int lightRank, D3DTypeObj type)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].incluType = type;
+ return true;
+}
+
+// Specifies the type (TYPE *) items excluded by this light.
+// This light does not illuminate then ever these objects.
+
+bool CLight::SetLightExcluType(int lightRank, D3DTypeObj type)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].excluType = type;
+ return true;
+}
+
+
+// Management of the position of the light.
+
+bool CLight::SetLightPos(int lightRank, Math::Vector pos)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].light.dvPosition = VEC_TO_D3DVEC(pos);
+ return true;
+}
+
+Math::Vector CLight::RetLightPos(int lightRank)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return Math::Vector(0.0f, 0.0f, 0.0f);
+
+ return D3DVEC_TO_VEC(m_lightTable[lightRank].light.dvPosition);
+}
+
+
+// Management direction of the light.
+
+bool CLight::SetLightDir(int lightRank, Math::Vector dir)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].light.dvDirection = VEC_TO_D3DVEC(dir);
+ return true;
+}
+
+Math::Vector CLight::RetLightDir(int lightRank)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return Math::Vector(0.0f, 0.0f, 0.0f);
+
+ return D3DVEC_TO_VEC(m_lightTable[lightRank].light.dvDirection);
+}
+
+
+// Specifies the rate of change.
+
+bool CLight::SetLightIntensitySpeed(int lightRank, float speed)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].intensity.speed = speed;
+ return true;
+}
+
+// Management of the intensity of light.
+
+bool CLight::SetLightIntensity(int lightRank, float value)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ ProgSet(m_lightTable[lightRank].intensity, value);
+ return true;
+}
+
+float CLight::RetLightIntensity(int lightRank)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return 0.0f;
+
+ return m_lightTable[lightRank].intensity.current;
+}
+
+
+// Specifies the rate of change.
+
+bool CLight::SetLightColorSpeed(int lightRank, float speed)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].colorRed.speed = speed;
+ m_lightTable[lightRank].colorGreen.speed = speed;
+ m_lightTable[lightRank].colorBlue.speed = speed;
+ return true;
+}
+
+// Color management for light.
+
+bool CLight::SetLightColor(int lightRank, D3DCOLORVALUE color)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ ProgSet(m_lightTable[lightRank].colorRed, color.r);
+ ProgSet(m_lightTable[lightRank].colorGreen, color.g);
+ ProgSet(m_lightTable[lightRank].colorBlue, color.b);
+ return true;
+}
+
+D3DCOLORVALUE CLight::RetLightColor(int lightRank)
+{
+ D3DCOLORVALUE color;
+
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT )
+ {
+ color.r = 0.5f;
+ color.g = 0.5f;
+ color.b = 0.5f;
+ color.a = 0.5f;
+ return color;
+ }
+
+ color.r = m_lightTable[lightRank].colorRed.current;
+ color.g = m_lightTable[lightRank].colorGreen.current;
+ color.b = m_lightTable[lightRank].colorBlue.current;
+ return color;
+}
+
+
+// Adjusts the color of all lights.
+
+void CLight::AdaptLightColor(D3DCOLORVALUE color, float factor)
+{
+ D3DCOLORVALUE value;
+ int i;
+
+ for ( i=0 ; i<m_lightUsed ; i++ )
+ {
+ if ( m_lightTable[i].bUsed == false ) continue;
+
+ value.r = m_lightTable[i].colorRed.current;
+ value.g = m_lightTable[i].colorGreen.current;
+ value.b = m_lightTable[i].colorBlue.current;
+
+ value.r += color.r*factor;
+ value.g += color.g*factor;
+ value.b += color.b*factor;
+
+ ProgInit(m_lightTable[i].colorRed, value.r);
+ ProgInit(m_lightTable[i].colorGreen, value.g);
+ ProgInit(m_lightTable[i].colorBlue, value.b);
+ }
+
+ LightUpdate();
+}
+
+
+
+// Makes all the lights evolve.
+
+void CLight::FrameLight(float rTime)
+{
+ Math::Vector dir;
+ float angle;
+ int i;
+
+ if ( m_engine->RetPause() ) return;
+
+ m_time += rTime;
+
+ for ( i=0 ; i<m_lightUsed ; i++ )
+ {
+ if ( m_lightTable[i].bUsed == false ) continue;
+
+ ProgFrame(m_lightTable[i].intensity, rTime);
+ ProgFrame(m_lightTable[i].colorRed, rTime);
+ ProgFrame(m_lightTable[i].colorGreen, rTime);
+ ProgFrame(m_lightTable[i].colorBlue, rTime);
+
+ if ( m_lightTable[i].incluType == TYPEQUARTZ )
+ {
+ m_lightTable[i].light.dvDirection.x = sinf((m_time+i*Math::PI*0.5f)*1.0f);
+ m_lightTable[i].light.dvDirection.z = cosf((m_time+i*Math::PI*0.5f)*1.1f);
+ m_lightTable[i].light.dvDirection.y = -1.0f+cosf((m_time+i*Math::PI*0.5f)*2.7f)*0.5f;
+ }
+
+ if ( m_lightTable[i].incluType == TYPEMETAL )
+ {
+ dir = m_engine->RetEyePt()-m_engine->RetLookatPt();
+ angle = Math::RotateAngle(dir.x, dir.z);
+ angle += Math::PI*0.5f*i;
+ m_lightTable[i].light.dvDirection.x = sinf(angle*2.0f);
+ m_lightTable[i].light.dvDirection.z = cosf(angle*2.0f);
+ }
+ }
+}
+
+
+// Updates all the lights.
+
+void CLight::LightUpdate()
+{
+ bool bEnable;
+ float value;
+ int i;
+
+ for ( i=0 ; i<m_lightUsed ; i++ )
+ {
+ if ( m_lightTable[i].bUsed == false ) continue;
+
+ bEnable = m_lightTable[i].bEnable;
+ if ( m_lightTable[i].intensity.current == 0.0f ) bEnable = false;
+
+ if ( bEnable )
+ {
+ value = m_lightTable[i].colorRed.current * m_lightTable[i].intensity.current;
+ m_lightTable[i].light.dcvDiffuse.r = value;
+
+ value = m_lightTable[i].colorGreen.current * m_lightTable[i].intensity.current;
+ m_lightTable[i].light.dcvDiffuse.g = value;
+
+ value = m_lightTable[i].colorBlue.current * m_lightTable[i].intensity.current;
+ m_lightTable[i].light.dcvDiffuse.b = value;
+
+ m_pD3DDevice->SetLight(i, &m_lightTable[i].light);
+ m_pD3DDevice->LightEnable(i, bEnable);
+ }
+ else
+ {
+ m_lightTable[i].light.dcvDiffuse.r = 0.0f;
+ m_lightTable[i].light.dcvDiffuse.g = 0.0f;
+ m_lightTable[i].light.dcvDiffuse.b = 0.0f;
+
+ m_pD3DDevice->LightEnable(i, bEnable);
+ }
+ }
+}
+
+// Updates the lights for a given type.
+
+void CLight::LightUpdate(D3DTypeObj type)
+{
+ bool bEnable;
+ int i;
+
+ for ( i=0 ; i<m_lightUsed ; i++ )
+ {
+ if ( m_lightTable[i].bUsed == false ) continue;
+ if ( m_lightTable[i].bEnable == false ) continue;
+ if ( m_lightTable[i].intensity.current == 0.0f ) continue;
+
+ if ( m_lightTable[i].incluType != TYPENULL )
+ {
+ bEnable = (m_lightTable[i].incluType == type);
+ m_pD3DDevice->LightEnable(i, bEnable);
+ }
+
+ if ( m_lightTable[i].excluType != TYPENULL )
+ {
+ bEnable = (m_lightTable[i].excluType != type);
+ m_pD3DDevice->LightEnable(i, bEnable);
+ }
+ }
+}
+
+
diff --git a/src/old/light.h b/src/old/light.h
index 8291ca9..49e4e7d 100644
--- a/src/old/light.h
+++ b/src/old/light.h
@@ -1,109 +1,109 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// light.h
-
-#pragma once
-
-
-#include "old/d3dengine.h"
-#include "graphics/common/color.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-
-
-const int D3DMAXLIGHT = 100;
-
-
-struct LightProg
-{
- float starting;
- float ending;
- float current;
- float progress;
- float speed;
-};
-
-
-struct Light
-{
- char bUsed; // true -> light exists
- char bEnable; // true -> light turned on
-
- D3DTypeObj incluType; // type of all objects included
- D3DTypeObj excluType; // type of all objects excluded
-
- D3DLIGHT7 light; // configuration of the light
-
- LightProg intensity; // intensity (0 .. 1)
- LightProg colorRed;
- LightProg colorGreen;
- LightProg colorBlue;
-};
-
-
-
-class CLight
-{
-public:
- CLight(CInstanceManager *iMan, CD3DEngine* engine);
- virtual ~CLight();
-
- void SetD3DDevice(LPDIRECT3DDEVICE7 device);
-
- void FlushLight();
- int CreateLight();
- bool DeleteLight(int lightRank);
- bool SetLight(int lightRank, const D3DLIGHT7 &light);
- bool GetLight(int lightRank, D3DLIGHT7 &light);
- bool LightEnable(int lightRank, bool bEnable);
-
- bool SetLightIncluType(int lightRank, D3DTypeObj type);
- bool SetLightExcluType(int lightRank, D3DTypeObj type);
-
- bool SetLightPos(int lightRank, Math::Vector pos);
- Math::Vector RetLightPos(int lightRank);
-
- bool SetLightDir(int lightRank, Math::Vector dir);
- Math::Vector RetLightDir(int lightRank);
-
- bool SetLightIntensitySpeed(int lightRank, float speed);
- bool SetLightIntensity(int lightRank, float value);
- float RetLightIntensity(int lightRank);
- void AdaptLightColor(D3DCOLORVALUE color, float factor);
-
- bool SetLightColorSpeed(int lightRank, float speed);
- bool SetLightColor(int lightRank, D3DCOLORVALUE color);
- D3DCOLORVALUE RetLightColor(int lightRank);
-
- void FrameLight(float rTime);
- void LightUpdate();
- void LightUpdate(D3DTypeObj type);
-
-protected:
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- LPDIRECT3DDEVICE7 m_pD3DDevice;
-
- float m_time;
- int m_lightUsed;
- Light* m_lightTable;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// light.h
+
+#pragma once
+
+
+#include "old/d3dengine.h"
+#include "graphics/common/color.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+
+
+const int D3DMAXLIGHT = 100;
+
+
+struct LightProg
+{
+ float starting;
+ float ending;
+ float current;
+ float progress;
+ float speed;
+};
+
+
+struct Light
+{
+ char bUsed; // true -> light exists
+ char bEnable; // true -> light turned on
+
+ D3DTypeObj incluType; // type of all objects included
+ D3DTypeObj excluType; // type of all objects excluded
+
+ D3DLIGHT7 light; // configuration of the light
+
+ LightProg intensity; // intensity (0 .. 1)
+ LightProg colorRed;
+ LightProg colorGreen;
+ LightProg colorBlue;
+};
+
+
+
+class CLight
+{
+public:
+ CLight(CInstanceManager *iMan, CD3DEngine* engine);
+ virtual ~CLight();
+
+ void SetD3DDevice(LPDIRECT3DDEVICE7 device);
+
+ void FlushLight();
+ int CreateLight();
+ bool DeleteLight(int lightRank);
+ bool SetLight(int lightRank, const D3DLIGHT7 &light);
+ bool GetLight(int lightRank, D3DLIGHT7 &light);
+ bool LightEnable(int lightRank, bool bEnable);
+
+ bool SetLightIncluType(int lightRank, D3DTypeObj type);
+ bool SetLightExcluType(int lightRank, D3DTypeObj type);
+
+ bool SetLightPos(int lightRank, Math::Vector pos);
+ Math::Vector RetLightPos(int lightRank);
+
+ bool SetLightDir(int lightRank, Math::Vector dir);
+ Math::Vector RetLightDir(int lightRank);
+
+ bool SetLightIntensitySpeed(int lightRank, float speed);
+ bool SetLightIntensity(int lightRank, float value);
+ float RetLightIntensity(int lightRank);
+ void AdaptLightColor(D3DCOLORVALUE color, float factor);
+
+ bool SetLightColorSpeed(int lightRank, float speed);
+ bool SetLightColor(int lightRank, D3DCOLORVALUE color);
+ D3DCOLORVALUE RetLightColor(int lightRank);
+
+ void FrameLight(float rTime);
+ void LightUpdate();
+ void LightUpdate(D3DTypeObj type);
+
+protected:
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ LPDIRECT3DDEVICE7 m_pD3DDevice;
+
+ float m_time;
+ int m_lightUsed;
+ Light* m_lightTable;
+};
+
diff --git a/src/old/math3d.cpp b/src/old/math3d.cpp
index 3b5f9dd..5282ac1 100644
--- a/src/old/math3d.cpp
+++ b/src/old/math3d.cpp
@@ -1,1197 +1,1197 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// math3d.cpp
-
-#define STRICT
-#define D3D_OVERLOADS
-
-#include <math.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "old/d3dutil.h"
-#include "old/math3d.h"
-
-
-// Old defines
-#define MATH3D_PI 3.14159265358979323846f
-#define MATH3D_CHOUIA 1e-6f
-#define MATH3D_BEAUCOUP 1e6f
-
-
-// Old FPOINT struct
-struct FPOINT
-{
- float x;
- float y;
-
- FPOINT() { }
- FPOINT(float _x, float _y)
- {
- x = _x;
- y = _y;
- }
-};
-
-
-// === Functions already replaced by new implementation ===
-
-//>>> func.h IsEqual()
-bool IsEqual(float a, float b);
-
-//>>> func.h Min()
-float Min(float a, float b);
-float Min(float a, float b, float c);
-float Min(float a, float b, float c, float d);
-float Min(float a, float b, float c, float d, float e);
-
-//>>> func.h Max()
-float Max(float a, float b);
-float Max(float a, float b, float c);
-float Max(float a, float b, float c, float d);
-float Max(float a, float b, float c, float d, float e);
-
-//>>> func.h Norm()
-float Norm(float a);
-//>>> fabs()
-float Abs(float a);
-
-//>>> func.h Swap()
-void Swap(int &a, int &b);
-//>>> func.h Swap()
-void Swap(float &a, float &b);
-//>>> point.h Swap()
-void Swap(FPOINT &a, FPOINT &b);
-
-//>>> func.h Mod()
-float Mod(float a, float m);
-//>>> func.h NormAngle()
-float NormAngle(float angle);
-//>>> func.h TestAngle()
-bool TestAngle(float angle, float min, float max);
-
-//>>> geometry.h RotateAngle()
-float RotateAngle(FPOINT center, FPOINT p1, FPOINT p2);
-
-//>>> func.h Direction()
-float Direction(float a, float g);
-
-//>>> geometry.h RotatePoint()
-FPOINT RotatePoint(FPOINT center, float angle, FPOINT p);
-//>>> geometry.h RotatePoint()
-FPOINT RotatePoint(float angle, FPOINT p);
-//>>> geometry.h RotatePoint()
-FPOINT RotatePoint(float angle, float dist);
-//>>> geometry.h RotateAngle()
-float RotateAngle(float x, float y);
-//>>> geometry.h RotatePoint()
-void RotatePoint(float cx, float cy, float angle, float &px, float &py);
-
-//>>> geometry.h IsInsideTriangle()
-bool IsInsideTriangle(FPOINT a, FPOINT b, FPOINT c, FPOINT p);
-
-//>>> point.h Distance()
-float Length(FPOINT a, FPOINT b);
-
-//>>> point.h Point::Length()
-float Length(float x, float y);
-
-//>>> func.h Rand()
-float Rand();
-//>>> func.h Neutral()
-float Neutral(float value, float dead);
-
-//>>> func.h PropAngle()
-float Prop(int a, int b, float p);
-//>>> func.h Smooth()
-float Smooth(float actual, float hope, float time);
-//>>> func.h Bounce()
-float Bounce(float progress, float middle=0.3f, float bounce=0.4f);
-
-
-//>>> geometry.h SegmentPoint()
-D3DVECTOR SegmentDist(const D3DVECTOR &p1, const D3DVECTOR &p2, float dist);
-
-//>>> geometry.h Intersect()
-bool Intersect(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c, D3DVECTOR d, D3DVECTOR e, D3DVECTOR &i);
-
-//>>> geometry.h IntersectY()
-bool IntersectY(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c, D3DVECTOR &p);
-
-//>>> geometry.h RotatePoint()
-void RotatePoint(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p);
-
-//>>> geometry.h RotatePoint2()
-void RotatePoint2(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p);
-
-//>>> geometry.h RotateView()
-D3DVECTOR RotateView(D3DVECTOR center, float angleH, float angleV, float dist);
-
-//>>> geometry.h LookatPoint()
-D3DVECTOR LookatPoint( D3DVECTOR eye, float angleH, float angleV, float length );
-
-//>>> vector.h Vector::Length()
-float Length(const D3DVECTOR &u);
-
-//>>> vector.h Distance()
-float Length(const D3DVECTOR &a, const D3DVECTOR &b);
-
-//>>> geometry.h DistanceProjected()
-float Length2d(const D3DVECTOR &a, const D3DVECTOR &b);
-
-//>>> vector.h Angle()
-float Angle( D3DVECTOR u, D3DVECTOR v );
-
-//>>> vector.h CrossProduct()
-D3DVECTOR Cross( D3DVECTOR u, D3DVECTOR v );
-
-//>>> geometry.h NormalToPlane()
-D3DVECTOR ComputeNormal( D3DVECTOR p1, D3DVECTOR p2, D3DVECTOR p3 );
-
-//>>> geometry.h Transform()
-D3DVECTOR Transform(const D3DMATRIX &m, D3DVECTOR p);
-
-//>>> geometry.h Projection()
-D3DVECTOR Projection(const D3DVECTOR &a, const D3DVECTOR &b, const D3DVECTOR &p);
-
-//>>> geometry.h DistanceToPlane()
-float DistancePlanPoint(const D3DVECTOR &a, const D3DVECTOR &b, const D3DVECTOR &c, const D3DVECTOR &p);
-
-//>>> geometry.h IsSamePlane()
-bool IsSamePlane(D3DVECTOR *plan1, D3DVECTOR *plan2);
-
-//>>> geometry.h LoadRotationXZYMatrix()
-void MatRotateXZY(D3DMATRIX &mat, D3DVECTOR angle);
-
-//>>> geometry.h LoadRotationZXYMatrix()
-void MatRotateZXY(D3DMATRIX &mat, D3DVECTOR angle);
-
-
-
-// UNUSED
-float MidPoint(FPOINT a, FPOINT b, float px);
-
-// UNUSED
-bool LineFunction(FPOINT p1, FPOINT p2, float &a, float &b);
-
-
-
-
-// Returns true if two numbers are nearly equal.
-
-bool IsEqual(float a, float b)
-{
- return Abs(a-b) < MATH3D_CHOUIA;
-}
-
-
-// Returns the minimum value.
-
-float Min(float a, float b)
-{
- if ( a <= b ) return a;
- else return b;
-}
-
-float Min(float a, float b, float c)
-{
- return Min( Min(a,b), c );
-}
-
-float Min(float a, float b, float c, float d)
-{
- return Min( Min(a,b), Min(c,d) );
-}
-
-float Min(float a, float b, float c, float d, float e)
-{
- return Min( Min(a,b), Min(c,d), e );
-}
-
-
-// Returns the maximum value.
-
-float Max(float a, float b)
-{
- if ( a >= b ) return a;
- else return b;
-}
-
-float Max(float a, float b, float c)
-{
- return Max( Max(a,b), c );
-}
-
-float Max(float a, float b, float c, float d)
-{
- return Max( Max(a,b), Max(c,d) );
-}
-
-float Max(float a, float b, float c, float d, float e)
-{
- return Max( Max(a,b), Max(c,d), e );
-}
-
-
-// Returns the normalized value (0 .. 1).
-
-float Norm(float a)
-{
- if ( a < 0.0f ) return 0.0f;
- if ( a > 1.0f ) return 1.0f;
- return a;
-}
-
-
-// Returns the absolute value of a number.
-
-float Abs(float a)
-{
- return (float)fabs(a);
-}
-
-
-// Swaps two integers.
-
-void Swap(int &a, int &b)
-{
- int c;
-
- c = a;
- a = b;
- b = c;
-}
-
-// Swaps two real numbers.
-
-void Swap(float &a, float &b)
-{
- float c;
-
- c = a;
- a = b;
- b = c;
-}
-
-// Permutes two points.
-
-void Swap(FPOINT &a, FPOINT &b)
-{
- FPOINT c;
-
- c = a;
- a = b;
- b = c;
-}
-
-// Returns the modulo of a floating point number.
-// Mod(8.1, 4) = 0.1
-// Mod(n, 1) = fractional part of n
-
-float Mod(float a, float m)
-{
- return a - ((int)(a/m))*m;
-}
-
-// Returns a normalized angle, that is in other words between 0 and 2 * MATH3D_PI.
-
-float NormAngle(float angle)
-{
- angle = Mod(angle, MATH3D_PI*2.0f);
- if ( angle < 0.0f )
- {
- return MATH3D_PI*2.0f + angle;
- }
- else
- {
- return angle;
- }
-}
-
-// Test if a angle is between two terminals.
-
-bool TestAngle(float angle, float min, float max)
-{
- angle = NormAngle(angle);
- min = NormAngle(min);
- max = NormAngle(max);
-
- if ( min > max )
- {
- return ( angle <= max || angle >= min );
- }
- else
- {
- return ( angle >= min && angle <= max );
- }
-}
-
-
-// Calculates the angle to rotate the angle a to the angle g.
-// A positive angle is counterclockwise (CCW).
-
-float Direction(float a, float g)
-{
- a = NormAngle(a);
- g = NormAngle(g);
-
- if ( a < g )
- {
- if ( a+MATH3D_PI*2.0f-g < g-a ) a += MATH3D_PI*2.0f;
- }
- else
- {
- if ( g+MATH3D_PI*2.0f-a < a-g ) g += MATH3D_PI*2.0f;
- }
- return (g-a);
-}
-
-
-// Rotates a point around a center.
-// The angle is in radians.
-// A positive angle is counterclockwise (CCW).
-
-FPOINT RotatePoint(FPOINT center, float angle, FPOINT p)
-{
- FPOINT a, b;
-
- a.x = p.x-center.x;
- a.y = p.y-center.y;
-
- b.x = a.x*cosf(angle) - a.y*sinf(angle);
- b.y = a.x*sinf(angle) + a.y*cosf(angle);
-
- b.x += center.x;
- b.y += center.y;
- return b;
-}
-
-// Rotates a point around the origin.
-// The angle is in radians.
-// A positive angle is counterclockwise (CCW).
-
-FPOINT RotatePoint(float angle, FPOINT p)
-{
- FPOINT a;
-
- a.x = p.x*cosf(angle) - p.y*sinf(angle);
- a.y = p.x*sinf(angle) + p.y*cosf(angle);
-
- return a;
-}
-
-// Rotates a vector (dist, 0).
-// The angle is in radians.
-// A positive angle is counterclockwise (CCW).
-
-FPOINT RotatePoint(float angle, float dist)
-{
- FPOINT a;
-
- a.x = dist*cosf(angle);
- a.y = dist*sinf(angle);
-
- return a;
-}
-
-// Calculates the angle of a right triangle.
-// The angle is counterclockwise (CCW), between 0 and 2 * MATH3D_PI.
-// For an angle clockwise (CW), just go ahead.
-//
-// ^
-// |
-// y o----o
-// | / |
-// |/)a |
-// ----o----o-->
-// | x
-// |
-
-float RotateAngle(float x, float y)
-{
-#if 1
- if ( x == 0.0f && y == 0.0f ) return 0.0f;
-
- if ( x >= 0.0f )
- {
- if ( y >= 0.0f )
- {
- if ( x > y ) return atanf(y/x);
- else return MATH3D_PI*0.5f - atanf(x/y);
- }
- else
- {
- if ( x > -y ) return MATH3D_PI*2.0f + atanf(y/x);
- else return MATH3D_PI*1.5f - atanf(x/y);
- }
- }
- else
- {
- if ( y >= 0.0f )
- {
- if ( -x > y ) return MATH3D_PI*1.0f + atanf(y/x);
- else return MATH3D_PI*0.5f - atanf(x/y);
- }
- else
- {
- if ( -x > -y ) return MATH3D_PI*1.0f + atanf(y/x);
- else return MATH3D_PI*1.5f - atanf(x/y);
- }
- }
-#else
- float angle;
-
- if ( x == 0.0f )
- {
- if ( y > 0.0f )
- {
- return 90.0f*MATH3D_PI/180.0f;
- }
- else
- {
- return 270.0f*MATH3D_PI/180.0f;
- }
- }
- else
- {
- angle = atanf(y/x);
- if ( x < 0.0f )
- {
- angle += MATH3D_PI;
- }
- return angle;
- }
-#endif
-}
-
-// Calculates the angle between two points and one center.
-// The angle is in radians.
-// A positive angle is counterclockwise (CCW).
-
-float RotateAngle(FPOINT center, FPOINT p1, FPOINT p2)
-{
- float a1, a2, a;
-
- if ( p1.x == center.x &&
- p1.y == center.y ) return 0;
-
- if ( p2.x == center.x &&
- p2.y == center.y ) return 0;
-
- a1 = asinf((p1.y-center.y)/Length(p1,center));
- a2 = asinf((p2.y-center.y)/Length(p2,center));
-
- if ( p1.x < center.x ) a1 = MATH3D_PI-a1;
- if ( p2.x < center.x ) a2 = MATH3D_PI-a2;
-
- a = a2-a1;
- if ( a < 0 ) a += MATH3D_PI*2;
- return a;
-}
-
-// Returns py up on the line ab.
-
-float MidPoint(FPOINT a, FPOINT b, float px)
-{
- if ( Abs(a.x-b.x) < MATH3D_CHOUIA )
- {
- if ( a.y < b.y ) return MATH3D_BEAUCOUP;
- else return -MATH3D_BEAUCOUP;
- }
- return (b.y-a.y)*(px-a.x)/(b.x-a.x)+a.y;
-}
-
-// Advance "dist" along the segment p1-p2.
-
-D3DVECTOR SegmentDist(const D3DVECTOR &p1, const D3DVECTOR &p2, float dist)
-{
- return p1+Normalize(p2-p1)*dist;
-}
-
-// Check if a point is inside a triangle.
-
-bool IsInsideTriangle(FPOINT a, FPOINT b, FPOINT c, FPOINT p)
-{
- float n, m;
-
- if ( p.x < a.x && p.x < b.x && p.x < c.x ) return false;
- if ( p.x > a.x && p.x > b.x && p.x > c.x ) return false;
- if ( p.y < a.y && p.y < b.y && p.y < c.y ) return false;
- if ( p.y > a.y && p.y > b.y && p.y > c.y ) return false;
-
- if ( a.x > b.x ) Swap(a,b);
- if ( a.x > c.x ) Swap(a,c);
- if ( c.x < a.x ) Swap(c,a);
- if ( c.x < b.x ) Swap(c,b);
-
- n = MidPoint(a, b, p.x);
- m = MidPoint(a, c, p.x);
- if ( (n>p.y||p.y>m) && (n<p.y||p.y<m) ) return false;
-
- n = MidPoint(c, b, p.x);
- m = MidPoint(c, a, p.x);
- if ( (n>p.y||p.y>m) && (n<p.y||p.y<m) ) return false;
-
- return true;
-}
-
-// Calculates the intersection "i" right "of" the plan "abc".
-
-bool Intersect(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c,
- D3DVECTOR d, D3DVECTOR e, D3DVECTOR &i)
-{
- float d1, d2;
-
- d1 = (d.x-a.x)*((b.y-a.y)*(c.z-a.z)-(c.y-a.y)*(b.z-a.z)) -
- (d.y-a.y)*((b.x-a.x)*(c.z-a.z)-(c.x-a.x)*(b.z-a.z)) +
- (d.z-a.z)*((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y));
-
- d2 = (d.x-e.x)*((b.y-a.y)*(c.z-a.z)-(c.y-a.y)*(b.z-a.z)) -
- (d.y-e.y)*((b.x-a.x)*(c.z-a.z)-(c.x-a.x)*(b.z-a.z)) +
- (d.z-e.z)*((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y));
-
- if ( d2 == 0 ) return false;
-
- i.x = d.x + d1/d2*(e.x-d.x);
- i.y = d.y + d1/d2*(e.y-d.y);
- i.z = d.z + d1/d2*(e.z-d.z);
- return true;
-}
-
-// Calculates the intersection of the straight line passing through p (x, z)
-// parallel to the y axis, with the plane abc. Returns p.y.
-
-bool IntersectY(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c, D3DVECTOR &p)
-{
-#if 0
- D3DVECTOR d,e,i;
-
- d.x = p.x;
- d.y = 0.0f;
- d.z = p.z;
- e.x = p.x;
- e.y = 1.0f;
- e.z = p.z;
- if ( !Intersect(a,b,c,d,e,i) ) return false;
- p.y = i.y;
- return true;
-#else
- float d, d1, d2;
-
- d = (b.x-a.x)*(c.z-a.z) - (c.x-a.x)*(b.z-a.z);
- d1 = (p.x-a.x)*(c.z-a.z) - (c.x-a.x)*(p.z-a.z);
- d2 = (b.x-a.x)*(p.z-a.z) - (p.x-a.x)*(b.z-a.z);
-
- if ( d == 0.0f ) return false;
-
- p.y = a.y + d1/d*(b.y-a.y) + d2/d*(c.y-a.y);
- return true;
-#endif
-}
-
-
-// Rotates a point around a center in the plan.
-// The angle is in radians.
-// A positive angle is counterclockwise (CCW).
-
-void RotatePoint(float cx, float cy, float angle, float &px, float &py)
-{
- float ax, ay;
-
- px -= cx;
- py -= cy;
-
- ax = px*cosf(angle) - py*sinf(angle);
- ay = px*sinf(angle) + py*cosf(angle);
-
- px = cx+ax;
- py = cy+ay;
-}
-
-// Rotates a point around a center in space.
-// The angle is in radians.
-// A positive angle is counterclockwise (CCW).
-
-void RotatePoint(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p)
-{
- D3DVECTOR a, b;
-
- p.x -= center.x;
- p.y -= center.y;
- p.z -= center.z;
-
- b.x = p.x*cosf(angleH) - p.z*sinf(angleH);
- b.y = p.z*sinf(angleV) + p.y*cosf(angleV);
- b.z = p.x*sinf(angleH) + p.z*cosf(angleH);
-
- p.x = center.x+b.x;
- p.y = center.y+b.y;
- p.z = center.z+b.z;
-}
-
-// Rotates a point around a center in space.
-// The angle is in radians.
-// A positive angle is counterclockwise (CCW).
-
-void RotatePoint2(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p)
-{
- D3DVECTOR a, b;
-
- p.x -= center.x;
- p.y -= center.y;
- p.z -= center.z;
-
- a.x = p.x*cosf(angleH) - p.z*sinf(angleH);
- a.y = p.y;
- a.z = p.x*sinf(angleH) + p.z*cosf(angleH);
-
- b.x = a.x;
- b.y = a.z*sinf(angleV) + a.y*cosf(angleV);
- b.z = a.z*cosf(angleV) - a.y*sinf(angleV);
-
- p.x = center.x+b.x;
- p.y = center.y+b.y;
- p.z = center.z+b.z;
-}
-
-// Calculation point of view to look at a center
-// two angles and a distance.
-
-D3DVECTOR RotateView(D3DVECTOR center, float angleH, float angleV, float dist)
-{
- D3DMATRIX mat1, mat2, mat;
- D3DVECTOR eye;
-
- D3DUtil_SetRotateZMatrix(mat1, -angleV);
- D3DUtil_SetRotateYMatrix(mat2, -angleH);
- D3DMath_MatrixMultiply(mat, mat1, mat2);
-
- eye.x = 0.0f+dist;
- eye.y = 0.0f;
- eye.z = 0.0f;
- eye = Transform(mat, eye);
-
- return eye+center;
-}
-
-// Calculates the end point.
-
-D3DVECTOR LookatPoint( D3DVECTOR eye, float angleH, float angleV, float length )
-{
- D3DVECTOR lookat;
-
- lookat = eye;
- lookat.z += length;
-
-//? RotatePoint(eye.x, eye.z, angleH, lookat.x, lookat.z);
-//? RotatePoint(eye.z, eye.y, angleV, lookat.z, lookat.y);
- RotatePoint(eye, angleH, angleV, lookat);
-
- return lookat;
-}
-
-
-// Returns the distance between two points.
-
-float Length(FPOINT a, FPOINT b)
-{
- return sqrtf( (a.x-b.x)*(a.x-b.x) +
- (a.y-b.y)*(a.y-b.y) );
-}
-
-// Returns the hypotenuse of a right triangle.
-
-float Length(float x, float y)
-{
- return sqrtf( (x*x) + (y*y) );
-}
-
-// Returns the length of a vector.
-
-float Length(const D3DVECTOR &u)
-{
- return sqrtf( (u.x*u.x) + (u.y*u.y) + (u.z*u.z) );
-}
-
-// Returns the distance between two points.
-
-float Length(const D3DVECTOR &a, const D3DVECTOR &b)
-{
- return sqrtf( (a.x-b.x)*(a.x-b.x) +
- (a.y-b.y)*(a.y-b.y) +
- (a.z-b.z)*(a.z-b.z) );
-}
-
-// Returns the distance "a flat" between two points.
-
-float Length2d(const D3DVECTOR &a, const D3DVECTOR &b)
-{
- return sqrtf( (a.x-b.x)*(a.x-b.x) +
- (a.z-b.z)*(a.z-b.z) );
-}
-
-
-// Returns the angle formed by two vectors.
-
-float Angle( D3DVECTOR u, D3DVECTOR v )
-{
-#if 0
- return acosf( Abs(u.x*v.x + u.y*v.y + u.z*v.z) / (Length(u)*Length(v)) );
-#endif
-#if 0
- float d;
- d = (u.y*v.z-u.z*v.y) + (u.z*v.x-u.x*v.z) + (u.x*v.y-u.y*v.x);
- return asinf( Abs(d) / (Length(u)*Length(v)) );
-#endif
-#if 0
- return asinf( Length(Cross(u,v)) / (Length(u)*Length(v)) );
-#endif
-#if 1
- float len, a, b;
-
- len = Length(u)*Length(v);
- a = acosf( (u.x*v.x + u.y*v.y + u.z*v.z) / len );
- b = asinf( Length(Cross(u,v)) / len );
- return a;
-#endif
-}
-
-// Returns the product of two vectors.
-
-D3DVECTOR Cross( D3DVECTOR u, D3DVECTOR v )
-{
- return D3DVECTOR( u.y*v.z - u.z*v.y,
- u.z*v.x - u.x*v.z,
- u.x*v.y - u.y*v.x );
-}
-
-// Returns the normal vector of a triangular face.
-
-D3DVECTOR ComputeNormal( D3DVECTOR p1, D3DVECTOR p2, D3DVECTOR p3 )
-{
- D3DVECTOR u, v;
-
- u = D3DVECTOR( p3.x-p1.x, p3.y-p1.y, p3.z-p1.z );
- v = D3DVECTOR( p2.x-p1.x, p2.y-p1.y, p2.z-p1.z );
-
- return Normalize(Cross(u, v));
-}
-
-
-// Transforms a point in a matrix, in exactly the same manner as Direct3D.
-
-D3DVECTOR Transform(const D3DMATRIX &m, D3DVECTOR p)
-{
- D3DVECTOR pp;
-
- pp.x = p.x*m._11 + p.y*m._21 + p.z*m._31 + m._41;
- pp.y = p.x*m._12 + p.y*m._22 + p.z*m._32 + m._42;
- pp.z = p.x*m._13 + p.y*m._23 + p.z*m._33 + m._43;
-
- return pp;
-}
-
-
-// Calculates the projection of a point P on a straight line AB.
-
-D3DVECTOR Projection(const D3DVECTOR &a, const D3DVECTOR &b, const D3DVECTOR &p)
-{
- float k;
-
- k = (b.x-a.x)*(p.x-a.x) + (b.y-a.y)*(p.y-a.y) + (b.z-a.z)*(p.z-a.z);
- k /= (b.x-a.x)*(b.x-a.x) + (b.y-a.y)*(b.y-a.y) + (b.z-a.z)*(b.z-a.z);
-
- return a + k*(b-a);
-}
-
-// The texture plate in the xz plane.
-
-void MappingObject(D3DVERTEX2* pVertices, int nb, float scale)
-{
- int i;
-
- for ( i=0 ; i<nb ; i++ )
- {
- pVertices[i].tu = pVertices[i].x*scale;
- pVertices[i].tv = pVertices[i].z*scale;
- }
-}
-
-// Smooths normal.
-
-void SmoothObject(D3DVERTEX2* pVertices, int nb)
-{
- char* bDone;
- int index[100];
- int i, j, rank;
- D3DVECTOR sum;
-
- bDone = (char*)malloc(nb*sizeof(char));
- ZeroMemory(bDone, nb*sizeof(char));
-
- for ( i=0 ; i<nb ; i++ )
- {
- bDone[i] = true;
- rank = 0;
- index[rank++] = i;
-
- for ( j=0 ; j<nb ; j++ )
- {
- if ( bDone[j] ) continue;
- if ( pVertices[j].x == pVertices[i].x &&
- pVertices[j].y == pVertices[i].y &&
- pVertices[j].z == pVertices[i].z )
- {
- bDone[j] = true;
- index[rank++] = j;
- if ( rank >= 100 ) break;
- }
- }
-
- sum.x = 0;
- sum.y = 0;
- sum.z = 0;
- for ( j=0 ; j<rank ; j++ )
- {
- sum.x += pVertices[index[j]].nx;
- sum.y += pVertices[index[j]].ny;
- sum.z += pVertices[index[j]].nz;
- }
- sum = Normalize(sum);
-
- for ( j=0 ; j<rank ; j++ )
- {
- pVertices[index[j]].nx = sum.x;
- pVertices[index[j]].ny = sum.y;
- pVertices[index[j]].nz = sum.z;
- }
- }
-
- free(bDone);
-}
-
-
-
-// Calculates the parameters a and b of the segment passing
-// through the points p1 and p2, knowing that:
-// f(x) = ax+b
-// Returns false if the line is vertical.
-
-bool LineFunction(FPOINT p1, FPOINT p2, float &a, float &b)
-{
- if ( D3DMath_IsZero(p1.x-p2.x) )
- {
- a = g_HUGE; // infinite slope!
- b = p2.x;
- return false;
- }
-
- a = (p2.y-p1.y)/(p2.x-p1.x);
- b = p2.y - p2.x*a;
- return true;
-}
-
-
-// Calculates the distance between a plane ABC and a point P.
-
-float DistancePlanPoint(const D3DVECTOR &a, const D3DVECTOR &b,
- const D3DVECTOR &c, const D3DVECTOR &p)
-{
- D3DVECTOR n;
- float aa,bb,cc,dd;
-
- n = ComputeNormal(a,b,c);
-
- aa = n.x;
- bb = n.y;
- cc = n.z;
- dd = -(n.x*a.x + n.y*a.y + n.z*a.z);
-
- return Abs(aa*p.x + bb*p.y + cc*p.z + dd);
-}
-
-// Check if two planes defined by 3 points are part of the same plan.
-
-bool IsSamePlane(D3DVECTOR *plan1, D3DVECTOR *plan2)
-{
- D3DVECTOR n1, n2;
- float dist;
-
- n1 = ComputeNormal(plan1[0], plan1[1], plan1[2]);
- n2 = ComputeNormal(plan2[0], plan2[1], plan2[2]);
-
- if ( Abs(n1.x-n2.x) > 0.1f ||
- Abs(n1.y-n2.y) > 0.1f ||
- Abs(n1.z-n2.z) > 0.1f ) return false;
-
- dist = DistancePlanPoint(plan1[0], plan1[1], plan1[2], plan2[0]);
- if ( dist > 0.1f ) return false;
-
- return true;
-}
-
-
-// Calculates the matrix to make three rotations in the X, Y and Z
-// >>>>>> OPTIMIZING!!!
-
-void MatRotateXZY(D3DMATRIX &mat, D3DVECTOR angle)
-{
- D3DMATRIX temp;
-
- D3DUtil_SetRotateXMatrix(temp, angle.x);
- D3DUtil_SetRotateZMatrix(mat, angle.z);
- D3DMath_MatrixMultiply(mat, mat, temp);
- D3DUtil_SetRotateYMatrix(temp, angle.y);
- D3DMath_MatrixMultiply(mat, mat, temp); // X-Z-Y
-}
-
-// Calculates the matrix to make three rotations in the order Z, X and Y.
-// >>>>>> OPTIMIZING!!!
-
-void MatRotateZXY(D3DMATRIX &mat, D3DVECTOR angle)
-{
- D3DMATRIX temp;
-
- D3DUtil_SetRotateZMatrix(temp, angle.z);
- D3DUtil_SetRotateXMatrix(mat, angle.x);
- D3DMath_MatrixMultiply(mat, mat, temp);
- D3DUtil_SetRotateYMatrix(temp, angle.y);
- D3DMath_MatrixMultiply(mat, mat, temp); // Z-X-Y
-}
-
-
-// Returns a random value between 0 and 1.
-
-float Rand()
-{
- return (float)rand()/RAND_MAX;
-}
-
-
-// Managing the dead zone of a joystick.
-
-// in: -1 0 1
-// --|-------|----o----|-------|-->
-// <---->
-// dead
-// out: -1 0 0 1
-
-float Neutral(float value, float dead)
-{
- if ( Abs(value) <= dead )
- {
- return 0.0f;
- }
- else
- {
- if ( value > 0.0f ) return (value-dead)/(1.0f-dead);
- else return (value+dead)/(1.0f-dead);
- }
-}
-
-
-// Calculates a value (radians) proportional between a and b (degrees).
-
-float Prop(int a, int b, float p)
-{
- float aa, bb;
-
- aa = (float)a*MATH3D_PI/180.0f;
- bb = (float)b*MATH3D_PI/180.0f;
-
- return aa+p*(bb-aa);
-}
-
-// Gently advanced a desired value from its current value.
-// Over time, the greater the progression is rapid.
-
-float Smooth(float actual, float hope, float time)
-{
- float futur;
-
- futur = actual + (hope-actual)*time;
-
- if ( hope > actual )
- {
- if ( futur > hope ) futur = hope;
- }
- if ( hope < actual )
- {
- if ( futur < hope ) futur = hope;
- }
-
- return futur;
-}
-
-
-// Bounces any movement.
-
-// out
-// |
-// 1+------o-------o---
-// | o | o o | | bounce
-// | o | o---|---
-// | o | |
-// | o | |
-// -o------|-------+----> progress
-// 0| | 1
-// |<---->|middle
-
-float Bounce(float progress, float middle, float bounce)
-{
- if ( progress < middle )
- {
- progress = progress/middle; // 0..1
- return 0.5f+sinf(progress*MATH3D_PI-MATH3D_PI/2.0f)/2.0f;
- }
- else
- {
- progress = (progress-middle)/(1.0f-middle); // 0..1
- return (1.0f-bounce/2.0f)+sinf((0.5f+progress*2.0f)*MATH3D_PI)*(bounce/2.0f);
- }
-}
-
-
-// Returns the color corresponding D3DCOLOR.
-
-D3DCOLOR RetColor(float intensity)
-{
- D3DCOLOR color;
-
- if ( intensity <= 0.0f ) return 0x00000000;
- if ( intensity >= 1.0f ) return 0xffffffff;
-
- color = (int)(intensity*255.0f)<<24;
- color |= (int)(intensity*255.0f)<<16;
- color |= (int)(intensity*255.0f)<<8;
- color |= (int)(intensity*255.0f);
-
- return color;
-}
-
-// Returns the color corresponding D3DCOLOR.
-
-D3DCOLOR RetColor(D3DCOLORVALUE intensity)
-{
- D3DCOLOR color;
-
- color = (int)(intensity.a*255.0f)<<24;
- color |= (int)(intensity.r*255.0f)<<16;
- color |= (int)(intensity.g*255.0f)<<8;
- color |= (int)(intensity.b*255.0f);
-
- return color;
-}
-
-// Returns the color corresponding D3DCOLORVALUE.
-
-D3DCOLORVALUE RetColor(D3DCOLOR intensity)
-{
- D3DCOLORVALUE color;
-
- color.r = (float)((intensity>>16)&0xff)/256.0f;
- color.g = (float)((intensity>>8 )&0xff)/256.0f;
- color.b = (float)((intensity>>0 )&0xff)/256.0f;
- color.a = (float)((intensity>>24)&0xff)/256.0f;
-
- return color;
-}
-
-
-// RGB to HSV conversion.
-
-void RGB2HSV(D3DCOLORVALUE src, ColorHSV &dest)
-{
- float min, max, delta;
-
- min = Min(src.r, src.g, src.b);
- max = Max(src.r, src.g, src.b);
-
- dest.v = max; // intensity
-
- if ( max == 0.0f )
- {
- dest.s = 0.0f; // saturation
- dest.h = 0.0f; // undefined color!
- }
- else
- {
- delta = max-min;
- dest.s = delta/max; // saturation
-
- if ( src.r == max ) // between yellow & magenta
- {
- dest.h = (src.g-src.b)/delta;
- }
- else if ( src.g == max ) // between cyan & yellow
- {
- dest.h = 2.0f+(src.b-src.r)/delta;
- }
- else // between magenta & cyan
- {
- dest.h = 4.0f+(src.r-src.g)/delta;
- }
-
- dest.h *= 60.0f; // in degrees
- if ( dest.h < 0.0f ) dest.h += 360.0f;
- dest.h /= 360.0f; // 0..1
- }
-}
-
-// HSV to RGB conversion.
-
-void HSV2RGB(ColorHSV src, D3DCOLORVALUE &dest)
-{
- int i;
- float f,v,p,q,t;
-
- src.h = Norm(src.h)*360.0f;
- src.s = Norm(src.s);
- src.v = Norm(src.v);
-
- if ( src.s == 0.0f ) // zero saturation?
- {
- dest.r = src.v;
- dest.g = src.v;
- dest.b = src.v; // gray
- }
- else
- {
- if ( src.h == 360.0f ) src.h = 0.0f;
- src.h /= 60.0f;
- i = (int)src.h; // integer part (0 .. 5)
- f = src.h-i; // fractional part
-
- v = src.v;
- p = src.v*(1.0f-src.s);
- q = src.v*(1.0f-(src.s*f));
- t = src.v*(1.0f-(src.s*(1.0f-f)));
-
- switch (i)
- {
- case 0: dest.r=v; dest.g=t; dest.b=p; break;
- case 1: dest.r=q; dest.g=v; dest.b=p; break;
- case 2: dest.r=p; dest.g=v; dest.b=t; break;
- case 3: dest.r=p; dest.g=q; dest.b=v; break;
- case 4: dest.r=t; dest.g=p; dest.b=v; break;
- case 5: dest.r=v; dest.g=p; dest.b=q; break;
- }
- }
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// math3d.cpp
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <math.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "old/d3dutil.h"
+#include "old/math3d.h"
+
+
+// Old defines
+#define MATH3D_PI 3.14159265358979323846f
+#define MATH3D_CHOUIA 1e-6f
+#define MATH3D_BEAUCOUP 1e6f
+
+
+// Old FPOINT struct
+struct FPOINT
+{
+ float x;
+ float y;
+
+ FPOINT() { }
+ FPOINT(float _x, float _y)
+ {
+ x = _x;
+ y = _y;
+ }
+};
+
+
+// === Functions already replaced by new implementation ===
+
+//>>> func.h IsEqual()
+bool IsEqual(float a, float b);
+
+//>>> func.h Min()
+float Min(float a, float b);
+float Min(float a, float b, float c);
+float Min(float a, float b, float c, float d);
+float Min(float a, float b, float c, float d, float e);
+
+//>>> func.h Max()
+float Max(float a, float b);
+float Max(float a, float b, float c);
+float Max(float a, float b, float c, float d);
+float Max(float a, float b, float c, float d, float e);
+
+//>>> func.h Norm()
+float Norm(float a);
+//>>> fabs()
+float Abs(float a);
+
+//>>> func.h Swap()
+void Swap(int &a, int &b);
+//>>> func.h Swap()
+void Swap(float &a, float &b);
+//>>> point.h Swap()
+void Swap(FPOINT &a, FPOINT &b);
+
+//>>> func.h Mod()
+float Mod(float a, float m);
+//>>> func.h NormAngle()
+float NormAngle(float angle);
+//>>> func.h TestAngle()
+bool TestAngle(float angle, float min, float max);
+
+//>>> geometry.h RotateAngle()
+float RotateAngle(FPOINT center, FPOINT p1, FPOINT p2);
+
+//>>> func.h Direction()
+float Direction(float a, float g);
+
+//>>> geometry.h RotatePoint()
+FPOINT RotatePoint(FPOINT center, float angle, FPOINT p);
+//>>> geometry.h RotatePoint()
+FPOINT RotatePoint(float angle, FPOINT p);
+//>>> geometry.h RotatePoint()
+FPOINT RotatePoint(float angle, float dist);
+//>>> geometry.h RotateAngle()
+float RotateAngle(float x, float y);
+//>>> geometry.h RotatePoint()
+void RotatePoint(float cx, float cy, float angle, float &px, float &py);
+
+//>>> geometry.h IsInsideTriangle()
+bool IsInsideTriangle(FPOINT a, FPOINT b, FPOINT c, FPOINT p);
+
+//>>> point.h Distance()
+float Length(FPOINT a, FPOINT b);
+
+//>>> point.h Point::Length()
+float Length(float x, float y);
+
+//>>> func.h Rand()
+float Rand();
+//>>> func.h Neutral()
+float Neutral(float value, float dead);
+
+//>>> func.h PropAngle()
+float Prop(int a, int b, float p);
+//>>> func.h Smooth()
+float Smooth(float actual, float hope, float time);
+//>>> func.h Bounce()
+float Bounce(float progress, float middle=0.3f, float bounce=0.4f);
+
+
+//>>> geometry.h SegmentPoint()
+D3DVECTOR SegmentDist(const D3DVECTOR &p1, const D3DVECTOR &p2, float dist);
+
+//>>> geometry.h Intersect()
+bool Intersect(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c, D3DVECTOR d, D3DVECTOR e, D3DVECTOR &i);
+
+//>>> geometry.h IntersectY()
+bool IntersectY(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c, D3DVECTOR &p);
+
+//>>> geometry.h RotatePoint()
+void RotatePoint(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p);
+
+//>>> geometry.h RotatePoint2()
+void RotatePoint2(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p);
+
+//>>> geometry.h RotateView()
+D3DVECTOR RotateView(D3DVECTOR center, float angleH, float angleV, float dist);
+
+//>>> geometry.h LookatPoint()
+D3DVECTOR LookatPoint( D3DVECTOR eye, float angleH, float angleV, float length );
+
+//>>> vector.h Vector::Length()
+float Length(const D3DVECTOR &u);
+
+//>>> vector.h Distance()
+float Length(const D3DVECTOR &a, const D3DVECTOR &b);
+
+//>>> geometry.h DistanceProjected()
+float Length2d(const D3DVECTOR &a, const D3DVECTOR &b);
+
+//>>> vector.h Angle()
+float Angle( D3DVECTOR u, D3DVECTOR v );
+
+//>>> vector.h CrossProduct()
+D3DVECTOR Cross( D3DVECTOR u, D3DVECTOR v );
+
+//>>> geometry.h NormalToPlane()
+D3DVECTOR ComputeNormal( D3DVECTOR p1, D3DVECTOR p2, D3DVECTOR p3 );
+
+//>>> geometry.h Transform()
+D3DVECTOR Transform(const D3DMATRIX &m, D3DVECTOR p);
+
+//>>> geometry.h Projection()
+D3DVECTOR Projection(const D3DVECTOR &a, const D3DVECTOR &b, const D3DVECTOR &p);
+
+//>>> geometry.h DistanceToPlane()
+float DistancePlanPoint(const D3DVECTOR &a, const D3DVECTOR &b, const D3DVECTOR &c, const D3DVECTOR &p);
+
+//>>> geometry.h IsSamePlane()
+bool IsSamePlane(D3DVECTOR *plan1, D3DVECTOR *plan2);
+
+//>>> geometry.h LoadRotationXZYMatrix()
+void MatRotateXZY(D3DMATRIX &mat, D3DVECTOR angle);
+
+//>>> geometry.h LoadRotationZXYMatrix()
+void MatRotateZXY(D3DMATRIX &mat, D3DVECTOR angle);
+
+
+
+// UNUSED
+float MidPoint(FPOINT a, FPOINT b, float px);
+
+// UNUSED
+bool LineFunction(FPOINT p1, FPOINT p2, float &a, float &b);
+
+
+
+
+// Returns true if two numbers are nearly equal.
+
+bool IsEqual(float a, float b)
+{
+ return Abs(a-b) < MATH3D_CHOUIA;
+}
+
+
+// Returns the minimum value.
+
+float Min(float a, float b)
+{
+ if ( a <= b ) return a;
+ else return b;
+}
+
+float Min(float a, float b, float c)
+{
+ return Min( Min(a,b), c );
+}
+
+float Min(float a, float b, float c, float d)
+{
+ return Min( Min(a,b), Min(c,d) );
+}
+
+float Min(float a, float b, float c, float d, float e)
+{
+ return Min( Min(a,b), Min(c,d), e );
+}
+
+
+// Returns the maximum value.
+
+float Max(float a, float b)
+{
+ if ( a >= b ) return a;
+ else return b;
+}
+
+float Max(float a, float b, float c)
+{
+ return Max( Max(a,b), c );
+}
+
+float Max(float a, float b, float c, float d)
+{
+ return Max( Max(a,b), Max(c,d) );
+}
+
+float Max(float a, float b, float c, float d, float e)
+{
+ return Max( Max(a,b), Max(c,d), e );
+}
+
+
+// Returns the normalized value (0 .. 1).
+
+float Norm(float a)
+{
+ if ( a < 0.0f ) return 0.0f;
+ if ( a > 1.0f ) return 1.0f;
+ return a;
+}
+
+
+// Returns the absolute value of a number.
+
+float Abs(float a)
+{
+ return (float)fabs(a);
+}
+
+
+// Swaps two integers.
+
+void Swap(int &a, int &b)
+{
+ int c;
+
+ c = a;
+ a = b;
+ b = c;
+}
+
+// Swaps two real numbers.
+
+void Swap(float &a, float &b)
+{
+ float c;
+
+ c = a;
+ a = b;
+ b = c;
+}
+
+// Permutes two points.
+
+void Swap(FPOINT &a, FPOINT &b)
+{
+ FPOINT c;
+
+ c = a;
+ a = b;
+ b = c;
+}
+
+// Returns the modulo of a floating point number.
+// Mod(8.1, 4) = 0.1
+// Mod(n, 1) = fractional part of n
+
+float Mod(float a, float m)
+{
+ return a - ((int)(a/m))*m;
+}
+
+// Returns a normalized angle, that is in other words between 0 and 2 * MATH3D_PI.
+
+float NormAngle(float angle)
+{
+ angle = Mod(angle, MATH3D_PI*2.0f);
+ if ( angle < 0.0f )
+ {
+ return MATH3D_PI*2.0f + angle;
+ }
+ else
+ {
+ return angle;
+ }
+}
+
+// Test if a angle is between two terminals.
+
+bool TestAngle(float angle, float min, float max)
+{
+ angle = NormAngle(angle);
+ min = NormAngle(min);
+ max = NormAngle(max);
+
+ if ( min > max )
+ {
+ return ( angle <= max || angle >= min );
+ }
+ else
+ {
+ return ( angle >= min && angle <= max );
+ }
+}
+
+
+// Calculates the angle to rotate the angle a to the angle g.
+// A positive angle is counterclockwise (CCW).
+
+float Direction(float a, float g)
+{
+ a = NormAngle(a);
+ g = NormAngle(g);
+
+ if ( a < g )
+ {
+ if ( a+MATH3D_PI*2.0f-g < g-a ) a += MATH3D_PI*2.0f;
+ }
+ else
+ {
+ if ( g+MATH3D_PI*2.0f-a < a-g ) g += MATH3D_PI*2.0f;
+ }
+ return (g-a);
+}
+
+
+// Rotates a point around a center.
+// The angle is in radians.
+// A positive angle is counterclockwise (CCW).
+
+FPOINT RotatePoint(FPOINT center, float angle, FPOINT p)
+{
+ FPOINT a, b;
+
+ a.x = p.x-center.x;
+ a.y = p.y-center.y;
+
+ b.x = a.x*cosf(angle) - a.y*sinf(angle);
+ b.y = a.x*sinf(angle) + a.y*cosf(angle);
+
+ b.x += center.x;
+ b.y += center.y;
+ return b;
+}
+
+// Rotates a point around the origin.
+// The angle is in radians.
+// A positive angle is counterclockwise (CCW).
+
+FPOINT RotatePoint(float angle, FPOINT p)
+{
+ FPOINT a;
+
+ a.x = p.x*cosf(angle) - p.y*sinf(angle);
+ a.y = p.x*sinf(angle) + p.y*cosf(angle);
+
+ return a;
+}
+
+// Rotates a vector (dist, 0).
+// The angle is in radians.
+// A positive angle is counterclockwise (CCW).
+
+FPOINT RotatePoint(float angle, float dist)
+{
+ FPOINT a;
+
+ a.x = dist*cosf(angle);
+ a.y = dist*sinf(angle);
+
+ return a;
+}
+
+// Calculates the angle of a right triangle.
+// The angle is counterclockwise (CCW), between 0 and 2 * MATH3D_PI.
+// For an angle clockwise (CW), just go ahead.
+//
+// ^
+// |
+// y o----o
+// | / |
+// |/)a |
+// ----o----o-->
+// | x
+// |
+
+float RotateAngle(float x, float y)
+{
+#if 1
+ if ( x == 0.0f && y == 0.0f ) return 0.0f;
+
+ if ( x >= 0.0f )
+ {
+ if ( y >= 0.0f )
+ {
+ if ( x > y ) return atanf(y/x);
+ else return MATH3D_PI*0.5f - atanf(x/y);
+ }
+ else
+ {
+ if ( x > -y ) return MATH3D_PI*2.0f + atanf(y/x);
+ else return MATH3D_PI*1.5f - atanf(x/y);
+ }
+ }
+ else
+ {
+ if ( y >= 0.0f )
+ {
+ if ( -x > y ) return MATH3D_PI*1.0f + atanf(y/x);
+ else return MATH3D_PI*0.5f - atanf(x/y);
+ }
+ else
+ {
+ if ( -x > -y ) return MATH3D_PI*1.0f + atanf(y/x);
+ else return MATH3D_PI*1.5f - atanf(x/y);
+ }
+ }
+#else
+ float angle;
+
+ if ( x == 0.0f )
+ {
+ if ( y > 0.0f )
+ {
+ return 90.0f*MATH3D_PI/180.0f;
+ }
+ else
+ {
+ return 270.0f*MATH3D_PI/180.0f;
+ }
+ }
+ else
+ {
+ angle = atanf(y/x);
+ if ( x < 0.0f )
+ {
+ angle += MATH3D_PI;
+ }
+ return angle;
+ }
+#endif
+}
+
+// Calculates the angle between two points and one center.
+// The angle is in radians.
+// A positive angle is counterclockwise (CCW).
+
+float RotateAngle(FPOINT center, FPOINT p1, FPOINT p2)
+{
+ float a1, a2, a;
+
+ if ( p1.x == center.x &&
+ p1.y == center.y ) return 0;
+
+ if ( p2.x == center.x &&
+ p2.y == center.y ) return 0;
+
+ a1 = asinf((p1.y-center.y)/Length(p1,center));
+ a2 = asinf((p2.y-center.y)/Length(p2,center));
+
+ if ( p1.x < center.x ) a1 = MATH3D_PI-a1;
+ if ( p2.x < center.x ) a2 = MATH3D_PI-a2;
+
+ a = a2-a1;
+ if ( a < 0 ) a += MATH3D_PI*2;
+ return a;
+}
+
+// Returns py up on the line ab.
+
+float MidPoint(FPOINT a, FPOINT b, float px)
+{
+ if ( Abs(a.x-b.x) < MATH3D_CHOUIA )
+ {
+ if ( a.y < b.y ) return MATH3D_BEAUCOUP;
+ else return -MATH3D_BEAUCOUP;
+ }
+ return (b.y-a.y)*(px-a.x)/(b.x-a.x)+a.y;
+}
+
+// Advance "dist" along the segment p1-p2.
+
+D3DVECTOR SegmentDist(const D3DVECTOR &p1, const D3DVECTOR &p2, float dist)
+{
+ return p1+Normalize(p2-p1)*dist;
+}
+
+// Check if a point is inside a triangle.
+
+bool IsInsideTriangle(FPOINT a, FPOINT b, FPOINT c, FPOINT p)
+{
+ float n, m;
+
+ if ( p.x < a.x && p.x < b.x && p.x < c.x ) return false;
+ if ( p.x > a.x && p.x > b.x && p.x > c.x ) return false;
+ if ( p.y < a.y && p.y < b.y && p.y < c.y ) return false;
+ if ( p.y > a.y && p.y > b.y && p.y > c.y ) return false;
+
+ if ( a.x > b.x ) Swap(a,b);
+ if ( a.x > c.x ) Swap(a,c);
+ if ( c.x < a.x ) Swap(c,a);
+ if ( c.x < b.x ) Swap(c,b);
+
+ n = MidPoint(a, b, p.x);
+ m = MidPoint(a, c, p.x);
+ if ( (n>p.y||p.y>m) && (n<p.y||p.y<m) ) return false;
+
+ n = MidPoint(c, b, p.x);
+ m = MidPoint(c, a, p.x);
+ if ( (n>p.y||p.y>m) && (n<p.y||p.y<m) ) return false;
+
+ return true;
+}
+
+// Calculates the intersection "i" right "of" the plan "abc".
+
+bool Intersect(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c,
+ D3DVECTOR d, D3DVECTOR e, D3DVECTOR &i)
+{
+ float d1, d2;
+
+ d1 = (d.x-a.x)*((b.y-a.y)*(c.z-a.z)-(c.y-a.y)*(b.z-a.z)) -
+ (d.y-a.y)*((b.x-a.x)*(c.z-a.z)-(c.x-a.x)*(b.z-a.z)) +
+ (d.z-a.z)*((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y));
+
+ d2 = (d.x-e.x)*((b.y-a.y)*(c.z-a.z)-(c.y-a.y)*(b.z-a.z)) -
+ (d.y-e.y)*((b.x-a.x)*(c.z-a.z)-(c.x-a.x)*(b.z-a.z)) +
+ (d.z-e.z)*((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y));
+
+ if ( d2 == 0 ) return false;
+
+ i.x = d.x + d1/d2*(e.x-d.x);
+ i.y = d.y + d1/d2*(e.y-d.y);
+ i.z = d.z + d1/d2*(e.z-d.z);
+ return true;
+}
+
+// Calculates the intersection of the straight line passing through p (x, z)
+// parallel to the y axis, with the plane abc. Returns p.y.
+
+bool IntersectY(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c, D3DVECTOR &p)
+{
+#if 0
+ D3DVECTOR d,e,i;
+
+ d.x = p.x;
+ d.y = 0.0f;
+ d.z = p.z;
+ e.x = p.x;
+ e.y = 1.0f;
+ e.z = p.z;
+ if ( !Intersect(a,b,c,d,e,i) ) return false;
+ p.y = i.y;
+ return true;
+#else
+ float d, d1, d2;
+
+ d = (b.x-a.x)*(c.z-a.z) - (c.x-a.x)*(b.z-a.z);
+ d1 = (p.x-a.x)*(c.z-a.z) - (c.x-a.x)*(p.z-a.z);
+ d2 = (b.x-a.x)*(p.z-a.z) - (p.x-a.x)*(b.z-a.z);
+
+ if ( d == 0.0f ) return false;
+
+ p.y = a.y + d1/d*(b.y-a.y) + d2/d*(c.y-a.y);
+ return true;
+#endif
+}
+
+
+// Rotates a point around a center in the plan.
+// The angle is in radians.
+// A positive angle is counterclockwise (CCW).
+
+void RotatePoint(float cx, float cy, float angle, float &px, float &py)
+{
+ float ax, ay;
+
+ px -= cx;
+ py -= cy;
+
+ ax = px*cosf(angle) - py*sinf(angle);
+ ay = px*sinf(angle) + py*cosf(angle);
+
+ px = cx+ax;
+ py = cy+ay;
+}
+
+// Rotates a point around a center in space.
+// The angle is in radians.
+// A positive angle is counterclockwise (CCW).
+
+void RotatePoint(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p)
+{
+ D3DVECTOR a, b;
+
+ p.x -= center.x;
+ p.y -= center.y;
+ p.z -= center.z;
+
+ b.x = p.x*cosf(angleH) - p.z*sinf(angleH);
+ b.y = p.z*sinf(angleV) + p.y*cosf(angleV);
+ b.z = p.x*sinf(angleH) + p.z*cosf(angleH);
+
+ p.x = center.x+b.x;
+ p.y = center.y+b.y;
+ p.z = center.z+b.z;
+}
+
+// Rotates a point around a center in space.
+// The angle is in radians.
+// A positive angle is counterclockwise (CCW).
+
+void RotatePoint2(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p)
+{
+ D3DVECTOR a, b;
+
+ p.x -= center.x;
+ p.y -= center.y;
+ p.z -= center.z;
+
+ a.x = p.x*cosf(angleH) - p.z*sinf(angleH);
+ a.y = p.y;
+ a.z = p.x*sinf(angleH) + p.z*cosf(angleH);
+
+ b.x = a.x;
+ b.y = a.z*sinf(angleV) + a.y*cosf(angleV);
+ b.z = a.z*cosf(angleV) - a.y*sinf(angleV);
+
+ p.x = center.x+b.x;
+ p.y = center.y+b.y;
+ p.z = center.z+b.z;
+}
+
+// Calculation point of view to look at a center
+// two angles and a distance.
+
+D3DVECTOR RotateView(D3DVECTOR center, float angleH, float angleV, float dist)
+{
+ D3DMATRIX mat1, mat2, mat;
+ D3DVECTOR eye;
+
+ D3DUtil_SetRotateZMatrix(mat1, -angleV);
+ D3DUtil_SetRotateYMatrix(mat2, -angleH);
+ D3DMath_MatrixMultiply(mat, mat1, mat2);
+
+ eye.x = 0.0f+dist;
+ eye.y = 0.0f;
+ eye.z = 0.0f;
+ eye = Transform(mat, eye);
+
+ return eye+center;
+}
+
+// Calculates the end point.
+
+D3DVECTOR LookatPoint( D3DVECTOR eye, float angleH, float angleV, float length )
+{
+ D3DVECTOR lookat;
+
+ lookat = eye;
+ lookat.z += length;
+
+//? RotatePoint(eye.x, eye.z, angleH, lookat.x, lookat.z);
+//? RotatePoint(eye.z, eye.y, angleV, lookat.z, lookat.y);
+ RotatePoint(eye, angleH, angleV, lookat);
+
+ return lookat;
+}
+
+
+// Returns the distance between two points.
+
+float Length(FPOINT a, FPOINT b)
+{
+ return sqrtf( (a.x-b.x)*(a.x-b.x) +
+ (a.y-b.y)*(a.y-b.y) );
+}
+
+// Returns the hypotenuse of a right triangle.
+
+float Length(float x, float y)
+{
+ return sqrtf( (x*x) + (y*y) );
+}
+
+// Returns the length of a vector.
+
+float Length(const D3DVECTOR &u)
+{
+ return sqrtf( (u.x*u.x) + (u.y*u.y) + (u.z*u.z) );
+}
+
+// Returns the distance between two points.
+
+float Length(const D3DVECTOR &a, const D3DVECTOR &b)
+{
+ return sqrtf( (a.x-b.x)*(a.x-b.x) +
+ (a.y-b.y)*(a.y-b.y) +
+ (a.z-b.z)*(a.z-b.z) );
+}
+
+// Returns the distance "a flat" between two points.
+
+float Length2d(const D3DVECTOR &a, const D3DVECTOR &b)
+{
+ return sqrtf( (a.x-b.x)*(a.x-b.x) +
+ (a.z-b.z)*(a.z-b.z) );
+}
+
+
+// Returns the angle formed by two vectors.
+
+float Angle( D3DVECTOR u, D3DVECTOR v )
+{
+#if 0
+ return acosf( Abs(u.x*v.x + u.y*v.y + u.z*v.z) / (Length(u)*Length(v)) );
+#endif
+#if 0
+ float d;
+ d = (u.y*v.z-u.z*v.y) + (u.z*v.x-u.x*v.z) + (u.x*v.y-u.y*v.x);
+ return asinf( Abs(d) / (Length(u)*Length(v)) );
+#endif
+#if 0
+ return asinf( Length(Cross(u,v)) / (Length(u)*Length(v)) );
+#endif
+#if 1
+ float len, a, b;
+
+ len = Length(u)*Length(v);
+ a = acosf( (u.x*v.x + u.y*v.y + u.z*v.z) / len );
+ b = asinf( Length(Cross(u,v)) / len );
+ return a;
+#endif
+}
+
+// Returns the product of two vectors.
+
+D3DVECTOR Cross( D3DVECTOR u, D3DVECTOR v )
+{
+ return D3DVECTOR( u.y*v.z - u.z*v.y,
+ u.z*v.x - u.x*v.z,
+ u.x*v.y - u.y*v.x );
+}
+
+// Returns the normal vector of a triangular face.
+
+D3DVECTOR ComputeNormal( D3DVECTOR p1, D3DVECTOR p2, D3DVECTOR p3 )
+{
+ D3DVECTOR u, v;
+
+ u = D3DVECTOR( p3.x-p1.x, p3.y-p1.y, p3.z-p1.z );
+ v = D3DVECTOR( p2.x-p1.x, p2.y-p1.y, p2.z-p1.z );
+
+ return Normalize(Cross(u, v));
+}
+
+
+// Transforms a point in a matrix, in exactly the same manner as Direct3D.
+
+D3DVECTOR Transform(const D3DMATRIX &m, D3DVECTOR p)
+{
+ D3DVECTOR pp;
+
+ pp.x = p.x*m._11 + p.y*m._21 + p.z*m._31 + m._41;
+ pp.y = p.x*m._12 + p.y*m._22 + p.z*m._32 + m._42;
+ pp.z = p.x*m._13 + p.y*m._23 + p.z*m._33 + m._43;
+
+ return pp;
+}
+
+
+// Calculates the projection of a point P on a straight line AB.
+
+D3DVECTOR Projection(const D3DVECTOR &a, const D3DVECTOR &b, const D3DVECTOR &p)
+{
+ float k;
+
+ k = (b.x-a.x)*(p.x-a.x) + (b.y-a.y)*(p.y-a.y) + (b.z-a.z)*(p.z-a.z);
+ k /= (b.x-a.x)*(b.x-a.x) + (b.y-a.y)*(b.y-a.y) + (b.z-a.z)*(b.z-a.z);
+
+ return a + k*(b-a);
+}
+
+// The texture plate in the xz plane.
+
+void MappingObject(D3DVERTEX2* pVertices, int nb, float scale)
+{
+ int i;
+
+ for ( i=0 ; i<nb ; i++ )
+ {
+ pVertices[i].tu = pVertices[i].x*scale;
+ pVertices[i].tv = pVertices[i].z*scale;
+ }
+}
+
+// Smooths normal.
+
+void SmoothObject(D3DVERTEX2* pVertices, int nb)
+{
+ char* bDone;
+ int index[100];
+ int i, j, rank;
+ D3DVECTOR sum;
+
+ bDone = (char*)malloc(nb*sizeof(char));
+ ZeroMemory(bDone, nb*sizeof(char));
+
+ for ( i=0 ; i<nb ; i++ )
+ {
+ bDone[i] = true;
+ rank = 0;
+ index[rank++] = i;
+
+ for ( j=0 ; j<nb ; j++ )
+ {
+ if ( bDone[j] ) continue;
+ if ( pVertices[j].x == pVertices[i].x &&
+ pVertices[j].y == pVertices[i].y &&
+ pVertices[j].z == pVertices[i].z )
+ {
+ bDone[j] = true;
+ index[rank++] = j;
+ if ( rank >= 100 ) break;
+ }
+ }
+
+ sum.x = 0;
+ sum.y = 0;
+ sum.z = 0;
+ for ( j=0 ; j<rank ; j++ )
+ {
+ sum.x += pVertices[index[j]].nx;
+ sum.y += pVertices[index[j]].ny;
+ sum.z += pVertices[index[j]].nz;
+ }
+ sum = Normalize(sum);
+
+ for ( j=0 ; j<rank ; j++ )
+ {
+ pVertices[index[j]].nx = sum.x;
+ pVertices[index[j]].ny = sum.y;
+ pVertices[index[j]].nz = sum.z;
+ }
+ }
+
+ free(bDone);
+}
+
+
+
+// Calculates the parameters a and b of the segment passing
+// through the points p1 and p2, knowing that:
+// f(x) = ax+b
+// Returns false if the line is vertical.
+
+bool LineFunction(FPOINT p1, FPOINT p2, float &a, float &b)
+{
+ if ( D3DMath_IsZero(p1.x-p2.x) )
+ {
+ a = g_HUGE; // infinite slope!
+ b = p2.x;
+ return false;
+ }
+
+ a = (p2.y-p1.y)/(p2.x-p1.x);
+ b = p2.y - p2.x*a;
+ return true;
+}
+
+
+// Calculates the distance between a plane ABC and a point P.
+
+float DistancePlanPoint(const D3DVECTOR &a, const D3DVECTOR &b,
+ const D3DVECTOR &c, const D3DVECTOR &p)
+{
+ D3DVECTOR n;
+ float aa,bb,cc,dd;
+
+ n = ComputeNormal(a,b,c);
+
+ aa = n.x;
+ bb = n.y;
+ cc = n.z;
+ dd = -(n.x*a.x + n.y*a.y + n.z*a.z);
+
+ return Abs(aa*p.x + bb*p.y + cc*p.z + dd);
+}
+
+// Check if two planes defined by 3 points are part of the same plan.
+
+bool IsSamePlane(D3DVECTOR *plan1, D3DVECTOR *plan2)
+{
+ D3DVECTOR n1, n2;
+ float dist;
+
+ n1 = ComputeNormal(plan1[0], plan1[1], plan1[2]);
+ n2 = ComputeNormal(plan2[0], plan2[1], plan2[2]);
+
+ if ( Abs(n1.x-n2.x) > 0.1f ||
+ Abs(n1.y-n2.y) > 0.1f ||
+ Abs(n1.z-n2.z) > 0.1f ) return false;
+
+ dist = DistancePlanPoint(plan1[0], plan1[1], plan1[2], plan2[0]);
+ if ( dist > 0.1f ) return false;
+
+ return true;
+}
+
+
+// Calculates the matrix to make three rotations in the X, Y and Z
+// >>>>>> OPTIMIZING!!!
+
+void MatRotateXZY(D3DMATRIX &mat, D3DVECTOR angle)
+{
+ D3DMATRIX temp;
+
+ D3DUtil_SetRotateXMatrix(temp, angle.x);
+ D3DUtil_SetRotateZMatrix(mat, angle.z);
+ D3DMath_MatrixMultiply(mat, mat, temp);
+ D3DUtil_SetRotateYMatrix(temp, angle.y);
+ D3DMath_MatrixMultiply(mat, mat, temp); // X-Z-Y
+}
+
+// Calculates the matrix to make three rotations in the order Z, X and Y.
+// >>>>>> OPTIMIZING!!!
+
+void MatRotateZXY(D3DMATRIX &mat, D3DVECTOR angle)
+{
+ D3DMATRIX temp;
+
+ D3DUtil_SetRotateZMatrix(temp, angle.z);
+ D3DUtil_SetRotateXMatrix(mat, angle.x);
+ D3DMath_MatrixMultiply(mat, mat, temp);
+ D3DUtil_SetRotateYMatrix(temp, angle.y);
+ D3DMath_MatrixMultiply(mat, mat, temp); // Z-X-Y
+}
+
+
+// Returns a random value between 0 and 1.
+
+float Rand()
+{
+ return (float)rand()/RAND_MAX;
+}
+
+
+// Managing the dead zone of a joystick.
+
+// in: -1 0 1
+// --|-------|----o----|-------|-->
+// <---->
+// dead
+// out: -1 0 0 1
+
+float Neutral(float value, float dead)
+{
+ if ( Abs(value) <= dead )
+ {
+ return 0.0f;
+ }
+ else
+ {
+ if ( value > 0.0f ) return (value-dead)/(1.0f-dead);
+ else return (value+dead)/(1.0f-dead);
+ }
+}
+
+
+// Calculates a value (radians) proportional between a and b (degrees).
+
+float Prop(int a, int b, float p)
+{
+ float aa, bb;
+
+ aa = (float)a*MATH3D_PI/180.0f;
+ bb = (float)b*MATH3D_PI/180.0f;
+
+ return aa+p*(bb-aa);
+}
+
+// Gently advanced a desired value from its current value.
+// Over time, the greater the progression is rapid.
+
+float Smooth(float actual, float hope, float time)
+{
+ float futur;
+
+ futur = actual + (hope-actual)*time;
+
+ if ( hope > actual )
+ {
+ if ( futur > hope ) futur = hope;
+ }
+ if ( hope < actual )
+ {
+ if ( futur < hope ) futur = hope;
+ }
+
+ return futur;
+}
+
+
+// Bounces any movement.
+
+// out
+// |
+// 1+------o-------o---
+// | o | o o | | bounce
+// | o | o---|---
+// | o | |
+// | o | |
+// -o------|-------+----> progress
+// 0| | 1
+// |<---->|middle
+
+float Bounce(float progress, float middle, float bounce)
+{
+ if ( progress < middle )
+ {
+ progress = progress/middle; // 0..1
+ return 0.5f+sinf(progress*MATH3D_PI-MATH3D_PI/2.0f)/2.0f;
+ }
+ else
+ {
+ progress = (progress-middle)/(1.0f-middle); // 0..1
+ return (1.0f-bounce/2.0f)+sinf((0.5f+progress*2.0f)*MATH3D_PI)*(bounce/2.0f);
+ }
+}
+
+
+// Returns the color corresponding D3DCOLOR.
+
+D3DCOLOR RetColor(float intensity)
+{
+ D3DCOLOR color;
+
+ if ( intensity <= 0.0f ) return 0x00000000;
+ if ( intensity >= 1.0f ) return 0xffffffff;
+
+ color = (int)(intensity*255.0f)<<24;
+ color |= (int)(intensity*255.0f)<<16;
+ color |= (int)(intensity*255.0f)<<8;
+ color |= (int)(intensity*255.0f);
+
+ return color;
+}
+
+// Returns the color corresponding D3DCOLOR.
+
+D3DCOLOR RetColor(D3DCOLORVALUE intensity)
+{
+ D3DCOLOR color;
+
+ color = (int)(intensity.a*255.0f)<<24;
+ color |= (int)(intensity.r*255.0f)<<16;
+ color |= (int)(intensity.g*255.0f)<<8;
+ color |= (int)(intensity.b*255.0f);
+
+ return color;
+}
+
+// Returns the color corresponding D3DCOLORVALUE.
+
+D3DCOLORVALUE RetColor(D3DCOLOR intensity)
+{
+ D3DCOLORVALUE color;
+
+ color.r = (float)((intensity>>16)&0xff)/256.0f;
+ color.g = (float)((intensity>>8 )&0xff)/256.0f;
+ color.b = (float)((intensity>>0 )&0xff)/256.0f;
+ color.a = (float)((intensity>>24)&0xff)/256.0f;
+
+ return color;
+}
+
+
+// RGB to HSV conversion.
+
+void RGB2HSV(D3DCOLORVALUE src, ColorHSV &dest)
+{
+ float min, max, delta;
+
+ min = Min(src.r, src.g, src.b);
+ max = Max(src.r, src.g, src.b);
+
+ dest.v = max; // intensity
+
+ if ( max == 0.0f )
+ {
+ dest.s = 0.0f; // saturation
+ dest.h = 0.0f; // undefined color!
+ }
+ else
+ {
+ delta = max-min;
+ dest.s = delta/max; // saturation
+
+ if ( src.r == max ) // between yellow & magenta
+ {
+ dest.h = (src.g-src.b)/delta;
+ }
+ else if ( src.g == max ) // between cyan & yellow
+ {
+ dest.h = 2.0f+(src.b-src.r)/delta;
+ }
+ else // between magenta & cyan
+ {
+ dest.h = 4.0f+(src.r-src.g)/delta;
+ }
+
+ dest.h *= 60.0f; // in degrees
+ if ( dest.h < 0.0f ) dest.h += 360.0f;
+ dest.h /= 360.0f; // 0..1
+ }
+}
+
+// HSV to RGB conversion.
+
+void HSV2RGB(ColorHSV src, D3DCOLORVALUE &dest)
+{
+ int i;
+ float f,v,p,q,t;
+
+ src.h = Norm(src.h)*360.0f;
+ src.s = Norm(src.s);
+ src.v = Norm(src.v);
+
+ if ( src.s == 0.0f ) // zero saturation?
+ {
+ dest.r = src.v;
+ dest.g = src.v;
+ dest.b = src.v; // gray
+ }
+ else
+ {
+ if ( src.h == 360.0f ) src.h = 0.0f;
+ src.h /= 60.0f;
+ i = (int)src.h; // integer part (0 .. 5)
+ f = src.h-i; // fractional part
+
+ v = src.v;
+ p = src.v*(1.0f-src.s);
+ q = src.v*(1.0f-(src.s*f));
+ t = src.v*(1.0f-(src.s*(1.0f-f)));
+
+ switch (i)
+ {
+ case 0: dest.r=v; dest.g=t; dest.b=p; break;
+ case 1: dest.r=q; dest.g=v; dest.b=p; break;
+ case 2: dest.r=p; dest.g=v; dest.b=t; break;
+ case 3: dest.r=p; dest.g=q; dest.b=v; break;
+ case 4: dest.r=t; dest.g=p; dest.b=v; break;
+ case 5: dest.r=v; dest.g=p; dest.b=q; break;
+ }
+ }
+}
+
diff --git a/src/old/math3d.h b/src/old/math3d.h
index 5ef6f43..54bc5ea 100644
--- a/src/old/math3d.h
+++ b/src/old/math3d.h
@@ -1,48 +1,48 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// math3d.h
-
-#pragma once
-
-
-#include <math.h>
-
-#include "common/struct.h"
-
-
-// TODO
-void MappingObject( D3DVERTEX2* pVertices, int nb, float scale );
-
-// TODO
-void SmoothObject( D3DVERTEX2* pVertices, int nb );
-
-// TODO
-D3DCOLOR RetColor(float intensity);
-
-// TODO
-D3DCOLOR RetColor(D3DCOLORVALUE intensity);
-
-// TODO
-D3DCOLORVALUE RetColor(D3DCOLOR intensity);
-
-// TODO
-void RGB2HSV(D3DCOLORVALUE src, ColorHSV &dest);
-
-// TODO
-void HSV2RGB(ColorHSV src, D3DCOLORVALUE &dest);
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// math3d.h
+
+#pragma once
+
+
+#include <math.h>
+
+#include "common/struct.h"
+
+
+// TODO
+void MappingObject( D3DVERTEX2* pVertices, int nb, float scale );
+
+// TODO
+void SmoothObject( D3DVERTEX2* pVertices, int nb );
+
+// TODO
+D3DCOLOR RetColor(float intensity);
+
+// TODO
+D3DCOLOR RetColor(D3DCOLORVALUE intensity);
+
+// TODO
+D3DCOLORVALUE RetColor(D3DCOLOR intensity);
+
+// TODO
+void RGB2HSV(D3DCOLORVALUE src, ColorHSV &dest);
+
+// TODO
+void HSV2RGB(ColorHSV src, D3DCOLORVALUE &dest);
+
+
diff --git a/src/old/model.cpp b/src/old/model.cpp
index 23ea6f5..987a870 100644
--- a/src/old/model.cpp
+++ b/src/old/model.cpp
@@ -1,3228 +1,3228 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// model.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "old/water.h"
-#include "object/robotmain.h"
-#include "ui/interface.h"
-#include "ui/edit.h"
-#include "ui/button.h"
-#include "script/cmdtoken.h"
-#include "old/modfile.h"
-#include "old/model.h"
-
-
-
-const int MAX_COLORS = 9;
-
-static float table_color[MAX_COLORS*3] =
-{
- 1.0f, 1.0f, 1.0f, // white
- 1.0f, 0.0f, 0.0f, // red
- 0.0f, 1.0f, 0.0f, // green
- 0.0f, 0.6f, 1.0f, // blue
- 1.0f, 1.0f, 0.0f, // yellow
- 0.0f, 1.0f, 1.0f, // cyan
- 1.0f, 0.0f, 1.0f, // magenta
- 0.3f, 0.3f, 0.3f, // grey
- 0.0f, 0.0f, 0.0f, // black
-};
-
-
-const int MAX_STATES = 10;
-
-static int table_state[MAX_STATES] =
-{
- D3DSTATENORMAL,
- D3DSTATEPART1,
- D3DSTATEPART2,
- D3DSTATEPART3,
- D3DSTATEPART4,
- D3DSTATE2FACE, // #5
- D3DSTATETTw,
- D3DSTATETTb,
- D3DSTATETTw|D3DSTATE2FACE, // #8
- D3DSTATETTb|D3DSTATE2FACE, // #9
-};
-
-
-const int MAX_NAMES = 23;
-
-
-
-
-// Object's constructor.
-
-CModel::CModel(CInstanceManager* iMan)
-{
- m_iMan = iMan;
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
-
- m_modFile = new CModFile(m_iMan);
- m_triangleTable = m_modFile->RetTriangleList();
-
- m_textureRank = 0;
- strcpy(m_textureName, "lemt.tga");
- m_color = 0;
- m_state = 0;
- m_textureMode = 0;
- m_textureRotate = 0;
- m_bTextureMirrorX = false;
- m_bTextureMirrorY = false;
- m_texturePart = 0;
- TexturePartUpdate();
-
- m_bDisplayTransparent = false;
- m_bDisplayOnlySelection = false;
- InitView();
-
- m_triangleSel1 = 0;
- m_triangleSel2 = 0;
-
- m_mode = 1;
- m_oper = 'P';
-
- m_secondTexNum = 0;
- m_secondSubdiv = 1;
- m_secondOffsetU = 0;
- m_secondOffsetV = 0;
-
- m_min = 0.0f;
- m_max = 1000000.0f;
-}
-
-// Object's destructor.
-
-CModel::~CModel()
-{
- delete m_modFile;
-}
-
-
-// You must call this procedure before changing the model interactively.
-
-void CModel::StartUserAction()
-{
- Event event;
- Math::Point pos, dim;
- CButton* pb;
-
- dim.x = 105.0f/640.0f;
- dim.y = 18.0f/480.0f;
- pos.x = 10.0f/640.0f;
- pos.y = 450.0f/480.0f;
- m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT1);
-
- dim.x = 50.0f/640.0f;
- pos.x = 125.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON1);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("Load");
- pos.x = 185.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON2);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("Script");
- pos.x = 245.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON3);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("Read");
- pos.x = 305.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON4);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("Add");
- pos.x = 365.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON5);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("Write");
-
- dim.x = 50.0f/640.0f;
- dim.y = 18.0f/480.0f;
- pos.x = 10.0f/640.0f;
- pos.y = 425.0f/480.0f;
- m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT2);
- pos.x = 65.0f/640.0f;
- pos.y = 425.0f/480.0f;
- m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT3);
- pos.x = 10.0f/640.0f;
- pos.y = 400.0f/480.0f;
- m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT4);
- pos.x = 65.0f/640.0f;
- pos.y = 400.0f/480.0f;
- m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT5);
-
- dim.x = 20.0f/640.0f;
- dim.y = 20.0f/480.0f;
- pos.y = 370.0f/480.0f;
- pos.x = 10.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON10);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("P");
- pos.x = 30.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON11);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("R");
- pos.x = 50.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON12);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("Z");
- pos.y = 350.0f/480.0f;
- pos.x = 10.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON13);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("+X");
- pos.x = 30.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON14);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("+Y");
- pos.x = 50.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON15);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("+Z");
- pos.y = 330.0f/480.0f;
- pos.x = 10.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON16);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("-X");
- pos.x = 30.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON17);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("-Y");
- pos.x = 50.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON18);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("-Z");
-
-//? m_modFile->ReadModel("objects\\io.mod");
- DeselectAll();
- CurrentInit();
-
- ZeroMemory(&event, sizeof(Event));
- EventFrame(event);
-
- m_engine->LoadAllTexture();
- UpdateInfoText();
-}
-
-// You must call this procedure after modifing the model interactively.
-
-void CModel::StopUserAction()
-{
- m_interface->DeleteControl(EVENT_EDIT1);
- m_interface->DeleteControl(EVENT_EDIT2);
- m_interface->DeleteControl(EVENT_EDIT3);
- m_interface->DeleteControl(EVENT_EDIT4);
- m_interface->DeleteControl(EVENT_EDIT5);
- m_interface->DeleteControl(EVENT_BUTTON1);
- m_interface->DeleteControl(EVENT_BUTTON2);
- m_interface->DeleteControl(EVENT_BUTTON3);
- m_interface->DeleteControl(EVENT_BUTTON4);
- m_interface->DeleteControl(EVENT_BUTTON5);
- m_interface->DeleteControl(EVENT_BUTTON10);
- m_interface->DeleteControl(EVENT_BUTTON11);
- m_interface->DeleteControl(EVENT_BUTTON12);
- m_interface->DeleteControl(EVENT_BUTTON13);
- m_interface->DeleteControl(EVENT_BUTTON14);
- m_interface->DeleteControl(EVENT_BUTTON15);
- m_interface->DeleteControl(EVENT_BUTTON16);
- m_interface->DeleteControl(EVENT_BUTTON17);
- m_interface->DeleteControl(EVENT_BUTTON18);
-
- m_engine->SetInfoText(0, "");
- m_engine->SetInfoText(1, "");
-}
-
-
-// Updates the​editable values for mapping textures.
-
-void CModel::PutTextureValues()
-{
- CEdit* pe;
- char s[100];
- int value;
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT2);
- if ( pe != 0 )
- {
- value = (int)(m_textureSup.x*256.0f+0.5f);
- sprintf(s, "%d", value);
- pe->SetText(s);
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT3);
- if ( pe != 0 )
- {
- value = (int)(m_textureSup.y*256.0f+0.5f);
- sprintf(s, "%d", value);
- pe->SetText(s);
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT4);
- if ( pe != 0 )
- {
- value = (int)(m_textureInf.x*256.0f-0.5f);
- sprintf(s, "%d", value);
- pe->SetText(s);
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT5);
- if ( pe != 0 )
- {
- value = (int)(m_textureInf.y*256.0f-0.5f);
- sprintf(s, "%d", value);
- pe->SetText(s);
- }
-}
-
-// Takes the editable values for mapping textures.
-
-void CModel::GetTextureValues()
-{
- CEdit* pe;
- char s[100];
- int value;
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT2);
- if ( pe != 0 )
- {
- pe->GetText(s, 100);
- sscanf(s, "%d", &value);
- m_textureSup.x = ((float)value-0.5f)/256.0f;
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT3);
- if ( pe != 0 )
- {
- pe->GetText(s, 100);
- sscanf(s, "%d", &value);
- m_textureSup.y = ((float)value-0.5f)/256.0f;
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT4);
- if ( pe != 0 )
- {
- pe->GetText(s, 100);
- sscanf(s, "%d", &value);
- m_textureInf.x = ((float)value+0.5f)/256.0f;
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT5);
- if ( pe != 0 )
- {
- pe->GetText(s, 100);
- sscanf(s, "%d", &value);
- m_textureInf.y = ((float)value+0.5f)/256.0f;
- }
-}
-
-
-// Gives the model name.
-
-void CModel::GetModelName(char *buffer)
-{
- CEdit* pe;
- char s[100];
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
- if ( pe == 0 )
- {
- strcpy(buffer, "objects\\io.mod");
- }
- else
- {
- pe->GetText(s, 100);
- sprintf(buffer, "objects\\%s.mod", s);
- }
-}
-
-// Gives the model name.
-
-void CModel::GetDXFName(char *buffer)
-{
- CEdit* pe;
- char s[100];
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
- if ( pe == 0 )
- {
- strcpy(buffer, "models\\import.dxf");
- }
- else
- {
- pe->GetText(s, 100);
- sprintf(buffer, "models\\%s.dxf", s);
- }
-}
-
-// Gives the model name.
-
-void CModel::GetScriptName(char *buffer)
-{
- CEdit* pe;
- char s[100];
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
- if ( pe == 0 )
- {
- strcpy(buffer, "objects\\script.txt");
- }
- else
- {
- pe->GetText(s, 100);
- sprintf(buffer, "objects\\%s.txt", s);
- }
-}
-
-// Indicates whether the edition name has focus.
-
-bool CModel::IsEditFocus()
-{
- CEdit* pe;
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
- if ( pe != 0 )
- {
- if ( pe->RetFocus() ) return true;
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT2);
- if ( pe != 0 )
- {
- if ( pe->RetFocus() ) return true;
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT3);
- if ( pe != 0 )
- {
- if ( pe->RetFocus() ) return true;
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT4);
- if ( pe != 0 )
- {
- if ( pe->RetFocus() ) return true;
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT5);
- if ( pe != 0 )
- {
- if ( pe->RetFocus() ) return true;
- }
-
- return false;
-}
-
-
-// Management of an event.
-
-bool CModel::EventProcess(const Event &event)
-{
- char s[100];
- int first, last;
-
- switch( event.event )
- {
- case EVENT_FRAME:
- EventFrame(event);
- break;
-
- case EVENT_KEYDOWN:
- if ( IsEditFocus() )
- break;
-
- if ( event.param == '1' )
- {
- m_mode = 1;
- UpdateInfoText();
- }
- if ( event.param == '2' )
- {
- m_mode = 2;
- UpdateInfoText();
- }
- if ( event.param == '3' )
- {
- m_mode = 3;
- UpdateInfoText();
- }
- if ( event.param == VK_ADD ) // numpad?
- {
- if ( event.keyState & KS_SHIFT ) CurrentSelect(true);
- CurrentSearchNext(+1, (event.keyState & KS_CONTROL));
- }
- if ( event.param == VK_SUBTRACT ) // least numpad?
- {
- if ( event.keyState & KS_SHIFT ) CurrentSelect(true);
- CurrentSearchNext(-1, (event.keyState & KS_CONTROL));
- }
- if ( event.param == VK_NUMPAD0 )
- {
- CurrentSelect(false);
- }
- if ( event.param == VK_DECIMAL )
- {
- CurrentSelect(true);
- }
- if ( event.param == VK_END )
- {
- DeselectAll();
- }
- if ( event.param == VK_INSERT )
- {
- SelectAll();
- }
- if ( event.param == VK_BACK ) // Delete normal ?
- {
- SelectDelete();
- }
- if ( event.param == VK_SPACE )
- {
- m_bDisplayTransparent = !m_bDisplayTransparent;
- m_bDisplayOnlySelection = false;
- }
- if ( event.param == 'H' )
- {
- m_bDisplayOnlySelection = !m_bDisplayOnlySelection;
- m_bDisplayTransparent = false;
- }
- if ( m_mode == 1 )
- {
- if ( event.param == 'S' )
- {
- SmoothSelect();
- }
- if ( event.param == 'N' )
- {
- PlaneSelect();
- }
- if ( event.param == 'C' )
- {
- ColorSelect();
- }
- if ( event.param == 'V' )
- {
- m_color ++;
- if ( m_color >= MAX_COLORS ) m_color = 0;
- UpdateInfoText();
- ColorSelect();
- }
- if ( event.param == 'J' )
- {
- StateSelect();
- }
- if ( event.param == 'K' )
- {
- m_state ++;
- if ( m_state >= MAX_STATES ) m_state = 0;
- UpdateInfoText();
- StateSelect();
- }
- if ( event.param == 'M' )
- {
- m_textureMode ++;
- if ( m_textureMode > 3 ) m_textureMode = 0;
- UpdateInfoText();
- GetTextureValues();
- MappingSelect(m_textureMode, m_textureRotate,
- m_bTextureMirrorX, m_bTextureMirrorY,
- m_textureInf, m_textureSup, m_textureName);
- }
- if ( event.param == 'Z' )
- {
- m_textureRotate ++;
- if ( m_textureRotate > 2 ) m_textureRotate = 0;
- UpdateInfoText();
- GetTextureValues();
- MappingSelect(m_textureMode, m_textureRotate,
- m_bTextureMirrorX, m_bTextureMirrorY,
- m_textureInf, m_textureSup, m_textureName);
- }
- if ( event.param == 'X' )
- {
- m_bTextureMirrorX = !m_bTextureMirrorX;
- UpdateInfoText();
- GetTextureValues();
- MappingSelect(m_textureMode, m_textureRotate,
- m_bTextureMirrorX, m_bTextureMirrorY,
- m_textureInf, m_textureSup, m_textureName);
- }
- if ( event.param == 'Y' )
- {
- m_bTextureMirrorY = !m_bTextureMirrorY;
- UpdateInfoText();
- GetTextureValues();
- MappingSelect(m_textureMode, m_textureRotate,
- m_bTextureMirrorX, m_bTextureMirrorY,
- m_textureInf, m_textureSup, m_textureName);
- }
- if ( event.param == 'O' )
- {
- TextureRankChange(+1);
- UpdateInfoText();
- }
- if ( event.param == 'P' )
- {
- TexturePartChange(+1);
- UpdateInfoText();
- GetTextureValues();
- MappingSelect(m_textureMode, m_textureRotate,
- m_bTextureMirrorX, m_bTextureMirrorY,
- m_textureInf, m_textureSup, m_textureName);
- }
- if ( event.param == 'T' )
- {
- GetTextureValues();
- MappingSelect(m_textureMode, m_textureRotate,
- m_bTextureMirrorX, m_bTextureMirrorY,
- m_textureInf, m_textureSup, m_textureName);
- }
- if ( event.param == 'E' )
- {
- Math::Point ti, ts;
- ti.x = 0.00f;
- ti.y = 0.00f;
- ts.x = 0.00f;
- ts.y = 0.00f;
- MappingSelect(m_textureMode, m_textureRotate,
- m_bTextureMirrorX, m_bTextureMirrorY,
- ti, ts, "");
- }
- }
- if ( m_mode == 2 )
- {
- if ( event.param == 'E' )
- {
- m_secondTexNum = 0;
- UpdateInfoText();
- MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
- }
- if ( event.param == 'O' )
- {
- m_secondTexNum ++;
- if ( m_secondTexNum > 10 ) m_secondTexNum = 1;
- UpdateInfoText();
- }
- if ( event.param == 'T' )
- {
- MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
- m_engine->LoadAllTexture();
- }
- if ( event.param == 'U' )
- {
- m_secondOffsetU += 45;
- if ( m_secondOffsetU >= 360 ) m_secondOffsetU = 0;
- MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
- UpdateInfoText();
- }
- if ( event.param == 'V' )
- {
- m_secondOffsetV += 45;
- if ( m_secondOffsetV >= 360 ) m_secondOffsetV = 0;
- MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
- UpdateInfoText();
- }
- if ( event.param == 'X' )
- {
- m_bTextureMirrorX = !m_bTextureMirrorX;
- MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
- UpdateInfoText();
- }
- if ( event.param == 'Y' )
- {
- m_bTextureMirrorY = !m_bTextureMirrorY;
- MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
- UpdateInfoText();
- }
- if ( event.param == 'S' )
- {
- m_secondSubdiv ++;
- if ( m_secondSubdiv > 7 ) m_secondSubdiv = 1;
- MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
- UpdateInfoText();
- }
- }
- if ( m_mode == 3 )
- {
- if ( event.param == 'M' )
- {
- if ( m_min == 0.0f && m_max == 1000000.0f )
- {
- m_min = 0.0f; m_max = 100.0f;
- }
- else if ( m_min == 0.0f && m_max == 100.0f )
- {
- m_min = 100.0f; m_max = 200.0f;
- }
- else if ( m_min == 100.0f && m_max == 200.0f )
- {
- m_min = 200.0f; m_max = 1000000.0f;
- }
- else if ( m_min == 200.0f && m_max == 1000000.0f )
- {
- m_min = 0.0f; m_max = 1000000.0f;
- }
- UpdateInfoText();
- }
- if ( event.param == 'C' )
- {
- MinMaxChange();
- }
- }
- break;
-
- case EVENT_BUTTON1: // import ?
- GetDXFName(s);
- m_modFile->ReadDXF(s, m_min, m_max);
- DeselectAll();
- CurrentInit();
- EventFrame(event);
- m_engine->LoadAllTexture();
- break;
-
- case EVENT_BUTTON2: // script ?
- GetScriptName(s);
- ReadScript(s);
- DeselectAll();
- CurrentInit();
- EventFrame(event);
- m_engine->LoadAllTexture();
- break;
-
- case EVENT_BUTTON3: // read ?
- GetModelName(s);
- m_modFile->ReadModel(s, true, false); // standard read with borders
- DeselectAll();
- CurrentInit();
- EventFrame(event);
- m_engine->LoadAllTexture();
- break;
-
- case EVENT_BUTTON4: // add ?
- GetModelName(s);
- first = m_modFile->RetTriangleUsed();
- m_modFile->AddModel(s, first, true, false); // standard read with borders
- last = m_modFile->RetTriangleUsed();
- SelectZone(first, last);
- EventFrame(event);
- break;
-
- case EVENT_BUTTON5: // write ?
- GetModelName(s);
- DeselectAll();
- m_modFile->WriteModel(s);
- break;
-
- case EVENT_BUTTON10: // pos ?
- m_oper = 'P';
- break;
- case EVENT_BUTTON11: // rotate ?
- m_oper = 'R';
- break;
- case EVENT_BUTTON12: // zoom ?
- m_oper = 'Z';
- break;
-
- case EVENT_BUTTON13: // +X ?
- MoveSelect(Math::Vector(1.0f, 0.0f, 0.0f));
- break;
- case EVENT_BUTTON16: // -X ?
- MoveSelect(Math::Vector(-1.0f, 0.0f, 0.0f));
- break;
- case EVENT_BUTTON14: // +Y ?
- MoveSelect(Math::Vector(0.0f, 1.0f, 0.0f));
- break;
- case EVENT_BUTTON17: // -Y ?
- MoveSelect(Math::Vector(0.0f, -1.0f, 0.0f));
- break;
- case EVENT_BUTTON15: // +Z ?
- MoveSelect(Math::Vector(0.0f, 0.0f, 1.0f));
- break;
- case EVENT_BUTTON18: // -Z ?
- MoveSelect(Math::Vector(0.0f, 0.0f, -1.0f));
- break;
- }
-
- return 0;
-}
-
-
-// Drives the model.
-
-bool CModel::EventFrame(const Event &event)
-{
- D3DMATERIAL7 matCurrent, matCurrenti, matCurrents, matTrans;
- D3DMATERIAL7* pMat;
- D3DVERTEX2 vertex[3];
- char texName2[20];
- int i, used, objRank, state;
-
- m_time += event.rTime;
-
- m_engine->FlushObject();
- objRank = m_engine->CreateObject();
-
- ZeroMemory(&matCurrent, sizeof(D3DMATERIAL7));
- matCurrent.diffuse.r = 1.0f;
- matCurrent.diffuse.g = 0.0f;
- matCurrent.diffuse.b = 0.0f; // red
- matCurrent.ambient.r = 0.5f;
- matCurrent.ambient.g = 0.5f;
- matCurrent.ambient.b = 0.5f;
-
- ZeroMemory(&matCurrents, sizeof(D3DMATERIAL7));
- matCurrents.diffuse.r = 1.0f;
- matCurrents.diffuse.g = 1.0f;
- matCurrents.diffuse.b = 0.0f; // yellow
- matCurrents.ambient.r = 0.5f;
- matCurrents.ambient.g = 0.5f;
- matCurrents.ambient.b = 0.5f;
-
- ZeroMemory(&matCurrenti, sizeof(D3DMATERIAL7));
- matCurrenti.diffuse.r = 0.0f;
- matCurrenti.diffuse.g = 0.0f;
- matCurrenti.diffuse.b = 1.0f; // blue
- matCurrenti.ambient.r = 0.5f;
- matCurrenti.ambient.g = 0.5f;
- matCurrenti.ambient.b = 0.5f;
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( !m_triangleTable[i].bUsed ) continue;
-
- if ( m_triangleTable[i].min != m_min ||
- m_triangleTable[i].max != m_max ) continue;
-
- pMat = &m_triangleTable[i].material;
- state = D3DSTATENORMAL;
-
- if ( i >= m_triangleSel1 &&
- i <= m_triangleSel2 &&
- (int)(m_time*10.0f)%2 == 0 )
- {
- pMat = &matCurrent;
- }
- else if ( m_triangleTable[i].bSelect &&
- (int)(m_time*10.0f)%2 == 0 )
- {
- pMat = &matCurrents;
- }
- else
- {
- if ( m_bDisplayOnlySelection ) continue;
- if ( m_bDisplayTransparent )
- {
- matTrans = m_triangleTable[i].material;
- matTrans.diffuse.a = 0.1f; // very transparent
- pMat = &matTrans;
- state = D3DSTATETD;
- }
- }
-
- if ( m_triangleTable[i].texNum2 == 0 )
- {
- m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
- *pMat, state,
- m_triangleTable[i].texName, "",
- 0.0f, 1000000.0f, false);
- }
- else
- {
- sprintf(texName2, "dirty%.2d.tga", m_triangleTable[i].texNum2);
- m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
- *pMat, state|D3DSTATEDUALb,
- m_triangleTable[i].texName, texName2,
- 0.0f, 1000000.0f, false);
- }
-
- if ( m_bDisplayTransparent && // draws inside?
- i >= m_triangleSel1 &&
- i <= m_triangleSel2 )
- {
- vertex[0] = m_triangleTable[i].p3;
- vertex[1] = m_triangleTable[i].p2;
- vertex[2] = m_triangleTable[i].p1;
-
- m_engine->AddTriangle(objRank, vertex, 3,
- matCurrenti, D3DSTATENORMAL,
- m_triangleTable[i].texName, "",
- 0.0f, 1000000.0f, false);
- }
- }
-
- return true;
-}
-
-
-// Gives a vertex.
-
-bool CModel::GetVertex(int rank, D3DVERTEX2 &vertex)
-{
- if ( rank < 0 || rank/3 >= m_modFile->RetTriangleUsed() ) return false;
- if ( !m_triangleTable[rank/3].bUsed ) return false;
-
- if ( !m_triangleTable[rank/3].bSelect ) return false;
-
- if ( rank%3 == 0 )
- {
- vertex = m_triangleTable[rank/3].p1;
- return true;
- }
- if ( rank%3 == 1 )
- {
- vertex = m_triangleTable[rank/3].p2;
- return true;
- }
- if ( rank%3 == 2 )
- {
- vertex = m_triangleTable[rank/3].p3;
- return true;
- }
- return false;
-}
-
-// Modifies a vertex.
-
-bool CModel::SetVertex(int rank, D3DVERTEX2 &vertex)
-{
- if ( rank < 0 || rank/3 >= m_modFile->RetTriangleUsed() ) return false;
- if ( !m_triangleTable[rank/3].bUsed ) return false;
-
- if ( !m_triangleTable[rank/3].bSelect ) return false;
-
- if ( rank%3 == 0 )
- {
- m_triangleTable[rank/3].p1 = vertex;
- return true;
- }
- if ( rank%3 == 1 )
- {
- m_triangleTable[rank/3].p2 = vertex;
- return true;
- }
- if ( rank%3 == 2 )
- {
- m_triangleTable[rank/3].p3 = vertex;
- return true;
- }
- return false;
-}
-
-// Smoothed normals selected triangles.
-
-void CModel::SmoothSelect()
-{
- char* bDone;
- int index[100];
- int used, i, j, rank;
- D3DVERTEX2 vi, vj;
- Math::Vector sum;
-
- used = m_modFile->RetTriangleUsed();
-
- bDone = (char*)malloc(used*3*sizeof(char));
- for ( i=0 ; i<used*3 ; i++ )
- {
- bDone[i] = false;
- }
-
- for ( i=0 ; i<used*3 ; i++ )
- {
- bDone[i] = true;
- rank = 0;
- index[rank++] = i;
- if ( !GetVertex(i, vi) ) continue;
-
- for ( j=0 ; j<used*3 ; j++ )
- {
- if ( bDone[j] ) continue;
- if ( !GetVertex(j, vj) ) continue;
- if ( vj.x == vi.x &&
- vj.y == vi.y &&
- vj.z == vi.z )
- {
- bDone[j] = true;
- index[rank++] = j;
- if ( rank >= 100 ) break;
- }
- }
-
- sum.x = 0;
- sum.y = 0;
- sum.z = 0;
- for ( j=0 ; j<rank ; j++ )
- {
- GetVertex(index[j], vj);
- sum.x += vj.nx;
- sum.y += vj.ny;
- sum.z += vj.nz;
- }
- sum = Normalize(sum);
-
- for ( j=0 ; j<rank ; j++ )
- {
- GetVertex(index[j], vj);
- vj.nx = sum.x;
- vj.ny = sum.y;
- vj.nz = sum.z;
- SetVertex(index[j], vj);
- }
- }
-
- free(bDone);
-
- SelectTerm();
-}
-
-
-// Cast normals selected triangles.
-
-void CModel::PlaneSelect()
-{
- Math::Vector p1, p2, p3, n;
- int used, i;
-
- used = m_modFile->RetTriangleUsed();
-
- for ( i=0 ; i<used ; i++ )
- {
- if ( m_triangleTable[i].bSelect )
- {
- p1.x = m_triangleTable[i].p1.x;
- p1.y = m_triangleTable[i].p1.y;
- p1.z = m_triangleTable[i].p1.z;
-
- p2.x = m_triangleTable[i].p2.x;
- p2.y = m_triangleTable[i].p2.y;
- p2.z = m_triangleTable[i].p2.z;
-
- p3.x = m_triangleTable[i].p3.x;
- p3.y = m_triangleTable[i].p3.y;
- p3.z = m_triangleTable[i].p3.z;
-
- n = Math::NormalToPlane(p3, p2, p1);
-
- m_triangleTable[i].p3.nx = n.x;
- m_triangleTable[i].p3.ny = n.y;
- m_triangleTable[i].p3.nz = n.z;
- }
- }
- SelectTerm();
-}
-
-
-// Change the color of the selected triangles.
-
-void CModel::ColorSelect()
-{
- int used, i;
-
- DefaultSelect();
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( m_triangleTable[i].bSelect )
- {
- m_triangleTable[i].material.diffuse.r = table_color[m_color*3+0];
- m_triangleTable[i].material.diffuse.g = table_color[m_color*3+1];
- m_triangleTable[i].material.diffuse.b = table_color[m_color*3+2];
- }
- }
- SelectTerm();
-}
-
-// Change the status of selected triangles.
-
-void CModel::StateSelect()
-{
- int used, i;
-
- DefaultSelect();
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( m_triangleTable[i].bSelect )
- {
- m_triangleTable[i].state = table_state[m_state];
- }
- }
- SelectTerm();
-}
-
-// Moves the selection.
-
-void CModel::MoveSelect(Math::Vector move)
-{
- if ( m_oper == 'Z' )
- {
- if ( move.x == +1 ) move.x = 1.1f;
- else if ( move.x == -1 ) move.x = 1.0f/1.1f;
- else move.x = 1.0f;
- if ( move.y == +1 ) move.y = 1.1f;
- else if ( move.y == -1 ) move.y = 1.0f/1.1f;
- else move.y = 1.0f;
- if ( move.z == +1 ) move.z = 1.1f;
- else if ( move.z == -1 ) move.z = 1.0f/1.1f;
- else move.z = 1.0f;
- }
- if ( m_oper == 'R' )
- {
-#if 0
- if ( move.x == +1 ) move.x = 5.0f*Math::PI/180.0f;
- else if ( move.x == -1 ) move.x = -5.0f*Math::PI/180.0f;
- if ( move.y == +1 ) move.y = 5.0f*Math::PI/180.0f;
- else if ( move.y == -1 ) move.y = -5.0f*Math::PI/180.0f;
- if ( move.z == +1 ) move.z = 5.0f*Math::PI/180.0f;
- else if ( move.z == -1 ) move.z = -5.0f*Math::PI/180.0f;
-#else
- if ( move.x == +1 ) move.x = 45.0f*Math::PI/180.0f;
- else if ( move.x == -1 ) move.x = -45.0f*Math::PI/180.0f;
- if ( move.y == +1 ) move.y = 45.0f*Math::PI/180.0f;
- else if ( move.y == -1 ) move.y = -45.0f*Math::PI/180.0f;
- if ( move.z == +1 ) move.z = 45.0f*Math::PI/180.0f;
- else if ( move.z == -1 ) move.z = -45.0f*Math::PI/180.0f;
-#endif
- }
-
- OperSelect(move, m_oper);
-}
-
-// Moves the selection.
-
-void CModel::OperSelect(Math::Vector move, char oper)
-{
- Math::Point rot;
- int used, i;
-
- DefaultSelect();
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( m_triangleTable[i].bSelect )
- {
- if ( oper == 'P' )
- {
- m_triangleTable[i].p1.x += move.x;
- m_triangleTable[i].p1.y += move.y;
- m_triangleTable[i].p1.z += move.z;
- m_triangleTable[i].p2.x += move.x;
- m_triangleTable[i].p2.y += move.y;
- m_triangleTable[i].p2.z += move.z;
- m_triangleTable[i].p3.x += move.x;
- m_triangleTable[i].p3.y += move.y;
- m_triangleTable[i].p3.z += move.z;
- }
- if ( oper == 'Z' )
- {
- m_triangleTable[i].p1.x *= move.x;
- m_triangleTable[i].p1.y *= move.y;
- m_triangleTable[i].p1.z *= move.z;
- m_triangleTable[i].p2.x *= move.x;
- m_triangleTable[i].p2.y *= move.y;
- m_triangleTable[i].p2.z *= move.z;
- m_triangleTable[i].p3.x *= move.x;
- m_triangleTable[i].p3.y *= move.y;
- m_triangleTable[i].p3.z *= move.z;
- }
- if ( oper == 'R' )
- {
- if ( move.x != 0 )
- {
- rot.x = m_triangleTable[i].p1.z;
- rot.y = m_triangleTable[i].p1.y;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.x, rot);
- m_triangleTable[i].p1.z = rot.x;
- m_triangleTable[i].p1.y = rot.y;
-
- rot.x = m_triangleTable[i].p2.z;
- rot.y = m_triangleTable[i].p2.y;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.x, rot);
- m_triangleTable[i].p2.z = rot.x;
- m_triangleTable[i].p2.y = rot.y;
-
- rot.x = m_triangleTable[i].p3.z;
- rot.y = m_triangleTable[i].p3.y;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.x, rot);
- m_triangleTable[i].p3.z = rot.x;
- m_triangleTable[i].p3.y = rot.y;
- }
- if ( move.y != 0 )
- {
- rot.x = m_triangleTable[i].p1.x;
- rot.y = m_triangleTable[i].p1.z;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.y, rot);
- m_triangleTable[i].p1.x = rot.x;
- m_triangleTable[i].p1.z = rot.y;
-
- rot.x = m_triangleTable[i].p2.x;
- rot.y = m_triangleTable[i].p2.z;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.y, rot);
- m_triangleTable[i].p2.x = rot.x;
- m_triangleTable[i].p2.z = rot.y;
-
- rot.x = m_triangleTable[i].p3.x;
- rot.y = m_triangleTable[i].p3.z;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.y, rot);
- m_triangleTable[i].p3.x = rot.x;
- m_triangleTable[i].p3.z = rot.y;
- }
- if ( move.z != 0 )
- {
- rot.x = m_triangleTable[i].p1.x;
- rot.y = m_triangleTable[i].p1.y;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.z, rot);
- m_triangleTable[i].p1.x = rot.x;
- m_triangleTable[i].p1.y = rot.y;
-
- rot.x = m_triangleTable[i].p2.x;
- rot.y = m_triangleTable[i].p2.y;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.z, rot);
- m_triangleTable[i].p2.x = rot.x;
- m_triangleTable[i].p2.y = rot.y;
-
- rot.x = m_triangleTable[i].p3.x;
- rot.y = m_triangleTable[i].p3.y;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.z, rot);
- m_triangleTable[i].p3.x = rot.x;
- m_triangleTable[i].p3.y = rot.y;
- }
- }
- }
- }
- SelectTerm();
-}
-
-// Performs a build script.
-
-void CModel::ReadScript(char *filename)
-{
- FILE* file = NULL;
- char line[200];
- char name[200];
- char buffer[200];
- int i, first, last;
- Math::Vector move;
- bool bFirst = true;
-
- file = fopen(filename, "r");
- if ( file == NULL ) return;
-
- while ( fgets(line, 200, file) != NULL )
- {
- for ( i=0 ; i<200 ; i++ )
- {
- if ( line[i] == '\t' ) line[i] = ' '; // replace tab by space
- if ( line[i] == '/' && line[i+1] == '/' )
- {
- line[i] = 0;
- break;
- }
- }
-
- if ( Cmd(line, "Object") )
- {
- OpString(line, "name", name);
- sprintf(buffer, "objects\\%s.mod", name);
-
- if ( bFirst )
- {
- m_modFile->ReadModel(buffer, true, true);
- last = m_modFile->RetTriangleUsed();
- SelectZone(0, last);
- }
- else
- {
- first = m_modFile->RetTriangleUsed();
- m_modFile->AddModel(buffer, first, true, false);
- last = m_modFile->RetTriangleUsed();
- SelectZone(first, last);
- }
- bFirst = false;
-
- move = OpDir(line, "zoom");
- OperSelect(move, 'Z');
-
- move = OpDir(line, "rot");
- move *= Math::PI/180.0f; // degrees -> radians
- OperSelect(move, 'R');
-
- move = OpDir(line, "pos");
- OperSelect(move, 'P');
- }
- }
-
- fclose(file);
-}
-
-
-
-// Computes the bbox of selected triangles.
-
-void CModel::BBoxCompute(Math::Vector &min, Math::Vector &max)
-{
- D3DVERTEX2 vertex;
- int used, i;
-
- min.x = 1000000.0f;
- min.y = 1000000.0f;
- min.z = 1000000.0f;
- max.x = -1000000.0f;
- max.y = -1000000.0f;
- max.z = -1000000.0f;
-
- used = m_modFile->RetTriangleUsed();
-
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( !GetVertex(i, vertex) ) continue;
-
- if ( vertex.x < min.x ) min.x = vertex.x;
- if ( vertex.y < min.y ) min.y = vertex.y;
- if ( vertex.z < min.z ) min.z = vertex.z;
-
- if ( vertex.x > max.x ) max.x = vertex.x;
- if ( vertex.y > max.y ) max.y = vertex.y;
- if ( vertex.z > max.z ) max.z = vertex.z;
- }
-}
-
-// Returns the gravity center of the selection.
-
-Math::Vector CModel::RetSelectCDG()
-{
- Math::Vector min, max, cdg;
-
- BBoxCompute(min, max);
-
- cdg.x = (min.x+max.x)/2.0f;
- cdg.y = (min.y+max.y)/2.0f;
- cdg.z = (min.z+max.z)/2.0f;
-
- return cdg;
-}
-
-// Returns the normal vector of the selection.
-
-Math::Vector CModel::RetSelectNormal()
-{
- Math::Vector p1, p2, p3, n;
-
- p1.x = m_triangleTable[m_triangleSel1].p1.nx;
- p1.y = m_triangleTable[m_triangleSel1].p1.ny;
- p1.z = m_triangleTable[m_triangleSel1].p1.nz;
-
- p2.x = m_triangleTable[m_triangleSel1].p2.nx;
- p2.y = m_triangleTable[m_triangleSel1].p2.ny;
- p2.z = m_triangleTable[m_triangleSel1].p2.nz;
-
- p3.x = m_triangleTable[m_triangleSel1].p3.nx;
- p3.y = m_triangleTable[m_triangleSel1].p3.ny;
- p3.z = m_triangleTable[m_triangleSel1].p3.nz;
-
- n = Normalize(p1+p2+p3);
-
- return n;
-}
-
-// Maps a texture onto the selected triangles.
-
-bool CModel::IsMappingSelectPlausible(D3DMaping D3Dmode)
-{
- D3DVERTEX2 vertex[3];
- Math::Vector min, max;
- Math::Point a, b, ti, ts;
- float au, bu, av, bv;
- int used, i, j;
-
- ti.x = 0.0f;
- ti.y = 0.0f;
- ts.x = 1.0f;
- ts.y = 1.0f;
-
- BBoxCompute(min, max);
-
- if ( D3Dmode == D3DMAPPINGX )
- {
- a.x = min.z;
- a.y = min.y;
- b.x = max.z;
- b.y = max.y;
- }
- if ( D3Dmode == D3DMAPPINGY )
- {
- a.x = min.x;
- a.y = min.z;
- b.x = max.x;
- b.y = max.z;
- }
- if ( D3Dmode == D3DMAPPINGZ )
- {
- a.x = min.x;
- a.y = min.y;
- b.x = max.x;
- b.y = max.y;
- }
-
- au = (ts.x-ti.x)/(b.x-a.x);
- bu = ts.x-b.x*(ts.x-ti.x)/(b.x-a.x);
-
- av = (ts.y-ti.y)/(b.y-a.y);
- bv = ts.y-b.y*(ts.y-ti.y)/(b.y-a.y);
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( !GetVertex(i*3+0, vertex[0]) ) continue;
- if ( !GetVertex(i*3+1, vertex[1]) ) continue;
- if ( !GetVertex(i*3+2, vertex[2]) ) continue;
-
- for ( j=0 ; j<3 ; j++ )
- {
- if ( D3Dmode == D3DMAPPINGX )
- {
- vertex[j].tu = vertex[j].z*au+bu;
- vertex[j].tv = vertex[j].y*av+bv;
- }
- if ( D3Dmode == D3DMAPPINGY )
- {
- vertex[j].tu = vertex[j].x*au+bu;
- vertex[j].tv = vertex[j].z*av+bv;
- }
- if ( D3Dmode == D3DMAPPINGZ )
- {
- vertex[j].tu = vertex[j].x*au+bu;
- vertex[j].tv = vertex[j].y*av+bv;
- }
- }
-
- if ( vertex[0].tu == vertex[1].tu &&
- vertex[0].tu == vertex[2].tu ) return false;
-
- if ( vertex[0].tv == vertex[1].tv &&
- vertex[0].tv == vertex[2].tv ) return false;
- }
-
- return true;
-}
-
-// Maps a texture onto the selected triangles.
-
-void CModel::MappingSelect(int mode, int rotate, bool bMirrorX, bool bMirrorY,
- Math::Point ti, Math::Point ts, char *texName)
-{
- D3DVERTEX2 vertex;
- Math::Vector min, max;
- Math::Point a, b;
- D3DMaping D3Dmode;
- float au, bu, av, bv;
- int used, i;
- bool bPlausible[3];
-
- DefaultSelect();
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( !m_triangleTable[i].bUsed ) continue;
- if ( !m_triangleTable[i].bSelect ) continue;
-
- strcpy(m_triangleTable[i].texName, texName);
- }
-
- if ( mode == 1 )
- {
- MappingSelectSpherical(mode, rotate, bMirrorX, bMirrorY, ti, ts, texName);
- return;
- }
- if ( mode == 2 )
- {
- MappingSelectCylindrical(mode, rotate, bMirrorX, bMirrorY, ti, ts, texName);
- return;
- }
- if ( mode == 3 )
- {
- MappingSelectFace(mode, rotate, bMirrorX, bMirrorY, ti, ts, texName);
- return;
- }
-
- BBoxCompute(min, max);
-
- bPlausible[0] = IsMappingSelectPlausible(D3DMAPPINGX);
- bPlausible[1] = IsMappingSelectPlausible(D3DMAPPINGY);
- bPlausible[2] = IsMappingSelectPlausible(D3DMAPPINGZ);
-
- for ( i=0 ; i<9 ; i++ )
- {
- if ( !bPlausible[i%3] ) continue;
- if ( rotate-- == 0 ) break;
- }
- if ( i%3 == 0 ) D3Dmode = D3DMAPPINGX;
- if ( i%3 == 1 ) D3Dmode = D3DMAPPINGY;
- if ( i%3 == 2 ) D3Dmode = D3DMAPPINGZ;
-
- if ( D3Dmode == D3DMAPPINGX )
- {
- a.x = min.z;
- a.y = min.y;
- b.x = max.z;
- b.y = max.y;
- }
- if ( D3Dmode == D3DMAPPINGY )
- {
- a.x = min.x;
- a.y = min.z;
- b.x = max.x;
- b.y = max.z;
- }
- if ( D3Dmode == D3DMAPPINGZ )
- {
- a.x = min.x;
- a.y = min.y;
- b.x = max.x;
- b.y = max.y;
- }
-
- if ( bMirrorX )
- {
- Math::Swap(ti.x, ts.x);
- }
-
- if ( !bMirrorY ) // reverse test!
- {
- Math::Swap(ti.y, ts.y);
- }
-
- au = (ts.x-ti.x)/(b.x-a.x);
- bu = ts.x-b.x*(ts.x-ti.x)/(b.x-a.x);
-
- av = (ts.y-ti.y)/(b.y-a.y);
- bv = ts.y-b.y*(ts.y-ti.y)/(b.y-a.y);
-
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( !GetVertex(i, vertex) ) continue;
-
- if ( D3Dmode == D3DMAPPINGX )
- {
- vertex.tu = vertex.z*au+bu;
- vertex.tv = vertex.y*av+bv;
- }
- if ( D3Dmode == D3DMAPPINGY )
- {
- vertex.tu = vertex.x*au+bu;
- vertex.tv = vertex.z*av+bv;
- }
- if ( D3Dmode == D3DMAPPINGZ )
- {
- vertex.tu = vertex.x*au+bu;
- vertex.tv = vertex.y*av+bv;
- }
-
- SetVertex(i, vertex);
- }
-
- SelectTerm();
-}
-
-// Maps a texture onto the selected triangles.
-
-void CModel::MappingSelectSpherical(int mode, int rotate, bool bMirrorX, bool bMirrorY,
- Math::Point ti, Math::Point ts, char *texName)
-{
- D3DVERTEX2 vertex;
- Math::Vector min, max, center, dim, p;
- float radius, k, u, v;
- int used, i;
-
- BBoxCompute(min, max);
- center = (min+max)/2.0f;
- dim = (max-min)/2.0f;
- radius = Math::Min(dim.x, dim.y, dim.z);
-
- if ( bMirrorX )
- {
- Math::Swap(ti.x, ts.x);
- }
-
- if ( !bMirrorY ) // reverse test!
- {
- Math::Swap(ti.y, ts.y);
- }
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( !GetVertex(i, vertex) ) continue;
-
- p.x = vertex.x-center.x;
- p.y = vertex.y-center.y;
- p.z = vertex.z-center.z;
-
- k = radius/p.Length();
- u = k*p.x;
- v = k*p.z;
- u = (u/dim.x*2.0f+1.0f)/2.0f; // 0..1
- v = (v/dim.z*2.0f+1.0f)/2.0f;
-
- vertex.tu = ti.x+(ts.x-ti.x)*u;
- vertex.tv = ti.y+(ts.y-ti.y)*v;
-
- SetVertex(i, vertex);
- }
-
- SelectTerm();
-}
-
-// Seeking the center of a group of points.
-
-Math::Vector CModel::RetMappingCenter(Math::Vector pos, Math::Vector min)
-{
- D3DVERTEX2 vertex;
- Math::Vector center, p;
- int used, i, nb;
-
- center.x = 0.0f;
- center.y = 0.0f;
- center.z = 0.0f;
-
- nb = 0;
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( !GetVertex(i, vertex) ) continue;
-
- p.x = vertex.x;
- p.y = vertex.y;
- p.z = vertex.z;
-
- if ( fabs(p.x-pos.x) <= min.x &&
- fabs(p.y-pos.y) <= min.y &&
- fabs(p.z-pos.z) <= min.z )
- {
- center.x += p.x;
- center.y += p.y;
- center.z += p.z;
- nb ++;
- }
- }
-
- if ( nb == 0 ) return pos;
-
- center.x /= (float)nb;
- center.y /= (float)nb;
- center.z /= (float)nb;
-
- return center;
-}
-
-// Maps a texture onto the selected triangles.
-
-void CModel::MappingSelectCylindrical(int mode, int rotate, bool bMirrorX, bool bMirrorY,
- Math::Point ti, Math::Point ts, char *texName)
-{
- D3DVERTEX2 vertex;
- Math::Vector min, max, center, local, dim, p, pp, box;
- float radius, u, v;
- int used, i;
-
- BBoxCompute(min, max);
- center = (min+max)/2.0f;
- dim = (max-min)/2.0f;
- radius = Math::Min(dim.x, dim.y, dim.z);
-
- if ( bMirrorX )
- {
- Math::Swap(ti.x, ts.x);
- }
-
- if ( !bMirrorY ) // reverse test!
- {
- Math::Swap(ti.y, ts.y);
- }
-
- if ( rotate == 0 )
- {
- box.x = 2.0f;
- box.y = 10.0f;
- box.z = 10.0f;
- }
- if ( rotate == 1 )
- {
- box.x = 10.0f;
- box.y = 2.0f;
- box.z = 10.0f;
- }
- if ( rotate == 2 )
- {
- box.x = 10.0f;
- box.y = 10.0f;
- box.z = 2.0f;
- }
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( !GetVertex(i, vertex) ) continue;
-
- p.x = vertex.x;
- p.y = vertex.y;
- p.z = vertex.z;
-
-#if 1
- p.x -= center.x;
- p.y -= center.y;
- p.z -= center.z;
-
- pp = p;
-#else
- local = RetMappingCenter(p, box);
-
- pp = p;
- pp.x -= local.x;
- pp.y -= local.y;
- pp.z -= local.z;
-
- p.x -= center.x;
- p.y -= center.y;
- p.z -= center.z;
-#endif
-
- if ( rotate == 0 )
- {
- u = Math::RotateAngle(pp.y, pp.z);
- v = p.x/dim.x/2.0f + 0.5f;
- }
- if ( rotate == 1 )
- {
- u = Math::RotateAngle(pp.x, pp.z);
- v = p.y/dim.y/2.0f + 0.5f;
- }
- if ( rotate == 2 )
- {
- u = Math::RotateAngle(pp.x, pp.y);
- v = p.z/dim.z/2.0f + 0.5f;
- }
-
-//? if ( u < Math::PI ) u = u/Math::PI;
-//? else u = 2.0f-u/Math::PI;
- u = u/(Math::PI*2.0f);
-
- vertex.tu = ti.x+(ts.x-ti.x)*u;
- vertex.tv = ti.y+(ts.y-ti.y)*v;
-
- SetVertex(i, vertex);
- }
-
- SelectTerm();
-}
-
-
-// Maps a texture onto the selected triangles.
-
-void CModel::MappingSelectFace(int mode, int rotate, bool bMirrorX, bool bMirrorY,
- Math::Point ti, Math::Point ts, char *texName)
-{
- D3DVERTEX2 vertex[3];
- Math::Vector min, max, center, local, dim, p;
- float radius, u[3], v[3], m[3], avg;
- int used, i, j;
-
- BBoxCompute(min, max);
- center = (min+max)/2.0f;
- dim = (max-min)/2.0f;
- radius = Math::Min(dim.x, dim.y, dim.z);
-
- if ( bMirrorX )
- {
- Math::Swap(ti.x, ts.x);
- }
-
- if ( !bMirrorY ) // reverse test!
- {
- Math::Swap(ti.y, ts.y);
- }
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- for ( j=0 ; j<3 ; j++ )
- {
- if ( !GetVertex(i*3+j, vertex[j]) ) continue;
-
- p.x = vertex[j].x - center.x;
- p.y = vertex[j].y - center.y;
- p.z = vertex[j].z - center.z;
-
-#if 0
- u[j] = Math::RotateAngle(p.x, p.z)/(Math::PI*2.0f)+0.5f;
- if ( u[j] > 1.0f ) u[j] -= 1.0f;
-#else
- u[j] = Math::RotateAngle(p.x, p.z)/Math::PI;
-//? if ( u[j] > 1.0f ) u[j] = 2.0f-u[j];
- if ( u[j] > 1.0f ) u[j] -= 1.0f;
-#endif
-
- v[j] = p.y/dim.y/2.0f + 0.5f;
-
- if ( u[j] < 0.5f ) m[j] = u[j];
- else m[j] = u[j]-1.0f;
- }
-
- avg = (m[0]+m[1]+m[2])/3.0f;
-
- for ( j=0 ; j<3 ; j++ )
- {
- if ( u[j] < 0.05f || u[j] > 0.95f )
- {
- if ( avg > 0.0f ) u[j] = 0.0f;
- else u[j] = 1.0f;
- }
-
- vertex[j].tu = ti.x+(ts.x-ti.x)*u[j];
- vertex[j].tv = ti.y+(ts.y-ti.y)*v[j];
-
- SetVertex(i*3+j, vertex[j]);
- }
- }
-
- SelectTerm();
-}
-
-
-// Maps a secondary texture on selected triangles.
-
-void CModel::MappingSelect2(int texNum2, int subdiv,
- int offsetU, int offsetV,
- bool bMirrorX, bool bMirrorY)
-{
- D3DVERTEX2 vertex;
- Math::Vector min, max, center, p;
- float u ,v;
- int used, i;
-
- DefaultSelect();
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( !m_triangleTable[i].bUsed ) continue;
- if ( !m_triangleTable[i].bSelect ) continue;
-
- m_triangleTable[i].texNum2 = texNum2;
- }
-
- if ( subdiv == 6 )
- {
- MappingSelectSpherical2(bMirrorX, bMirrorY);
- return;
- }
- if ( subdiv == 7 )
- {
- MappingSelectMagic2(bMirrorX, bMirrorY);
- return;
- }
- if ( subdiv > 2 )
- {
- MappingSelectPlane2(subdiv-3, bMirrorX, bMirrorY);
- return;
- }
-
- BBoxCompute(min, max);
- center = (min+max)/2.0f;
-
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( !GetVertex(i, vertex) ) continue;
-
- p.x = vertex.x-center.x;
- p.y = vertex.y-center.y;
- p.z = vertex.z-center.z;
-
- u = Math::RotateAngle(p.x, p.z);
- v = Math::RotateAngle(Math::Point(p.x, p.z).Length(), p.y);
- if ( p.x < 0.0f ) v += Math::PI;
-
- u = Math::NormAngle(u+(float)offsetU*Math::PI/180.0f);
- v = Math::NormAngle(v+(float)offsetV*Math::PI/180.0f);
-
- if ( subdiv == 1 )
- {
- u = u/(Math::PI*2.0f);
- v = v/(Math::PI*2.0f);
- }
- if ( subdiv == 2 )
- {
- if ( u < Math::PI ) u = u/Math::PI;
- else u = (Math::PI*2.0f-u)/Math::PI;
- if ( v < Math::PI ) v = v/Math::PI;
- else v = (Math::PI*2.0f-v)/Math::PI;
- }
-
- vertex.tu2 = u;
- vertex.tv2 = v;
-
- SetVertex(i, vertex);
- }
-
- SelectTerm();
-}
-
-// Maps a secondary texture on flat.
-
-void CModel::MappingSelectPlane2(int mode, bool bMirrorX, bool bMirrorY)
-{
- D3DVERTEX2 vertex;
- Math::Vector min, max;
- Math::Point ti, ts, a, b;
- float au, bu, av, bv;
- int used, i;
-
- ti = Math::Point(0.0f, 0.0f);
- ts = Math::Point(1.0f, 1.0f);
-
- BBoxCompute(min, max);
-
- if ( mode == 0 )
- {
- a.x = min.z;
- a.y = min.y;
- b.x = max.z;
- b.y = max.y;
- }
- if ( mode == 1 )
- {
- a.x = min.x;
- a.y = min.z;
- b.x = max.x;
- b.y = max.z;
- }
- if ( mode == 2 )
- {
- a.x = min.x;
- a.y = min.y;
- b.x = max.x;
- b.y = max.y;
- }
-
- if ( bMirrorX )
- {
- Math::Swap(ti.x, ts.x);
- }
-
- if ( !bMirrorY ) // reverse test!
- {
- Math::Swap(ti.y, ts.y);
- }
-
- au = (ts.x-ti.x)/(b.x-a.x);
- bu = ts.x-b.x*(ts.x-ti.x)/(b.x-a.x);
-
- av = (ts.y-ti.y)/(b.y-a.y);
- bv = ts.y-b.y*(ts.y-ti.y)/(b.y-a.y);
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( !GetVertex(i, vertex) ) continue;
-
- if ( mode == 0 )
- {
- vertex.tu2 = vertex.z*au+bu;
- vertex.tv2 = vertex.y*av+bv;
- }
- if ( mode == 1 )
- {
- vertex.tu2 = vertex.x*au+bu;
- vertex.tv2 = vertex.z*av+bv;
- }
- if ( mode == 2 )
- {
- vertex.tu2 = vertex.x*au+bu;
- vertex.tv2 = vertex.y*av+bv;
- }
-
- SetVertex(i, vertex);
- }
-
- SelectTerm();
-}
-
-// Maps a texture onto the selected triangles.
-
-void CModel::MappingSelectSpherical2(bool bMirrorX, bool bMirrorY)
-{
- D3DVERTEX2 vertex;
- Math::Vector min, max, center, dim, p;
- Math::Point ti, ts;
- float radius, k, u, v;
- int used, i;
-
- BBoxCompute(min, max);
- center = (min+max)/2.0f;
- dim = (max-min)/2.0f;
- radius = Math::Min(dim.x, dim.y, dim.z);
-
- ti = Math::Point(0.0f, 0.0f);
- ts = Math::Point(1.0f, 1.0f);
-
- if ( bMirrorX )
- {
- Math::Swap(ti.x, ts.x);
- }
-
- if ( !bMirrorY ) // reverse test!
- {
- Math::Swap(ti.y, ts.y);
- }
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( !GetVertex(i, vertex) ) continue;
-
- p.x = vertex.x-center.x;
- p.y = vertex.y-center.y;
- p.z = vertex.z-center.z;
-
- k = radius/p.Length();
- u = k*p.x;
- v = k*p.z;
- u = (u/dim.x*2.0f+1.0f)/2.0f; // 0..1
- v = (v/dim.z*2.0f+1.0f)/2.0f;
-
- vertex.tu2 = ti.x+(ts.x-ti.x)*u;
- vertex.tv2 = ti.y+(ts.y-ti.y)*v;
-
- SetVertex(i, vertex);
- }
-
- SelectTerm();
-}
-
-// Maps a texture onto the selected triangles.
-
-void CModel::MappingSelectMagic2(bool bMirrorX, bool bMirrorY)
-{
- D3DVERTEX2 vertex, v[3];
- Math::Vector min, max, au, bu, av, bv, n;
- Math::Point ti, ts;
- int used, i, mode;
-
- ti = Math::Point(0.0f, 0.0f);
- ts = Math::Point(1.0f, 1.0f);
-
- BBoxCompute(min, max);
-
- if ( bMirrorX )
- {
- Math::Swap(ti.x, ts.x);
- }
-
- if ( !bMirrorY ) // reverse test!
- {
- Math::Swap(ti.y, ts.y);
- }
-
- au.x = (ts.x-ti.x)/(max.x-min.x);
- bu.x = ts.x-max.x*(ts.x-ti.x)/(max.x-min.x);
- au.y = (ts.x-ti.x)/(max.y-min.y);
- bu.y = ts.x-max.y*(ts.x-ti.x)/(max.y-min.y);
- au.z = (ts.x-ti.x)/(max.z-min.z);
- bu.z = ts.x-max.z*(ts.x-ti.x)/(max.z-min.z);
-
- av.x = (ts.y-ti.y)/(max.x-min.x);
- bv.x = ts.y-max.x*(ts.y-ti.y)/(max.x-min.x);
- av.y = (ts.y-ti.y)/(max.y-min.y);
- bv.y = ts.y-max.y*(ts.y-ti.y)/(max.y-min.y);
- av.z = (ts.y-ti.y)/(max.z-min.z);
- bv.z = ts.y-max.z*(ts.y-ti.y)/(max.z-min.z);
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( i%3 == 0 )
- {
- if ( !GetVertex(i+0, v[0]) ) continue;
- if ( !GetVertex(i+1, v[1]) ) continue;
- if ( !GetVertex(i+2, v[2]) ) continue;
-
- n = Math::NormalToPlane(Math::Vector(v[0].x, v[0].y, v[0].z),
- Math::Vector(v[1].x, v[1].y, v[1].z),
- Math::Vector(v[2].x, v[2].y, v[2].z));
-
- n.x = fabs(n.x);
- n.y = fabs(n.y);
- n.z = fabs(n.z);
-
- if ( n.x >= Math::Max(n.y, n.z) ) mode = 0;
- if ( n.y >= Math::Max(n.x, n.z) ) mode = 1;
- if ( n.z >= Math::Max(n.x, n.y) ) mode = 2;
- }
-
- if ( !GetVertex(i, vertex) ) continue;
-
- if ( mode == 0 )
- {
- vertex.tu2 = vertex.z*au.z+bu.z;
- vertex.tv2 = vertex.y*av.y+bv.y;
- }
- if ( mode == 1 )
- {
- vertex.tu2 = vertex.x*au.x+bu.x;
- vertex.tv2 = vertex.z*av.z+bv.z;
- }
- if ( mode == 2 )
- {
- vertex.tu2 = vertex.x*au.x+bu.x;
- vertex.tv2 = vertex.y*av.y+bv.y;
- }
-
- SetVertex(i, vertex);
- }
-
- SelectTerm();
-}
-
-
-// Seeks the next triangle.
-
-int CModel::SearchNext(int rank, int step)
-{
- int max, i;
-
- max = m_modFile->RetTriangleUsed();
-
- for ( i=0 ; i<max ; i++ )
- {
- rank += step;
- if ( rank < 0 ) rank = max-1;
- if ( rank >= max ) rank = 0;
-
- if ( m_triangleTable[rank].min != m_min ||
- m_triangleTable[rank].max != m_max ) continue;
-
- if ( m_triangleTable[rank].bUsed ) break;
- }
- return rank;
-}
-
-// Seeks all the triangles belonging to the same plane.
-
-int CModel::SearchSamePlane(int first, int step)
-{
- Math::Vector vFirst[3], vNext[3];
- int last, i;
-
- vFirst[0].x = m_triangleTable[first].p1.x;
- vFirst[0].y = m_triangleTable[first].p1.y;
- vFirst[0].z = m_triangleTable[first].p1.z;
- vFirst[1].x = m_triangleTable[first].p2.x;
- vFirst[1].y = m_triangleTable[first].p2.y;
- vFirst[1].z = m_triangleTable[first].p2.z;
- vFirst[2].x = m_triangleTable[first].p3.x;
- vFirst[2].y = m_triangleTable[first].p3.y;
- vFirst[2].z = m_triangleTable[first].p3.z;
-
- for ( i=0 ; i<1000 ; i++ )
- {
- last = first;
- first = SearchNext(first, step);
-
- vNext[0].x = m_triangleTable[first].p1.x;
- vNext[0].y = m_triangleTable[first].p1.y;
- vNext[0].z = m_triangleTable[first].p1.z;
- vNext[1].x = m_triangleTable[first].p2.x;
- vNext[1].y = m_triangleTable[first].p2.y;
- vNext[1].z = m_triangleTable[first].p2.z;
- vNext[2].x = m_triangleTable[first].p3.x;
- vNext[2].y = m_triangleTable[first].p3.y;
- vNext[2].z = m_triangleTable[first].p3.z;
-
- if ( !IsSamePlane(vFirst, vNext) ) // other plan?
- {
- return last;
- }
- }
- return first;
-}
-
-// Seeks the next triangle.
-
-void CModel::CurrentSearchNext(int step, bool bControl)
-{
- if ( step > 0 ) // forward?
- {
- m_triangleSel1 = SearchNext(m_triangleSel2, step);
- if ( bControl )
- {
- m_triangleSel2 = m_triangleSel1;
- }
- else
- {
- m_triangleSel2 = SearchSamePlane(m_triangleSel1, step);
- }
- }
- if ( step < 0 ) // back?
- {
- m_triangleSel2 = SearchNext(m_triangleSel1, step);
- if ( bControl )
- {
- m_triangleSel1 = m_triangleSel2;
- }
- else
- {
- m_triangleSel1 = SearchSamePlane(m_triangleSel2, step);
- }
- }
-
-#if 0
- char s[100];
- sprintf(s, "(%.2f;%.2f;%.2f) (%.2f;%.2f;%.2f) (%.2f;%.2f;%.2f)",
- m_triangleTable[m_triangleSel1].p1.x,
- m_triangleTable[m_triangleSel1].p1.y,
- m_triangleTable[m_triangleSel1].p1.z,
- m_triangleTable[m_triangleSel1].p2.x,
- m_triangleTable[m_triangleSel1].p2.y,
- m_triangleTable[m_triangleSel1].p2.z,
- m_triangleTable[m_triangleSel1].p3.x,
- m_triangleTable[m_triangleSel1].p3.y,
- m_triangleTable[m_triangleSel1].p3.z);
- m_engine->SetInfoText(2, s);
- sprintf(s, "(%.2f;%.2f) (%.2f;%.2f) (%.2f;%.2f)",
- m_triangleTable[m_triangleSel1].p1.tu2,
- m_triangleTable[m_triangleSel1].p1.tv2,
- m_triangleTable[m_triangleSel1].p2.tu2,
- m_triangleTable[m_triangleSel1].p2.tv2,
- m_triangleTable[m_triangleSel1].p3.tu2,
- m_triangleTable[m_triangleSel1].p3.tv2);
- m_engine->SetInfoText(3, s);
-#endif
-
- InitViewFromSelect();
- UpdateInfoText();
-}
-
-// Initializes the current triangles.
-
-void CModel::CurrentInit()
-{
- m_triangleSel1 = 0;
- m_triangleSel2 = SearchSamePlane(m_triangleSel1, +1);
-
- InitViewFromSelect();
- UpdateInfoText();
-}
-
-// Selects the current triangles.
-
-void CModel::CurrentSelect(bool bSelect)
-{
- int i;
-
- for ( i=m_triangleSel1 ; i<=m_triangleSel2 ; i++ )
- {
- m_triangleTable[i].bSelect = bSelect;
- }
-}
-
-
-// Deselects all triangles.
-
-void CModel::DeselectAll()
-{
- int used, i;
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- m_triangleTable[i].bSelect = false;
- }
-}
-
-// Selects an area.
-
-void CModel::SelectZone(int first, int last)
-{
- int used, i;
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- m_triangleTable[i].bSelect = false;
- if ( i >= first && i < last )
- {
- m_triangleTable[i].bSelect = true;
- }
- }
- m_triangleSel1 = first;
- m_triangleSel2 = last-1;
-}
-
-// Selects all triangles.
-
-void CModel::SelectAll()
-{
- int used, i;
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( m_triangleTable[i].min == m_min &&
- m_triangleTable[i].max == m_max )
- {
- m_triangleTable[i].bSelect = true;
- }
- }
-}
-
-// Deselects all triangles.
-
-void CModel::SelectTerm()
-{
- int used, i;
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( i >= m_triangleSel1 && i <= m_triangleSel2 )
- {
- if ( !m_triangleTable[i].bSelect ) return;
- }
- else
- {
- if ( m_triangleTable[i].bSelect ) return;
- }
- }
-
- DeselectAll();
-}
-
-// Selects the triangles currents.
-
-void CModel::DefaultSelect()
-{
- int used, i;
-
- used = m_modFile->RetTriangleUsed();
- for ( i=m_triangleSel1 ; i<=m_triangleSel2 ; i++ )
- {
- m_triangleTable[i].bSelect = true;
- }
-}
-
-
-
-// Removes all selected triangles.
-
-void CModel::SelectDelete()
-{
- int used ,i;
-
- DefaultSelect();
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( m_triangleTable[i].bSelect )
- {
- m_triangleTable[i].bUsed = false;
- }
- }
-
- i = m_triangleSel1;
- Compress();
-
- m_triangleSel1 = i;
- m_triangleSel2 = SearchSamePlane(m_triangleSel1, +1);
- InitViewFromSelect();
- UpdateInfoText();
-}
-
-// Compresses all triangles.
-
-void CModel::Compress()
-{
- int used, i, j;
-
- j = 0;
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( m_triangleTable[i].bUsed )
- {
- m_triangleTable[j++] = m_triangleTable[i];
- }
- }
- m_modFile->SetTriangleUsed(j);
- CurrentInit();
-}
-
-
-// Change the min / max of all selected triangles.
-
-void CModel::MinMaxChange()
-{
- int used, i;
-
- DefaultSelect();
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( !m_triangleTable[i].bSelect ) continue;
-
- m_triangleTable[i].min = m_min;
- m_triangleTable[i].max = m_max;
- }
-}
-
-
-// Initializes the point of view.
-
-void CModel::InitView()
-{
- m_viewHeight = 5.0f;
- m_viewDist = 50.0f;
- m_viewAngleH = 0.0f;
- m_viewAngleV = 0.0f;
-}
-
-// Initializes the point of view to see the selected triangles.
-
-void CModel::InitViewFromSelect()
-{
-#if 0
- Math::Vector n;
- float h,v;
-
- n = RetSelectNormal();
-
- m_viewAngleH = Math::RotateAngle(n.x, n.z)+Math::PI;
- m_viewAngleV = Math::RotateAngle(sqrtf(n.x*n.x+n.z*n.z), n.y)+Math::PI;
- h = m_viewAngleH;
- v = m_viewAngleV;
-
- while ( m_viewAngleV <= -Math::PI )
- {
- m_viewAngleV += Math::PI;
- m_viewAngleH += Math::PI;
- }
- while ( m_viewAngleV >= Math::PI )
- {
- m_viewAngleV -= Math::PI;
- m_viewAngleH -= Math::PI;
- }
- m_viewAngleV *= 0.75f;
-
- char s[100];
- sprintf(s, "angle=%f %f -> %f %f\n", h,v, m_viewAngleH, m_viewAngleV);
- OutputDebugString(s);
-#endif
-}
-
-// Updates the parameters for the point of view.
-
-void CModel::UpdateView()
-{
- Math::Vector eye, lookat, vUpVec;
-
-//? lookat = RetSelectCDG();
- lookat = Math::Vector(0.0f, m_viewHeight, 0.0f);
- eye = RotateView(lookat, m_viewAngleH, m_viewAngleV, m_viewDist);
-
- vUpVec = Math::Vector(0.0f, 1.0f, 0.0f);
- m_engine->SetViewParams(eye, lookat, vUpVec, 10.0f);
- m_engine->SetRankView(0);
-}
-
-// Moves the point of view.
-
-void CModel::ViewMove(const Event &event, float speed)
-{
- if ( IsEditFocus() ) return;
-
- // Up/Down.
- if ( event.axeY > 0.5f )
- {
- if ( event.keyState & KS_CONTROL )
- {
- m_viewHeight += event.rTime*10.0f*speed;
- if ( m_viewHeight > 100.0f ) m_viewHeight = 100.0f;
- }
- else
- {
- m_viewAngleV -= event.rTime*1.0f*speed;
- if ( m_viewAngleV < -Math::PI*0.49f ) m_viewAngleV = -Math::PI*0.49f;
- }
- }
- if ( event.axeY < -0.5f )
- {
- if ( event.keyState & KS_CONTROL )
- {
- m_viewHeight -= event.rTime*10.0f*speed;
- if ( m_viewHeight < -100.0f ) m_viewHeight = -100.0f;
- }
- else
- {
- m_viewAngleV += event.rTime*1.0f*speed;
- if ( m_viewAngleV > Math::PI*0.49f ) m_viewAngleV = Math::PI*0.49f;
- }
- }
-
- // Left/Right.
- if ( event.axeX < -0.5f )
- {
- m_viewAngleH -= event.rTime*1.0f*speed;
- }
- if ( event.axeX > 0.5f )
- {
- m_viewAngleH += event.rTime*1.0f*speed;
- }
-
- // PageUp/PageDown.
- if ( event.keyState & KS_PAGEUP )
- {
- m_viewDist -= event.rTime*30.0f*speed;
- if ( m_viewDist < 1.0f ) m_viewDist = 1.0f;
- }
- if ( event.keyState & KS_PAGEDOWN )
- {
- m_viewDist += event.rTime*30.0f*speed;
- if ( m_viewDist > 300.0f ) m_viewDist = 300.0f;
- }
-}
-
-
-
-// Updates the text information.
-
-void CModel::UpdateInfoText()
-{
- char info[100];
-
- if ( m_mode == 1 )
- {
- sprintf(info, "[1] V:color=%d K:state=%d Sel=%d..%d (T=%d)",
- m_color, m_state,
- m_triangleSel1, m_triangleSel2,
- m_triangleSel2-m_triangleSel1+1);
- m_engine->SetInfoText(0, info);
-
- sprintf(info, "M:mode=%d Z:rot=%d XY:mir=%d;%d P:part=%d O:name=%s",
- m_textureMode, m_textureRotate,
- m_bTextureMirrorX, m_bTextureMirrorY,
- m_texturePart, m_textureName);
- m_engine->SetInfoText(1, info);
- }
-
- if ( m_mode == 2 )
- {
- sprintf(info, "[2] Sel=%d..%d (T=%d)",
- m_triangleSel1, m_triangleSel2,
- m_triangleSel2-m_triangleSel1+1);
- m_engine->SetInfoText(0, info);
-
- sprintf(info, "O:dirty=%d UV:offset=%d;%d XY:mir=%d;%d S:subdiv=%d",
- m_secondTexNum,
- m_secondOffsetU, m_secondOffsetV,
- m_bTextureMirrorX, m_bTextureMirrorY,
- m_secondSubdiv);
- m_engine->SetInfoText(1, info);
- }
-
- if ( m_mode == 3 )
- {
- sprintf(info, "[3] LOD Math::Min/max=%d..%d Sel=%d..%d (T=%d)",
- (int)m_min, (int)m_max,
- m_triangleSel1, m_triangleSel2,
- m_triangleSel2-m_triangleSel1+1);
- m_engine->SetInfoText(0, info);
-
- sprintf(info, "[Change]");
- m_engine->SetInfoText(1, info);
- }
-}
-
-
-
-static int tablePartT[] = // lemt.tga
-{
- 192, 0, 256, 32, // track profile
- 0, 64, 128, 128, // wheels for track
- 0, 0, 128, 64, // profile
- 90, 0, 128, 28, // pivot trainer
- 128, 0, 192, 44, // chest front
- 128, 44, 192, 58, // shell
- 128, 58, 192, 87, // back chest
- 128, 87, 192, 128, // back shell
- 128, 128, 192, 144, // sub back shell
- 0, 128, 32, 152, // rear fender
- 0, 152, 32, 182, // fender middle
- 0, 182, 32, 256, // front fender
- 32, 128, 112, 176, // wing
- 224, 48, 232, 64, // thrust tunnel
- 192, 32, 224, 64, // fire under reactor
- 224, 32, 256, 48, // foot
- 192, 64, 256, 128, // sensor
- 192, 128, 224, 176, // battery holder
- 192, 216, 248, 248, // cannon board
- 220, 216, 222, 245, // cannon board
- 64, 176, 128, 224, // top cannon
- 128, 152, 192, 160, // external cannon
- 128, 144, 192, 152, // interior cannon
- 192, 176, 224, 192, // small cannon
- 128, 236, 192, 256, // cannon organic
- 214, 192, 224, 216, // crosshair
- 224, 128, 248, 152, // articulation
- 128, 192, 192, 214, // piston board
- 128, 214, 192, 236, // piston front
- 192, 192, 214, 214, // piston edge
- 128, 192, 161, 214, // small piston board
- 32, 176, 64, 198, // radar piston
- 128, 160, 160, 192, // wheel
- 232, 48, 255, 56, // tire profile
- 240, 152, 248, 216, // vertical hatching
- 248, 192, 256, 256, // battery
- 224, 152, 240, 168, // rock
- 144, 80, 176, 112, // nuclear
- 140, 76, 180, 116, // large nuclear
- 144, 80, 152, 88, // yellow nuclear
- 224, 168, 240, 192, // cap resolution C
- 224, 192, 240, 210, // back resolution C
- 32, 224, 96, 235, // arm resolution C
- 32, 235, 96, 246, // arm resolution C
- 161, 1, 164, 4, // blank
- 168, 1, 171, 4, // medium gray
- 154, 1, 157, 4, // dark gray uniform
- 147, 1, 150, 4, // blue unifrom
- 114, 130, 118, 134, // red unifrom
- 121, 130, 125, 134, // green uniform
- 114, 137, 118, 141, // yellow uniform
- 121, 137, 125, 141, // violet uniform
- -1
-};
-
-static int tablePartR[] = // roller.tga
-{
- 0, 0, 128, 52, // wheels for track
- 48, 137, 128, 201, // catalytic radiator
- 0, 52, 32, 84, // front radiator
- 32, 52, 43, 84, // back radiator
- 0, 84, 96, 137, // large catalytic
- 128, 0, 192, 85, // front
- 128, 173, 192, 256, // back
- 192, 0, 256, 42, // over
- 128, 85, 192, 109, // catalytic pillon
- 128, 109, 192, 173, // top pillon
- 192, 85, 240, 109, // catalytic gate pillon
- 0, 137, 24, 256, // catalytic verrin
- 24, 137, 48, 256, // catalytic verrin
- 48, 201, 128, 233, // medium cannon
- 192, 109, 256, 173, // bottom cannon
- 192, 173, 240, 205, // cannon 1
- 192, 173, 240, 177, // cannon 2
- 43, 52, 75, 84, // front cannon
- 48, 233, 128, 247, // piston
- 96, 105, 128, 137, // front phazer
- 96, 97, 128, 105, // phazer cannon
- 75, 52, 107, 84, // exhaust pipe
- 192, 205, 243, 256, // nuclear power plant instruction
- 192, 42, 256, 85, // reflection glass
- -1
-};
-
-static int tablePartW[] = // subm.tga
-{
- 0, 0, 128, 26, // chenilles
- 0, 26, 22, 114, // portique 1
- 0, 114, 22, 202, // portique 2
- 22, 26, 82, 56, // c�t� hublot
- 22, 56, 82, 86, // c�t� ligne rouge
- 22, 86, 82, 116, // c�t� simple
- 22, 116, 82, 146, // avant/arri�re
- 22, 146, 82, 176, // avant/arri�re + phare
- 132, 82, 196, 166, // capot trainer
- 132, 166, 196, 177, // capot trainer
- 132, 177, 196, 188, // capot trainer
- 0, 224, 96, 256, // c�t� trainer
- 30, 224, 48, 256, // arri�re trainer
- 136, 240, 216, 256, // barri�re courte
- 96, 240, 256, 256, // barri�re longue
- 128, 0, 160, 32, // black-box 1
- 160, 0, 192, 32, // black-box 2
- 192, 0, 224, 32, // black-box 3
- 224, 105, 256, 137, // TNT 1
- 224, 137, 256, 169, // TNT 2
- 82, 32, 146, 82, // factory r�solution C
- 146, 32, 210, 82, // factory r�solution C
- 224, 0, 256, 105, // tower r�solution C
- 82, 82, 132, 150, // research r�solution C
- 199, 169, 256, 233, // sac r�solution C
- 106, 150, 130, 214, // cl� A
- 82, 150, 106, 214, // cl� B
- 132, 188, 196, 212, // cl� C
- 132, 212, 196, 236, // cl� D
- 210, 32, 224, 46, // gris
- 56, 176, 82, 224, // sol coffre-fort
- -1
-};
-
-static int tablePartDr[] = // drawer.tga
-{
- 128, 0, 134, 6, // bleu
- 128, 6, 134, 12, // gris fonc�
- 128, 12, 134, 18, // gris clair
- 0, 0, 128, 32, // roues chenille
- 192, 0, 256, 32, // profil chenille
- 140, 0, 160, 8, // profil phare
- 160, 0, 192, 32, // face phare
- 0, 32, 160, 48, // hachure
- 160, 32, 192, 48, // c�t�
- 0, 48, 96, 96, // tableau de bord
- 96, 48, 192, 112, // radiateur
- 192, 32, 256, 112, // grille lat�rale
- 192, 112, 256, 128, // capot
- 0, 96, 8, 160, // chassis
- 8, 96, 96, 104, // axe chenilles
- 8, 104, 16, 160, // axe carrousel
- 16, 128, 24, 160, // flan support
- 224, 128, 256, 160, // rotule
- 24, 104, 32, 160, // bocal (18)
- 32, 104, 40, 160, // bocal
- 40, 104, 48, 160, // bocal
- 24, 152, 48, 160, // bocal fond
- 0, 240, 32, 256, // crayon 1: couleur (22)
- 0, 160, 32, 192, // crayon 1: dessus
- 0, 192, 32, 256, // crayon 1: pointe
- 32, 240, 64, 256, // crayon 2: couleur
- 32, 160, 64, 192, // crayon 2: dessus
- 32, 192, 64, 256, // crayon 2: pointe
- 64, 240, 96, 256, // crayon 3: couleur
- 64, 160, 96, 192, // crayon 3: dessus
- 64, 192, 96, 256, // crayon 3: pointe
- 96, 240, 128, 256, // crayon 4: couleur
- 96, 160, 128, 192, // crayon 4: dessus
- 96, 192, 128, 256, // crayon 4: pointe
- 128, 240, 160, 256, // crayon 5: couleur
- 128, 160, 160, 192, // crayon 5: dessus
- 128, 192, 160, 256, // crayon 5: pointe
- 160, 240, 192, 256, // crayon 6: couleur
- 160, 160, 192, 192, // crayon 6: dessus
- 160, 192, 192, 256, // crayon 6: pointe
- 192, 240, 224, 256, // crayon 7: couleur
- 192, 160, 224, 192, // crayon 7: dessus
- 192, 192, 224, 256, // crayon 7: pointe
- 224, 240, 256, 256, // crayon 8: couleur
- 224, 160, 256, 192, // crayon 8: dessus
- 224, 192, 256, 256, // crayon 8: pointe
- -1
-};
-
-static int tablePartKi[] = // kid.tga
-{
- 0, 0, 128, 53, // ciseaux
- 128, 0, 256, 128, // CD
- 0, 0, 8, 8, // livre 1: fond
- 8, 0, 16, 8, // livre 2: fond
- 16, 0, 24, 8, // livre: fond
- 24, 0, 32, 8, // livre: fond
- 32, 0, 40, 8, // livre: fond
- 40, 0, 48, 8, // livre: fond
- 0, 53, 22, 138, // livre 1: tranche
- 22, 53, 86, 138, // livre 1: face
- 0, 138, 22, 224, // livre 2: tranche
- 22, 138, 86, 224, // livre 2: face
- 86, 53, 94, 85, // livre: pages
- 94, 53, 110, 139, // livre: tranche
- 110, 53, 126, 139, // livre: tranche
- 86, 139, 102, 225, // livre: tranche
- 102, 139, 118, 225, // livre: tranche
- 118, 139, 134, 225, // livre: tranche
- 64, 0, 72, 8, // fauille: fond
- 155, 155, 256, 256, // feuille: carreaux
- 72, 0, 80, 8, // lampe
- 80, 0, 88, 8, // lampe
- 80, 8, 88, 16, // ampoule
- 72, 8, 80, 16, // rayons (23)
- 86, 85, 94, 139, // lampe
- 0, 224, 32, 256, // lampe rotule
- 64, 8, 72, 16, // arrosoir: fond
- 134, 128, 142, 256, // arrosoir: corps
- 142, 128, 150, 256, // arrosoir: tuyau
- 128, 225, 134, 256, // arrosoir: int�rieur
- 32, 224, 64, 256, // arrosoir: ponneau
- 56, 8, 64, 16, // skate: roues (31)
- 48, 8, 56, 16, // skate: axes
- 40, 8, 48, 16, // skate: grip
- 32, 8, 40, 16, // skate: tranche
- 24, 8, 32, 16, // skate: dessous
- 150, 128, 200, 256, // skate: motif 1
- 200, 128, 250, 256, // skate: motif 2
- 64, 224, 96, 256, // skate: roue (38)
- 96, 225, 104, 256, // skate: amortisseur
- -1
-};
-
-static int tablePartKi2[] = // kid2.tga
-{
- 2, 2, 62, 62, // coca: dessus
- 0, 64, 8, 192, // coca: flan
- 8, 64, 96, 192, // coca: logo
- 128, 0, 256, 85, // carton
- 128, 85, 256, 91, // carton tranche
- 128, 128, 256, 256, // roue
- 192, 96, 256, 128, // pneu
- 184, 96, 192, 128, // jante
- 128, 96, 160, 128, // int�rieur
- 160, 96, 168, 104, // porte bois
- 160, 104, 168, 112, // porte m�tal
- 160, 112, 184, 128, // vitre
- 96, 0, 128, 256, // bouteille: corps (12)
- 64, 0, 96, 32, // bouteille: bouchon
- 168, 96, 176, 104, // bouteille: vert
- 0, 192, 96, 224, // bois clair
- 0, 224, 96, 256, // bois fonc�
- 64, 32, 96, 64, // bateau
- 168, 104, 176, 112, // ballon (18)
- 176, 104, 184, 112, // ballon
- 176, 96, 184, 104, // int�rieur caisse
- -1
-};
-
-static int tablePartKi3[] = // kid3.tga
-{
- 0, 0, 32, 28, // �crou: flan
- 0, 28, 32, 44, // �crou: profil
- 0, 44, 32, 60, // �crou: pas de vis
- 0, 60, 32, 64, // tuyau
- 0, 64, 32, 68, // tuyau
- 0, 68, 8, 76, // tuyau
- 0, 76, 32, 108, // plastic
- 8, 68, 16, 76, // saut: gris clair (7)
- 16, 68, 24, 76, // saut: gris fonc�
- 24, 68, 32, 76, // saut: gris bois
- 0, 108, 32, 140, // saut: rotule
- 0, 140, 32, 144, // saut: axe
- 128, 0, 256, 128, // saut: flan
- 0, 144, 8, 152, // basket: gris fonc� (13)
- 8, 144, 16, 152, // basket: gris clair
- 16, 144, 24, 152, // basket: gris lacets
- 24, 144, 32, 152, // basket: gris semelle
- 0, 152, 8, 181, // basket: int�rieur
- 0, 181, 192, 256, // basket: c�t�
- 192, 181, 226, 256, // basket: arri�re
- 32, 135, 96, 181, // basket: dessus (20)
- 96, 168, 128, 181, // basket: avant
- 8, 152, 16, 160, // chaise: plastique
- 16, 152, 24, 160, // chaise: m�tal
- 32, 0, 64, 32, // chaise: roue
- 8, 177, 24, 181, // chaise: roue
- 226, 181, 234, 256, // chaise: piston (26)
- 64, 96, 128, 128, // chaise: relief
- 96, 135, 128, 167, // chaise: dessous
- 32, 128, 250, 135, // paille 1
- 38, 128, 256, 135, // paille 2
- 234, 181, 242, 256, // allumette
- 8, 160, 16, 168, // allumette (dessus)
- 128, 135, 224, 181, // panneau
- 242, 135, 256, 256, // poteau (34)
- 24, 152, 32, 160, // clou
- 16, 160, 24, 168, // tuyau m�talique
- 112, 181, 192, 185, // tuyau int�rieur
- 32, 32, 48, 80, // pas de vis
- 24, 160, 32, 168, // ventillateur: plastique (39)
- 40, 80, 56, 96, // ventillateur: plastique d�grad�
- 8, 168, 16, 176, // ventillateur: m�tal
- 32, 80, 40, 112, // ventillateur: socle 1
- 64, 0, 96, 16, // ventillateur: socle 2
- 48, 32, 56, 80, // ventillateur: socle 3
- 64, 16, 96, 32, // ventillateur: moteur flan
- 96, 0, 128, 32, // ventillateur: moteur face
- 102, 6, 122, 26, // ventillateur: socle dessus
- 16, 168, 24, 176, // pot: uni (48)
- 56, 32, 64, 64, // pot: haut
- 56, 64, 64, 96, // pot: bas
- 64, 32, 128, 96, // pot: terre
- -1
-};
-
-static int tablePartF[] = // factory.tga
-{
- 0, 0, 152, 152, // plancher octogonal fabrique
- 50, 50, 102, 102, // dessus pile
- 0, 152, 128, 252, // avant
- 128, 152, 256, 252, // arri�re
- 152, 28, 225, 128, // c�t�
- 152, 28, 176, 128, // c�t� partiel
- 152, 0, 216, 16, // hachures
- 236, 0, 256, 40, // axe
- 152, 128, 224, 152, // support cible
- -1
-};
-
-static int tablePartD[] = // derrick.tga
-{
- 0, 0, 64, 32, // grand c�t�
- 64, 0, 96, 24, // petit c�t�
- 96, 0, 136, 24, // attention
- 0, 32, 8, 160, // tube 1
- 8, 32, 16, 96, // tube 2
- 16, 32, 24, 160, // pilier
- 24, 32, 32, 160, // tige foret
- 32, 32, 40, 160, // tige destructeur
- 8, 96, 16, 128, // foret
- 136, 0, 256, 120, // plancher octogonal station de recharge
- 40, 32, 64, 56, // cube m�tal
- 64, 24, 128, 48, // c�t� tour haut
- 64, 48, 128, 229, // c�t� tour bas
- 136, 120, 256, 240, // int�rieur usine
- 0, 160, 64, 224, // to�t usine
- -1
-};
-
-static int tablePartC[] = // convert.tga
-{
- 0, 0, 120, 120, // plancher octogonal convertisseur
- 0, 120, 128, 176, // grand c�t�
- 128, 120, 192, 176, // petit c�t�
- 192, 120, 256, 184, // couvercle convertisseur
- 120, 0, 216, 64, // face trianble
- 216, 0, 248, 64, // c�t� triangle
- 120, 64, 160, 84, // axe
- 0, 141, 128, 176, // recherche: base
- 0, 176, 128, 214, // recherche: haut
- 0, 214, 128, 252, // recherche: haut (!)
- 174, 64, 190, 120, // recherche: montant
- 190, 64, 206, 120, // recherche: montant
- 206, 64, 254, 85, // radar
- 192, 168, 256, 232, // hachures carr�es
- 248, 0, 256, 64, // c�ne fabrique de piles
- 128, 176, 192, 240, // dessus centrale nucl�aire
- 120, 85, 174, 120, // technicien, visage
- 206, 106, 256, 120, // technicien, casquette
- 160, 64, 174, 78, // technicien, visi�re
- -1
-};
-
-static int tablePartS[] = // search.tga
-{
- 0, 0, 128, 128, // usine 1
- 128, 0, 256, 128, // usine 2
- 0, 128, 128, 256, // pile
- 128, 128, 228, 240, // support pile
- 228, 128, 256, 184, // antenne
- 128, 128, 192, 160, // contr�le 1
- 128, 160, 192, 192, // contr�le 2
- 128, 192, 192, 224, // contr�le 3
- 128, 224, 192, 256, // contr�le 4
- -1
-};
-
-static int tablePartP[] = // plant.tga
-{
- 0, 160, 48, 256, // feuille 1
- 0, 0, 94, 100, // feuille 2
- 48, 156, 108, 256, // feuille 3
- 94, 0, 104, 100, // tige 1
- 185, 0, 195, 100, // tige 2
- 108, 100, 182, 256, // foug�re
- 104, 0, 144, 100, // courge
- 203, 0, 256, 83, // armature derrick r�solution C
- -1
-};
-
-static int tablePartV[] = // vegetal.tga
-{
- 0, 0, 94, 100, // racine
- 186, 0, 256, 256, // tronc
- 162, 0, 168, 128, // mat drapeau bleu
- 168, 0, 174, 128, // mat drapeau rouge
- 174, 0, 180, 128, // mat drapeau vert
- 180, 0, 186, 128, // mat drapeau jaune
- 180, 128, 186, 256, // mat drapeau violet
- 94, 0, 107, 32, // drapeau bleu
- 107, 0, 120, 32, // drapeau rouge
- 120, 0, 133, 32, // drapeau vert
- 133, 0, 146, 32, // drapeau jaune
- 146, 0, 159, 32, // drapeau violet
- 94, 64, 126, 96, // verre 1
- 126, 64, 158, 86, // verre 2
- 128, 128, 180, 144, // verre 3a
- 128, 144, 180, 160, // verre 3b
- 128, 94, 162, 128, // verre 4
- 0, 100, 32, 228, // champignon 1
- 32, 100, 48, 228, // champignon 1
- 48, 100, 112, 228, // champignon 2
- 112, 100, 128, 228, // champignon 2
- 128, 160, 180, 212, // tronc (21)
- -1
-};
-
-static int tablePartM[] = // mother.tga
-{
- 0, 0, 128, 128, // corps arri�re
- 128, 0, 192, 128, // corps avant
- 0, 128, 64, 192, // t�te
- 64, 128, 192, 160, // pince ext.
- 64, 160, 192, 192, // pince int.
- 0, 192, 64, 256, // mire
- -1
-};
-
-static int tablePartA[] = // ant.tga
-{
- 0, 0, 64, 64, // queue
- 0, 96, 128, 160, // queue abeille
- 64, 0, 128, 64, // corps
- 128, 0, 192, 64, // t�te
- 0, 64, 64, 72, // patte
- 0, 72, 64, 80, // antenne
- 64, 64, 150, 96, // queue ver
- 150, 64, 182, 96, // corps ver
- 182, 64, 256, 96, // t�te ver
- 224, 32, 256, 64, // articulation ver
- 128, 96, 220, 160, // aile
- 0, 80, 16, 96, // oeil
- 200, 0, 208, 8, // vert clair
- 200, 8, 208, 16, // vert fonc�
- 0, 160, 64, 224, // corps araign�e
- 64, 160, 128, 192, // t�te araign�e
- 208, 0, 216, 64, // patte araign�e
- 216, 0, 224, 32, // patte araign�e
- 224, 0, 256, 8, // antenne araign�e
- 192, 0, 200, 8, // brun clair
- 192, 8, 200, 16, // brun fonc�
- 128, 160, 256, 256, // SatCom
- -1
-};
-
-static int tablePartH[] = // human.tga
-{
- 0, 0, 64, 64, // vissi�re
- 64, 0, 96, 64, // cuisse
- 96, 0, 128, 64, // jambe
- 128, 0, 192, 32, // bras
- 128, 32, 192, 64, // avant-bras
- 0, 64, 128, 224, // ventre
- 128, 64, 256, 224, // dos
- 64, 224, 112, 256, // dessus pied
- 144, 224, 168, 240, // dessous pied
- 112, 224, 144, 240, // c�t� pied
- 112, 224, 128, 240, // c�t� pied
- 0, 224, 64, 256, // gant
- 168, 224, 200, 256, // oreille
- 112, 240, 144, 256, // ligne casque
- 200, 224, 208, 256, // int�rieur coup
- 240, 0, 244, 64, // bombone orange
- 244, 0, 248, 64, // bombone orange (reflet)
- 248, 0, 252, 64, // bombone bleu
- 252, 0, 256, 64, // bombone bleu (reflet)
- 144, 240, 156, 256, // gris habit
- 156, 240, 168, 256, // gris articulation
-//? 208, 224, 256, 256, // SatCom
- 192, 0, 240, 64, // quartz
- -1
-};
-
-static int tablePartG[] = // apollo.tga
-{
- 0, 0, 64, 64, // rev�tement LEM
- 64, 0, 128, 64, // rev�tement LEM
- 128, 8, 136, 128, // pied
- 0, 64, 64, 128, // roue
- 136, 24, 152, 44, // profil pneu
- 136, 8, 160, 24, // garde boue
- 64, 64, 128, 128, // si�ge
- 64, 128, 128, 192, // si�ge
- 64, 192, 128, 212, // si�ge
- 128, 128, 240, 192, // moteur
- 0, 192, 28, 256, // moteur
- 32, 128, 60, 256, // moteur
- 224, 0, 256, 128, // avant
- 206, 0, 224, 128, // avant
- 136, 44, 168, 62, // avant
- 64, 212, 108, 256, // panneau de commande
- 198, 0, 206, 128, // mat
- 190, 64, 198, 128, // mat
- 160, 8, 176, 24, // cam�ra
- 176, 8, 192, 24, // moyeu
- 136, 64, 168, 96, // module
- 168, 64, 190, 96, // module
- 136, 96, 168, 128, // module
- 128, 192, 230, 252, // drapeau
- 0, 128, 32, 192, // antenne
- 128, 0, 136, 8, // jaune
- 136, 0, 144, 8, // beige
- 144, 0, 152, 8, // brun
- 168, 0, 176, 8, // gris tr�s clair
- 152, 0, 160, 8, // gris clair
- 160, 0, 168, 8, // gris fonc�
- -1
-};
-
-static int tablePartB[] = // base1.tga
-{
- 0, 0, 80, 256, // int�rieur porte
- 80, 0, 88, 256, // tranche porte
- 116, 0, 180, 64, // coiffe 1
- 116, 64, 180, 102, // coiffe 2
- 180, 0, 244, 37, // base
- 180, 37, 196, 101, // support
- 88, 0, 116, 256, // colonne
- 212, 37, 256, 128, // suppl�ment
- 128, 128, 256, 256, // 1/4 du sol
- 196, 37, 212, 53, // gris fonc�
- 196, 53, 212, 69, // gris clair
- -1
-};
-
-static int tablePartCe[] = // cellar01.tga
-{
- 0, 128, 64, 192, // briques
- 64, 128, 128, 192, // briques
- 128, 128, 192, 192, // briques
- 192, 128, 256, 192, // briques
- -1
-};
-
-static int tablePartFa[] = // face01.tga
-{
- 0, 0, 256, 256, // visage
- -1
-};
-
-// Retourne le pointeur la table.
-
-int* CModel::RetTextureTable()
-{
- if ( m_textureRank == 0 ) return tablePartT;
- if ( m_textureRank == 1 ) return tablePartR;
- if ( m_textureRank == 2 ) return tablePartW;
- if ( m_textureRank == 3 ) return tablePartDr;
- if ( m_textureRank == 4 ) return tablePartKi;
- if ( m_textureRank == 5 ) return tablePartKi2;
- if ( m_textureRank == 6 ) return tablePartKi3;
- if ( m_textureRank == 7 ) return tablePartF;
- if ( m_textureRank == 8 ) return tablePartD;
- if ( m_textureRank == 9 ) return tablePartC;
- if ( m_textureRank == 10 ) return tablePartS;
- if ( m_textureRank == 11 ) return tablePartP;
- if ( m_textureRank == 12 ) return tablePartV;
- if ( m_textureRank == 13 ) return tablePartM;
- if ( m_textureRank == 14 ) return tablePartA;
- if ( m_textureRank == 15 ) return tablePartH;
- if ( m_textureRank == 16 ) return tablePartG;
- if ( m_textureRank == 17 ) return tablePartB;
- if ( m_textureRank == 18 ) return tablePartCe;
- if ( m_textureRank == 19 ) return tablePartFa;
- if ( m_textureRank == 20 ) return tablePartFa;
- if ( m_textureRank == 21 ) return tablePartFa;
- if ( m_textureRank == 22 ) return tablePartFa;
- return 0;
-}
-
-// Updates the part of texture.
-
-void CModel::TexturePartUpdate()
-{
- int *table;
-
- table = RetTextureTable();
- if ( table == 0 ) return;
-
- m_textureInf.x = (table[m_texturePart*4+0]+0.5f)/256.0f;
- m_textureInf.y = (table[m_texturePart*4+1]+0.5f)/256.0f;
- m_textureSup.x = (table[m_texturePart*4+2]-0.5f)/256.0f;
- m_textureSup.y = (table[m_texturePart*4+3]-0.5f)/256.0f;
-
- PutTextureValues();
-}
-
-// Changes the texture.
-
-void CModel::TextureRankChange(int step)
-{
- m_textureRank += step;
-
- if ( m_textureRank >= MAX_NAMES ) m_textureRank = 0;
- if ( m_textureRank < 0 ) m_textureRank = MAX_NAMES-1;
-
- if ( m_textureRank == 0 ) strcpy(m_textureName, "lemt.tga");
- if ( m_textureRank == 1 ) strcpy(m_textureName, "roller.tga");
- if ( m_textureRank == 2 ) strcpy(m_textureName, "subm.tga");
- if ( m_textureRank == 3 ) strcpy(m_textureName, "drawer.tga");
- if ( m_textureRank == 4 ) strcpy(m_textureName, "kid.tga");
- if ( m_textureRank == 5 ) strcpy(m_textureName, "kid2.tga");
- if ( m_textureRank == 6 ) strcpy(m_textureName, "kid3.tga");
- if ( m_textureRank == 7 ) strcpy(m_textureName, "factory.tga");
- if ( m_textureRank == 8 ) strcpy(m_textureName, "derrick.tga");
- if ( m_textureRank == 9 ) strcpy(m_textureName, "convert.tga");
- if ( m_textureRank == 10 ) strcpy(m_textureName, "search.tga");
- if ( m_textureRank == 11 ) strcpy(m_textureName, "plant.tga");
- if ( m_textureRank == 12 ) strcpy(m_textureName, "vegetal.tga");
- if ( m_textureRank == 13 ) strcpy(m_textureName, "mother.tga");
- if ( m_textureRank == 14 ) strcpy(m_textureName, "ant.tga");
- if ( m_textureRank == 15 ) strcpy(m_textureName, "human.tga");
- if ( m_textureRank == 16 ) strcpy(m_textureName, "apollo.tga");
- if ( m_textureRank == 17 ) strcpy(m_textureName, "base1.tga");
- if ( m_textureRank == 18 ) strcpy(m_textureName, "cellar01.tga");
- if ( m_textureRank == 19 ) strcpy(m_textureName, "face01.tga");
- if ( m_textureRank == 20 ) strcpy(m_textureName, "face02.tga");
- if ( m_textureRank == 21 ) strcpy(m_textureName, "face03.tga");
- if ( m_textureRank == 22 ) strcpy(m_textureName, "face04.tga");
-
- m_texturePart = 0;
-}
-
-// Changes the part of texture.
-
-void CModel::TexturePartChange(int step)
-{
- int *table;
-
- table = RetTextureTable();
- if ( table == 0 ) return;
-
- m_texturePart ++;
-
- if ( table[m_texturePart*4] == -1 )
- {
- m_texturePart = 0;
- }
-
- TexturePartUpdate();
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// model.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "old/water.h"
+#include "object/robotmain.h"
+#include "ui/interface.h"
+#include "ui/edit.h"
+#include "ui/button.h"
+#include "script/cmdtoken.h"
+#include "old/modfile.h"
+#include "old/model.h"
+
+
+
+const int MAX_COLORS = 9;
+
+static float table_color[MAX_COLORS*3] =
+{
+ 1.0f, 1.0f, 1.0f, // white
+ 1.0f, 0.0f, 0.0f, // red
+ 0.0f, 1.0f, 0.0f, // green
+ 0.0f, 0.6f, 1.0f, // blue
+ 1.0f, 1.0f, 0.0f, // yellow
+ 0.0f, 1.0f, 1.0f, // cyan
+ 1.0f, 0.0f, 1.0f, // magenta
+ 0.3f, 0.3f, 0.3f, // grey
+ 0.0f, 0.0f, 0.0f, // black
+};
+
+
+const int MAX_STATES = 10;
+
+static int table_state[MAX_STATES] =
+{
+ D3DSTATENORMAL,
+ D3DSTATEPART1,
+ D3DSTATEPART2,
+ D3DSTATEPART3,
+ D3DSTATEPART4,
+ D3DSTATE2FACE, // #5
+ D3DSTATETTw,
+ D3DSTATETTb,
+ D3DSTATETTw|D3DSTATE2FACE, // #8
+ D3DSTATETTb|D3DSTATE2FACE, // #9
+};
+
+
+const int MAX_NAMES = 23;
+
+
+
+
+// Object's constructor.
+
+CModel::CModel(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+
+ m_modFile = new CModFile(m_iMan);
+ m_triangleTable = m_modFile->RetTriangleList();
+
+ m_textureRank = 0;
+ strcpy(m_textureName, "lemt.tga");
+ m_color = 0;
+ m_state = 0;
+ m_textureMode = 0;
+ m_textureRotate = 0;
+ m_bTextureMirrorX = false;
+ m_bTextureMirrorY = false;
+ m_texturePart = 0;
+ TexturePartUpdate();
+
+ m_bDisplayTransparent = false;
+ m_bDisplayOnlySelection = false;
+ InitView();
+
+ m_triangleSel1 = 0;
+ m_triangleSel2 = 0;
+
+ m_mode = 1;
+ m_oper = 'P';
+
+ m_secondTexNum = 0;
+ m_secondSubdiv = 1;
+ m_secondOffsetU = 0;
+ m_secondOffsetV = 0;
+
+ m_min = 0.0f;
+ m_max = 1000000.0f;
+}
+
+// Object's destructor.
+
+CModel::~CModel()
+{
+ delete m_modFile;
+}
+
+
+// You must call this procedure before changing the model interactively.
+
+void CModel::StartUserAction()
+{
+ Event event;
+ Math::Point pos, dim;
+ CButton* pb;
+
+ dim.x = 105.0f/640.0f;
+ dim.y = 18.0f/480.0f;
+ pos.x = 10.0f/640.0f;
+ pos.y = 450.0f/480.0f;
+ m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT1);
+
+ dim.x = 50.0f/640.0f;
+ pos.x = 125.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON1);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("Load");
+ pos.x = 185.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON2);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("Script");
+ pos.x = 245.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON3);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("Read");
+ pos.x = 305.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON4);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("Add");
+ pos.x = 365.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON5);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("Write");
+
+ dim.x = 50.0f/640.0f;
+ dim.y = 18.0f/480.0f;
+ pos.x = 10.0f/640.0f;
+ pos.y = 425.0f/480.0f;
+ m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT2);
+ pos.x = 65.0f/640.0f;
+ pos.y = 425.0f/480.0f;
+ m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT3);
+ pos.x = 10.0f/640.0f;
+ pos.y = 400.0f/480.0f;
+ m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT4);
+ pos.x = 65.0f/640.0f;
+ pos.y = 400.0f/480.0f;
+ m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT5);
+
+ dim.x = 20.0f/640.0f;
+ dim.y = 20.0f/480.0f;
+ pos.y = 370.0f/480.0f;
+ pos.x = 10.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON10);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("P");
+ pos.x = 30.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON11);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("R");
+ pos.x = 50.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON12);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("Z");
+ pos.y = 350.0f/480.0f;
+ pos.x = 10.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON13);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("+X");
+ pos.x = 30.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON14);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("+Y");
+ pos.x = 50.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON15);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("+Z");
+ pos.y = 330.0f/480.0f;
+ pos.x = 10.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON16);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("-X");
+ pos.x = 30.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON17);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("-Y");
+ pos.x = 50.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON18);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("-Z");
+
+//? m_modFile->ReadModel("objects\\io.mod");
+ DeselectAll();
+ CurrentInit();
+
+ ZeroMemory(&event, sizeof(Event));
+ EventFrame(event);
+
+ m_engine->LoadAllTexture();
+ UpdateInfoText();
+}
+
+// You must call this procedure after modifing the model interactively.
+
+void CModel::StopUserAction()
+{
+ m_interface->DeleteControl(EVENT_EDIT1);
+ m_interface->DeleteControl(EVENT_EDIT2);
+ m_interface->DeleteControl(EVENT_EDIT3);
+ m_interface->DeleteControl(EVENT_EDIT4);
+ m_interface->DeleteControl(EVENT_EDIT5);
+ m_interface->DeleteControl(EVENT_BUTTON1);
+ m_interface->DeleteControl(EVENT_BUTTON2);
+ m_interface->DeleteControl(EVENT_BUTTON3);
+ m_interface->DeleteControl(EVENT_BUTTON4);
+ m_interface->DeleteControl(EVENT_BUTTON5);
+ m_interface->DeleteControl(EVENT_BUTTON10);
+ m_interface->DeleteControl(EVENT_BUTTON11);
+ m_interface->DeleteControl(EVENT_BUTTON12);
+ m_interface->DeleteControl(EVENT_BUTTON13);
+ m_interface->DeleteControl(EVENT_BUTTON14);
+ m_interface->DeleteControl(EVENT_BUTTON15);
+ m_interface->DeleteControl(EVENT_BUTTON16);
+ m_interface->DeleteControl(EVENT_BUTTON17);
+ m_interface->DeleteControl(EVENT_BUTTON18);
+
+ m_engine->SetInfoText(0, "");
+ m_engine->SetInfoText(1, "");
+}
+
+
+// Updates the​editable values for mapping textures.
+
+void CModel::PutTextureValues()
+{
+ CEdit* pe;
+ char s[100];
+ int value;
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT2);
+ if ( pe != 0 )
+ {
+ value = (int)(m_textureSup.x*256.0f+0.5f);
+ sprintf(s, "%d", value);
+ pe->SetText(s);
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT3);
+ if ( pe != 0 )
+ {
+ value = (int)(m_textureSup.y*256.0f+0.5f);
+ sprintf(s, "%d", value);
+ pe->SetText(s);
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT4);
+ if ( pe != 0 )
+ {
+ value = (int)(m_textureInf.x*256.0f-0.5f);
+ sprintf(s, "%d", value);
+ pe->SetText(s);
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT5);
+ if ( pe != 0 )
+ {
+ value = (int)(m_textureInf.y*256.0f-0.5f);
+ sprintf(s, "%d", value);
+ pe->SetText(s);
+ }
+}
+
+// Takes the editable values for mapping textures.
+
+void CModel::GetTextureValues()
+{
+ CEdit* pe;
+ char s[100];
+ int value;
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT2);
+ if ( pe != 0 )
+ {
+ pe->GetText(s, 100);
+ sscanf(s, "%d", &value);
+ m_textureSup.x = ((float)value-0.5f)/256.0f;
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT3);
+ if ( pe != 0 )
+ {
+ pe->GetText(s, 100);
+ sscanf(s, "%d", &value);
+ m_textureSup.y = ((float)value-0.5f)/256.0f;
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT4);
+ if ( pe != 0 )
+ {
+ pe->GetText(s, 100);
+ sscanf(s, "%d", &value);
+ m_textureInf.x = ((float)value+0.5f)/256.0f;
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT5);
+ if ( pe != 0 )
+ {
+ pe->GetText(s, 100);
+ sscanf(s, "%d", &value);
+ m_textureInf.y = ((float)value+0.5f)/256.0f;
+ }
+}
+
+
+// Gives the model name.
+
+void CModel::GetModelName(char *buffer)
+{
+ CEdit* pe;
+ char s[100];
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
+ if ( pe == 0 )
+ {
+ strcpy(buffer, "objects\\io.mod");
+ }
+ else
+ {
+ pe->GetText(s, 100);
+ sprintf(buffer, "objects\\%s.mod", s);
+ }
+}
+
+// Gives the model name.
+
+void CModel::GetDXFName(char *buffer)
+{
+ CEdit* pe;
+ char s[100];
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
+ if ( pe == 0 )
+ {
+ strcpy(buffer, "models\\import.dxf");
+ }
+ else
+ {
+ pe->GetText(s, 100);
+ sprintf(buffer, "models\\%s.dxf", s);
+ }
+}
+
+// Gives the model name.
+
+void CModel::GetScriptName(char *buffer)
+{
+ CEdit* pe;
+ char s[100];
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
+ if ( pe == 0 )
+ {
+ strcpy(buffer, "objects\\script.txt");
+ }
+ else
+ {
+ pe->GetText(s, 100);
+ sprintf(buffer, "objects\\%s.txt", s);
+ }
+}
+
+// Indicates whether the edition name has focus.
+
+bool CModel::IsEditFocus()
+{
+ CEdit* pe;
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
+ if ( pe != 0 )
+ {
+ if ( pe->RetFocus() ) return true;
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT2);
+ if ( pe != 0 )
+ {
+ if ( pe->RetFocus() ) return true;
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT3);
+ if ( pe != 0 )
+ {
+ if ( pe->RetFocus() ) return true;
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT4);
+ if ( pe != 0 )
+ {
+ if ( pe->RetFocus() ) return true;
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT5);
+ if ( pe != 0 )
+ {
+ if ( pe->RetFocus() ) return true;
+ }
+
+ return false;
+}
+
+
+// Management of an event.
+
+bool CModel::EventProcess(const Event &event)
+{
+ char s[100];
+ int first, last;
+
+ switch( event.event )
+ {
+ case EVENT_FRAME:
+ EventFrame(event);
+ break;
+
+ case EVENT_KEYDOWN:
+ if ( IsEditFocus() )
+ break;
+
+ if ( event.param == '1' )
+ {
+ m_mode = 1;
+ UpdateInfoText();
+ }
+ if ( event.param == '2' )
+ {
+ m_mode = 2;
+ UpdateInfoText();
+ }
+ if ( event.param == '3' )
+ {
+ m_mode = 3;
+ UpdateInfoText();
+ }
+ if ( event.param == VK_ADD ) // numpad?
+ {
+ if ( event.keyState & KS_SHIFT ) CurrentSelect(true);
+ CurrentSearchNext(+1, (event.keyState & KS_CONTROL));
+ }
+ if ( event.param == VK_SUBTRACT ) // least numpad?
+ {
+ if ( event.keyState & KS_SHIFT ) CurrentSelect(true);
+ CurrentSearchNext(-1, (event.keyState & KS_CONTROL));
+ }
+ if ( event.param == VK_NUMPAD0 )
+ {
+ CurrentSelect(false);
+ }
+ if ( event.param == VK_DECIMAL )
+ {
+ CurrentSelect(true);
+ }
+ if ( event.param == VK_END )
+ {
+ DeselectAll();
+ }
+ if ( event.param == VK_INSERT )
+ {
+ SelectAll();
+ }
+ if ( event.param == VK_BACK ) // Delete normal ?
+ {
+ SelectDelete();
+ }
+ if ( event.param == VK_SPACE )
+ {
+ m_bDisplayTransparent = !m_bDisplayTransparent;
+ m_bDisplayOnlySelection = false;
+ }
+ if ( event.param == 'H' )
+ {
+ m_bDisplayOnlySelection = !m_bDisplayOnlySelection;
+ m_bDisplayTransparent = false;
+ }
+ if ( m_mode == 1 )
+ {
+ if ( event.param == 'S' )
+ {
+ SmoothSelect();
+ }
+ if ( event.param == 'N' )
+ {
+ PlaneSelect();
+ }
+ if ( event.param == 'C' )
+ {
+ ColorSelect();
+ }
+ if ( event.param == 'V' )
+ {
+ m_color ++;
+ if ( m_color >= MAX_COLORS ) m_color = 0;
+ UpdateInfoText();
+ ColorSelect();
+ }
+ if ( event.param == 'J' )
+ {
+ StateSelect();
+ }
+ if ( event.param == 'K' )
+ {
+ m_state ++;
+ if ( m_state >= MAX_STATES ) m_state = 0;
+ UpdateInfoText();
+ StateSelect();
+ }
+ if ( event.param == 'M' )
+ {
+ m_textureMode ++;
+ if ( m_textureMode > 3 ) m_textureMode = 0;
+ UpdateInfoText();
+ GetTextureValues();
+ MappingSelect(m_textureMode, m_textureRotate,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ m_textureInf, m_textureSup, m_textureName);
+ }
+ if ( event.param == 'Z' )
+ {
+ m_textureRotate ++;
+ if ( m_textureRotate > 2 ) m_textureRotate = 0;
+ UpdateInfoText();
+ GetTextureValues();
+ MappingSelect(m_textureMode, m_textureRotate,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ m_textureInf, m_textureSup, m_textureName);
+ }
+ if ( event.param == 'X' )
+ {
+ m_bTextureMirrorX = !m_bTextureMirrorX;
+ UpdateInfoText();
+ GetTextureValues();
+ MappingSelect(m_textureMode, m_textureRotate,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ m_textureInf, m_textureSup, m_textureName);
+ }
+ if ( event.param == 'Y' )
+ {
+ m_bTextureMirrorY = !m_bTextureMirrorY;
+ UpdateInfoText();
+ GetTextureValues();
+ MappingSelect(m_textureMode, m_textureRotate,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ m_textureInf, m_textureSup, m_textureName);
+ }
+ if ( event.param == 'O' )
+ {
+ TextureRankChange(+1);
+ UpdateInfoText();
+ }
+ if ( event.param == 'P' )
+ {
+ TexturePartChange(+1);
+ UpdateInfoText();
+ GetTextureValues();
+ MappingSelect(m_textureMode, m_textureRotate,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ m_textureInf, m_textureSup, m_textureName);
+ }
+ if ( event.param == 'T' )
+ {
+ GetTextureValues();
+ MappingSelect(m_textureMode, m_textureRotate,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ m_textureInf, m_textureSup, m_textureName);
+ }
+ if ( event.param == 'E' )
+ {
+ Math::Point ti, ts;
+ ti.x = 0.00f;
+ ti.y = 0.00f;
+ ts.x = 0.00f;
+ ts.y = 0.00f;
+ MappingSelect(m_textureMode, m_textureRotate,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ ti, ts, "");
+ }
+ }
+ if ( m_mode == 2 )
+ {
+ if ( event.param == 'E' )
+ {
+ m_secondTexNum = 0;
+ UpdateInfoText();
+ MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
+ }
+ if ( event.param == 'O' )
+ {
+ m_secondTexNum ++;
+ if ( m_secondTexNum > 10 ) m_secondTexNum = 1;
+ UpdateInfoText();
+ }
+ if ( event.param == 'T' )
+ {
+ MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
+ m_engine->LoadAllTexture();
+ }
+ if ( event.param == 'U' )
+ {
+ m_secondOffsetU += 45;
+ if ( m_secondOffsetU >= 360 ) m_secondOffsetU = 0;
+ MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
+ UpdateInfoText();
+ }
+ if ( event.param == 'V' )
+ {
+ m_secondOffsetV += 45;
+ if ( m_secondOffsetV >= 360 ) m_secondOffsetV = 0;
+ MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
+ UpdateInfoText();
+ }
+ if ( event.param == 'X' )
+ {
+ m_bTextureMirrorX = !m_bTextureMirrorX;
+ MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
+ UpdateInfoText();
+ }
+ if ( event.param == 'Y' )
+ {
+ m_bTextureMirrorY = !m_bTextureMirrorY;
+ MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
+ UpdateInfoText();
+ }
+ if ( event.param == 'S' )
+ {
+ m_secondSubdiv ++;
+ if ( m_secondSubdiv > 7 ) m_secondSubdiv = 1;
+ MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
+ UpdateInfoText();
+ }
+ }
+ if ( m_mode == 3 )
+ {
+ if ( event.param == 'M' )
+ {
+ if ( m_min == 0.0f && m_max == 1000000.0f )
+ {
+ m_min = 0.0f; m_max = 100.0f;
+ }
+ else if ( m_min == 0.0f && m_max == 100.0f )
+ {
+ m_min = 100.0f; m_max = 200.0f;
+ }
+ else if ( m_min == 100.0f && m_max == 200.0f )
+ {
+ m_min = 200.0f; m_max = 1000000.0f;
+ }
+ else if ( m_min == 200.0f && m_max == 1000000.0f )
+ {
+ m_min = 0.0f; m_max = 1000000.0f;
+ }
+ UpdateInfoText();
+ }
+ if ( event.param == 'C' )
+ {
+ MinMaxChange();
+ }
+ }
+ break;
+
+ case EVENT_BUTTON1: // import ?
+ GetDXFName(s);
+ m_modFile->ReadDXF(s, m_min, m_max);
+ DeselectAll();
+ CurrentInit();
+ EventFrame(event);
+ m_engine->LoadAllTexture();
+ break;
+
+ case EVENT_BUTTON2: // script ?
+ GetScriptName(s);
+ ReadScript(s);
+ DeselectAll();
+ CurrentInit();
+ EventFrame(event);
+ m_engine->LoadAllTexture();
+ break;
+
+ case EVENT_BUTTON3: // read ?
+ GetModelName(s);
+ m_modFile->ReadModel(s, true, false); // standard read with borders
+ DeselectAll();
+ CurrentInit();
+ EventFrame(event);
+ m_engine->LoadAllTexture();
+ break;
+
+ case EVENT_BUTTON4: // add ?
+ GetModelName(s);
+ first = m_modFile->RetTriangleUsed();
+ m_modFile->AddModel(s, first, true, false); // standard read with borders
+ last = m_modFile->RetTriangleUsed();
+ SelectZone(first, last);
+ EventFrame(event);
+ break;
+
+ case EVENT_BUTTON5: // write ?
+ GetModelName(s);
+ DeselectAll();
+ m_modFile->WriteModel(s);
+ break;
+
+ case EVENT_BUTTON10: // pos ?
+ m_oper = 'P';
+ break;
+ case EVENT_BUTTON11: // rotate ?
+ m_oper = 'R';
+ break;
+ case EVENT_BUTTON12: // zoom ?
+ m_oper = 'Z';
+ break;
+
+ case EVENT_BUTTON13: // +X ?
+ MoveSelect(Math::Vector(1.0f, 0.0f, 0.0f));
+ break;
+ case EVENT_BUTTON16: // -X ?
+ MoveSelect(Math::Vector(-1.0f, 0.0f, 0.0f));
+ break;
+ case EVENT_BUTTON14: // +Y ?
+ MoveSelect(Math::Vector(0.0f, 1.0f, 0.0f));
+ break;
+ case EVENT_BUTTON17: // -Y ?
+ MoveSelect(Math::Vector(0.0f, -1.0f, 0.0f));
+ break;
+ case EVENT_BUTTON15: // +Z ?
+ MoveSelect(Math::Vector(0.0f, 0.0f, 1.0f));
+ break;
+ case EVENT_BUTTON18: // -Z ?
+ MoveSelect(Math::Vector(0.0f, 0.0f, -1.0f));
+ break;
+ }
+
+ return 0;
+}
+
+
+// Drives the model.
+
+bool CModel::EventFrame(const Event &event)
+{
+ D3DMATERIAL7 matCurrent, matCurrenti, matCurrents, matTrans;
+ D3DMATERIAL7* pMat;
+ D3DVERTEX2 vertex[3];
+ char texName2[20];
+ int i, used, objRank, state;
+
+ m_time += event.rTime;
+
+ m_engine->FlushObject();
+ objRank = m_engine->CreateObject();
+
+ ZeroMemory(&matCurrent, sizeof(D3DMATERIAL7));
+ matCurrent.diffuse.r = 1.0f;
+ matCurrent.diffuse.g = 0.0f;
+ matCurrent.diffuse.b = 0.0f; // red
+ matCurrent.ambient.r = 0.5f;
+ matCurrent.ambient.g = 0.5f;
+ matCurrent.ambient.b = 0.5f;
+
+ ZeroMemory(&matCurrents, sizeof(D3DMATERIAL7));
+ matCurrents.diffuse.r = 1.0f;
+ matCurrents.diffuse.g = 1.0f;
+ matCurrents.diffuse.b = 0.0f; // yellow
+ matCurrents.ambient.r = 0.5f;
+ matCurrents.ambient.g = 0.5f;
+ matCurrents.ambient.b = 0.5f;
+
+ ZeroMemory(&matCurrenti, sizeof(D3DMATERIAL7));
+ matCurrenti.diffuse.r = 0.0f;
+ matCurrenti.diffuse.g = 0.0f;
+ matCurrenti.diffuse.b = 1.0f; // blue
+ matCurrenti.ambient.r = 0.5f;
+ matCurrenti.ambient.g = 0.5f;
+ matCurrenti.ambient.b = 0.5f;
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( !m_triangleTable[i].bUsed ) continue;
+
+ if ( m_triangleTable[i].min != m_min ||
+ m_triangleTable[i].max != m_max ) continue;
+
+ pMat = &m_triangleTable[i].material;
+ state = D3DSTATENORMAL;
+
+ if ( i >= m_triangleSel1 &&
+ i <= m_triangleSel2 &&
+ (int)(m_time*10.0f)%2 == 0 )
+ {
+ pMat = &matCurrent;
+ }
+ else if ( m_triangleTable[i].bSelect &&
+ (int)(m_time*10.0f)%2 == 0 )
+ {
+ pMat = &matCurrents;
+ }
+ else
+ {
+ if ( m_bDisplayOnlySelection ) continue;
+ if ( m_bDisplayTransparent )
+ {
+ matTrans = m_triangleTable[i].material;
+ matTrans.diffuse.a = 0.1f; // very transparent
+ pMat = &matTrans;
+ state = D3DSTATETD;
+ }
+ }
+
+ if ( m_triangleTable[i].texNum2 == 0 )
+ {
+ m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
+ *pMat, state,
+ m_triangleTable[i].texName, "",
+ 0.0f, 1000000.0f, false);
+ }
+ else
+ {
+ sprintf(texName2, "dirty%.2d.tga", m_triangleTable[i].texNum2);
+ m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
+ *pMat, state|D3DSTATEDUALb,
+ m_triangleTable[i].texName, texName2,
+ 0.0f, 1000000.0f, false);
+ }
+
+ if ( m_bDisplayTransparent && // draws inside?
+ i >= m_triangleSel1 &&
+ i <= m_triangleSel2 )
+ {
+ vertex[0] = m_triangleTable[i].p3;
+ vertex[1] = m_triangleTable[i].p2;
+ vertex[2] = m_triangleTable[i].p1;
+
+ m_engine->AddTriangle(objRank, vertex, 3,
+ matCurrenti, D3DSTATENORMAL,
+ m_triangleTable[i].texName, "",
+ 0.0f, 1000000.0f, false);
+ }
+ }
+
+ return true;
+}
+
+
+// Gives a vertex.
+
+bool CModel::GetVertex(int rank, D3DVERTEX2 &vertex)
+{
+ if ( rank < 0 || rank/3 >= m_modFile->RetTriangleUsed() ) return false;
+ if ( !m_triangleTable[rank/3].bUsed ) return false;
+
+ if ( !m_triangleTable[rank/3].bSelect ) return false;
+
+ if ( rank%3 == 0 )
+ {
+ vertex = m_triangleTable[rank/3].p1;
+ return true;
+ }
+ if ( rank%3 == 1 )
+ {
+ vertex = m_triangleTable[rank/3].p2;
+ return true;
+ }
+ if ( rank%3 == 2 )
+ {
+ vertex = m_triangleTable[rank/3].p3;
+ return true;
+ }
+ return false;
+}
+
+// Modifies a vertex.
+
+bool CModel::SetVertex(int rank, D3DVERTEX2 &vertex)
+{
+ if ( rank < 0 || rank/3 >= m_modFile->RetTriangleUsed() ) return false;
+ if ( !m_triangleTable[rank/3].bUsed ) return false;
+
+ if ( !m_triangleTable[rank/3].bSelect ) return false;
+
+ if ( rank%3 == 0 )
+ {
+ m_triangleTable[rank/3].p1 = vertex;
+ return true;
+ }
+ if ( rank%3 == 1 )
+ {
+ m_triangleTable[rank/3].p2 = vertex;
+ return true;
+ }
+ if ( rank%3 == 2 )
+ {
+ m_triangleTable[rank/3].p3 = vertex;
+ return true;
+ }
+ return false;
+}
+
+// Smoothed normals selected triangles.
+
+void CModel::SmoothSelect()
+{
+ char* bDone;
+ int index[100];
+ int used, i, j, rank;
+ D3DVERTEX2 vi, vj;
+ Math::Vector sum;
+
+ used = m_modFile->RetTriangleUsed();
+
+ bDone = (char*)malloc(used*3*sizeof(char));
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ bDone[i] = false;
+ }
+
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ bDone[i] = true;
+ rank = 0;
+ index[rank++] = i;
+ if ( !GetVertex(i, vi) ) continue;
+
+ for ( j=0 ; j<used*3 ; j++ )
+ {
+ if ( bDone[j] ) continue;
+ if ( !GetVertex(j, vj) ) continue;
+ if ( vj.x == vi.x &&
+ vj.y == vi.y &&
+ vj.z == vi.z )
+ {
+ bDone[j] = true;
+ index[rank++] = j;
+ if ( rank >= 100 ) break;
+ }
+ }
+
+ sum.x = 0;
+ sum.y = 0;
+ sum.z = 0;
+ for ( j=0 ; j<rank ; j++ )
+ {
+ GetVertex(index[j], vj);
+ sum.x += vj.nx;
+ sum.y += vj.ny;
+ sum.z += vj.nz;
+ }
+ sum = Normalize(sum);
+
+ for ( j=0 ; j<rank ; j++ )
+ {
+ GetVertex(index[j], vj);
+ vj.nx = sum.x;
+ vj.ny = sum.y;
+ vj.nz = sum.z;
+ SetVertex(index[j], vj);
+ }
+ }
+
+ free(bDone);
+
+ SelectTerm();
+}
+
+
+// Cast normals selected triangles.
+
+void CModel::PlaneSelect()
+{
+ Math::Vector p1, p2, p3, n;
+ int used, i;
+
+ used = m_modFile->RetTriangleUsed();
+
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( m_triangleTable[i].bSelect )
+ {
+ p1.x = m_triangleTable[i].p1.x;
+ p1.y = m_triangleTable[i].p1.y;
+ p1.z = m_triangleTable[i].p1.z;
+
+ p2.x = m_triangleTable[i].p2.x;
+ p2.y = m_triangleTable[i].p2.y;
+ p2.z = m_triangleTable[i].p2.z;
+
+ p3.x = m_triangleTable[i].p3.x;
+ p3.y = m_triangleTable[i].p3.y;
+ p3.z = m_triangleTable[i].p3.z;
+
+ n = Math::NormalToPlane(p3, p2, p1);
+
+ m_triangleTable[i].p3.nx = n.x;
+ m_triangleTable[i].p3.ny = n.y;
+ m_triangleTable[i].p3.nz = n.z;
+ }
+ }
+ SelectTerm();
+}
+
+
+// Change the color of the selected triangles.
+
+void CModel::ColorSelect()
+{
+ int used, i;
+
+ DefaultSelect();
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( m_triangleTable[i].bSelect )
+ {
+ m_triangleTable[i].material.diffuse.r = table_color[m_color*3+0];
+ m_triangleTable[i].material.diffuse.g = table_color[m_color*3+1];
+ m_triangleTable[i].material.diffuse.b = table_color[m_color*3+2];
+ }
+ }
+ SelectTerm();
+}
+
+// Change the status of selected triangles.
+
+void CModel::StateSelect()
+{
+ int used, i;
+
+ DefaultSelect();
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( m_triangleTable[i].bSelect )
+ {
+ m_triangleTable[i].state = table_state[m_state];
+ }
+ }
+ SelectTerm();
+}
+
+// Moves the selection.
+
+void CModel::MoveSelect(Math::Vector move)
+{
+ if ( m_oper == 'Z' )
+ {
+ if ( move.x == +1 ) move.x = 1.1f;
+ else if ( move.x == -1 ) move.x = 1.0f/1.1f;
+ else move.x = 1.0f;
+ if ( move.y == +1 ) move.y = 1.1f;
+ else if ( move.y == -1 ) move.y = 1.0f/1.1f;
+ else move.y = 1.0f;
+ if ( move.z == +1 ) move.z = 1.1f;
+ else if ( move.z == -1 ) move.z = 1.0f/1.1f;
+ else move.z = 1.0f;
+ }
+ if ( m_oper == 'R' )
+ {
+#if 0
+ if ( move.x == +1 ) move.x = 5.0f*Math::PI/180.0f;
+ else if ( move.x == -1 ) move.x = -5.0f*Math::PI/180.0f;
+ if ( move.y == +1 ) move.y = 5.0f*Math::PI/180.0f;
+ else if ( move.y == -1 ) move.y = -5.0f*Math::PI/180.0f;
+ if ( move.z == +1 ) move.z = 5.0f*Math::PI/180.0f;
+ else if ( move.z == -1 ) move.z = -5.0f*Math::PI/180.0f;
+#else
+ if ( move.x == +1 ) move.x = 45.0f*Math::PI/180.0f;
+ else if ( move.x == -1 ) move.x = -45.0f*Math::PI/180.0f;
+ if ( move.y == +1 ) move.y = 45.0f*Math::PI/180.0f;
+ else if ( move.y == -1 ) move.y = -45.0f*Math::PI/180.0f;
+ if ( move.z == +1 ) move.z = 45.0f*Math::PI/180.0f;
+ else if ( move.z == -1 ) move.z = -45.0f*Math::PI/180.0f;
+#endif
+ }
+
+ OperSelect(move, m_oper);
+}
+
+// Moves the selection.
+
+void CModel::OperSelect(Math::Vector move, char oper)
+{
+ Math::Point rot;
+ int used, i;
+
+ DefaultSelect();
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( m_triangleTable[i].bSelect )
+ {
+ if ( oper == 'P' )
+ {
+ m_triangleTable[i].p1.x += move.x;
+ m_triangleTable[i].p1.y += move.y;
+ m_triangleTable[i].p1.z += move.z;
+ m_triangleTable[i].p2.x += move.x;
+ m_triangleTable[i].p2.y += move.y;
+ m_triangleTable[i].p2.z += move.z;
+ m_triangleTable[i].p3.x += move.x;
+ m_triangleTable[i].p3.y += move.y;
+ m_triangleTable[i].p3.z += move.z;
+ }
+ if ( oper == 'Z' )
+ {
+ m_triangleTable[i].p1.x *= move.x;
+ m_triangleTable[i].p1.y *= move.y;
+ m_triangleTable[i].p1.z *= move.z;
+ m_triangleTable[i].p2.x *= move.x;
+ m_triangleTable[i].p2.y *= move.y;
+ m_triangleTable[i].p2.z *= move.z;
+ m_triangleTable[i].p3.x *= move.x;
+ m_triangleTable[i].p3.y *= move.y;
+ m_triangleTable[i].p3.z *= move.z;
+ }
+ if ( oper == 'R' )
+ {
+ if ( move.x != 0 )
+ {
+ rot.x = m_triangleTable[i].p1.z;
+ rot.y = m_triangleTable[i].p1.y;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.x, rot);
+ m_triangleTable[i].p1.z = rot.x;
+ m_triangleTable[i].p1.y = rot.y;
+
+ rot.x = m_triangleTable[i].p2.z;
+ rot.y = m_triangleTable[i].p2.y;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.x, rot);
+ m_triangleTable[i].p2.z = rot.x;
+ m_triangleTable[i].p2.y = rot.y;
+
+ rot.x = m_triangleTable[i].p3.z;
+ rot.y = m_triangleTable[i].p3.y;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.x, rot);
+ m_triangleTable[i].p3.z = rot.x;
+ m_triangleTable[i].p3.y = rot.y;
+ }
+ if ( move.y != 0 )
+ {
+ rot.x = m_triangleTable[i].p1.x;
+ rot.y = m_triangleTable[i].p1.z;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.y, rot);
+ m_triangleTable[i].p1.x = rot.x;
+ m_triangleTable[i].p1.z = rot.y;
+
+ rot.x = m_triangleTable[i].p2.x;
+ rot.y = m_triangleTable[i].p2.z;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.y, rot);
+ m_triangleTable[i].p2.x = rot.x;
+ m_triangleTable[i].p2.z = rot.y;
+
+ rot.x = m_triangleTable[i].p3.x;
+ rot.y = m_triangleTable[i].p3.z;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.y, rot);
+ m_triangleTable[i].p3.x = rot.x;
+ m_triangleTable[i].p3.z = rot.y;
+ }
+ if ( move.z != 0 )
+ {
+ rot.x = m_triangleTable[i].p1.x;
+ rot.y = m_triangleTable[i].p1.y;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.z, rot);
+ m_triangleTable[i].p1.x = rot.x;
+ m_triangleTable[i].p1.y = rot.y;
+
+ rot.x = m_triangleTable[i].p2.x;
+ rot.y = m_triangleTable[i].p2.y;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.z, rot);
+ m_triangleTable[i].p2.x = rot.x;
+ m_triangleTable[i].p2.y = rot.y;
+
+ rot.x = m_triangleTable[i].p3.x;
+ rot.y = m_triangleTable[i].p3.y;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.z, rot);
+ m_triangleTable[i].p3.x = rot.x;
+ m_triangleTable[i].p3.y = rot.y;
+ }
+ }
+ }
+ }
+ SelectTerm();
+}
+
+// Performs a build script.
+
+void CModel::ReadScript(char *filename)
+{
+ FILE* file = NULL;
+ char line[200];
+ char name[200];
+ char buffer[200];
+ int i, first, last;
+ Math::Vector move;
+ bool bFirst = true;
+
+ file = fopen(filename, "r");
+ if ( file == NULL ) return;
+
+ while ( fgets(line, 200, file) != NULL )
+ {
+ for ( i=0 ; i<200 ; i++ )
+ {
+ if ( line[i] == '\t' ) line[i] = ' '; // replace tab by space
+ if ( line[i] == '/' && line[i+1] == '/' )
+ {
+ line[i] = 0;
+ break;
+ }
+ }
+
+ if ( Cmd(line, "Object") )
+ {
+ OpString(line, "name", name);
+ sprintf(buffer, "objects\\%s.mod", name);
+
+ if ( bFirst )
+ {
+ m_modFile->ReadModel(buffer, true, true);
+ last = m_modFile->RetTriangleUsed();
+ SelectZone(0, last);
+ }
+ else
+ {
+ first = m_modFile->RetTriangleUsed();
+ m_modFile->AddModel(buffer, first, true, false);
+ last = m_modFile->RetTriangleUsed();
+ SelectZone(first, last);
+ }
+ bFirst = false;
+
+ move = OpDir(line, "zoom");
+ OperSelect(move, 'Z');
+
+ move = OpDir(line, "rot");
+ move *= Math::PI/180.0f; // degrees -> radians
+ OperSelect(move, 'R');
+
+ move = OpDir(line, "pos");
+ OperSelect(move, 'P');
+ }
+ }
+
+ fclose(file);
+}
+
+
+
+// Computes the bbox of selected triangles.
+
+void CModel::BBoxCompute(Math::Vector &min, Math::Vector &max)
+{
+ D3DVERTEX2 vertex;
+ int used, i;
+
+ min.x = 1000000.0f;
+ min.y = 1000000.0f;
+ min.z = 1000000.0f;
+ max.x = -1000000.0f;
+ max.y = -1000000.0f;
+ max.z = -1000000.0f;
+
+ used = m_modFile->RetTriangleUsed();
+
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( !GetVertex(i, vertex) ) continue;
+
+ if ( vertex.x < min.x ) min.x = vertex.x;
+ if ( vertex.y < min.y ) min.y = vertex.y;
+ if ( vertex.z < min.z ) min.z = vertex.z;
+
+ if ( vertex.x > max.x ) max.x = vertex.x;
+ if ( vertex.y > max.y ) max.y = vertex.y;
+ if ( vertex.z > max.z ) max.z = vertex.z;
+ }
+}
+
+// Returns the gravity center of the selection.
+
+Math::Vector CModel::RetSelectCDG()
+{
+ Math::Vector min, max, cdg;
+
+ BBoxCompute(min, max);
+
+ cdg.x = (min.x+max.x)/2.0f;
+ cdg.y = (min.y+max.y)/2.0f;
+ cdg.z = (min.z+max.z)/2.0f;
+
+ return cdg;
+}
+
+// Returns the normal vector of the selection.
+
+Math::Vector CModel::RetSelectNormal()
+{
+ Math::Vector p1, p2, p3, n;
+
+ p1.x = m_triangleTable[m_triangleSel1].p1.nx;
+ p1.y = m_triangleTable[m_triangleSel1].p1.ny;
+ p1.z = m_triangleTable[m_triangleSel1].p1.nz;
+
+ p2.x = m_triangleTable[m_triangleSel1].p2.nx;
+ p2.y = m_triangleTable[m_triangleSel1].p2.ny;
+ p2.z = m_triangleTable[m_triangleSel1].p2.nz;
+
+ p3.x = m_triangleTable[m_triangleSel1].p3.nx;
+ p3.y = m_triangleTable[m_triangleSel1].p3.ny;
+ p3.z = m_triangleTable[m_triangleSel1].p3.nz;
+
+ n = Normalize(p1+p2+p3);
+
+ return n;
+}
+
+// Maps a texture onto the selected triangles.
+
+bool CModel::IsMappingSelectPlausible(D3DMaping D3Dmode)
+{
+ D3DVERTEX2 vertex[3];
+ Math::Vector min, max;
+ Math::Point a, b, ti, ts;
+ float au, bu, av, bv;
+ int used, i, j;
+
+ ti.x = 0.0f;
+ ti.y = 0.0f;
+ ts.x = 1.0f;
+ ts.y = 1.0f;
+
+ BBoxCompute(min, max);
+
+ if ( D3Dmode == D3DMAPPINGX )
+ {
+ a.x = min.z;
+ a.y = min.y;
+ b.x = max.z;
+ b.y = max.y;
+ }
+ if ( D3Dmode == D3DMAPPINGY )
+ {
+ a.x = min.x;
+ a.y = min.z;
+ b.x = max.x;
+ b.y = max.z;
+ }
+ if ( D3Dmode == D3DMAPPINGZ )
+ {
+ a.x = min.x;
+ a.y = min.y;
+ b.x = max.x;
+ b.y = max.y;
+ }
+
+ au = (ts.x-ti.x)/(b.x-a.x);
+ bu = ts.x-b.x*(ts.x-ti.x)/(b.x-a.x);
+
+ av = (ts.y-ti.y)/(b.y-a.y);
+ bv = ts.y-b.y*(ts.y-ti.y)/(b.y-a.y);
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( !GetVertex(i*3+0, vertex[0]) ) continue;
+ if ( !GetVertex(i*3+1, vertex[1]) ) continue;
+ if ( !GetVertex(i*3+2, vertex[2]) ) continue;
+
+ for ( j=0 ; j<3 ; j++ )
+ {
+ if ( D3Dmode == D3DMAPPINGX )
+ {
+ vertex[j].tu = vertex[j].z*au+bu;
+ vertex[j].tv = vertex[j].y*av+bv;
+ }
+ if ( D3Dmode == D3DMAPPINGY )
+ {
+ vertex[j].tu = vertex[j].x*au+bu;
+ vertex[j].tv = vertex[j].z*av+bv;
+ }
+ if ( D3Dmode == D3DMAPPINGZ )
+ {
+ vertex[j].tu = vertex[j].x*au+bu;
+ vertex[j].tv = vertex[j].y*av+bv;
+ }
+ }
+
+ if ( vertex[0].tu == vertex[1].tu &&
+ vertex[0].tu == vertex[2].tu ) return false;
+
+ if ( vertex[0].tv == vertex[1].tv &&
+ vertex[0].tv == vertex[2].tv ) return false;
+ }
+
+ return true;
+}
+
+// Maps a texture onto the selected triangles.
+
+void CModel::MappingSelect(int mode, int rotate, bool bMirrorX, bool bMirrorY,
+ Math::Point ti, Math::Point ts, char *texName)
+{
+ D3DVERTEX2 vertex;
+ Math::Vector min, max;
+ Math::Point a, b;
+ D3DMaping D3Dmode;
+ float au, bu, av, bv;
+ int used, i;
+ bool bPlausible[3];
+
+ DefaultSelect();
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( !m_triangleTable[i].bUsed ) continue;
+ if ( !m_triangleTable[i].bSelect ) continue;
+
+ strcpy(m_triangleTable[i].texName, texName);
+ }
+
+ if ( mode == 1 )
+ {
+ MappingSelectSpherical(mode, rotate, bMirrorX, bMirrorY, ti, ts, texName);
+ return;
+ }
+ if ( mode == 2 )
+ {
+ MappingSelectCylindrical(mode, rotate, bMirrorX, bMirrorY, ti, ts, texName);
+ return;
+ }
+ if ( mode == 3 )
+ {
+ MappingSelectFace(mode, rotate, bMirrorX, bMirrorY, ti, ts, texName);
+ return;
+ }
+
+ BBoxCompute(min, max);
+
+ bPlausible[0] = IsMappingSelectPlausible(D3DMAPPINGX);
+ bPlausible[1] = IsMappingSelectPlausible(D3DMAPPINGY);
+ bPlausible[2] = IsMappingSelectPlausible(D3DMAPPINGZ);
+
+ for ( i=0 ; i<9 ; i++ )
+ {
+ if ( !bPlausible[i%3] ) continue;
+ if ( rotate-- == 0 ) break;
+ }
+ if ( i%3 == 0 ) D3Dmode = D3DMAPPINGX;
+ if ( i%3 == 1 ) D3Dmode = D3DMAPPINGY;
+ if ( i%3 == 2 ) D3Dmode = D3DMAPPINGZ;
+
+ if ( D3Dmode == D3DMAPPINGX )
+ {
+ a.x = min.z;
+ a.y = min.y;
+ b.x = max.z;
+ b.y = max.y;
+ }
+ if ( D3Dmode == D3DMAPPINGY )
+ {
+ a.x = min.x;
+ a.y = min.z;
+ b.x = max.x;
+ b.y = max.z;
+ }
+ if ( D3Dmode == D3DMAPPINGZ )
+ {
+ a.x = min.x;
+ a.y = min.y;
+ b.x = max.x;
+ b.y = max.y;
+ }
+
+ if ( bMirrorX )
+ {
+ Math::Swap(ti.x, ts.x);
+ }
+
+ if ( !bMirrorY ) // reverse test!
+ {
+ Math::Swap(ti.y, ts.y);
+ }
+
+ au = (ts.x-ti.x)/(b.x-a.x);
+ bu = ts.x-b.x*(ts.x-ti.x)/(b.x-a.x);
+
+ av = (ts.y-ti.y)/(b.y-a.y);
+ bv = ts.y-b.y*(ts.y-ti.y)/(b.y-a.y);
+
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( !GetVertex(i, vertex) ) continue;
+
+ if ( D3Dmode == D3DMAPPINGX )
+ {
+ vertex.tu = vertex.z*au+bu;
+ vertex.tv = vertex.y*av+bv;
+ }
+ if ( D3Dmode == D3DMAPPINGY )
+ {
+ vertex.tu = vertex.x*au+bu;
+ vertex.tv = vertex.z*av+bv;
+ }
+ if ( D3Dmode == D3DMAPPINGZ )
+ {
+ vertex.tu = vertex.x*au+bu;
+ vertex.tv = vertex.y*av+bv;
+ }
+
+ SetVertex(i, vertex);
+ }
+
+ SelectTerm();
+}
+
+// Maps a texture onto the selected triangles.
+
+void CModel::MappingSelectSpherical(int mode, int rotate, bool bMirrorX, bool bMirrorY,
+ Math::Point ti, Math::Point ts, char *texName)
+{
+ D3DVERTEX2 vertex;
+ Math::Vector min, max, center, dim, p;
+ float radius, k, u, v;
+ int used, i;
+
+ BBoxCompute(min, max);
+ center = (min+max)/2.0f;
+ dim = (max-min)/2.0f;
+ radius = Math::Min(dim.x, dim.y, dim.z);
+
+ if ( bMirrorX )
+ {
+ Math::Swap(ti.x, ts.x);
+ }
+
+ if ( !bMirrorY ) // reverse test!
+ {
+ Math::Swap(ti.y, ts.y);
+ }
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( !GetVertex(i, vertex) ) continue;
+
+ p.x = vertex.x-center.x;
+ p.y = vertex.y-center.y;
+ p.z = vertex.z-center.z;
+
+ k = radius/p.Length();
+ u = k*p.x;
+ v = k*p.z;
+ u = (u/dim.x*2.0f+1.0f)/2.0f; // 0..1
+ v = (v/dim.z*2.0f+1.0f)/2.0f;
+
+ vertex.tu = ti.x+(ts.x-ti.x)*u;
+ vertex.tv = ti.y+(ts.y-ti.y)*v;
+
+ SetVertex(i, vertex);
+ }
+
+ SelectTerm();
+}
+
+// Seeking the center of a group of points.
+
+Math::Vector CModel::RetMappingCenter(Math::Vector pos, Math::Vector min)
+{
+ D3DVERTEX2 vertex;
+ Math::Vector center, p;
+ int used, i, nb;
+
+ center.x = 0.0f;
+ center.y = 0.0f;
+ center.z = 0.0f;
+
+ nb = 0;
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( !GetVertex(i, vertex) ) continue;
+
+ p.x = vertex.x;
+ p.y = vertex.y;
+ p.z = vertex.z;
+
+ if ( fabs(p.x-pos.x) <= min.x &&
+ fabs(p.y-pos.y) <= min.y &&
+ fabs(p.z-pos.z) <= min.z )
+ {
+ center.x += p.x;
+ center.y += p.y;
+ center.z += p.z;
+ nb ++;
+ }
+ }
+
+ if ( nb == 0 ) return pos;
+
+ center.x /= (float)nb;
+ center.y /= (float)nb;
+ center.z /= (float)nb;
+
+ return center;
+}
+
+// Maps a texture onto the selected triangles.
+
+void CModel::MappingSelectCylindrical(int mode, int rotate, bool bMirrorX, bool bMirrorY,
+ Math::Point ti, Math::Point ts, char *texName)
+{
+ D3DVERTEX2 vertex;
+ Math::Vector min, max, center, local, dim, p, pp, box;
+ float radius, u, v;
+ int used, i;
+
+ BBoxCompute(min, max);
+ center = (min+max)/2.0f;
+ dim = (max-min)/2.0f;
+ radius = Math::Min(dim.x, dim.y, dim.z);
+
+ if ( bMirrorX )
+ {
+ Math::Swap(ti.x, ts.x);
+ }
+
+ if ( !bMirrorY ) // reverse test!
+ {
+ Math::Swap(ti.y, ts.y);
+ }
+
+ if ( rotate == 0 )
+ {
+ box.x = 2.0f;
+ box.y = 10.0f;
+ box.z = 10.0f;
+ }
+ if ( rotate == 1 )
+ {
+ box.x = 10.0f;
+ box.y = 2.0f;
+ box.z = 10.0f;
+ }
+ if ( rotate == 2 )
+ {
+ box.x = 10.0f;
+ box.y = 10.0f;
+ box.z = 2.0f;
+ }
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( !GetVertex(i, vertex) ) continue;
+
+ p.x = vertex.x;
+ p.y = vertex.y;
+ p.z = vertex.z;
+
+#if 1
+ p.x -= center.x;
+ p.y -= center.y;
+ p.z -= center.z;
+
+ pp = p;
+#else
+ local = RetMappingCenter(p, box);
+
+ pp = p;
+ pp.x -= local.x;
+ pp.y -= local.y;
+ pp.z -= local.z;
+
+ p.x -= center.x;
+ p.y -= center.y;
+ p.z -= center.z;
+#endif
+
+ if ( rotate == 0 )
+ {
+ u = Math::RotateAngle(pp.y, pp.z);
+ v = p.x/dim.x/2.0f + 0.5f;
+ }
+ if ( rotate == 1 )
+ {
+ u = Math::RotateAngle(pp.x, pp.z);
+ v = p.y/dim.y/2.0f + 0.5f;
+ }
+ if ( rotate == 2 )
+ {
+ u = Math::RotateAngle(pp.x, pp.y);
+ v = p.z/dim.z/2.0f + 0.5f;
+ }
+
+//? if ( u < Math::PI ) u = u/Math::PI;
+//? else u = 2.0f-u/Math::PI;
+ u = u/(Math::PI*2.0f);
+
+ vertex.tu = ti.x+(ts.x-ti.x)*u;
+ vertex.tv = ti.y+(ts.y-ti.y)*v;
+
+ SetVertex(i, vertex);
+ }
+
+ SelectTerm();
+}
+
+
+// Maps a texture onto the selected triangles.
+
+void CModel::MappingSelectFace(int mode, int rotate, bool bMirrorX, bool bMirrorY,
+ Math::Point ti, Math::Point ts, char *texName)
+{
+ D3DVERTEX2 vertex[3];
+ Math::Vector min, max, center, local, dim, p;
+ float radius, u[3], v[3], m[3], avg;
+ int used, i, j;
+
+ BBoxCompute(min, max);
+ center = (min+max)/2.0f;
+ dim = (max-min)/2.0f;
+ radius = Math::Min(dim.x, dim.y, dim.z);
+
+ if ( bMirrorX )
+ {
+ Math::Swap(ti.x, ts.x);
+ }
+
+ if ( !bMirrorY ) // reverse test!
+ {
+ Math::Swap(ti.y, ts.y);
+ }
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ for ( j=0 ; j<3 ; j++ )
+ {
+ if ( !GetVertex(i*3+j, vertex[j]) ) continue;
+
+ p.x = vertex[j].x - center.x;
+ p.y = vertex[j].y - center.y;
+ p.z = vertex[j].z - center.z;
+
+#if 0
+ u[j] = Math::RotateAngle(p.x, p.z)/(Math::PI*2.0f)+0.5f;
+ if ( u[j] > 1.0f ) u[j] -= 1.0f;
+#else
+ u[j] = Math::RotateAngle(p.x, p.z)/Math::PI;
+//? if ( u[j] > 1.0f ) u[j] = 2.0f-u[j];
+ if ( u[j] > 1.0f ) u[j] -= 1.0f;
+#endif
+
+ v[j] = p.y/dim.y/2.0f + 0.5f;
+
+ if ( u[j] < 0.5f ) m[j] = u[j];
+ else m[j] = u[j]-1.0f;
+ }
+
+ avg = (m[0]+m[1]+m[2])/3.0f;
+
+ for ( j=0 ; j<3 ; j++ )
+ {
+ if ( u[j] < 0.05f || u[j] > 0.95f )
+ {
+ if ( avg > 0.0f ) u[j] = 0.0f;
+ else u[j] = 1.0f;
+ }
+
+ vertex[j].tu = ti.x+(ts.x-ti.x)*u[j];
+ vertex[j].tv = ti.y+(ts.y-ti.y)*v[j];
+
+ SetVertex(i*3+j, vertex[j]);
+ }
+ }
+
+ SelectTerm();
+}
+
+
+// Maps a secondary texture on selected triangles.
+
+void CModel::MappingSelect2(int texNum2, int subdiv,
+ int offsetU, int offsetV,
+ bool bMirrorX, bool bMirrorY)
+{
+ D3DVERTEX2 vertex;
+ Math::Vector min, max, center, p;
+ float u ,v;
+ int used, i;
+
+ DefaultSelect();
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( !m_triangleTable[i].bUsed ) continue;
+ if ( !m_triangleTable[i].bSelect ) continue;
+
+ m_triangleTable[i].texNum2 = texNum2;
+ }
+
+ if ( subdiv == 6 )
+ {
+ MappingSelectSpherical2(bMirrorX, bMirrorY);
+ return;
+ }
+ if ( subdiv == 7 )
+ {
+ MappingSelectMagic2(bMirrorX, bMirrorY);
+ return;
+ }
+ if ( subdiv > 2 )
+ {
+ MappingSelectPlane2(subdiv-3, bMirrorX, bMirrorY);
+ return;
+ }
+
+ BBoxCompute(min, max);
+ center = (min+max)/2.0f;
+
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( !GetVertex(i, vertex) ) continue;
+
+ p.x = vertex.x-center.x;
+ p.y = vertex.y-center.y;
+ p.z = vertex.z-center.z;
+
+ u = Math::RotateAngle(p.x, p.z);
+ v = Math::RotateAngle(Math::Point(p.x, p.z).Length(), p.y);
+ if ( p.x < 0.0f ) v += Math::PI;
+
+ u = Math::NormAngle(u+(float)offsetU*Math::PI/180.0f);
+ v = Math::NormAngle(v+(float)offsetV*Math::PI/180.0f);
+
+ if ( subdiv == 1 )
+ {
+ u = u/(Math::PI*2.0f);
+ v = v/(Math::PI*2.0f);
+ }
+ if ( subdiv == 2 )
+ {
+ if ( u < Math::PI ) u = u/Math::PI;
+ else u = (Math::PI*2.0f-u)/Math::PI;
+ if ( v < Math::PI ) v = v/Math::PI;
+ else v = (Math::PI*2.0f-v)/Math::PI;
+ }
+
+ vertex.tu2 = u;
+ vertex.tv2 = v;
+
+ SetVertex(i, vertex);
+ }
+
+ SelectTerm();
+}
+
+// Maps a secondary texture on flat.
+
+void CModel::MappingSelectPlane2(int mode, bool bMirrorX, bool bMirrorY)
+{
+ D3DVERTEX2 vertex;
+ Math::Vector min, max;
+ Math::Point ti, ts, a, b;
+ float au, bu, av, bv;
+ int used, i;
+
+ ti = Math::Point(0.0f, 0.0f);
+ ts = Math::Point(1.0f, 1.0f);
+
+ BBoxCompute(min, max);
+
+ if ( mode == 0 )
+ {
+ a.x = min.z;
+ a.y = min.y;
+ b.x = max.z;
+ b.y = max.y;
+ }
+ if ( mode == 1 )
+ {
+ a.x = min.x;
+ a.y = min.z;
+ b.x = max.x;
+ b.y = max.z;
+ }
+ if ( mode == 2 )
+ {
+ a.x = min.x;
+ a.y = min.y;
+ b.x = max.x;
+ b.y = max.y;
+ }
+
+ if ( bMirrorX )
+ {
+ Math::Swap(ti.x, ts.x);
+ }
+
+ if ( !bMirrorY ) // reverse test!
+ {
+ Math::Swap(ti.y, ts.y);
+ }
+
+ au = (ts.x-ti.x)/(b.x-a.x);
+ bu = ts.x-b.x*(ts.x-ti.x)/(b.x-a.x);
+
+ av = (ts.y-ti.y)/(b.y-a.y);
+ bv = ts.y-b.y*(ts.y-ti.y)/(b.y-a.y);
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( !GetVertex(i, vertex) ) continue;
+
+ if ( mode == 0 )
+ {
+ vertex.tu2 = vertex.z*au+bu;
+ vertex.tv2 = vertex.y*av+bv;
+ }
+ if ( mode == 1 )
+ {
+ vertex.tu2 = vertex.x*au+bu;
+ vertex.tv2 = vertex.z*av+bv;
+ }
+ if ( mode == 2 )
+ {
+ vertex.tu2 = vertex.x*au+bu;
+ vertex.tv2 = vertex.y*av+bv;
+ }
+
+ SetVertex(i, vertex);
+ }
+
+ SelectTerm();
+}
+
+// Maps a texture onto the selected triangles.
+
+void CModel::MappingSelectSpherical2(bool bMirrorX, bool bMirrorY)
+{
+ D3DVERTEX2 vertex;
+ Math::Vector min, max, center, dim, p;
+ Math::Point ti, ts;
+ float radius, k, u, v;
+ int used, i;
+
+ BBoxCompute(min, max);
+ center = (min+max)/2.0f;
+ dim = (max-min)/2.0f;
+ radius = Math::Min(dim.x, dim.y, dim.z);
+
+ ti = Math::Point(0.0f, 0.0f);
+ ts = Math::Point(1.0f, 1.0f);
+
+ if ( bMirrorX )
+ {
+ Math::Swap(ti.x, ts.x);
+ }
+
+ if ( !bMirrorY ) // reverse test!
+ {
+ Math::Swap(ti.y, ts.y);
+ }
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( !GetVertex(i, vertex) ) continue;
+
+ p.x = vertex.x-center.x;
+ p.y = vertex.y-center.y;
+ p.z = vertex.z-center.z;
+
+ k = radius/p.Length();
+ u = k*p.x;
+ v = k*p.z;
+ u = (u/dim.x*2.0f+1.0f)/2.0f; // 0..1
+ v = (v/dim.z*2.0f+1.0f)/2.0f;
+
+ vertex.tu2 = ti.x+(ts.x-ti.x)*u;
+ vertex.tv2 = ti.y+(ts.y-ti.y)*v;
+
+ SetVertex(i, vertex);
+ }
+
+ SelectTerm();
+}
+
+// Maps a texture onto the selected triangles.
+
+void CModel::MappingSelectMagic2(bool bMirrorX, bool bMirrorY)
+{
+ D3DVERTEX2 vertex, v[3];
+ Math::Vector min, max, au, bu, av, bv, n;
+ Math::Point ti, ts;
+ int used, i, mode;
+
+ ti = Math::Point(0.0f, 0.0f);
+ ts = Math::Point(1.0f, 1.0f);
+
+ BBoxCompute(min, max);
+
+ if ( bMirrorX )
+ {
+ Math::Swap(ti.x, ts.x);
+ }
+
+ if ( !bMirrorY ) // reverse test!
+ {
+ Math::Swap(ti.y, ts.y);
+ }
+
+ au.x = (ts.x-ti.x)/(max.x-min.x);
+ bu.x = ts.x-max.x*(ts.x-ti.x)/(max.x-min.x);
+ au.y = (ts.x-ti.x)/(max.y-min.y);
+ bu.y = ts.x-max.y*(ts.x-ti.x)/(max.y-min.y);
+ au.z = (ts.x-ti.x)/(max.z-min.z);
+ bu.z = ts.x-max.z*(ts.x-ti.x)/(max.z-min.z);
+
+ av.x = (ts.y-ti.y)/(max.x-min.x);
+ bv.x = ts.y-max.x*(ts.y-ti.y)/(max.x-min.x);
+ av.y = (ts.y-ti.y)/(max.y-min.y);
+ bv.y = ts.y-max.y*(ts.y-ti.y)/(max.y-min.y);
+ av.z = (ts.y-ti.y)/(max.z-min.z);
+ bv.z = ts.y-max.z*(ts.y-ti.y)/(max.z-min.z);
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( i%3 == 0 )
+ {
+ if ( !GetVertex(i+0, v[0]) ) continue;
+ if ( !GetVertex(i+1, v[1]) ) continue;
+ if ( !GetVertex(i+2, v[2]) ) continue;
+
+ n = Math::NormalToPlane(Math::Vector(v[0].x, v[0].y, v[0].z),
+ Math::Vector(v[1].x, v[1].y, v[1].z),
+ Math::Vector(v[2].x, v[2].y, v[2].z));
+
+ n.x = fabs(n.x);
+ n.y = fabs(n.y);
+ n.z = fabs(n.z);
+
+ if ( n.x >= Math::Max(n.y, n.z) ) mode = 0;
+ if ( n.y >= Math::Max(n.x, n.z) ) mode = 1;
+ if ( n.z >= Math::Max(n.x, n.y) ) mode = 2;
+ }
+
+ if ( !GetVertex(i, vertex) ) continue;
+
+ if ( mode == 0 )
+ {
+ vertex.tu2 = vertex.z*au.z+bu.z;
+ vertex.tv2 = vertex.y*av.y+bv.y;
+ }
+ if ( mode == 1 )
+ {
+ vertex.tu2 = vertex.x*au.x+bu.x;
+ vertex.tv2 = vertex.z*av.z+bv.z;
+ }
+ if ( mode == 2 )
+ {
+ vertex.tu2 = vertex.x*au.x+bu.x;
+ vertex.tv2 = vertex.y*av.y+bv.y;
+ }
+
+ SetVertex(i, vertex);
+ }
+
+ SelectTerm();
+}
+
+
+// Seeks the next triangle.
+
+int CModel::SearchNext(int rank, int step)
+{
+ int max, i;
+
+ max = m_modFile->RetTriangleUsed();
+
+ for ( i=0 ; i<max ; i++ )
+ {
+ rank += step;
+ if ( rank < 0 ) rank = max-1;
+ if ( rank >= max ) rank = 0;
+
+ if ( m_triangleTable[rank].min != m_min ||
+ m_triangleTable[rank].max != m_max ) continue;
+
+ if ( m_triangleTable[rank].bUsed ) break;
+ }
+ return rank;
+}
+
+// Seeks all the triangles belonging to the same plane.
+
+int CModel::SearchSamePlane(int first, int step)
+{
+ Math::Vector vFirst[3], vNext[3];
+ int last, i;
+
+ vFirst[0].x = m_triangleTable[first].p1.x;
+ vFirst[0].y = m_triangleTable[first].p1.y;
+ vFirst[0].z = m_triangleTable[first].p1.z;
+ vFirst[1].x = m_triangleTable[first].p2.x;
+ vFirst[1].y = m_triangleTable[first].p2.y;
+ vFirst[1].z = m_triangleTable[first].p2.z;
+ vFirst[2].x = m_triangleTable[first].p3.x;
+ vFirst[2].y = m_triangleTable[first].p3.y;
+ vFirst[2].z = m_triangleTable[first].p3.z;
+
+ for ( i=0 ; i<1000 ; i++ )
+ {
+ last = first;
+ first = SearchNext(first, step);
+
+ vNext[0].x = m_triangleTable[first].p1.x;
+ vNext[0].y = m_triangleTable[first].p1.y;
+ vNext[0].z = m_triangleTable[first].p1.z;
+ vNext[1].x = m_triangleTable[first].p2.x;
+ vNext[1].y = m_triangleTable[first].p2.y;
+ vNext[1].z = m_triangleTable[first].p2.z;
+ vNext[2].x = m_triangleTable[first].p3.x;
+ vNext[2].y = m_triangleTable[first].p3.y;
+ vNext[2].z = m_triangleTable[first].p3.z;
+
+ if ( !IsSamePlane(vFirst, vNext) ) // other plan?
+ {
+ return last;
+ }
+ }
+ return first;
+}
+
+// Seeks the next triangle.
+
+void CModel::CurrentSearchNext(int step, bool bControl)
+{
+ if ( step > 0 ) // forward?
+ {
+ m_triangleSel1 = SearchNext(m_triangleSel2, step);
+ if ( bControl )
+ {
+ m_triangleSel2 = m_triangleSel1;
+ }
+ else
+ {
+ m_triangleSel2 = SearchSamePlane(m_triangleSel1, step);
+ }
+ }
+ if ( step < 0 ) // back?
+ {
+ m_triangleSel2 = SearchNext(m_triangleSel1, step);
+ if ( bControl )
+ {
+ m_triangleSel1 = m_triangleSel2;
+ }
+ else
+ {
+ m_triangleSel1 = SearchSamePlane(m_triangleSel2, step);
+ }
+ }
+
+#if 0
+ char s[100];
+ sprintf(s, "(%.2f;%.2f;%.2f) (%.2f;%.2f;%.2f) (%.2f;%.2f;%.2f)",
+ m_triangleTable[m_triangleSel1].p1.x,
+ m_triangleTable[m_triangleSel1].p1.y,
+ m_triangleTable[m_triangleSel1].p1.z,
+ m_triangleTable[m_triangleSel1].p2.x,
+ m_triangleTable[m_triangleSel1].p2.y,
+ m_triangleTable[m_triangleSel1].p2.z,
+ m_triangleTable[m_triangleSel1].p3.x,
+ m_triangleTable[m_triangleSel1].p3.y,
+ m_triangleTable[m_triangleSel1].p3.z);
+ m_engine->SetInfoText(2, s);
+ sprintf(s, "(%.2f;%.2f) (%.2f;%.2f) (%.2f;%.2f)",
+ m_triangleTable[m_triangleSel1].p1.tu2,
+ m_triangleTable[m_triangleSel1].p1.tv2,
+ m_triangleTable[m_triangleSel1].p2.tu2,
+ m_triangleTable[m_triangleSel1].p2.tv2,
+ m_triangleTable[m_triangleSel1].p3.tu2,
+ m_triangleTable[m_triangleSel1].p3.tv2);
+ m_engine->SetInfoText(3, s);
+#endif
+
+ InitViewFromSelect();
+ UpdateInfoText();
+}
+
+// Initializes the current triangles.
+
+void CModel::CurrentInit()
+{
+ m_triangleSel1 = 0;
+ m_triangleSel2 = SearchSamePlane(m_triangleSel1, +1);
+
+ InitViewFromSelect();
+ UpdateInfoText();
+}
+
+// Selects the current triangles.
+
+void CModel::CurrentSelect(bool bSelect)
+{
+ int i;
+
+ for ( i=m_triangleSel1 ; i<=m_triangleSel2 ; i++ )
+ {
+ m_triangleTable[i].bSelect = bSelect;
+ }
+}
+
+
+// Deselects all triangles.
+
+void CModel::DeselectAll()
+{
+ int used, i;
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ m_triangleTable[i].bSelect = false;
+ }
+}
+
+// Selects an area.
+
+void CModel::SelectZone(int first, int last)
+{
+ int used, i;
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ m_triangleTable[i].bSelect = false;
+ if ( i >= first && i < last )
+ {
+ m_triangleTable[i].bSelect = true;
+ }
+ }
+ m_triangleSel1 = first;
+ m_triangleSel2 = last-1;
+}
+
+// Selects all triangles.
+
+void CModel::SelectAll()
+{
+ int used, i;
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( m_triangleTable[i].min == m_min &&
+ m_triangleTable[i].max == m_max )
+ {
+ m_triangleTable[i].bSelect = true;
+ }
+ }
+}
+
+// Deselects all triangles.
+
+void CModel::SelectTerm()
+{
+ int used, i;
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( i >= m_triangleSel1 && i <= m_triangleSel2 )
+ {
+ if ( !m_triangleTable[i].bSelect ) return;
+ }
+ else
+ {
+ if ( m_triangleTable[i].bSelect ) return;
+ }
+ }
+
+ DeselectAll();
+}
+
+// Selects the triangles currents.
+
+void CModel::DefaultSelect()
+{
+ int used, i;
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=m_triangleSel1 ; i<=m_triangleSel2 ; i++ )
+ {
+ m_triangleTable[i].bSelect = true;
+ }
+}
+
+
+
+// Removes all selected triangles.
+
+void CModel::SelectDelete()
+{
+ int used ,i;
+
+ DefaultSelect();
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( m_triangleTable[i].bSelect )
+ {
+ m_triangleTable[i].bUsed = false;
+ }
+ }
+
+ i = m_triangleSel1;
+ Compress();
+
+ m_triangleSel1 = i;
+ m_triangleSel2 = SearchSamePlane(m_triangleSel1, +1);
+ InitViewFromSelect();
+ UpdateInfoText();
+}
+
+// Compresses all triangles.
+
+void CModel::Compress()
+{
+ int used, i, j;
+
+ j = 0;
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( m_triangleTable[i].bUsed )
+ {
+ m_triangleTable[j++] = m_triangleTable[i];
+ }
+ }
+ m_modFile->SetTriangleUsed(j);
+ CurrentInit();
+}
+
+
+// Change the min / max of all selected triangles.
+
+void CModel::MinMaxChange()
+{
+ int used, i;
+
+ DefaultSelect();
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( !m_triangleTable[i].bSelect ) continue;
+
+ m_triangleTable[i].min = m_min;
+ m_triangleTable[i].max = m_max;
+ }
+}
+
+
+// Initializes the point of view.
+
+void CModel::InitView()
+{
+ m_viewHeight = 5.0f;
+ m_viewDist = 50.0f;
+ m_viewAngleH = 0.0f;
+ m_viewAngleV = 0.0f;
+}
+
+// Initializes the point of view to see the selected triangles.
+
+void CModel::InitViewFromSelect()
+{
+#if 0
+ Math::Vector n;
+ float h,v;
+
+ n = RetSelectNormal();
+
+ m_viewAngleH = Math::RotateAngle(n.x, n.z)+Math::PI;
+ m_viewAngleV = Math::RotateAngle(sqrtf(n.x*n.x+n.z*n.z), n.y)+Math::PI;
+ h = m_viewAngleH;
+ v = m_viewAngleV;
+
+ while ( m_viewAngleV <= -Math::PI )
+ {
+ m_viewAngleV += Math::PI;
+ m_viewAngleH += Math::PI;
+ }
+ while ( m_viewAngleV >= Math::PI )
+ {
+ m_viewAngleV -= Math::PI;
+ m_viewAngleH -= Math::PI;
+ }
+ m_viewAngleV *= 0.75f;
+
+ char s[100];
+ sprintf(s, "angle=%f %f -> %f %f\n", h,v, m_viewAngleH, m_viewAngleV);
+ OutputDebugString(s);
+#endif
+}
+
+// Updates the parameters for the point of view.
+
+void CModel::UpdateView()
+{
+ Math::Vector eye, lookat, vUpVec;
+
+//? lookat = RetSelectCDG();
+ lookat = Math::Vector(0.0f, m_viewHeight, 0.0f);
+ eye = RotateView(lookat, m_viewAngleH, m_viewAngleV, m_viewDist);
+
+ vUpVec = Math::Vector(0.0f, 1.0f, 0.0f);
+ m_engine->SetViewParams(eye, lookat, vUpVec, 10.0f);
+ m_engine->SetRankView(0);
+}
+
+// Moves the point of view.
+
+void CModel::ViewMove(const Event &event, float speed)
+{
+ if ( IsEditFocus() ) return;
+
+ // Up/Down.
+ if ( event.axeY > 0.5f )
+ {
+ if ( event.keyState & KS_CONTROL )
+ {
+ m_viewHeight += event.rTime*10.0f*speed;
+ if ( m_viewHeight > 100.0f ) m_viewHeight = 100.0f;
+ }
+ else
+ {
+ m_viewAngleV -= event.rTime*1.0f*speed;
+ if ( m_viewAngleV < -Math::PI*0.49f ) m_viewAngleV = -Math::PI*0.49f;
+ }
+ }
+ if ( event.axeY < -0.5f )
+ {
+ if ( event.keyState & KS_CONTROL )
+ {
+ m_viewHeight -= event.rTime*10.0f*speed;
+ if ( m_viewHeight < -100.0f ) m_viewHeight = -100.0f;
+ }
+ else
+ {
+ m_viewAngleV += event.rTime*1.0f*speed;
+ if ( m_viewAngleV > Math::PI*0.49f ) m_viewAngleV = Math::PI*0.49f;
+ }
+ }
+
+ // Left/Right.
+ if ( event.axeX < -0.5f )
+ {
+ m_viewAngleH -= event.rTime*1.0f*speed;
+ }
+ if ( event.axeX > 0.5f )
+ {
+ m_viewAngleH += event.rTime*1.0f*speed;
+ }
+
+ // PageUp/PageDown.
+ if ( event.keyState & KS_PAGEUP )
+ {
+ m_viewDist -= event.rTime*30.0f*speed;
+ if ( m_viewDist < 1.0f ) m_viewDist = 1.0f;
+ }
+ if ( event.keyState & KS_PAGEDOWN )
+ {
+ m_viewDist += event.rTime*30.0f*speed;
+ if ( m_viewDist > 300.0f ) m_viewDist = 300.0f;
+ }
+}
+
+
+
+// Updates the text information.
+
+void CModel::UpdateInfoText()
+{
+ char info[100];
+
+ if ( m_mode == 1 )
+ {
+ sprintf(info, "[1] V:color=%d K:state=%d Sel=%d..%d (T=%d)",
+ m_color, m_state,
+ m_triangleSel1, m_triangleSel2,
+ m_triangleSel2-m_triangleSel1+1);
+ m_engine->SetInfoText(0, info);
+
+ sprintf(info, "M:mode=%d Z:rot=%d XY:mir=%d;%d P:part=%d O:name=%s",
+ m_textureMode, m_textureRotate,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ m_texturePart, m_textureName);
+ m_engine->SetInfoText(1, info);
+ }
+
+ if ( m_mode == 2 )
+ {
+ sprintf(info, "[2] Sel=%d..%d (T=%d)",
+ m_triangleSel1, m_triangleSel2,
+ m_triangleSel2-m_triangleSel1+1);
+ m_engine->SetInfoText(0, info);
+
+ sprintf(info, "O:dirty=%d UV:offset=%d;%d XY:mir=%d;%d S:subdiv=%d",
+ m_secondTexNum,
+ m_secondOffsetU, m_secondOffsetV,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ m_secondSubdiv);
+ m_engine->SetInfoText(1, info);
+ }
+
+ if ( m_mode == 3 )
+ {
+ sprintf(info, "[3] LOD Math::Min/max=%d..%d Sel=%d..%d (T=%d)",
+ (int)m_min, (int)m_max,
+ m_triangleSel1, m_triangleSel2,
+ m_triangleSel2-m_triangleSel1+1);
+ m_engine->SetInfoText(0, info);
+
+ sprintf(info, "[Change]");
+ m_engine->SetInfoText(1, info);
+ }
+}
+
+
+
+static int tablePartT[] = // lemt.tga
+{
+ 192, 0, 256, 32, // track profile
+ 0, 64, 128, 128, // wheels for track
+ 0, 0, 128, 64, // profile
+ 90, 0, 128, 28, // pivot trainer
+ 128, 0, 192, 44, // chest front
+ 128, 44, 192, 58, // shell
+ 128, 58, 192, 87, // back chest
+ 128, 87, 192, 128, // back shell
+ 128, 128, 192, 144, // sub back shell
+ 0, 128, 32, 152, // rear fender
+ 0, 152, 32, 182, // fender middle
+ 0, 182, 32, 256, // front fender
+ 32, 128, 112, 176, // wing
+ 224, 48, 232, 64, // thrust tunnel
+ 192, 32, 224, 64, // fire under reactor
+ 224, 32, 256, 48, // foot
+ 192, 64, 256, 128, // sensor
+ 192, 128, 224, 176, // battery holder
+ 192, 216, 248, 248, // cannon board
+ 220, 216, 222, 245, // cannon board
+ 64, 176, 128, 224, // top cannon
+ 128, 152, 192, 160, // external cannon
+ 128, 144, 192, 152, // interior cannon
+ 192, 176, 224, 192, // small cannon
+ 128, 236, 192, 256, // cannon organic
+ 214, 192, 224, 216, // crosshair
+ 224, 128, 248, 152, // articulation
+ 128, 192, 192, 214, // piston board
+ 128, 214, 192, 236, // piston front
+ 192, 192, 214, 214, // piston edge
+ 128, 192, 161, 214, // small piston board
+ 32, 176, 64, 198, // radar piston
+ 128, 160, 160, 192, // wheel
+ 232, 48, 255, 56, // tire profile
+ 240, 152, 248, 216, // vertical hatching
+ 248, 192, 256, 256, // battery
+ 224, 152, 240, 168, // rock
+ 144, 80, 176, 112, // nuclear
+ 140, 76, 180, 116, // large nuclear
+ 144, 80, 152, 88, // yellow nuclear
+ 224, 168, 240, 192, // cap resolution C
+ 224, 192, 240, 210, // back resolution C
+ 32, 224, 96, 235, // arm resolution C
+ 32, 235, 96, 246, // arm resolution C
+ 161, 1, 164, 4, // blank
+ 168, 1, 171, 4, // medium gray
+ 154, 1, 157, 4, // dark gray uniform
+ 147, 1, 150, 4, // blue unifrom
+ 114, 130, 118, 134, // red unifrom
+ 121, 130, 125, 134, // green uniform
+ 114, 137, 118, 141, // yellow uniform
+ 121, 137, 125, 141, // violet uniform
+ -1
+};
+
+static int tablePartR[] = // roller.tga
+{
+ 0, 0, 128, 52, // wheels for track
+ 48, 137, 128, 201, // catalytic radiator
+ 0, 52, 32, 84, // front radiator
+ 32, 52, 43, 84, // back radiator
+ 0, 84, 96, 137, // large catalytic
+ 128, 0, 192, 85, // front
+ 128, 173, 192, 256, // back
+ 192, 0, 256, 42, // over
+ 128, 85, 192, 109, // catalytic pillon
+ 128, 109, 192, 173, // top pillon
+ 192, 85, 240, 109, // catalytic gate pillon
+ 0, 137, 24, 256, // catalytic verrin
+ 24, 137, 48, 256, // catalytic verrin
+ 48, 201, 128, 233, // medium cannon
+ 192, 109, 256, 173, // bottom cannon
+ 192, 173, 240, 205, // cannon 1
+ 192, 173, 240, 177, // cannon 2
+ 43, 52, 75, 84, // front cannon
+ 48, 233, 128, 247, // piston
+ 96, 105, 128, 137, // front phazer
+ 96, 97, 128, 105, // phazer cannon
+ 75, 52, 107, 84, // exhaust pipe
+ 192, 205, 243, 256, // nuclear power plant instruction
+ 192, 42, 256, 85, // reflection glass
+ -1
+};
+
+static int tablePartW[] = // subm.tga
+{
+ 0, 0, 128, 26, // chenilles
+ 0, 26, 22, 114, // portique 1
+ 0, 114, 22, 202, // portique 2
+ 22, 26, 82, 56, // c�t� hublot
+ 22, 56, 82, 86, // c�t� ligne rouge
+ 22, 86, 82, 116, // c�t� simple
+ 22, 116, 82, 146, // avant/arri�re
+ 22, 146, 82, 176, // avant/arri�re + phare
+ 132, 82, 196, 166, // capot trainer
+ 132, 166, 196, 177, // capot trainer
+ 132, 177, 196, 188, // capot trainer
+ 0, 224, 96, 256, // c�t� trainer
+ 30, 224, 48, 256, // arri�re trainer
+ 136, 240, 216, 256, // barri�re courte
+ 96, 240, 256, 256, // barri�re longue
+ 128, 0, 160, 32, // black-box 1
+ 160, 0, 192, 32, // black-box 2
+ 192, 0, 224, 32, // black-box 3
+ 224, 105, 256, 137, // TNT 1
+ 224, 137, 256, 169, // TNT 2
+ 82, 32, 146, 82, // factory r�solution C
+ 146, 32, 210, 82, // factory r�solution C
+ 224, 0, 256, 105, // tower r�solution C
+ 82, 82, 132, 150, // research r�solution C
+ 199, 169, 256, 233, // sac r�solution C
+ 106, 150, 130, 214, // cl� A
+ 82, 150, 106, 214, // cl� B
+ 132, 188, 196, 212, // cl� C
+ 132, 212, 196, 236, // cl� D
+ 210, 32, 224, 46, // gris
+ 56, 176, 82, 224, // sol coffre-fort
+ -1
+};
+
+static int tablePartDr[] = // drawer.tga
+{
+ 128, 0, 134, 6, // bleu
+ 128, 6, 134, 12, // gris fonc�
+ 128, 12, 134, 18, // gris clair
+ 0, 0, 128, 32, // roues chenille
+ 192, 0, 256, 32, // profil chenille
+ 140, 0, 160, 8, // profil phare
+ 160, 0, 192, 32, // face phare
+ 0, 32, 160, 48, // hachure
+ 160, 32, 192, 48, // c�t�
+ 0, 48, 96, 96, // tableau de bord
+ 96, 48, 192, 112, // radiateur
+ 192, 32, 256, 112, // grille lat�rale
+ 192, 112, 256, 128, // capot
+ 0, 96, 8, 160, // chassis
+ 8, 96, 96, 104, // axe chenilles
+ 8, 104, 16, 160, // axe carrousel
+ 16, 128, 24, 160, // flan support
+ 224, 128, 256, 160, // rotule
+ 24, 104, 32, 160, // bocal (18)
+ 32, 104, 40, 160, // bocal
+ 40, 104, 48, 160, // bocal
+ 24, 152, 48, 160, // bocal fond
+ 0, 240, 32, 256, // crayon 1: couleur (22)
+ 0, 160, 32, 192, // crayon 1: dessus
+ 0, 192, 32, 256, // crayon 1: pointe
+ 32, 240, 64, 256, // crayon 2: couleur
+ 32, 160, 64, 192, // crayon 2: dessus
+ 32, 192, 64, 256, // crayon 2: pointe
+ 64, 240, 96, 256, // crayon 3: couleur
+ 64, 160, 96, 192, // crayon 3: dessus
+ 64, 192, 96, 256, // crayon 3: pointe
+ 96, 240, 128, 256, // crayon 4: couleur
+ 96, 160, 128, 192, // crayon 4: dessus
+ 96, 192, 128, 256, // crayon 4: pointe
+ 128, 240, 160, 256, // crayon 5: couleur
+ 128, 160, 160, 192, // crayon 5: dessus
+ 128, 192, 160, 256, // crayon 5: pointe
+ 160, 240, 192, 256, // crayon 6: couleur
+ 160, 160, 192, 192, // crayon 6: dessus
+ 160, 192, 192, 256, // crayon 6: pointe
+ 192, 240, 224, 256, // crayon 7: couleur
+ 192, 160, 224, 192, // crayon 7: dessus
+ 192, 192, 224, 256, // crayon 7: pointe
+ 224, 240, 256, 256, // crayon 8: couleur
+ 224, 160, 256, 192, // crayon 8: dessus
+ 224, 192, 256, 256, // crayon 8: pointe
+ -1
+};
+
+static int tablePartKi[] = // kid.tga
+{
+ 0, 0, 128, 53, // ciseaux
+ 128, 0, 256, 128, // CD
+ 0, 0, 8, 8, // livre 1: fond
+ 8, 0, 16, 8, // livre 2: fond
+ 16, 0, 24, 8, // livre: fond
+ 24, 0, 32, 8, // livre: fond
+ 32, 0, 40, 8, // livre: fond
+ 40, 0, 48, 8, // livre: fond
+ 0, 53, 22, 138, // livre 1: tranche
+ 22, 53, 86, 138, // livre 1: face
+ 0, 138, 22, 224, // livre 2: tranche
+ 22, 138, 86, 224, // livre 2: face
+ 86, 53, 94, 85, // livre: pages
+ 94, 53, 110, 139, // livre: tranche
+ 110, 53, 126, 139, // livre: tranche
+ 86, 139, 102, 225, // livre: tranche
+ 102, 139, 118, 225, // livre: tranche
+ 118, 139, 134, 225, // livre: tranche
+ 64, 0, 72, 8, // fauille: fond
+ 155, 155, 256, 256, // feuille: carreaux
+ 72, 0, 80, 8, // lampe
+ 80, 0, 88, 8, // lampe
+ 80, 8, 88, 16, // ampoule
+ 72, 8, 80, 16, // rayons (23)
+ 86, 85, 94, 139, // lampe
+ 0, 224, 32, 256, // lampe rotule
+ 64, 8, 72, 16, // arrosoir: fond
+ 134, 128, 142, 256, // arrosoir: corps
+ 142, 128, 150, 256, // arrosoir: tuyau
+ 128, 225, 134, 256, // arrosoir: int�rieur
+ 32, 224, 64, 256, // arrosoir: ponneau
+ 56, 8, 64, 16, // skate: roues (31)
+ 48, 8, 56, 16, // skate: axes
+ 40, 8, 48, 16, // skate: grip
+ 32, 8, 40, 16, // skate: tranche
+ 24, 8, 32, 16, // skate: dessous
+ 150, 128, 200, 256, // skate: motif 1
+ 200, 128, 250, 256, // skate: motif 2
+ 64, 224, 96, 256, // skate: roue (38)
+ 96, 225, 104, 256, // skate: amortisseur
+ -1
+};
+
+static int tablePartKi2[] = // kid2.tga
+{
+ 2, 2, 62, 62, // coca: dessus
+ 0, 64, 8, 192, // coca: flan
+ 8, 64, 96, 192, // coca: logo
+ 128, 0, 256, 85, // carton
+ 128, 85, 256, 91, // carton tranche
+ 128, 128, 256, 256, // roue
+ 192, 96, 256, 128, // pneu
+ 184, 96, 192, 128, // jante
+ 128, 96, 160, 128, // int�rieur
+ 160, 96, 168, 104, // porte bois
+ 160, 104, 168, 112, // porte m�tal
+ 160, 112, 184, 128, // vitre
+ 96, 0, 128, 256, // bouteille: corps (12)
+ 64, 0, 96, 32, // bouteille: bouchon
+ 168, 96, 176, 104, // bouteille: vert
+ 0, 192, 96, 224, // bois clair
+ 0, 224, 96, 256, // bois fonc�
+ 64, 32, 96, 64, // bateau
+ 168, 104, 176, 112, // ballon (18)
+ 176, 104, 184, 112, // ballon
+ 176, 96, 184, 104, // int�rieur caisse
+ -1
+};
+
+static int tablePartKi3[] = // kid3.tga
+{
+ 0, 0, 32, 28, // �crou: flan
+ 0, 28, 32, 44, // �crou: profil
+ 0, 44, 32, 60, // �crou: pas de vis
+ 0, 60, 32, 64, // tuyau
+ 0, 64, 32, 68, // tuyau
+ 0, 68, 8, 76, // tuyau
+ 0, 76, 32, 108, // plastic
+ 8, 68, 16, 76, // saut: gris clair (7)
+ 16, 68, 24, 76, // saut: gris fonc�
+ 24, 68, 32, 76, // saut: gris bois
+ 0, 108, 32, 140, // saut: rotule
+ 0, 140, 32, 144, // saut: axe
+ 128, 0, 256, 128, // saut: flan
+ 0, 144, 8, 152, // basket: gris fonc� (13)
+ 8, 144, 16, 152, // basket: gris clair
+ 16, 144, 24, 152, // basket: gris lacets
+ 24, 144, 32, 152, // basket: gris semelle
+ 0, 152, 8, 181, // basket: int�rieur
+ 0, 181, 192, 256, // basket: c�t�
+ 192, 181, 226, 256, // basket: arri�re
+ 32, 135, 96, 181, // basket: dessus (20)
+ 96, 168, 128, 181, // basket: avant
+ 8, 152, 16, 160, // chaise: plastique
+ 16, 152, 24, 160, // chaise: m�tal
+ 32, 0, 64, 32, // chaise: roue
+ 8, 177, 24, 181, // chaise: roue
+ 226, 181, 234, 256, // chaise: piston (26)
+ 64, 96, 128, 128, // chaise: relief
+ 96, 135, 128, 167, // chaise: dessous
+ 32, 128, 250, 135, // paille 1
+ 38, 128, 256, 135, // paille 2
+ 234, 181, 242, 256, // allumette
+ 8, 160, 16, 168, // allumette (dessus)
+ 128, 135, 224, 181, // panneau
+ 242, 135, 256, 256, // poteau (34)
+ 24, 152, 32, 160, // clou
+ 16, 160, 24, 168, // tuyau m�talique
+ 112, 181, 192, 185, // tuyau int�rieur
+ 32, 32, 48, 80, // pas de vis
+ 24, 160, 32, 168, // ventillateur: plastique (39)
+ 40, 80, 56, 96, // ventillateur: plastique d�grad�
+ 8, 168, 16, 176, // ventillateur: m�tal
+ 32, 80, 40, 112, // ventillateur: socle 1
+ 64, 0, 96, 16, // ventillateur: socle 2
+ 48, 32, 56, 80, // ventillateur: socle 3
+ 64, 16, 96, 32, // ventillateur: moteur flan
+ 96, 0, 128, 32, // ventillateur: moteur face
+ 102, 6, 122, 26, // ventillateur: socle dessus
+ 16, 168, 24, 176, // pot: uni (48)
+ 56, 32, 64, 64, // pot: haut
+ 56, 64, 64, 96, // pot: bas
+ 64, 32, 128, 96, // pot: terre
+ -1
+};
+
+static int tablePartF[] = // factory.tga
+{
+ 0, 0, 152, 152, // plancher octogonal fabrique
+ 50, 50, 102, 102, // dessus pile
+ 0, 152, 128, 252, // avant
+ 128, 152, 256, 252, // arri�re
+ 152, 28, 225, 128, // c�t�
+ 152, 28, 176, 128, // c�t� partiel
+ 152, 0, 216, 16, // hachures
+ 236, 0, 256, 40, // axe
+ 152, 128, 224, 152, // support cible
+ -1
+};
+
+static int tablePartD[] = // derrick.tga
+{
+ 0, 0, 64, 32, // grand c�t�
+ 64, 0, 96, 24, // petit c�t�
+ 96, 0, 136, 24, // attention
+ 0, 32, 8, 160, // tube 1
+ 8, 32, 16, 96, // tube 2
+ 16, 32, 24, 160, // pilier
+ 24, 32, 32, 160, // tige foret
+ 32, 32, 40, 160, // tige destructeur
+ 8, 96, 16, 128, // foret
+ 136, 0, 256, 120, // plancher octogonal station de recharge
+ 40, 32, 64, 56, // cube m�tal
+ 64, 24, 128, 48, // c�t� tour haut
+ 64, 48, 128, 229, // c�t� tour bas
+ 136, 120, 256, 240, // int�rieur usine
+ 0, 160, 64, 224, // to�t usine
+ -1
+};
+
+static int tablePartC[] = // convert.tga
+{
+ 0, 0, 120, 120, // plancher octogonal convertisseur
+ 0, 120, 128, 176, // grand c�t�
+ 128, 120, 192, 176, // petit c�t�
+ 192, 120, 256, 184, // couvercle convertisseur
+ 120, 0, 216, 64, // face trianble
+ 216, 0, 248, 64, // c�t� triangle
+ 120, 64, 160, 84, // axe
+ 0, 141, 128, 176, // recherche: base
+ 0, 176, 128, 214, // recherche: haut
+ 0, 214, 128, 252, // recherche: haut (!)
+ 174, 64, 190, 120, // recherche: montant
+ 190, 64, 206, 120, // recherche: montant
+ 206, 64, 254, 85, // radar
+ 192, 168, 256, 232, // hachures carr�es
+ 248, 0, 256, 64, // c�ne fabrique de piles
+ 128, 176, 192, 240, // dessus centrale nucl�aire
+ 120, 85, 174, 120, // technicien, visage
+ 206, 106, 256, 120, // technicien, casquette
+ 160, 64, 174, 78, // technicien, visi�re
+ -1
+};
+
+static int tablePartS[] = // search.tga
+{
+ 0, 0, 128, 128, // usine 1
+ 128, 0, 256, 128, // usine 2
+ 0, 128, 128, 256, // pile
+ 128, 128, 228, 240, // support pile
+ 228, 128, 256, 184, // antenne
+ 128, 128, 192, 160, // contr�le 1
+ 128, 160, 192, 192, // contr�le 2
+ 128, 192, 192, 224, // contr�le 3
+ 128, 224, 192, 256, // contr�le 4
+ -1
+};
+
+static int tablePartP[] = // plant.tga
+{
+ 0, 160, 48, 256, // feuille 1
+ 0, 0, 94, 100, // feuille 2
+ 48, 156, 108, 256, // feuille 3
+ 94, 0, 104, 100, // tige 1
+ 185, 0, 195, 100, // tige 2
+ 108, 100, 182, 256, // foug�re
+ 104, 0, 144, 100, // courge
+ 203, 0, 256, 83, // armature derrick r�solution C
+ -1
+};
+
+static int tablePartV[] = // vegetal.tga
+{
+ 0, 0, 94, 100, // racine
+ 186, 0, 256, 256, // tronc
+ 162, 0, 168, 128, // mat drapeau bleu
+ 168, 0, 174, 128, // mat drapeau rouge
+ 174, 0, 180, 128, // mat drapeau vert
+ 180, 0, 186, 128, // mat drapeau jaune
+ 180, 128, 186, 256, // mat drapeau violet
+ 94, 0, 107, 32, // drapeau bleu
+ 107, 0, 120, 32, // drapeau rouge
+ 120, 0, 133, 32, // drapeau vert
+ 133, 0, 146, 32, // drapeau jaune
+ 146, 0, 159, 32, // drapeau violet
+ 94, 64, 126, 96, // verre 1
+ 126, 64, 158, 86, // verre 2
+ 128, 128, 180, 144, // verre 3a
+ 128, 144, 180, 160, // verre 3b
+ 128, 94, 162, 128, // verre 4
+ 0, 100, 32, 228, // champignon 1
+ 32, 100, 48, 228, // champignon 1
+ 48, 100, 112, 228, // champignon 2
+ 112, 100, 128, 228, // champignon 2
+ 128, 160, 180, 212, // tronc (21)
+ -1
+};
+
+static int tablePartM[] = // mother.tga
+{
+ 0, 0, 128, 128, // corps arri�re
+ 128, 0, 192, 128, // corps avant
+ 0, 128, 64, 192, // t�te
+ 64, 128, 192, 160, // pince ext.
+ 64, 160, 192, 192, // pince int.
+ 0, 192, 64, 256, // mire
+ -1
+};
+
+static int tablePartA[] = // ant.tga
+{
+ 0, 0, 64, 64, // queue
+ 0, 96, 128, 160, // queue abeille
+ 64, 0, 128, 64, // corps
+ 128, 0, 192, 64, // t�te
+ 0, 64, 64, 72, // patte
+ 0, 72, 64, 80, // antenne
+ 64, 64, 150, 96, // queue ver
+ 150, 64, 182, 96, // corps ver
+ 182, 64, 256, 96, // t�te ver
+ 224, 32, 256, 64, // articulation ver
+ 128, 96, 220, 160, // aile
+ 0, 80, 16, 96, // oeil
+ 200, 0, 208, 8, // vert clair
+ 200, 8, 208, 16, // vert fonc�
+ 0, 160, 64, 224, // corps araign�e
+ 64, 160, 128, 192, // t�te araign�e
+ 208, 0, 216, 64, // patte araign�e
+ 216, 0, 224, 32, // patte araign�e
+ 224, 0, 256, 8, // antenne araign�e
+ 192, 0, 200, 8, // brun clair
+ 192, 8, 200, 16, // brun fonc�
+ 128, 160, 256, 256, // SatCom
+ -1
+};
+
+static int tablePartH[] = // human.tga
+{
+ 0, 0, 64, 64, // vissi�re
+ 64, 0, 96, 64, // cuisse
+ 96, 0, 128, 64, // jambe
+ 128, 0, 192, 32, // bras
+ 128, 32, 192, 64, // avant-bras
+ 0, 64, 128, 224, // ventre
+ 128, 64, 256, 224, // dos
+ 64, 224, 112, 256, // dessus pied
+ 144, 224, 168, 240, // dessous pied
+ 112, 224, 144, 240, // c�t� pied
+ 112, 224, 128, 240, // c�t� pied
+ 0, 224, 64, 256, // gant
+ 168, 224, 200, 256, // oreille
+ 112, 240, 144, 256, // ligne casque
+ 200, 224, 208, 256, // int�rieur coup
+ 240, 0, 244, 64, // bombone orange
+ 244, 0, 248, 64, // bombone orange (reflet)
+ 248, 0, 252, 64, // bombone bleu
+ 252, 0, 256, 64, // bombone bleu (reflet)
+ 144, 240, 156, 256, // gris habit
+ 156, 240, 168, 256, // gris articulation
+//? 208, 224, 256, 256, // SatCom
+ 192, 0, 240, 64, // quartz
+ -1
+};
+
+static int tablePartG[] = // apollo.tga
+{
+ 0, 0, 64, 64, // rev�tement LEM
+ 64, 0, 128, 64, // rev�tement LEM
+ 128, 8, 136, 128, // pied
+ 0, 64, 64, 128, // roue
+ 136, 24, 152, 44, // profil pneu
+ 136, 8, 160, 24, // garde boue
+ 64, 64, 128, 128, // si�ge
+ 64, 128, 128, 192, // si�ge
+ 64, 192, 128, 212, // si�ge
+ 128, 128, 240, 192, // moteur
+ 0, 192, 28, 256, // moteur
+ 32, 128, 60, 256, // moteur
+ 224, 0, 256, 128, // avant
+ 206, 0, 224, 128, // avant
+ 136, 44, 168, 62, // avant
+ 64, 212, 108, 256, // panneau de commande
+ 198, 0, 206, 128, // mat
+ 190, 64, 198, 128, // mat
+ 160, 8, 176, 24, // cam�ra
+ 176, 8, 192, 24, // moyeu
+ 136, 64, 168, 96, // module
+ 168, 64, 190, 96, // module
+ 136, 96, 168, 128, // module
+ 128, 192, 230, 252, // drapeau
+ 0, 128, 32, 192, // antenne
+ 128, 0, 136, 8, // jaune
+ 136, 0, 144, 8, // beige
+ 144, 0, 152, 8, // brun
+ 168, 0, 176, 8, // gris tr�s clair
+ 152, 0, 160, 8, // gris clair
+ 160, 0, 168, 8, // gris fonc�
+ -1
+};
+
+static int tablePartB[] = // base1.tga
+{
+ 0, 0, 80, 256, // int�rieur porte
+ 80, 0, 88, 256, // tranche porte
+ 116, 0, 180, 64, // coiffe 1
+ 116, 64, 180, 102, // coiffe 2
+ 180, 0, 244, 37, // base
+ 180, 37, 196, 101, // support
+ 88, 0, 116, 256, // colonne
+ 212, 37, 256, 128, // suppl�ment
+ 128, 128, 256, 256, // 1/4 du sol
+ 196, 37, 212, 53, // gris fonc�
+ 196, 53, 212, 69, // gris clair
+ -1
+};
+
+static int tablePartCe[] = // cellar01.tga
+{
+ 0, 128, 64, 192, // briques
+ 64, 128, 128, 192, // briques
+ 128, 128, 192, 192, // briques
+ 192, 128, 256, 192, // briques
+ -1
+};
+
+static int tablePartFa[] = // face01.tga
+{
+ 0, 0, 256, 256, // visage
+ -1
+};
+
+// Retourne le pointeur la table.
+
+int* CModel::RetTextureTable()
+{
+ if ( m_textureRank == 0 ) return tablePartT;
+ if ( m_textureRank == 1 ) return tablePartR;
+ if ( m_textureRank == 2 ) return tablePartW;
+ if ( m_textureRank == 3 ) return tablePartDr;
+ if ( m_textureRank == 4 ) return tablePartKi;
+ if ( m_textureRank == 5 ) return tablePartKi2;
+ if ( m_textureRank == 6 ) return tablePartKi3;
+ if ( m_textureRank == 7 ) return tablePartF;
+ if ( m_textureRank == 8 ) return tablePartD;
+ if ( m_textureRank == 9 ) return tablePartC;
+ if ( m_textureRank == 10 ) return tablePartS;
+ if ( m_textureRank == 11 ) return tablePartP;
+ if ( m_textureRank == 12 ) return tablePartV;
+ if ( m_textureRank == 13 ) return tablePartM;
+ if ( m_textureRank == 14 ) return tablePartA;
+ if ( m_textureRank == 15 ) return tablePartH;
+ if ( m_textureRank == 16 ) return tablePartG;
+ if ( m_textureRank == 17 ) return tablePartB;
+ if ( m_textureRank == 18 ) return tablePartCe;
+ if ( m_textureRank == 19 ) return tablePartFa;
+ if ( m_textureRank == 20 ) return tablePartFa;
+ if ( m_textureRank == 21 ) return tablePartFa;
+ if ( m_textureRank == 22 ) return tablePartFa;
+ return 0;
+}
+
+// Updates the part of texture.
+
+void CModel::TexturePartUpdate()
+{
+ int *table;
+
+ table = RetTextureTable();
+ if ( table == 0 ) return;
+
+ m_textureInf.x = (table[m_texturePart*4+0]+0.5f)/256.0f;
+ m_textureInf.y = (table[m_texturePart*4+1]+0.5f)/256.0f;
+ m_textureSup.x = (table[m_texturePart*4+2]-0.5f)/256.0f;
+ m_textureSup.y = (table[m_texturePart*4+3]-0.5f)/256.0f;
+
+ PutTextureValues();
+}
+
+// Changes the texture.
+
+void CModel::TextureRankChange(int step)
+{
+ m_textureRank += step;
+
+ if ( m_textureRank >= MAX_NAMES ) m_textureRank = 0;
+ if ( m_textureRank < 0 ) m_textureRank = MAX_NAMES-1;
+
+ if ( m_textureRank == 0 ) strcpy(m_textureName, "lemt.tga");
+ if ( m_textureRank == 1 ) strcpy(m_textureName, "roller.tga");
+ if ( m_textureRank == 2 ) strcpy(m_textureName, "subm.tga");
+ if ( m_textureRank == 3 ) strcpy(m_textureName, "drawer.tga");
+ if ( m_textureRank == 4 ) strcpy(m_textureName, "kid.tga");
+ if ( m_textureRank == 5 ) strcpy(m_textureName, "kid2.tga");
+ if ( m_textureRank == 6 ) strcpy(m_textureName, "kid3.tga");
+ if ( m_textureRank == 7 ) strcpy(m_textureName, "factory.tga");
+ if ( m_textureRank == 8 ) strcpy(m_textureName, "derrick.tga");
+ if ( m_textureRank == 9 ) strcpy(m_textureName, "convert.tga");
+ if ( m_textureRank == 10 ) strcpy(m_textureName, "search.tga");
+ if ( m_textureRank == 11 ) strcpy(m_textureName, "plant.tga");
+ if ( m_textureRank == 12 ) strcpy(m_textureName, "vegetal.tga");
+ if ( m_textureRank == 13 ) strcpy(m_textureName, "mother.tga");
+ if ( m_textureRank == 14 ) strcpy(m_textureName, "ant.tga");
+ if ( m_textureRank == 15 ) strcpy(m_textureName, "human.tga");
+ if ( m_textureRank == 16 ) strcpy(m_textureName, "apollo.tga");
+ if ( m_textureRank == 17 ) strcpy(m_textureName, "base1.tga");
+ if ( m_textureRank == 18 ) strcpy(m_textureName, "cellar01.tga");
+ if ( m_textureRank == 19 ) strcpy(m_textureName, "face01.tga");
+ if ( m_textureRank == 20 ) strcpy(m_textureName, "face02.tga");
+ if ( m_textureRank == 21 ) strcpy(m_textureName, "face03.tga");
+ if ( m_textureRank == 22 ) strcpy(m_textureName, "face04.tga");
+
+ m_texturePart = 0;
+}
+
+// Changes the part of texture.
+
+void CModel::TexturePartChange(int step)
+{
+ int *table;
+
+ table = RetTextureTable();
+ if ( table == 0 ) return;
+
+ m_texturePart ++;
+
+ if ( table[m_texturePart*4] == -1 )
+ {
+ m_texturePart = 0;
+ }
+
+ TexturePartUpdate();
+}
+
+
diff --git a/src/old/model.h b/src/old/model.h
index 9acfbbc..275807b 100644
--- a/src/old/model.h
+++ b/src/old/model.h
@@ -1,136 +1,136 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// model.h
-
-#pragma once
-
-
-#include "common/event.h"
-#include "old/modfile.h"
-#include "math/point.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CModFile;
-class CInterface;
-
-
-
-class CModel
-{
-public:
- CModel(CInstanceManager* iMan);
- ~CModel();
-
- void StartUserAction();
- void StopUserAction();
-
- bool EventProcess(const Event &event);
-
- void InitView();
- void InitViewFromSelect();
- void UpdateView();
- void ViewMove(const Event &event, float speed);
-
-protected:
- bool EventFrame(const Event &event);
- bool GetVertex(int rank, D3DVERTEX2 &vertex);
- bool SetVertex(int rank, D3DVERTEX2 &vertex);
- Math::Vector RetSelectCDG();
- Math::Vector RetSelectNormal();
- void SmoothSelect();
- void PlaneSelect();
- void ColorSelect();
- void StateSelect();
- void MoveSelect(Math::Vector move);
- void OperSelect(Math::Vector move, char oper);
- void ReadScript(char *filename);
- void BBoxCompute(Math::Vector &min, Math::Vector &max);
- bool IsMappingSelectPlausible(D3DMaping D3Dmode);
- void MappingSelect(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
- void MappingSelectSpherical(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
- Math::Vector RetMappingCenter(Math::Vector pos, Math::Vector min);
- void MappingSelectCylindrical(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
- void MappingSelectFace(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
- void MappingSelect2(int texNum2, int subdiv, int offsetU, int offsetV, bool bMirrorX, bool bMirrorY);
- void MappingSelectPlane2(int mode, bool bMirrorX, bool bMirrorY);
- void MappingSelectSpherical2(bool bMirrorX, bool bMirrorY);
- void MappingSelectMagic2(bool bMirrorX, bool bMirrorY);
- int SearchNext(int rank, int step);
- int SearchSamePlane(int first, int step);
- void CurrentSearchNext(int step, bool bControl);
- void CurrentInit();
- void CurrentSelect(bool bSelect);
- void DeselectAll();
- void SelectAll();
- void SelectZone(int first, int last);
- void SelectTerm();
- void DefaultSelect();
- void SelectDelete();
- void Compress();
- void MinMaxSelect();
- void MinMaxChange();
- void UpdateInfoText();
- int* RetTextureTable();
- void TexturePartUpdate();
- void TextureRankChange(int step);
- void TexturePartChange(int step);
- void PutTextureValues();
- void GetTextureValues();
- void GetModelName(char *buffer);
- void GetDXFName(char *buffer);
- void GetScriptName(char *buffer);
- bool IsEditFocus();
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CModFile* m_modFile;
- CInterface* m_interface;
-
- float m_time;
- ModelTriangle* m_triangleTable;
- int m_triangleSel1;
- int m_triangleSel2;
- int m_mode;
- int m_textureMode;
- int m_textureRotate;
- bool m_bTextureMirrorX;
- bool m_bTextureMirrorY;
- Math::Point m_textureInf;
- Math::Point m_textureSup;
- int m_texturePart;
- int m_textureRank;
- char m_textureName[20];
- bool m_bDisplayTransparent;
- bool m_bDisplayOnlySelection;
- float m_viewHeight;
- float m_viewDist;
- float m_viewAngleH;
- float m_viewAngleV;
- int m_color;
- int m_state;
- int m_secondTexNum;
- int m_secondSubdiv;
- int m_secondOffsetU;
- int m_secondOffsetV;
- char m_oper;
- float m_min;
- float m_max;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// model.h
+
+#pragma once
+
+
+#include "common/event.h"
+#include "old/modfile.h"
+#include "math/point.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CModFile;
+class CInterface;
+
+
+
+class CModel
+{
+public:
+ CModel(CInstanceManager* iMan);
+ ~CModel();
+
+ void StartUserAction();
+ void StopUserAction();
+
+ bool EventProcess(const Event &event);
+
+ void InitView();
+ void InitViewFromSelect();
+ void UpdateView();
+ void ViewMove(const Event &event, float speed);
+
+protected:
+ bool EventFrame(const Event &event);
+ bool GetVertex(int rank, D3DVERTEX2 &vertex);
+ bool SetVertex(int rank, D3DVERTEX2 &vertex);
+ Math::Vector RetSelectCDG();
+ Math::Vector RetSelectNormal();
+ void SmoothSelect();
+ void PlaneSelect();
+ void ColorSelect();
+ void StateSelect();
+ void MoveSelect(Math::Vector move);
+ void OperSelect(Math::Vector move, char oper);
+ void ReadScript(char *filename);
+ void BBoxCompute(Math::Vector &min, Math::Vector &max);
+ bool IsMappingSelectPlausible(D3DMaping D3Dmode);
+ void MappingSelect(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
+ void MappingSelectSpherical(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
+ Math::Vector RetMappingCenter(Math::Vector pos, Math::Vector min);
+ void MappingSelectCylindrical(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
+ void MappingSelectFace(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
+ void MappingSelect2(int texNum2, int subdiv, int offsetU, int offsetV, bool bMirrorX, bool bMirrorY);
+ void MappingSelectPlane2(int mode, bool bMirrorX, bool bMirrorY);
+ void MappingSelectSpherical2(bool bMirrorX, bool bMirrorY);
+ void MappingSelectMagic2(bool bMirrorX, bool bMirrorY);
+ int SearchNext(int rank, int step);
+ int SearchSamePlane(int first, int step);
+ void CurrentSearchNext(int step, bool bControl);
+ void CurrentInit();
+ void CurrentSelect(bool bSelect);
+ void DeselectAll();
+ void SelectAll();
+ void SelectZone(int first, int last);
+ void SelectTerm();
+ void DefaultSelect();
+ void SelectDelete();
+ void Compress();
+ void MinMaxSelect();
+ void MinMaxChange();
+ void UpdateInfoText();
+ int* RetTextureTable();
+ void TexturePartUpdate();
+ void TextureRankChange(int step);
+ void TexturePartChange(int step);
+ void PutTextureValues();
+ void GetTextureValues();
+ void GetModelName(char *buffer);
+ void GetDXFName(char *buffer);
+ void GetScriptName(char *buffer);
+ bool IsEditFocus();
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CModFile* m_modFile;
+ CInterface* m_interface;
+
+ float m_time;
+ ModelTriangle* m_triangleTable;
+ int m_triangleSel1;
+ int m_triangleSel2;
+ int m_mode;
+ int m_textureMode;
+ int m_textureRotate;
+ bool m_bTextureMirrorX;
+ bool m_bTextureMirrorY;
+ Math::Point m_textureInf;
+ Math::Point m_textureSup;
+ int m_texturePart;
+ int m_textureRank;
+ char m_textureName[20];
+ bool m_bDisplayTransparent;
+ bool m_bDisplayOnlySelection;
+ float m_viewHeight;
+ float m_viewDist;
+ float m_viewAngleH;
+ float m_viewAngleV;
+ int m_color;
+ int m_state;
+ int m_secondTexNum;
+ int m_secondSubdiv;
+ int m_secondOffsetU;
+ int m_secondOffsetV;
+ char m_oper;
+ float m_min;
+ float m_max;
+};
+
diff --git a/src/old/modfile.cpp b/src/old/modfile.cpp
index fa0b0be..705885a 100644
--- a/src/old/modfile.cpp
+++ b/src/old/modfile.cpp
@@ -42,20 +42,20 @@ const int MAX_VERTICES = 2000;
CModFile::CModFile(CInstanceManager* iMan)
{
- m_iMan = iMan;
+ m_iMan = iMan;
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_triangleUsed = 0;
- m_triangleTable = (ModelTriangle*)malloc(sizeof(ModelTriangle)*MAX_VERTICES);
- ZeroMemory(m_triangleTable, sizeof(ModelTriangle)*MAX_VERTICES);
+ m_triangleUsed = 0;
+ m_triangleTable = (ModelTriangle*)malloc(sizeof(ModelTriangle)*MAX_VERTICES);
+ ZeroMemory(m_triangleTable, sizeof(ModelTriangle)*MAX_VERTICES);
}
// Object's destructor.
CModFile::~CModFile()
{
- free(m_triangleTable);
+ free(m_triangleTable);
}
@@ -64,190 +64,190 @@ CModFile::~CModFile()
// Creates a triangle in the internal structure.
bool CModFile::CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3,
- float min, float max)
+ float min, float max)
{
- Math::Vector n;
- int i;
+ Math::Vector n;
+ int i;
- if ( m_triangleUsed >= MAX_VERTICES )
- {
- OutputDebugString("ERROR: CreateTriangle::Too many triangles\n");
- return false;
- }
+ if ( m_triangleUsed >= MAX_VERTICES )
+ {
+ OutputDebugString("ERROR: CreateTriangle::Too many triangles\n");
+ return false;
+ }
- i = m_triangleUsed++;
+ i = m_triangleUsed++;
- ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
+ ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
- m_triangleTable[i].bUsed = true;
- m_triangleTable[i].bSelect = false;
+ m_triangleTable[i].bUsed = true;
+ m_triangleTable[i].bSelect = false;
- n = Math::NormalToPlane(p3, p2, p1);
- m_triangleTable[i].p1 = D3DVERTEX2( p1, n);
- m_triangleTable[i].p2 = D3DVERTEX2( p2, n);
- m_triangleTable[i].p3 = D3DVERTEX2( p3, n);
+ n = Math::NormalToPlane(p3, p2, p1);
+ m_triangleTable[i].p1 = D3DVERTEX2( p1, n);
+ m_triangleTable[i].p2 = D3DVERTEX2( p2, n);
+ m_triangleTable[i].p3 = D3DVERTEX2( p3, n);
- m_triangleTable[i].material.diffuse.r = 1.0f;
- m_triangleTable[i].material.diffuse.g = 1.0f;
- m_triangleTable[i].material.diffuse.b = 1.0f; // white
- m_triangleTable[i].material.ambient.r = 0.5f;
- m_triangleTable[i].material.ambient.g = 0.5f;
- m_triangleTable[i].material.ambient.b = 0.5f;
+ m_triangleTable[i].material.diffuse.r = 1.0f;
+ m_triangleTable[i].material.diffuse.g = 1.0f;
+ m_triangleTable[i].material.diffuse.b = 1.0f; // white
+ m_triangleTable[i].material.ambient.r = 0.5f;
+ m_triangleTable[i].material.ambient.g = 0.5f;
+ m_triangleTable[i].material.ambient.b = 0.5f;
- m_triangleTable[i].min = min;
- m_triangleTable[i].max = max;
+ m_triangleTable[i].min = min;
+ m_triangleTable[i].max = max;
- return true;
+ return true;
}
// Reads a DXF file.
bool CModFile::ReadDXF(char *filename, float min, float max)
{
- FILE* file = NULL;
- char line[100];
- int command, rankSommet, nbSommet, nbFace;
- Math::Vector table[MAX_VERTICES];
- bool bWaitNbSommet;
- bool bWaitNbFace;
- bool bWaitSommetX;
- bool bWaitSommetY;
- bool bWaitSommetZ;
- bool bWaitFaceX;
- bool bWaitFaceY;
- bool bWaitFaceZ;
- float x,y,z;
- int p1,p2,p3;
-
- file = fopen(filename, "r");
- if ( file == NULL ) return false;
-
- m_triangleUsed = 0;
-
- rankSommet = 0;
- bWaitNbSommet = false;
- bWaitNbFace = false;
- bWaitSommetX = false;
- bWaitSommetY = false;
- bWaitSommetZ = false;
- bWaitFaceX = false;
- bWaitFaceY = false;
- bWaitFaceZ = false;
-
- while ( fgets(line, 100, file) != NULL )
- {
- sscanf(line, "%d", &command);
- if ( fgets(line, 100, file) == NULL ) break;
-
- if ( command == 66 )
- {
- bWaitNbSommet = true;
- }
-
- if ( command == 71 && bWaitNbSommet )
- {
- bWaitNbSommet = false;
- sscanf(line, "%d", &nbSommet);
- if ( nbSommet > MAX_VERTICES ) nbSommet = MAX_VERTICES;
- rankSommet = 0;
- bWaitNbFace = true;
-
-//? sprintf(s, "Waiting for %d sommets\n", nbSommet);
-//? OutputDebugString(s);
- }
-
- if ( command == 72 && bWaitNbFace )
- {
- bWaitNbFace = false;
- sscanf(line, "%d", &nbFace);
- bWaitSommetX = true;
-
-//? sprintf(s, "Waiting for %d faces\n", nbFace);
-//? OutputDebugString(s);
- }
-
- if ( command == 10 && bWaitSommetX )
- {
- bWaitSommetX = false;
- sscanf(line, "%f", &x);
- bWaitSommetY = true;
- }
-
- if ( command == 20 && bWaitSommetY )
- {
- bWaitSommetY = false;
- sscanf(line, "%f", &y);
- bWaitSommetZ = true;
- }
-
- if ( command == 30 && bWaitSommetZ )
- {
- bWaitSommetZ = false;
- sscanf(line, "%f", &z);
-
- nbSommet --;
- if ( nbSommet >= 0 )
- {
- Math::Vector p(x,z,y); // permutation of Y and Z!
- table[rankSommet++] = p;
- bWaitSommetX = true;
-
-//? sprintf(s, "Sommet[%d]=%f;%f;%f\n", rankSommet, p.x,p.y,p.z);
-//? OutputDebugString(s);
- }
- else
- {
- bWaitFaceX = true;
- }
- }
-
- if ( command == 71 && bWaitFaceX )
- {
- bWaitFaceX = false;
- sscanf(line, "%d", &p1);
- if ( p1 < 0 ) p1 = -p1;
- bWaitFaceY = true;
- }
-
- if ( command == 72 && bWaitFaceY )
- {
- bWaitFaceY = false;
- sscanf(line, "%d", &p2);
- if ( p2 < 0 ) p2 = -p2;
- bWaitFaceZ = true;
- }
-
- if ( command == 73 && bWaitFaceZ )
- {
- bWaitFaceZ = false;
- sscanf(line, "%d", &p3);
- if ( p3 < 0 ) p3 = -p3;
-
- nbFace --;
- if ( nbFace >= 0 )
- {
- CreateTriangle( table[p3-1], table[p2-1], table[p1-1], min,max );
- bWaitFaceX = true;
-
-//? sprintf(s, "Face=%d;%d;%d\n", p1,p2,p3);
-//? OutputDebugString(s);
- }
- }
-
- }
-
- fclose(file);
- return true;
+ FILE* file = NULL;
+ char line[100];
+ int command, rankSommet, nbSommet, nbFace;
+ Math::Vector table[MAX_VERTICES];
+ bool bWaitNbSommet;
+ bool bWaitNbFace;
+ bool bWaitSommetX;
+ bool bWaitSommetY;
+ bool bWaitSommetZ;
+ bool bWaitFaceX;
+ bool bWaitFaceY;
+ bool bWaitFaceZ;
+ float x,y,z;
+ int p1,p2,p3;
+
+ file = fopen(filename, "r");
+ if ( file == NULL ) return false;
+
+ m_triangleUsed = 0;
+
+ rankSommet = 0;
+ bWaitNbSommet = false;
+ bWaitNbFace = false;
+ bWaitSommetX = false;
+ bWaitSommetY = false;
+ bWaitSommetZ = false;
+ bWaitFaceX = false;
+ bWaitFaceY = false;
+ bWaitFaceZ = false;
+
+ while ( fgets(line, 100, file) != NULL )
+ {
+ sscanf(line, "%d", &command);
+ if ( fgets(line, 100, file) == NULL ) break;
+
+ if ( command == 66 )
+ {
+ bWaitNbSommet = true;
+ }
+
+ if ( command == 71 && bWaitNbSommet )
+ {
+ bWaitNbSommet = false;
+ sscanf(line, "%d", &nbSommet);
+ if ( nbSommet > MAX_VERTICES ) nbSommet = MAX_VERTICES;
+ rankSommet = 0;
+ bWaitNbFace = true;
+
+//? sprintf(s, "Waiting for %d sommets\n", nbSommet);
+//? OutputDebugString(s);
+ }
+
+ if ( command == 72 && bWaitNbFace )
+ {
+ bWaitNbFace = false;
+ sscanf(line, "%d", &nbFace);
+ bWaitSommetX = true;
+
+//? sprintf(s, "Waiting for %d faces\n", nbFace);
+//? OutputDebugString(s);
+ }
+
+ if ( command == 10 && bWaitSommetX )
+ {
+ bWaitSommetX = false;
+ sscanf(line, "%f", &x);
+ bWaitSommetY = true;
+ }
+
+ if ( command == 20 && bWaitSommetY )
+ {
+ bWaitSommetY = false;
+ sscanf(line, "%f", &y);
+ bWaitSommetZ = true;
+ }
+
+ if ( command == 30 && bWaitSommetZ )
+ {
+ bWaitSommetZ = false;
+ sscanf(line, "%f", &z);
+
+ nbSommet --;
+ if ( nbSommet >= 0 )
+ {
+ Math::Vector p(x,z,y); // permutation of Y and Z!
+ table[rankSommet++] = p;
+ bWaitSommetX = true;
+
+//? sprintf(s, "Sommet[%d]=%f;%f;%f\n", rankSommet, p.x,p.y,p.z);
+//? OutputDebugString(s);
+ }
+ else
+ {
+ bWaitFaceX = true;
+ }
+ }
+
+ if ( command == 71 && bWaitFaceX )
+ {
+ bWaitFaceX = false;
+ sscanf(line, "%d", &p1);
+ if ( p1 < 0 ) p1 = -p1;
+ bWaitFaceY = true;
+ }
+
+ if ( command == 72 && bWaitFaceY )
+ {
+ bWaitFaceY = false;
+ sscanf(line, "%d", &p2);
+ if ( p2 < 0 ) p2 = -p2;
+ bWaitFaceZ = true;
+ }
+
+ if ( command == 73 && bWaitFaceZ )
+ {
+ bWaitFaceZ = false;
+ sscanf(line, "%d", &p3);
+ if ( p3 < 0 ) p3 = -p3;
+
+ nbFace --;
+ if ( nbFace >= 0 )
+ {
+ CreateTriangle( table[p3-1], table[p2-1], table[p1-1], min,max );
+ bWaitFaceX = true;
+
+//? sprintf(s, "Face=%d;%d;%d\n", p1,p2,p3);
+//? OutputDebugString(s);
+ }
+ }
+
+ }
+
+ fclose(file);
+ return true;
}
struct InfoMOD
{
- int rev;
- int vers;
- int total;
- int reserve[10];
+ int rev;
+ int vers;
+ int total;
+ int reserve[10];
};
@@ -255,10 +255,10 @@ struct InfoMOD
void ChangeBMPtoTGA(char *filename)
{
- char* p;
+ char* p;
- p = strstr(filename, ".bmp");
- if ( p != 0 ) strcpy(p, ".tga");
+ p = strstr(filename, ".bmp");
+ if ( p != 0 ) strcpy(p, ".tga");
}
@@ -266,224 +266,224 @@ void ChangeBMPtoTGA(char *filename)
bool CModFile::AddModel(char *filename, int first, bool bEdit, bool bMeta)
{
- FILE* file;
- InfoMOD info;
- float limit[2];
- int i, nb, err;
- char* p;
-
- if ( m_engine->RetDebugMode() )
- {
- bMeta = false;
- }
-
- if ( bMeta )
- {
- p = strchr(filename, '\\');
- if ( p == 0 )
- {
+ FILE* file;
+ InfoMOD info;
+ float limit[2];
+ int i, nb, err;
+ char* p;
+
+ if ( m_engine->RetDebugMode() )
+ {
+ bMeta = false;
+ }
+
+ if ( bMeta )
+ {
+ p = strchr(filename, '\\');
+ if ( p == 0 )
+ {
#if _SCHOOL
- err = g_metafile.Open("ceebot2.dat", filename);
+ err = g_metafile.Open("ceebot2.dat", filename);
#else
- err = g_metafile.Open("colobot2.dat", filename);
+ err = g_metafile.Open("colobot2.dat", filename);
#endif
- }
- else
- {
+ }
+ else
+ {
#if _SCHOOL
- err = g_metafile.Open("ceebot2.dat", p+1);
+ err = g_metafile.Open("ceebot2.dat", p+1);
#else
- err = g_metafile.Open("colobot2.dat", p+1);
+ err = g_metafile.Open("colobot2.dat", p+1);
#endif
- }
- if ( err != 0 ) bMeta = false;
- }
- if ( !bMeta )
- {
- file = fopen(filename, "rb");
- if ( file == NULL ) return false;
- }
-
- if ( bMeta )
- {
- g_metafile.Read(&info, sizeof(InfoMOD));
- }
- else
- {
- fread(&info, sizeof(InfoMOD), 1, file);
- }
- nb = info.total;
- m_triangleUsed += nb;
-
- if ( info.rev == 1 && info.vers == 0 )
- {
- OldModelTriangle1 old;
-
- for ( i=first ; i<m_triangleUsed ; i++ )
- {
- if ( bMeta )
- {
- g_metafile.Read(&old, sizeof(OldModelTriangle1));
- }
- else
- {
- fread(&old, sizeof(OldModelTriangle1), 1, file);
- }
-
- ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
- m_triangleTable[i].bUsed = old.bUsed;
- m_triangleTable[i].bSelect = old.bSelect;
-
- m_triangleTable[i].p1.x = old.p1.x;
- m_triangleTable[i].p1.y = old.p1.y;
- m_triangleTable[i].p1.z = old.p1.z;
- m_triangleTable[i].p1.nx = old.p1.nx;
- m_triangleTable[i].p1.ny = old.p1.ny;
- m_triangleTable[i].p1.nz = old.p1.nz;
- m_triangleTable[i].p1.tu = old.p1.tu;
- m_triangleTable[i].p1.tv = old.p1.tv;
-
- m_triangleTable[i].p2.x = old.p2.x;
- m_triangleTable[i].p2.y = old.p2.y;
- m_triangleTable[i].p2.z = old.p2.z;
- m_triangleTable[i].p2.nx = old.p2.nx;
- m_triangleTable[i].p2.ny = old.p2.ny;
- m_triangleTable[i].p2.nz = old.p2.nz;
- m_triangleTable[i].p2.tu = old.p2.tu;
- m_triangleTable[i].p2.tv = old.p2.tv;
-
- m_triangleTable[i].p3.x = old.p3.x;
- m_triangleTable[i].p3.y = old.p3.y;
- m_triangleTable[i].p3.z = old.p3.z;
- m_triangleTable[i].p3.nx = old.p3.nx;
- m_triangleTable[i].p3.ny = old.p3.ny;
- m_triangleTable[i].p3.nz = old.p3.nz;
- m_triangleTable[i].p3.tu = old.p3.tu;
- m_triangleTable[i].p3.tv = old.p3.tv;
-
- m_triangleTable[i].material = old.material;
- strcpy(m_triangleTable[i].texName, old.texName);
- m_triangleTable[i].min = old.min;
- m_triangleTable[i].max = old.max;
- }
- }
- else if ( info.rev == 1 && info.vers == 1 )
- {
- OldModelTriangle2 old;
-
- for ( i=first ; i<m_triangleUsed ; i++ )
- {
- if ( bMeta )
- {
- g_metafile.Read(&old, sizeof(OldModelTriangle2));
- }
- else
- {
- fread(&old, sizeof(OldModelTriangle2), 1, file);
- }
-
- ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
- m_triangleTable[i].bUsed = old.bUsed;
- m_triangleTable[i].bSelect = old.bSelect;
-
- m_triangleTable[i].p1.x = old.p1.x;
- m_triangleTable[i].p1.y = old.p1.y;
- m_triangleTable[i].p1.z = old.p1.z;
- m_triangleTable[i].p1.nx = old.p1.nx;
- m_triangleTable[i].p1.ny = old.p1.ny;
- m_triangleTable[i].p1.nz = old.p1.nz;
- m_triangleTable[i].p1.tu = old.p1.tu;
- m_triangleTable[i].p1.tv = old.p1.tv;
-
- m_triangleTable[i].p2.x = old.p2.x;
- m_triangleTable[i].p2.y = old.p2.y;
- m_triangleTable[i].p2.z = old.p2.z;
- m_triangleTable[i].p2.nx = old.p2.nx;
- m_triangleTable[i].p2.ny = old.p2.ny;
- m_triangleTable[i].p2.nz = old.p2.nz;
- m_triangleTable[i].p2.tu = old.p2.tu;
- m_triangleTable[i].p2.tv = old.p2.tv;
-
- m_triangleTable[i].p3.x = old.p3.x;
- m_triangleTable[i].p3.y = old.p3.y;
- m_triangleTable[i].p3.z = old.p3.z;
- m_triangleTable[i].p3.nx = old.p3.nx;
- m_triangleTable[i].p3.ny = old.p3.ny;
- m_triangleTable[i].p3.nz = old.p3.nz;
- m_triangleTable[i].p3.tu = old.p3.tu;
- m_triangleTable[i].p3.tv = old.p3.tv;
-
- m_triangleTable[i].material = old.material;
- strcpy(m_triangleTable[i].texName, old.texName);
- m_triangleTable[i].min = old.min;
- m_triangleTable[i].max = old.max;
- m_triangleTable[i].state = old.state;
- m_triangleTable[i].reserve2 = old.reserve2;
- m_triangleTable[i].reserve3 = old.reserve3;
- m_triangleTable[i].reserve4 = old.reserve4;
- }
- }
- else
- {
- if ( bMeta )
- {
- g_metafile.Read(m_triangleTable+first, sizeof(ModelTriangle)*nb);
- }
- else
- {
- fread(m_triangleTable+first, sizeof(ModelTriangle), nb, file);
- }
- }
-
- for ( i=first ; i<m_triangleUsed ; i++ )
- {
- ChangeBMPtoTGA(m_triangleTable[i].texName);
- }
-
- if ( !bEdit )
- {
- limit[0] = m_engine->RetLimitLOD(0); // frontier AB as config
- limit[1] = m_engine->RetLimitLOD(1); // frontier BC as config
-
- // Standard frontiers -> config.
- for ( i=first ; i<m_triangleUsed ; i++ )
- {
- if ( m_triangleTable[i].min == 0.0f &&
- m_triangleTable[i].max == 100.0f ) // resolution A ?
- {
- m_triangleTable[i].max = limit[0];
- }
- else if ( m_triangleTable[i].min == 100.0f &&
- m_triangleTable[i].max == 200.0f ) // resolution B ?
- {
- m_triangleTable[i].min = limit[0];
- m_triangleTable[i].max = limit[1];
- }
- else if ( m_triangleTable[i].min == 200.0f &&
- m_triangleTable[i].max == 1000000.0f ) // resolution C ?
- {
- m_triangleTable[i].min = limit[1];
- }
- }
- }
-
- if ( bMeta )
- {
- g_metafile.Close();
- }
- else
- {
- fclose(file);
- }
- return true;
+ }
+ if ( err != 0 ) bMeta = false;
+ }
+ if ( !bMeta )
+ {
+ file = fopen(filename, "rb");
+ if ( file == NULL ) return false;
+ }
+
+ if ( bMeta )
+ {
+ g_metafile.Read(&info, sizeof(InfoMOD));
+ }
+ else
+ {
+ fread(&info, sizeof(InfoMOD), 1, file);
+ }
+ nb = info.total;
+ m_triangleUsed += nb;
+
+ if ( info.rev == 1 && info.vers == 0 )
+ {
+ OldModelTriangle1 old;
+
+ for ( i=first ; i<m_triangleUsed ; i++ )
+ {
+ if ( bMeta )
+ {
+ g_metafile.Read(&old, sizeof(OldModelTriangle1));
+ }
+ else
+ {
+ fread(&old, sizeof(OldModelTriangle1), 1, file);
+ }
+
+ ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
+ m_triangleTable[i].bUsed = old.bUsed;
+ m_triangleTable[i].bSelect = old.bSelect;
+
+ m_triangleTable[i].p1.x = old.p1.x;
+ m_triangleTable[i].p1.y = old.p1.y;
+ m_triangleTable[i].p1.z = old.p1.z;
+ m_triangleTable[i].p1.nx = old.p1.nx;
+ m_triangleTable[i].p1.ny = old.p1.ny;
+ m_triangleTable[i].p1.nz = old.p1.nz;
+ m_triangleTable[i].p1.tu = old.p1.tu;
+ m_triangleTable[i].p1.tv = old.p1.tv;
+
+ m_triangleTable[i].p2.x = old.p2.x;
+ m_triangleTable[i].p2.y = old.p2.y;
+ m_triangleTable[i].p2.z = old.p2.z;
+ m_triangleTable[i].p2.nx = old.p2.nx;
+ m_triangleTable[i].p2.ny = old.p2.ny;
+ m_triangleTable[i].p2.nz = old.p2.nz;
+ m_triangleTable[i].p2.tu = old.p2.tu;
+ m_triangleTable[i].p2.tv = old.p2.tv;
+
+ m_triangleTable[i].p3.x = old.p3.x;
+ m_triangleTable[i].p3.y = old.p3.y;
+ m_triangleTable[i].p3.z = old.p3.z;
+ m_triangleTable[i].p3.nx = old.p3.nx;
+ m_triangleTable[i].p3.ny = old.p3.ny;
+ m_triangleTable[i].p3.nz = old.p3.nz;
+ m_triangleTable[i].p3.tu = old.p3.tu;
+ m_triangleTable[i].p3.tv = old.p3.tv;
+
+ m_triangleTable[i].material = old.material;
+ strcpy(m_triangleTable[i].texName, old.texName);
+ m_triangleTable[i].min = old.min;
+ m_triangleTable[i].max = old.max;
+ }
+ }
+ else if ( info.rev == 1 && info.vers == 1 )
+ {
+ OldModelTriangle2 old;
+
+ for ( i=first ; i<m_triangleUsed ; i++ )
+ {
+ if ( bMeta )
+ {
+ g_metafile.Read(&old, sizeof(OldModelTriangle2));
+ }
+ else
+ {
+ fread(&old, sizeof(OldModelTriangle2), 1, file);
+ }
+
+ ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
+ m_triangleTable[i].bUsed = old.bUsed;
+ m_triangleTable[i].bSelect = old.bSelect;
+
+ m_triangleTable[i].p1.x = old.p1.x;
+ m_triangleTable[i].p1.y = old.p1.y;
+ m_triangleTable[i].p1.z = old.p1.z;
+ m_triangleTable[i].p1.nx = old.p1.nx;
+ m_triangleTable[i].p1.ny = old.p1.ny;
+ m_triangleTable[i].p1.nz = old.p1.nz;
+ m_triangleTable[i].p1.tu = old.p1.tu;
+ m_triangleTable[i].p1.tv = old.p1.tv;
+
+ m_triangleTable[i].p2.x = old.p2.x;
+ m_triangleTable[i].p2.y = old.p2.y;
+ m_triangleTable[i].p2.z = old.p2.z;
+ m_triangleTable[i].p2.nx = old.p2.nx;
+ m_triangleTable[i].p2.ny = old.p2.ny;
+ m_triangleTable[i].p2.nz = old.p2.nz;
+ m_triangleTable[i].p2.tu = old.p2.tu;
+ m_triangleTable[i].p2.tv = old.p2.tv;
+
+ m_triangleTable[i].p3.x = old.p3.x;
+ m_triangleTable[i].p3.y = old.p3.y;
+ m_triangleTable[i].p3.z = old.p3.z;
+ m_triangleTable[i].p3.nx = old.p3.nx;
+ m_triangleTable[i].p3.ny = old.p3.ny;
+ m_triangleTable[i].p3.nz = old.p3.nz;
+ m_triangleTable[i].p3.tu = old.p3.tu;
+ m_triangleTable[i].p3.tv = old.p3.tv;
+
+ m_triangleTable[i].material = old.material;
+ strcpy(m_triangleTable[i].texName, old.texName);
+ m_triangleTable[i].min = old.min;
+ m_triangleTable[i].max = old.max;
+ m_triangleTable[i].state = old.state;
+ m_triangleTable[i].reserve2 = old.reserve2;
+ m_triangleTable[i].reserve3 = old.reserve3;
+ m_triangleTable[i].reserve4 = old.reserve4;
+ }
+ }
+ else
+ {
+ if ( bMeta )
+ {
+ g_metafile.Read(m_triangleTable+first, sizeof(ModelTriangle)*nb);
+ }
+ else
+ {
+ fread(m_triangleTable+first, sizeof(ModelTriangle), nb, file);
+ }
+ }
+
+ for ( i=first ; i<m_triangleUsed ; i++ )
+ {
+ ChangeBMPtoTGA(m_triangleTable[i].texName);
+ }
+
+ if ( !bEdit )
+ {
+ limit[0] = m_engine->RetLimitLOD(0); // frontier AB as config
+ limit[1] = m_engine->RetLimitLOD(1); // frontier BC as config
+
+ // Standard frontiers -> config.
+ for ( i=first ; i<m_triangleUsed ; i++ )
+ {
+ if ( m_triangleTable[i].min == 0.0f &&
+ m_triangleTable[i].max == 100.0f ) // resolution A ?
+ {
+ m_triangleTable[i].max = limit[0];
+ }
+ else if ( m_triangleTable[i].min == 100.0f &&
+ m_triangleTable[i].max == 200.0f ) // resolution B ?
+ {
+ m_triangleTable[i].min = limit[0];
+ m_triangleTable[i].max = limit[1];
+ }
+ else if ( m_triangleTable[i].min == 200.0f &&
+ m_triangleTable[i].max == 1000000.0f ) // resolution C ?
+ {
+ m_triangleTable[i].min = limit[1];
+ }
+ }
+ }
+
+ if ( bMeta )
+ {
+ g_metafile.Close();
+ }
+ else
+ {
+ fclose(file);
+ }
+ return true;
}
// Reads a MOD file.
bool CModFile::ReadModel(char *filename, bool bEdit, bool bMeta)
{
- m_triangleUsed = 0;
- return AddModel(filename, 0, bEdit, bMeta);
+ m_triangleUsed = 0;
+ return AddModel(filename, 0, bEdit, bMeta);
}
@@ -491,24 +491,24 @@ bool CModFile::ReadModel(char *filename, bool bEdit, bool bMeta)
bool CModFile::WriteModel(char *filename)
{
- FILE* file;
- InfoMOD info;
+ FILE* file;
+ InfoMOD info;
- if ( m_triangleUsed == 0 ) return false;
+ if ( m_triangleUsed == 0 ) return false;
- file = fopen(filename, "wb");
- if ( file == NULL ) return false;
+ file = fopen(filename, "wb");
+ if ( file == NULL ) return false;
- ZeroMemory(&info, sizeof(InfoMOD));
- info.rev = 1;
- info.vers = 2;
- info.total = m_triangleUsed;
- fwrite(&info, sizeof(InfoMOD), 1, file);
+ ZeroMemory(&info, sizeof(InfoMOD));
+ info.rev = 1;
+ info.vers = 2;
+ info.total = m_triangleUsed;
+ fwrite(&info, sizeof(InfoMOD), 1, file);
- fwrite(m_triangleTable, sizeof(ModelTriangle), m_triangleUsed, file);
+ fwrite(m_triangleTable, sizeof(ModelTriangle), m_triangleUsed, file);
- fclose(file);
- return true;
+ fclose(file);
+ return true;
}
@@ -517,94 +517,94 @@ bool CModFile::WriteModel(char *filename)
bool CModFile::CreateEngineObject(int objRank, int addState)
{
#if 0
- char texName2[20];
- int texNum, i, state;
-
- for ( i=0 ; i<m_triangleUsed ; i++ )
- {
- if ( !m_triangleTable[i].bUsed ) continue;
-
- state = m_triangleTable[i].state;
- texName2[0] = 0;
-
- if ( m_triangleTable[i].texNum2 != 0 )
- {
- if ( m_triangleTable[i].texNum2 == 1 )
- {
- texNum = m_engine->RetSecondTexture();
- }
- else
- {
- texNum = m_triangleTable[i].texNum2;
- }
-
- if ( texNum >= 1 && texNum <= 10 )
- {
- state = m_triangleTable[i].state|D3DSTATEDUALb;
- }
- if ( texNum >= 11 && texNum <= 20 )
- {
- state = m_triangleTable[i].state|D3DSTATEDUALw;
- }
- sprintf(texName2, "dirty%.2d.bmp", texNum);
- }
-
- m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
- m_triangleTable[i].material,
- state+addState,
- m_triangleTable[i].texName, texName2,
- m_triangleTable[i].min,
- m_triangleTable[i].max, false);
- }
- return true;
+ char texName2[20];
+ int texNum, i, state;
+
+ for ( i=0 ; i<m_triangleUsed ; i++ )
+ {
+ if ( !m_triangleTable[i].bUsed ) continue;
+
+ state = m_triangleTable[i].state;
+ texName2[0] = 0;
+
+ if ( m_triangleTable[i].texNum2 != 0 )
+ {
+ if ( m_triangleTable[i].texNum2 == 1 )
+ {
+ texNum = m_engine->RetSecondTexture();
+ }
+ else
+ {
+ texNum = m_triangleTable[i].texNum2;
+ }
+
+ if ( texNum >= 1 && texNum <= 10 )
+ {
+ state = m_triangleTable[i].state|D3DSTATEDUALb;
+ }
+ if ( texNum >= 11 && texNum <= 20 )
+ {
+ state = m_triangleTable[i].state|D3DSTATEDUALw;
+ }
+ sprintf(texName2, "dirty%.2d.bmp", texNum);
+ }
+
+ m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
+ m_triangleTable[i].material,
+ state+addState,
+ m_triangleTable[i].texName, texName2,
+ m_triangleTable[i].min,
+ m_triangleTable[i].max, false);
+ }
+ return true;
#else
- char texName1[20];
- char texName2[20];
- int texNum, i, state;
-
- for ( i=0 ; i<m_triangleUsed ; i++ )
- {
- if ( !m_triangleTable[i].bUsed ) continue;
-
- state = m_triangleTable[i].state;
- strcpy(texName1, m_triangleTable[i].texName);
- texName2[0] = 0;
-
- if ( strcmp(texName1, "plant.tga") == 0 )
- {
- state |= D3DSTATEALPHA;
- }
-
- if ( m_triangleTable[i].texNum2 != 0 )
- {
- if ( m_triangleTable[i].texNum2 == 1 )
- {
- texNum = m_engine->RetSecondTexture();
- }
- else
- {
- texNum = m_triangleTable[i].texNum2;
- }
-
- if ( texNum >= 1 && texNum <= 10 )
- {
- state |= D3DSTATEDUALb;
- }
- if ( texNum >= 11 && texNum <= 20 )
- {
- state |= D3DSTATEDUALw;
- }
- sprintf(texName2, "dirty%.2d.tga", texNum);
- }
-
- m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
- m_triangleTable[i].material,
- state+addState,
- texName1, texName2,
- m_triangleTable[i].min,
- m_triangleTable[i].max, false);
- }
- return true;
+ char texName1[20];
+ char texName2[20];
+ int texNum, i, state;
+
+ for ( i=0 ; i<m_triangleUsed ; i++ )
+ {
+ if ( !m_triangleTable[i].bUsed ) continue;
+
+ state = m_triangleTable[i].state;
+ strcpy(texName1, m_triangleTable[i].texName);
+ texName2[0] = 0;
+
+ if ( strcmp(texName1, "plant.tga") == 0 )
+ {
+ state |= D3DSTATEALPHA;
+ }
+
+ if ( m_triangleTable[i].texNum2 != 0 )
+ {
+ if ( m_triangleTable[i].texNum2 == 1 )
+ {
+ texNum = m_engine->RetSecondTexture();
+ }
+ else
+ {
+ texNum = m_triangleTable[i].texNum2;
+ }
+
+ if ( texNum >= 1 && texNum <= 10 )
+ {
+ state |= D3DSTATEDUALb;
+ }
+ if ( texNum >= 11 && texNum <= 20 )
+ {
+ state |= D3DSTATEDUALw;
+ }
+ sprintf(texName2, "dirty%.2d.tga", texNum);
+ }
+
+ m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
+ m_triangleTable[i].material,
+ state+addState,
+ texName1, texName2,
+ m_triangleTable[i].min,
+ m_triangleTable[i].max, false);
+ }
+ return true;
#endif
}
@@ -613,23 +613,23 @@ bool CModFile::CreateEngineObject(int objRank, int addState)
void CModFile::Mirror()
{
- D3DVERTEX2 t;
- int i;
-
- for ( i=0 ; i<m_triangleUsed ; i++ )
- {
- t = m_triangleTable[i].p1;
- m_triangleTable[i].p1 = m_triangleTable[i].p2;
- m_triangleTable[i].p2 = t;
-
- m_triangleTable[i].p1.z = -m_triangleTable[i].p1.z;
- m_triangleTable[i].p2.z = -m_triangleTable[i].p2.z;
- m_triangleTable[i].p3.z = -m_triangleTable[i].p3.z;
-
- m_triangleTable[i].p1.nz = -m_triangleTable[i].p1.nz;
- m_triangleTable[i].p2.nz = -m_triangleTable[i].p2.nz;
- m_triangleTable[i].p3.nz = -m_triangleTable[i].p3.nz;
- }
+ D3DVERTEX2 t;
+ int i;
+
+ for ( i=0 ; i<m_triangleUsed ; i++ )
+ {
+ t = m_triangleTable[i].p1;
+ m_triangleTable[i].p1 = m_triangleTable[i].p2;
+ m_triangleTable[i].p2 = t;
+
+ m_triangleTable[i].p1.z = -m_triangleTable[i].p1.z;
+ m_triangleTable[i].p2.z = -m_triangleTable[i].p2.z;
+ m_triangleTable[i].p3.z = -m_triangleTable[i].p3.z;
+
+ m_triangleTable[i].p1.nz = -m_triangleTable[i].p1.nz;
+ m_triangleTable[i].p2.nz = -m_triangleTable[i].p2.nz;
+ m_triangleTable[i].p3.nz = -m_triangleTable[i].p3.nz;
+ }
}
@@ -637,22 +637,22 @@ void CModFile::Mirror()
void CModFile::SetTriangleUsed(int total)
{
- m_triangleUsed = total;
+ m_triangleUsed = total;
}
int CModFile::RetTriangleUsed()
{
- return m_triangleUsed;
+ return m_triangleUsed;
}
int CModFile::RetTriangleMax()
{
- return MAX_VERTICES;
+ return MAX_VERTICES;
}
ModelTriangle* CModFile::RetTriangleList()
{
- return m_triangleTable;
+ return m_triangleTable;
}
@@ -660,36 +660,36 @@ ModelTriangle* CModFile::RetTriangleList()
float CModFile::RetHeight(Math::Vector pos)
{
- Math::Vector p1, p2, p3;
- float limit;
- int i;
-
- limit = 5.0f;
-
- for ( i=0 ; i<m_triangleUsed ; i++ )
- {
- if ( !m_triangleTable[i].bUsed ) continue;
-
- if ( fabs(pos.x-m_triangleTable[i].p1.x) < limit &&
- fabs(pos.z-m_triangleTable[i].p1.z) < limit )
- {
- return m_triangleTable[i].p1.y;
- }
-
- if ( fabs(pos.x-m_triangleTable[i].p2.x) < limit &&
- fabs(pos.z-m_triangleTable[i].p2.z) < limit )
- {
- return m_triangleTable[i].p2.y;
- }
-
- if ( fabs(pos.x-m_triangleTable[i].p3.x) < limit &&
- fabs(pos.z-m_triangleTable[i].p3.z) < limit )
- {
- return m_triangleTable[i].p3.y;
- }
- }
-
- return 0.0f;
+ Math::Vector p1, p2, p3;
+ float limit;
+ int i;
+
+ limit = 5.0f;
+
+ for ( i=0 ; i<m_triangleUsed ; i++ )
+ {
+ if ( !m_triangleTable[i].bUsed ) continue;
+
+ if ( fabs(pos.x-m_triangleTable[i].p1.x) < limit &&
+ fabs(pos.z-m_triangleTable[i].p1.z) < limit )
+ {
+ return m_triangleTable[i].p1.y;
+ }
+
+ if ( fabs(pos.x-m_triangleTable[i].p2.x) < limit &&
+ fabs(pos.z-m_triangleTable[i].p2.z) < limit )
+ {
+ return m_triangleTable[i].p2.y;
+ }
+
+ if ( fabs(pos.x-m_triangleTable[i].p3.x) < limit &&
+ fabs(pos.z-m_triangleTable[i].p3.z) < limit )
+ {
+ return m_triangleTable[i].p3.y;
+ }
+ }
+
+ return 0.0f;
}
diff --git a/src/old/modfile.h b/src/old/modfile.h
index 1422687..c852c1e 100644
--- a/src/old/modfile.h
+++ b/src/old/modfile.h
@@ -30,52 +30,52 @@ class CInstanceManager;
struct OldModelTriangle1
{
- char bUsed; // true -> using
- char bSelect; // true -> selected
- D3DVERTEX p1;
- D3DVERTEX p2;
- D3DVERTEX p3;
- D3DMATERIAL7 material;
- char texName[20];
- float min;
- float max;
-}; // length = 196 bytes
+ char bUsed; // true -> using
+ char bSelect; // true -> selected
+ D3DVERTEX p1;
+ D3DVERTEX p2;
+ D3DVERTEX p3;
+ D3DMATERIAL7 material;
+ char texName[20];
+ float min;
+ float max;
+}; // length = 196 bytes
struct OldModelTriangle2
{
- char bUsed; // true -> used
- char bSelect; // true -> selected
- D3DVERTEX p1;
- D3DVERTEX p2;
- D3DVERTEX p3;
- D3DMATERIAL7 material;
- char texName[20];
- float min;
- float max;
- long state;
- short reserve1;
- short reserve2;
- short reserve3;
- short reserve4;
+ char bUsed; // true -> used
+ char bSelect; // true -> selected
+ D3DVERTEX p1;
+ D3DVERTEX p2;
+ D3DVERTEX p3;
+ D3DMATERIAL7 material;
+ char texName[20];
+ float min;
+ float max;
+ long state;
+ short reserve1;
+ short reserve2;
+ short reserve3;
+ short reserve4;
};
struct ModelTriangle
{
- char bUsed; // true -> used
- char bSelect; // true -> selected
- D3DVERTEX2 p1;
- D3DVERTEX2 p2;
- D3DVERTEX2 p3;
- D3DMATERIAL7 material;
- char texName[20];
- float min;
- float max;
- long state;
- short texNum2;
- short reserve2;
- short reserve3;
- short reserve4;
-}; // length = 208 bytes
+ char bUsed; // true -> used
+ char bSelect; // true -> selected
+ D3DVERTEX2 p1;
+ D3DVERTEX2 p2;
+ D3DVERTEX2 p3;
+ D3DMATERIAL7 material;
+ char texName[20];
+ float min;
+ float max;
+ long state;
+ short texNum2;
+ short reserve2;
+ short reserve3;
+ short reserve4;
+}; // length = 208 bytes
@@ -83,33 +83,33 @@ struct ModelTriangle
class CModFile
{
public:
- CModFile(CInstanceManager* iMan);
- ~CModFile();
+ CModFile(CInstanceManager* iMan);
+ ~CModFile();
- bool ReadDXF(char *filename, float min, float max);
- bool AddModel(char *filename, int first, bool bEdit=false, bool bMeta=true);
- bool ReadModel(char *filename, bool bEdit=false, bool bMeta=true);
- bool WriteModel(char *filename);
+ bool ReadDXF(char *filename, float min, float max);
+ bool AddModel(char *filename, int first, bool bEdit=false, bool bMeta=true);
+ bool ReadModel(char *filename, bool bEdit=false, bool bMeta=true);
+ bool WriteModel(char *filename);
- bool CreateEngineObject(int objRank, int addState=0);
- void Mirror();
+ bool CreateEngineObject(int objRank, int addState=0);
+ void Mirror();
- void SetTriangleUsed(int total);
- int RetTriangleUsed();
- int RetTriangleMax();
- ModelTriangle* RetTriangleList();
+ void SetTriangleUsed(int total);
+ int RetTriangleUsed();
+ int RetTriangleMax();
+ ModelTriangle* RetTriangleList();
- float RetHeight(Math::Vector pos);
+ float RetHeight(Math::Vector pos);
protected:
- bool CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, float min, float max);
+ bool CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, float min, float max);
protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
- ModelTriangle* m_triangleTable;
- int m_triangleUsed;
+ ModelTriangle* m_triangleTable;
+ int m_triangleUsed;
};
diff --git a/src/old/particule.cpp b/src/old/particule.cpp
index 8c8a162..b807e3d 100644
--- a/src/old/particule.cpp
+++ b/src/old/particule.cpp
@@ -1,4401 +1,4401 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// particule.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "math/conv.h"
-#include "old/d3dmath.h"
-#include "old/d3dtextr.h"
-#include "old/d3dengine.h"
-#include "old/d3dutil.h"
-#include "common/language.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "object/object.h"
-#include "physics/physics.h"
-#include "object/auto/auto.h"
-#include "object/robotmain.h"
-#include "old/terrain.h"
-#include "old/sound.h"
-#include "old/water.h"
-#include "old/particule.h"
-
-
-
-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)
-{
- 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 RetDecay(ObjectType type)
-{
- if ( IsSoft(type) ) return 0.2f;
- return 1.0f;
-}
-
-
-
-// Application constructor.
-
-CParticule::CParticule(CInstanceManager *iMan, CD3DEngine* engine)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_PARTICULE, this);
-
- m_pD3DDevice = 0;
- m_engine = engine;
- m_main = 0;
- m_terrain = 0;
- m_water = 0;
- m_sound = 0;
- m_uniqueStamp = 0;
- m_exploGunCounter = 0;
- m_lastTimeGunDel = 0.0f;
- m_absTime = 0.0f;
-
- FlushParticule();
-}
-
-// Application destructor. Free memory.
-
-CParticule::~CParticule()
-{
- m_iMan->DeleteInstance(CLASS_PARTICULE, this);
-}
-
-
-void CParticule::SetD3DDevice(LPDIRECT3DDEVICE7 device)
-{
- m_pD3DDevice = device;
-}
-
-
-// Removes all particles.
-
-void CParticule::FlushParticule()
-{
- int i, j;
-
- for ( i=0 ; i<MAXPARTICULE*MAXPARTITYPE ; i++ )
- {
- m_particule[i].bUsed = false;
- }
-
- for ( i=0 ; i<MAXPARTITYPE ; i++ )
- {
- for ( j=0 ; j<SH_MAX ; j++ )
- {
- m_totalInterface[i][j] = 0;
- }
- }
-
- for ( i=0 ; i<MAXTRACK ; i++ )
- {
- m_track[i].bUsed = false;
- }
-
- m_wheelTraceTotal = 0;
- m_wheelTraceIndex = 0;
-
- for ( i=0 ; i<SH_MAX ; i++ )
- {
- m_bFrameUpdate[i] = true;
- }
-
- m_fogTotal = 0;
- m_exploGunCounter = 0;
-}
-
-// Removes all particles of a sheet.
-
-void CParticule::FlushParticule(int sheet)
-{
- int i;
-
- for ( i=0 ; i<MAXPARTICULE*MAXPARTITYPE ; i++ )
- {
- if ( !m_particule[i].bUsed ) continue;
- if ( m_particule[i].sheet != sheet ) continue;
-
- m_particule[i].bUsed = false;
- }
-
- for ( i=0 ; i<MAXPARTITYPE ; i++ )
- {
- m_totalInterface[i][sheet] = 0;
- }
-
- for ( i=0 ; i<MAXTRACK ; i++ )
- {
- m_track[i].bUsed = false;
- }
-
- if ( sheet == SH_WORLD )
- {
- m_wheelTraceTotal = 0;
- m_wheelTraceIndex = 0;
- }
-}
-
-
-// Builds file name of the effect.
-// effectNN.tga, with NN = number
-
-void NameParticule(char *buffer, int num)
-{
- if ( num == 1 ) strcpy(buffer, "effect00.tga");
- else if ( num == 2 ) strcpy(buffer, "effect01.tga");
- else if ( num == 3 ) strcpy(buffer, "effect02.tga");
-#if _POLISH
- else if ( num == 4 ) strcpy(buffer, "textp.tga");
-#else
- else if ( num == 4 ) strcpy(buffer, "text.tga");
-#endif
- else strcpy(buffer, "xxx.tga");
-}
-
-
-// Creates a new particle.
-// Returns the channel of the particle created or -1 on error.
-
-int CParticule::CreateParticule(Math::Vector pos, Math::Vector speed, Math::Point dim,
- ParticuleType type,
- float duration, float mass,
- float windSensitivity, int sheet)
-{
-//? float dist;
- int i, j, t;
-
- if ( m_main == 0 )
- {
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- }
-
-#if 0
- if ( sheet == SH_WORLD &&
- type != PARTISELY &&
- type != PARTISELR &&
- type != PARTIGUN1 &&
- type != PARTIGUN2 &&
- type != PARTIGUN3 &&
- type != PARTIGUN4 &&
- type != PARTIQUARTZ &&
- !m_main->RetMovieLock() )
- {
- dist = Math::Distance(pos, m_engine->RetEyePt());
- if ( dist > 300.0f ) return -1;
- }
-#endif
-
- 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 ( j=0 ; j<MAXPARTICULE ; j++ )
- {
- i = MAXPARTICULE*t+j;
-
- if ( !m_particule[i].bUsed )
- {
- ZeroMemory(&m_particule[i], sizeof(Particule));
- m_particule[i].bUsed = true;
- m_particule[i].bRay = false;
- m_particule[i].uniqueStamp = m_uniqueStamp++;
- m_particule[i].sheet = sheet;
- m_particule[i].mass = mass;
- m_particule[i].duration = duration;
- m_particule[i].pos = pos;
- m_particule[i].goal = pos;
- m_particule[i].speed = speed;
- m_particule[i].windSensitivity = windSensitivity;
- m_particule[i].dim = dim;
- m_particule[i].zoom = 1.0f;
- m_particule[i].angle = 0.0f;
- m_particule[i].intensity = 1.0f;
- m_particule[i].type = type;
- m_particule[i].phase = PARPHSTART;
- m_particule[i].texSup.x = 0.0f;
- m_particule[i].texSup.y = 0.0f;
- m_particule[i].texInf.x = 0.0f;
- m_particule[i].texInf.y = 0.0f;
- m_particule[i].time = 0.0f;
- m_particule[i].phaseTime = 0.0f;
- m_particule[i].testTime = 0.0f;
- m_particule[i].objLink = 0;
- m_particule[i].objFather = 0;
- m_particule[i].trackRank = -1;
-
- m_totalInterface[t][sheet] ++;
-
- if ( type == PARTIEXPLOT ||
- type == PARTIEXPLOO )
- {
- m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
- }
-
- if ( type == PARTIGUN1 ||
- type == PARTIGUN4 )
- {
- m_particule[i].testTime = 1.0f; // impact immediately
- }
-
- if ( type >= PARTIFOG0 &&
- type <= PARTIFOG9 )
- {
- if ( m_fogTotal < MAXPARTIFOG )
- m_fog[m_fogTotal++] = i;
- }
-
- return i | ((m_particule[i].uniqueStamp&0xffff)<<16);
- }
- }
-
- return -1;
-}
-
-// Creates a new triangular particle (debris).
-// Returns the channel of the particle created or -1 on error.
-
-int CParticule::CreateFrag(Math::Vector pos, Math::Vector speed,
- D3DTriangle *triangle,
- ParticuleType type,
- float duration, float mass,
- float windSensitivity, int sheet)
-{
- Math::Vector p1, p2, p3, n;
- float l1, l2, l3, dx, dy;
- int i, j, t;
-
- t = 0;
- for ( j=0 ; j<MAXPARTICULE ; j++ )
- {
- i = MAXPARTICULE*t+j;
-
- if ( !m_particule[i].bUsed )
- {
- ZeroMemory(&m_particule[i], sizeof(Particule));
- m_particule[i].bUsed = true;
- m_particule[i].bRay = false;
- m_particule[i].uniqueStamp = m_uniqueStamp++;
- m_particule[i].sheet = sheet;
- m_particule[i].mass = mass;
- m_particule[i].duration = duration;
- m_particule[i].pos = pos;
- m_particule[i].goal = pos;
- m_particule[i].speed = speed;
- m_particule[i].windSensitivity = windSensitivity;
- m_particule[i].zoom = 1.0f;
- m_particule[i].angle = 0.0f;
- m_particule[i].intensity = 1.0f;
- m_particule[i].type = type;
- m_particule[i].phase = PARPHSTART;
- m_particule[i].texSup.x = 0.0f;
- m_particule[i].texSup.y = 0.0f;
- m_particule[i].texInf.x = 0.0f;
- m_particule[i].texInf.y = 0.0f;
- m_particule[i].time = 0.0f;
- m_particule[i].phaseTime = 0.0f;
- m_particule[i].testTime = 0.0f;
- m_particule[i].objLink = 0;
- m_particule[i].objFather = 0;
- m_particule[i].trackRank = -1;
- m_triangle[i] = *triangle;
-
- m_totalInterface[t][sheet] ++;
-
- p1.x = m_triangle[i].triangle[0].x;
- p1.y = m_triangle[i].triangle[0].y;
- p1.z = m_triangle[i].triangle[0].z;
-
- p2.x = m_triangle[i].triangle[1].x;
- p2.y = m_triangle[i].triangle[1].y;
- p2.z = m_triangle[i].triangle[1].z;
-
- p3.x = m_triangle[i].triangle[2].x;
- p3.y = m_triangle[i].triangle[2].y;
- p3.z = m_triangle[i].triangle[2].z;
-
- l1 = Math::Distance(p1, p2);
- l2 = Math::Distance(p2, p3);
- l3 = Math::Distance(p3, p1);
- dx = fabs(Math::Min(l1, l2, l3))*0.5f;
- 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].x = p1.x;
- m_triangle[i].triangle[0].y = p1.y;
- m_triangle[i].triangle[0].z = p1.z;
-
- m_triangle[i].triangle[1].x = p2.x;
- m_triangle[i].triangle[1].y = p2.y;
- m_triangle[i].triangle[1].z = p2.z;
-
- m_triangle[i].triangle[2].x = p3.x;
- m_triangle[i].triangle[2].y = p3.y;
- m_triangle[i].triangle[2].z = p3.z;
-
- n = Math::Vector(0.0f, 0.0f, -1.0f);
-
- m_triangle[i].triangle[0].nx = n.x;
- m_triangle[i].triangle[0].ny = n.y;
- m_triangle[i].triangle[0].nz = n.z;
-
- m_triangle[i].triangle[1].nx = n.x;
- m_triangle[i].triangle[1].ny = n.y;
- m_triangle[i].triangle[1].nz = n.z;
-
- m_triangle[i].triangle[2].nx = n.x;
- m_triangle[i].triangle[2].ny = n.y;
- m_triangle[i].triangle[2].nz = n.z;
-
- if ( type == PARTIFRAG )
- {
- m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
- }
- return i | ((m_particule[i].uniqueStamp&0xffff)<<16);
- }
- }
-
- return -1;
-}
-
-// Creates a new particle being a part of object.
-// Returns the channel of the particle created or -1 on error.
-
-int CParticule::CreatePart(Math::Vector pos, Math::Vector speed,
- ParticuleType type,
- float duration, float mass, float weight,
- float windSensitivity, int sheet)
-{
- int i, j, t;
-
- t = 0;
- for ( j=0 ; j<MAXPARTICULE ; j++ )
- {
- i = MAXPARTICULE*t+j;
-
- if ( !m_particule[i].bUsed )
- {
- ZeroMemory(&m_particule[i], sizeof(Particule));
- m_particule[i].bUsed = true;
- m_particule[i].bRay = false;
- m_particule[i].uniqueStamp = m_uniqueStamp++;
- m_particule[i].sheet = sheet;
- m_particule[i].mass = mass;
- m_particule[i].weight = weight;
- m_particule[i].duration = duration;
- m_particule[i].pos = pos;
- m_particule[i].goal = pos;
- m_particule[i].speed = speed;
- m_particule[i].windSensitivity = windSensitivity;
- m_particule[i].zoom = 1.0f;
- m_particule[i].angle = 0.0f;
- m_particule[i].intensity = 1.0f;
- m_particule[i].type = type;
- m_particule[i].phase = PARPHSTART;
- m_particule[i].texSup.x = 0.0f;
- m_particule[i].texSup.y = 0.0f;
- m_particule[i].texInf.x = 0.0f;
- m_particule[i].texInf.y = 0.0f;
- m_particule[i].time = 0.0f;
- m_particule[i].phaseTime = 0.0f;
- m_particule[i].testTime = 0.0f;
- m_particule[i].trackRank = -1;
-
- m_totalInterface[t][sheet] ++;
-
- return i | ((m_particule[i].uniqueStamp&0xffff)<<16);
- }
- }
-
- return -1;
-}
-
-// Creates a new linear particle (radius).
-// Returns the channel of the particle created or -1 on error.
-
-int CParticule::CreateRay(Math::Vector pos, Math::Vector goal,
- ParticuleType type, Math::Point dim,
- float duration, int sheet)
-{
- int i, j, t;
-
- 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 ( j=0 ; j<MAXPARTICULE ; j++ )
- {
- i = MAXPARTICULE*t+j;
-
- if ( !m_particule[i].bUsed )
- {
- ZeroMemory(&m_particule[i], sizeof(Particule));
- m_particule[i].bUsed = true;
- m_particule[i].bRay = true;
- m_particule[i].uniqueStamp = m_uniqueStamp++;
- m_particule[i].sheet = sheet;
- m_particule[i].mass = 0.0f;
- m_particule[i].duration = duration;
- m_particule[i].pos = pos;
- m_particule[i].goal = goal;
- m_particule[i].speed = Math::Vector(0.0f, 0.0f, 0.0f);
- m_particule[i].windSensitivity = 0.0f;
- m_particule[i].dim = dim;
- m_particule[i].zoom = 1.0f;
- m_particule[i].angle = 0.0f;
- m_particule[i].intensity = 1.0f;
- m_particule[i].type = type;
- m_particule[i].phase = PARPHSTART;
- m_particule[i].texSup.x = 0.0f;
- m_particule[i].texSup.y = 0.0f;
- m_particule[i].texInf.x = 0.0f;
- m_particule[i].texInf.y = 0.0f;
- m_particule[i].time = 0.0f;
- m_particule[i].phaseTime = 0.0f;
- m_particule[i].testTime = 0.0f;
- m_particule[i].objLink = 0;
- m_particule[i].objFather = 0;
- m_particule[i].trackRank = -1;
-
- m_totalInterface[t][sheet] ++;
-
- return i | ((m_particule[i].uniqueStamp&0xffff)<<16);
- }
- }
-
- return -1;
-}
-
-// Creates a particle with a trail.
-// "length" is the length of the tail of drag (in seconds)!
-
-int CParticule::CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim,
- ParticuleType type, float duration, float mass,
- float length, float width)
-{
- int channel, rank, i;
-
- // Creates the normal particle.
- channel = CreateParticule(pos, speed, dim, type, duration, mass, 0.0f, 0);
- if ( channel == -1 ) return -1;
-
- // Seeks a streak free.
- for ( i=0 ; i<MAXTRACK ; i++ )
- {
- if ( !m_track[i].bUsed ) // free?
- {
- rank = channel;
- if ( !CheckChannel(rank) ) return -1;
- m_particule[rank].trackRank = i;
-
- m_track[i].bUsed = 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].used = 1;
- m_track[i].head = 0;
- m_track[i].pos[0] = pos;
- break;
- }
- }
-
- return channel;
-}
-
-// Creates a tire mark.
-
-void CParticule::CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2,
- const Math::Vector &p3, const Math::Vector &p4,
- ParticuleType type)
-{
- int i, max;
-
-//? max = (int)(m_engine->RetWheelTraceQuantity()*MAXWHEELTRACE);
- max = MAXWHEELTRACE;
- 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 == 0 )
- {
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- }
-
- m_terrain->MoveOnFloor(m_wheelTrace[i].pos[0]);
- m_wheelTrace[i].pos[0].y += 0.2f; // just above the ground
-
- m_terrain->MoveOnFloor(m_wheelTrace[i].pos[1]);
- m_wheelTrace[i].pos[1].y += 0.2f; // just above the ground
-
- m_terrain->MoveOnFloor(m_wheelTrace[i].pos[2]);
- m_wheelTrace[i].pos[2].y += 0.2f; // just above the ground
-
- m_terrain->MoveOnFloor(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;
- }
-}
-
-
-// Check a channel number.
-// Adapts the channel so it can be used as an offset in m_particule.
-
-bool CParticule::CheckChannel(int &channel)
-{
- int uniqueStamp;
-
- uniqueStamp = (channel>>16)&0xffff;
- channel &= 0xffff;
-
- if ( channel < 0 ) return false;
- if ( channel >= MAXPARTICULE*MAXPARTITYPE ) return false;
-#if 0
- if ( !m_particule[channel].bUsed ) return false;
-
- if ( m_particule[channel].uniqueStamp != uniqueStamp ) return false;
-#else
- if ( !m_particule[channel].bUsed )
- {
- OutputDebugString("CheckChannel bUsed=false !\n");
- return false;
- }
-
- if ( m_particule[channel].uniqueStamp != uniqueStamp )
- {
- OutputDebugString("CheckChannel uniqueStamp !\n");
- return false;
- }
-#endif
-
- return true;
-}
-
-// Removes a particle after his rank.
-
-void CParticule::DeleteRank(int rank)
-{
- int i;
-
- if ( m_totalInterface[rank/MAXPARTICULE][m_particule[rank].sheet] > 0 )
- {
- m_totalInterface[rank/MAXPARTICULE][m_particule[rank].sheet] --;
- }
-
- i = m_particule[rank].trackRank;
- if ( i != -1 ) // drag associated?
- {
- m_track[i].bUsed = false; // frees the drag
- }
-
- m_particule[rank].bUsed = false;
-}
-
-// Removes all particles of a given type.
-
-void CParticule::DeleteParticule(ParticuleType type)
-{
- int i;
-
- for ( i=0 ; i<MAXPARTICULE*MAXPARTITYPE ; i++ )
- {
- if ( !m_particule[i].bUsed ) continue;
- if ( m_particule[i].type != type ) continue;
-
- DeleteRank(i);
- }
-}
-
-// Removes all particles of a given channel.
-
-void CParticule::DeleteParticule(int channel)
-{
- int i;
-
- if ( !CheckChannel(channel) ) return;
-
- if ( m_totalInterface[channel/MAXPARTICULE][m_particule[channel].sheet] > 0 )
- {
- m_totalInterface[channel/MAXPARTICULE][m_particule[channel].sheet] --;
- }
-
- i = m_particule[channel].trackRank;
- if ( i != -1 ) // drag associated?
- {
- m_track[i].bUsed = false; // frees the drag
- }
-
- m_particule[channel].bUsed = false;
-}
-
-
-// Specifies the object to which the particle is bound.
-
-void CParticule::SetObjectLink(int channel, CObject *object)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].objLink = object;
-}
-
-// Specifies the parent object that created the particle.
-
-void CParticule::SetObjectFather(int channel, CObject *object)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].objFather = object;
-}
-
-void CParticule::SetPosition(int channel, Math::Vector pos)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].pos = pos;
-}
-
-void CParticule::SetDimension(int channel, Math::Point dim)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].dim = dim;
-}
-
-void CParticule::SetZoom(int channel, float zoom)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].zoom = zoom;
-}
-
-void CParticule::SetAngle(int channel, float angle)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].angle = angle;
-}
-
-void CParticule::SetIntensity(int channel, float intensity)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].intensity = intensity;
-}
-
-void CParticule::SetParam(int channel, Math::Vector pos, Math::Point dim, float zoom,
- float angle, float intensity)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].pos = pos;
- m_particule[channel].dim = dim;
- m_particule[channel].zoom = zoom;
- m_particule[channel].angle = angle;
- m_particule[channel].intensity = intensity;
-}
-
-void CParticule::SetPhase(int channel, ParticulePhase phase, float duration)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].phase = phase;
- m_particule[channel].duration = duration;
- m_particule[channel].phaseTime = m_particule[channel].time;
-}
-
-// Returns the position of the particle.
-
-bool CParticule::GetPosition(int channel, Math::Vector &pos)
-{
- if ( !CheckChannel(channel) ) return false;
- pos = m_particule[channel].pos;
- return true;
-}
-
-
-// Indicates whether a sheet evolves or not.
-
-void CParticule::SetFrameUpdate(int sheet, bool bUpdate)
-{
- m_bFrameUpdate[sheet] = bUpdate;
-}
-
-// Makes evolve all the particles.
-
-void CParticule::FrameParticule(float rTime)
-{
- CObject* object;
- Math::Vector eye, pos, speed, wind;
- Math::Point ts, ti, dim;
- bool bPause;
- float progress, dp, h, duration, mass, amplitude;
- int i, j, r, total;
-
- if ( m_main == 0 )
- {
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- }
-
- bPause = ( m_engine->RetPause() && !m_main->RetInfoLock() );
-
- if ( m_terrain == 0 )
- {
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- }
- if ( m_water == 0 )
- {
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
- }
-
- if ( !bPause )
- {
- m_lastTimeGunDel += rTime;
- m_absTime += rTime;
- }
-
- wind = m_terrain->RetWind();
- eye = m_engine->RetEyePt();
-
- for ( i=0 ; i<MAXPARTICULE*MAXPARTITYPE ; i++ )
- {
- if ( !m_particule[i].bUsed ) continue;
- if ( !m_bFrameUpdate[m_particule[i].sheet] ) continue;
-
- if ( m_particule[i].type != PARTISHOW )
- {
- if ( bPause && m_particule[i].sheet != SH_INTERFACE ) continue;
- }
-
- if ( m_particule[i].type != PARTIQUARTZ )
- {
- m_particule[i].pos += m_particule[i].speed*rTime;
- }
-
- if ( m_particule[i].sheet == SH_WORLD )
- {
- h = rTime*m_particule[i].windSensitivity*Math::Rand()*2.0f;
- m_particule[i].pos += wind*h;
- }
-
- progress = (m_particule[i].time-m_particule[i].phaseTime)/m_particule[i].duration;
-
- // Manages the particles with mass that bounce.
- if ( m_particule[i].mass != 0.0f &&
- m_particule[i].type != PARTIQUARTZ )
- {
- m_particule[i].speed.y -= m_particule[i].mass*rTime;
-
- if ( m_particule[i].sheet == SH_INTERFACE )
- {
- h = 0.0f;
- }
- else
- {
- h = m_terrain->RetFloorLevel(m_particule[i].pos, true);
- }
- h += m_particule[i].dim.y*0.75f;
- if ( m_particule[i].pos.y < h ) // impact with the ground?
- {
- if ( m_particule[i].type == PARTIPART &&
- m_particule[i].weight > 3.0f && // heavy enough?
- m_particule[i].bounce < 3 )
- {
- amplitude = m_particule[i].weight*0.1f;
- amplitude *= 1.0f-0.3f*m_particule[i].bounce;
- if ( amplitude > 1.0f ) amplitude = 1.0f;
- if ( amplitude > 0.0f )
- {
- Play(SOUND_BOUM, m_particule[i].pos, amplitude);
- }
- }
-
- if ( m_particule[i].bounce < 3 )
- {
- m_particule[i].pos.y = h;
- m_particule[i].speed.y *= -0.4f;
- m_particule[i].speed.x *= 0.4f;
- m_particule[i].speed.z *= 0.4f;
- m_particule[i].bounce ++; // more impact
- }
- else // disappears after 3 bounces?
- {
- if ( m_particule[i].pos.y < h-10.0f ||
- m_particule[i].time >= 20.0f )
- {
- DeleteRank(i);
- continue;
- }
- }
- }
- }
-
- // Manages drag associated.
- r = m_particule[i].trackRank;
- if ( r != -1 ) // drag exists?
- {
- if ( TrackMove(r, m_particule[i].pos, progress) )
- {
- DeleteRank(i);
- continue;
- }
-
- m_track[r].bDrawParticule = (progress < 1.0f);
- }
-
- if ( m_particule[i].type == PARTITRACK1 ) // explosion technique?
- {
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.375f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTITRACK2 ) // spray blue?
- {
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.500f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTITRACK3 ) // spider?
- {
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.500f;
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTITRACK4 ) // insect explosion?
- {
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.625f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTITRACK5 ) // derrick?
- {
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.750f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTITRACK6 ) // reset in/out?
- {
- ts.x = 0.0f;
- ts.y = 0.0f;
- ti.x = 0.0f;
- ti.y = 0.0f;
- }
-
- if ( m_particule[i].type == PARTITRACK7 || // win-1 ?
- m_particule[i].type == PARTITRACK8 || // win-2 ?
- m_particule[i].type == PARTITRACK9 || // win-3 ?
- m_particule[i].type == PARTITRACK10 ) // win-4 ?
- {
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.25f*(m_particule[i].type-PARTITRACK7);
- ts.y = 0.25f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTITRACK11 ) // phazer shot?
- {
- object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
- m_particule[i].goal = m_particule[i].pos;
- if ( object != 0 )
- {
- if ( object->RetType() == OBJECT_MOTHER )
- {
- object->ExploObject(EXPLO_BOUM, 0.1f);
- }
- else
- {
- object->ExploObject(EXPLO_BOUM, 0.0f, RetDecay(object->RetType()));
- }
- }
-
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.375f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTITRACK12 ) // drag reactor?
- {
- m_particule[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_particule[i].type == PARTIMOTOR )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-progress;
- m_particule[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_particule[i].type == PARTIBLITZ )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-progress;
- m_particule[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_particule[i].type == PARTICRASH )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
-//? m_particule[i].intensity = 1.0f-progress;
- if ( progress < 0.25f )
- {
- m_particule[i].zoom = progress/0.25f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f;
- }
-
-//? ts.x = 0.250f;
- ts.x = 0.000f;
-//? ts.x = 0.375f;
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIVAPOR )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].intensity = 1.0f-progress;
- m_particule[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_particule[i].type == PARTIGAS )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[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_particule[i].type == PARTIBASE )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f+progress*7.0f;
- m_particule[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_particule[i].type == PARTIFIRE ||
- m_particule[i].type == PARTIFIREZ )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( m_particule[i].type == PARTIFIRE )
- {
- m_particule[i].zoom = 1.0f-progress;
- }
- else
- {
- m_particule[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_particule[i].type == PARTIGUN1 ) // fireball shot?
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( m_particule[i].testTime >= 0.1f )
- {
- m_particule[i].testTime = 0.0f;
-
- if ( m_terrain->RetFloorHeight(m_particule[i].pos, true) < -2.0f )
- {
- m_exploGunCounter ++;
-
- if ( m_exploGunCounter%2 == 0 )
- {
- pos = m_particule[i].goal;
- m_terrain->MoveOnFloor(pos, true);
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 0.0f;
- dim.x = Math::Rand()*6.0f+6.0f;
- dim.y = dim.x;
- duration = Math::Rand()*1.0f+1.0f;
- mass = 0.0f;
- CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
-
- pos.y += 1.0f;
- total = (int)(2.0f*m_engine->RetParticuleDensity());
- for ( 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;
- CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
- }
- }
-
- if ( m_exploGunCounter%4 == 0 )
- {
- Play(SOUND_EXPLOg1, pos, 0.5f);
- }
-
- DeleteRank(i);
- continue;
- }
-
- object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
- m_particule[i].goal = m_particule[i].pos;
- if ( object != 0 )
- {
- object->ExploObject(EXPLO_BURN, 0.0f, RetDecay(object->RetType()));
-
- m_exploGunCounter ++;
-
- if ( m_exploGunCounter%2 == 0 )
- {
- pos = m_particule[i].pos;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 0.0f;
- dim.x = Math::Rand()*6.0f+6.0f;
- dim.y = dim.x;
- duration = Math::Rand()*1.0f+1.0f;
- mass = 0.0f;
- CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
-
- pos.y += 1.0f;
- total = (int)(2.0f*m_engine->RetParticuleDensity());
- for ( 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;
- CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
- }
- }
-
- if ( m_exploGunCounter%4 == 0 )
- {
- Play(SOUND_EXPLOg1, pos, 0.5f);
- }
-
- DeleteRank(i);
- continue;
- }
- }
-
- m_particule[i].angle -= rTime*Math::PI*8.0f;
- m_particule[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_particule[i].type == PARTIGUN2 ) // ant shot?
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( m_particule[i].testTime >= 0.2f )
- {
- m_particule[i].testTime = 0.0f;
- object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
- m_particule[i].goal = m_particule[i].pos;
- if ( object != 0 )
- {
- if ( object->RetShieldRadius() > 0.0f ) // protected by shield?
- {
- CreateParticule(m_particule[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_particule[i].pos, 1.0f);
- }
- DeleteRank(i);
- continue;
- }
- else
- {
- if ( object->RetType() != OBJECT_HUMAN )
- {
- Play(SOUND_TOUCH, m_particule[i].pos, 1.0f);
- }
- object->ExploObject(EXPLO_BOUM, 0.0f); // starts explosion
- }
- }
- }
-
- m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
- m_particule[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_particule[i].type == PARTIGUN3 ) // spider suicides?
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( m_particule[i].testTime >= 0.2f )
- {
- m_particule[i].testTime = 0.0f;
- object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
- m_particule[i].goal = m_particule[i].pos;
- if ( object != 0 )
- {
- if ( object->RetShieldRadius() > 0.0f )
- {
- CreateParticule(m_particule[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_particule[i].pos, 1.0f);
- }
- DeleteRank(i);
- continue;
- }
- else
- {
- object->ExploObject(EXPLO_BURN, 1.0f); // starts explosion
- }
- }
- }
-
-//? ts.x = 0.875f;
-//? ts.y = 0.750f;
- ts.x = 0.500f;
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIGUN4 ) // orgaball shot?
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( m_particule[i].testTime >= 0.1f )
- {
- m_particule[i].testTime = 0.0f;
-
- if ( m_terrain->RetFloorHeight(m_particule[i].pos, true) < -2.0f )
- {
- m_exploGunCounter ++;
-
- if ( m_exploGunCounter%2 == 0 )
- {
- pos = m_particule[i].goal;
- m_terrain->MoveOnFloor(pos, true);
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 0.0f;
- dim.x = Math::Rand()*4.0f+2.0f;
- dim.y = dim.x;
- duration = Math::Rand()*0.7f+0.7f;
- mass = 0.0f;
- CreateParticule(pos, speed, dim, PARTIEXPLOG2, duration, mass, 1.0f);
- }
-
- if ( m_exploGunCounter%4 == 0 )
- {
- Play(SOUND_EXPLOg2, pos, 0.5f);
- }
-
- DeleteRank(i);
- continue;
- }
-
- object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
- m_particule[i].goal = m_particule[i].pos;
- if ( object != 0 )
- {
- object->ExploObject(EXPLO_BOUM, 0.0f, RetDecay(object->RetType()));
-
- m_exploGunCounter ++;
-
- if ( m_exploGunCounter%2 == 0 )
- {
- pos = m_particule[i].pos;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 0.0f;
- dim.x = Math::Rand()*4.0f+2.0f;
- dim.y = dim.x;
- duration = Math::Rand()*0.7f+0.7f;
- mass = 0.0f;
- CreateParticule(pos, speed, dim, PARTIEXPLOG2, duration, mass, 1.0f);
- }
-
- if ( m_exploGunCounter%4 == 0 )
- {
- Play(SOUND_EXPLOg2, pos, 0.5f);
- }
-
- DeleteRank(i);
- continue;
- }
- }
-
- m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
- m_particule[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_particule[i].type == PARTIFLIC )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 0.1f+progress;
- m_particule[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_particule[i].type == PARTISHOW )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.5f ) m_particule[i].intensity = progress/0.5f;
- else m_particule[i].intensity = 2.0f-progress/0.5f;
- m_particule[i].zoom = 1.0f-progress*0.8f;
- m_particule[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_particule[i].type == PARTICHOC )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 0.1f+progress;
- m_particule[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_particule[i].type == PARTIGFLAT )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 0.1f+progress;
- m_particule[i].intensity = 1.0f-progress;
- m_particule[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_particule[i].type == PARTILIMIT1 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f;
- m_particule[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_particule[i].type == PARTILIMIT2 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f;
- m_particule[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_particule[i].type == PARTILIMIT3 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f;
- m_particule[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_particule[i].type == PARTIFOG0 )
- {
- m_particule[i].zoom = progress;
- m_particule[i].intensity = 0.3f+sinf(progress)*0.15f;
- m_particule[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_particule[i].type == PARTIFOG1 )
- {
- m_particule[i].zoom = progress;
- m_particule[i].intensity = 0.3f+sinf(progress)*0.15f;
- m_particule[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_particule[i].type == PARTIFOG2 )
- {
- m_particule[i].zoom = progress;
- m_particule[i].intensity = 0.6f+sinf(progress)*0.15f;
- m_particule[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_particule[i].type == PARTIFOG3 )
- {
- m_particule[i].zoom = progress;
- m_particule[i].intensity = 0.6f+sinf(progress)*0.15f;
- m_particule[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_particule[i].type == PARTIFOG4 )
- {
- m_particule[i].zoom = progress;
- m_particule[i].intensity = 0.5f+sinf(progress)*0.2f;
- m_particule[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_particule[i].type == PARTIFOG5 )
- {
- m_particule[i].zoom = progress;
- m_particule[i].intensity = 0.5f+sinf(progress)*0.2f;
- m_particule[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_particule[i].type == PARTIFOG6 )
- {
- m_particule[i].zoom = progress;
- m_particule[i].intensity = 0.5f+sinf(progress)*0.2f;
- m_particule[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_particule[i].type == PARTIFOG7 )
- {
- m_particule[i].zoom = progress;
- m_particule[i].intensity = 0.5f+sinf(progress)*0.2f;
- m_particule[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_particule[i].type >= PARTIFOG0 &&
- m_particule[i].type <= PARTIFOG9 )
- {
- h = 10.0f;
-
- if ( m_particule[i].pos.y >= eye.y &&
- m_particule[i].pos.y < eye.y+h )
- {
- m_particule[i].intensity *= (m_particule[i].pos.y-eye.y)/h;
- }
- if ( m_particule[i].pos.y > eye.y-h &&
- m_particule[i].pos.y < eye.y )
- {
- m_particule[i].intensity *= (eye.y-m_particule[i].pos.y)/h;
- }
- }
-
- if ( m_particule[i].type == PARTIEXPLOT ||
- m_particule[i].type == PARTIEXPLOO )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-progress/2.0f;
- m_particule[i].intensity = 1.0f-progress;
-
- if ( m_particule[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_particule[i].type == PARTIEXPLOG1 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[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_particule[i].type == PARTIEXPLOG2 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[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_particule[i].type == PARTIFLAME )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-progress/2.0f;
- if ( progress < 0.5f )
- {
- m_particule[i].intensity = progress/0.5f;
- }
- else
- {
- m_particule[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_particule[i].type == PARTIBUBBLE )
- {
- if ( progress >= 1.0f ||
- m_particule[i].pos.y >= m_water->RetLevel() )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-progress/2.0f;
- m_particule[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_particule[i].type == PARTISMOKE1 ||
- m_particule[i].type == PARTISMOKE2 ||
- m_particule[i].type == PARTISMOKE3 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.25f )
- {
- m_particule[i].zoom = progress/0.25f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f;
- }
-
- ts.x = 0.500f+0.125f*(m_particule[i].type-PARTISMOKE1);
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIBLOOD )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[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_particule[i].type == PARTIBLOODM )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[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_particule[i].type == PARTIVIRUS1 ||
- m_particule[i].type == PARTIVIRUS2 ||
- m_particule[i].type == PARTIVIRUS3 ||
- m_particule[i].type == PARTIVIRUS4 ||
- m_particule[i].type == PARTIVIRUS5 ||
- m_particule[i].type == PARTIVIRUS6 ||
- m_particule[i].type == PARTIVIRUS7 ||
- m_particule[i].type == PARTIVIRUS8 ||
- m_particule[i].type == PARTIVIRUS9 ||
- m_particule[i].type == PARTIVIRUS10 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.25f )
- {
- m_particule[i].zoom = progress/0.25f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f;
- }
- m_particule[i].angle += rTime*Math::PI*1.0f;
-
- if ( m_particule[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_particule[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_particule[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_particule[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_particule[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_particule[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_particule[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_particule[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_particule[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_particule[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_particule[i].type == PARTIBLUE )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[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_particule[i].type == PARTIROOT )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.25f )
- {
- m_particule[i].zoom = progress/0.25f;
- }
- else
- {
- m_particule[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_particule[i].type == PARTIRECOVER )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.25f )
- {
- m_particule[i].zoom = progress/0.25f;
- }
- else
- {
- m_particule[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_particule[i].type == PARTIEJECT )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f+powf(progress, 2.0f)*5.0f;
- m_particule[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_particule[i].type == PARTISCRAPS )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[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_particule[i].type == PARTIFRAG )
- {
- m_particule[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_particule[i].type == PARTIPART )
- {
- ts.x = 0.0f;
- ts.y = 0.0f;
- ti.x = 0.0f;
- ti.y = 0.0f;
- }
-
- if ( m_particule[i].type == PARTIQUEUE )
- {
- if ( m_particule[i].testTime >= 0.05f )
- {
- m_particule[i].testTime = 0.0f;
-
- Math::Vector pos, speed;
- Math::Point dim;
-
- pos = m_particule[i].pos;
-//? speed = -m_particule[i].speed*0.5f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 1.0f*(Math::Rand()*0.8f+0.6f);
- dim.y = dim.x;
- CreateParticule(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_particule[i].type == PARTIORGANIC1 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
-
- pos = m_particule[i].pos;
- dim.x = m_particule[i].dim.x/4.0f;
- dim.y = dim.x;
- duration = m_particule[i].duration;
- mass = m_particule[i].mass;
- total = (int)(10.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<total ; i++ )
- {
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.y = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- CreateParticule(pos, speed, dim, PARTIORGANIC2, duration, mass);
- }
- total = (int)(5.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<total ; i++ )
- {
- 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_particule[i].zoom = (m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.125f;
- ts.y = 0.875f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIORGANIC2 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.125f;
- ts.y = 0.875f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIGLINT )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress > 0.5f )
- {
-//? m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration/2.0f);
- m_particule[i].zoom = 1.0f-(progress-0.5f)*2.0f;
- }
- m_particule[i].angle = m_particule[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_particule[i].type == PARTIGLINTb )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress > 0.5f )
- {
- m_particule[i].zoom = 1.0f-(progress-0.5f)*2.0f;
- }
- m_particule[i].angle = m_particule[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_particule[i].type == PARTIGLINTr )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress > 0.5f )
- {
- m_particule[i].zoom = 1.0f-(progress-0.5f)*2.0f;
- }
- m_particule[i].angle = m_particule[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_particule[i].type >= PARTILENS1 &&
- m_particule[i].type <= PARTILENS4 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.5f )
- {
- m_particule[i].zoom = progress*2.0f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.5f)*2.0f;
- }
-//? m_particule[i].angle = m_particule[i].time*Math::PI;
-
- ts.x = 0.25f*(m_particule[i].type-PARTILENS1);
- ts.y = 0.25f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTICONTROL )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.3f )
- {
- m_particule[i].zoom = progress/0.3f;
- }
- else
- {
- m_particule[i].zoom = 1.0f;
- m_particule[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_particule[i].type == PARTIGUNDEL )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress > 0.5f )
- {
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration/2.0f);
- }
- m_particule[i].angle = m_particule[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_particule[i].type == PARTIQUARTZ )
- {
- if ( progress >= 1.0f )
- {
- m_particule[i].time = 0.0f;
- m_particule[i].duration = 0.5f+Math::Rand()*2.0f;
- m_particule[i].pos.x = m_particule[i].speed.x + (Math::Rand()-0.5f)*m_particule[i].mass;
- m_particule[i].pos.y = m_particule[i].speed.y + (Math::Rand()-0.5f)*m_particule[i].mass;
- m_particule[i].pos.z = m_particule[i].speed.z + (Math::Rand()-0.5f)*m_particule[i].mass;
- m_particule[i].dim.x = 0.5f+Math::Rand()*1.5f;
- m_particule[i].dim.y = m_particule[i].dim.x;
- progress = 0.0f;
- }
-
- if ( progress < 0.2f )
- {
- m_particule[i].zoom = progress/0.2f;
- m_particule[i].intensity = 1.0f;
- }
- else
- {
- m_particule[i].zoom = 1.0f;
- m_particule[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_particule[i].type == PARTITOTO )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-progress;
- if ( progress < 0.15f )
- {
- m_particule[i].intensity = progress/0.15f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.15f)/0.85f;
- }
- m_particule[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_particule[i].type == PARTIERROR )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = progress*1.0f;
- m_particule[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_particule[i].type == PARTIWARNING )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = progress*1.0f;
- m_particule[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_particule[i].type == PARTIINFO )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = progress*1.0f;
- m_particule[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_particule[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_particule[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_particule[i].type == PARTISPHERE0 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = progress*m_particule[i].dim.x;
-//? m_particule[i].intensity = 1.0f-progress;
- if ( progress < 0.65f )
- {
- m_particule[i].intensity = progress/0.65f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.65f)/0.35f;
- }
- m_particule[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_particule[i].type == PARTISPHERE1 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.30f )
- {
- m_particule[i].intensity = progress/0.30f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.30f)/0.70f;
- }
- m_particule[i].zoom = progress*m_particule[i].dim.x;
- m_particule[i].angle = m_particule[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_particule[i].type == PARTISPHERE2 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.20f )
- {
- m_particule[i].intensity = 1.0f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.20f)/0.80f;
- }
- m_particule[i].zoom = progress*m_particule[i].dim.x;
- m_particule[i].angle = m_particule[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_particule[i].type == PARTISPHERE3 )
- {
- if ( m_particule[i].phase == PARPHEND &&
- progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( m_particule[i].phase == PARPHSTART )
- {
- m_particule[i].intensity = progress;
- if ( m_particule[i].intensity > 1.0f )
- {
- m_particule[i].intensity = 1.0f;
- }
- }
-
- if ( m_particule[i].phase == PARPHEND )
- {
- m_particule[i].intensity = 1.0f-progress;
- }
-
- m_particule[i].zoom = m_particule[i].dim.x;
- m_particule[i].angle = m_particule[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_particule[i].type == PARTISPHERE4 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = progress*m_particule[i].dim.x;
- if ( progress < 0.65f )
- {
- m_particule[i].intensity = progress/0.65f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.65f)/0.35f;
- }
- m_particule[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_particule[i].type == PARTISPHERE5 )
- {
- m_particule[i].intensity = 0.7f+sinf(progress)*0.3f;
- m_particule[i].zoom = m_particule[i].dim.x*(1.0f+sinf(progress*0.7f)*0.01f);
- m_particule[i].angle = m_particule[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_particule[i].type == PARTISPHERE6 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = (1.0f-progress)*m_particule[i].dim.x;
- m_particule[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_particule[i].type == PARTIPLOUF0 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = progress;
-#if 0
- if ( progress <= 0.5f )
- {
- m_particule[i].intensity = 1.0f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.5f)/0.5f;
- }
-#else
-//? m_particule[i].intensity = 1.0f;
- m_particule[i].intensity = 1.0f-progress;
-#endif
-
- ts.x = 0.50f;
- ts.y = 0.50f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTIDROP )
- {
- if ( progress >= 1.0f ||
- m_particule[i].pos.y < m_water->RetLevel() )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-progress;
- m_particule[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_particule[i].type == PARTIWATER )
- {
- if ( progress >= 1.0f ||
- m_particule[i].pos.y < m_water->RetLevel() )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[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_particule[i].type == PARTIRAY1 ) // rayon tour ?
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( m_particule[i].testTime >= 0.2f )
- {
- m_particule[i].testTime = 0.0f;
- object = SearchObjectRay(m_particule[i].pos, m_particule[i].goal,
- m_particule[i].type, m_particule[i].objFather);
- if ( object != 0 )
- {
- 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_particule[i].type == PARTIRAY2 ||
- m_particule[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;
- }
-
- dp = (1.0f/256.0f)/2.0f;
- m_particule[i].texSup.x = ts.x+dp;
- m_particule[i].texSup.y = ts.y+dp;
- m_particule[i].texInf.x = ti.x-dp;
- m_particule[i].texInf.y = ti.y-dp;
- m_particule[i].time += rTime;
- m_particule[i].testTime += rTime;
- }
-}
-
-
-// Moves a drag.
-// Returns true if the drag is finished.
-
-bool CParticule::TrackMove(int i, Math::Vector pos, float progress)
-{
- Math::Vector last;
- int h, hh;
-
- if ( i < 0 || i >= MAXTRACK ) return true;
- if ( m_track[i].bUsed == false ) return true;
-
- if ( progress < 1.0f ) // particle exists?
- {
- h = m_track[i].head;
-
- if ( m_track[i].used == 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].used < MAXTRACKLEN ) m_track[i].used ++;
- }
- else
- {
- 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;
- m_track[i].intensity = 1.0f-progress;
- }
- else // mort lente de la tra�n�e ?
- {
-//? m_track[i].intensity = 1.0f-(progress-1.0f)/(m_track[i].step*MAXTRACKLEN);
- m_track[i].intensity = 0.0f;
- }
-
- return (m_track[i].intensity <= 0.0f);
-}
-
-// Draws a drag.
-
-void CParticule::TrackDraw(int i, ParticuleType type)
-{
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Vector corner[4], p1, p2, p, n, eye;
- Math::Matrix matrix;
- Math::Point texInf, texSup, rot;
- float lTotal, f1, f2, a;
- int counter, h;
-
- // Calculates the total length memorized.
- lTotal = 0.0f;
- h = m_track[i].head;
- for ( counter=0 ; counter<m_track[i].used-1 ; counter++ )
- {
- lTotal += m_track[i].len[h];
- h --; if ( h < 0 ) h = MAXTRACKLEN-1;
- }
-
- matrix.LoadIdentity();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- 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;
- p1 = m_track[i].pos[h];
- f1 = m_track[i].intensity;
-
- eye = m_engine->RetEyePt();
- a = Math::RotateAngle(eye.x-p1.x, eye.z-p1.z);
-
- for ( counter=0 ; counter<m_track[i].used-1 ; counter++ )
- {
- f2 = f1-(m_track[i].len[h]/lTotal);
- if ( f2 < 0.0f ) f2 = 0.0f;
- h --; if ( h < 0 ) h = MAXTRACKLEN-1;
- p2 = m_track[i].pos[h];
-
- n = Normalize(p1-eye);
-
- 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] = D3DVERTEX2(corner[1], n, texSup.x, texSup.y);
- vertex[1] = D3DVERTEX2(corner[0], n, texInf.x, texSup.y);
- vertex[2] = D3DVERTEX2(corner[3], n, texSup.x, texInf.y);
- vertex[3] = D3DVERTEX2(corner[2], n, texInf.x, texInf.y);
- }
- else
- {
- vertex[0] = D3DVERTEX2(corner[0], n, texSup.x, texSup.y);
- vertex[1] = D3DVERTEX2(corner[1], n, texInf.x, texSup.y);
- vertex[2] = D3DVERTEX2(corner[2], n, texSup.x, texInf.y);
- vertex[3] = D3DVERTEX2(corner[3], n, texInf.x, texInf.y);
- }
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-
- if ( f2 < 0.0f ) break;
- f1 = f2;
- p1 = p2;
- }
-}
-
-// Draws a triangular particle.
-
-void CParticule::DrawParticuleTriangle(int i)
-{
- CObject* object;
- Math::Matrix matrix;
- Math::Vector eye, pos, angle;
-
- if ( m_particule[i].zoom == 0.0f ) return;
-
- eye = m_engine->RetEyePt();
- pos = m_particule[i].pos;
-
- object = m_particule[i].objLink;
- if ( object != 0 )
- {
- pos += object->RetPosition(0);
- }
-
- 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_particule[i].angle;
-
- Math::LoadRotationXZYMatrix(matrix, angle);
- matrix.Set(1, 4, pos.x);
- matrix.Set(2, 4, pos.y);
- matrix.Set(3, 4, pos.z);
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_VERTEX2,
- m_triangle[i].triangle, 3, NULL);
- m_engine->AddStatisticTriangle(1);
-}
-
-// Draw a normal particle.
-
-void CParticule::DrawParticuleNorm(int i)
-{
- CObject* object;
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Matrix matrix;
- Math::Vector corner[4], eye, pos, n, angle;
- Math::Point dim;
- float zoom;
-
- zoom = m_particule[i].zoom;
- if ( !m_engine->RetStateColor() && m_particule[i].intensity < 0.5f )
- {
- zoom *= m_particule[i].intensity/0.5f;
- }
-
- if ( zoom == 0.0f ) return;
- if ( m_particule[i].intensity == 0.0f ) return;
-
- if ( m_particule[i].sheet == SH_INTERFACE )
- {
- pos = m_particule[i].pos;
-
- n = Math::Vector(0.0f, 0.0f, -1.0f);
-
- dim.x = m_particule[i].dim.x * zoom;
- dim.y = m_particule[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] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y);
- vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y);
- vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y);
- vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
- }
- else
- {
- eye = m_engine->RetEyePt();
- pos = m_particule[i].pos;
-
- object = m_particule[i].objLink;
- if ( object != 0 )
- {
- pos += object->RetPosition(0);
- }
-
- 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_particule[i].angle;
-
- Math::LoadRotationXZYMatrix(matrix, angle);
- matrix.Set(1, 4, pos.x);
- matrix.Set(2, 4, pos.y);
- matrix.Set(3, 4, pos.z);
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- n = Math::Vector(0.0f, 0.0f, -1.0f);
-
- dim.x = m_particule[i].dim.x * zoom;
- dim.y = m_particule[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] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y);
- vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y);
- vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y);
- vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
- }
-}
-
-// Draw a particle flat (horizontal).
-
-void CParticule::DrawParticuleFlat(int i)
-{
- CObject* object;
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Matrix matrix;
- Math::Vector corner[4], pos, n, angle, eye;
- Math::Point dim;
-
- if ( m_particule[i].zoom == 0.0f ) return;
- if ( m_particule[i].intensity == 0.0f ) return;
-
- pos = m_particule[i].pos;
-
- object = m_particule[i].objLink;
- if ( object != 0 )
- {
- pos += object->RetPosition(0);
- }
-
- angle.x = Math::PI/2.0f;
- angle.y = 0.0f;
- angle.z = m_particule[i].angle;
-
-#if 0
- if ( m_engine->RetRankView() == 1 ) // underwater?
- {
- angle.x = -Math::PI/2.0f;
- pos.y -= 1.0f;
- }
-#else
- if ( m_engine->RetRankView() == 1 ) // underwater?
- {
- pos.y -= 1.0f;
- }
-
- eye = m_engine->RetEyePt();
- if ( pos.y > eye.y ) // seen from below?
- {
- angle.x = -Math::PI/2.0f;
- }
-#endif
-
- Math::LoadRotationXZYMatrix(matrix, angle);
- matrix.Set(1, 4, pos.x);
- matrix.Set(2, 4, pos.y);
- matrix.Set(3, 4, pos.z);
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- n = Math::Vector(0.0f, 0.0f, -1.0f);
-
- dim.x = m_particule[i].dim.x * m_particule[i].zoom;
- dim.y = m_particule[i].dim.y * m_particule[i].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] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y);
- vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y);
- vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y);
- vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-}
-
-// Draw a particle to a flat sheet of fog.
-
-void CParticule::DrawParticuleFog(int i)
-{
- CObject* object;
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Matrix matrix;
- Math::Vector corner[4], pos, n, angle, eye;
- Math::Point dim, zoom;
-
- if ( !m_engine->RetFog() ) return;
- if ( m_particule[i].intensity == 0.0f ) return;
-
- pos = m_particule[i].pos;
-
- dim.x = m_particule[i].dim.x;
- dim.y = m_particule[i].dim.y;
-
- if ( m_particule[i].type == PARTIFOG0 ||
- m_particule[i].type == PARTIFOG2 ||
- m_particule[i].type == PARTIFOG4 ||
- m_particule[i].type == PARTIFOG6 )
- {
-//? pos.x += sinf(m_particule[i].zoom*1.2f)*dim.x*0.1f;
-//? pos.y += cosf(m_particule[i].zoom*1.5f)*dim.y*0.1f;
- zoom.x = 1.0f+sinf(m_particule[i].zoom*2.0f)/6.0f;
- zoom.y = 1.0f+cosf(m_particule[i].zoom*2.7f)/6.0f;
- }
- if ( m_particule[i].type == PARTIFOG1 ||
- m_particule[i].type == PARTIFOG3 ||
- m_particule[i].type == PARTIFOG5 ||
- m_particule[i].type == PARTIFOG7 )
- {
-//? pos.x += sinf(m_particule[i].zoom*1.0f)*dim.x*0.1f;
-//? pos.y += cosf(m_particule[i].zoom*1.3f)*dim.y*0.1f;
- zoom.x = 1.0f+sinf(m_particule[i].zoom*3.0f)/6.0f;
- zoom.y = 1.0f+cosf(m_particule[i].zoom*3.7f)/6.0f;
- }
-
- dim.x *= zoom.x;
- dim.y *= zoom.y;
-
- object = m_particule[i].objLink;
- if ( object != 0 )
- {
- pos += object->RetPosition(0);
- }
-
- angle.x = Math::PI/2.0f;
- angle.y = 0.0f;
- angle.z = m_particule[i].angle;
-
- if ( m_engine->RetRankView() == 1 ) // underwater?
- {
- pos.y -= 1.0f;
- }
-
- eye = m_engine->RetEyePt();
- if ( pos.y > eye.y ) // seen from below?
- {
- angle.x = -Math::PI/2.0f;
- }
-
- Math::LoadRotationXZYMatrix(matrix, angle);
- matrix.Set(1, 4, pos.x);
- matrix.Set(2, 4, pos.y);
- matrix.Set(3, 4, pos.z);
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- n = Math::Vector(0.0f, 0.0f, -1.0f);
-
- 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] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y);
- vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y);
- vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y);
- vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-}
-
-// Draw a particle in the form of radius.
-
-void CParticule::DrawParticuleRay(int i)
-{
- CObject* object;
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Matrix matrix;
- Math::Vector corner[4], eye, pos, goal, n, angle, proj;
- Math::Point dim, texInf, texSup;
- bool bLeft;
- float a, len, adv, prop, vario1, vario2;
- int r, rank, step, first, last;
-
- if ( m_particule[i].zoom == 0.0f ) return;
- if ( m_particule[i].intensity == 0.0f ) return;
-
- eye = m_engine->RetEyePt();
- pos = m_particule[i].pos;
- goal = m_particule[i].goal;
-
- object = m_particule[i].objLink;
- if ( object != 0 )
- {
- pos += object->RetPosition(0);
- }
-
- a = Math::RotateAngle(Math::Point(pos.x,pos.z), Math::Point(goal.x,goal.z), Math::Point(eye.x,eye.z));
- bLeft = (a < Math::PI);
-
- proj = Math::Projection(pos, goal, eye);
- 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 ( bLeft ) angle.x = -angle.x;
-
- Math::LoadRotationZXYMatrix(matrix, angle);
- matrix.Set(1, 4, pos.x);
- matrix.Set(2, 4, pos.y);
- matrix.Set(3, 4, pos.z);
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- n = Math::Vector(0.0f, 0.0f, bLeft?1.0f:-1.0f);
-
- dim.x = m_particule[i].dim.x * m_particule[i].zoom;
- dim.y = m_particule[i].dim.y * m_particule[i].zoom;
-
- if ( bLeft ) dim.y = -dim.y;
-
- len = Math::Distance(pos, goal);
- adv = 0.0f;
-
- step = (int)(len/(dim.x*2.0f))+1;
-
- if ( step == 1 )
- {
- vario1 = 1.0f;
- vario2 = 1.0f;
- }
- else
- {
- vario1 = 0.0f;
- vario2 = 2.0f;
- }
-
- if ( m_particule[i].type == PARTIRAY2 )
- {
- first = 0;
- last = step;
- vario1 = 0.0f;
- vario2 = 0.0f;
- }
- else if ( m_particule[i].type == PARTIRAY3 )
- {
- if ( m_particule[i].time < m_particule[i].duration*0.40f )
- {
- prop = m_particule[i].time / (m_particule[i].duration*0.40f);
- first = 0;
- last = (int)(prop*step);
- }
- else if ( m_particule[i].time < m_particule[i].duration*0.60f )
- {
- first = 0;
- last = step;
- }
- else
- {
- prop = (m_particule[i].time-m_particule[i].duration*0.60f) / (m_particule[i].duration*0.40f);
- first = (int)(prop*step);
- last = step;
- }
- }
- else
- {
- if ( m_particule[i].time < m_particule[i].duration*0.50f )
- {
- prop = m_particule[i].time / (m_particule[i].duration*0.50f);
- first = 0;
- last = (int)(prop*step);
- }
- else if ( m_particule[i].time < m_particule[i].duration*0.75f )
- {
- first = 0;
- last = step;
- }
- else
- {
- prop = (m_particule[i].time-m_particule[i].duration*0.75f) / (m_particule[i].duration*0.25f);
- first = (int)(prop*step);
- last = step;
- }
- }
-
- 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;
-
- for ( 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 )
- {
-#if 1
- texInf = m_particule[i].texInf;
- texSup = m_particule[i].texSup;
-
- r = rand()%16;
- texInf.x += 0.25f*(r/4);
- texSup.x += 0.25f*(r/4);
- if ( r%2 < 1 && adv > 0.0f && m_particule[i].type != PARTIRAY1 )
- {
- Math::Swap(texInf.x, texSup.x);
- }
- if ( r%4 < 2 )
- {
- Math::Swap(texInf.y, texSup.y);
- }
-#else
- texInf.x = Math::Mod(texInf.x+0.25f, 1.0f);
- texSup.x = Math::Mod(texSup.x+0.25f, 1.0f);
-#endif
-
- vertex[0] = D3DVERTEX2(corner[1], n, texSup.x, texSup.y);
- vertex[1] = D3DVERTEX2(corner[0], n, texInf.x, texSup.y);
- vertex[2] = D3DVERTEX2(corner[3], n, texSup.x, texInf.y);
- vertex[3] = D3DVERTEX2(corner[2], n, texInf.x, texInf.y);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
- }
- adv += dim.x*2.0f;
- }
-}
-
-// Draws a spherical particle.
-
-void CParticule::DrawParticuleSphere(int i)
-{
- D3DVERTEX2 vertex[2*16*(16+1)]; // triangles
- Math::Matrix matrix, rot;
- Math::Vector angle, v0, v1;
- Math::Point ts, ti;
- float zoom, deltaRingAngle, deltaSegAngle;
- float r0,r1, tu0,tv0, tu1,tv1;
- int j, ring, seg, numRings, numSegments;
-
- zoom = m_particule[i].zoom;
-#if 0
- if ( !m_engine->RetStateColor() && m_particule[i].intensity < 0.5f )
- {
- zoom *= m_particule[i].intensity/0.5f;
- }
-#endif
-
- if ( zoom == 0.0f ) return;
-
- m_engine->SetState(D3DSTATETTb|D3DSTATE2FACE|D3DSTATEWRAP, RetColor(m_particule[i].intensity));
-
- matrix.LoadIdentity();
- matrix.Set(1, 1, zoom);
- matrix.Set(2, 2, zoom);
- matrix.Set(3, 3, zoom);
- matrix.Set(1, 4, m_particule[i].pos.x);
- matrix.Set(2, 4, m_particule[i].pos.y);
- matrix.Set(3, 4, m_particule[i].pos.z);
-
- if ( m_particule[i].angle != 0.0f )
- {
- angle.x = m_particule[i].angle*0.4f;
- angle.y = m_particule[i].angle*1.0f;
- angle.z = m_particule[i].angle*0.7f;
- Math::LoadRotationZXYMatrix(rot, angle);
- matrix = Math::MultiplyMatrices(rot, matrix);
- }
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- ts.x = m_particule[i].texSup.x;
- ts.y = m_particule[i].texSup.y;
- ti.x = m_particule[i].texInf.x;
- ti.y = m_particule[i].texInf.y;
-
- // Choose a tesselation level.
- if ( m_particule[i].type == PARTISPHERE3 ||
- m_particule[i].type == PARTISPHERE5 )
- {
- numRings = 16;
- numSegments = 16;
- }
- else
- {
- numRings = 8;
- numSegments = 10;
- }
-
- // Establish constants used in sphere generation.
- deltaRingAngle = Math::PI/numRings;
- deltaSegAngle = 2.0f*Math::PI/numSegments;
-
- // Generate the group of rings for the sphere.
- j = 0;
- for ( ring=0 ; ring<numRings ; ring++ )
- {
- r0 = sinf((ring+0)*deltaRingAngle);
- r1 = sinf((ring+1)*deltaRingAngle);
- v0.y = cosf((ring+0)*deltaRingAngle);
- v1.y = cosf((ring+1)*deltaRingAngle);
-
- tv0 = (ring+0)/(float)numRings;
- tv1 = (ring+1)/(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 ( 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.
- tu0 = ((float)seg)/numSegments;
- tu0 = ts.x+(ti.x-ts.x)*tu0;
- tu1 = tu0;
-
- vertex[j++] = D3DVERTEX2(v0,v0, tu0,tv0);
- vertex[j++] = D3DVERTEX2(v1,v1, tu1,tv1);
- }
- }
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, j, NULL);
- m_engine->AddStatisticTriangle(j);
-
- m_engine->SetState(D3DSTATETTb, RetColor(m_particule[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));
- }
-}
-
-// Draws a cylindrical particle.
-
-void CParticule::DrawParticuleCylinder(int i)
-{
- D3DVERTEX2 vertex[2*5*(10+1)]; // triangles
- Math::Matrix matrix, rot;
- Math::Vector angle, v0, v1;
- Math::Point ts, ti;
- float progress, zoom, diam, deltaSegAngle, h[6], d[6];
- float r0,r1, tu0,tv0, tu1,tv1, p1, p2, pp;
- int j, ring, seg, numRings, numSegments;
-
- progress = m_particule[i].zoom;
- zoom = m_particule[i].dim.x;
- diam = m_particule[i].dim.y;
- if ( progress >= 1.0f || zoom == 0.0f ) return;
-
- m_engine->SetState(D3DSTATETTb|D3DSTATE2FACE|D3DSTATEWRAP, RetColor(m_particule[i].intensity));
-
- matrix.LoadIdentity();
- matrix.Set(1, 1, zoom);
- matrix.Set(2, 2, zoom);
- matrix.Set(3, 3, zoom);
- matrix.Set(1, 4, m_particule[i].pos.x);
- matrix.Set(2, 4, m_particule[i].pos.y);
- matrix.Set(3, 4, m_particule[i].pos.z);
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- ts.x = m_particule[i].texSup.x;
- ts.y = m_particule[i].texSup.y;
- ti.x = m_particule[i].texInf.x;
- ti.y = m_particule[i].texInf.y;
-
- numRings = 5;
- numSegments = 10;
- deltaSegAngle = 2.0f*Math::PI/numSegments;
-
- if ( m_particule[i].type == PARTIPLOUF0 )
- {
-#if 0
- if ( progress <= 0.5f )
- {
- p1 = progress/0.5f; // front
- p2 = 0.0f; // back
- }
- else
- {
- p1 = 1.0f; // front
- p2 = (progress-0.5f)/0.5f; // back
- ts.y += (ti.y-ts.y)*p2;
- }
-#else
- p1 = progress; // front
- p2 = powf(progress, 5.0f); // back
-#endif
-
- for ( ring=0 ; ring<=numRings ; ring++ )
- {
- pp = p2+(p1-p2)*((float)ring/numRings);
- d[ring] = diam/zoom+pp*2.0f;
- h[ring] = ProgressCylinder(pp);
- }
- }
-
- j = 0;
- for ( ring=0 ; ring<numRings ; ring++ )
- {
- r0 = 1.0f*d[ring+0]; // radius at the base
- 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
-
- tv0 = 1.0f-(ring+0)*(1.0f/numRings);
- 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 ( 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);
-
-//? tu0 = ((float)seg)/numSegments;
- tu0 = (seg%2)?0.0f:1.0f;
- tu0 = ts.x+(ti.x-ts.x)*tu0;
- tu1 = tu0;
-
- vertex[j++] = D3DVERTEX2(v0,v0, tu0,tv0);
- vertex[j++] = D3DVERTEX2(v1,v1, tu1,tv1);
- }
- }
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, j, NULL);
- m_engine->AddStatisticTriangle(j);
-
- m_engine->SetState(D3DSTATETTb, RetColor(m_particule[i].intensity));
-}
-
-// Draws a tire mark.
-
-void CParticule::DrawParticuleWheel(int i)
-{
- Math::Vector pos[4], center;
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Vector n;
- Math::Point ts, ti;
- float dist, dp;
-
- dist = Math::DistanceProjected(m_engine->RetEyePt(), m_wheelTrace[i].pos[0]);
- if ( dist > 300.0f ) return;
-
- 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];
-
- 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;
- }
-
- 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;
- }
-
- 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;
-
- n = Math::Vector(0.0f, 1.0f, 0.0f);
-
- vertex[0] = D3DVERTEX2(pos[0], n, ts.x, ts.y);
- vertex[1] = D3DVERTEX2(pos[1], n, ti.x, ts.y);
- vertex[2] = D3DVERTEX2(pos[2], n, ts.x, ti.y);
- vertex[3] = D3DVERTEX2(pos[3], n, ti.x, ti.y);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-}
-
-// Draws all the particles.
-
-void CParticule::DrawParticule(int sheet)
-{
- D3DMATERIAL7 mat;
- Math::Matrix matrix;
- bool bLoadTexture;
- char name[20];
- int state, t, i, j, r;
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
-
- // Draw the basic particles of triangles.
- if ( m_totalInterface[0][sheet] > 0 )
- {
- for ( i=0 ; i<MAXPARTICULE ; i++ )
- {
- if ( !m_particule[i].bUsed ) continue;
- if ( m_particule[i].sheet != sheet ) continue;
- if ( m_particule[i].type == PARTIPART ) continue;
-
- m_engine->SetTexture(m_triangle[i].texName1);
- m_engine->SetMaterial(m_triangle[i].material);
- m_engine->SetState(m_triangle[i].state);
- DrawParticuleTriangle(i);
- }
- }
-
- // Draw the particles was calculated based on edge.
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
-
- ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
- 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 )
- {
-#if _POLISH
- m_engine->SetTexture("textp.tga");
-#else
- m_engine->SetTexture("text.tga");
-#endif
- m_engine->SetState(D3DSTATETTw);
-//? m_engine->SetState(D3DSTATENORMAL);
- matrix.LoadIdentity();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
- for ( i=0 ; i<m_wheelTraceTotal ; i++ )
- {
- DrawParticuleWheel(i);
- }
- }
-
-//? for ( t=1 ; t<MAXPARTITYPE ; t++ )
- for ( t=MAXPARTITYPE-1 ; t>=1 ; t-- ) // black behind!
- {
- if ( m_totalInterface[t][sheet] == 0 ) continue;
-
- bLoadTexture = false;
-
- if ( t == 4 ) state = D3DSTATETTw; // text.tga
- else state = D3DSTATETTb; // effect[00..02].tga
- m_engine->SetState(state);
-
- for ( j=0 ; j<MAXPARTICULE ; j++ )
- {
- i = MAXPARTICULE*t+j;
- if ( !m_particule[i].bUsed ) continue;
- if ( m_particule[i].sheet != sheet ) continue;
-
- if ( !bLoadTexture )
- {
- NameParticule(name, t);
- m_engine->SetTexture(name);
- bLoadTexture = true;
- }
-
- r = m_particule[i].trackRank;
- if ( r != -1 )
- {
- m_engine->SetState(state);
- TrackDraw(r, m_particule[i].type); // draws the drag
- if ( !m_track[r].bDrawParticule ) continue;
- }
-
- m_engine->SetState(state, RetColor(m_particule[i].intensity));
-
- if ( m_particule[i].bRay ) // ray?
- {
- DrawParticuleRay(i);
- }
- else if ( m_particule[i].type == PARTIFLIC || // circle in the water?
- m_particule[i].type == PARTISHOW ||
- m_particule[i].type == PARTICHOC ||
- m_particule[i].type == PARTIGFLAT )
- {
- DrawParticuleFlat(i);
- }
- else if ( m_particule[i].type >= PARTIFOG0 &&
- m_particule[i].type <= PARTIFOG9 )
- {
- DrawParticuleFog(i);
- }
- else if ( m_particule[i].type >= PARTISPHERE0 &&
- m_particule[i].type <= PARTISPHERE9 ) // sphere?
- {
- DrawParticuleSphere(i);
- }
- else if ( m_particule[i].type >= PARTIPLOUF0 &&
- m_particule[i].type <= PARTIPLOUF4 ) // cylinder?
- {
- DrawParticuleCylinder(i);
- }
- else // normal?
- {
- DrawParticuleNorm(i);
- }
- }
- }
-
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
-}
-
-
-// Seeks if an object collided with a bullet.
-
-CObject* CParticule::SearchObjectGun(Math::Vector old, Math::Vector pos,
- ParticuleType type, CObject *father)
-{
- CObject *pObj, *pBest;
- Math::Vector box1, box2, oPos, p;
- ObjectType oType;
- bool bShield;
- float min, oRadius, dist, shieldRadius;
- int i, j;
- bool bHimself;
-
- if ( m_main->RetMovieLock() ) return 0; // current movie?
-
- bHimself = m_main->RetHimselfDamage();
-
- min = 5.0f;
- if ( type == PARTIGUN2 ) min = 2.0f; // shooting insect?
- if ( type == PARTIGUN3 ) min = 3.0f; // suiciding spider?
-
- box1 = old;
- 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;
-
- pBest = 0;
- bShield = false;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj == father ) continue;
-
- oType = pObj->RetType();
-
- if ( oType == OBJECT_TOTO ) continue;
-
- if ( type == PARTIGUN1 ) // fireball shooting?
- {
- if ( oType == OBJECT_MOTHER ) continue;
- if ( bHimself ) // 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 ( bHimself ) // 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 ( bHimself ) // damage is oneself?
- {
- if ( !IsAlien(oType) &&
- !IsSoft(oType) ) continue;
- }
- else // damage only to enemies?
- {
- if ( !IsAlien(oType) ) continue;
- }
- }
- else
- {
- continue;
- }
-
- oPos = pObj->RetPosition(0);
-
- if ( type == PARTIGUN2 || // shooting insect?
- type == PARTIGUN3 ) // suiciding spider?
- {
- // Test if the ball is entered into the sphere of a shield.
- shieldRadius = pObj->RetShieldRadius();
- if ( shieldRadius > 0.0f )
- {
- dist = Math::Distance(oPos, pos);
- if ( dist <= shieldRadius )
- {
- pBest = pObj;
- bShield = true;
- }
- }
- }
- if ( bShield ) continue;
-
- // Test the center of the object, which is necessary for objects
- // that have no sphere in the center (station).
- dist = Math::Distance(oPos, pos)-4.0f;
- if ( dist < min )
- {
- pBest = pObj;
- }
-
- // Test with all spheres of the object.
- j = 0;
- while ( pObj->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;
-
- p = Math::Projection(old, pos, oPos);
- dist = Math::Distance(p, oPos)-oRadius;
- if ( dist < min )
- {
- pBest = pObj;
- }
- }
- }
-
- return pBest;
-}
-
-// Seeks if an object collided with a ray.
-
-CObject* CParticule::SearchObjectRay(Math::Vector pos, Math::Vector goal,
- ParticuleType type, CObject *father)
-{
- CObject* pObj;
- Math::Vector box1, box2, oPos, p;
- ObjectType oType;
- float min, dist;
- int i;
-
- if ( m_main->RetMovieLock() ) return 0; // current movie?
-
- min = 10.0f;
-
- box1 = pos;
- 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 ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj == father ) continue;
-
- oType = pObj->RetType();
-
- 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;
-
- oPos = pObj->RetPosition(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;
-
- p = Math::Projection(pos, goal, oPos);
- dist = Math::Distance(p, oPos);
- if ( dist < min ) return pObj;
- }
-
- return 0;
-}
-
-
-// Sounded one.
-
-void CParticule::Play(Sound sound, Math::Vector pos, float amplitude)
-{
- if ( m_sound == 0 )
- {
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- }
-
- m_sound->Play(sound, pos, amplitude);
-}
-
-
-
-// Seeks the color if you're in the fog.
-// Returns black if you're not in the fog.
-
-D3DCOLORVALUE CParticule::RetFogColor(Math::Vector pos)
-{
- D3DCOLORVALUE result, color;
- float dist, factor;
- int fog, i;
-
- result.r = 0.0f;
- result.g = 0.0f;
- result.b = 0.0f;
- result.a = 0.0f;
-
- for ( fog=0 ; fog<m_fogTotal ; fog++ )
- {
- i = m_fog[fog]; // i = rank of the particle
-
- if ( pos.y >= m_particule[i].pos.y+FOG_HSUP ) continue;
- if ( pos.y <= m_particule[i].pos.y-FOG_HINF ) continue;
-
- dist = Math::DistanceProjected(pos, m_particule[i].pos);
- if ( dist >= m_particule[i].dim.x*1.5f ) continue;
-
- // Calculates the horizontal distance.
- factor = 1.0f-powf(dist/(m_particule[i].dim.x*1.5f), 4.0f);
-
- // Calculates the vertical distance.
- if ( pos.y > m_particule[i].pos.y )
- {
- factor *= 1.0f-(pos.y-m_particule[i].pos.y)/FOG_HSUP;
- }
- else
- {
- factor *= 1.0f-(m_particule[i].pos.y-pos.y)/FOG_HINF;
- }
-
- factor *= 0.3f;
-
- if ( m_particule[i].type == PARTIFOG0 ||
- m_particule[i].type == PARTIFOG1 ) // blue?
- {
- color.r = 0.0f;
- color.g = 0.5f;
- color.b = 1.0f;
- }
- else if ( m_particule[i].type == PARTIFOG2 ||
- m_particule[i].type == PARTIFOG3 ) // red?
- {
- color.r = 2.0f;
- color.g = 1.0f;
- color.b = 0.0f;
- }
- else if ( m_particule[i].type == PARTIFOG4 ||
- m_particule[i].type == PARTIFOG5 ) // white?
- {
- color.r = 1.0f;
- color.g = 1.0f;
- color.b = 1.0f;
- }
- else if ( m_particule[i].type == PARTIFOG6 ||
- m_particule[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;
-}
-
-
-// Writes a file. BMP containing all the tire tracks.
-
-bool CParticule::WriteWheelTrace(char *filename, int width, int height,
- Math::Vector dl, Math::Vector ur)
-{
- HDC hDC;
- HDC hDCImage;
- HBITMAP hb;
- PBITMAPINFO info;
- HBRUSH hBrush;
- HPEN hPen;
- HGDIOBJ old;
- RECT rect;
- COLORREF color;
- Math::Point pos[4];
- POINT list[4];
- int i;
-
- if ( !m_engine->GetRenderDC(hDC) ) return false;
-
- hDCImage = CreateCompatibleDC(hDC);
- if ( hDCImage == 0 )
- {
- m_engine->ReleaseRenderDC(hDC);
- return false;
- }
-
- hb = CreateCompatibleBitmap(hDC, width, height);
- if ( hb == 0 )
- {
- DeleteDC(hDCImage);
- m_engine->ReleaseRenderDC(hDC);
- return false;
- }
-
- SelectObject(hDCImage, hb);
-
- rect.left = 0;
- rect.right = width;
- rect.top = 0;
- rect.bottom = height;
- FillRect(hDCImage, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
-
- hPen = CreatePen(PS_NULL, 1, 0);
- SelectObject(hDCImage, hPen);
-
- for ( i=0 ; i<m_wheelTraceTotal ; i++ )
- {
- if ( m_wheelTrace[i].type == PARTITRACE0 ) // black ground track?
- {
- color = RGB(0,0,0);
- }
- else if ( m_wheelTrace[i].type == PARTITRACE1 ) // red ground track?
- {
- color = RGB(255,0,0);
- }
- else if ( m_wheelTrace[i].type == PARTITRACE2 ) // green ground track?
- {
- color = RGB(0,255,0);
- }
- else if ( m_wheelTrace[i].type == PARTITRACE3 ) // blue ground track?
- {
- color = RGB(0,0,255);
- }
- else if ( m_wheelTrace[i].type == PARTITRACE4 ) // cyan ground track?
- {
- color = RGB(0,255,255);
- }
- else if ( m_wheelTrace[i].type == PARTITRACE5 ) // magenta ground track?
- {
- color = RGB(255,0,255);
- }
- else if ( m_wheelTrace[i].type == PARTITRACE6 ) // yellow ground track?
- {
- color = RGB(255,255,0);
- }
- else
- {
- color = RGB(0,0,0);
- }
- hBrush = CreateSolidBrush(color);
- old = SelectObject(hDCImage, hBrush);
-
- pos[0].x = ((m_wheelTrace[i].pos[0].x-dl.x)*width)/(ur.x-dl.x);
- pos[0].y = ((m_wheelTrace[i].pos[0].z-dl.z)*width)/(ur.z-dl.z);
- pos[1].x = ((m_wheelTrace[i].pos[1].x-dl.x)*width)/(ur.x-dl.x);
- pos[1].y = ((m_wheelTrace[i].pos[1].z-dl.z)*width)/(ur.z-dl.z);
- pos[2].x = ((m_wheelTrace[i].pos[2].x-dl.x)*width)/(ur.x-dl.x);
- pos[2].y = ((m_wheelTrace[i].pos[2].z-dl.z)*width)/(ur.z-dl.z);
- pos[3].x = ((m_wheelTrace[i].pos[3].x-dl.x)*width)/(ur.x-dl.x);
- pos[3].y = ((m_wheelTrace[i].pos[3].z-dl.z)*width)/(ur.z-dl.z);
-
- list[0].x = (int)pos[0].x;
- list[0].y = (int)pos[0].y;
- list[1].x = (int)pos[1].x;
- list[1].y = (int)pos[1].y;
- list[2].x = (int)pos[3].x;
- list[2].y = (int)pos[3].y;
- list[3].x = (int)pos[2].x;
- list[3].y = (int)pos[2].y;
- Polygon(hDCImage, list, 4);
-
- if ( old != 0 ) SelectObject(hDCImage, old);
- DeleteObject(hBrush);
- }
-
- info = m_engine->CreateBitmapInfoStruct(hb);
- if ( info == 0 )
- {
- DeleteObject(hb);
- DeleteDC(hDCImage);
- m_engine->ReleaseRenderDC(hDC);
- return false;
- }
-
- m_engine->CreateBMPFile(filename, info, hb, hDCImage);
-
- DeleteObject(hb);
- DeleteDC(hDCImage);
- m_engine->ReleaseRenderDC(hDC);
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// particule.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "math/conv.h"
+#include "old/d3dmath.h"
+#include "old/d3dtextr.h"
+#include "old/d3dengine.h"
+#include "old/d3dutil.h"
+#include "common/language.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "object/object.h"
+#include "physics/physics.h"
+#include "object/auto/auto.h"
+#include "object/robotmain.h"
+#include "old/terrain.h"
+#include "old/sound.h"
+#include "old/water.h"
+#include "old/particule.h"
+
+
+
+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)
+{
+ 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 RetDecay(ObjectType type)
+{
+ if ( IsSoft(type) ) return 0.2f;
+ return 1.0f;
+}
+
+
+
+// Application constructor.
+
+CParticule::CParticule(CInstanceManager *iMan, CD3DEngine* engine)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_PARTICULE, this);
+
+ m_pD3DDevice = 0;
+ m_engine = engine;
+ m_main = 0;
+ m_terrain = 0;
+ m_water = 0;
+ m_sound = 0;
+ m_uniqueStamp = 0;
+ m_exploGunCounter = 0;
+ m_lastTimeGunDel = 0.0f;
+ m_absTime = 0.0f;
+
+ FlushParticule();
+}
+
+// Application destructor. Free memory.
+
+CParticule::~CParticule()
+{
+ m_iMan->DeleteInstance(CLASS_PARTICULE, this);
+}
+
+
+void CParticule::SetD3DDevice(LPDIRECT3DDEVICE7 device)
+{
+ m_pD3DDevice = device;
+}
+
+
+// Removes all particles.
+
+void CParticule::FlushParticule()
+{
+ int i, j;
+
+ for ( i=0 ; i<MAXPARTICULE*MAXPARTITYPE ; i++ )
+ {
+ m_particule[i].bUsed = false;
+ }
+
+ for ( i=0 ; i<MAXPARTITYPE ; i++ )
+ {
+ for ( j=0 ; j<SH_MAX ; j++ )
+ {
+ m_totalInterface[i][j] = 0;
+ }
+ }
+
+ for ( i=0 ; i<MAXTRACK ; i++ )
+ {
+ m_track[i].bUsed = false;
+ }
+
+ m_wheelTraceTotal = 0;
+ m_wheelTraceIndex = 0;
+
+ for ( i=0 ; i<SH_MAX ; i++ )
+ {
+ m_bFrameUpdate[i] = true;
+ }
+
+ m_fogTotal = 0;
+ m_exploGunCounter = 0;
+}
+
+// Removes all particles of a sheet.
+
+void CParticule::FlushParticule(int sheet)
+{
+ int i;
+
+ for ( i=0 ; i<MAXPARTICULE*MAXPARTITYPE ; i++ )
+ {
+ if ( !m_particule[i].bUsed ) continue;
+ if ( m_particule[i].sheet != sheet ) continue;
+
+ m_particule[i].bUsed = false;
+ }
+
+ for ( i=0 ; i<MAXPARTITYPE ; i++ )
+ {
+ m_totalInterface[i][sheet] = 0;
+ }
+
+ for ( i=0 ; i<MAXTRACK ; i++ )
+ {
+ m_track[i].bUsed = false;
+ }
+
+ if ( sheet == SH_WORLD )
+ {
+ m_wheelTraceTotal = 0;
+ m_wheelTraceIndex = 0;
+ }
+}
+
+
+// Builds file name of the effect.
+// effectNN.tga, with NN = number
+
+void NameParticule(char *buffer, int num)
+{
+ if ( num == 1 ) strcpy(buffer, "effect00.tga");
+ else if ( num == 2 ) strcpy(buffer, "effect01.tga");
+ else if ( num == 3 ) strcpy(buffer, "effect02.tga");
+#if _POLISH
+ else if ( num == 4 ) strcpy(buffer, "textp.tga");
+#else
+ else if ( num == 4 ) strcpy(buffer, "text.tga");
+#endif
+ else strcpy(buffer, "xxx.tga");
+}
+
+
+// Creates a new particle.
+// Returns the channel of the particle created or -1 on error.
+
+int CParticule::CreateParticule(Math::Vector pos, Math::Vector speed, Math::Point dim,
+ ParticuleType type,
+ float duration, float mass,
+ float windSensitivity, int sheet)
+{
+//? float dist;
+ int i, j, t;
+
+ if ( m_main == 0 )
+ {
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ }
+
+#if 0
+ if ( sheet == SH_WORLD &&
+ type != PARTISELY &&
+ type != PARTISELR &&
+ type != PARTIGUN1 &&
+ type != PARTIGUN2 &&
+ type != PARTIGUN3 &&
+ type != PARTIGUN4 &&
+ type != PARTIQUARTZ &&
+ !m_main->RetMovieLock() )
+ {
+ dist = Math::Distance(pos, m_engine->RetEyePt());
+ if ( dist > 300.0f ) return -1;
+ }
+#endif
+
+ 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 ( j=0 ; j<MAXPARTICULE ; j++ )
+ {
+ i = MAXPARTICULE*t+j;
+
+ if ( !m_particule[i].bUsed )
+ {
+ ZeroMemory(&m_particule[i], sizeof(Particule));
+ m_particule[i].bUsed = true;
+ m_particule[i].bRay = false;
+ m_particule[i].uniqueStamp = m_uniqueStamp++;
+ m_particule[i].sheet = sheet;
+ m_particule[i].mass = mass;
+ m_particule[i].duration = duration;
+ m_particule[i].pos = pos;
+ m_particule[i].goal = pos;
+ m_particule[i].speed = speed;
+ m_particule[i].windSensitivity = windSensitivity;
+ m_particule[i].dim = dim;
+ m_particule[i].zoom = 1.0f;
+ m_particule[i].angle = 0.0f;
+ m_particule[i].intensity = 1.0f;
+ m_particule[i].type = type;
+ m_particule[i].phase = PARPHSTART;
+ m_particule[i].texSup.x = 0.0f;
+ m_particule[i].texSup.y = 0.0f;
+ m_particule[i].texInf.x = 0.0f;
+ m_particule[i].texInf.y = 0.0f;
+ m_particule[i].time = 0.0f;
+ m_particule[i].phaseTime = 0.0f;
+ m_particule[i].testTime = 0.0f;
+ m_particule[i].objLink = 0;
+ m_particule[i].objFather = 0;
+ m_particule[i].trackRank = -1;
+
+ m_totalInterface[t][sheet] ++;
+
+ if ( type == PARTIEXPLOT ||
+ type == PARTIEXPLOO )
+ {
+ m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
+ }
+
+ if ( type == PARTIGUN1 ||
+ type == PARTIGUN4 )
+ {
+ m_particule[i].testTime = 1.0f; // impact immediately
+ }
+
+ if ( type >= PARTIFOG0 &&
+ type <= PARTIFOG9 )
+ {
+ if ( m_fogTotal < MAXPARTIFOG )
+ m_fog[m_fogTotal++] = i;
+ }
+
+ return i | ((m_particule[i].uniqueStamp&0xffff)<<16);
+ }
+ }
+
+ return -1;
+}
+
+// Creates a new triangular particle (debris).
+// Returns the channel of the particle created or -1 on error.
+
+int CParticule::CreateFrag(Math::Vector pos, Math::Vector speed,
+ D3DTriangle *triangle,
+ ParticuleType type,
+ float duration, float mass,
+ float windSensitivity, int sheet)
+{
+ Math::Vector p1, p2, p3, n;
+ float l1, l2, l3, dx, dy;
+ int i, j, t;
+
+ t = 0;
+ for ( j=0 ; j<MAXPARTICULE ; j++ )
+ {
+ i = MAXPARTICULE*t+j;
+
+ if ( !m_particule[i].bUsed )
+ {
+ ZeroMemory(&m_particule[i], sizeof(Particule));
+ m_particule[i].bUsed = true;
+ m_particule[i].bRay = false;
+ m_particule[i].uniqueStamp = m_uniqueStamp++;
+ m_particule[i].sheet = sheet;
+ m_particule[i].mass = mass;
+ m_particule[i].duration = duration;
+ m_particule[i].pos = pos;
+ m_particule[i].goal = pos;
+ m_particule[i].speed = speed;
+ m_particule[i].windSensitivity = windSensitivity;
+ m_particule[i].zoom = 1.0f;
+ m_particule[i].angle = 0.0f;
+ m_particule[i].intensity = 1.0f;
+ m_particule[i].type = type;
+ m_particule[i].phase = PARPHSTART;
+ m_particule[i].texSup.x = 0.0f;
+ m_particule[i].texSup.y = 0.0f;
+ m_particule[i].texInf.x = 0.0f;
+ m_particule[i].texInf.y = 0.0f;
+ m_particule[i].time = 0.0f;
+ m_particule[i].phaseTime = 0.0f;
+ m_particule[i].testTime = 0.0f;
+ m_particule[i].objLink = 0;
+ m_particule[i].objFather = 0;
+ m_particule[i].trackRank = -1;
+ m_triangle[i] = *triangle;
+
+ m_totalInterface[t][sheet] ++;
+
+ p1.x = m_triangle[i].triangle[0].x;
+ p1.y = m_triangle[i].triangle[0].y;
+ p1.z = m_triangle[i].triangle[0].z;
+
+ p2.x = m_triangle[i].triangle[1].x;
+ p2.y = m_triangle[i].triangle[1].y;
+ p2.z = m_triangle[i].triangle[1].z;
+
+ p3.x = m_triangle[i].triangle[2].x;
+ p3.y = m_triangle[i].triangle[2].y;
+ p3.z = m_triangle[i].triangle[2].z;
+
+ l1 = Math::Distance(p1, p2);
+ l2 = Math::Distance(p2, p3);
+ l3 = Math::Distance(p3, p1);
+ dx = fabs(Math::Min(l1, l2, l3))*0.5f;
+ 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].x = p1.x;
+ m_triangle[i].triangle[0].y = p1.y;
+ m_triangle[i].triangle[0].z = p1.z;
+
+ m_triangle[i].triangle[1].x = p2.x;
+ m_triangle[i].triangle[1].y = p2.y;
+ m_triangle[i].triangle[1].z = p2.z;
+
+ m_triangle[i].triangle[2].x = p3.x;
+ m_triangle[i].triangle[2].y = p3.y;
+ m_triangle[i].triangle[2].z = p3.z;
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f);
+
+ m_triangle[i].triangle[0].nx = n.x;
+ m_triangle[i].triangle[0].ny = n.y;
+ m_triangle[i].triangle[0].nz = n.z;
+
+ m_triangle[i].triangle[1].nx = n.x;
+ m_triangle[i].triangle[1].ny = n.y;
+ m_triangle[i].triangle[1].nz = n.z;
+
+ m_triangle[i].triangle[2].nx = n.x;
+ m_triangle[i].triangle[2].ny = n.y;
+ m_triangle[i].triangle[2].nz = n.z;
+
+ if ( type == PARTIFRAG )
+ {
+ m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
+ }
+ return i | ((m_particule[i].uniqueStamp&0xffff)<<16);
+ }
+ }
+
+ return -1;
+}
+
+// Creates a new particle being a part of object.
+// Returns the channel of the particle created or -1 on error.
+
+int CParticule::CreatePart(Math::Vector pos, Math::Vector speed,
+ ParticuleType type,
+ float duration, float mass, float weight,
+ float windSensitivity, int sheet)
+{
+ int i, j, t;
+
+ t = 0;
+ for ( j=0 ; j<MAXPARTICULE ; j++ )
+ {
+ i = MAXPARTICULE*t+j;
+
+ if ( !m_particule[i].bUsed )
+ {
+ ZeroMemory(&m_particule[i], sizeof(Particule));
+ m_particule[i].bUsed = true;
+ m_particule[i].bRay = false;
+ m_particule[i].uniqueStamp = m_uniqueStamp++;
+ m_particule[i].sheet = sheet;
+ m_particule[i].mass = mass;
+ m_particule[i].weight = weight;
+ m_particule[i].duration = duration;
+ m_particule[i].pos = pos;
+ m_particule[i].goal = pos;
+ m_particule[i].speed = speed;
+ m_particule[i].windSensitivity = windSensitivity;
+ m_particule[i].zoom = 1.0f;
+ m_particule[i].angle = 0.0f;
+ m_particule[i].intensity = 1.0f;
+ m_particule[i].type = type;
+ m_particule[i].phase = PARPHSTART;
+ m_particule[i].texSup.x = 0.0f;
+ m_particule[i].texSup.y = 0.0f;
+ m_particule[i].texInf.x = 0.0f;
+ m_particule[i].texInf.y = 0.0f;
+ m_particule[i].time = 0.0f;
+ m_particule[i].phaseTime = 0.0f;
+ m_particule[i].testTime = 0.0f;
+ m_particule[i].trackRank = -1;
+
+ m_totalInterface[t][sheet] ++;
+
+ return i | ((m_particule[i].uniqueStamp&0xffff)<<16);
+ }
+ }
+
+ return -1;
+}
+
+// Creates a new linear particle (radius).
+// Returns the channel of the particle created or -1 on error.
+
+int CParticule::CreateRay(Math::Vector pos, Math::Vector goal,
+ ParticuleType type, Math::Point dim,
+ float duration, int sheet)
+{
+ int i, j, t;
+
+ 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 ( j=0 ; j<MAXPARTICULE ; j++ )
+ {
+ i = MAXPARTICULE*t+j;
+
+ if ( !m_particule[i].bUsed )
+ {
+ ZeroMemory(&m_particule[i], sizeof(Particule));
+ m_particule[i].bUsed = true;
+ m_particule[i].bRay = true;
+ m_particule[i].uniqueStamp = m_uniqueStamp++;
+ m_particule[i].sheet = sheet;
+ m_particule[i].mass = 0.0f;
+ m_particule[i].duration = duration;
+ m_particule[i].pos = pos;
+ m_particule[i].goal = goal;
+ m_particule[i].speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_particule[i].windSensitivity = 0.0f;
+ m_particule[i].dim = dim;
+ m_particule[i].zoom = 1.0f;
+ m_particule[i].angle = 0.0f;
+ m_particule[i].intensity = 1.0f;
+ m_particule[i].type = type;
+ m_particule[i].phase = PARPHSTART;
+ m_particule[i].texSup.x = 0.0f;
+ m_particule[i].texSup.y = 0.0f;
+ m_particule[i].texInf.x = 0.0f;
+ m_particule[i].texInf.y = 0.0f;
+ m_particule[i].time = 0.0f;
+ m_particule[i].phaseTime = 0.0f;
+ m_particule[i].testTime = 0.0f;
+ m_particule[i].objLink = 0;
+ m_particule[i].objFather = 0;
+ m_particule[i].trackRank = -1;
+
+ m_totalInterface[t][sheet] ++;
+
+ return i | ((m_particule[i].uniqueStamp&0xffff)<<16);
+ }
+ }
+
+ return -1;
+}
+
+// Creates a particle with a trail.
+// "length" is the length of the tail of drag (in seconds)!
+
+int CParticule::CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim,
+ ParticuleType type, float duration, float mass,
+ float length, float width)
+{
+ int channel, rank, i;
+
+ // Creates the normal particle.
+ channel = CreateParticule(pos, speed, dim, type, duration, mass, 0.0f, 0);
+ if ( channel == -1 ) return -1;
+
+ // Seeks a streak free.
+ for ( i=0 ; i<MAXTRACK ; i++ )
+ {
+ if ( !m_track[i].bUsed ) // free?
+ {
+ rank = channel;
+ if ( !CheckChannel(rank) ) return -1;
+ m_particule[rank].trackRank = i;
+
+ m_track[i].bUsed = 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].used = 1;
+ m_track[i].head = 0;
+ m_track[i].pos[0] = pos;
+ break;
+ }
+ }
+
+ return channel;
+}
+
+// Creates a tire mark.
+
+void CParticule::CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2,
+ const Math::Vector &p3, const Math::Vector &p4,
+ ParticuleType type)
+{
+ int i, max;
+
+//? max = (int)(m_engine->RetWheelTraceQuantity()*MAXWHEELTRACE);
+ max = MAXWHEELTRACE;
+ 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 == 0 )
+ {
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ }
+
+ m_terrain->MoveOnFloor(m_wheelTrace[i].pos[0]);
+ m_wheelTrace[i].pos[0].y += 0.2f; // just above the ground
+
+ m_terrain->MoveOnFloor(m_wheelTrace[i].pos[1]);
+ m_wheelTrace[i].pos[1].y += 0.2f; // just above the ground
+
+ m_terrain->MoveOnFloor(m_wheelTrace[i].pos[2]);
+ m_wheelTrace[i].pos[2].y += 0.2f; // just above the ground
+
+ m_terrain->MoveOnFloor(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;
+ }
+}
+
+
+// Check a channel number.
+// Adapts the channel so it can be used as an offset in m_particule.
+
+bool CParticule::CheckChannel(int &channel)
+{
+ int uniqueStamp;
+
+ uniqueStamp = (channel>>16)&0xffff;
+ channel &= 0xffff;
+
+ if ( channel < 0 ) return false;
+ if ( channel >= MAXPARTICULE*MAXPARTITYPE ) return false;
+#if 0
+ if ( !m_particule[channel].bUsed ) return false;
+
+ if ( m_particule[channel].uniqueStamp != uniqueStamp ) return false;
+#else
+ if ( !m_particule[channel].bUsed )
+ {
+ OutputDebugString("CheckChannel bUsed=false !\n");
+ return false;
+ }
+
+ if ( m_particule[channel].uniqueStamp != uniqueStamp )
+ {
+ OutputDebugString("CheckChannel uniqueStamp !\n");
+ return false;
+ }
+#endif
+
+ return true;
+}
+
+// Removes a particle after his rank.
+
+void CParticule::DeleteRank(int rank)
+{
+ int i;
+
+ if ( m_totalInterface[rank/MAXPARTICULE][m_particule[rank].sheet] > 0 )
+ {
+ m_totalInterface[rank/MAXPARTICULE][m_particule[rank].sheet] --;
+ }
+
+ i = m_particule[rank].trackRank;
+ if ( i != -1 ) // drag associated?
+ {
+ m_track[i].bUsed = false; // frees the drag
+ }
+
+ m_particule[rank].bUsed = false;
+}
+
+// Removes all particles of a given type.
+
+void CParticule::DeleteParticule(ParticuleType type)
+{
+ int i;
+
+ for ( i=0 ; i<MAXPARTICULE*MAXPARTITYPE ; i++ )
+ {
+ if ( !m_particule[i].bUsed ) continue;
+ if ( m_particule[i].type != type ) continue;
+
+ DeleteRank(i);
+ }
+}
+
+// Removes all particles of a given channel.
+
+void CParticule::DeleteParticule(int channel)
+{
+ int i;
+
+ if ( !CheckChannel(channel) ) return;
+
+ if ( m_totalInterface[channel/MAXPARTICULE][m_particule[channel].sheet] > 0 )
+ {
+ m_totalInterface[channel/MAXPARTICULE][m_particule[channel].sheet] --;
+ }
+
+ i = m_particule[channel].trackRank;
+ if ( i != -1 ) // drag associated?
+ {
+ m_track[i].bUsed = false; // frees the drag
+ }
+
+ m_particule[channel].bUsed = false;
+}
+
+
+// Specifies the object to which the particle is bound.
+
+void CParticule::SetObjectLink(int channel, CObject *object)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].objLink = object;
+}
+
+// Specifies the parent object that created the particle.
+
+void CParticule::SetObjectFather(int channel, CObject *object)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].objFather = object;
+}
+
+void CParticule::SetPosition(int channel, Math::Vector pos)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].pos = pos;
+}
+
+void CParticule::SetDimension(int channel, Math::Point dim)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].dim = dim;
+}
+
+void CParticule::SetZoom(int channel, float zoom)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].zoom = zoom;
+}
+
+void CParticule::SetAngle(int channel, float angle)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].angle = angle;
+}
+
+void CParticule::SetIntensity(int channel, float intensity)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].intensity = intensity;
+}
+
+void CParticule::SetParam(int channel, Math::Vector pos, Math::Point dim, float zoom,
+ float angle, float intensity)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].pos = pos;
+ m_particule[channel].dim = dim;
+ m_particule[channel].zoom = zoom;
+ m_particule[channel].angle = angle;
+ m_particule[channel].intensity = intensity;
+}
+
+void CParticule::SetPhase(int channel, ParticulePhase phase, float duration)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].phase = phase;
+ m_particule[channel].duration = duration;
+ m_particule[channel].phaseTime = m_particule[channel].time;
+}
+
+// Returns the position of the particle.
+
+bool CParticule::GetPosition(int channel, Math::Vector &pos)
+{
+ if ( !CheckChannel(channel) ) return false;
+ pos = m_particule[channel].pos;
+ return true;
+}
+
+
+// Indicates whether a sheet evolves or not.
+
+void CParticule::SetFrameUpdate(int sheet, bool bUpdate)
+{
+ m_bFrameUpdate[sheet] = bUpdate;
+}
+
+// Makes evolve all the particles.
+
+void CParticule::FrameParticule(float rTime)
+{
+ CObject* object;
+ Math::Vector eye, pos, speed, wind;
+ Math::Point ts, ti, dim;
+ bool bPause;
+ float progress, dp, h, duration, mass, amplitude;
+ int i, j, r, total;
+
+ if ( m_main == 0 )
+ {
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ }
+
+ bPause = ( m_engine->RetPause() && !m_main->RetInfoLock() );
+
+ if ( m_terrain == 0 )
+ {
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ }
+ if ( m_water == 0 )
+ {
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ }
+
+ if ( !bPause )
+ {
+ m_lastTimeGunDel += rTime;
+ m_absTime += rTime;
+ }
+
+ wind = m_terrain->RetWind();
+ eye = m_engine->RetEyePt();
+
+ for ( i=0 ; i<MAXPARTICULE*MAXPARTITYPE ; i++ )
+ {
+ if ( !m_particule[i].bUsed ) continue;
+ if ( !m_bFrameUpdate[m_particule[i].sheet] ) continue;
+
+ if ( m_particule[i].type != PARTISHOW )
+ {
+ if ( bPause && m_particule[i].sheet != SH_INTERFACE ) continue;
+ }
+
+ if ( m_particule[i].type != PARTIQUARTZ )
+ {
+ m_particule[i].pos += m_particule[i].speed*rTime;
+ }
+
+ if ( m_particule[i].sheet == SH_WORLD )
+ {
+ h = rTime*m_particule[i].windSensitivity*Math::Rand()*2.0f;
+ m_particule[i].pos += wind*h;
+ }
+
+ progress = (m_particule[i].time-m_particule[i].phaseTime)/m_particule[i].duration;
+
+ // Manages the particles with mass that bounce.
+ if ( m_particule[i].mass != 0.0f &&
+ m_particule[i].type != PARTIQUARTZ )
+ {
+ m_particule[i].speed.y -= m_particule[i].mass*rTime;
+
+ if ( m_particule[i].sheet == SH_INTERFACE )
+ {
+ h = 0.0f;
+ }
+ else
+ {
+ h = m_terrain->RetFloorLevel(m_particule[i].pos, true);
+ }
+ h += m_particule[i].dim.y*0.75f;
+ if ( m_particule[i].pos.y < h ) // impact with the ground?
+ {
+ if ( m_particule[i].type == PARTIPART &&
+ m_particule[i].weight > 3.0f && // heavy enough?
+ m_particule[i].bounce < 3 )
+ {
+ amplitude = m_particule[i].weight*0.1f;
+ amplitude *= 1.0f-0.3f*m_particule[i].bounce;
+ if ( amplitude > 1.0f ) amplitude = 1.0f;
+ if ( amplitude > 0.0f )
+ {
+ Play(SOUND_BOUM, m_particule[i].pos, amplitude);
+ }
+ }
+
+ if ( m_particule[i].bounce < 3 )
+ {
+ m_particule[i].pos.y = h;
+ m_particule[i].speed.y *= -0.4f;
+ m_particule[i].speed.x *= 0.4f;
+ m_particule[i].speed.z *= 0.4f;
+ m_particule[i].bounce ++; // more impact
+ }
+ else // disappears after 3 bounces?
+ {
+ if ( m_particule[i].pos.y < h-10.0f ||
+ m_particule[i].time >= 20.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+ }
+ }
+ }
+
+ // Manages drag associated.
+ r = m_particule[i].trackRank;
+ if ( r != -1 ) // drag exists?
+ {
+ if ( TrackMove(r, m_particule[i].pos, progress) )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_track[r].bDrawParticule = (progress < 1.0f);
+ }
+
+ if ( m_particule[i].type == PARTITRACK1 ) // explosion technique?
+ {
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.375f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTITRACK2 ) // spray blue?
+ {
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.500f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTITRACK3 ) // spider?
+ {
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.500f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTITRACK4 ) // insect explosion?
+ {
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.625f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTITRACK5 ) // derrick?
+ {
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.750f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTITRACK6 ) // reset in/out?
+ {
+ ts.x = 0.0f;
+ ts.y = 0.0f;
+ ti.x = 0.0f;
+ ti.y = 0.0f;
+ }
+
+ if ( m_particule[i].type == PARTITRACK7 || // win-1 ?
+ m_particule[i].type == PARTITRACK8 || // win-2 ?
+ m_particule[i].type == PARTITRACK9 || // win-3 ?
+ m_particule[i].type == PARTITRACK10 ) // win-4 ?
+ {
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.25f*(m_particule[i].type-PARTITRACK7);
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTITRACK11 ) // phazer shot?
+ {
+ object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
+ m_particule[i].goal = m_particule[i].pos;
+ if ( object != 0 )
+ {
+ if ( object->RetType() == OBJECT_MOTHER )
+ {
+ object->ExploObject(EXPLO_BOUM, 0.1f);
+ }
+ else
+ {
+ object->ExploObject(EXPLO_BOUM, 0.0f, RetDecay(object->RetType()));
+ }
+ }
+
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.375f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTITRACK12 ) // drag reactor?
+ {
+ m_particule[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_particule[i].type == PARTIMOTOR )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-progress;
+ m_particule[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_particule[i].type == PARTIBLITZ )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-progress;
+ m_particule[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_particule[i].type == PARTICRASH )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+//? m_particule[i].intensity = 1.0f-progress;
+ if ( progress < 0.25f )
+ {
+ m_particule[i].zoom = progress/0.25f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f;
+ }
+
+//? ts.x = 0.250f;
+ ts.x = 0.000f;
+//? ts.x = 0.375f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIVAPOR )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].intensity = 1.0f-progress;
+ m_particule[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_particule[i].type == PARTIGAS )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[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_particule[i].type == PARTIBASE )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f+progress*7.0f;
+ m_particule[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_particule[i].type == PARTIFIRE ||
+ m_particule[i].type == PARTIFIREZ )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( m_particule[i].type == PARTIFIRE )
+ {
+ m_particule[i].zoom = 1.0f-progress;
+ }
+ else
+ {
+ m_particule[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_particule[i].type == PARTIGUN1 ) // fireball shot?
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( m_particule[i].testTime >= 0.1f )
+ {
+ m_particule[i].testTime = 0.0f;
+
+ if ( m_terrain->RetFloorHeight(m_particule[i].pos, true) < -2.0f )
+ {
+ m_exploGunCounter ++;
+
+ if ( m_exploGunCounter%2 == 0 )
+ {
+ pos = m_particule[i].goal;
+ m_terrain->MoveOnFloor(pos, true);
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 0.0f;
+ dim.x = Math::Rand()*6.0f+6.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*1.0f+1.0f;
+ mass = 0.0f;
+ CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
+
+ pos.y += 1.0f;
+ total = (int)(2.0f*m_engine->RetParticuleDensity());
+ for ( 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;
+ CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
+ }
+ }
+
+ if ( m_exploGunCounter%4 == 0 )
+ {
+ Play(SOUND_EXPLOg1, pos, 0.5f);
+ }
+
+ DeleteRank(i);
+ continue;
+ }
+
+ object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
+ m_particule[i].goal = m_particule[i].pos;
+ if ( object != 0 )
+ {
+ object->ExploObject(EXPLO_BURN, 0.0f, RetDecay(object->RetType()));
+
+ m_exploGunCounter ++;
+
+ if ( m_exploGunCounter%2 == 0 )
+ {
+ pos = m_particule[i].pos;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 0.0f;
+ dim.x = Math::Rand()*6.0f+6.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*1.0f+1.0f;
+ mass = 0.0f;
+ CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
+
+ pos.y += 1.0f;
+ total = (int)(2.0f*m_engine->RetParticuleDensity());
+ for ( 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;
+ CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
+ }
+ }
+
+ if ( m_exploGunCounter%4 == 0 )
+ {
+ Play(SOUND_EXPLOg1, pos, 0.5f);
+ }
+
+ DeleteRank(i);
+ continue;
+ }
+ }
+
+ m_particule[i].angle -= rTime*Math::PI*8.0f;
+ m_particule[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_particule[i].type == PARTIGUN2 ) // ant shot?
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( m_particule[i].testTime >= 0.2f )
+ {
+ m_particule[i].testTime = 0.0f;
+ object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
+ m_particule[i].goal = m_particule[i].pos;
+ if ( object != 0 )
+ {
+ if ( object->RetShieldRadius() > 0.0f ) // protected by shield?
+ {
+ CreateParticule(m_particule[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_particule[i].pos, 1.0f);
+ }
+ DeleteRank(i);
+ continue;
+ }
+ else
+ {
+ if ( object->RetType() != OBJECT_HUMAN )
+ {
+ Play(SOUND_TOUCH, m_particule[i].pos, 1.0f);
+ }
+ object->ExploObject(EXPLO_BOUM, 0.0f); // starts explosion
+ }
+ }
+ }
+
+ m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
+ m_particule[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_particule[i].type == PARTIGUN3 ) // spider suicides?
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( m_particule[i].testTime >= 0.2f )
+ {
+ m_particule[i].testTime = 0.0f;
+ object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
+ m_particule[i].goal = m_particule[i].pos;
+ if ( object != 0 )
+ {
+ if ( object->RetShieldRadius() > 0.0f )
+ {
+ CreateParticule(m_particule[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_particule[i].pos, 1.0f);
+ }
+ DeleteRank(i);
+ continue;
+ }
+ else
+ {
+ object->ExploObject(EXPLO_BURN, 1.0f); // starts explosion
+ }
+ }
+ }
+
+//? ts.x = 0.875f;
+//? ts.y = 0.750f;
+ ts.x = 0.500f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIGUN4 ) // orgaball shot?
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( m_particule[i].testTime >= 0.1f )
+ {
+ m_particule[i].testTime = 0.0f;
+
+ if ( m_terrain->RetFloorHeight(m_particule[i].pos, true) < -2.0f )
+ {
+ m_exploGunCounter ++;
+
+ if ( m_exploGunCounter%2 == 0 )
+ {
+ pos = m_particule[i].goal;
+ m_terrain->MoveOnFloor(pos, true);
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 0.0f;
+ dim.x = Math::Rand()*4.0f+2.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*0.7f+0.7f;
+ mass = 0.0f;
+ CreateParticule(pos, speed, dim, PARTIEXPLOG2, duration, mass, 1.0f);
+ }
+
+ if ( m_exploGunCounter%4 == 0 )
+ {
+ Play(SOUND_EXPLOg2, pos, 0.5f);
+ }
+
+ DeleteRank(i);
+ continue;
+ }
+
+ object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
+ m_particule[i].goal = m_particule[i].pos;
+ if ( object != 0 )
+ {
+ object->ExploObject(EXPLO_BOUM, 0.0f, RetDecay(object->RetType()));
+
+ m_exploGunCounter ++;
+
+ if ( m_exploGunCounter%2 == 0 )
+ {
+ pos = m_particule[i].pos;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 0.0f;
+ dim.x = Math::Rand()*4.0f+2.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*0.7f+0.7f;
+ mass = 0.0f;
+ CreateParticule(pos, speed, dim, PARTIEXPLOG2, duration, mass, 1.0f);
+ }
+
+ if ( m_exploGunCounter%4 == 0 )
+ {
+ Play(SOUND_EXPLOg2, pos, 0.5f);
+ }
+
+ DeleteRank(i);
+ continue;
+ }
+ }
+
+ m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
+ m_particule[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_particule[i].type == PARTIFLIC )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 0.1f+progress;
+ m_particule[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_particule[i].type == PARTISHOW )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.5f ) m_particule[i].intensity = progress/0.5f;
+ else m_particule[i].intensity = 2.0f-progress/0.5f;
+ m_particule[i].zoom = 1.0f-progress*0.8f;
+ m_particule[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_particule[i].type == PARTICHOC )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 0.1f+progress;
+ m_particule[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_particule[i].type == PARTIGFLAT )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 0.1f+progress;
+ m_particule[i].intensity = 1.0f-progress;
+ m_particule[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_particule[i].type == PARTILIMIT1 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f;
+ m_particule[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_particule[i].type == PARTILIMIT2 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f;
+ m_particule[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_particule[i].type == PARTILIMIT3 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f;
+ m_particule[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_particule[i].type == PARTIFOG0 )
+ {
+ m_particule[i].zoom = progress;
+ m_particule[i].intensity = 0.3f+sinf(progress)*0.15f;
+ m_particule[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_particule[i].type == PARTIFOG1 )
+ {
+ m_particule[i].zoom = progress;
+ m_particule[i].intensity = 0.3f+sinf(progress)*0.15f;
+ m_particule[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_particule[i].type == PARTIFOG2 )
+ {
+ m_particule[i].zoom = progress;
+ m_particule[i].intensity = 0.6f+sinf(progress)*0.15f;
+ m_particule[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_particule[i].type == PARTIFOG3 )
+ {
+ m_particule[i].zoom = progress;
+ m_particule[i].intensity = 0.6f+sinf(progress)*0.15f;
+ m_particule[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_particule[i].type == PARTIFOG4 )
+ {
+ m_particule[i].zoom = progress;
+ m_particule[i].intensity = 0.5f+sinf(progress)*0.2f;
+ m_particule[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_particule[i].type == PARTIFOG5 )
+ {
+ m_particule[i].zoom = progress;
+ m_particule[i].intensity = 0.5f+sinf(progress)*0.2f;
+ m_particule[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_particule[i].type == PARTIFOG6 )
+ {
+ m_particule[i].zoom = progress;
+ m_particule[i].intensity = 0.5f+sinf(progress)*0.2f;
+ m_particule[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_particule[i].type == PARTIFOG7 )
+ {
+ m_particule[i].zoom = progress;
+ m_particule[i].intensity = 0.5f+sinf(progress)*0.2f;
+ m_particule[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_particule[i].type >= PARTIFOG0 &&
+ m_particule[i].type <= PARTIFOG9 )
+ {
+ h = 10.0f;
+
+ if ( m_particule[i].pos.y >= eye.y &&
+ m_particule[i].pos.y < eye.y+h )
+ {
+ m_particule[i].intensity *= (m_particule[i].pos.y-eye.y)/h;
+ }
+ if ( m_particule[i].pos.y > eye.y-h &&
+ m_particule[i].pos.y < eye.y )
+ {
+ m_particule[i].intensity *= (eye.y-m_particule[i].pos.y)/h;
+ }
+ }
+
+ if ( m_particule[i].type == PARTIEXPLOT ||
+ m_particule[i].type == PARTIEXPLOO )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-progress/2.0f;
+ m_particule[i].intensity = 1.0f-progress;
+
+ if ( m_particule[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_particule[i].type == PARTIEXPLOG1 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[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_particule[i].type == PARTIEXPLOG2 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[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_particule[i].type == PARTIFLAME )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-progress/2.0f;
+ if ( progress < 0.5f )
+ {
+ m_particule[i].intensity = progress/0.5f;
+ }
+ else
+ {
+ m_particule[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_particule[i].type == PARTIBUBBLE )
+ {
+ if ( progress >= 1.0f ||
+ m_particule[i].pos.y >= m_water->RetLevel() )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-progress/2.0f;
+ m_particule[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_particule[i].type == PARTISMOKE1 ||
+ m_particule[i].type == PARTISMOKE2 ||
+ m_particule[i].type == PARTISMOKE3 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.25f )
+ {
+ m_particule[i].zoom = progress/0.25f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f;
+ }
+
+ ts.x = 0.500f+0.125f*(m_particule[i].type-PARTISMOKE1);
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIBLOOD )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[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_particule[i].type == PARTIBLOODM )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[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_particule[i].type == PARTIVIRUS1 ||
+ m_particule[i].type == PARTIVIRUS2 ||
+ m_particule[i].type == PARTIVIRUS3 ||
+ m_particule[i].type == PARTIVIRUS4 ||
+ m_particule[i].type == PARTIVIRUS5 ||
+ m_particule[i].type == PARTIVIRUS6 ||
+ m_particule[i].type == PARTIVIRUS7 ||
+ m_particule[i].type == PARTIVIRUS8 ||
+ m_particule[i].type == PARTIVIRUS9 ||
+ m_particule[i].type == PARTIVIRUS10 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.25f )
+ {
+ m_particule[i].zoom = progress/0.25f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f;
+ }
+ m_particule[i].angle += rTime*Math::PI*1.0f;
+
+ if ( m_particule[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_particule[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_particule[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_particule[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_particule[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_particule[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_particule[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_particule[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_particule[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_particule[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_particule[i].type == PARTIBLUE )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[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_particule[i].type == PARTIROOT )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.25f )
+ {
+ m_particule[i].zoom = progress/0.25f;
+ }
+ else
+ {
+ m_particule[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_particule[i].type == PARTIRECOVER )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.25f )
+ {
+ m_particule[i].zoom = progress/0.25f;
+ }
+ else
+ {
+ m_particule[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_particule[i].type == PARTIEJECT )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f+powf(progress, 2.0f)*5.0f;
+ m_particule[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_particule[i].type == PARTISCRAPS )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[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_particule[i].type == PARTIFRAG )
+ {
+ m_particule[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_particule[i].type == PARTIPART )
+ {
+ ts.x = 0.0f;
+ ts.y = 0.0f;
+ ti.x = 0.0f;
+ ti.y = 0.0f;
+ }
+
+ if ( m_particule[i].type == PARTIQUEUE )
+ {
+ if ( m_particule[i].testTime >= 0.05f )
+ {
+ m_particule[i].testTime = 0.0f;
+
+ Math::Vector pos, speed;
+ Math::Point dim;
+
+ pos = m_particule[i].pos;
+//? speed = -m_particule[i].speed*0.5f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 1.0f*(Math::Rand()*0.8f+0.6f);
+ dim.y = dim.x;
+ CreateParticule(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_particule[i].type == PARTIORGANIC1 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+
+ pos = m_particule[i].pos;
+ dim.x = m_particule[i].dim.x/4.0f;
+ dim.y = dim.x;
+ duration = m_particule[i].duration;
+ mass = m_particule[i].mass;
+ total = (int)(10.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<total ; i++ )
+ {
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.y = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ CreateParticule(pos, speed, dim, PARTIORGANIC2, duration, mass);
+ }
+ total = (int)(5.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<total ; i++ )
+ {
+ 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_particule[i].zoom = (m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.125f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIORGANIC2 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.125f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIGLINT )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress > 0.5f )
+ {
+//? m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration/2.0f);
+ m_particule[i].zoom = 1.0f-(progress-0.5f)*2.0f;
+ }
+ m_particule[i].angle = m_particule[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_particule[i].type == PARTIGLINTb )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress > 0.5f )
+ {
+ m_particule[i].zoom = 1.0f-(progress-0.5f)*2.0f;
+ }
+ m_particule[i].angle = m_particule[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_particule[i].type == PARTIGLINTr )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress > 0.5f )
+ {
+ m_particule[i].zoom = 1.0f-(progress-0.5f)*2.0f;
+ }
+ m_particule[i].angle = m_particule[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_particule[i].type >= PARTILENS1 &&
+ m_particule[i].type <= PARTILENS4 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.5f )
+ {
+ m_particule[i].zoom = progress*2.0f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.5f)*2.0f;
+ }
+//? m_particule[i].angle = m_particule[i].time*Math::PI;
+
+ ts.x = 0.25f*(m_particule[i].type-PARTILENS1);
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTICONTROL )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.3f )
+ {
+ m_particule[i].zoom = progress/0.3f;
+ }
+ else
+ {
+ m_particule[i].zoom = 1.0f;
+ m_particule[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_particule[i].type == PARTIGUNDEL )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress > 0.5f )
+ {
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration/2.0f);
+ }
+ m_particule[i].angle = m_particule[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_particule[i].type == PARTIQUARTZ )
+ {
+ if ( progress >= 1.0f )
+ {
+ m_particule[i].time = 0.0f;
+ m_particule[i].duration = 0.5f+Math::Rand()*2.0f;
+ m_particule[i].pos.x = m_particule[i].speed.x + (Math::Rand()-0.5f)*m_particule[i].mass;
+ m_particule[i].pos.y = m_particule[i].speed.y + (Math::Rand()-0.5f)*m_particule[i].mass;
+ m_particule[i].pos.z = m_particule[i].speed.z + (Math::Rand()-0.5f)*m_particule[i].mass;
+ m_particule[i].dim.x = 0.5f+Math::Rand()*1.5f;
+ m_particule[i].dim.y = m_particule[i].dim.x;
+ progress = 0.0f;
+ }
+
+ if ( progress < 0.2f )
+ {
+ m_particule[i].zoom = progress/0.2f;
+ m_particule[i].intensity = 1.0f;
+ }
+ else
+ {
+ m_particule[i].zoom = 1.0f;
+ m_particule[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_particule[i].type == PARTITOTO )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-progress;
+ if ( progress < 0.15f )
+ {
+ m_particule[i].intensity = progress/0.15f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.15f)/0.85f;
+ }
+ m_particule[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_particule[i].type == PARTIERROR )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = progress*1.0f;
+ m_particule[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_particule[i].type == PARTIWARNING )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = progress*1.0f;
+ m_particule[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_particule[i].type == PARTIINFO )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = progress*1.0f;
+ m_particule[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_particule[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_particule[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_particule[i].type == PARTISPHERE0 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = progress*m_particule[i].dim.x;
+//? m_particule[i].intensity = 1.0f-progress;
+ if ( progress < 0.65f )
+ {
+ m_particule[i].intensity = progress/0.65f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.65f)/0.35f;
+ }
+ m_particule[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_particule[i].type == PARTISPHERE1 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.30f )
+ {
+ m_particule[i].intensity = progress/0.30f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.30f)/0.70f;
+ }
+ m_particule[i].zoom = progress*m_particule[i].dim.x;
+ m_particule[i].angle = m_particule[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_particule[i].type == PARTISPHERE2 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.20f )
+ {
+ m_particule[i].intensity = 1.0f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.20f)/0.80f;
+ }
+ m_particule[i].zoom = progress*m_particule[i].dim.x;
+ m_particule[i].angle = m_particule[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_particule[i].type == PARTISPHERE3 )
+ {
+ if ( m_particule[i].phase == PARPHEND &&
+ progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( m_particule[i].phase == PARPHSTART )
+ {
+ m_particule[i].intensity = progress;
+ if ( m_particule[i].intensity > 1.0f )
+ {
+ m_particule[i].intensity = 1.0f;
+ }
+ }
+
+ if ( m_particule[i].phase == PARPHEND )
+ {
+ m_particule[i].intensity = 1.0f-progress;
+ }
+
+ m_particule[i].zoom = m_particule[i].dim.x;
+ m_particule[i].angle = m_particule[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_particule[i].type == PARTISPHERE4 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = progress*m_particule[i].dim.x;
+ if ( progress < 0.65f )
+ {
+ m_particule[i].intensity = progress/0.65f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.65f)/0.35f;
+ }
+ m_particule[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_particule[i].type == PARTISPHERE5 )
+ {
+ m_particule[i].intensity = 0.7f+sinf(progress)*0.3f;
+ m_particule[i].zoom = m_particule[i].dim.x*(1.0f+sinf(progress*0.7f)*0.01f);
+ m_particule[i].angle = m_particule[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_particule[i].type == PARTISPHERE6 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = (1.0f-progress)*m_particule[i].dim.x;
+ m_particule[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_particule[i].type == PARTIPLOUF0 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = progress;
+#if 0
+ if ( progress <= 0.5f )
+ {
+ m_particule[i].intensity = 1.0f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.5f)/0.5f;
+ }
+#else
+//? m_particule[i].intensity = 1.0f;
+ m_particule[i].intensity = 1.0f-progress;
+#endif
+
+ ts.x = 0.50f;
+ ts.y = 0.50f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTIDROP )
+ {
+ if ( progress >= 1.0f ||
+ m_particule[i].pos.y < m_water->RetLevel() )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-progress;
+ m_particule[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_particule[i].type == PARTIWATER )
+ {
+ if ( progress >= 1.0f ||
+ m_particule[i].pos.y < m_water->RetLevel() )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[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_particule[i].type == PARTIRAY1 ) // rayon tour ?
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( m_particule[i].testTime >= 0.2f )
+ {
+ m_particule[i].testTime = 0.0f;
+ object = SearchObjectRay(m_particule[i].pos, m_particule[i].goal,
+ m_particule[i].type, m_particule[i].objFather);
+ if ( object != 0 )
+ {
+ 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_particule[i].type == PARTIRAY2 ||
+ m_particule[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;
+ }
+
+ dp = (1.0f/256.0f)/2.0f;
+ m_particule[i].texSup.x = ts.x+dp;
+ m_particule[i].texSup.y = ts.y+dp;
+ m_particule[i].texInf.x = ti.x-dp;
+ m_particule[i].texInf.y = ti.y-dp;
+ m_particule[i].time += rTime;
+ m_particule[i].testTime += rTime;
+ }
+}
+
+
+// Moves a drag.
+// Returns true if the drag is finished.
+
+bool CParticule::TrackMove(int i, Math::Vector pos, float progress)
+{
+ Math::Vector last;
+ int h, hh;
+
+ if ( i < 0 || i >= MAXTRACK ) return true;
+ if ( m_track[i].bUsed == false ) return true;
+
+ if ( progress < 1.0f ) // particle exists?
+ {
+ h = m_track[i].head;
+
+ if ( m_track[i].used == 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].used < MAXTRACKLEN ) m_track[i].used ++;
+ }
+ else
+ {
+ 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;
+ m_track[i].intensity = 1.0f-progress;
+ }
+ else // mort lente de la tra�n�e ?
+ {
+//? m_track[i].intensity = 1.0f-(progress-1.0f)/(m_track[i].step*MAXTRACKLEN);
+ m_track[i].intensity = 0.0f;
+ }
+
+ return (m_track[i].intensity <= 0.0f);
+}
+
+// Draws a drag.
+
+void CParticule::TrackDraw(int i, ParticuleType type)
+{
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Vector corner[4], p1, p2, p, n, eye;
+ Math::Matrix matrix;
+ Math::Point texInf, texSup, rot;
+ float lTotal, f1, f2, a;
+ int counter, h;
+
+ // Calculates the total length memorized.
+ lTotal = 0.0f;
+ h = m_track[i].head;
+ for ( counter=0 ; counter<m_track[i].used-1 ; counter++ )
+ {
+ lTotal += m_track[i].len[h];
+ h --; if ( h < 0 ) h = MAXTRACKLEN-1;
+ }
+
+ matrix.LoadIdentity();
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ 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;
+ p1 = m_track[i].pos[h];
+ f1 = m_track[i].intensity;
+
+ eye = m_engine->RetEyePt();
+ a = Math::RotateAngle(eye.x-p1.x, eye.z-p1.z);
+
+ for ( counter=0 ; counter<m_track[i].used-1 ; counter++ )
+ {
+ f2 = f1-(m_track[i].len[h]/lTotal);
+ if ( f2 < 0.0f ) f2 = 0.0f;
+ h --; if ( h < 0 ) h = MAXTRACKLEN-1;
+ p2 = m_track[i].pos[h];
+
+ n = Normalize(p1-eye);
+
+ 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] = D3DVERTEX2(corner[1], n, texSup.x, texSup.y);
+ vertex[1] = D3DVERTEX2(corner[0], n, texInf.x, texSup.y);
+ vertex[2] = D3DVERTEX2(corner[3], n, texSup.x, texInf.y);
+ vertex[3] = D3DVERTEX2(corner[2], n, texInf.x, texInf.y);
+ }
+ else
+ {
+ vertex[0] = D3DVERTEX2(corner[0], n, texSup.x, texSup.y);
+ vertex[1] = D3DVERTEX2(corner[1], n, texInf.x, texSup.y);
+ vertex[2] = D3DVERTEX2(corner[2], n, texSup.x, texInf.y);
+ vertex[3] = D3DVERTEX2(corner[3], n, texInf.x, texInf.y);
+ }
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+
+ if ( f2 < 0.0f ) break;
+ f1 = f2;
+ p1 = p2;
+ }
+}
+
+// Draws a triangular particle.
+
+void CParticule::DrawParticuleTriangle(int i)
+{
+ CObject* object;
+ Math::Matrix matrix;
+ Math::Vector eye, pos, angle;
+
+ if ( m_particule[i].zoom == 0.0f ) return;
+
+ eye = m_engine->RetEyePt();
+ pos = m_particule[i].pos;
+
+ object = m_particule[i].objLink;
+ if ( object != 0 )
+ {
+ pos += object->RetPosition(0);
+ }
+
+ 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_particule[i].angle;
+
+ Math::LoadRotationXZYMatrix(matrix, angle);
+ matrix.Set(1, 4, pos.x);
+ matrix.Set(2, 4, pos.y);
+ matrix.Set(3, 4, pos.z);
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_VERTEX2,
+ m_triangle[i].triangle, 3, NULL);
+ m_engine->AddStatisticTriangle(1);
+}
+
+// Draw a normal particle.
+
+void CParticule::DrawParticuleNorm(int i)
+{
+ CObject* object;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Matrix matrix;
+ Math::Vector corner[4], eye, pos, n, angle;
+ Math::Point dim;
+ float zoom;
+
+ zoom = m_particule[i].zoom;
+ if ( !m_engine->RetStateColor() && m_particule[i].intensity < 0.5f )
+ {
+ zoom *= m_particule[i].intensity/0.5f;
+ }
+
+ if ( zoom == 0.0f ) return;
+ if ( m_particule[i].intensity == 0.0f ) return;
+
+ if ( m_particule[i].sheet == SH_INTERFACE )
+ {
+ pos = m_particule[i].pos;
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f);
+
+ dim.x = m_particule[i].dim.x * zoom;
+ dim.y = m_particule[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] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y);
+ vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y);
+ vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y);
+ vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+ }
+ else
+ {
+ eye = m_engine->RetEyePt();
+ pos = m_particule[i].pos;
+
+ object = m_particule[i].objLink;
+ if ( object != 0 )
+ {
+ pos += object->RetPosition(0);
+ }
+
+ 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_particule[i].angle;
+
+ Math::LoadRotationXZYMatrix(matrix, angle);
+ matrix.Set(1, 4, pos.x);
+ matrix.Set(2, 4, pos.y);
+ matrix.Set(3, 4, pos.z);
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f);
+
+ dim.x = m_particule[i].dim.x * zoom;
+ dim.y = m_particule[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] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y);
+ vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y);
+ vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y);
+ vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+ }
+}
+
+// Draw a particle flat (horizontal).
+
+void CParticule::DrawParticuleFlat(int i)
+{
+ CObject* object;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Matrix matrix;
+ Math::Vector corner[4], pos, n, angle, eye;
+ Math::Point dim;
+
+ if ( m_particule[i].zoom == 0.0f ) return;
+ if ( m_particule[i].intensity == 0.0f ) return;
+
+ pos = m_particule[i].pos;
+
+ object = m_particule[i].objLink;
+ if ( object != 0 )
+ {
+ pos += object->RetPosition(0);
+ }
+
+ angle.x = Math::PI/2.0f;
+ angle.y = 0.0f;
+ angle.z = m_particule[i].angle;
+
+#if 0
+ if ( m_engine->RetRankView() == 1 ) // underwater?
+ {
+ angle.x = -Math::PI/2.0f;
+ pos.y -= 1.0f;
+ }
+#else
+ if ( m_engine->RetRankView() == 1 ) // underwater?
+ {
+ pos.y -= 1.0f;
+ }
+
+ eye = m_engine->RetEyePt();
+ if ( pos.y > eye.y ) // seen from below?
+ {
+ angle.x = -Math::PI/2.0f;
+ }
+#endif
+
+ Math::LoadRotationXZYMatrix(matrix, angle);
+ matrix.Set(1, 4, pos.x);
+ matrix.Set(2, 4, pos.y);
+ matrix.Set(3, 4, pos.z);
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f);
+
+ dim.x = m_particule[i].dim.x * m_particule[i].zoom;
+ dim.y = m_particule[i].dim.y * m_particule[i].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] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y);
+ vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y);
+ vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y);
+ vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+}
+
+// Draw a particle to a flat sheet of fog.
+
+void CParticule::DrawParticuleFog(int i)
+{
+ CObject* object;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Matrix matrix;
+ Math::Vector corner[4], pos, n, angle, eye;
+ Math::Point dim, zoom;
+
+ if ( !m_engine->RetFog() ) return;
+ if ( m_particule[i].intensity == 0.0f ) return;
+
+ pos = m_particule[i].pos;
+
+ dim.x = m_particule[i].dim.x;
+ dim.y = m_particule[i].dim.y;
+
+ if ( m_particule[i].type == PARTIFOG0 ||
+ m_particule[i].type == PARTIFOG2 ||
+ m_particule[i].type == PARTIFOG4 ||
+ m_particule[i].type == PARTIFOG6 )
+ {
+//? pos.x += sinf(m_particule[i].zoom*1.2f)*dim.x*0.1f;
+//? pos.y += cosf(m_particule[i].zoom*1.5f)*dim.y*0.1f;
+ zoom.x = 1.0f+sinf(m_particule[i].zoom*2.0f)/6.0f;
+ zoom.y = 1.0f+cosf(m_particule[i].zoom*2.7f)/6.0f;
+ }
+ if ( m_particule[i].type == PARTIFOG1 ||
+ m_particule[i].type == PARTIFOG3 ||
+ m_particule[i].type == PARTIFOG5 ||
+ m_particule[i].type == PARTIFOG7 )
+ {
+//? pos.x += sinf(m_particule[i].zoom*1.0f)*dim.x*0.1f;
+//? pos.y += cosf(m_particule[i].zoom*1.3f)*dim.y*0.1f;
+ zoom.x = 1.0f+sinf(m_particule[i].zoom*3.0f)/6.0f;
+ zoom.y = 1.0f+cosf(m_particule[i].zoom*3.7f)/6.0f;
+ }
+
+ dim.x *= zoom.x;
+ dim.y *= zoom.y;
+
+ object = m_particule[i].objLink;
+ if ( object != 0 )
+ {
+ pos += object->RetPosition(0);
+ }
+
+ angle.x = Math::PI/2.0f;
+ angle.y = 0.0f;
+ angle.z = m_particule[i].angle;
+
+ if ( m_engine->RetRankView() == 1 ) // underwater?
+ {
+ pos.y -= 1.0f;
+ }
+
+ eye = m_engine->RetEyePt();
+ if ( pos.y > eye.y ) // seen from below?
+ {
+ angle.x = -Math::PI/2.0f;
+ }
+
+ Math::LoadRotationXZYMatrix(matrix, angle);
+ matrix.Set(1, 4, pos.x);
+ matrix.Set(2, 4, pos.y);
+ matrix.Set(3, 4, pos.z);
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f);
+
+ 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] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y);
+ vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y);
+ vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y);
+ vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+}
+
+// Draw a particle in the form of radius.
+
+void CParticule::DrawParticuleRay(int i)
+{
+ CObject* object;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Matrix matrix;
+ Math::Vector corner[4], eye, pos, goal, n, angle, proj;
+ Math::Point dim, texInf, texSup;
+ bool bLeft;
+ float a, len, adv, prop, vario1, vario2;
+ int r, rank, step, first, last;
+
+ if ( m_particule[i].zoom == 0.0f ) return;
+ if ( m_particule[i].intensity == 0.0f ) return;
+
+ eye = m_engine->RetEyePt();
+ pos = m_particule[i].pos;
+ goal = m_particule[i].goal;
+
+ object = m_particule[i].objLink;
+ if ( object != 0 )
+ {
+ pos += object->RetPosition(0);
+ }
+
+ a = Math::RotateAngle(Math::Point(pos.x,pos.z), Math::Point(goal.x,goal.z), Math::Point(eye.x,eye.z));
+ bLeft = (a < Math::PI);
+
+ proj = Math::Projection(pos, goal, eye);
+ 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 ( bLeft ) angle.x = -angle.x;
+
+ Math::LoadRotationZXYMatrix(matrix, angle);
+ matrix.Set(1, 4, pos.x);
+ matrix.Set(2, 4, pos.y);
+ matrix.Set(3, 4, pos.z);
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ n = Math::Vector(0.0f, 0.0f, bLeft?1.0f:-1.0f);
+
+ dim.x = m_particule[i].dim.x * m_particule[i].zoom;
+ dim.y = m_particule[i].dim.y * m_particule[i].zoom;
+
+ if ( bLeft ) dim.y = -dim.y;
+
+ len = Math::Distance(pos, goal);
+ adv = 0.0f;
+
+ step = (int)(len/(dim.x*2.0f))+1;
+
+ if ( step == 1 )
+ {
+ vario1 = 1.0f;
+ vario2 = 1.0f;
+ }
+ else
+ {
+ vario1 = 0.0f;
+ vario2 = 2.0f;
+ }
+
+ if ( m_particule[i].type == PARTIRAY2 )
+ {
+ first = 0;
+ last = step;
+ vario1 = 0.0f;
+ vario2 = 0.0f;
+ }
+ else if ( m_particule[i].type == PARTIRAY3 )
+ {
+ if ( m_particule[i].time < m_particule[i].duration*0.40f )
+ {
+ prop = m_particule[i].time / (m_particule[i].duration*0.40f);
+ first = 0;
+ last = (int)(prop*step);
+ }
+ else if ( m_particule[i].time < m_particule[i].duration*0.60f )
+ {
+ first = 0;
+ last = step;
+ }
+ else
+ {
+ prop = (m_particule[i].time-m_particule[i].duration*0.60f) / (m_particule[i].duration*0.40f);
+ first = (int)(prop*step);
+ last = step;
+ }
+ }
+ else
+ {
+ if ( m_particule[i].time < m_particule[i].duration*0.50f )
+ {
+ prop = m_particule[i].time / (m_particule[i].duration*0.50f);
+ first = 0;
+ last = (int)(prop*step);
+ }
+ else if ( m_particule[i].time < m_particule[i].duration*0.75f )
+ {
+ first = 0;
+ last = step;
+ }
+ else
+ {
+ prop = (m_particule[i].time-m_particule[i].duration*0.75f) / (m_particule[i].duration*0.25f);
+ first = (int)(prop*step);
+ last = step;
+ }
+ }
+
+ 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;
+
+ for ( 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 )
+ {
+#if 1
+ texInf = m_particule[i].texInf;
+ texSup = m_particule[i].texSup;
+
+ r = rand()%16;
+ texInf.x += 0.25f*(r/4);
+ texSup.x += 0.25f*(r/4);
+ if ( r%2 < 1 && adv > 0.0f && m_particule[i].type != PARTIRAY1 )
+ {
+ Math::Swap(texInf.x, texSup.x);
+ }
+ if ( r%4 < 2 )
+ {
+ Math::Swap(texInf.y, texSup.y);
+ }
+#else
+ texInf.x = Math::Mod(texInf.x+0.25f, 1.0f);
+ texSup.x = Math::Mod(texSup.x+0.25f, 1.0f);
+#endif
+
+ vertex[0] = D3DVERTEX2(corner[1], n, texSup.x, texSup.y);
+ vertex[1] = D3DVERTEX2(corner[0], n, texInf.x, texSup.y);
+ vertex[2] = D3DVERTEX2(corner[3], n, texSup.x, texInf.y);
+ vertex[3] = D3DVERTEX2(corner[2], n, texInf.x, texInf.y);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+ }
+ adv += dim.x*2.0f;
+ }
+}
+
+// Draws a spherical particle.
+
+void CParticule::DrawParticuleSphere(int i)
+{
+ D3DVERTEX2 vertex[2*16*(16+1)]; // triangles
+ Math::Matrix matrix, rot;
+ Math::Vector angle, v0, v1;
+ Math::Point ts, ti;
+ float zoom, deltaRingAngle, deltaSegAngle;
+ float r0,r1, tu0,tv0, tu1,tv1;
+ int j, ring, seg, numRings, numSegments;
+
+ zoom = m_particule[i].zoom;
+#if 0
+ if ( !m_engine->RetStateColor() && m_particule[i].intensity < 0.5f )
+ {
+ zoom *= m_particule[i].intensity/0.5f;
+ }
+#endif
+
+ if ( zoom == 0.0f ) return;
+
+ m_engine->SetState(D3DSTATETTb|D3DSTATE2FACE|D3DSTATEWRAP, RetColor(m_particule[i].intensity));
+
+ matrix.LoadIdentity();
+ matrix.Set(1, 1, zoom);
+ matrix.Set(2, 2, zoom);
+ matrix.Set(3, 3, zoom);
+ matrix.Set(1, 4, m_particule[i].pos.x);
+ matrix.Set(2, 4, m_particule[i].pos.y);
+ matrix.Set(3, 4, m_particule[i].pos.z);
+
+ if ( m_particule[i].angle != 0.0f )
+ {
+ angle.x = m_particule[i].angle*0.4f;
+ angle.y = m_particule[i].angle*1.0f;
+ angle.z = m_particule[i].angle*0.7f;
+ Math::LoadRotationZXYMatrix(rot, angle);
+ matrix = Math::MultiplyMatrices(rot, matrix);
+ }
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ ts.x = m_particule[i].texSup.x;
+ ts.y = m_particule[i].texSup.y;
+ ti.x = m_particule[i].texInf.x;
+ ti.y = m_particule[i].texInf.y;
+
+ // Choose a tesselation level.
+ if ( m_particule[i].type == PARTISPHERE3 ||
+ m_particule[i].type == PARTISPHERE5 )
+ {
+ numRings = 16;
+ numSegments = 16;
+ }
+ else
+ {
+ numRings = 8;
+ numSegments = 10;
+ }
+
+ // Establish constants used in sphere generation.
+ deltaRingAngle = Math::PI/numRings;
+ deltaSegAngle = 2.0f*Math::PI/numSegments;
+
+ // Generate the group of rings for the sphere.
+ j = 0;
+ for ( ring=0 ; ring<numRings ; ring++ )
+ {
+ r0 = sinf((ring+0)*deltaRingAngle);
+ r1 = sinf((ring+1)*deltaRingAngle);
+ v0.y = cosf((ring+0)*deltaRingAngle);
+ v1.y = cosf((ring+1)*deltaRingAngle);
+
+ tv0 = (ring+0)/(float)numRings;
+ tv1 = (ring+1)/(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 ( 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.
+ tu0 = ((float)seg)/numSegments;
+ tu0 = ts.x+(ti.x-ts.x)*tu0;
+ tu1 = tu0;
+
+ vertex[j++] = D3DVERTEX2(v0,v0, tu0,tv0);
+ vertex[j++] = D3DVERTEX2(v1,v1, tu1,tv1);
+ }
+ }
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, j, NULL);
+ m_engine->AddStatisticTriangle(j);
+
+ m_engine->SetState(D3DSTATETTb, RetColor(m_particule[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));
+ }
+}
+
+// Draws a cylindrical particle.
+
+void CParticule::DrawParticuleCylinder(int i)
+{
+ D3DVERTEX2 vertex[2*5*(10+1)]; // triangles
+ Math::Matrix matrix, rot;
+ Math::Vector angle, v0, v1;
+ Math::Point ts, ti;
+ float progress, zoom, diam, deltaSegAngle, h[6], d[6];
+ float r0,r1, tu0,tv0, tu1,tv1, p1, p2, pp;
+ int j, ring, seg, numRings, numSegments;
+
+ progress = m_particule[i].zoom;
+ zoom = m_particule[i].dim.x;
+ diam = m_particule[i].dim.y;
+ if ( progress >= 1.0f || zoom == 0.0f ) return;
+
+ m_engine->SetState(D3DSTATETTb|D3DSTATE2FACE|D3DSTATEWRAP, RetColor(m_particule[i].intensity));
+
+ matrix.LoadIdentity();
+ matrix.Set(1, 1, zoom);
+ matrix.Set(2, 2, zoom);
+ matrix.Set(3, 3, zoom);
+ matrix.Set(1, 4, m_particule[i].pos.x);
+ matrix.Set(2, 4, m_particule[i].pos.y);
+ matrix.Set(3, 4, m_particule[i].pos.z);
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ ts.x = m_particule[i].texSup.x;
+ ts.y = m_particule[i].texSup.y;
+ ti.x = m_particule[i].texInf.x;
+ ti.y = m_particule[i].texInf.y;
+
+ numRings = 5;
+ numSegments = 10;
+ deltaSegAngle = 2.0f*Math::PI/numSegments;
+
+ if ( m_particule[i].type == PARTIPLOUF0 )
+ {
+#if 0
+ if ( progress <= 0.5f )
+ {
+ p1 = progress/0.5f; // front
+ p2 = 0.0f; // back
+ }
+ else
+ {
+ p1 = 1.0f; // front
+ p2 = (progress-0.5f)/0.5f; // back
+ ts.y += (ti.y-ts.y)*p2;
+ }
+#else
+ p1 = progress; // front
+ p2 = powf(progress, 5.0f); // back
+#endif
+
+ for ( ring=0 ; ring<=numRings ; ring++ )
+ {
+ pp = p2+(p1-p2)*((float)ring/numRings);
+ d[ring] = diam/zoom+pp*2.0f;
+ h[ring] = ProgressCylinder(pp);
+ }
+ }
+
+ j = 0;
+ for ( ring=0 ; ring<numRings ; ring++ )
+ {
+ r0 = 1.0f*d[ring+0]; // radius at the base
+ 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
+
+ tv0 = 1.0f-(ring+0)*(1.0f/numRings);
+ 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 ( 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);
+
+//? tu0 = ((float)seg)/numSegments;
+ tu0 = (seg%2)?0.0f:1.0f;
+ tu0 = ts.x+(ti.x-ts.x)*tu0;
+ tu1 = tu0;
+
+ vertex[j++] = D3DVERTEX2(v0,v0, tu0,tv0);
+ vertex[j++] = D3DVERTEX2(v1,v1, tu1,tv1);
+ }
+ }
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, j, NULL);
+ m_engine->AddStatisticTriangle(j);
+
+ m_engine->SetState(D3DSTATETTb, RetColor(m_particule[i].intensity));
+}
+
+// Draws a tire mark.
+
+void CParticule::DrawParticuleWheel(int i)
+{
+ Math::Vector pos[4], center;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Vector n;
+ Math::Point ts, ti;
+ float dist, dp;
+
+ dist = Math::DistanceProjected(m_engine->RetEyePt(), m_wheelTrace[i].pos[0]);
+ if ( dist > 300.0f ) return;
+
+ 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];
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+
+ n = Math::Vector(0.0f, 1.0f, 0.0f);
+
+ vertex[0] = D3DVERTEX2(pos[0], n, ts.x, ts.y);
+ vertex[1] = D3DVERTEX2(pos[1], n, ti.x, ts.y);
+ vertex[2] = D3DVERTEX2(pos[2], n, ts.x, ti.y);
+ vertex[3] = D3DVERTEX2(pos[3], n, ti.x, ti.y);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+}
+
+// Draws all the particles.
+
+void CParticule::DrawParticule(int sheet)
+{
+ D3DMATERIAL7 mat;
+ Math::Matrix matrix;
+ bool bLoadTexture;
+ char name[20];
+ int state, t, i, j, r;
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+
+ // Draw the basic particles of triangles.
+ if ( m_totalInterface[0][sheet] > 0 )
+ {
+ for ( i=0 ; i<MAXPARTICULE ; i++ )
+ {
+ if ( !m_particule[i].bUsed ) continue;
+ if ( m_particule[i].sheet != sheet ) continue;
+ if ( m_particule[i].type == PARTIPART ) continue;
+
+ m_engine->SetTexture(m_triangle[i].texName1);
+ m_engine->SetMaterial(m_triangle[i].material);
+ m_engine->SetState(m_triangle[i].state);
+ DrawParticuleTriangle(i);
+ }
+ }
+
+ // Draw the particles was calculated based on edge.
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
+
+ ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
+ 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 )
+ {
+#if _POLISH
+ m_engine->SetTexture("textp.tga");
+#else
+ m_engine->SetTexture("text.tga");
+#endif
+ m_engine->SetState(D3DSTATETTw);
+//? m_engine->SetState(D3DSTATENORMAL);
+ matrix.LoadIdentity();
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+ for ( i=0 ; i<m_wheelTraceTotal ; i++ )
+ {
+ DrawParticuleWheel(i);
+ }
+ }
+
+//? for ( t=1 ; t<MAXPARTITYPE ; t++ )
+ for ( t=MAXPARTITYPE-1 ; t>=1 ; t-- ) // black behind!
+ {
+ if ( m_totalInterface[t][sheet] == 0 ) continue;
+
+ bLoadTexture = false;
+
+ if ( t == 4 ) state = D3DSTATETTw; // text.tga
+ else state = D3DSTATETTb; // effect[00..02].tga
+ m_engine->SetState(state);
+
+ for ( j=0 ; j<MAXPARTICULE ; j++ )
+ {
+ i = MAXPARTICULE*t+j;
+ if ( !m_particule[i].bUsed ) continue;
+ if ( m_particule[i].sheet != sheet ) continue;
+
+ if ( !bLoadTexture )
+ {
+ NameParticule(name, t);
+ m_engine->SetTexture(name);
+ bLoadTexture = true;
+ }
+
+ r = m_particule[i].trackRank;
+ if ( r != -1 )
+ {
+ m_engine->SetState(state);
+ TrackDraw(r, m_particule[i].type); // draws the drag
+ if ( !m_track[r].bDrawParticule ) continue;
+ }
+
+ m_engine->SetState(state, RetColor(m_particule[i].intensity));
+
+ if ( m_particule[i].bRay ) // ray?
+ {
+ DrawParticuleRay(i);
+ }
+ else if ( m_particule[i].type == PARTIFLIC || // circle in the water?
+ m_particule[i].type == PARTISHOW ||
+ m_particule[i].type == PARTICHOC ||
+ m_particule[i].type == PARTIGFLAT )
+ {
+ DrawParticuleFlat(i);
+ }
+ else if ( m_particule[i].type >= PARTIFOG0 &&
+ m_particule[i].type <= PARTIFOG9 )
+ {
+ DrawParticuleFog(i);
+ }
+ else if ( m_particule[i].type >= PARTISPHERE0 &&
+ m_particule[i].type <= PARTISPHERE9 ) // sphere?
+ {
+ DrawParticuleSphere(i);
+ }
+ else if ( m_particule[i].type >= PARTIPLOUF0 &&
+ m_particule[i].type <= PARTIPLOUF4 ) // cylinder?
+ {
+ DrawParticuleCylinder(i);
+ }
+ else // normal?
+ {
+ DrawParticuleNorm(i);
+ }
+ }
+ }
+
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
+}
+
+
+// Seeks if an object collided with a bullet.
+
+CObject* CParticule::SearchObjectGun(Math::Vector old, Math::Vector pos,
+ ParticuleType type, CObject *father)
+{
+ CObject *pObj, *pBest;
+ Math::Vector box1, box2, oPos, p;
+ ObjectType oType;
+ bool bShield;
+ float min, oRadius, dist, shieldRadius;
+ int i, j;
+ bool bHimself;
+
+ if ( m_main->RetMovieLock() ) return 0; // current movie?
+
+ bHimself = m_main->RetHimselfDamage();
+
+ min = 5.0f;
+ if ( type == PARTIGUN2 ) min = 2.0f; // shooting insect?
+ if ( type == PARTIGUN3 ) min = 3.0f; // suiciding spider?
+
+ box1 = old;
+ 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;
+
+ pBest = 0;
+ bShield = false;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue; // inactive?
+ if ( pObj == father ) continue;
+
+ oType = pObj->RetType();
+
+ if ( oType == OBJECT_TOTO ) continue;
+
+ if ( type == PARTIGUN1 ) // fireball shooting?
+ {
+ if ( oType == OBJECT_MOTHER ) continue;
+ if ( bHimself ) // 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 ( bHimself ) // 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 ( bHimself ) // damage is oneself?
+ {
+ if ( !IsAlien(oType) &&
+ !IsSoft(oType) ) continue;
+ }
+ else // damage only to enemies?
+ {
+ if ( !IsAlien(oType) ) continue;
+ }
+ }
+ else
+ {
+ continue;
+ }
+
+ oPos = pObj->RetPosition(0);
+
+ if ( type == PARTIGUN2 || // shooting insect?
+ type == PARTIGUN3 ) // suiciding spider?
+ {
+ // Test if the ball is entered into the sphere of a shield.
+ shieldRadius = pObj->RetShieldRadius();
+ if ( shieldRadius > 0.0f )
+ {
+ dist = Math::Distance(oPos, pos);
+ if ( dist <= shieldRadius )
+ {
+ pBest = pObj;
+ bShield = true;
+ }
+ }
+ }
+ if ( bShield ) continue;
+
+ // Test the center of the object, which is necessary for objects
+ // that have no sphere in the center (station).
+ dist = Math::Distance(oPos, pos)-4.0f;
+ if ( dist < min )
+ {
+ pBest = pObj;
+ }
+
+ // Test with all spheres of the object.
+ j = 0;
+ while ( pObj->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;
+
+ p = Math::Projection(old, pos, oPos);
+ dist = Math::Distance(p, oPos)-oRadius;
+ if ( dist < min )
+ {
+ pBest = pObj;
+ }
+ }
+ }
+
+ return pBest;
+}
+
+// Seeks if an object collided with a ray.
+
+CObject* CParticule::SearchObjectRay(Math::Vector pos, Math::Vector goal,
+ ParticuleType type, CObject *father)
+{
+ CObject* pObj;
+ Math::Vector box1, box2, oPos, p;
+ ObjectType oType;
+ float min, dist;
+ int i;
+
+ if ( m_main->RetMovieLock() ) return 0; // current movie?
+
+ min = 10.0f;
+
+ box1 = pos;
+ 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 ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue; // inactive?
+ if ( pObj == father ) continue;
+
+ oType = pObj->RetType();
+
+ 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;
+
+ oPos = pObj->RetPosition(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;
+
+ p = Math::Projection(pos, goal, oPos);
+ dist = Math::Distance(p, oPos);
+ if ( dist < min ) return pObj;
+ }
+
+ return 0;
+}
+
+
+// Sounded one.
+
+void CParticule::Play(Sound sound, Math::Vector pos, float amplitude)
+{
+ if ( m_sound == 0 )
+ {
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ }
+
+ m_sound->Play(sound, pos, amplitude);
+}
+
+
+
+// Seeks the color if you're in the fog.
+// Returns black if you're not in the fog.
+
+D3DCOLORVALUE CParticule::RetFogColor(Math::Vector pos)
+{
+ D3DCOLORVALUE result, color;
+ float dist, factor;
+ int fog, i;
+
+ result.r = 0.0f;
+ result.g = 0.0f;
+ result.b = 0.0f;
+ result.a = 0.0f;
+
+ for ( fog=0 ; fog<m_fogTotal ; fog++ )
+ {
+ i = m_fog[fog]; // i = rank of the particle
+
+ if ( pos.y >= m_particule[i].pos.y+FOG_HSUP ) continue;
+ if ( pos.y <= m_particule[i].pos.y-FOG_HINF ) continue;
+
+ dist = Math::DistanceProjected(pos, m_particule[i].pos);
+ if ( dist >= m_particule[i].dim.x*1.5f ) continue;
+
+ // Calculates the horizontal distance.
+ factor = 1.0f-powf(dist/(m_particule[i].dim.x*1.5f), 4.0f);
+
+ // Calculates the vertical distance.
+ if ( pos.y > m_particule[i].pos.y )
+ {
+ factor *= 1.0f-(pos.y-m_particule[i].pos.y)/FOG_HSUP;
+ }
+ else
+ {
+ factor *= 1.0f-(m_particule[i].pos.y-pos.y)/FOG_HINF;
+ }
+
+ factor *= 0.3f;
+
+ if ( m_particule[i].type == PARTIFOG0 ||
+ m_particule[i].type == PARTIFOG1 ) // blue?
+ {
+ color.r = 0.0f;
+ color.g = 0.5f;
+ color.b = 1.0f;
+ }
+ else if ( m_particule[i].type == PARTIFOG2 ||
+ m_particule[i].type == PARTIFOG3 ) // red?
+ {
+ color.r = 2.0f;
+ color.g = 1.0f;
+ color.b = 0.0f;
+ }
+ else if ( m_particule[i].type == PARTIFOG4 ||
+ m_particule[i].type == PARTIFOG5 ) // white?
+ {
+ color.r = 1.0f;
+ color.g = 1.0f;
+ color.b = 1.0f;
+ }
+ else if ( m_particule[i].type == PARTIFOG6 ||
+ m_particule[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;
+}
+
+
+// Writes a file. BMP containing all the tire tracks.
+
+bool CParticule::WriteWheelTrace(char *filename, int width, int height,
+ Math::Vector dl, Math::Vector ur)
+{
+ HDC hDC;
+ HDC hDCImage;
+ HBITMAP hb;
+ PBITMAPINFO info;
+ HBRUSH hBrush;
+ HPEN hPen;
+ HGDIOBJ old;
+ RECT rect;
+ COLORREF color;
+ Math::Point pos[4];
+ POINT list[4];
+ int i;
+
+ if ( !m_engine->GetRenderDC(hDC) ) return false;
+
+ hDCImage = CreateCompatibleDC(hDC);
+ if ( hDCImage == 0 )
+ {
+ m_engine->ReleaseRenderDC(hDC);
+ return false;
+ }
+
+ hb = CreateCompatibleBitmap(hDC, width, height);
+ if ( hb == 0 )
+ {
+ DeleteDC(hDCImage);
+ m_engine->ReleaseRenderDC(hDC);
+ return false;
+ }
+
+ SelectObject(hDCImage, hb);
+
+ rect.left = 0;
+ rect.right = width;
+ rect.top = 0;
+ rect.bottom = height;
+ FillRect(hDCImage, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
+
+ hPen = CreatePen(PS_NULL, 1, 0);
+ SelectObject(hDCImage, hPen);
+
+ for ( i=0 ; i<m_wheelTraceTotal ; i++ )
+ {
+ if ( m_wheelTrace[i].type == PARTITRACE0 ) // black ground track?
+ {
+ color = RGB(0,0,0);
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE1 ) // red ground track?
+ {
+ color = RGB(255,0,0);
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE2 ) // green ground track?
+ {
+ color = RGB(0,255,0);
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE3 ) // blue ground track?
+ {
+ color = RGB(0,0,255);
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE4 ) // cyan ground track?
+ {
+ color = RGB(0,255,255);
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE5 ) // magenta ground track?
+ {
+ color = RGB(255,0,255);
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE6 ) // yellow ground track?
+ {
+ color = RGB(255,255,0);
+ }
+ else
+ {
+ color = RGB(0,0,0);
+ }
+ hBrush = CreateSolidBrush(color);
+ old = SelectObject(hDCImage, hBrush);
+
+ pos[0].x = ((m_wheelTrace[i].pos[0].x-dl.x)*width)/(ur.x-dl.x);
+ pos[0].y = ((m_wheelTrace[i].pos[0].z-dl.z)*width)/(ur.z-dl.z);
+ pos[1].x = ((m_wheelTrace[i].pos[1].x-dl.x)*width)/(ur.x-dl.x);
+ pos[1].y = ((m_wheelTrace[i].pos[1].z-dl.z)*width)/(ur.z-dl.z);
+ pos[2].x = ((m_wheelTrace[i].pos[2].x-dl.x)*width)/(ur.x-dl.x);
+ pos[2].y = ((m_wheelTrace[i].pos[2].z-dl.z)*width)/(ur.z-dl.z);
+ pos[3].x = ((m_wheelTrace[i].pos[3].x-dl.x)*width)/(ur.x-dl.x);
+ pos[3].y = ((m_wheelTrace[i].pos[3].z-dl.z)*width)/(ur.z-dl.z);
+
+ list[0].x = (int)pos[0].x;
+ list[0].y = (int)pos[0].y;
+ list[1].x = (int)pos[1].x;
+ list[1].y = (int)pos[1].y;
+ list[2].x = (int)pos[3].x;
+ list[2].y = (int)pos[3].y;
+ list[3].x = (int)pos[2].x;
+ list[3].y = (int)pos[2].y;
+ Polygon(hDCImage, list, 4);
+
+ if ( old != 0 ) SelectObject(hDCImage, old);
+ DeleteObject(hBrush);
+ }
+
+ info = m_engine->CreateBitmapInfoStruct(hb);
+ if ( info == 0 )
+ {
+ DeleteObject(hb);
+ DeleteDC(hDCImage);
+ m_engine->ReleaseRenderDC(hDC);
+ return false;
+ }
+
+ m_engine->CreateBMPFile(filename, info, hb, hDCImage);
+
+ DeleteObject(hb);
+ DeleteDC(hDCImage);
+ m_engine->ReleaseRenderDC(hDC);
+ return true;
+}
+
diff --git a/src/old/particule.h b/src/old/particule.h
index 23d0899..23c9838 100644
--- a/src/old/particule.h
+++ b/src/old/particule.h
@@ -1,337 +1,337 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// particule.h
-
-#pragma once
-
-
-#include "math/point.h"
-#include "old/d3dengine.h"
-#include "old/sound.h"
-
-
-class CInstanceManager;
-class CRobotMain;
-class CTerrain;
-class CWater;
-class CObject;
-
-
-const int MAXPARTICULE = 500;
-const int MAXPARTITYPE = 5;
-const int MAXTRACK = 100;
-const int MAXTRACKLEN = 10;
-const int MAXPARTIFOG = 100;
-const int MAXWHEELTRACE = 1000;
-
-enum ParticulePlace
-{
- SH_WORLD = 0, // particle in the world in the interface
- SH_FRONT = 1, // particle in the world on the interface
- SH_INTERFACE = 2, // particle in the interface
- SH_MAX = 3
-};
-
-// type == 0 -> triangles
-// type == 1 -> effect00 (black background)
-// type == 2 -> effect01 (black background)
-// type == 3 -> effect02 (black background)
-// type == 4 -> text (white background)
-
-
-enum ParticuleType
-{
- 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 ParticulePhase
-{
- PARPHSTART = 0,
- PARPHEND = 1,
-};
-
-struct Particule
-{
- char bUsed; // true -> particle used
- char bRay; // true -> ray with goal
- unsigned short uniqueStamp; // unique mark
- short sheet; // sheet (0..n)
- ParticuleType type; // type PARTI*
- ParticulePhase phase; // phase PARPH*
- float mass; // mass of the particle (in rebounding)
- float weight; // weight of the particle (for noise)
- float duration; // length of life
- Math::Vector pos; // absolute position (relative if object links)
- Math::Vector goal; // goal position (if bRay)
- Math::Vector speed; // speed of displacement
- float windSensitivity;
- short bounce; // number of rebounds
- Math::Point dim; // dimensions of the rectangle
- float zoom; // zoom (0..1)
- float angle; // angle of rotation
- float intensity; // intensity
- Math::Point texSup; // coordinated upper texture
- Math::Point texInf; // coordinated lower texture
- float time; // age of the particle (0..n)
- float phaseTime; // age at the beginning of phase
- float testTime; // time since last test
- CObject* objLink; // father object (for example reactor)
- CObject* objFather; // father object (for example reactor)
- short objRank; // rank of the object, or -1
- short trackRank; // rank of the drag
-};
-
-struct Track
-{
- char bUsed; // true -> drag used
- char bDrawParticule;
- float step; // duration of not
- float last; // increase last not memorized
- float intensity; // intensity at starting (0..1)
- float width; // tail width
- int used; // number of positions in "pos"
- int head; // head to write index
- Math::Vector pos[MAXTRACKLEN];
- float len[MAXTRACKLEN];
-};
-
-struct WheelTrace
-{
- ParticuleType type; // type PARTI*
- Math::Vector pos[4]; // rectangle positions
- float startTime; // beginning of life
-};
-
-
-
-class CParticule
-{
-public:
- CParticule(CInstanceManager* iMan, CD3DEngine* engine);
- ~CParticule();
-
- void SetD3DDevice(LPDIRECT3DDEVICE7 device);
-
- void FlushParticule();
- void FlushParticule(int sheet);
- int CreateParticule(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticuleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0);
- int CreateFrag(Math::Vector pos, Math::Vector speed, D3DTriangle *triangle, ParticuleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0);
- int CreatePart(Math::Vector pos, Math::Vector speed, ParticuleType type, float duration=1.0f, float mass=0.0f, float weight=0.0f, float windSensitivity=1.0f, int sheet=0);
- int CreateRay(Math::Vector pos, Math::Vector goal, ParticuleType type, Math::Point dim, float duration=1.0f, int sheet=0);
- int CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticuleType type, float duration=1.0f, float mass=0.0f, float length=10.0f, float width=1.0f);
- void CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3, const Math::Vector &p4, ParticuleType type);
- void DeleteParticule(ParticuleType type);
- void DeleteParticule(int channel);
- void SetObjectLink(int channel, CObject *object);
- void SetObjectFather(int channel, CObject *object);
- void SetPosition(int channel, Math::Vector pos);
- void SetDimension(int channel, Math::Point dim);
- void SetZoom(int channel, float zoom);
- void SetAngle(int channel, float angle);
- 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, ParticulePhase phase, float duration);
- bool GetPosition(int channel, Math::Vector &pos);
-
- D3DCOLORVALUE RetFogColor(Math::Vector pos);
-
- void SetFrameUpdate(int sheet, bool bUpdate);
- void FrameParticule(float rTime);
- void DrawParticule(int sheet);
-
- bool WriteWheelTrace(char *filename, int width, int height, Math::Vector dl, Math::Vector ur);
-
-protected:
- void DeleteRank(int rank);
- bool CheckChannel(int &channel);
- void DrawParticuleTriangle(int i);
- void DrawParticuleNorm(int i);
- void DrawParticuleFlat(int i);
- void DrawParticuleFog(int i);
- void DrawParticuleRay(int i);
- void DrawParticuleSphere(int i);
- void DrawParticuleCylinder(int i);
- void DrawParticuleWheel(int i);
- CObject* SearchObjectGun(Math::Vector old, Math::Vector pos, ParticuleType type, CObject *father);
- CObject* SearchObjectRay(Math::Vector pos, Math::Vector goal, ParticuleType type, CObject *father);
- void Play(Sound sound, Math::Vector pos, float amplitude);
- bool TrackMove(int i, Math::Vector pos, float progress);
- void TrackDraw(int i, ParticuleType type);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- LPDIRECT3DDEVICE7 m_pD3DDevice;
- CRobotMain* m_main;
- CTerrain* m_terrain;
- CWater* m_water;
- CSound* m_sound;
-
- Particule m_particule[MAXPARTICULE*MAXPARTITYPE];
- D3DTriangle m_triangle[MAXPARTICULE]; // triangle if PartiType == 0
- Track m_track[MAXTRACK];
- int m_wheelTraceTotal;
- int m_wheelTraceIndex;
- WheelTrace m_wheelTrace[MAXWHEELTRACE];
- int m_totalInterface[MAXPARTITYPE][SH_MAX];
- bool m_bFrameUpdate[SH_MAX];
- int m_fogTotal;
- int m_fog[MAXPARTIFOG];
- int m_uniqueStamp;
- int m_exploGunCounter;
- float m_lastTimeGunDel;
- float m_absTime;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// particule.h
+
+#pragma once
+
+
+#include "math/point.h"
+#include "old/d3dengine.h"
+#include "old/sound.h"
+
+
+class CInstanceManager;
+class CRobotMain;
+class CTerrain;
+class CWater;
+class CObject;
+
+
+const int MAXPARTICULE = 500;
+const int MAXPARTITYPE = 5;
+const int MAXTRACK = 100;
+const int MAXTRACKLEN = 10;
+const int MAXPARTIFOG = 100;
+const int MAXWHEELTRACE = 1000;
+
+enum ParticulePlace
+{
+ SH_WORLD = 0, // particle in the world in the interface
+ SH_FRONT = 1, // particle in the world on the interface
+ SH_INTERFACE = 2, // particle in the interface
+ SH_MAX = 3
+};
+
+// type == 0 -> triangles
+// type == 1 -> effect00 (black background)
+// type == 2 -> effect01 (black background)
+// type == 3 -> effect02 (black background)
+// type == 4 -> text (white background)
+
+
+enum ParticuleType
+{
+ 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 ParticulePhase
+{
+ PARPHSTART = 0,
+ PARPHEND = 1,
+};
+
+struct Particule
+{
+ char bUsed; // true -> particle used
+ char bRay; // true -> ray with goal
+ unsigned short uniqueStamp; // unique mark
+ short sheet; // sheet (0..n)
+ ParticuleType type; // type PARTI*
+ ParticulePhase phase; // phase PARPH*
+ float mass; // mass of the particle (in rebounding)
+ float weight; // weight of the particle (for noise)
+ float duration; // length of life
+ Math::Vector pos; // absolute position (relative if object links)
+ Math::Vector goal; // goal position (if bRay)
+ Math::Vector speed; // speed of displacement
+ float windSensitivity;
+ short bounce; // number of rebounds
+ Math::Point dim; // dimensions of the rectangle
+ float zoom; // zoom (0..1)
+ float angle; // angle of rotation
+ float intensity; // intensity
+ Math::Point texSup; // coordinated upper texture
+ Math::Point texInf; // coordinated lower texture
+ float time; // age of the particle (0..n)
+ float phaseTime; // age at the beginning of phase
+ float testTime; // time since last test
+ CObject* objLink; // father object (for example reactor)
+ CObject* objFather; // father object (for example reactor)
+ short objRank; // rank of the object, or -1
+ short trackRank; // rank of the drag
+};
+
+struct Track
+{
+ char bUsed; // true -> drag used
+ char bDrawParticule;
+ float step; // duration of not
+ float last; // increase last not memorized
+ float intensity; // intensity at starting (0..1)
+ float width; // tail width
+ int used; // number of positions in "pos"
+ int head; // head to write index
+ Math::Vector pos[MAXTRACKLEN];
+ float len[MAXTRACKLEN];
+};
+
+struct WheelTrace
+{
+ ParticuleType type; // type PARTI*
+ Math::Vector pos[4]; // rectangle positions
+ float startTime; // beginning of life
+};
+
+
+
+class CParticule
+{
+public:
+ CParticule(CInstanceManager* iMan, CD3DEngine* engine);
+ ~CParticule();
+
+ void SetD3DDevice(LPDIRECT3DDEVICE7 device);
+
+ void FlushParticule();
+ void FlushParticule(int sheet);
+ int CreateParticule(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticuleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0);
+ int CreateFrag(Math::Vector pos, Math::Vector speed, D3DTriangle *triangle, ParticuleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0);
+ int CreatePart(Math::Vector pos, Math::Vector speed, ParticuleType type, float duration=1.0f, float mass=0.0f, float weight=0.0f, float windSensitivity=1.0f, int sheet=0);
+ int CreateRay(Math::Vector pos, Math::Vector goal, ParticuleType type, Math::Point dim, float duration=1.0f, int sheet=0);
+ int CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticuleType type, float duration=1.0f, float mass=0.0f, float length=10.0f, float width=1.0f);
+ void CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3, const Math::Vector &p4, ParticuleType type);
+ void DeleteParticule(ParticuleType type);
+ void DeleteParticule(int channel);
+ void SetObjectLink(int channel, CObject *object);
+ void SetObjectFather(int channel, CObject *object);
+ void SetPosition(int channel, Math::Vector pos);
+ void SetDimension(int channel, Math::Point dim);
+ void SetZoom(int channel, float zoom);
+ void SetAngle(int channel, float angle);
+ 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, ParticulePhase phase, float duration);
+ bool GetPosition(int channel, Math::Vector &pos);
+
+ D3DCOLORVALUE RetFogColor(Math::Vector pos);
+
+ void SetFrameUpdate(int sheet, bool bUpdate);
+ void FrameParticule(float rTime);
+ void DrawParticule(int sheet);
+
+ bool WriteWheelTrace(char *filename, int width, int height, Math::Vector dl, Math::Vector ur);
+
+protected:
+ void DeleteRank(int rank);
+ bool CheckChannel(int &channel);
+ void DrawParticuleTriangle(int i);
+ void DrawParticuleNorm(int i);
+ void DrawParticuleFlat(int i);
+ void DrawParticuleFog(int i);
+ void DrawParticuleRay(int i);
+ void DrawParticuleSphere(int i);
+ void DrawParticuleCylinder(int i);
+ void DrawParticuleWheel(int i);
+ CObject* SearchObjectGun(Math::Vector old, Math::Vector pos, ParticuleType type, CObject *father);
+ CObject* SearchObjectRay(Math::Vector pos, Math::Vector goal, ParticuleType type, CObject *father);
+ void Play(Sound sound, Math::Vector pos, float amplitude);
+ bool TrackMove(int i, Math::Vector pos, float progress);
+ void TrackDraw(int i, ParticuleType type);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ LPDIRECT3DDEVICE7 m_pD3DDevice;
+ CRobotMain* m_main;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CSound* m_sound;
+
+ Particule m_particule[MAXPARTICULE*MAXPARTITYPE];
+ D3DTriangle m_triangle[MAXPARTICULE]; // triangle if PartiType == 0
+ Track m_track[MAXTRACK];
+ int m_wheelTraceTotal;
+ int m_wheelTraceIndex;
+ WheelTrace m_wheelTrace[MAXWHEELTRACE];
+ int m_totalInterface[MAXPARTITYPE][SH_MAX];
+ bool m_bFrameUpdate[SH_MAX];
+ int m_fogTotal;
+ int m_fog[MAXPARTIFOG];
+ int m_uniqueStamp;
+ int m_exploGunCounter;
+ float m_lastTimeGunDel;
+ float m_absTime;
+};
+
diff --git a/src/old/planet.cpp b/src/old/planet.cpp
index 0733459..48a3d4d 100644
--- a/src/old/planet.cpp
+++ b/src/old/planet.cpp
@@ -1,247 +1,247 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// planet.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "old/planet.h"
-
-
-
-
-// Constructor of the terrain.
-
-CPlanet::CPlanet(CInstanceManager* iMan, CD3DEngine* engine)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_PLANET, this);
-
- m_engine = engine;
- Flush();
-
-}
-
-// Destructor of the terrain.
-
-CPlanet::~CPlanet()
-{
-}
-
-
-// Removes all the planets.
-
-void CPlanet::Flush()
-{
- int i, j;
-
- for ( j=0 ; j<2 ; j++ )
- {
- for ( i=0 ; i<MAXPLANET ; i++ )
- {
- m_planet[j][i].bUsed = false;
- }
- }
-
- m_bPlanetExist = false;
- m_mode = 0;
- m_time = 0.0f;
-}
-
-
-// Management of an event.
-
-bool CPlanet::EventProcess(const Event &event)
-{
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
- return true;
-}
-
-// Makes the planets evolve.
-
-bool CPlanet::EventFrame(const Event &event)
-{
- float a;
- int i;
-
- if ( m_engine->RetPause() ) return true;
-
- m_time += event.rTime;
-
- for ( i=0 ; i<MAXPLANET ; i++ )
- {
- if ( !m_planet[m_mode][i].bUsed ) continue;
-
- a = m_time*m_planet[m_mode][i].speed;
- if ( a < 0.0f )
- {
- a += Math::PI*1000.0f;
- }
- m_planet[m_mode][i].angle.x = a+m_planet[m_mode][i].start.x;
- m_planet[m_mode][i].angle.y = sinf(a)*sinf(m_planet[m_mode][i].dir)+m_planet[m_mode][i].start.y;
- }
-
- return true;
-}
-
-
-// Load all the textures for the planets.
-
-void CPlanet::LoadTexture()
-{
- int i, j;
-
- for ( j=0 ; j<2 ; j++ )
- {
- for ( i=0 ; i<MAXPLANET ; i++ )
- {
- if ( !m_planet[j][i].bUsed ) continue;
-
- m_engine->LoadTexture(m_planet[j][i].name);
- }
- }
-}
-
-// Draws all the planets.
-
-void CPlanet::Draw()
-{
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Vector n;
- Math::Point p1, p2;
- float eyeDirH, eyeDirV, dp, u1, u2, v1, v2, a;
- int i;
-
- device = m_engine->RetD3DDevice();
- eyeDirH = m_engine->RetEyeDirH();
- eyeDirV = m_engine->RetEyeDirV();
-
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
- dp = 0.5f/256.0f;
-
- for ( i=0 ; i<MAXPLANET ; i++ )
- {
- if ( !m_planet[m_mode][i].bUsed ) continue;
-
- m_engine->SetTexture(m_planet[m_mode][i].name);
-
- if ( m_planet[m_mode][i].bTGA )
- {
- m_engine->SetState(D3DSTATEWRAP|D3DSTATEALPHA);
- }
- else
- {
- m_engine->SetState(D3DSTATEWRAP|D3DSTATETTb);
- }
-
- a = eyeDirH + m_planet[m_mode][i].angle.x;
- p1.x = Math::Mod(a, Math::PI*2.0f)-0.5f;
-
- a = eyeDirV + m_planet[m_mode][i].angle.y;
- p1.y = 0.4f+(Math::Mod(a+Math::PI, Math::PI*2.0f)-Math::PI)*(2.0f/Math::PI);
-
- p1.x -= m_planet[m_mode][i].dim/2.0f*0.75f;
- p1.y -= m_planet[m_mode][i].dim/2.0f;
- p2.x = p1.x+m_planet[m_mode][i].dim*0.75f;
- p2.y = p1.y+m_planet[m_mode][i].dim;
-
- u1 = m_planet[m_mode][i].uv1.x + dp;
- v1 = m_planet[m_mode][i].uv1.y + dp;
- u2 = m_planet[m_mode][i].uv2.x - dp;
- v2 = m_planet[m_mode][i].uv2.y - dp;
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
-
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
- }
-}
-
-
-// Creates a new planet.
-
-bool CPlanet::Create(int mode, Math::Point start, float dim, float speed,
- float dir, char *name, Math::Point uv1, Math::Point uv2)
-{
- int i;
-
- if ( mode < 0 ) mode = 0;
- if ( mode > 1 ) mode = 1;
-
- for ( i=0 ; i<MAXPLANET ; i++ )
- {
- if ( m_planet[mode][i].bUsed ) continue;
-
- m_planet[mode][i].bUsed = true;
- m_planet[mode][i].start = start;
- m_planet[mode][i].angle = start;
- m_planet[mode][i].dim = dim;
- m_planet[mode][i].speed = speed;
- m_planet[mode][i].dir = dir;
-
- strcpy(m_planet[mode][i].name, name);
- m_planet[mode][i].uv1 = uv1;
- m_planet[mode][i].uv2 = uv2;
-
- m_planet[mode][i].bTGA = ( strstr(m_planet[mode][i].name, "planet") != 0 );
-
- m_bPlanetExist = true;
- return true;
- }
-
- return false;
-}
-
-// Indicates if there is at least one planet.
-
-bool CPlanet::PlanetExist()
-{
- return m_bPlanetExist;
-}
-
-
-// Choice of mode.
-
-void CPlanet::SetMode(int mode)
-{
- if ( mode < 0 ) mode = 0;
- if ( mode > 1 ) mode = 1;
- m_mode = mode;
-}
-
-int CPlanet::RetMode()
-{
- return m_mode;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// planet.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "old/planet.h"
+
+
+
+
+// Constructor of the terrain.
+
+CPlanet::CPlanet(CInstanceManager* iMan, CD3DEngine* engine)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_PLANET, this);
+
+ m_engine = engine;
+ Flush();
+
+}
+
+// Destructor of the terrain.
+
+CPlanet::~CPlanet()
+{
+}
+
+
+// Removes all the planets.
+
+void CPlanet::Flush()
+{
+ int i, j;
+
+ for ( j=0 ; j<2 ; j++ )
+ {
+ for ( i=0 ; i<MAXPLANET ; i++ )
+ {
+ m_planet[j][i].bUsed = false;
+ }
+ }
+
+ m_bPlanetExist = false;
+ m_mode = 0;
+ m_time = 0.0f;
+}
+
+
+// Management of an event.
+
+bool CPlanet::EventProcess(const Event &event)
+{
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+ return true;
+}
+
+// Makes the planets evolve.
+
+bool CPlanet::EventFrame(const Event &event)
+{
+ float a;
+ int i;
+
+ if ( m_engine->RetPause() ) return true;
+
+ m_time += event.rTime;
+
+ for ( i=0 ; i<MAXPLANET ; i++ )
+ {
+ if ( !m_planet[m_mode][i].bUsed ) continue;
+
+ a = m_time*m_planet[m_mode][i].speed;
+ if ( a < 0.0f )
+ {
+ a += Math::PI*1000.0f;
+ }
+ m_planet[m_mode][i].angle.x = a+m_planet[m_mode][i].start.x;
+ m_planet[m_mode][i].angle.y = sinf(a)*sinf(m_planet[m_mode][i].dir)+m_planet[m_mode][i].start.y;
+ }
+
+ return true;
+}
+
+
+// Load all the textures for the planets.
+
+void CPlanet::LoadTexture()
+{
+ int i, j;
+
+ for ( j=0 ; j<2 ; j++ )
+ {
+ for ( i=0 ; i<MAXPLANET ; i++ )
+ {
+ if ( !m_planet[j][i].bUsed ) continue;
+
+ m_engine->LoadTexture(m_planet[j][i].name);
+ }
+ }
+}
+
+// Draws all the planets.
+
+void CPlanet::Draw()
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Vector n;
+ Math::Point p1, p2;
+ float eyeDirH, eyeDirV, dp, u1, u2, v1, v2, a;
+ int i;
+
+ device = m_engine->RetD3DDevice();
+ eyeDirH = m_engine->RetEyeDirH();
+ eyeDirV = m_engine->RetEyeDirV();
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+ dp = 0.5f/256.0f;
+
+ for ( i=0 ; i<MAXPLANET ; i++ )
+ {
+ if ( !m_planet[m_mode][i].bUsed ) continue;
+
+ m_engine->SetTexture(m_planet[m_mode][i].name);
+
+ if ( m_planet[m_mode][i].bTGA )
+ {
+ m_engine->SetState(D3DSTATEWRAP|D3DSTATEALPHA);
+ }
+ else
+ {
+ m_engine->SetState(D3DSTATEWRAP|D3DSTATETTb);
+ }
+
+ a = eyeDirH + m_planet[m_mode][i].angle.x;
+ p1.x = Math::Mod(a, Math::PI*2.0f)-0.5f;
+
+ a = eyeDirV + m_planet[m_mode][i].angle.y;
+ p1.y = 0.4f+(Math::Mod(a+Math::PI, Math::PI*2.0f)-Math::PI)*(2.0f/Math::PI);
+
+ p1.x -= m_planet[m_mode][i].dim/2.0f*0.75f;
+ p1.y -= m_planet[m_mode][i].dim/2.0f;
+ p2.x = p1.x+m_planet[m_mode][i].dim*0.75f;
+ p2.y = p1.y+m_planet[m_mode][i].dim;
+
+ u1 = m_planet[m_mode][i].uv1.x + dp;
+ v1 = m_planet[m_mode][i].uv1.y + dp;
+ u2 = m_planet[m_mode][i].uv2.x - dp;
+ v2 = m_planet[m_mode][i].uv2.y - dp;
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
+
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+ }
+}
+
+
+// Creates a new planet.
+
+bool CPlanet::Create(int mode, Math::Point start, float dim, float speed,
+ float dir, char *name, Math::Point uv1, Math::Point uv2)
+{
+ int i;
+
+ if ( mode < 0 ) mode = 0;
+ if ( mode > 1 ) mode = 1;
+
+ for ( i=0 ; i<MAXPLANET ; i++ )
+ {
+ if ( m_planet[mode][i].bUsed ) continue;
+
+ m_planet[mode][i].bUsed = true;
+ m_planet[mode][i].start = start;
+ m_planet[mode][i].angle = start;
+ m_planet[mode][i].dim = dim;
+ m_planet[mode][i].speed = speed;
+ m_planet[mode][i].dir = dir;
+
+ strcpy(m_planet[mode][i].name, name);
+ m_planet[mode][i].uv1 = uv1;
+ m_planet[mode][i].uv2 = uv2;
+
+ m_planet[mode][i].bTGA = ( strstr(m_planet[mode][i].name, "planet") != 0 );
+
+ m_bPlanetExist = true;
+ return true;
+ }
+
+ return false;
+}
+
+// Indicates if there is at least one planet.
+
+bool CPlanet::PlanetExist()
+{
+ return m_bPlanetExist;
+}
+
+
+// Choice of mode.
+
+void CPlanet::SetMode(int mode)
+{
+ if ( mode < 0 ) mode = 0;
+ if ( mode > 1 ) mode = 1;
+ m_mode = mode;
+}
+
+int CPlanet::RetMode()
+{
+ return m_mode;
+}
+
diff --git a/src/old/planet.h b/src/old/planet.h
index 14c8111..36f5586 100644
--- a/src/old/planet.h
+++ b/src/old/planet.h
@@ -1,76 +1,76 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// planet.h
-
-#pragma once
-
-
-#include "common/event.h"
-#include "math/point.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-
-
-
-const int MAXPLANET = 10;
-
-struct Planet
-{
- char bUsed; // true -> planet exists
- Math::Point start; // initial position in degrees
- Math::Point angle; // current position in degrees
- float dim; // dimensions (0..1)
- float speed; // speed
- float dir; // direction in the sky
- char name[20]; // name of the texture
- Math::Point uv1, uv2; // texture mapping
- char bTGA; // texture .TGA
-};
-
-
-
-
-class CPlanet
-{
-public:
- CPlanet(CInstanceManager* iMan, CD3DEngine* engine);
- ~CPlanet();
-
- void Flush();
- bool EventProcess(const Event &event);
- bool Create(int mode, Math::Point start, float dim, float speed, float dir, char *name, Math::Point uv1, Math::Point uv2);
- bool PlanetExist();
- void LoadTexture();
- void Draw();
- void SetMode(int mode);
- int RetMode();
-
-protected:
- bool EventFrame(const Event &event);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
-
- float m_time;
- int m_mode;
- Planet m_planet[2][MAXPLANET];
- bool m_bPlanetExist;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// planet.h
+
+#pragma once
+
+
+#include "common/event.h"
+#include "math/point.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+
+
+
+const int MAXPLANET = 10;
+
+struct Planet
+{
+ char bUsed; // true -> planet exists
+ Math::Point start; // initial position in degrees
+ Math::Point angle; // current position in degrees
+ float dim; // dimensions (0..1)
+ float speed; // speed
+ float dir; // direction in the sky
+ char name[20]; // name of the texture
+ Math::Point uv1, uv2; // texture mapping
+ char bTGA; // texture .TGA
+};
+
+
+
+
+class CPlanet
+{
+public:
+ CPlanet(CInstanceManager* iMan, CD3DEngine* engine);
+ ~CPlanet();
+
+ void Flush();
+ bool EventProcess(const Event &event);
+ bool Create(int mode, Math::Point start, float dim, float speed, float dir, char *name, Math::Point uv1, Math::Point uv2);
+ bool PlanetExist();
+ void LoadTexture();
+ void Draw();
+ void SetMode(int mode);
+ int RetMode();
+
+protected:
+ bool EventFrame(const Event &event);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+
+ float m_time;
+ int m_mode;
+ Planet m_planet[2][MAXPLANET];
+ bool m_bPlanetExist;
+};
+
diff --git a/src/old/pyro.cpp b/src/old/pyro.cpp
index fc61e62..96fc776 100644
--- a/src/old/pyro.cpp
+++ b/src/old/pyro.cpp
@@ -1,2486 +1,2486 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// pyro.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "object/robotmain.h"
-#include "old/terrain.h"
-#include "old/camera.h"
-#include "old/particule.h"
-#include "old/light.h"
-#include "object/object.h"
-#include "object/motion/motion.h"
-#include "object/motion/motionhuman.h"
-#include "ui/displaytext.h"
-#include "old/sound.h"
-#include "old/pyro.h"
-
-
-
-
-// Object's constructor.
-
-CPyro::CPyro(CInstanceManager* iMan)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_PYRO, this, 100);
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
- m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- m_object = 0;
-
- m_progress = 0.0f;
- m_speed = 0.0f;
- m_lightRank = -1;
- m_soundChannel = -1;
- LightOperFlush();
-}
-
-// Object's destructor.
-
-CPyro::~CPyro()
-{
- m_iMan->DeleteInstance(CLASS_PYRO, this);
-}
-
-
-// Destroys the object.
-
-void CPyro::DeleteObject(bool bAll)
-{
- if ( m_lightRank != -1 )
- {
- m_light->DeleteLight(m_lightRank);
- m_lightRank = -1;
- }
-}
-
-
-// Creates pyrotechnic effect.
-
-bool CPyro::Create(PyroType type, CObject* pObj, float force)
-{
- Math::Matrix* mat;
- CObject* power;
- CMotion* motion;
- Math::Vector min, max, pos, speed;
- Math::Point dim;
- ObjectType oType;
- Sound sound;
- float duration, mass, h, limit;
- int part, objRank, total, i, channel;
-
- m_object = pObj;
- m_force = force;
-
- oType = pObj->RetType();
- objRank = pObj->RetObjectRank(0);
- if ( objRank == -1 ) return false;
- m_engine->GetBBox(objRank, min, max);
- pos = pObj->RetPosition(0);
-
- DisplayError(type, pObj); // displays eventual messages
-
- // Copies all spheres of the object.
- for ( i=0 ; i<50 ; i++ )
- {
- if ( !pObj->GetCrashSphere(i, m_crashSpherePos[i], m_crashSphereRadius[i]) ) break;
- }
- m_crashSphereUsed = i;
-
- // Calculates the size of the effect.
- if ( oType == OBJECT_ANT ||
- oType == OBJECT_BEE ||
- oType == OBJECT_WORM ||
- oType == OBJECT_SPIDER )
- {
- m_size = 40.0f;
- }
- else
- {
- m_size = Math::Distance(min, max)*2.0f;
- if ( m_size < 4.0f ) m_size = 4.0f;
- if ( m_size > 80.0f ) m_size = 80.0f;
- }
- if ( oType == OBJECT_TNT ||
- oType == OBJECT_BOMB )
- {
- m_size *= 2.0f;
- }
-
- m_pos = pos+(min+max)/2.0f;
- m_type = type;
- m_progress = 0.0f;
- m_speed = 1.0f/20.0f;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- m_lastParticuleSmoke = 0.0f;
- m_lightRank = -1;
-
- if ( oType == OBJECT_TEEN28 ||
- oType == OBJECT_TEEN31 )
- {
- m_pos.y = pos.y+1.0f;
- }
-
- // Seeking the position of the battery.
- power = pObj->RetPower();
- if ( power == 0 )
- {
- m_bPower = false;
- }
- else
- {
- m_bPower = true;
- pos = power->RetPosition(0);
- pos.y += 1.0f;
- mat = pObj->RetWorldMatrix(0);
- m_posPower = Math::Transform(*mat, pos);
- }
- if ( oType == OBJECT_POWER ||
- oType == OBJECT_ATOMIC ||
- oType == OBJECT_URANIUM ||
- oType == OBJECT_TNT ||
- oType == OBJECT_BOMB )
- {
- m_bPower = true;
- m_posPower = m_pos;
- m_posPower.y += 1.0f;
- m_pos = m_posPower;
- }
- if ( oType == OBJECT_STATION )
- {
- m_bPower = true;
- mat = pObj->RetWorldMatrix(0);
- m_posPower = Math::Transform(*mat, Math::Vector(-15.0f, 7.0f, 0.0f));
- m_pos = m_posPower;
- }
- if ( oType == OBJECT_ENERGY )
- {
- m_bPower = true;
- mat = pObj->RetWorldMatrix(0);
- m_posPower = Math::Transform(*mat, Math::Vector(-7.0f, 6.0f, 0.0f));
- m_pos = m_posPower;
- }
- if ( oType == OBJECT_NUCLEAR )
- {
- m_bPower = true;
- m_posPower = m_pos;
- }
- if ( oType == OBJECT_PARA )
- {
- m_bPower = true;
- m_posPower = m_pos;
- }
- if ( oType == OBJECT_SCRAP4 ||
- oType == OBJECT_SCRAP5 ) // plastic material?
- {
- m_bPower = true;
- m_posPower = m_pos;
- }
-
- // Plays the sound of a pyrotechnic effect.
- if ( type == PT_FRAGT ||
- type == PT_FRAGW ||
- type == PT_EXPLOT ||
- type == PT_EXPLOW )
- {
- if ( m_bPower )
- {
- sound = SOUND_EXPLOp;
- }
- else
- {
- sound = SOUND_EXPLO;
- }
- if ( oType == OBJECT_STONE ||
- oType == OBJECT_METAL ||
- oType == OBJECT_BULLET ||
- oType == OBJECT_BBOX ||
- oType == OBJECT_KEYa ||
- oType == OBJECT_KEYb ||
- oType == OBJECT_KEYc ||
- oType == OBJECT_KEYd )
- {
- sound = SOUND_EXPLOl;
- }
- if ( oType == OBJECT_URANIUM ||
- oType == OBJECT_POWER ||
- oType == OBJECT_ATOMIC ||
- oType == OBJECT_TNT ||
- oType == OBJECT_BOMB )
- {
- sound = SOUND_EXPLOlp;
- }
- m_sound->Play(sound, m_pos);
- }
- if ( type == PT_FRAGO ||
- type == PT_EXPLOO ||
- type == PT_SPIDER ||
- type == PT_SHOTM )
- {
- m_sound->Play(SOUND_EXPLOi, m_pos);
- }
- if ( type == PT_BURNT ||
- type == PT_BURNO )
- {
- m_soundChannel = m_sound->Play(SOUND_BURN, m_pos, 1.0f, 1.0f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 12.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 5.0f, SOPER_STOP);
- }
- if ( type == PT_BURNO )
- {
- m_sound->Play(SOUND_DEADi, m_pos);
- m_sound->Play(SOUND_DEADi, m_engine->RetEyePt());
- }
- if ( type == PT_EGG )
- {
- m_sound->Play(SOUND_EGG, m_pos);
- }
- if ( type == PT_WPCHECK ||
- type == PT_FLCREATE ||
- type == PT_FLDELETE )
- {
- m_sound->Play(SOUND_WAYPOINT, m_pos);
- }
- if ( oType == OBJECT_HUMAN )
- {
- if ( type == PT_DEADG )
- {
- m_sound->Play(SOUND_DEADg, m_pos);
- }
- if ( type == PT_DEADW )
- {
- m_sound->Play(SOUND_DEADw, m_pos);
- }
- if ( type == PT_SHOTH && m_object->RetSelect() )
- {
- m_sound->Play(SOUND_AIE, m_pos);
- m_sound->Play(SOUND_AIE, m_engine->RetEyePt());
- }
- }
-
- if ( m_type == PT_FRAGT ||
- m_type == PT_FRAGO ||
- m_type == PT_FRAGW )
- {
- m_engine->ShadowDelete(m_object->RetObjectRank(0));
- }
-
- if ( m_type == PT_DEADG )
- {
- m_object->SetDead(true);
-
- motion = m_object->RetMotion();
- if ( motion != 0 )
- {
- motion->SetAction(MHS_DEADg, 1.0f);
- }
- m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 1.5f);
- m_camera->StartOver(OE_FADEOUTw, m_pos, 1.0f);
- m_speed = 1.0f/10.0f;
- return true;
- }
- if ( m_type == PT_DEADW )
- {
- m_object->SetDead(true);
-
- motion = m_object->RetMotion();
- if ( motion != 0 )
- {
- motion->SetAction(MHS_DEADw, 4.0f);
- }
- m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 3.0f);
- m_camera->StartOver(OE_FADEOUTb, m_pos, 1.0f);
- m_speed = 1.0f/10.0f;
- return true;
- }
-
- if ( m_type == PT_SHOTT ||
- m_type == PT_SHOTM )
- {
- m_camera->StartEffect(CE_SHOT, m_pos, force);
- m_speed = 1.0f/1.0f;
- return true;
- }
- if ( m_type == PT_SHOTH )
- {
- if ( m_object->RetSelect() )
- {
- m_camera->StartOver(OE_BLOOD, m_pos, force);
- }
- m_speed = 1.0f/0.2f;
- return true;
- }
-
- if ( m_type == PT_SHOTW )
- {
- m_speed = 1.0f/1.0f;
- }
-
- if ( m_type == PT_BURNT )
- {
- BurnStart();
- }
-
- if ( m_type == PT_WPCHECK )
- {
- m_speed = 1.0f/8.0f;
- m_object->SetEnable(false); // object more functional
- }
- if ( m_type == PT_FLCREATE )
- {
- m_speed = 1.0f/2.0f;
- }
- if ( m_type == PT_FLDELETE )
- {
- m_speed = 1.0f/2.0f;
- m_object->SetEnable(false); // object more functional
- }
- if ( m_type == PT_RESET )
- {
- m_speed = 1.0f/2.0f;
- m_object->SetPosition(0, m_object->RetResetPosition());
- m_object->SetAngle(0, m_object->RetResetAngle());
- m_object->SetZoom(0, 0.0f);
- }
- if ( m_type == PT_FINDING )
- {
- limit = (m_size-1.0f)/4.0f;
- if ( limit > 8.0f ) limit = 8.0f;
- if ( oType == OBJECT_APOLLO2 ) limit = 2.0f;
- m_speed = 1.0f/limit;
- }
-
- if ( m_type == PT_EXPLOT ||
- m_type == PT_EXPLOO ||
- m_type == PT_EXPLOW )
- {
- CreateTriangle(pObj, oType, 0);
- m_engine->ShadowDelete(m_object->RetObjectRank(0));
- ExploStart();
- }
-
- if ( m_type == PT_FALL )
- {
- FallStart();
- return true;
- }
-
- if ( m_type == PT_BURNT ||
- m_type == PT_BURNO )
- {
- m_speed = 1.0f/15.0f;
-
- LightOperAdd(0.00f, 0.0f, 2.0f, 1.0f, 0.0f); // red-orange
- LightOperAdd(0.30f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
- LightOperAdd(0.80f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
- LightOperAdd(1.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
- CreateLight(m_pos, 40.0f);
- return true;
- }
-
- if ( m_type == PT_SPIDER )
- {
- m_speed = 1.0f/15.0f;
-
- pos = Math::Vector(-3.0f, 2.0f, 0.0f);
- mat = pObj->RetWorldMatrix(0);
- m_pos = Math::Transform(*mat, pos);
-
- m_engine->ShadowDelete(m_object->RetObjectRank(0));
- }
-
- if ( m_type != PT_EGG &&
- m_type != PT_WIN &&
- m_type != PT_LOST )
- {
- h = 40.0f;
- if ( m_type == PT_FRAGO ||
- m_type == PT_EXPLOO )
- {
- LightOperAdd(0.00f, 0.0f, -1.0f, -0.5f, -1.0f); // dark green
- LightOperAdd(0.05f, 1.0f, -1.0f, -0.5f, -1.0f); // dark green
- LightOperAdd(1.00f, 0.0f, -1.0f, -0.5f, -1.0f); // dark green
- }
- else if ( m_type == PT_FRAGT ||
- m_type == PT_EXPLOT )
- {
- LightOperAdd(0.00f, 1.0f, 4.0f, 4.0f, 2.0f); // yellow
- LightOperAdd(0.02f, 1.0f, 4.0f, 2.0f, 0.0f); // red-orange
- LightOperAdd(0.16f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
- LightOperAdd(1.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
- h = m_size*2.0f;
- }
- else if ( m_type == PT_SPIDER )
- {
- LightOperAdd(0.00f, 0.0f, -0.5f, -1.0f, -1.0f); // dark red
- LightOperAdd(0.05f, 1.0f, -0.5f, -1.0f, -1.0f); // dark red
- LightOperAdd(1.00f, 0.0f, -0.5f, -1.0f, -1.0f); // dark red
- }
- else if ( m_type == PT_FRAGW ||
- m_type == PT_EXPLOW ||
- m_type == PT_SHOTW )
- {
- LightOperAdd(0.00f, 0.0f, -0.5f, -0.5f, -1.0f); // dark yellow
- LightOperAdd(0.05f, 1.0f, -0.5f, -0.5f, -1.0f); // dark yellow
- LightOperAdd(1.00f, 0.0f, -0.5f, -0.5f, -1.0f); // dark yellow
- }
- else if ( m_type == PT_WPCHECK ||
- m_type == PT_FLCREATE ||
- m_type == PT_FLDELETE ||
- m_type == PT_RESET ||
- m_type == PT_FINDING )
- {
- LightOperAdd(0.00f, 1.0f, 4.0f, 4.0f, 2.0f); // yellow
- LightOperAdd(1.00f, 0.0f, 4.0f, 4.0f, 2.0f); // yellow
- }
- else
- {
- LightOperAdd(0.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
- LightOperAdd(0.05f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
- LightOperAdd(1.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
- }
- CreateLight(m_pos, h);
-
- if ( m_type != PT_SHOTW &&
- m_type != PT_WPCHECK &&
- m_type != PT_FLCREATE &&
- m_type != PT_FLDELETE &&
- m_type != PT_RESET &&
- m_type != PT_FINDING )
- {
- m_camera->StartEffect(CE_EXPLO, m_pos, force);
- }
- }
-
- if ( m_type == PT_SHOTW ) return true;
-
- // Generates the triangles of the explosion.
- if ( m_type == PT_FRAGT ||
- m_type == PT_FRAGO ||
- m_type == PT_FRAGW ||
- m_type == PT_SPIDER ||
- m_type == PT_EGG ||
- (m_type == PT_EXPLOT && oType == OBJECT_MOBILEtg) ||
- (m_type == PT_EXPLOT && oType == OBJECT_TEEN28 ) ||
- (m_type == PT_EXPLOT && oType == OBJECT_TEEN31 ) )
- {
- for ( part=0 ; part<OBJECTMAXPART ; part++ )
- {
- CreateTriangle(pObj, oType, part);
- }
- }
-
- if ( m_type == PT_FRAGT ||
- m_type == PT_EXPLOT )
- {
- if ( m_bPower )
- {
- total = (int)(10.0f*m_engine->RetParticuleDensity());
- if ( oType == OBJECT_TNT ||
- oType == OBJECT_BOMB ) total *= 3;
- for ( i=0 ; i<total ; i++ )
- {
- pos = m_posPower;
- speed.x = (Math::Rand()-0.5f)*30.0f;
- speed.z = (Math::Rand()-0.5f)*30.0f;
- speed.y = Math::Rand()*30.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- duration = Math::Rand()*3.0f+2.0f;
- mass = Math::Rand()*10.0f+15.0f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK1,
- duration, mass, Math::Rand()+0.7f, 1.0f);
- }
- }
-
- if ( m_size > 10.0f ) // large enough (freight excluded)?
- {
- if ( m_bPower )
- {
- pos = m_posPower;
- }
- else
- {
- pos = m_pos;
- m_terrain->MoveOnFloor(pos);
- pos.y += 1.0f;
- }
- dim.x = m_size*0.4f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, Math::Vector(0.0f,0.0f,0.0f), dim, PARTISPHERE0, 2.0f, 0.0f, 0.0f);
- }
- }
-
- if ( m_type == PT_FRAGO ||
- m_type == PT_EXPLOO )
- {
- total = (int)(10.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<total ; i++ )
- {
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*30.0f;
- speed.z = (Math::Rand()-0.5f)*30.0f;
- speed.y = Math::Rand()*50.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- duration = Math::Rand()*1.0f+0.8f;
- mass = Math::Rand()*10.0f+15.0f;
- m_particule->CreateParticule(pos, speed, dim, PARTIORGANIC1,
- duration, mass);
- }
- total = (int)(5.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<total ; i++ )
- {
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*30.0f;
- speed.z = (Math::Rand()-0.5f)*30.0f;
- speed.y = Math::Rand()*50.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- duration = Math::Rand()*2.0f+1.4f;
- mass = Math::Rand()*10.0f+15.0f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK4,
- duration, mass, duration*0.5f, dim.x*2.0f);
- }
- }
-
- if ( m_type == PT_SPIDER )
- {
- for ( i=0 ; i<50 ; i++ )
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*3.0f;
- pos.z += (Math::Rand()-0.5f)*3.0f;
- pos.y += (Math::Rand()-0.5f)*2.0f;
- speed.x = (Math::Rand()-0.5f)*24.0f;
- speed.z = (Math::Rand()-0.5f)*24.0f;
- speed.y = 10.0f+Math::Rand()*10.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN3, 2.0f+Math::Rand()*2.0f, 10.0f);
- m_particule->SetObjectFather(channel, pObj);
- }
- total = (int)(10.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<total ; i++ )
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*3.0f;
- pos.z += (Math::Rand()-0.5f)*3.0f;
- pos.y += (Math::Rand()-0.5f)*2.0f;
- speed.x = (Math::Rand()-0.5f)*24.0f;
- speed.z = (Math::Rand()-0.5f)*24.0f;
- speed.y = 7.0f+Math::Rand()*7.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK3,
- 2.0f+Math::Rand()*2.0f, 10.0f, 2.0f, 0.6f);
- }
- }
-
- if ( type == PT_FRAGT ||
- type == PT_FRAGW ||
- type == PT_EXPLOT ||
- type == PT_EXPLOW )
- {
- if ( m_size > 10.0f || m_bPower )
- {
- pos = m_pos;
-//? m_terrain->MoveOnFloor(pos);
-//? pos.y += 2.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = m_size;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICHOC, 2.0f);
- }
- }
-
- return true;
-}
-
-// Creates an explosion with triangular form of particles.
-
-void CPyro::CreateTriangle(CObject* pObj, ObjectType oType, int part)
-{
- D3DTriangle buffer[100];
- Math::Matrix* mat;
- Math::Vector offset, pos, speed;
- float percent, min, max, h, duration, mass;
- int objRank, total, i;
-
- objRank = pObj->RetObjectRank(part);
- if ( objRank == -1 ) return;
-
- min = 0.0f;
- max = m_engine->RetLimitLOD(0);
- total = m_engine->RetTotalTriangles(objRank);
- percent = 0.10f;
- if ( total < 50 ) percent = 0.25f;
- if ( total < 20 ) percent = 0.50f;
- if ( m_type == PT_EGG ) percent = 0.30f;
- if ( oType == OBJECT_POWER ||
- oType == OBJECT_ATOMIC ||
- oType == OBJECT_URANIUM ||
- oType == OBJECT_TNT ||
- oType == OBJECT_BOMB ) percent = 0.75f;
- if ( oType == OBJECT_MOBILEtg ) percent = 0.50f;
- if ( oType == OBJECT_TEEN28 ) percent = 0.75f;
- if ( oType == OBJECT_MOTHER ) max = 1000000.0f;
- if ( oType == OBJECT_TEEN28 ) max = 1000000.0f;
- if ( oType == OBJECT_TEEN31 ) max = 1000000.0f;
- total = m_engine->GetTriangles(objRank, min, max, buffer, 100, percent);
-
- for ( i=0 ; i<total ; i++ )
- {
- Math::Vector p1, p2, p3;
-
- p1.x = buffer[i].triangle[0].x;
- p1.y = buffer[i].triangle[0].y;
- p1.z = buffer[i].triangle[0].z;
- p2.x = buffer[i].triangle[1].x;
- p2.y = buffer[i].triangle[1].y;
- p2.z = buffer[i].triangle[1].z;
- p3.x = buffer[i].triangle[2].x;
- p3.y = buffer[i].triangle[2].y;
- p3.z = buffer[i].triangle[2].z;
-
- h = Math::Distance(p1, p2);
- if ( h > 5.0f )
- {
- p2.x = p1.x+((p2.x-p1.x)*5.0f/h);
- p2.y = p1.y+((p2.y-p1.y)*5.0f/h);
- p2.z = p1.z+((p2.z-p1.z)*5.0f/h);
- }
-
- h = Math::Distance(p2, p3);
- if ( h > 5.0f )
- {
- p3.x = p2.x+((p3.x-p2.x)*5.0f/h);
- p3.y = p2.y+((p3.y-p2.y)*5.0f/h);
- p3.z = p2.z+((p3.z-p2.z)*5.0f/h);
- }
-
- h = Math::Distance(p3, p1);
- if ( h > 5.0f )
- {
- p1.x = p3.x+((p1.x-p3.x)*5.0f/h);
- p1.y = p3.y+((p1.y-p3.y)*5.0f/h);
- p1.z = p3.z+((p1.z-p3.z)*5.0f/h);
- }
-
- buffer[i].triangle[0].x = p1.x;
- buffer[i].triangle[0].y = p1.y;
- buffer[i].triangle[0].z = p1.z;
- buffer[i].triangle[1].x = p2.x;
- buffer[i].triangle[1].y = p2.y;
- buffer[i].triangle[1].z = p2.z;
- buffer[i].triangle[2].x = p3.x;
- buffer[i].triangle[2].y = p3.y;
- buffer[i].triangle[2].z = p3.z;
-
- offset.x = (buffer[i].triangle[0].x+buffer[i].triangle[1].x+buffer[i].triangle[2].x)/3.0f;
- offset.y = (buffer[i].triangle[0].y+buffer[i].triangle[1].y+buffer[i].triangle[2].y)/3.0f;
- offset.z = (buffer[i].triangle[0].z+buffer[i].triangle[1].z+buffer[i].triangle[2].z)/3.0f;
-
- buffer[i].triangle[0].x -= offset.x;
- buffer[i].triangle[1].x -= offset.x;
- buffer[i].triangle[2].x -= offset.x;
-
- buffer[i].triangle[0].y -= offset.y;
- buffer[i].triangle[1].y -= offset.y;
- buffer[i].triangle[2].y -= offset.y;
-
- buffer[i].triangle[0].z -= offset.z;
- buffer[i].triangle[1].z -= offset.z;
- buffer[i].triangle[2].z -= offset.z;
-
- mat = pObj->RetWorldMatrix(part);
- pos = Math::Transform(*mat, offset);
- if ( m_type == PT_EGG )
- {
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = Math::Rand()*15.0f;
- mass = Math::Rand()*20.0f+20.0f;
- }
- else if ( m_type == PT_SPIDER )
- {
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = Math::Rand()*20.0f;
- mass = Math::Rand()*10.0f+15.0f;
- }
- else
- {
- speed.x = (Math::Rand()-0.5f)*30.0f;
- speed.z = (Math::Rand()-0.5f)*30.0f;
- speed.y = Math::Rand()*30.0f;
- mass = Math::Rand()*10.0f+15.0f;
- }
- if ( oType == OBJECT_STONE ) speed *= 0.5f;
- if ( oType == OBJECT_URANIUM ) speed *= 0.4f;
- duration = Math::Rand()*3.0f+3.0f;
- m_particule->CreateFrag(pos, speed, &buffer[i], PARTIFRAG,
- duration, mass, 0.5f);
- }
-}
-
-// Displays the error or eventual information,
-// linked to the destruction of an insect, a vehicle or building.
-
-void CPyro::DisplayError(PyroType type, CObject* pObj)
-{
- ObjectType oType;
- Error err;
-
- oType = pObj->RetType();
-
- if ( type == PT_FRAGT ||
- type == PT_FRAGO ||
- type == PT_FRAGW ||
- type == PT_EXPLOT ||
- type == PT_EXPLOO ||
- type == PT_EXPLOW ||
- type == PT_BURNT ||
- type == PT_BURNO )
- {
- err = ERR_OK;
- if ( oType == OBJECT_MOTHER ) err = INFO_DELETEMOTHER;
- if ( oType == OBJECT_ANT ) err = INFO_DELETEANT;
- if ( oType == OBJECT_BEE ) err = INFO_DELETEBEE;
- if ( oType == OBJECT_WORM ) err = INFO_DELETEWORM;
- if ( oType == OBJECT_SPIDER ) err = INFO_DELETESPIDER;
-
- if ( oType == OBJECT_MOBILEwa ||
- oType == OBJECT_MOBILEta ||
- oType == OBJECT_MOBILEfa ||
- oType == OBJECT_MOBILEia ||
- oType == OBJECT_MOBILEwc ||
- oType == OBJECT_MOBILEtc ||
- oType == OBJECT_MOBILEfc ||
- oType == OBJECT_MOBILEic ||
- oType == OBJECT_MOBILEwi ||
- oType == OBJECT_MOBILEti ||
- oType == OBJECT_MOBILEfi ||
- oType == OBJECT_MOBILEii ||
- oType == OBJECT_MOBILEws ||
- oType == OBJECT_MOBILEts ||
- oType == OBJECT_MOBILEfs ||
- oType == OBJECT_MOBILEis ||
- oType == OBJECT_MOBILErt ||
- oType == OBJECT_MOBILErc ||
- oType == OBJECT_MOBILErr ||
- oType == OBJECT_MOBILErs ||
- oType == OBJECT_MOBILEsa ||
- oType == OBJECT_MOBILEwt ||
- oType == OBJECT_MOBILEtt ||
- oType == OBJECT_MOBILEft ||
- oType == OBJECT_MOBILEit ||
- oType == OBJECT_MOBILEdr )
- {
- err = ERR_DELETEMOBILE;
- }
-
- if ( oType == OBJECT_DERRICK ||
- oType == OBJECT_FACTORY ||
- oType == OBJECT_STATION ||
- oType == OBJECT_CONVERT ||
- oType == OBJECT_REPAIR ||
- oType == OBJECT_DESTROYER||
- oType == OBJECT_TOWER ||
- oType == OBJECT_RESEARCH ||
- oType == OBJECT_RADAR ||
- oType == OBJECT_INFO ||
- oType == OBJECT_ENERGY ||
- oType == OBJECT_LABO ||
- oType == OBJECT_NUCLEAR ||
- oType == OBJECT_PARA ||
- oType == OBJECT_SAFE ||
- oType == OBJECT_HUSTON ||
- oType == OBJECT_START ||
- oType == OBJECT_END )
- {
- err = ERR_DELETEBUILDING;
- m_displayText->DisplayError(err, pObj->RetPosition(0), 5.0f);
- return;
- }
-
- if ( err != ERR_OK )
- {
- m_displayText->DisplayError(err, pObj);
- }
- }
-}
-
-
-// Management of an event.
-
-bool CPyro::EventProcess(const Event &event)
-{
- ParticuleType type;
- Math::Vector pos, speed, angle;
- Math::Point dim;
- float prog, factor, duration;
- int i, r;
-
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_engine->RetPause() ) return true;
-
- m_time += event.rTime;
- m_progress += event.rTime*m_speed;
-
- if ( m_soundChannel != -1 && m_object != 0 )
- {
- pos = m_object->RetPosition(0);
- m_sound->Position(m_soundChannel, pos);
-
- if ( m_lightRank != -1 )
- {
- pos.y += m_lightHeight;
- m_light->SetLightPos(m_lightRank, pos);
- }
- }
-
- if ( m_type == PT_SHOTT &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- if ( m_crashSphereUsed > 0 )
- {
- i = rand()%m_crashSphereUsed;
- pos = m_crashSpherePos[i];
- pos.x += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
- pos.z += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
- speed.x = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
- speed.z = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
- speed.y = Math::Rand()*m_crashSphereRadius[i]*1.0f;
- dim.x = Math::Rand()*m_crashSphereRadius[i]*0.5f+m_crashSphereRadius[i]*0.75f*m_force;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
- }
- else
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*m_size*0.3f;
- pos.z += (Math::Rand()-0.5f)*m_size*0.3f;
- speed.x = (Math::Rand()-0.5f)*m_size*0.1f;
- speed.z = (Math::Rand()-0.5f)*m_size*0.1f;
- speed.y = Math::Rand()*m_size*0.2f;
- dim.x = Math::Rand()*m_size/10.0f+m_size/10.0f*m_force;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
- }
- }
-
- if ( m_type == PT_SHOTH &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- for ( i=0 ; i<10 ; i++ )
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*m_size*0.2f;
- pos.z += (Math::Rand()-0.5f)*m_size*0.2f;
- pos.y += (Math::Rand()-0.5f)*m_size*0.5f;
- speed.x = (Math::Rand()-0.5f)*5.0f;
- speed.z = (Math::Rand()-0.5f)*5.0f;
- speed.y = Math::Rand()*1.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLOOD, Math::Rand()*3.0f+3.0f, Math::Rand()*10.0f+15.0f, 0.5f);
- }
- }
-
- if ( m_type == PT_SHOTM &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- r = (int)(10.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<r ; i++ )
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*20.0f;
- pos.z += (Math::Rand()-0.5f)*20.0f;
- pos.y += 8.0f;
- speed.x = (Math::Rand()-0.5f)*40.0f;
- speed.z = (Math::Rand()-0.5f)*40.0f;
- speed.y = Math::Rand()*40.0f;
- dim.x = Math::Rand()*8.0f+8.0f*m_force;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIBLOODM, 2.0f, 50.0f, 0.0f);
- }
- }
-
- if ( m_type == PT_SHOTW &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- if ( m_crashSphereUsed > 0 )
- {
- i = rand()%m_crashSphereUsed;
- pos = m_crashSpherePos[i];
- pos.x += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
- pos.z += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
- speed.x = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
- speed.z = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
- speed.y = Math::Rand()*m_crashSphereRadius[i]*1.0f;
- dim.x = 1.0f*m_force;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
- }
- else
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*m_size*0.3f;
- pos.z += (Math::Rand()-0.5f)*m_size*0.3f;
- speed.x = (Math::Rand()-0.5f)*m_size*0.1f;
- speed.z = (Math::Rand()-0.5f)*m_size*0.1f;
- speed.y = Math::Rand()*m_size*0.2f;
- dim.x = 1.0f*m_force;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
- }
- }
-
- if ( m_type == PT_SHOTW &&
- m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticuleSmoke = m_time;
-
- pos = m_pos;
- pos.y -= 2.0f;
- pos.x += (Math::Rand()-0.5f)*4.0f;
- pos.z += (Math::Rand()-0.5f)*4.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 10.0f+Math::Rand()*10.0f;
- dim.x = Math::Rand()*2.5f+2.0f*m_force;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 4.0f);
- }
-
- if ( (m_type == PT_FRAGT || m_type == PT_EXPLOT) &&
- m_progress < 0.05f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*m_size*1.0f;
- speed.z = (Math::Rand()-0.5f)*m_size*1.0f;
- speed.y = Math::Rand()*m_size*0.50f;
- dim.x = Math::Rand()*m_size/5.0f+m_size/5.0f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIEXPLOT);
- }
-
- if ( (m_type == PT_FRAGT || m_type == PT_EXPLOT) &&
- m_progress < 0.10f &&
- m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticuleSmoke = m_time;
-
- dim.x = Math::Rand()*m_size/3.0f+m_size/3.0f;
- dim.y = dim.x;
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*m_size*0.5f;
- pos.z += (Math::Rand()-0.5f)*m_size*0.5f;
- m_terrain->MoveOnFloor(pos);
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = -dim.x/2.0f/4.0f;
- pos.y += dim.x/2.0f;
-
- r = rand()%2;
- if ( r == 0 ) type = PARTISMOKE1;
- if ( r == 1 ) type = PARTISMOKE2;
- m_particule->CreateParticule(pos, speed, dim, type, 6.0f);
- }
-
- if ( (m_type == PT_FRAGO || m_type == PT_EXPLOO) &&
- m_progress < 0.03f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*m_size*2.0f;
- speed.z = (Math::Rand()-0.5f)*m_size*2.0f;
- speed.y = Math::Rand()*m_size*1.0f;
- dim.x = Math::Rand()*m_size/2.0f+m_size/2.0f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIEXPLOO);
- }
-
- if ( (m_type == PT_FRAGW || m_type == PT_EXPLOW) &&
- m_progress < 0.05f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*m_size*1.0f;
- speed.z = (Math::Rand()-0.5f)*m_size*1.0f;
- speed.y = Math::Rand()*m_size*0.50f;
- dim.x = 1.0f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
- }
-
- if ( (m_type == PT_FRAGW || m_type == PT_EXPLOW) &&
- m_progress < 0.25f &&
- m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticuleSmoke = m_time;
-
- pos = m_pos;
- pos.y -= 2.0f;
- pos.x += (Math::Rand()-0.5f)*4.0f;
- pos.z += (Math::Rand()-0.5f)*4.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 4.0f+Math::Rand()*4.0f;
- dim.x = Math::Rand()*2.5f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 4.0f);
- }
-
- if ( m_type == PT_WPCHECK )
- {
- if ( m_progress < 0.25f )
- {
- factor = 0.0f;
- }
- else
- {
- factor = powf((m_progress-0.25f)/0.75f, 2.0f)*30.0f;
- }
-
- if ( m_progress < 0.85f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- pos.y += factor;
- pos.x += (Math::Rand()-0.5f)*3.0f;
- pos.z += (Math::Rand()-0.5f)*3.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 5.0f+Math::Rand()*5.0f;
- dim.x = Math::Rand()*1.5f+1.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f);
-//? m_particule->CreateParticule(pos, speed, dim, (ParticuleType)(PARTILENS1+rand()%4), 2.0f);
- }
-
- angle = m_object->RetAngle(0);
- angle.y = m_progress*20.0f;
- angle.x = sinf(m_progress*49.0f)*0.3f;
- angle.z = sinf(m_progress*47.0f)*0.2f;
- m_object->SetAngle(0, angle);
-
- pos = m_pos;
- pos.y += factor;
- m_object->SetPosition(0, pos);
-
- if ( m_progress > 0.85f )
- {
- m_object->SetZoom(0, 1.0f-(m_progress-0.85f)/0.15f);
- }
- }
-
- if ( m_type == PT_FLCREATE )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- m_terrain->MoveOnFloor(pos);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = 2.0f+Math::Rand()*2.0f;
- dim.x = (Math::Rand()*1.0f+1.0f)*(0.2f+m_progress*0.8f);
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
- }
-
- angle = m_object->RetAngle(0);
-//? angle.y = powf(m_progress, 0.2f)*20.0f;
- angle.x = sinf(m_progress*49.0f)*0.3f*(1.0f-m_progress);
- angle.z = sinf(m_progress*47.0f)*0.2f*(1.0f-m_progress);
- m_object->SetAngle(0, angle);
-
- m_object->SetZoom(0, m_progress);
- }
-
- if ( m_type == PT_FLDELETE )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- m_terrain->MoveOnFloor(pos);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = 2.0f+Math::Rand()*2.0f;
- dim.x = (Math::Rand()*1.0f+1.0f)*(0.2f+m_progress*0.8f);
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.5f);
- }
-
- angle = m_object->RetAngle(0);
- angle.y = m_progress*20.0f;
- angle.x = sinf(m_progress*49.0f)*0.3f;
- angle.z = sinf(m_progress*47.0f)*0.2f;
- m_object->SetAngle(0, angle);
-
- m_object->SetZoom(0, 1.0f-m_progress);
- }
-
- if ( m_type == PT_RESET )
- {
-#if 0
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*6.0f;
- speed.z = (Math::Rand()-0.5f)*6.0f;
- speed.y = Math::Rand()*12.0f;
- dim.x = (Math::Rand()*2.5f+2.5f)*(1.0f-m_progress*0.9f);
- dim.y = dim.x;
- pos.y += dim.y;
- m_particule->CreateParticule(pos, speed, dim,
- (ParticuleType)(PARTILENS1+rand()%4),
- Math::Rand()*2.5f+2.5f,
- Math::Rand()*5.0f+5.0f, 0.0f);
- }
-#else
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 5.0f+Math::Rand()*5.0f;
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
-
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = Math::Rand()*10.0f;
- speed *= 0.5f+m_progress*0.5f;
- dim.x = 0.6f;
- dim.y = dim.x;
- pos.y += dim.y;
- duration = Math::Rand()*1.5f+1.5f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
- duration, 0.0f,
- duration*0.9f, 0.7f);
- }
-#endif
-
- angle = m_object->RetResetAngle();
- m_object->SetAngleY(0, angle.y-powf((1.0f-m_progress)*5.0f, 2.0f));
- m_object->SetZoom(0, m_progress);
- }
-
- if ( m_type == PT_FINDING )
- {
- if ( m_object != 0 &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- factor = m_size*0.3f;
- if ( m_object->RetType() == OBJECT_SAFE ) factor *= 1.3f;
- if ( factor > 40.0f ) factor = 40.0f;
- pos = m_pos;
- m_terrain->MoveOnFloor(pos);
- pos.x += (Math::Rand()-0.5f)*factor;
- pos.z += (Math::Rand()-0.5f)*factor;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = 4.0f+Math::Rand()*4.0f;
- dim.x = (Math::Rand()*3.0f+3.0f)*(1.0f-m_progress*0.9f);
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.5f);
- }
- }
-
- if ( (m_type == PT_BURNT || m_type == PT_BURNO) &&
- m_object != 0 )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- factor = m_size/25.0f; // 1 = standard size
-
- pos = m_object->RetPosition(0);
- pos.y -= m_object->RetCharacter()->height;
- pos.x += (Math::Rand()-0.5f)*(4.0f+8.0f*m_progress)*factor;
- pos.z += (Math::Rand()-0.5f)*(4.0f+8.0f*m_progress)*factor;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 0.0f;
- dim.x = (Math::Rand()*2.5f+1.0f)*factor;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f);
-
- pos = m_object->RetPosition(0);
- pos.y -= m_object->RetCharacter()->height;
- pos.x += (Math::Rand()-0.5f)*(2.0f+4.0f*m_progress)*factor;
- pos.z += (Math::Rand()-0.5f)*(2.0f+4.0f*m_progress)*factor;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = (Math::Rand()*5.0f*m_progress+3.0f)*factor;
- dim.x = (Math::Rand()*2.0f+1.0f)*factor;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f);
-
- pos = m_object->RetPosition(0);
- pos.y -= 2.0f;
- pos.x += (Math::Rand()-0.5f)*5.0f*factor;
- pos.z += (Math::Rand()-0.5f)*5.0f*factor;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = (6.0f+Math::Rand()*6.0f+m_progress*6.0f)*factor;
- dim.x = (Math::Rand()*1.5f+1.0f+m_progress*3.0f)*factor;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
- }
-
- if ( m_type == PT_BURNT )
- {
- BurnProgress();
- }
- else
- {
- speed.y = 0.0f;
- speed.x = (Math::Rand()-0.5f)*m_progress*1.0f;
- speed.z = (Math::Rand()-0.5f)*m_progress*1.0f;
- if ( m_progress > 0.8f )
- {
- prog = (m_progress-0.8f)/0.2f; // 0..1
- speed.y = -prog*6.0f; // sinks into the ground
- m_object->SetZoom(0, 1.0f-prog*0.5f);
- }
- m_object->SetLinVibration(speed);
- }
- }
-
- if ( m_type == PT_WIN )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.y += 1.5f;
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = 8.0f+Math::Rand()*8.0f;
- dim.x = Math::Rand()*0.2f+0.2f;
- dim.y = dim.x;
- m_particule->CreateTrack(pos, speed, dim,
- (ParticuleType)(PARTITRACK7+rand()%4),
- 3.0f, 20.0f, 1.0f, 0.4f);
- }
- }
-
- if ( m_type == PT_LOST )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.y -= 2.0f;
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 1.0f+Math::Rand()*1.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 8.0f, 0.0f, 0.0f);
- }
- }
-
- if ( m_type == PT_FALL )
- {
- FallProgress(event.rTime);
- }
-
- if ( m_lightRank != -1 )
- {
- LightOperFrame(event.rTime);
- }
-
- return true;
-}
-
-// Indicates that the object binds to the effect no longer exists, without deleting it.
-
-void CPyro::CutObjectLink(CObject* pObj)
-{
- if ( m_object == pObj )
- {
- m_object = 0;
- }
-}
-
-// Indicates whether the pyrotechnic effect is complete.
-
-Error CPyro::IsEnded()
-{
- // Destroys the object that exploded.
- //It should not be destroyed at the end of the Create,
- //because it is sometimes the object itself that makes the Create:
- // pyro->Create(PT_FRAGT, this);
- if ( m_type == PT_FRAGT ||
- m_type == PT_FRAGO ||
- m_type == PT_FRAGW ||
- m_type == PT_SPIDER ||
- m_type == PT_EGG )
- {
- DeleteObject(true, true);
- }
-
- if ( m_type == PT_FALL ) // freight which grave?
- {
- return FallIsEnded();
- }
-
- if ( m_type == PT_WIN ||
- m_type == PT_LOST )
- {
- return ERR_CONTINUE;
- }
-
- // End of the pyrotechnic effect?
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- if ( m_type == PT_EXPLOT ||
- m_type == PT_EXPLOO ||
- m_type == PT_EXPLOW ) // explosion?
- {
- ExploTerminate();
- }
-
- if ( m_type == PT_BURNT ||
- m_type == PT_BURNO ) // burning?
- {
- BurnTerminate();
- }
-
- if ( m_type == PT_WPCHECK ||
- m_type == PT_FLDELETE )
- {
- DeleteObject(true, true);
- }
-
- if ( m_type == PT_FLCREATE )
- {
- m_object->SetAngleX(0, 0.0f);
- m_object->SetAngleZ(0, 0.0f);
- m_object->SetZoom(0, 1.0f);
- }
-
- if ( m_type == PT_RESET )
- {
- m_object->SetPosition(0, m_object->RetResetPosition());
- m_object->SetAngle(0, m_object->RetResetAngle());
- m_object->SetZoom(0, 1.0f);
- }
-
- if ( m_lightRank != -1 )
- {
- m_light->DeleteLight(m_lightRank);
- m_lightRank = -1;
- }
-
- return ERR_STOP;
-}
-
-// Removes the binding to a pyrotechnic effect.
-
-void CPyro::DeleteObject(bool bPrimary, bool bSecondary)
-{
- CObject *sub, *truck;
- Math::Vector pos;
- ObjectType type;
-
- if ( m_object == 0 ) return;
-
- if ( m_object->RetResetCap() == RESET_MOVE ) // resettable object?
- {
- m_object->SetEnable(false); // object cache and inactive
- pos = m_object->RetPosition(0);
- pos.y = -100.0f;
- m_object->SetPosition(0, pos);
- return;
- }
-
- type = m_object->RetType();
- if ( bSecondary &&
- type != OBJECT_FACTORY &&
- type != OBJECT_NUCLEAR &&
- type != OBJECT_ENERGY )
- {
- sub = m_object->RetPower();
- if ( sub != 0 )
- {
- sub->DeleteObject(); // removes the battery
- delete sub;
- m_object->SetPower(0);
- }
-
- sub = m_object->RetFret();
- if ( sub != 0 )
- {
- sub->DeleteObject(); // removes the object transported
- delete sub;
- m_object->SetFret(0);
- }
- }
-
- if ( bPrimary )
- {
- truck = m_object->RetTruck();
- if ( truck != 0 ) // object carries?
- {
- if ( truck->RetPower() == m_object )
- {
- truck->SetPower(0);
- }
- if ( truck->RetFret() == m_object )
- {
- truck->SetFret(0);
- }
- }
-
- sub = m_object;
- sub->DeleteObject(); // removes the object (*)
- delete sub;
- m_object = 0;
- }
-}
-
-// (*) CObject :: DeleteObject can reset m_object through CPyro :: CutObjectLink!
-
-
-// Empty the table of operations of animation of light.
-
-void CPyro::LightOperFlush()
-{
- m_lightOperTotal = 0;
-}
-
-// Adds an animation operation of the light.
-
-void CPyro::LightOperAdd(float progress, float intensity,
- float r, float g, float b)
-{
- int i;
-
- i = m_lightOperTotal;
-
- m_lightOper[i].progress = progress;
- m_lightOper[i].intensity = intensity;
- m_lightOper[i].color.r = r;
- m_lightOper[i].color.g = g;
- m_lightOper[i].color.b = b;
-
- m_lightOperTotal ++;
-}
-
-// Makes evolve the associated light.
-
-void CPyro::LightOperFrame(float rTime)
-{
- D3DCOLORVALUE color;
- float progress, intensity;
- int i;
-
- for ( i=0 ; i<m_lightOperTotal ; i++ )
- {
- if ( m_progress < m_lightOper[i].progress )
- {
- progress = (m_progress-m_lightOper[i-1].progress) / (m_lightOper[i].progress-m_lightOper[i-1].progress);
-
- intensity = m_lightOper[i-1].intensity + (m_lightOper[i].intensity-m_lightOper[i-1].intensity)*progress;
- color.r = m_lightOper[i-1].color.r + (m_lightOper[i].color.r-m_lightOper[i-1].color.r)*progress;
- color.g = m_lightOper[i-1].color.g + (m_lightOper[i].color.g-m_lightOper[i-1].color.g)*progress;
- color.b = m_lightOper[i-1].color.b + (m_lightOper[i].color.b-m_lightOper[i-1].color.b)*progress;
-
- m_light->SetLightIntensity(m_lightRank, intensity);
- m_light->SetLightColor(m_lightRank, color);
- break;
- }
- }
-}
-
-
-// Creates light to accompany a pyrotechnic effect.
-
-bool CPyro::CreateLight(Math::Vector pos, float height)
-{
- D3DLIGHT7 light;
-
- if ( !m_engine->RetLightMode() ) return true;
-
- m_lightHeight = height;
-
- ZeroMemory( &light, sizeof(light) );
- light.dltType = D3DLIGHT_SPOT;
- light.dvPosition.x = pos.x;
- light.dvPosition.y = pos.y+height;
- light.dvPosition.z = pos.z;
- light.dvDirection.x = 0.0f;
- light.dvDirection.y = -1.0f; // against the bottom
- light.dvDirection.z = 0.0f;
- light.dvRange = D3DLIGHT_RANGE_MAX;
- light.dvFalloff = 1.0f;
- light.dvAttenuation0 = 1.0f;
- light.dvAttenuation1 = 0.0f;
- light.dvAttenuation2 = 0.0f;
- light.dvTheta = 0.0f;
- light.dvPhi = Math::PI/4.0f;
-
- m_lightRank = m_light->CreateLight();
- if ( m_lightRank == -1 ) return false;
-
- m_light->SetLight(m_lightRank, light);
- m_light->SetLightIntensity(m_lightRank, 0.0f);
-
- // Only illuminates the objects on the ground.
- m_light->SetLightIncluType(m_lightRank, TYPETERRAIN);
-
- return true;
-}
-
-
-// Starts the explosion of a vehicle.
-
-void CPyro::ExploStart()
-{
- Math::Vector pos, angle, speed, min, max;
- float weight;
- int i, objRank, channel;
-
- m_burnType = m_object->RetType();
-
- pos = m_object->RetPosition(0);
- m_burnFall = m_terrain->RetFloorHeight(pos, true);
-
- m_object->Simplify();
- m_object->SetLock(true); // ruin not usable yet
- m_object->SetExplo(true); // being destroyed
- m_object->FlatParent();
-
- if ( m_object->RetSelect() )
- {
- m_object->SetSelect(false); // deselects the object
- m_camera->SetType(CAMERA_EXPLO);
- m_main->DeselectAll();
- }
- m_object->DeleteDeselList(m_object);
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- objRank = m_object->RetObjectRank(i);
- if ( objRank == -1 ) continue;
- m_engine->ChangeSecondTexture(objRank, "dirty04.tga");
-
- pos = m_object->RetPosition(i);
-
- if ( i == 0 ) // main part?
- {
- weight = 0.0f;
-
- speed.y = -1.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- }
- else
- {
- m_engine->GetBBox(objRank, min, max);
- weight = Math::Distance(min, max); // weight according to size!
-
- speed.y = 10.0f+Math::Rand()*20.0f;
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- }
-
- channel = m_particule->CreatePart(pos, speed, PARTIPART, 10.0f, 20.0f, weight, 0.5f);
- if ( channel != -1 )
- {
- m_object->SetMasterParticule(i, channel);
- }
- }
- m_engine->LoadTexture("dirty04.tga", 1);
-
- DeleteObject(false, true); // destroys the object transported + the battery
-}
-
-// Ends the explosion of a vehicle.
-
-void CPyro::ExploTerminate()
-{
- DeleteObject(true, false); // removes the main object
-}
-
-
-// Starts a vehicle fire.
-
-void CPyro::BurnStart()
-{
- Math::Vector pos, angle;
- int i, objRank;
-
- m_burnType = m_object->RetType();
-
- pos = m_object->RetPosition(0);
- m_burnFall = m_terrain->RetFloorHeight(pos, true);
-
- m_object->Simplify();
- m_object->SetLock(true); // ruin not usable yet
-
- if ( m_object->RetSelect() )
- {
- m_object->SetSelect(false); // deselects the object
- m_camera->SetType(CAMERA_EXPLO);
- m_main->DeselectAll();
- }
- m_object->DeleteDeselList(m_object);
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- objRank = m_object->RetObjectRank(i);
- if ( objRank == -1 ) continue;
- m_engine->ChangeSecondTexture(objRank, "dirty04.tga");
- }
- m_engine->LoadTexture("dirty04.tga", 1);
-
- m_burnPartTotal = 0;
-
- if ( m_burnType == OBJECT_DERRICK ||
- m_burnType == OBJECT_FACTORY ||
- m_burnType == OBJECT_REPAIR ||
- m_burnType == OBJECT_DESTROYER||
- m_burnType == OBJECT_CONVERT ||
- m_burnType == OBJECT_TOWER ||
- m_burnType == OBJECT_RESEARCH ||
- m_burnType == OBJECT_ENERGY ||
- m_burnType == OBJECT_LABO )
- {
- pos.x = 0.0f;
- pos.y = -(4.0f+Math::Rand()*4.0f);
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.4f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.4f;
- }
- else if ( m_burnType == OBJECT_STATION ||
- m_burnType == OBJECT_RADAR ||
- m_burnType == OBJECT_INFO )
- {
- pos.x = 0.0f;
- pos.y = -(1.0f+Math::Rand()*1.0f);
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.2f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.2f;
- }
- else if ( m_burnType == OBJECT_NUCLEAR )
- {
- pos.x = 0.0f;
- pos.y = -(10.0f+Math::Rand()*10.0f);
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.4f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.4f;
- }
- else if ( m_burnType == OBJECT_PARA )
- {
- pos.x = 0.0f;
- pos.y = -(10.0f+Math::Rand()*10.0f);
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.4f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.4f;
- }
- else if ( m_burnType == OBJECT_SAFE )
- {
- pos.x = 0.0f;
- pos.y = -(10.0f+Math::Rand()*10.0f);
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.4f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.4f;
- }
- else if ( m_burnType == OBJECT_HUSTON )
- {
- pos.x = 0.0f;
- pos.y = -(10.0f+Math::Rand()*10.0f);
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.4f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.4f;
- }
- else if ( m_burnType == OBJECT_MOBILEwa ||
- m_burnType == OBJECT_MOBILEwc ||
- m_burnType == OBJECT_MOBILEwi ||
- m_burnType == OBJECT_MOBILEws ||
- m_burnType == OBJECT_MOBILEwt )
- {
- pos.x = 0.0f;
- pos.y = -(0.5f+Math::Rand()*1.0f);
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.8f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.4f;
- }
- else if ( m_burnType == OBJECT_TEEN31 ) // basket?
- {
- pos.x = 0.0f;
- pos.y = 0.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.8f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.2f;
- }
- else
- {
- pos.x = 0.0f;
- pos.y = -(2.0f+Math::Rand()*2.0f);
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.8f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.8f;
- }
- BurnAddPart(0, pos, angle); // movement of the main part
-
- m_burnKeepPart[0] = -1; // nothing to keep
-
- if ( m_burnType == OBJECT_DERRICK )
- {
- pos.x = 0.0f;
- pos.y = -40.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the drill
- }
-
- if ( m_burnType == OBJECT_REPAIR )
- {
- pos.x = 0.0f;
- pos.y = -12.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.2f;
- angle.y = (Math::Rand()-0.5f)*0.2f;
- angle.z = -90.0f*Math::PI/180.0f;
- BurnAddPart(1, pos, angle); // down the sensor
- }
-
- if ( m_burnType == OBJECT_DESTROYER )
- {
- pos.x = 0.0f;
- pos.y = -12.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.2f;
- angle.y = (Math::Rand()-0.5f)*0.2f;
- angle.z = -90.0f*Math::PI/180.0f;
- BurnAddPart(1, pos, angle); // down the sensor
- }
-
- if ( m_burnType == OBJECT_CONVERT )
- {
- pos.x = 0.0f;
- pos.y = -200.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.5f;
- angle.y = (Math::Rand()-0.5f)*0.5f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the cover
- BurnAddPart(2, pos, angle);
- BurnAddPart(3, pos, angle);
- }
-
- if ( m_burnType == OBJECT_TOWER )
- {
- pos.x = 0.0f;
- pos.y = -7.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.4f;
- angle.y = (Math::Rand()-0.5f)*0.4f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the cannon
- }
-
- if ( m_burnType == OBJECT_RESEARCH )
- {
- pos.x = 0.0f;
- pos.y = -7.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.2f;
- angle.y = (Math::Rand()-0.5f)*0.2f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the anemometer
- }
-
- if ( m_burnType == OBJECT_RADAR )
- {
- pos.x = 0.0f;
- pos.y = -14.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.4f;
- angle.y = (Math::Rand()-0.5f)*0.4f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the radar
- BurnAddPart(2, pos, angle);
- }
-
- if ( m_burnType == OBJECT_INFO )
- {
- pos.x = 0.0f;
- pos.y = -14.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.4f;
- angle.y = (Math::Rand()-0.5f)*0.4f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the information terminal
- BurnAddPart(2, pos, angle);
- }
-
- if ( m_burnType == OBJECT_LABO )
- {
- pos.x = 0.0f;
- pos.y = -12.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the arm
- }
-
- if ( m_burnType == OBJECT_NUCLEAR )
- {
- pos.x = 0.0f;
- pos.y = 0.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = -135.0f*Math::PI/180.0f;
- BurnAddPart(1, pos, angle); // down the cover
- }
-
- if ( m_burnType == OBJECT_MOBILEfa ||
- m_burnType == OBJECT_MOBILEta ||
- m_burnType == OBJECT_MOBILEwa ||
- m_burnType == OBJECT_MOBILEia )
- {
- pos.x = 2.0f;
- pos.y = -5.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.2f;
- angle.y = (Math::Rand()-0.5f)*0.2f;
- angle.z = 40.0f*Math::PI/180.0f;
- BurnAddPart(1, pos, angle); // down the arm
- }
-
- if ( m_burnType == OBJECT_MOBILEfs ||
- m_burnType == OBJECT_MOBILEts ||
- m_burnType == OBJECT_MOBILEws ||
- m_burnType == OBJECT_MOBILEis )
- {
- pos.x = 0.0f;
- pos.y = -7.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.2f;
- angle.y = (Math::Rand()-0.5f)*0.2f;
- angle.z = 50.0f*Math::PI/180.0f;
- BurnAddPart(1, pos, angle); // down the sensor
- }
-
- if ( m_burnType == OBJECT_MOBILEfc ||
- m_burnType == OBJECT_MOBILEtc ||
- m_burnType == OBJECT_MOBILEwc ||
- m_burnType == OBJECT_MOBILEic )
- {
- pos.x = -1.5f;
- pos.y = -5.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.2f;
- angle.y = (Math::Rand()-0.5f)*0.2f;
- angle.z = -25.0f*Math::PI/180.0f;
- BurnAddPart(1, pos, angle); // down the cannon
- }
-
- if ( m_burnType == OBJECT_MOBILEfi ||
- m_burnType == OBJECT_MOBILEti ||
- m_burnType == OBJECT_MOBILEwi ||
- m_burnType == OBJECT_MOBILEii )
- {
- pos.x = -1.5f;
- pos.y = -5.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.2f;
- angle.y = (Math::Rand()-0.5f)*0.2f;
- angle.z = -25.0f*Math::PI/180.0f;
- BurnAddPart(1, pos, angle); // down the insect-cannon
- }
-
- if ( m_burnType == OBJECT_MOBILErt ||
- m_burnType == OBJECT_MOBILErc )
- {
- pos.x = 0.0f;
- pos.y = -10.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the holder
-
- pos.x = 0.0f;
- pos.y = -10.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(2, pos, angle); // down the pestle/cannon
- }
-
- if ( m_burnType == OBJECT_MOBILErr )
- {
- pos.x = 0.0f;
- pos.y = -10.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the holder
-
- pos.x = 0.0f;
- pos.y = 0.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = -Math::PI/2.0f;
- BurnAddPart(4, pos, angle);
-
- pos.x = 0.0f;
- pos.y = 0.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = Math::PI/2.5f;
- BurnAddPart(2, pos, angle);
- }
-
- if ( m_burnType == OBJECT_MOBILErs )
- {
- pos.x = 0.0f;
- pos.y = -10.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the holder
-
- pos.x = 0.0f;
- pos.y = -5.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(2, pos, angle);
-
- pos.x = 0.0f;
- pos.y = -5.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(3, pos, angle);
- }
-
- if ( m_burnType == OBJECT_MOBILEsa )
- {
- pos.x = 0.0f;
- pos.y = -10.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the holder
- }
-
- if ( m_burnType == OBJECT_MOBILEwa ||
- m_burnType == OBJECT_MOBILEwc ||
- m_burnType == OBJECT_MOBILEwi ||
- m_burnType == OBJECT_MOBILEws ||
- m_burnType == OBJECT_MOBILEwt ) // wheels?
- {
- for ( i=0 ; i<4 ; i++ )
- {
- pos.x = 0.0f;
- pos.y = Math::Rand()*0.5f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*Math::PI/2.0f;
- angle.y = (Math::Rand()-0.5f)*Math::PI/2.0f;
- angle.z = 0.0f;
- BurnAddPart(6+i, pos, angle); // wheel
-
- m_burnKeepPart[i] = 6+i; // we keep the wheels
- }
- m_burnKeepPart[i] = -1;
- }
-
- if ( m_burnType == OBJECT_MOBILEta ||
- m_burnType == OBJECT_MOBILEtc ||
- m_burnType == OBJECT_MOBILEti ||
- m_burnType == OBJECT_MOBILEts ||
- m_burnType == OBJECT_MOBILErt ||
- m_burnType == OBJECT_MOBILErc ||
- m_burnType == OBJECT_MOBILErr ||
- m_burnType == OBJECT_MOBILErs ||
- m_burnType == OBJECT_MOBILEsa ||
- m_burnType == OBJECT_MOBILEdr ) // caterpillars?
- {
- pos.x = 0.0f;
- pos.y = -4.0f;
- pos.z = 2.0f;
- angle.x = (Math::Rand()-0.5f)*20.0f*Math::PI/180.0f;
- angle.y = (Math::Rand()-0.5f)*10.0f*Math::PI/180.0f;
- angle.z = (Math::Rand()-0.5f)*30.0f*Math::PI/180.0f;
- BurnAddPart(6, pos, angle); // down the right caterpillar
-
- pos.x = 0.0f;
- pos.y = -4.0f;
- pos.z = -2.0f;
- angle.x = (Math::Rand()-0.5f)*20.0f*Math::PI/180.0f;
- angle.y = (Math::Rand()-0.5f)*10.0f*Math::PI/180.0f;
- angle.z = (Math::Rand()-0.5f)*30.0f*Math::PI/180.0f;
- BurnAddPart(7, pos, angle); // down the left caterpillar
- }
-
- if ( m_burnType == OBJECT_MOBILEfa ||
- m_burnType == OBJECT_MOBILEfc ||
- m_burnType == OBJECT_MOBILEfi ||
- m_burnType == OBJECT_MOBILEfs ||
- m_burnType == OBJECT_MOBILEft ) // flying?
- {
- for ( i=0 ; i<3 ; i++ )
- {
- pos.x = 0.0f;
- pos.y = -3.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*Math::PI/2.0f;
- BurnAddPart(6+i, pos, angle); // foot
- }
- m_burnKeepPart[i] = -1;
- }
-
- if ( m_burnType == OBJECT_MOBILEia ||
- m_burnType == OBJECT_MOBILEic ||
- m_burnType == OBJECT_MOBILEii ||
- m_burnType == OBJECT_MOBILEis ) // legs?
- {
- for ( i=0 ; i<6; i++ )
- {
- pos.x = 0.0f;
- pos.y = -3.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = (Math::Rand()-0.5f)*Math::PI/4.0f;
- angle.z = (Math::Rand()-0.5f)*Math::PI/4.0f;
- BurnAddPart(6+i, pos, angle); // leg
- }
- }
-}
-
-// Adds a part move.
-
-void CPyro::BurnAddPart(int part, Math::Vector pos, Math::Vector angle)
-{
- int i;
-
- i = m_burnPartTotal;
- m_burnPart[i].part = part;
- m_burnPart[i].initialPos = m_object->RetPosition(part);
- m_burnPart[i].finalPos = m_burnPart[i].initialPos+pos;
- m_burnPart[i].initialAngle = m_object->RetAngle(part);
- m_burnPart[i].finalAngle = m_burnPart[i].initialAngle+angle;
-
- m_burnPartTotal ++;
-}
-
-// Advances of a vehicle fire.
-
-void CPyro::BurnProgress()
-{
- CObject* sub;
- Math::Vector pos;
- float h;
- int i;
-
- if ( m_burnType == OBJECT_TEEN31 ) // basket?
- {
- m_object->SetZoomY(0, 1.0f-m_progress*0.5f); // slight flattening
- }
-
- for ( i=0 ; i<m_burnPartTotal ; i++ )
- {
- pos = m_burnPart[i].initialPos + m_progress*(m_burnPart[i].finalPos-m_burnPart[i].initialPos);
- if ( i == 0 && m_burnFall > 0.0f )
- {
- h = powf(m_progress, 2.0f)*1000.0f;
- if ( h > m_burnFall ) h = m_burnFall;
- pos.y -= h;
- }
- m_object->SetPosition(m_burnPart[i].part, pos);
-
- pos = m_burnPart[i].initialAngle + m_progress*(m_burnPart[i].finalAngle-m_burnPart[i].initialAngle);
- m_object->SetAngle(m_burnPart[i].part, pos);
- }
-
- sub = m_object->RetPower();
- if ( sub != 0 ) // is there a battery?
- {
- sub->SetZoomY(0, 1.0f-m_progress); // complete flattening
- }
-}
-
-// Indicates whether a part should be retained.
-
-bool CPyro::BurnIsKeepPart(int part)
-{
- int i;
-
- i = 0;
- while ( m_burnKeepPart[i] != -1 )
- {
- if ( part == m_burnKeepPart[i++] ) return true; // must keep
- }
- return false; // must destroy
-}
-
-// Ends the fire of an insect or a vehicle.
-
-void CPyro::BurnTerminate()
-{
- int i, objRank;
-
- if ( m_type == PT_BURNO ) // organic object is burning?
- {
- DeleteObject(true, true); // removes the insect
- return;
- }
-
- for ( i=1 ; i<OBJECTMAXPART ; i++ )
- {
- objRank = m_object->RetObjectRank(i);
- if ( objRank == -1 ) continue;
- if ( BurnIsKeepPart(i) ) continue;
-
- m_object->DeletePart(i);
- }
-
- DeleteObject(false, true); // destroys the object transported + the battery
-
- if ( m_burnType == OBJECT_DERRICK ||
- m_burnType == OBJECT_STATION ||
- m_burnType == OBJECT_FACTORY ||
- m_burnType == OBJECT_REPAIR ||
- m_burnType == OBJECT_DESTROYER||
- m_burnType == OBJECT_CONVERT ||
- m_burnType == OBJECT_TOWER ||
- m_burnType == OBJECT_RESEARCH ||
- m_burnType == OBJECT_RADAR ||
- m_burnType == OBJECT_INFO ||
- m_burnType == OBJECT_ENERGY ||
- m_burnType == OBJECT_LABO ||
- m_burnType == OBJECT_NUCLEAR ||
- m_burnType == OBJECT_PARA ||
- m_burnType == OBJECT_SAFE ||
- m_burnType == OBJECT_HUSTON ||
- m_burnType == OBJECT_START ||
- m_burnType == OBJECT_END )
- {
- m_object->SetType(OBJECT_RUINfactory); // others become a ruin
- m_object->SetLock(false);
- }
- else
- {
- m_object->SetType(OBJECT_RUINmobilew1); // others become a ruin
- m_object->SetLock(false);
- }
-
- m_object->SetBurn(false); // ruin usable (c-e-d. recoverable)
-}
-
-
-// Start of an object freight falling.
-
-void CPyro::FallStart()
-{
- Math::Vector pos;
-
- m_object->SetBurn(true); // usable
-
- pos = m_object->RetPosition(0);
- m_fallFloor = m_terrain->RetFloorLevel(pos);
- m_fallSpeed = 0.0f;
- m_fallBulletTime = 0.0f;
- m_bFallEnding = false;
-}
-
-// Seeking an object explode by the falling ball of bees.
-
-CObject* CPyro::FallSearchBeeExplo()
-{
- CObject* pObj;
- Math::Vector iPos, oPos;
- ObjectType oType;
- float iRadius, oRadius, distance, shieldRadius;
- int i, j;
-
- m_object->GetCrashSphere(0, iPos, iRadius);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( oType != OBJECT_HUMAN &&
- oType != OBJECT_MOBILEfa &&
- oType != OBJECT_MOBILEta &&
- oType != OBJECT_MOBILEwa &&
- oType != OBJECT_MOBILEia &&
- oType != OBJECT_MOBILEfc &&
- oType != OBJECT_MOBILEtc &&
- oType != OBJECT_MOBILEwc &&
- oType != OBJECT_MOBILEic &&
- oType != OBJECT_MOBILEfi &&
- oType != OBJECT_MOBILEti &&
- oType != OBJECT_MOBILEwi &&
- oType != OBJECT_MOBILEii &&
- oType != OBJECT_MOBILEfs &&
- oType != OBJECT_MOBILEts &&
- oType != OBJECT_MOBILEws &&
- oType != OBJECT_MOBILEis &&
- oType != OBJECT_MOBILErt &&
- oType != OBJECT_MOBILErc &&
- oType != OBJECT_MOBILErr &&
- oType != OBJECT_MOBILErs &&
- oType != OBJECT_MOBILEsa &&
- oType != OBJECT_MOBILEtg &&
- oType != OBJECT_MOBILEft &&
- oType != OBJECT_MOBILEtt &&
- oType != OBJECT_MOBILEwt &&
- oType != OBJECT_MOBILEit &&
- oType != OBJECT_MOBILEdr &&
- oType != OBJECT_BASE &&
- oType != OBJECT_DERRICK &&
- oType != OBJECT_STATION &&
- oType != OBJECT_FACTORY &&
- oType != OBJECT_REPAIR &&
- oType != OBJECT_DESTROYER&&
- oType != OBJECT_CONVERT &&
- oType != OBJECT_TOWER &&
- oType != OBJECT_RESEARCH &&
- oType != OBJECT_RADAR &&
- oType != OBJECT_INFO &&
- oType != OBJECT_ENERGY &&
- oType != OBJECT_LABO &&
- oType != OBJECT_NUCLEAR &&
- oType != OBJECT_PARA &&
- oType != OBJECT_SAFE &&
- oType != OBJECT_HUSTON &&
- oType != OBJECT_METAL &&
- oType != OBJECT_POWER &&
- oType != OBJECT_ATOMIC ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- oPos = pObj->RetPosition(0);
-
- shieldRadius = pObj->RetShieldRadius();
- if ( shieldRadius > 0.0f )
- {
- distance = Math::Distance(oPos, iPos);
- if ( distance <= shieldRadius ) return pObj;
- }
-
- if ( oType == OBJECT_BASE )
- {
- distance = Math::Distance(oPos, iPos);
- if ( distance < 25.0f ) return pObj;
- }
-
- // Test the center of the object, which is necessary for objects
- // that have no sphere in the center (station).
- distance = Math::Distance(oPos, iPos)-4.0f;
- if ( distance < 5.0f ) return pObj;
-
- // Test with all spheres of the object.
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- distance = Math::Distance(oPos, iPos);
- if ( distance <= iRadius+oRadius )
- {
- return pObj;
- }
- }
- }
- return 0;
-}
-
-// Fall of an object's freight.
-
-void CPyro::FallProgress(float rTime)
-{
- CObject* pObj;
- Math::Vector pos;
- bool bFloor = false;
-
- if ( m_object == 0 ) return;
-
- m_fallSpeed += rTime*50.0f; // v2 = v1 + a*dt
- pos = m_object->RetPosition(0);
- pos.y -= m_fallSpeed*rTime; // dd -= v2*dt
-
- if ( pos.y <= m_fallFloor ) // below the ground level?
- {
- pos.y = m_fallFloor;
- bFloor = true;
- }
- m_object->SetPosition(0, pos);
-
- if ( m_object->RetType() == OBJECT_BULLET )
- {
- m_fallBulletTime += rTime;
-
- if ( m_fallBulletTime > 0.2f || bFloor )
- {
- m_fallBulletTime = 0.0f;
-
- pObj = FallSearchBeeExplo();
- if ( pObj == 0 )
- {
- if ( bFloor ) // reaches the ground?
- {
- m_object->ExploObject(EXPLO_BOUM, 0.0f); // start explosion
- }
- }
- else
- {
- if ( pObj->RetShieldRadius() > 0.0f ) // protected by shield?
- {
- m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f, 0.0f, 0.0f);
- m_sound->Play(SOUND_GUNDEL);
-
- DeleteObject(true, true); // removes the ball
- }
- else
- {
- if ( pObj->ExploObject(EXPLO_BOUM, 1.0f) ) // start explosion
- {
- DeleteObject(true, true); // removes the ball
- }
- else
- {
- m_object->ExploObject(EXPLO_BOUM, 0.0f); // start explosion
- }
- }
- }
-
- if ( bFloor || pObj != 0 )
- {
- m_bFallEnding = true;
- }
- }
- }
-}
-
-// Indicates whether the fall is over.
-
-Error CPyro::FallIsEnded()
-{
- Math::Vector pos;
-
- if ( m_bFallEnding || m_object == 0 ) return ERR_STOP;
-
- pos = m_object->RetPosition(0);
- if ( pos.y > m_fallFloor ) return ERR_CONTINUE;
-
- m_sound->Play(SOUND_BOUM, pos);
- m_object->SetBurn(false); // usable again
-
- return ERR_STOP;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// pyro.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "object/robotmain.h"
+#include "old/terrain.h"
+#include "old/camera.h"
+#include "old/particule.h"
+#include "old/light.h"
+#include "object/object.h"
+#include "object/motion/motion.h"
+#include "object/motion/motionhuman.h"
+#include "ui/displaytext.h"
+#include "old/sound.h"
+#include "old/pyro.h"
+
+
+
+
+// Object's constructor.
+
+CPyro::CPyro(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_PYRO, this, 100);
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
+ m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ m_object = 0;
+
+ m_progress = 0.0f;
+ m_speed = 0.0f;
+ m_lightRank = -1;
+ m_soundChannel = -1;
+ LightOperFlush();
+}
+
+// Object's destructor.
+
+CPyro::~CPyro()
+{
+ m_iMan->DeleteInstance(CLASS_PYRO, this);
+}
+
+
+// Destroys the object.
+
+void CPyro::DeleteObject(bool bAll)
+{
+ if ( m_lightRank != -1 )
+ {
+ m_light->DeleteLight(m_lightRank);
+ m_lightRank = -1;
+ }
+}
+
+
+// Creates pyrotechnic effect.
+
+bool CPyro::Create(PyroType type, CObject* pObj, float force)
+{
+ Math::Matrix* mat;
+ CObject* power;
+ CMotion* motion;
+ Math::Vector min, max, pos, speed;
+ Math::Point dim;
+ ObjectType oType;
+ Sound sound;
+ float duration, mass, h, limit;
+ int part, objRank, total, i, channel;
+
+ m_object = pObj;
+ m_force = force;
+
+ oType = pObj->RetType();
+ objRank = pObj->RetObjectRank(0);
+ if ( objRank == -1 ) return false;
+ m_engine->GetBBox(objRank, min, max);
+ pos = pObj->RetPosition(0);
+
+ DisplayError(type, pObj); // displays eventual messages
+
+ // Copies all spheres of the object.
+ for ( i=0 ; i<50 ; i++ )
+ {
+ if ( !pObj->GetCrashSphere(i, m_crashSpherePos[i], m_crashSphereRadius[i]) ) break;
+ }
+ m_crashSphereUsed = i;
+
+ // Calculates the size of the effect.
+ if ( oType == OBJECT_ANT ||
+ oType == OBJECT_BEE ||
+ oType == OBJECT_WORM ||
+ oType == OBJECT_SPIDER )
+ {
+ m_size = 40.0f;
+ }
+ else
+ {
+ m_size = Math::Distance(min, max)*2.0f;
+ if ( m_size < 4.0f ) m_size = 4.0f;
+ if ( m_size > 80.0f ) m_size = 80.0f;
+ }
+ if ( oType == OBJECT_TNT ||
+ oType == OBJECT_BOMB )
+ {
+ m_size *= 2.0f;
+ }
+
+ m_pos = pos+(min+max)/2.0f;
+ m_type = type;
+ m_progress = 0.0f;
+ m_speed = 1.0f/20.0f;
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+ m_lastParticuleSmoke = 0.0f;
+ m_lightRank = -1;
+
+ if ( oType == OBJECT_TEEN28 ||
+ oType == OBJECT_TEEN31 )
+ {
+ m_pos.y = pos.y+1.0f;
+ }
+
+ // Seeking the position of the battery.
+ power = pObj->RetPower();
+ if ( power == 0 )
+ {
+ m_bPower = false;
+ }
+ else
+ {
+ m_bPower = true;
+ pos = power->RetPosition(0);
+ pos.y += 1.0f;
+ mat = pObj->RetWorldMatrix(0);
+ m_posPower = Math::Transform(*mat, pos);
+ }
+ if ( oType == OBJECT_POWER ||
+ oType == OBJECT_ATOMIC ||
+ oType == OBJECT_URANIUM ||
+ oType == OBJECT_TNT ||
+ oType == OBJECT_BOMB )
+ {
+ m_bPower = true;
+ m_posPower = m_pos;
+ m_posPower.y += 1.0f;
+ m_pos = m_posPower;
+ }
+ if ( oType == OBJECT_STATION )
+ {
+ m_bPower = true;
+ mat = pObj->RetWorldMatrix(0);
+ m_posPower = Math::Transform(*mat, Math::Vector(-15.0f, 7.0f, 0.0f));
+ m_pos = m_posPower;
+ }
+ if ( oType == OBJECT_ENERGY )
+ {
+ m_bPower = true;
+ mat = pObj->RetWorldMatrix(0);
+ m_posPower = Math::Transform(*mat, Math::Vector(-7.0f, 6.0f, 0.0f));
+ m_pos = m_posPower;
+ }
+ if ( oType == OBJECT_NUCLEAR )
+ {
+ m_bPower = true;
+ m_posPower = m_pos;
+ }
+ if ( oType == OBJECT_PARA )
+ {
+ m_bPower = true;
+ m_posPower = m_pos;
+ }
+ if ( oType == OBJECT_SCRAP4 ||
+ oType == OBJECT_SCRAP5 ) // plastic material?
+ {
+ m_bPower = true;
+ m_posPower = m_pos;
+ }
+
+ // Plays the sound of a pyrotechnic effect.
+ if ( type == PT_FRAGT ||
+ type == PT_FRAGW ||
+ type == PT_EXPLOT ||
+ type == PT_EXPLOW )
+ {
+ if ( m_bPower )
+ {
+ sound = SOUND_EXPLOp;
+ }
+ else
+ {
+ sound = SOUND_EXPLO;
+ }
+ if ( oType == OBJECT_STONE ||
+ oType == OBJECT_METAL ||
+ oType == OBJECT_BULLET ||
+ oType == OBJECT_BBOX ||
+ oType == OBJECT_KEYa ||
+ oType == OBJECT_KEYb ||
+ oType == OBJECT_KEYc ||
+ oType == OBJECT_KEYd )
+ {
+ sound = SOUND_EXPLOl;
+ }
+ if ( oType == OBJECT_URANIUM ||
+ oType == OBJECT_POWER ||
+ oType == OBJECT_ATOMIC ||
+ oType == OBJECT_TNT ||
+ oType == OBJECT_BOMB )
+ {
+ sound = SOUND_EXPLOlp;
+ }
+ m_sound->Play(sound, m_pos);
+ }
+ if ( type == PT_FRAGO ||
+ type == PT_EXPLOO ||
+ type == PT_SPIDER ||
+ type == PT_SHOTM )
+ {
+ m_sound->Play(SOUND_EXPLOi, m_pos);
+ }
+ if ( type == PT_BURNT ||
+ type == PT_BURNO )
+ {
+ m_soundChannel = m_sound->Play(SOUND_BURN, m_pos, 1.0f, 1.0f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 12.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 5.0f, SOPER_STOP);
+ }
+ if ( type == PT_BURNO )
+ {
+ m_sound->Play(SOUND_DEADi, m_pos);
+ m_sound->Play(SOUND_DEADi, m_engine->RetEyePt());
+ }
+ if ( type == PT_EGG )
+ {
+ m_sound->Play(SOUND_EGG, m_pos);
+ }
+ if ( type == PT_WPCHECK ||
+ type == PT_FLCREATE ||
+ type == PT_FLDELETE )
+ {
+ m_sound->Play(SOUND_WAYPOINT, m_pos);
+ }
+ if ( oType == OBJECT_HUMAN )
+ {
+ if ( type == PT_DEADG )
+ {
+ m_sound->Play(SOUND_DEADg, m_pos);
+ }
+ if ( type == PT_DEADW )
+ {
+ m_sound->Play(SOUND_DEADw, m_pos);
+ }
+ if ( type == PT_SHOTH && m_object->RetSelect() )
+ {
+ m_sound->Play(SOUND_AIE, m_pos);
+ m_sound->Play(SOUND_AIE, m_engine->RetEyePt());
+ }
+ }
+
+ if ( m_type == PT_FRAGT ||
+ m_type == PT_FRAGO ||
+ m_type == PT_FRAGW )
+ {
+ m_engine->ShadowDelete(m_object->RetObjectRank(0));
+ }
+
+ if ( m_type == PT_DEADG )
+ {
+ m_object->SetDead(true);
+
+ motion = m_object->RetMotion();
+ if ( motion != 0 )
+ {
+ motion->SetAction(MHS_DEADg, 1.0f);
+ }
+ m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 1.5f);
+ m_camera->StartOver(OE_FADEOUTw, m_pos, 1.0f);
+ m_speed = 1.0f/10.0f;
+ return true;
+ }
+ if ( m_type == PT_DEADW )
+ {
+ m_object->SetDead(true);
+
+ motion = m_object->RetMotion();
+ if ( motion != 0 )
+ {
+ motion->SetAction(MHS_DEADw, 4.0f);
+ }
+ m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 3.0f);
+ m_camera->StartOver(OE_FADEOUTb, m_pos, 1.0f);
+ m_speed = 1.0f/10.0f;
+ return true;
+ }
+
+ if ( m_type == PT_SHOTT ||
+ m_type == PT_SHOTM )
+ {
+ m_camera->StartEffect(CE_SHOT, m_pos, force);
+ m_speed = 1.0f/1.0f;
+ return true;
+ }
+ if ( m_type == PT_SHOTH )
+ {
+ if ( m_object->RetSelect() )
+ {
+ m_camera->StartOver(OE_BLOOD, m_pos, force);
+ }
+ m_speed = 1.0f/0.2f;
+ return true;
+ }
+
+ if ( m_type == PT_SHOTW )
+ {
+ m_speed = 1.0f/1.0f;
+ }
+
+ if ( m_type == PT_BURNT )
+ {
+ BurnStart();
+ }
+
+ if ( m_type == PT_WPCHECK )
+ {
+ m_speed = 1.0f/8.0f;
+ m_object->SetEnable(false); // object more functional
+ }
+ if ( m_type == PT_FLCREATE )
+ {
+ m_speed = 1.0f/2.0f;
+ }
+ if ( m_type == PT_FLDELETE )
+ {
+ m_speed = 1.0f/2.0f;
+ m_object->SetEnable(false); // object more functional
+ }
+ if ( m_type == PT_RESET )
+ {
+ m_speed = 1.0f/2.0f;
+ m_object->SetPosition(0, m_object->RetResetPosition());
+ m_object->SetAngle(0, m_object->RetResetAngle());
+ m_object->SetZoom(0, 0.0f);
+ }
+ if ( m_type == PT_FINDING )
+ {
+ limit = (m_size-1.0f)/4.0f;
+ if ( limit > 8.0f ) limit = 8.0f;
+ if ( oType == OBJECT_APOLLO2 ) limit = 2.0f;
+ m_speed = 1.0f/limit;
+ }
+
+ if ( m_type == PT_EXPLOT ||
+ m_type == PT_EXPLOO ||
+ m_type == PT_EXPLOW )
+ {
+ CreateTriangle(pObj, oType, 0);
+ m_engine->ShadowDelete(m_object->RetObjectRank(0));
+ ExploStart();
+ }
+
+ if ( m_type == PT_FALL )
+ {
+ FallStart();
+ return true;
+ }
+
+ if ( m_type == PT_BURNT ||
+ m_type == PT_BURNO )
+ {
+ m_speed = 1.0f/15.0f;
+
+ LightOperAdd(0.00f, 0.0f, 2.0f, 1.0f, 0.0f); // red-orange
+ LightOperAdd(0.30f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ LightOperAdd(0.80f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ LightOperAdd(1.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ CreateLight(m_pos, 40.0f);
+ return true;
+ }
+
+ if ( m_type == PT_SPIDER )
+ {
+ m_speed = 1.0f/15.0f;
+
+ pos = Math::Vector(-3.0f, 2.0f, 0.0f);
+ mat = pObj->RetWorldMatrix(0);
+ m_pos = Math::Transform(*mat, pos);
+
+ m_engine->ShadowDelete(m_object->RetObjectRank(0));
+ }
+
+ if ( m_type != PT_EGG &&
+ m_type != PT_WIN &&
+ m_type != PT_LOST )
+ {
+ h = 40.0f;
+ if ( m_type == PT_FRAGO ||
+ m_type == PT_EXPLOO )
+ {
+ LightOperAdd(0.00f, 0.0f, -1.0f, -0.5f, -1.0f); // dark green
+ LightOperAdd(0.05f, 1.0f, -1.0f, -0.5f, -1.0f); // dark green
+ LightOperAdd(1.00f, 0.0f, -1.0f, -0.5f, -1.0f); // dark green
+ }
+ else if ( m_type == PT_FRAGT ||
+ m_type == PT_EXPLOT )
+ {
+ LightOperAdd(0.00f, 1.0f, 4.0f, 4.0f, 2.0f); // yellow
+ LightOperAdd(0.02f, 1.0f, 4.0f, 2.0f, 0.0f); // red-orange
+ LightOperAdd(0.16f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ LightOperAdd(1.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ h = m_size*2.0f;
+ }
+ else if ( m_type == PT_SPIDER )
+ {
+ LightOperAdd(0.00f, 0.0f, -0.5f, -1.0f, -1.0f); // dark red
+ LightOperAdd(0.05f, 1.0f, -0.5f, -1.0f, -1.0f); // dark red
+ LightOperAdd(1.00f, 0.0f, -0.5f, -1.0f, -1.0f); // dark red
+ }
+ else if ( m_type == PT_FRAGW ||
+ m_type == PT_EXPLOW ||
+ m_type == PT_SHOTW )
+ {
+ LightOperAdd(0.00f, 0.0f, -0.5f, -0.5f, -1.0f); // dark yellow
+ LightOperAdd(0.05f, 1.0f, -0.5f, -0.5f, -1.0f); // dark yellow
+ LightOperAdd(1.00f, 0.0f, -0.5f, -0.5f, -1.0f); // dark yellow
+ }
+ else if ( m_type == PT_WPCHECK ||
+ m_type == PT_FLCREATE ||
+ m_type == PT_FLDELETE ||
+ m_type == PT_RESET ||
+ m_type == PT_FINDING )
+ {
+ LightOperAdd(0.00f, 1.0f, 4.0f, 4.0f, 2.0f); // yellow
+ LightOperAdd(1.00f, 0.0f, 4.0f, 4.0f, 2.0f); // yellow
+ }
+ else
+ {
+ LightOperAdd(0.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ LightOperAdd(0.05f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ LightOperAdd(1.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ }
+ CreateLight(m_pos, h);
+
+ if ( m_type != PT_SHOTW &&
+ m_type != PT_WPCHECK &&
+ m_type != PT_FLCREATE &&
+ m_type != PT_FLDELETE &&
+ m_type != PT_RESET &&
+ m_type != PT_FINDING )
+ {
+ m_camera->StartEffect(CE_EXPLO, m_pos, force);
+ }
+ }
+
+ if ( m_type == PT_SHOTW ) return true;
+
+ // Generates the triangles of the explosion.
+ if ( m_type == PT_FRAGT ||
+ m_type == PT_FRAGO ||
+ m_type == PT_FRAGW ||
+ m_type == PT_SPIDER ||
+ m_type == PT_EGG ||
+ (m_type == PT_EXPLOT && oType == OBJECT_MOBILEtg) ||
+ (m_type == PT_EXPLOT && oType == OBJECT_TEEN28 ) ||
+ (m_type == PT_EXPLOT && oType == OBJECT_TEEN31 ) )
+ {
+ for ( part=0 ; part<OBJECTMAXPART ; part++ )
+ {
+ CreateTriangle(pObj, oType, part);
+ }
+ }
+
+ if ( m_type == PT_FRAGT ||
+ m_type == PT_EXPLOT )
+ {
+ if ( m_bPower )
+ {
+ total = (int)(10.0f*m_engine->RetParticuleDensity());
+ if ( oType == OBJECT_TNT ||
+ oType == OBJECT_BOMB ) total *= 3;
+ for ( i=0 ; i<total ; i++ )
+ {
+ pos = m_posPower;
+ speed.x = (Math::Rand()-0.5f)*30.0f;
+ speed.z = (Math::Rand()-0.5f)*30.0f;
+ speed.y = Math::Rand()*30.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*3.0f+2.0f;
+ mass = Math::Rand()*10.0f+15.0f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK1,
+ duration, mass, Math::Rand()+0.7f, 1.0f);
+ }
+ }
+
+ if ( m_size > 10.0f ) // large enough (freight excluded)?
+ {
+ if ( m_bPower )
+ {
+ pos = m_posPower;
+ }
+ else
+ {
+ pos = m_pos;
+ m_terrain->MoveOnFloor(pos);
+ pos.y += 1.0f;
+ }
+ dim.x = m_size*0.4f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, Math::Vector(0.0f,0.0f,0.0f), dim, PARTISPHERE0, 2.0f, 0.0f, 0.0f);
+ }
+ }
+
+ if ( m_type == PT_FRAGO ||
+ m_type == PT_EXPLOO )
+ {
+ total = (int)(10.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<total ; i++ )
+ {
+ pos = m_pos;
+ speed.x = (Math::Rand()-0.5f)*30.0f;
+ speed.z = (Math::Rand()-0.5f)*30.0f;
+ speed.y = Math::Rand()*50.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*1.0f+0.8f;
+ mass = Math::Rand()*10.0f+15.0f;
+ m_particule->CreateParticule(pos, speed, dim, PARTIORGANIC1,
+ duration, mass);
+ }
+ total = (int)(5.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<total ; i++ )
+ {
+ pos = m_pos;
+ speed.x = (Math::Rand()-0.5f)*30.0f;
+ speed.z = (Math::Rand()-0.5f)*30.0f;
+ speed.y = Math::Rand()*50.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*2.0f+1.4f;
+ mass = Math::Rand()*10.0f+15.0f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK4,
+ duration, mass, duration*0.5f, dim.x*2.0f);
+ }
+ }
+
+ if ( m_type == PT_SPIDER )
+ {
+ for ( i=0 ; i<50 ; i++ )
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*3.0f;
+ pos.z += (Math::Rand()-0.5f)*3.0f;
+ pos.y += (Math::Rand()-0.5f)*2.0f;
+ speed.x = (Math::Rand()-0.5f)*24.0f;
+ speed.z = (Math::Rand()-0.5f)*24.0f;
+ speed.y = 10.0f+Math::Rand()*10.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN3, 2.0f+Math::Rand()*2.0f, 10.0f);
+ m_particule->SetObjectFather(channel, pObj);
+ }
+ total = (int)(10.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<total ; i++ )
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*3.0f;
+ pos.z += (Math::Rand()-0.5f)*3.0f;
+ pos.y += (Math::Rand()-0.5f)*2.0f;
+ speed.x = (Math::Rand()-0.5f)*24.0f;
+ speed.z = (Math::Rand()-0.5f)*24.0f;
+ speed.y = 7.0f+Math::Rand()*7.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK3,
+ 2.0f+Math::Rand()*2.0f, 10.0f, 2.0f, 0.6f);
+ }
+ }
+
+ if ( type == PT_FRAGT ||
+ type == PT_FRAGW ||
+ type == PT_EXPLOT ||
+ type == PT_EXPLOW )
+ {
+ if ( m_size > 10.0f || m_bPower )
+ {
+ pos = m_pos;
+//? m_terrain->MoveOnFloor(pos);
+//? pos.y += 2.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = m_size;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICHOC, 2.0f);
+ }
+ }
+
+ return true;
+}
+
+// Creates an explosion with triangular form of particles.
+
+void CPyro::CreateTriangle(CObject* pObj, ObjectType oType, int part)
+{
+ D3DTriangle buffer[100];
+ Math::Matrix* mat;
+ Math::Vector offset, pos, speed;
+ float percent, min, max, h, duration, mass;
+ int objRank, total, i;
+
+ objRank = pObj->RetObjectRank(part);
+ if ( objRank == -1 ) return;
+
+ min = 0.0f;
+ max = m_engine->RetLimitLOD(0);
+ total = m_engine->RetTotalTriangles(objRank);
+ percent = 0.10f;
+ if ( total < 50 ) percent = 0.25f;
+ if ( total < 20 ) percent = 0.50f;
+ if ( m_type == PT_EGG ) percent = 0.30f;
+ if ( oType == OBJECT_POWER ||
+ oType == OBJECT_ATOMIC ||
+ oType == OBJECT_URANIUM ||
+ oType == OBJECT_TNT ||
+ oType == OBJECT_BOMB ) percent = 0.75f;
+ if ( oType == OBJECT_MOBILEtg ) percent = 0.50f;
+ if ( oType == OBJECT_TEEN28 ) percent = 0.75f;
+ if ( oType == OBJECT_MOTHER ) max = 1000000.0f;
+ if ( oType == OBJECT_TEEN28 ) max = 1000000.0f;
+ if ( oType == OBJECT_TEEN31 ) max = 1000000.0f;
+ total = m_engine->GetTriangles(objRank, min, max, buffer, 100, percent);
+
+ for ( i=0 ; i<total ; i++ )
+ {
+ Math::Vector p1, p2, p3;
+
+ p1.x = buffer[i].triangle[0].x;
+ p1.y = buffer[i].triangle[0].y;
+ p1.z = buffer[i].triangle[0].z;
+ p2.x = buffer[i].triangle[1].x;
+ p2.y = buffer[i].triangle[1].y;
+ p2.z = buffer[i].triangle[1].z;
+ p3.x = buffer[i].triangle[2].x;
+ p3.y = buffer[i].triangle[2].y;
+ p3.z = buffer[i].triangle[2].z;
+
+ h = Math::Distance(p1, p2);
+ if ( h > 5.0f )
+ {
+ p2.x = p1.x+((p2.x-p1.x)*5.0f/h);
+ p2.y = p1.y+((p2.y-p1.y)*5.0f/h);
+ p2.z = p1.z+((p2.z-p1.z)*5.0f/h);
+ }
+
+ h = Math::Distance(p2, p3);
+ if ( h > 5.0f )
+ {
+ p3.x = p2.x+((p3.x-p2.x)*5.0f/h);
+ p3.y = p2.y+((p3.y-p2.y)*5.0f/h);
+ p3.z = p2.z+((p3.z-p2.z)*5.0f/h);
+ }
+
+ h = Math::Distance(p3, p1);
+ if ( h > 5.0f )
+ {
+ p1.x = p3.x+((p1.x-p3.x)*5.0f/h);
+ p1.y = p3.y+((p1.y-p3.y)*5.0f/h);
+ p1.z = p3.z+((p1.z-p3.z)*5.0f/h);
+ }
+
+ buffer[i].triangle[0].x = p1.x;
+ buffer[i].triangle[0].y = p1.y;
+ buffer[i].triangle[0].z = p1.z;
+ buffer[i].triangle[1].x = p2.x;
+ buffer[i].triangle[1].y = p2.y;
+ buffer[i].triangle[1].z = p2.z;
+ buffer[i].triangle[2].x = p3.x;
+ buffer[i].triangle[2].y = p3.y;
+ buffer[i].triangle[2].z = p3.z;
+
+ offset.x = (buffer[i].triangle[0].x+buffer[i].triangle[1].x+buffer[i].triangle[2].x)/3.0f;
+ offset.y = (buffer[i].triangle[0].y+buffer[i].triangle[1].y+buffer[i].triangle[2].y)/3.0f;
+ offset.z = (buffer[i].triangle[0].z+buffer[i].triangle[1].z+buffer[i].triangle[2].z)/3.0f;
+
+ buffer[i].triangle[0].x -= offset.x;
+ buffer[i].triangle[1].x -= offset.x;
+ buffer[i].triangle[2].x -= offset.x;
+
+ buffer[i].triangle[0].y -= offset.y;
+ buffer[i].triangle[1].y -= offset.y;
+ buffer[i].triangle[2].y -= offset.y;
+
+ buffer[i].triangle[0].z -= offset.z;
+ buffer[i].triangle[1].z -= offset.z;
+ buffer[i].triangle[2].z -= offset.z;
+
+ mat = pObj->RetWorldMatrix(part);
+ pos = Math::Transform(*mat, offset);
+ if ( m_type == PT_EGG )
+ {
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = Math::Rand()*15.0f;
+ mass = Math::Rand()*20.0f+20.0f;
+ }
+ else if ( m_type == PT_SPIDER )
+ {
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = Math::Rand()*20.0f;
+ mass = Math::Rand()*10.0f+15.0f;
+ }
+ else
+ {
+ speed.x = (Math::Rand()-0.5f)*30.0f;
+ speed.z = (Math::Rand()-0.5f)*30.0f;
+ speed.y = Math::Rand()*30.0f;
+ mass = Math::Rand()*10.0f+15.0f;
+ }
+ if ( oType == OBJECT_STONE ) speed *= 0.5f;
+ if ( oType == OBJECT_URANIUM ) speed *= 0.4f;
+ duration = Math::Rand()*3.0f+3.0f;
+ m_particule->CreateFrag(pos, speed, &buffer[i], PARTIFRAG,
+ duration, mass, 0.5f);
+ }
+}
+
+// Displays the error or eventual information,
+// linked to the destruction of an insect, a vehicle or building.
+
+void CPyro::DisplayError(PyroType type, CObject* pObj)
+{
+ ObjectType oType;
+ Error err;
+
+ oType = pObj->RetType();
+
+ if ( type == PT_FRAGT ||
+ type == PT_FRAGO ||
+ type == PT_FRAGW ||
+ type == PT_EXPLOT ||
+ type == PT_EXPLOO ||
+ type == PT_EXPLOW ||
+ type == PT_BURNT ||
+ type == PT_BURNO )
+ {
+ err = ERR_OK;
+ if ( oType == OBJECT_MOTHER ) err = INFO_DELETEMOTHER;
+ if ( oType == OBJECT_ANT ) err = INFO_DELETEANT;
+ if ( oType == OBJECT_BEE ) err = INFO_DELETEBEE;
+ if ( oType == OBJECT_WORM ) err = INFO_DELETEWORM;
+ if ( oType == OBJECT_SPIDER ) err = INFO_DELETESPIDER;
+
+ if ( oType == OBJECT_MOBILEwa ||
+ oType == OBJECT_MOBILEta ||
+ oType == OBJECT_MOBILEfa ||
+ oType == OBJECT_MOBILEia ||
+ oType == OBJECT_MOBILEwc ||
+ oType == OBJECT_MOBILEtc ||
+ oType == OBJECT_MOBILEfc ||
+ oType == OBJECT_MOBILEic ||
+ oType == OBJECT_MOBILEwi ||
+ oType == OBJECT_MOBILEti ||
+ oType == OBJECT_MOBILEfi ||
+ oType == OBJECT_MOBILEii ||
+ oType == OBJECT_MOBILEws ||
+ oType == OBJECT_MOBILEts ||
+ oType == OBJECT_MOBILEfs ||
+ oType == OBJECT_MOBILEis ||
+ oType == OBJECT_MOBILErt ||
+ oType == OBJECT_MOBILErc ||
+ oType == OBJECT_MOBILErr ||
+ oType == OBJECT_MOBILErs ||
+ oType == OBJECT_MOBILEsa ||
+ oType == OBJECT_MOBILEwt ||
+ oType == OBJECT_MOBILEtt ||
+ oType == OBJECT_MOBILEft ||
+ oType == OBJECT_MOBILEit ||
+ oType == OBJECT_MOBILEdr )
+ {
+ err = ERR_DELETEMOBILE;
+ }
+
+ if ( oType == OBJECT_DERRICK ||
+ oType == OBJECT_FACTORY ||
+ oType == OBJECT_STATION ||
+ oType == OBJECT_CONVERT ||
+ oType == OBJECT_REPAIR ||
+ oType == OBJECT_DESTROYER||
+ oType == OBJECT_TOWER ||
+ oType == OBJECT_RESEARCH ||
+ oType == OBJECT_RADAR ||
+ oType == OBJECT_INFO ||
+ oType == OBJECT_ENERGY ||
+ oType == OBJECT_LABO ||
+ oType == OBJECT_NUCLEAR ||
+ oType == OBJECT_PARA ||
+ oType == OBJECT_SAFE ||
+ oType == OBJECT_HUSTON ||
+ oType == OBJECT_START ||
+ oType == OBJECT_END )
+ {
+ err = ERR_DELETEBUILDING;
+ m_displayText->DisplayError(err, pObj->RetPosition(0), 5.0f);
+ return;
+ }
+
+ if ( err != ERR_OK )
+ {
+ m_displayText->DisplayError(err, pObj);
+ }
+ }
+}
+
+
+// Management of an event.
+
+bool CPyro::EventProcess(const Event &event)
+{
+ ParticuleType type;
+ Math::Vector pos, speed, angle;
+ Math::Point dim;
+ float prog, factor, duration;
+ int i, r;
+
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_engine->RetPause() ) return true;
+
+ m_time += event.rTime;
+ m_progress += event.rTime*m_speed;
+
+ if ( m_soundChannel != -1 && m_object != 0 )
+ {
+ pos = m_object->RetPosition(0);
+ m_sound->Position(m_soundChannel, pos);
+
+ if ( m_lightRank != -1 )
+ {
+ pos.y += m_lightHeight;
+ m_light->SetLightPos(m_lightRank, pos);
+ }
+ }
+
+ if ( m_type == PT_SHOTT &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ if ( m_crashSphereUsed > 0 )
+ {
+ i = rand()%m_crashSphereUsed;
+ pos = m_crashSpherePos[i];
+ pos.x += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
+ pos.z += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
+ speed.x = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
+ speed.z = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
+ speed.y = Math::Rand()*m_crashSphereRadius[i]*1.0f;
+ dim.x = Math::Rand()*m_crashSphereRadius[i]*0.5f+m_crashSphereRadius[i]*0.75f*m_force;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
+ }
+ else
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*m_size*0.3f;
+ pos.z += (Math::Rand()-0.5f)*m_size*0.3f;
+ speed.x = (Math::Rand()-0.5f)*m_size*0.1f;
+ speed.z = (Math::Rand()-0.5f)*m_size*0.1f;
+ speed.y = Math::Rand()*m_size*0.2f;
+ dim.x = Math::Rand()*m_size/10.0f+m_size/10.0f*m_force;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
+ }
+ }
+
+ if ( m_type == PT_SHOTH &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*m_size*0.2f;
+ pos.z += (Math::Rand()-0.5f)*m_size*0.2f;
+ pos.y += (Math::Rand()-0.5f)*m_size*0.5f;
+ speed.x = (Math::Rand()-0.5f)*5.0f;
+ speed.z = (Math::Rand()-0.5f)*5.0f;
+ speed.y = Math::Rand()*1.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLOOD, Math::Rand()*3.0f+3.0f, Math::Rand()*10.0f+15.0f, 0.5f);
+ }
+ }
+
+ if ( m_type == PT_SHOTM &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ r = (int)(10.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<r ; i++ )
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*20.0f;
+ pos.z += (Math::Rand()-0.5f)*20.0f;
+ pos.y += 8.0f;
+ speed.x = (Math::Rand()-0.5f)*40.0f;
+ speed.z = (Math::Rand()-0.5f)*40.0f;
+ speed.y = Math::Rand()*40.0f;
+ dim.x = Math::Rand()*8.0f+8.0f*m_force;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLOODM, 2.0f, 50.0f, 0.0f);
+ }
+ }
+
+ if ( m_type == PT_SHOTW &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ if ( m_crashSphereUsed > 0 )
+ {
+ i = rand()%m_crashSphereUsed;
+ pos = m_crashSpherePos[i];
+ pos.x += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
+ pos.z += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
+ speed.x = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
+ speed.z = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
+ speed.y = Math::Rand()*m_crashSphereRadius[i]*1.0f;
+ dim.x = 1.0f*m_force;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
+ }
+ else
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*m_size*0.3f;
+ pos.z += (Math::Rand()-0.5f)*m_size*0.3f;
+ speed.x = (Math::Rand()-0.5f)*m_size*0.1f;
+ speed.z = (Math::Rand()-0.5f)*m_size*0.1f;
+ speed.y = Math::Rand()*m_size*0.2f;
+ dim.x = 1.0f*m_force;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
+ }
+ }
+
+ if ( m_type == PT_SHOTW &&
+ m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticuleSmoke = m_time;
+
+ pos = m_pos;
+ pos.y -= 2.0f;
+ pos.x += (Math::Rand()-0.5f)*4.0f;
+ pos.z += (Math::Rand()-0.5f)*4.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 10.0f+Math::Rand()*10.0f;
+ dim.x = Math::Rand()*2.5f+2.0f*m_force;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 4.0f);
+ }
+
+ if ( (m_type == PT_FRAGT || m_type == PT_EXPLOT) &&
+ m_progress < 0.05f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_pos;
+ speed.x = (Math::Rand()-0.5f)*m_size*1.0f;
+ speed.z = (Math::Rand()-0.5f)*m_size*1.0f;
+ speed.y = Math::Rand()*m_size*0.50f;
+ dim.x = Math::Rand()*m_size/5.0f+m_size/5.0f;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTIEXPLOT);
+ }
+
+ if ( (m_type == PT_FRAGT || m_type == PT_EXPLOT) &&
+ m_progress < 0.10f &&
+ m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticuleSmoke = m_time;
+
+ dim.x = Math::Rand()*m_size/3.0f+m_size/3.0f;
+ dim.y = dim.x;
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*m_size*0.5f;
+ pos.z += (Math::Rand()-0.5f)*m_size*0.5f;
+ m_terrain->MoveOnFloor(pos);
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = -dim.x/2.0f/4.0f;
+ pos.y += dim.x/2.0f;
+
+ r = rand()%2;
+ if ( r == 0 ) type = PARTISMOKE1;
+ if ( r == 1 ) type = PARTISMOKE2;
+ m_particule->CreateParticule(pos, speed, dim, type, 6.0f);
+ }
+
+ if ( (m_type == PT_FRAGO || m_type == PT_EXPLOO) &&
+ m_progress < 0.03f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_pos;
+ speed.x = (Math::Rand()-0.5f)*m_size*2.0f;
+ speed.z = (Math::Rand()-0.5f)*m_size*2.0f;
+ speed.y = Math::Rand()*m_size*1.0f;
+ dim.x = Math::Rand()*m_size/2.0f+m_size/2.0f;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTIEXPLOO);
+ }
+
+ if ( (m_type == PT_FRAGW || m_type == PT_EXPLOW) &&
+ m_progress < 0.05f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_pos;
+ speed.x = (Math::Rand()-0.5f)*m_size*1.0f;
+ speed.z = (Math::Rand()-0.5f)*m_size*1.0f;
+ speed.y = Math::Rand()*m_size*0.50f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
+ }
+
+ if ( (m_type == PT_FRAGW || m_type == PT_EXPLOW) &&
+ m_progress < 0.25f &&
+ m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticuleSmoke = m_time;
+
+ pos = m_pos;
+ pos.y -= 2.0f;
+ pos.x += (Math::Rand()-0.5f)*4.0f;
+ pos.z += (Math::Rand()-0.5f)*4.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 4.0f+Math::Rand()*4.0f;
+ dim.x = Math::Rand()*2.5f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 4.0f);
+ }
+
+ if ( m_type == PT_WPCHECK )
+ {
+ if ( m_progress < 0.25f )
+ {
+ factor = 0.0f;
+ }
+ else
+ {
+ factor = powf((m_progress-0.25f)/0.75f, 2.0f)*30.0f;
+ }
+
+ if ( m_progress < 0.85f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_pos;
+ pos.y += factor;
+ pos.x += (Math::Rand()-0.5f)*3.0f;
+ pos.z += (Math::Rand()-0.5f)*3.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 5.0f+Math::Rand()*5.0f;
+ dim.x = Math::Rand()*1.5f+1.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f);
+//? m_particule->CreateParticule(pos, speed, dim, (ParticuleType)(PARTILENS1+rand()%4), 2.0f);
+ }
+
+ angle = m_object->RetAngle(0);
+ angle.y = m_progress*20.0f;
+ angle.x = sinf(m_progress*49.0f)*0.3f;
+ angle.z = sinf(m_progress*47.0f)*0.2f;
+ m_object->SetAngle(0, angle);
+
+ pos = m_pos;
+ pos.y += factor;
+ m_object->SetPosition(0, pos);
+
+ if ( m_progress > 0.85f )
+ {
+ m_object->SetZoom(0, 1.0f-(m_progress-0.85f)/0.15f);
+ }
+ }
+
+ if ( m_type == PT_FLCREATE )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_pos;
+ m_terrain->MoveOnFloor(pos);
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = 2.0f+Math::Rand()*2.0f;
+ dim.x = (Math::Rand()*1.0f+1.0f)*(0.2f+m_progress*0.8f);
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
+ }
+
+ angle = m_object->RetAngle(0);
+//? angle.y = powf(m_progress, 0.2f)*20.0f;
+ angle.x = sinf(m_progress*49.0f)*0.3f*(1.0f-m_progress);
+ angle.z = sinf(m_progress*47.0f)*0.2f*(1.0f-m_progress);
+ m_object->SetAngle(0, angle);
+
+ m_object->SetZoom(0, m_progress);
+ }
+
+ if ( m_type == PT_FLDELETE )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_pos;
+ m_terrain->MoveOnFloor(pos);
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = 2.0f+Math::Rand()*2.0f;
+ dim.x = (Math::Rand()*1.0f+1.0f)*(0.2f+m_progress*0.8f);
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.5f);
+ }
+
+ angle = m_object->RetAngle(0);
+ angle.y = m_progress*20.0f;
+ angle.x = sinf(m_progress*49.0f)*0.3f;
+ angle.z = sinf(m_progress*47.0f)*0.2f;
+ m_object->SetAngle(0, angle);
+
+ m_object->SetZoom(0, 1.0f-m_progress);
+ }
+
+ if ( m_type == PT_RESET )
+ {
+#if 0
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_pos;
+ speed.x = (Math::Rand()-0.5f)*6.0f;
+ speed.z = (Math::Rand()-0.5f)*6.0f;
+ speed.y = Math::Rand()*12.0f;
+ dim.x = (Math::Rand()*2.5f+2.5f)*(1.0f-m_progress*0.9f);
+ dim.y = dim.x;
+ pos.y += dim.y;
+ m_particule->CreateParticule(pos, speed, dim,
+ (ParticuleType)(PARTILENS1+rand()%4),
+ Math::Rand()*2.5f+2.5f,
+ Math::Rand()*5.0f+5.0f, 0.0f);
+ }
+#else
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 5.0f+Math::Rand()*5.0f;
+ dim.x = Math::Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
+
+ pos = m_pos;
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ speed.y = Math::Rand()*10.0f;
+ speed *= 0.5f+m_progress*0.5f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ pos.y += dim.y;
+ duration = Math::Rand()*1.5f+1.5f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
+ duration, 0.0f,
+ duration*0.9f, 0.7f);
+ }
+#endif
+
+ angle = m_object->RetResetAngle();
+ m_object->SetAngleY(0, angle.y-powf((1.0f-m_progress)*5.0f, 2.0f));
+ m_object->SetZoom(0, m_progress);
+ }
+
+ if ( m_type == PT_FINDING )
+ {
+ if ( m_object != 0 &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ factor = m_size*0.3f;
+ if ( m_object->RetType() == OBJECT_SAFE ) factor *= 1.3f;
+ if ( factor > 40.0f ) factor = 40.0f;
+ pos = m_pos;
+ m_terrain->MoveOnFloor(pos);
+ pos.x += (Math::Rand()-0.5f)*factor;
+ pos.z += (Math::Rand()-0.5f)*factor;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = 4.0f+Math::Rand()*4.0f;
+ dim.x = (Math::Rand()*3.0f+3.0f)*(1.0f-m_progress*0.9f);
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.5f);
+ }
+ }
+
+ if ( (m_type == PT_BURNT || m_type == PT_BURNO) &&
+ m_object != 0 )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ factor = m_size/25.0f; // 1 = standard size
+
+ pos = m_object->RetPosition(0);
+ pos.y -= m_object->RetCharacter()->height;
+ pos.x += (Math::Rand()-0.5f)*(4.0f+8.0f*m_progress)*factor;
+ pos.z += (Math::Rand()-0.5f)*(4.0f+8.0f*m_progress)*factor;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 0.0f;
+ dim.x = (Math::Rand()*2.5f+1.0f)*factor;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f);
+
+ pos = m_object->RetPosition(0);
+ pos.y -= m_object->RetCharacter()->height;
+ pos.x += (Math::Rand()-0.5f)*(2.0f+4.0f*m_progress)*factor;
+ pos.z += (Math::Rand()-0.5f)*(2.0f+4.0f*m_progress)*factor;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = (Math::Rand()*5.0f*m_progress+3.0f)*factor;
+ dim.x = (Math::Rand()*2.0f+1.0f)*factor;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f);
+
+ pos = m_object->RetPosition(0);
+ pos.y -= 2.0f;
+ pos.x += (Math::Rand()-0.5f)*5.0f*factor;
+ pos.z += (Math::Rand()-0.5f)*5.0f*factor;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = (6.0f+Math::Rand()*6.0f+m_progress*6.0f)*factor;
+ dim.x = (Math::Rand()*1.5f+1.0f+m_progress*3.0f)*factor;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
+ }
+
+ if ( m_type == PT_BURNT )
+ {
+ BurnProgress();
+ }
+ else
+ {
+ speed.y = 0.0f;
+ speed.x = (Math::Rand()-0.5f)*m_progress*1.0f;
+ speed.z = (Math::Rand()-0.5f)*m_progress*1.0f;
+ if ( m_progress > 0.8f )
+ {
+ prog = (m_progress-0.8f)/0.2f; // 0..1
+ speed.y = -prog*6.0f; // sinks into the ground
+ m_object->SetZoom(0, 1.0f-prog*0.5f);
+ }
+ m_object->SetLinVibration(speed);
+ }
+ }
+
+ if ( m_type == PT_WIN )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.y += 1.5f;
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = 8.0f+Math::Rand()*8.0f;
+ dim.x = Math::Rand()*0.2f+0.2f;
+ dim.y = dim.x;
+ m_particule->CreateTrack(pos, speed, dim,
+ (ParticuleType)(PARTITRACK7+rand()%4),
+ 3.0f, 20.0f, 1.0f, 0.4f);
+ }
+ }
+
+ if ( m_type == PT_LOST )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.y -= 2.0f;
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 1.0f+Math::Rand()*1.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 8.0f, 0.0f, 0.0f);
+ }
+ }
+
+ if ( m_type == PT_FALL )
+ {
+ FallProgress(event.rTime);
+ }
+
+ if ( m_lightRank != -1 )
+ {
+ LightOperFrame(event.rTime);
+ }
+
+ return true;
+}
+
+// Indicates that the object binds to the effect no longer exists, without deleting it.
+
+void CPyro::CutObjectLink(CObject* pObj)
+{
+ if ( m_object == pObj )
+ {
+ m_object = 0;
+ }
+}
+
+// Indicates whether the pyrotechnic effect is complete.
+
+Error CPyro::IsEnded()
+{
+ // Destroys the object that exploded.
+ //It should not be destroyed at the end of the Create,
+ //because it is sometimes the object itself that makes the Create:
+ // pyro->Create(PT_FRAGT, this);
+ if ( m_type == PT_FRAGT ||
+ m_type == PT_FRAGO ||
+ m_type == PT_FRAGW ||
+ m_type == PT_SPIDER ||
+ m_type == PT_EGG )
+ {
+ DeleteObject(true, true);
+ }
+
+ if ( m_type == PT_FALL ) // freight which grave?
+ {
+ return FallIsEnded();
+ }
+
+ if ( m_type == PT_WIN ||
+ m_type == PT_LOST )
+ {
+ return ERR_CONTINUE;
+ }
+
+ // End of the pyrotechnic effect?
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ if ( m_type == PT_EXPLOT ||
+ m_type == PT_EXPLOO ||
+ m_type == PT_EXPLOW ) // explosion?
+ {
+ ExploTerminate();
+ }
+
+ if ( m_type == PT_BURNT ||
+ m_type == PT_BURNO ) // burning?
+ {
+ BurnTerminate();
+ }
+
+ if ( m_type == PT_WPCHECK ||
+ m_type == PT_FLDELETE )
+ {
+ DeleteObject(true, true);
+ }
+
+ if ( m_type == PT_FLCREATE )
+ {
+ m_object->SetAngleX(0, 0.0f);
+ m_object->SetAngleZ(0, 0.0f);
+ m_object->SetZoom(0, 1.0f);
+ }
+
+ if ( m_type == PT_RESET )
+ {
+ m_object->SetPosition(0, m_object->RetResetPosition());
+ m_object->SetAngle(0, m_object->RetResetAngle());
+ m_object->SetZoom(0, 1.0f);
+ }
+
+ if ( m_lightRank != -1 )
+ {
+ m_light->DeleteLight(m_lightRank);
+ m_lightRank = -1;
+ }
+
+ return ERR_STOP;
+}
+
+// Removes the binding to a pyrotechnic effect.
+
+void CPyro::DeleteObject(bool bPrimary, bool bSecondary)
+{
+ CObject *sub, *truck;
+ Math::Vector pos;
+ ObjectType type;
+
+ if ( m_object == 0 ) return;
+
+ if ( m_object->RetResetCap() == RESET_MOVE ) // resettable object?
+ {
+ m_object->SetEnable(false); // object cache and inactive
+ pos = m_object->RetPosition(0);
+ pos.y = -100.0f;
+ m_object->SetPosition(0, pos);
+ return;
+ }
+
+ type = m_object->RetType();
+ if ( bSecondary &&
+ type != OBJECT_FACTORY &&
+ type != OBJECT_NUCLEAR &&
+ type != OBJECT_ENERGY )
+ {
+ sub = m_object->RetPower();
+ if ( sub != 0 )
+ {
+ sub->DeleteObject(); // removes the battery
+ delete sub;
+ m_object->SetPower(0);
+ }
+
+ sub = m_object->RetFret();
+ if ( sub != 0 )
+ {
+ sub->DeleteObject(); // removes the object transported
+ delete sub;
+ m_object->SetFret(0);
+ }
+ }
+
+ if ( bPrimary )
+ {
+ truck = m_object->RetTruck();
+ if ( truck != 0 ) // object carries?
+ {
+ if ( truck->RetPower() == m_object )
+ {
+ truck->SetPower(0);
+ }
+ if ( truck->RetFret() == m_object )
+ {
+ truck->SetFret(0);
+ }
+ }
+
+ sub = m_object;
+ sub->DeleteObject(); // removes the object (*)
+ delete sub;
+ m_object = 0;
+ }
+}
+
+// (*) CObject :: DeleteObject can reset m_object through CPyro :: CutObjectLink!
+
+
+// Empty the table of operations of animation of light.
+
+void CPyro::LightOperFlush()
+{
+ m_lightOperTotal = 0;
+}
+
+// Adds an animation operation of the light.
+
+void CPyro::LightOperAdd(float progress, float intensity,
+ float r, float g, float b)
+{
+ int i;
+
+ i = m_lightOperTotal;
+
+ m_lightOper[i].progress = progress;
+ m_lightOper[i].intensity = intensity;
+ m_lightOper[i].color.r = r;
+ m_lightOper[i].color.g = g;
+ m_lightOper[i].color.b = b;
+
+ m_lightOperTotal ++;
+}
+
+// Makes evolve the associated light.
+
+void CPyro::LightOperFrame(float rTime)
+{
+ D3DCOLORVALUE color;
+ float progress, intensity;
+ int i;
+
+ for ( i=0 ; i<m_lightOperTotal ; i++ )
+ {
+ if ( m_progress < m_lightOper[i].progress )
+ {
+ progress = (m_progress-m_lightOper[i-1].progress) / (m_lightOper[i].progress-m_lightOper[i-1].progress);
+
+ intensity = m_lightOper[i-1].intensity + (m_lightOper[i].intensity-m_lightOper[i-1].intensity)*progress;
+ color.r = m_lightOper[i-1].color.r + (m_lightOper[i].color.r-m_lightOper[i-1].color.r)*progress;
+ color.g = m_lightOper[i-1].color.g + (m_lightOper[i].color.g-m_lightOper[i-1].color.g)*progress;
+ color.b = m_lightOper[i-1].color.b + (m_lightOper[i].color.b-m_lightOper[i-1].color.b)*progress;
+
+ m_light->SetLightIntensity(m_lightRank, intensity);
+ m_light->SetLightColor(m_lightRank, color);
+ break;
+ }
+ }
+}
+
+
+// Creates light to accompany a pyrotechnic effect.
+
+bool CPyro::CreateLight(Math::Vector pos, float height)
+{
+ D3DLIGHT7 light;
+
+ if ( !m_engine->RetLightMode() ) return true;
+
+ m_lightHeight = height;
+
+ ZeroMemory( &light, sizeof(light) );
+ light.dltType = D3DLIGHT_SPOT;
+ light.dvPosition.x = pos.x;
+ light.dvPosition.y = pos.y+height;
+ light.dvPosition.z = pos.z;
+ light.dvDirection.x = 0.0f;
+ light.dvDirection.y = -1.0f; // against the bottom
+ light.dvDirection.z = 0.0f;
+ light.dvRange = D3DLIGHT_RANGE_MAX;
+ light.dvFalloff = 1.0f;
+ light.dvAttenuation0 = 1.0f;
+ light.dvAttenuation1 = 0.0f;
+ light.dvAttenuation2 = 0.0f;
+ light.dvTheta = 0.0f;
+ light.dvPhi = Math::PI/4.0f;
+
+ m_lightRank = m_light->CreateLight();
+ if ( m_lightRank == -1 ) return false;
+
+ m_light->SetLight(m_lightRank, light);
+ m_light->SetLightIntensity(m_lightRank, 0.0f);
+
+ // Only illuminates the objects on the ground.
+ m_light->SetLightIncluType(m_lightRank, TYPETERRAIN);
+
+ return true;
+}
+
+
+// Starts the explosion of a vehicle.
+
+void CPyro::ExploStart()
+{
+ Math::Vector pos, angle, speed, min, max;
+ float weight;
+ int i, objRank, channel;
+
+ m_burnType = m_object->RetType();
+
+ pos = m_object->RetPosition(0);
+ m_burnFall = m_terrain->RetFloorHeight(pos, true);
+
+ m_object->Simplify();
+ m_object->SetLock(true); // ruin not usable yet
+ m_object->SetExplo(true); // being destroyed
+ m_object->FlatParent();
+
+ if ( m_object->RetSelect() )
+ {
+ m_object->SetSelect(false); // deselects the object
+ m_camera->SetType(CAMERA_EXPLO);
+ m_main->DeselectAll();
+ }
+ m_object->DeleteDeselList(m_object);
+
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ objRank = m_object->RetObjectRank(i);
+ if ( objRank == -1 ) continue;
+ m_engine->ChangeSecondTexture(objRank, "dirty04.tga");
+
+ pos = m_object->RetPosition(i);
+
+ if ( i == 0 ) // main part?
+ {
+ weight = 0.0f;
+
+ speed.y = -1.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ }
+ else
+ {
+ m_engine->GetBBox(objRank, min, max);
+ weight = Math::Distance(min, max); // weight according to size!
+
+ speed.y = 10.0f+Math::Rand()*20.0f;
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ }
+
+ channel = m_particule->CreatePart(pos, speed, PARTIPART, 10.0f, 20.0f, weight, 0.5f);
+ if ( channel != -1 )
+ {
+ m_object->SetMasterParticule(i, channel);
+ }
+ }
+ m_engine->LoadTexture("dirty04.tga", 1);
+
+ DeleteObject(false, true); // destroys the object transported + the battery
+}
+
+// Ends the explosion of a vehicle.
+
+void CPyro::ExploTerminate()
+{
+ DeleteObject(true, false); // removes the main object
+}
+
+
+// Starts a vehicle fire.
+
+void CPyro::BurnStart()
+{
+ Math::Vector pos, angle;
+ int i, objRank;
+
+ m_burnType = m_object->RetType();
+
+ pos = m_object->RetPosition(0);
+ m_burnFall = m_terrain->RetFloorHeight(pos, true);
+
+ m_object->Simplify();
+ m_object->SetLock(true); // ruin not usable yet
+
+ if ( m_object->RetSelect() )
+ {
+ m_object->SetSelect(false); // deselects the object
+ m_camera->SetType(CAMERA_EXPLO);
+ m_main->DeselectAll();
+ }
+ m_object->DeleteDeselList(m_object);
+
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ objRank = m_object->RetObjectRank(i);
+ if ( objRank == -1 ) continue;
+ m_engine->ChangeSecondTexture(objRank, "dirty04.tga");
+ }
+ m_engine->LoadTexture("dirty04.tga", 1);
+
+ m_burnPartTotal = 0;
+
+ if ( m_burnType == OBJECT_DERRICK ||
+ m_burnType == OBJECT_FACTORY ||
+ m_burnType == OBJECT_REPAIR ||
+ m_burnType == OBJECT_DESTROYER||
+ m_burnType == OBJECT_CONVERT ||
+ m_burnType == OBJECT_TOWER ||
+ m_burnType == OBJECT_RESEARCH ||
+ m_burnType == OBJECT_ENERGY ||
+ m_burnType == OBJECT_LABO )
+ {
+ pos.x = 0.0f;
+ pos.y = -(4.0f+Math::Rand()*4.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.4f;
+ }
+ else if ( m_burnType == OBJECT_STATION ||
+ m_burnType == OBJECT_RADAR ||
+ m_burnType == OBJECT_INFO )
+ {
+ pos.x = 0.0f;
+ pos.y = -(1.0f+Math::Rand()*1.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.2f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.2f;
+ }
+ else if ( m_burnType == OBJECT_NUCLEAR )
+ {
+ pos.x = 0.0f;
+ pos.y = -(10.0f+Math::Rand()*10.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.4f;
+ }
+ else if ( m_burnType == OBJECT_PARA )
+ {
+ pos.x = 0.0f;
+ pos.y = -(10.0f+Math::Rand()*10.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.4f;
+ }
+ else if ( m_burnType == OBJECT_SAFE )
+ {
+ pos.x = 0.0f;
+ pos.y = -(10.0f+Math::Rand()*10.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.4f;
+ }
+ else if ( m_burnType == OBJECT_HUSTON )
+ {
+ pos.x = 0.0f;
+ pos.y = -(10.0f+Math::Rand()*10.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.4f;
+ }
+ else if ( m_burnType == OBJECT_MOBILEwa ||
+ m_burnType == OBJECT_MOBILEwc ||
+ m_burnType == OBJECT_MOBILEwi ||
+ m_burnType == OBJECT_MOBILEws ||
+ m_burnType == OBJECT_MOBILEwt )
+ {
+ pos.x = 0.0f;
+ pos.y = -(0.5f+Math::Rand()*1.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.8f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.4f;
+ }
+ else if ( m_burnType == OBJECT_TEEN31 ) // basket?
+ {
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.8f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.2f;
+ }
+ else
+ {
+ pos.x = 0.0f;
+ pos.y = -(2.0f+Math::Rand()*2.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.8f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.8f;
+ }
+ BurnAddPart(0, pos, angle); // movement of the main part
+
+ m_burnKeepPart[0] = -1; // nothing to keep
+
+ if ( m_burnType == OBJECT_DERRICK )
+ {
+ pos.x = 0.0f;
+ pos.y = -40.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the drill
+ }
+
+ if ( m_burnType == OBJECT_REPAIR )
+ {
+ pos.x = 0.0f;
+ pos.y = -12.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.2f;
+ angle.y = (Math::Rand()-0.5f)*0.2f;
+ angle.z = -90.0f*Math::PI/180.0f;
+ BurnAddPart(1, pos, angle); // down the sensor
+ }
+
+ if ( m_burnType == OBJECT_DESTROYER )
+ {
+ pos.x = 0.0f;
+ pos.y = -12.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.2f;
+ angle.y = (Math::Rand()-0.5f)*0.2f;
+ angle.z = -90.0f*Math::PI/180.0f;
+ BurnAddPart(1, pos, angle); // down the sensor
+ }
+
+ if ( m_burnType == OBJECT_CONVERT )
+ {
+ pos.x = 0.0f;
+ pos.y = -200.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.5f;
+ angle.y = (Math::Rand()-0.5f)*0.5f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the cover
+ BurnAddPart(2, pos, angle);
+ BurnAddPart(3, pos, angle);
+ }
+
+ if ( m_burnType == OBJECT_TOWER )
+ {
+ pos.x = 0.0f;
+ pos.y = -7.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = (Math::Rand()-0.5f)*0.4f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the cannon
+ }
+
+ if ( m_burnType == OBJECT_RESEARCH )
+ {
+ pos.x = 0.0f;
+ pos.y = -7.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.2f;
+ angle.y = (Math::Rand()-0.5f)*0.2f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the anemometer
+ }
+
+ if ( m_burnType == OBJECT_RADAR )
+ {
+ pos.x = 0.0f;
+ pos.y = -14.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = (Math::Rand()-0.5f)*0.4f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the radar
+ BurnAddPart(2, pos, angle);
+ }
+
+ if ( m_burnType == OBJECT_INFO )
+ {
+ pos.x = 0.0f;
+ pos.y = -14.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = (Math::Rand()-0.5f)*0.4f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the information terminal
+ BurnAddPart(2, pos, angle);
+ }
+
+ if ( m_burnType == OBJECT_LABO )
+ {
+ pos.x = 0.0f;
+ pos.y = -12.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the arm
+ }
+
+ if ( m_burnType == OBJECT_NUCLEAR )
+ {
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = -135.0f*Math::PI/180.0f;
+ BurnAddPart(1, pos, angle); // down the cover
+ }
+
+ if ( m_burnType == OBJECT_MOBILEfa ||
+ m_burnType == OBJECT_MOBILEta ||
+ m_burnType == OBJECT_MOBILEwa ||
+ m_burnType == OBJECT_MOBILEia )
+ {
+ pos.x = 2.0f;
+ pos.y = -5.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.2f;
+ angle.y = (Math::Rand()-0.5f)*0.2f;
+ angle.z = 40.0f*Math::PI/180.0f;
+ BurnAddPart(1, pos, angle); // down the arm
+ }
+
+ if ( m_burnType == OBJECT_MOBILEfs ||
+ m_burnType == OBJECT_MOBILEts ||
+ m_burnType == OBJECT_MOBILEws ||
+ m_burnType == OBJECT_MOBILEis )
+ {
+ pos.x = 0.0f;
+ pos.y = -7.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.2f;
+ angle.y = (Math::Rand()-0.5f)*0.2f;
+ angle.z = 50.0f*Math::PI/180.0f;
+ BurnAddPart(1, pos, angle); // down the sensor
+ }
+
+ if ( m_burnType == OBJECT_MOBILEfc ||
+ m_burnType == OBJECT_MOBILEtc ||
+ m_burnType == OBJECT_MOBILEwc ||
+ m_burnType == OBJECT_MOBILEic )
+ {
+ pos.x = -1.5f;
+ pos.y = -5.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.2f;
+ angle.y = (Math::Rand()-0.5f)*0.2f;
+ angle.z = -25.0f*Math::PI/180.0f;
+ BurnAddPart(1, pos, angle); // down the cannon
+ }
+
+ if ( m_burnType == OBJECT_MOBILEfi ||
+ m_burnType == OBJECT_MOBILEti ||
+ m_burnType == OBJECT_MOBILEwi ||
+ m_burnType == OBJECT_MOBILEii )
+ {
+ pos.x = -1.5f;
+ pos.y = -5.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.2f;
+ angle.y = (Math::Rand()-0.5f)*0.2f;
+ angle.z = -25.0f*Math::PI/180.0f;
+ BurnAddPart(1, pos, angle); // down the insect-cannon
+ }
+
+ if ( m_burnType == OBJECT_MOBILErt ||
+ m_burnType == OBJECT_MOBILErc )
+ {
+ pos.x = 0.0f;
+ pos.y = -10.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the holder
+
+ pos.x = 0.0f;
+ pos.y = -10.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(2, pos, angle); // down the pestle/cannon
+ }
+
+ if ( m_burnType == OBJECT_MOBILErr )
+ {
+ pos.x = 0.0f;
+ pos.y = -10.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the holder
+
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = -Math::PI/2.0f;
+ BurnAddPart(4, pos, angle);
+
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = Math::PI/2.5f;
+ BurnAddPart(2, pos, angle);
+ }
+
+ if ( m_burnType == OBJECT_MOBILErs )
+ {
+ pos.x = 0.0f;
+ pos.y = -10.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the holder
+
+ pos.x = 0.0f;
+ pos.y = -5.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(2, pos, angle);
+
+ pos.x = 0.0f;
+ pos.y = -5.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(3, pos, angle);
+ }
+
+ if ( m_burnType == OBJECT_MOBILEsa )
+ {
+ pos.x = 0.0f;
+ pos.y = -10.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the holder
+ }
+
+ if ( m_burnType == OBJECT_MOBILEwa ||
+ m_burnType == OBJECT_MOBILEwc ||
+ m_burnType == OBJECT_MOBILEwi ||
+ m_burnType == OBJECT_MOBILEws ||
+ m_burnType == OBJECT_MOBILEwt ) // wheels?
+ {
+ for ( i=0 ; i<4 ; i++ )
+ {
+ pos.x = 0.0f;
+ pos.y = Math::Rand()*0.5f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*Math::PI/2.0f;
+ angle.y = (Math::Rand()-0.5f)*Math::PI/2.0f;
+ angle.z = 0.0f;
+ BurnAddPart(6+i, pos, angle); // wheel
+
+ m_burnKeepPart[i] = 6+i; // we keep the wheels
+ }
+ m_burnKeepPart[i] = -1;
+ }
+
+ if ( m_burnType == OBJECT_MOBILEta ||
+ m_burnType == OBJECT_MOBILEtc ||
+ m_burnType == OBJECT_MOBILEti ||
+ m_burnType == OBJECT_MOBILEts ||
+ m_burnType == OBJECT_MOBILErt ||
+ m_burnType == OBJECT_MOBILErc ||
+ m_burnType == OBJECT_MOBILErr ||
+ m_burnType == OBJECT_MOBILErs ||
+ m_burnType == OBJECT_MOBILEsa ||
+ m_burnType == OBJECT_MOBILEdr ) // caterpillars?
+ {
+ pos.x = 0.0f;
+ pos.y = -4.0f;
+ pos.z = 2.0f;
+ angle.x = (Math::Rand()-0.5f)*20.0f*Math::PI/180.0f;
+ angle.y = (Math::Rand()-0.5f)*10.0f*Math::PI/180.0f;
+ angle.z = (Math::Rand()-0.5f)*30.0f*Math::PI/180.0f;
+ BurnAddPart(6, pos, angle); // down the right caterpillar
+
+ pos.x = 0.0f;
+ pos.y = -4.0f;
+ pos.z = -2.0f;
+ angle.x = (Math::Rand()-0.5f)*20.0f*Math::PI/180.0f;
+ angle.y = (Math::Rand()-0.5f)*10.0f*Math::PI/180.0f;
+ angle.z = (Math::Rand()-0.5f)*30.0f*Math::PI/180.0f;
+ BurnAddPart(7, pos, angle); // down the left caterpillar
+ }
+
+ if ( m_burnType == OBJECT_MOBILEfa ||
+ m_burnType == OBJECT_MOBILEfc ||
+ m_burnType == OBJECT_MOBILEfi ||
+ m_burnType == OBJECT_MOBILEfs ||
+ m_burnType == OBJECT_MOBILEft ) // flying?
+ {
+ for ( i=0 ; i<3 ; i++ )
+ {
+ pos.x = 0.0f;
+ pos.y = -3.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*Math::PI/2.0f;
+ BurnAddPart(6+i, pos, angle); // foot
+ }
+ m_burnKeepPart[i] = -1;
+ }
+
+ if ( m_burnType == OBJECT_MOBILEia ||
+ m_burnType == OBJECT_MOBILEic ||
+ m_burnType == OBJECT_MOBILEii ||
+ m_burnType == OBJECT_MOBILEis ) // legs?
+ {
+ for ( i=0 ; i<6; i++ )
+ {
+ pos.x = 0.0f;
+ pos.y = -3.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = (Math::Rand()-0.5f)*Math::PI/4.0f;
+ angle.z = (Math::Rand()-0.5f)*Math::PI/4.0f;
+ BurnAddPart(6+i, pos, angle); // leg
+ }
+ }
+}
+
+// Adds a part move.
+
+void CPyro::BurnAddPart(int part, Math::Vector pos, Math::Vector angle)
+{
+ int i;
+
+ i = m_burnPartTotal;
+ m_burnPart[i].part = part;
+ m_burnPart[i].initialPos = m_object->RetPosition(part);
+ m_burnPart[i].finalPos = m_burnPart[i].initialPos+pos;
+ m_burnPart[i].initialAngle = m_object->RetAngle(part);
+ m_burnPart[i].finalAngle = m_burnPart[i].initialAngle+angle;
+
+ m_burnPartTotal ++;
+}
+
+// Advances of a vehicle fire.
+
+void CPyro::BurnProgress()
+{
+ CObject* sub;
+ Math::Vector pos;
+ float h;
+ int i;
+
+ if ( m_burnType == OBJECT_TEEN31 ) // basket?
+ {
+ m_object->SetZoomY(0, 1.0f-m_progress*0.5f); // slight flattening
+ }
+
+ for ( i=0 ; i<m_burnPartTotal ; i++ )
+ {
+ pos = m_burnPart[i].initialPos + m_progress*(m_burnPart[i].finalPos-m_burnPart[i].initialPos);
+ if ( i == 0 && m_burnFall > 0.0f )
+ {
+ h = powf(m_progress, 2.0f)*1000.0f;
+ if ( h > m_burnFall ) h = m_burnFall;
+ pos.y -= h;
+ }
+ m_object->SetPosition(m_burnPart[i].part, pos);
+
+ pos = m_burnPart[i].initialAngle + m_progress*(m_burnPart[i].finalAngle-m_burnPart[i].initialAngle);
+ m_object->SetAngle(m_burnPart[i].part, pos);
+ }
+
+ sub = m_object->RetPower();
+ if ( sub != 0 ) // is there a battery?
+ {
+ sub->SetZoomY(0, 1.0f-m_progress); // complete flattening
+ }
+}
+
+// Indicates whether a part should be retained.
+
+bool CPyro::BurnIsKeepPart(int part)
+{
+ int i;
+
+ i = 0;
+ while ( m_burnKeepPart[i] != -1 )
+ {
+ if ( part == m_burnKeepPart[i++] ) return true; // must keep
+ }
+ return false; // must destroy
+}
+
+// Ends the fire of an insect or a vehicle.
+
+void CPyro::BurnTerminate()
+{
+ int i, objRank;
+
+ if ( m_type == PT_BURNO ) // organic object is burning?
+ {
+ DeleteObject(true, true); // removes the insect
+ return;
+ }
+
+ for ( i=1 ; i<OBJECTMAXPART ; i++ )
+ {
+ objRank = m_object->RetObjectRank(i);
+ if ( objRank == -1 ) continue;
+ if ( BurnIsKeepPart(i) ) continue;
+
+ m_object->DeletePart(i);
+ }
+
+ DeleteObject(false, true); // destroys the object transported + the battery
+
+ if ( m_burnType == OBJECT_DERRICK ||
+ m_burnType == OBJECT_STATION ||
+ m_burnType == OBJECT_FACTORY ||
+ m_burnType == OBJECT_REPAIR ||
+ m_burnType == OBJECT_DESTROYER||
+ m_burnType == OBJECT_CONVERT ||
+ m_burnType == OBJECT_TOWER ||
+ m_burnType == OBJECT_RESEARCH ||
+ m_burnType == OBJECT_RADAR ||
+ m_burnType == OBJECT_INFO ||
+ m_burnType == OBJECT_ENERGY ||
+ m_burnType == OBJECT_LABO ||
+ m_burnType == OBJECT_NUCLEAR ||
+ m_burnType == OBJECT_PARA ||
+ m_burnType == OBJECT_SAFE ||
+ m_burnType == OBJECT_HUSTON ||
+ m_burnType == OBJECT_START ||
+ m_burnType == OBJECT_END )
+ {
+ m_object->SetType(OBJECT_RUINfactory); // others become a ruin
+ m_object->SetLock(false);
+ }
+ else
+ {
+ m_object->SetType(OBJECT_RUINmobilew1); // others become a ruin
+ m_object->SetLock(false);
+ }
+
+ m_object->SetBurn(false); // ruin usable (c-e-d. recoverable)
+}
+
+
+// Start of an object freight falling.
+
+void CPyro::FallStart()
+{
+ Math::Vector pos;
+
+ m_object->SetBurn(true); // usable
+
+ pos = m_object->RetPosition(0);
+ m_fallFloor = m_terrain->RetFloorLevel(pos);
+ m_fallSpeed = 0.0f;
+ m_fallBulletTime = 0.0f;
+ m_bFallEnding = false;
+}
+
+// Seeking an object explode by the falling ball of bees.
+
+CObject* CPyro::FallSearchBeeExplo()
+{
+ CObject* pObj;
+ Math::Vector iPos, oPos;
+ ObjectType oType;
+ float iRadius, oRadius, distance, shieldRadius;
+ int i, j;
+
+ m_object->GetCrashSphere(0, iPos, iRadius);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( oType != OBJECT_HUMAN &&
+ oType != OBJECT_MOBILEfa &&
+ oType != OBJECT_MOBILEta &&
+ oType != OBJECT_MOBILEwa &&
+ oType != OBJECT_MOBILEia &&
+ oType != OBJECT_MOBILEfc &&
+ oType != OBJECT_MOBILEtc &&
+ oType != OBJECT_MOBILEwc &&
+ oType != OBJECT_MOBILEic &&
+ oType != OBJECT_MOBILEfi &&
+ oType != OBJECT_MOBILEti &&
+ oType != OBJECT_MOBILEwi &&
+ oType != OBJECT_MOBILEii &&
+ oType != OBJECT_MOBILEfs &&
+ oType != OBJECT_MOBILEts &&
+ oType != OBJECT_MOBILEws &&
+ oType != OBJECT_MOBILEis &&
+ oType != OBJECT_MOBILErt &&
+ oType != OBJECT_MOBILErc &&
+ oType != OBJECT_MOBILErr &&
+ oType != OBJECT_MOBILErs &&
+ oType != OBJECT_MOBILEsa &&
+ oType != OBJECT_MOBILEtg &&
+ oType != OBJECT_MOBILEft &&
+ oType != OBJECT_MOBILEtt &&
+ oType != OBJECT_MOBILEwt &&
+ oType != OBJECT_MOBILEit &&
+ oType != OBJECT_MOBILEdr &&
+ oType != OBJECT_BASE &&
+ oType != OBJECT_DERRICK &&
+ oType != OBJECT_STATION &&
+ oType != OBJECT_FACTORY &&
+ oType != OBJECT_REPAIR &&
+ oType != OBJECT_DESTROYER&&
+ oType != OBJECT_CONVERT &&
+ oType != OBJECT_TOWER &&
+ oType != OBJECT_RESEARCH &&
+ oType != OBJECT_RADAR &&
+ oType != OBJECT_INFO &&
+ oType != OBJECT_ENERGY &&
+ oType != OBJECT_LABO &&
+ oType != OBJECT_NUCLEAR &&
+ oType != OBJECT_PARA &&
+ oType != OBJECT_SAFE &&
+ oType != OBJECT_HUSTON &&
+ oType != OBJECT_METAL &&
+ oType != OBJECT_POWER &&
+ oType != OBJECT_ATOMIC ) continue;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+
+ oPos = pObj->RetPosition(0);
+
+ shieldRadius = pObj->RetShieldRadius();
+ if ( shieldRadius > 0.0f )
+ {
+ distance = Math::Distance(oPos, iPos);
+ if ( distance <= shieldRadius ) return pObj;
+ }
+
+ if ( oType == OBJECT_BASE )
+ {
+ distance = Math::Distance(oPos, iPos);
+ if ( distance < 25.0f ) return pObj;
+ }
+
+ // Test the center of the object, which is necessary for objects
+ // that have no sphere in the center (station).
+ distance = Math::Distance(oPos, iPos)-4.0f;
+ if ( distance < 5.0f ) return pObj;
+
+ // Test with all spheres of the object.
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ distance = Math::Distance(oPos, iPos);
+ if ( distance <= iRadius+oRadius )
+ {
+ return pObj;
+ }
+ }
+ }
+ return 0;
+}
+
+// Fall of an object's freight.
+
+void CPyro::FallProgress(float rTime)
+{
+ CObject* pObj;
+ Math::Vector pos;
+ bool bFloor = false;
+
+ if ( m_object == 0 ) return;
+
+ m_fallSpeed += rTime*50.0f; // v2 = v1 + a*dt
+ pos = m_object->RetPosition(0);
+ pos.y -= m_fallSpeed*rTime; // dd -= v2*dt
+
+ if ( pos.y <= m_fallFloor ) // below the ground level?
+ {
+ pos.y = m_fallFloor;
+ bFloor = true;
+ }
+ m_object->SetPosition(0, pos);
+
+ if ( m_object->RetType() == OBJECT_BULLET )
+ {
+ m_fallBulletTime += rTime;
+
+ if ( m_fallBulletTime > 0.2f || bFloor )
+ {
+ m_fallBulletTime = 0.0f;
+
+ pObj = FallSearchBeeExplo();
+ if ( pObj == 0 )
+ {
+ if ( bFloor ) // reaches the ground?
+ {
+ m_object->ExploObject(EXPLO_BOUM, 0.0f); // start explosion
+ }
+ }
+ else
+ {
+ if ( pObj->RetShieldRadius() > 0.0f ) // protected by shield?
+ {
+ m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f, 0.0f, 0.0f);
+ m_sound->Play(SOUND_GUNDEL);
+
+ DeleteObject(true, true); // removes the ball
+ }
+ else
+ {
+ if ( pObj->ExploObject(EXPLO_BOUM, 1.0f) ) // start explosion
+ {
+ DeleteObject(true, true); // removes the ball
+ }
+ else
+ {
+ m_object->ExploObject(EXPLO_BOUM, 0.0f); // start explosion
+ }
+ }
+ }
+
+ if ( bFloor || pObj != 0 )
+ {
+ m_bFallEnding = true;
+ }
+ }
+ }
+}
+
+// Indicates whether the fall is over.
+
+Error CPyro::FallIsEnded()
+{
+ Math::Vector pos;
+
+ if ( m_bFallEnding || m_object == 0 ) return ERR_STOP;
+
+ pos = m_object->RetPosition(0);
+ if ( pos.y > m_fallFloor ) return ERR_CONTINUE;
+
+ m_sound->Play(SOUND_BOUM, pos);
+ m_object->SetBurn(false); // usable again
+
+ return ERR_STOP;
+}
+
diff --git a/src/old/pyro.h b/src/old/pyro.h
index 4b61356..f64d8f0 100644
--- a/src/old/pyro.h
+++ b/src/old/pyro.h
@@ -1,170 +1,170 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// pyro.h
-
-#pragma once
-
-
-#include "old/d3dengine.h"
-#include "object/object.h"
-#include "common/misc.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CTerrain;
-class CCamera;
-class CParticule;
-class CLight;
-class CObject;
-class CDisplayText;
-class CRobotMain;
-class CSound;
-
-
-
-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
-};
-
-
-struct PyroBurnPart
-{
- int part;
- Math::Vector initialPos;
- Math::Vector finalPos;
- Math::Vector initialAngle;
- Math::Vector finalAngle;
-};
-
-struct PyroLightOper
-{
- float progress;
- float intensity;
- D3DCOLORVALUE color;
-};
-
-
-
-class CPyro
-{
-public:
- CPyro(CInstanceManager* iMan);
- ~CPyro();
-
- void DeleteObject(bool bAll=false);
- bool Create(PyroType type, CObject* pObj, float force=1.0f);
- bool EventProcess(const Event &event);
- Error IsEnded();
- void CutObjectLink(CObject* pObj);
-
-protected:
- void DisplayError(PyroType type, CObject* pObj);
- bool CreateLight(Math::Vector pos, float height);
- void DeleteObject(bool bPrimary, bool bSecondary);
-
- void CreateTriangle(CObject* pObj, ObjectType oType, int part);
-
- void ExploStart();
- void ExploTerminate();
-
- void BurnStart();
- void BurnAddPart(int part, Math::Vector pos, Math::Vector angle);
- void BurnProgress();
- bool BurnIsKeepPart(int part);
- void BurnTerminate();
-
- void FallStart();
- CObject* FallSearchBeeExplo();
- void FallProgress(float rTime);
- Error FallIsEnded();
-
- void LightOperFlush();
- void LightOperAdd(float progress, float intensity, float r, float g, float b);
- void LightOperFrame(float rTime);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CTerrain* m_terrain;
- CCamera* m_camera;
- CParticule* m_particule;
- CLight* m_light;
- CObject* m_object;
- CDisplayText* m_displayText;
- CRobotMain* m_main;
- CSound* m_sound;
-
- Math::Vector m_pos; // center of the effect
- Math::Vector m_posPower; // center of the battery
- bool m_bPower; // battery exists?
- PyroType m_type;
- float m_force;
- float m_size;
- float m_progress;
- float m_speed;
- float m_time;
- float m_lastParticule;
- float m_lastParticuleSmoke;
- int m_soundChannel;
-
- int m_lightRank;
- int m_lightOperTotal;
- PyroLightOper m_lightOper[10];
- float m_lightHeight;
-
- ObjectType m_burnType;
- int m_burnPartTotal;
- PyroBurnPart m_burnPart[10];
- int m_burnKeepPart[10];
- float m_burnFall;
-
- float m_fallFloor;
- float m_fallSpeed;
- float m_fallBulletTime;
- bool m_bFallEnding;
-
- int m_crashSphereUsed; // number of spheres used
- Math::Vector m_crashSpherePos[50];
- float m_crashSphereRadius[50];
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// pyro.h
+
+#pragma once
+
+
+#include "old/d3dengine.h"
+#include "object/object.h"
+#include "common/misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CTerrain;
+class CCamera;
+class CParticule;
+class CLight;
+class CObject;
+class CDisplayText;
+class CRobotMain;
+class CSound;
+
+
+
+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
+};
+
+
+struct PyroBurnPart
+{
+ int part;
+ Math::Vector initialPos;
+ Math::Vector finalPos;
+ Math::Vector initialAngle;
+ Math::Vector finalAngle;
+};
+
+struct PyroLightOper
+{
+ float progress;
+ float intensity;
+ D3DCOLORVALUE color;
+};
+
+
+
+class CPyro
+{
+public:
+ CPyro(CInstanceManager* iMan);
+ ~CPyro();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(PyroType type, CObject* pObj, float force=1.0f);
+ bool EventProcess(const Event &event);
+ Error IsEnded();
+ void CutObjectLink(CObject* pObj);
+
+protected:
+ void DisplayError(PyroType type, CObject* pObj);
+ bool CreateLight(Math::Vector pos, float height);
+ void DeleteObject(bool bPrimary, bool bSecondary);
+
+ void CreateTriangle(CObject* pObj, ObjectType oType, int part);
+
+ void ExploStart();
+ void ExploTerminate();
+
+ void BurnStart();
+ void BurnAddPart(int part, Math::Vector pos, Math::Vector angle);
+ void BurnProgress();
+ bool BurnIsKeepPart(int part);
+ void BurnTerminate();
+
+ void FallStart();
+ CObject* FallSearchBeeExplo();
+ void FallProgress(float rTime);
+ Error FallIsEnded();
+
+ void LightOperFlush();
+ void LightOperAdd(float progress, float intensity, float r, float g, float b);
+ void LightOperFrame(float rTime);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CTerrain* m_terrain;
+ CCamera* m_camera;
+ CParticule* m_particule;
+ CLight* m_light;
+ CObject* m_object;
+ CDisplayText* m_displayText;
+ CRobotMain* m_main;
+ CSound* m_sound;
+
+ Math::Vector m_pos; // center of the effect
+ Math::Vector m_posPower; // center of the battery
+ bool m_bPower; // battery exists?
+ PyroType m_type;
+ float m_force;
+ float m_size;
+ float m_progress;
+ float m_speed;
+ float m_time;
+ float m_lastParticule;
+ float m_lastParticuleSmoke;
+ int m_soundChannel;
+
+ int m_lightRank;
+ int m_lightOperTotal;
+ PyroLightOper m_lightOper[10];
+ float m_lightHeight;
+
+ ObjectType m_burnType;
+ int m_burnPartTotal;
+ PyroBurnPart m_burnPart[10];
+ int m_burnKeepPart[10];
+ float m_burnFall;
+
+ float m_fallFloor;
+ float m_fallSpeed;
+ float m_fallBulletTime;
+ bool m_bFallEnding;
+
+ int m_crashSphereUsed; // number of spheres used
+ Math::Vector m_crashSpherePos[50];
+ float m_crashSphereRadius[50];
+};
+
diff --git a/src/old/resource.h b/src/old/resource.h
index 0f3be0a..959592d 100644
--- a/src/old/resource.h
+++ b/src/old/resource.h
@@ -1,55 +1,55 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by winmain.rc
-//
-#define IDI_MAIN_ICON 101
-#define IDR_MAIN_ACCEL 113
-#define IDR_MENU 141
-#define IDR_POPUP 142
-#define IDD_ABOUT 143
-#define IDD_CHANGEDEVICE 144
-#define IDC_CURSORHAND 149
-#define IDC_CURSORSCROLLL 150
-#define IDC_CURSORSCROLLR 151
-#define IDC_CURSORSCROLLU 152
-#define IDC_CURSORSCROLLD 153
-#define IDC_CURSORTARGET 154
-#define IDC_DEVICE_COMBO 1000
-#define IDC_MODE_COMBO 1001
-#define IDC_WINDOWED_CHECKBOX 1012
-#define IDC_STEREO_CHECKBOX 1013
-#define IDC_FULLSCREEN_TEXT 1014
-#define IDM_ABOUT 40001
-#define IDM_CHANGEDEVICE 40002
-#define IDM_TOGGLEFULLSCREEN 40003
-#define IDM_TOGGLESTART 40004
-#define IDM_SINGLESTEP 40005
-#define IDM_EXIT 40006
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_3D_CONTROLS 1
-#define _APS_NEXT_RESOURCE_VALUE 159
-#define _APS_NEXT_COMMAND_VALUE 40011
-#define _APS_NEXT_CONTROL_VALUE 1015
-#define _APS_NEXT_SYMED_VALUE 102
-#endif
-#endif
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by winmain.rc
+//
+#define IDI_MAIN_ICON 101
+#define IDR_MAIN_ACCEL 113
+#define IDR_MENU 141
+#define IDR_POPUP 142
+#define IDD_ABOUT 143
+#define IDD_CHANGEDEVICE 144
+#define IDC_CURSORHAND 149
+#define IDC_CURSORSCROLLL 150
+#define IDC_CURSORSCROLLR 151
+#define IDC_CURSORSCROLLU 152
+#define IDC_CURSORSCROLLD 153
+#define IDC_CURSORTARGET 154
+#define IDC_DEVICE_COMBO 1000
+#define IDC_MODE_COMBO 1001
+#define IDC_WINDOWED_CHECKBOX 1012
+#define IDC_STEREO_CHECKBOX 1013
+#define IDC_FULLSCREEN_TEXT 1014
+#define IDM_ABOUT 40001
+#define IDM_CHANGEDEVICE 40002
+#define IDM_TOGGLEFULLSCREEN 40003
+#define IDM_TOGGLESTART 40004
+#define IDM_SINGLESTEP 40005
+#define IDM_EXIT 40006
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_3D_CONTROLS 1
+#define _APS_NEXT_RESOURCE_VALUE 159
+#define _APS_NEXT_COMMAND_VALUE 40011
+#define _APS_NEXT_CONTROL_VALUE 1015
+#define _APS_NEXT_SYMED_VALUE 102
+#endif
+#endif
diff --git a/src/old/sound.cpp b/src/old/sound.cpp
index 8b4089a..9aca05a 100644
--- a/src/old/sound.cpp
+++ b/src/old/sound.cpp
@@ -1,1659 +1,1659 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// sound.cpp
-
-
-#include <stdlib.h>
-#include <ctype.h>
-#include <d3dtypes.h>
-#include <dsound.h>
-#include <stdio.h>
-
-#include "common/language.h"
-#include "common/struct.h"
-#include "common/iman.h"
-#include "math/geometry.h"
-#include "math/conv.h"
-#include "old/math3d.h"
-#include "old/sound.h"
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-
-const int LXIMAGE = 640;
-const int LYIMAGE = 480;
-
-
-
-// Header .WAV file.
-
-struct WaveHeader
-{
- BYTE RIFF[4]; // "RIFF"
- DWORD dwSize; // size of data to follow
- BYTE WAVE[4]; // "WAVE"
- BYTE fmt_[4]; // "fmt "
- DWORD dw16; // 16
- WORD wOne_0; // 1
- WORD wChnls; // number of Channels
- DWORD dwSRate; // sample Rate
- DWORD BytesPerSec; // sample Rate
- WORD wBlkAlign; // 1
- WORD BitsPerSample; // sample size
- BYTE DATA[4]; // "DATA"
- DWORD dwDSize; // number of Samples
-};
-
-
-
-
-// Displays an error DirectSound.
-
-void DisplayError(char *name, Sound sound, HRESULT err)
-{
- char s[100];
- unsigned int i = err;
- if ( err == DS_OK ) return;
- sprintf(s, "SoundError in %s, sound=%d err=%d\n", name, sound, i);
- OutputDebugString(s);
-
- if ( err == DSERR_ALLOCATED ) OutputDebugString("DSERR_ALLOCATED\n");
- if ( err == DSERR_CONTROLUNAVAIL ) OutputDebugString("DSERR_CONTROLUNAVAIL\n");
- if ( err == DSERR_INVALIDPARAM ) OutputDebugString("DSERR_INVALIDPARAM\n");
- if ( err == DSERR_INVALIDCALL ) OutputDebugString("DSERR_INVALIDCALL\n");
- if ( err == DSERR_GENERIC ) OutputDebugString("DSERR_GENERIC\n");
- if ( err == DSERR_PRIOLEVELNEEDED ) OutputDebugString("DSERR_PRIOLEVELNEEDED\n");
- if ( err == DSERR_OUTOFMEMORY ) OutputDebugString("DSERR_OUTOFMEMORY\n");
- if ( err == DSERR_BADFORMAT ) OutputDebugString("DSERR_BADFORMAT\n");
- if ( err == DSERR_UNSUPPORTED ) OutputDebugString("DSERR_UNSUPPORTED\n");
- if ( err == DSERR_NODRIVER ) OutputDebugString("DSERR_NODRIVER\n");
- if ( err == DSERR_ALREADYINITIALIZED ) OutputDebugString("DSERR_ALREADYINITIALIZED\n");
- if ( err == DSERR_NOAGGREGATION ) OutputDebugString("DSERR_NOAGGREGATION\n");
- if ( err == DSERR_BUFFERLOST ) OutputDebugString("DSERR_BUFFERLOST\n");
- if ( err == DSERR_OTHERAPPHASPRIO ) OutputDebugString("DSERR_OTHERAPPHASPRIO\n");
- if ( err == DSERR_UNINITIALIZED ) OutputDebugString("DSERR_UNINITIALIZED\n");
- if ( err == DSERR_NOINTERFACE ) OutputDebugString("DSERR_NOINTERFACE\n");
- if ( err == DSERR_ACCESSDENIED ) OutputDebugString("DSERR_ACCESSDENIED\n");
-}
-
-// Returns the name of the current folder.
-
-void GetCurrentDir(char *pName, int lg)
-{
- int i;
-
- strncpy(pName, _pgmptr, lg-1);
- pName[lg-1] = 0;
-
- lg = strlen(pName);
- if ( lg == 0 ) return;
-
- for ( i=0 ; i<lg ; i++ )
- {
- pName[i] = tolower(pName[i]);
- }
-
- while ( lg > 0 )
- {
- lg --;
- if ( pName[lg] == '\\' )
- {
- pName[lg+1] = 0;
- break;
- }
- }
-
- if ( lg > 6 && strcmp(pName+lg-6, "\\debug\\") == 0 )
- {
- pName[lg-5] = 0; // ignores the folder \debug!
- }
-
- if ( lg > 6 && strcmp(pName+lg-6, "\\release\\") == 0 )
- {
- pName[lg-7] = 0; // ignores the folder \release !
- }
-}
-
-
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-
-// Changes the volume of midi.
-// The volume is between 0 and 20!
-
-void InitMidiVolume(int volume)
-{
- int nb, i, n;
- MMRESULT result;
- HMIDIOUT hmo = 0;
-
- static int table[21] =
- {
- 0x00000000,
- 0x11111111,
- 0x22222222,
- 0x33333333,
- 0x44444444,
- 0x55555555,
- 0x66666666,
- 0x77777777,
- 0x88888888,
- 0x99999999,
- 0xAAAAAAAA,
- 0xBBBBBBBB,
- 0xCCCCCCCC,
- 0xDDDDDDDD,
- 0xEEEEEEEE,
- 0xF222F222,
- 0xF555F555,
- 0xF777F777,
- 0xFAAAFAAA,
- 0xFDDDFDDD,
- 0xFFFFFFFF,
- };
-
- if ( volume < 0 ) volume = 0;
- if ( volume > MAXVOLUME ) volume = MAXVOLUME;
-
- nb = midiOutGetNumDevs();
- for ( i=0 ; i<nb ; i++ )
- {
- result = midiOutOpen((LPHMIDIOUT)&hmo, i, 0L, 0L, 0L);
- if ( result != MMSYSERR_NOERROR )
- {
- continue;
- }
-
- result = midiOutSetVolume(hmo, table[volume]);
- if ( result != MMSYSERR_NOERROR )
- {
- n = 1;
- }
- midiOutClose(hmo);
- hmo = 0;
- }
-}
-
-// Changes the volume of audio CD.
-// The volume is between 0 and 20!
-// Crashing in Vista. The current craft (if _SOUNDTRACKS = true) no longer crashes,
-// but this is not the correct volume which is modified!
-
-bool InitAudioTrackVolume(int volume)
-{
-#if _SOUNDTRACKS
- MMRESULT rc; // Return code.
- HMIXER hMixer; // Mixer handle used in mixer API calls.
- MIXERCONTROL mxc; // Holds the mixer control data.
- MIXERLINE mxl; // Holds the mixer line data.
- MIXERLINECONTROLS mxlc; // Obtains the mixer control.
-
- if ( volume < 0 ) volume = 0;
- if ( volume > MAXVOLUME ) volume = MAXVOLUME;
-
- // Open the mixer. This opens the mixer with a deviceID of 0. If you
- // have a single sound card/mixer, then this will open it. If you have
- // multiple sound cards/mixers, the deviceIDs will be 0, 1, 2, and
- // so on.
- rc = mixerOpen(&hMixer, 0,0,0,0);
- if ( rc != MMSYSERR_NOERROR )
- {
- return false; // Couldn't open the mixer.
- }
-
- // Initialize MIXERLINE structure.
- ZeroMemory(&mxl,sizeof(mxl));
- mxl.cbStruct = sizeof(mxl);
-
- // Specify the line you want to get. You are getting the input line
- // here. If you want to get the output line, you need to use
- // MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT.
- mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
-
- rc = mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl,
- MIXER_GETLINEINFOF_COMPONENTTYPE);
- if ( rc != MMSYSERR_NOERROR )
- {
- return false; // Couldn't get the mixer line.
- }
-
- // Get the control.
- ZeroMemory(&mxlc, sizeof(mxlc));
- mxlc.cbStruct = sizeof(mxlc);
- mxlc.dwLineID = mxl.dwLineID;
-//? mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_PEAKMETER;
-//? mxlc.dwControlType = MIXERCONTROL_CONTROLF_UNIFORM;
- mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
- mxlc.cControls = 1;
- mxlc.cbmxctrl = sizeof(mxc);
- mxlc.pamxctrl = &mxc;
- ZeroMemory(&mxc, sizeof(mxc));
- mxc.cbStruct = sizeof(mxc);
- rc = mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc,
- MIXER_GETLINECONTROLSF_ONEBYTYPE);
-//? MIXER_GETLINECONTROLSF_ALL);
- if ( rc != MMSYSERR_NOERROR )
- {
- return false; // Couldn't get the control.
- }
-
- // After successfully getting the peakmeter control, the volume range
- // will be specified by mxc.Bounds.lMinimum to mxc.Bounds.lMaximum.
-
- MIXERCONTROLDETAILS mxcd; // Gets the control values.
- MIXERCONTROLDETAILS_SIGNED volStruct; // Gets the control values.
-
- volStruct.lValue = volume*(mxc.Bounds.lMaximum-mxc.Bounds.lMinimum);
- volStruct.lValue /= MAXVOLUME;
- volStruct.lValue += mxc.Bounds.lMinimum;
-
- // Initialize the MIXERCONTROLDETAILS structure
- ZeroMemory(&mxcd, sizeof(mxcd));
- mxcd.cbStruct = sizeof(mxcd);
- mxcd.cbDetails = sizeof(volStruct);
- mxcd.dwControlID = mxc.dwControlID;
- mxcd.paDetails = &volStruct;
- mxcd.cChannels = 1;
-
- // Get the current value of the peakmeter control. Typically, you
- // would set a timer in your program to query the volume every 10th
- // of a second or so.
- rc = mixerSetControlDetails((HMIXEROBJ)hMixer, &mxcd,
- MIXER_SETCONTROLDETAILSF_VALUE);
- if ( rc != MMSYSERR_NOERROR )
- {
- return false; // Couldn't get the current volume.
- }
-#endif
-
- return true;
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-
-// Constructor.
-
-CSound::CSound(CInstanceManager* iMan)
-{
- int i;
-
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_SOUND, this);
-
- m_bEnable = false;
- m_bState = false;
- m_bAudioTrack = true;
- m_ctrl3D = true;
- m_bDebugMode = false;
- m_MidiDeviceID = 0;
- m_MIDIMusic = 0;
- m_audioVolume = 20;
- m_midiVolume = 15;
- m_lastMidiVolume = 0;
- m_listener = 0;
- m_lastTime = 0.0f;
- m_playTime = 0.0f;
- m_uniqueStamp = 0;
- m_maxSound = MAXSOUND;
- m_eye = Math::Vector(0.0f, 0.0f, 0.0f);
- m_hWnd = 0;
-
- m_lpDS = NULL;
-
- ZeroMemory(m_channel, sizeof(SoundChannel)*MAXSOUND);
- for ( i=0 ; i<MAXSOUND ; i++ )
- {
- m_channel[i].bUsed = false;
- }
-
- for ( i=0 ; i<MAXFILES ; i++ )
- {
- m_files[i] = 0;
- }
-}
-
-// Destructor.
-
-CSound::~CSound()
-{
- int i;
-
- if ( m_bEnable )
- {
- InitMidiVolume(15); // gives an average volume!
- InitAudioTrackVolume(15); // gives an average volume!
- }
-
- for ( i=0 ; i<MAXSOUND ; i++ )
- {
- if ( m_channel[i].bUsed )
- {
- m_channel[i].soundBuffer->Stop();
- m_channel[i].soundBuffer->Release();
- m_channel[i].soundBuffer = 0;
- m_channel[i].bUsed = false;
- }
- }
-
- if ( m_listener != NULL )
- {
- m_listener->Release();
- m_listener = NULL;
- }
-
- if ( m_lpDS != NULL )
- {
- m_lpDS->Release();
- m_lpDS = NULL;
- }
-}
-
-
-// Specifies whether you are in debug mode.
-
-void CSound::SetDebugMode(bool bMode)
-{
- m_bDebugMode = bMode;
-}
-
-
-// Initializes DirectSound.
-
-bool CSound::Create(HWND hWnd, bool b3D)
-{
- LPDIRECTSOUNDBUFFER primary;
- DSBUFFERDESC dsbdesc;
- DSCAPS dscaps;
- WAVEFORMATEX wfx;
- HRESULT hr;
-
- if ( !DirectSoundCreate(NULL, &m_lpDS, NULL) == DS_OK )
- {
- OutputDebugString("Fatal error: DirectSoundCreate\n");
- m_bEnable = false;
- return false;
- }
-
-//? m_lpDS->SetCooperativeLevel(hWnd, DSSCL_NORMAL);
- m_lpDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);
-
- if ( !RetSound3DCap() ) b3D = false;
-
- m_ctrl3D = false;
- if ( b3D )
- {
- // Obtain primary buffer, asking it for 3D control.
- ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
- dsbdesc.dwSize = sizeof(DSBUFFERDESC);
- dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
- hr = m_lpDS->CreateSoundBuffer( &dsbdesc, &primary, NULL );
- if ( hr == S_OK )
- {
- m_ctrl3D = true;
- }
- }
-
- if ( !m_ctrl3D )
- {
- // Obtain primary buffer, without 3D control.
- ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
- dsbdesc.dwSize = sizeof(DSBUFFERDESC);
- dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
- hr = m_lpDS->CreateSoundBuffer( &dsbdesc, &primary, NULL );
- if ( hr != S_OK )
- {
- return false;
- }
- m_ctrl3D = false;
- }
-
- if ( m_ctrl3D )
- {
- hr = primary->QueryInterface( IID_IDirectSound3DListener,
- (VOID**)&m_listener );
- if ( hr != S_OK )
- {
- primary->Release();
- return false;
- }
- }
-
- // Set primary buffer format to 44kHz and 16-bit output.
- ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
- wfx.wFormatTag = WAVE_FORMAT_PCM;
- wfx.nChannels = 2;
- wfx.nSamplesPerSec = 22050;
-//? wfx.nSamplesPerSec = 44100;
- wfx.wBitsPerSample = 16;
- wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
- wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
- hr = primary->SetFormat(&wfx);
- if ( hr != S_OK )
- {
- DisplayError("SetFormat", SOUND_CLICK, hr);
- }
-
- // Release the primary buffer, since it is not need anymore.
- primary->Release();
-
- // Search the maximum possible voices.
- if ( m_ctrl3D )
- {
- ZeroMemory( &dscaps, sizeof(DSCAPS) );
- dscaps.dwSize = sizeof(DSCAPS);
- hr = m_lpDS->GetCaps(&dscaps);
- if ( hr == DS_OK )
- {
- m_maxSound = dscaps.dwMaxHwMixingAllBuffers;
- if ( dscaps.dwMaxHw3DAllBuffers > 0 &&
- m_maxSound > (int)dscaps.dwMaxHw3DAllBuffers )
- {
- m_maxSound = dscaps.dwMaxHw3DAllBuffers;
- }
- if ( m_maxSound > MAXSOUND ) m_maxSound = MAXSOUND;
- }
- }
-
- m_bEnable = true;
- m_hWnd = hWnd;
- return true;
-}
-
-
-// Indicates whether to play sounds in 3D or not.
-
-void CSound::SetSound3D(bool bMode)
-{
- StopAll();
-
- if ( m_listener != NULL )
- {
- m_listener->Release();
- m_listener = NULL;
- }
-
- if ( m_lpDS != NULL )
- {
- m_lpDS->Release();
- m_lpDS = NULL;
- }
-
- Create(m_hWnd, bMode);
-}
-
-bool CSound::RetSound3D()
-{
- return m_ctrl3D;
-}
-
-// Indicates whether it is possible to play sounds in 3D.
-
-bool CSound::RetSound3DCap()
-{
- DSCAPS dscaps;
- HRESULT hr;
-
- ZeroMemory( &dscaps, sizeof(DSCAPS) );
- dscaps.dwSize = sizeof(DSCAPS);
- hr = m_lpDS->GetCaps(&dscaps);
- if ( hr != DS_OK ) return false;
-
- return ( dscaps.dwMaxHw3DAllBuffers > 0 );
-}
-
-
-
-// Returns the state of DirectSound.
-
-bool CSound::RetEnable()
-{
- return m_bEnable;
-}
-
-
-// Switches on or off the sound.
-
-void CSound::SetState(bool bState)
-{
- m_bState = bState;
-}
-
-// Specifies the pathname to the CD.
-
-void CSound::SetCDpath(char *path)
-{
- strcpy(m_CDpath, path);
-}
-
-// Switches on or off the CD-audio music.
-
-void CSound::SetAudioTrack(bool bAudio)
-{
- m_bAudioTrack = bAudio;
-}
-
-
-// Manages volumes of audio (. Wav) and midi (. Mid).
-
-void CSound::SetAudioVolume(int volume)
-{
- m_audioVolume = volume;
-}
-
-int CSound::RetAudioVolume()
-{
- if ( !m_bEnable ) return 0;
- return m_audioVolume;
-}
-
-void CSound::SetMidiVolume(int volume)
-{
- m_midiVolume = volume;
-
- if ( m_bAudioTrack )
- {
- InitAudioTrackVolume(m_midiVolume);
- }
-}
-
-int CSound::RetMidiVolume()
-{
- if ( !m_bEnable ) return 0;
- return m_midiVolume;
-}
-
-
-// Reads a file.
-
-bool CSound::ReadFile(Sound sound, char *metaname, char *filename)
-{
- WaveHeader wavHdr;
- DWORD size;
- int err;
-
- // Open the wave file.
- err = g_metafile.Open(metaname, filename);
- if ( err != 0 ) return false;
-
- // Read in the wave header.
- g_metafile.Read(&wavHdr, sizeof(wavHdr));
-
- // Figure out the size of the data region.
- size = wavHdr.dwDSize;
-
- if ( m_files[sound] != 0 )
- {
- free(m_files[sound]);
- }
- m_files[sound] = (char*)malloc(sizeof(WaveHeader)+size);
-
- memcpy(m_files[sound], &wavHdr, sizeof(WaveHeader));
- g_metafile.Read(m_files[sound]+sizeof(WaveHeader), size);
-
- // Close out the wave file.
- g_metafile.Close();
- return true;
-}
-
-// Hides all sound files (. Wav).
-
-void CSound::CacheAll()
-{
- int i;
- char meta[50];
- char name[50];
-
- if ( !m_bEnable ) return;
-
- if ( m_bDebugMode )
- {
- strcpy(meta, "");
- }
- else
- {
-#if _SCHOOL
- strcpy(meta, "ceebot3.dat");
-#else
- strcpy(meta, "colobot3.dat");
-#endif
- }
-
- for ( i=0 ; i<MAXFILES ; i++ )
- {
- if ( m_bDebugMode )
- {
- sprintf(name, "sound\\sound%.3d.wav", i);
- }
- else
- {
- sprintf(name, "sound%.3d.wav", i);
- }
- if ( !ReadFile((Sound)i, meta, name) ) break;
- }
-}
-
-
-// Return the priority of a sound.
-// The higher the value, the greater the sound is important.
-
-int CSound::RetPriority(Sound sound)
-{
- if ( sound == SOUND_FLYh ||
- sound == SOUND_FLY ||
- sound == SOUND_MOTORw ||
- sound == SOUND_MOTORt ||
- sound == SOUND_MOTORr ||
- sound == SOUND_MOTORs ||
- sound == SOUND_SLIDE ||
- sound == SOUND_ERROR )
- {
- return 30;
- }
-
- if ( sound == SOUND_CONVERT ||
- sound == SOUND_ENERGY ||
- sound == SOUND_DERRICK ||
- sound == SOUND_STATION ||
- sound == SOUND_REPAIR ||
- sound == SOUND_RESEARCH ||
- sound == SOUND_BURN ||
- sound == SOUND_BUILD ||
- sound == SOUND_TREMBLE ||
- sound == SOUND_NUCLEAR ||
- sound == SOUND_EXPLO ||
- sound == SOUND_EXPLOl ||
- sound == SOUND_EXPLOlp ||
- sound == SOUND_EXPLOp ||
- sound == SOUND_EXPLOi )
- {
- return 20;
- }
-
- if ( sound == SOUND_BLUP ||
- sound == SOUND_INSECTs ||
- sound == SOUND_INSECTa ||
- sound == SOUND_INSECTb ||
- sound == SOUND_INSECTw ||
- sound == SOUND_INSECTm ||
- sound == SOUND_PSHHH ||
- sound == SOUND_EGG )
- {
- return 0;
- }
-
- return 10;
-}
-
-// Seeks a free buffer.
-
-bool CSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded)
-{
- DWORD status;
- int i, priority;
-
- priority = RetPriority(sound);
-
-#if 1
- // Seeks a channel used which sound is stopped.
- for ( i=0 ; i<m_maxSound ; i++ )
- {
- if ( !m_channel[i].bUsed ) continue;
- if ( m_channel[i].type != sound ) continue;
-
- m_channel[i].soundBuffer->GetStatus(&status);
- if ( (status&DSBSTATUS_PLAYING) == 0 )
- {
- m_channel[i].priority = priority;
- m_channel[i].uniqueStamp = m_uniqueStamp++;
- channel = i;
- bAlreadyLoaded = true;
- return true;
- }
- }
-#endif
-
- // Seeks a channel completely free.
- for ( i=0 ; i<m_maxSound ; i++ )
- {
- if ( !m_channel[i].bUsed )
- {
- m_channel[i].priority = priority;
- m_channel[i].uniqueStamp = m_uniqueStamp++;
- channel = i;
- bAlreadyLoaded = false;
- return true;
- }
- }
-
- // Seeks a channel used which sound is stopped.
- for ( i=0 ; i<m_maxSound ; i++ )
- {
- if ( !m_channel[i].bUsed ) continue;
-
- m_channel[i].soundBuffer->GetStatus(&status);
- if ( (status&DSBSTATUS_PLAYING) == 0 )
- {
- m_channel[i].soundBuffer->Release();
- m_channel[i].soundBuffer = 0;
- m_channel[i].priority = priority;
- m_channel[i].uniqueStamp = m_uniqueStamp++;
-
- channel = i;
- bAlreadyLoaded = false;
- return true;
- }
- }
-
- // Seeks a lower priority channel used.
- for ( i=0 ; i<m_maxSound ; i++ )
- {
- if ( !m_channel[i].bUsed ) continue;
- if ( m_channel[i].priority >= priority ) continue;
-
- m_channel[i].soundBuffer->Stop();
- m_channel[i].soundBuffer->Release();
- m_channel[i].soundBuffer = 0;
- m_channel[i].priority = priority;
- m_channel[i].uniqueStamp = m_uniqueStamp++;
-
- channel = i;
- bAlreadyLoaded = false;
- return true;
- }
-
- // Seeks a channel used the same or lower priority.
- for ( i=0 ; i<m_maxSound ; i++ )
- {
- if ( !m_channel[i].bUsed ) continue;
- if ( m_channel[i].priority > priority ) continue;
-
- m_channel[i].soundBuffer->Stop();
- m_channel[i].soundBuffer->Release();
- m_channel[i].soundBuffer = 0;
- m_channel[i].priority = priority;
- m_channel[i].uniqueStamp = m_uniqueStamp++;
-
- channel = i;
- bAlreadyLoaded = false;
- return true;
- }
-
- char s[100];
- sprintf(s, "Sound %d forget (priority=%d)\n", sound, priority);
- OutputDebugString(s);
-
- return false;
-}
-
-// Reads in data from a wave file.
-
-bool CSound::ReadData(LPDIRECTSOUNDBUFFER lpDSB, Sound sound, DWORD size)
-{
- LPVOID pData1;
- DWORD dwData1Size;
- LPVOID pData2;
- DWORD dwData2Size;
- HRESULT hr;
-
- // Lock data in buffer for writing.
- hr = lpDSB->Lock(0, size, &pData1, &dwData1Size, &pData2, &dwData2Size, DSBLOCK_FROMWRITECURSOR);
- if ( hr != DS_OK )
- {
- return false;
- }
-
- // Read in first chunk of data.
- if ( dwData1Size > 0 )
- {
- memcpy(pData1, m_files[sound]+sizeof(WaveHeader), dwData1Size);
- }
-
- // Read in second chunk if necessary.
- if ( dwData2Size > 0 )
- {
- memcpy(pData2, m_files[sound]+sizeof(WaveHeader)+dwData1Size, dwData2Size);
- }
-
- // Unlock data in buffer.
- hr = lpDSB->Unlock(pData1, dwData1Size, pData2, dwData2Size);
- if ( hr != DS_OK )
- {
- return false;
- }
-
- return true;
-}
-
-// Creates a DirectSound buffer.
-
-bool CSound::CreateSoundBuffer(int channel, DWORD size, DWORD freq,
- DWORD bitsPerSample, DWORD blkAlign,
- bool bStereo)
-{
- PCMWAVEFORMAT pcmwf;
- DSBUFFERDESC dsbdesc;
- DS3DBUFFER bufferParams; // 3D buffer properties
- HRESULT hr;
-
- // Set up wave format structure.
- memset( &pcmwf, 0, sizeof(PCMWAVEFORMAT) );
- pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
- pcmwf.wf.nChannels = bStereo ? 2 : 1;
- pcmwf.wf.nSamplesPerSec = freq;
- pcmwf.wf.nBlockAlign = (WORD)blkAlign;
- pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
- pcmwf.wBitsPerSample = (WORD)bitsPerSample;
-
- // Set up DSBUFFERDESC structure.
- memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
- dsbdesc.dwSize = sizeof(DSBUFFERDESC);
- if ( m_ctrl3D )
- {
- dsbdesc.dwFlags = DSBCAPS_CTRL3D|DSBCAPS_MUTE3DATMAXDISTANCE|
- DSBCAPS_LOCDEFER|
- DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLFREQUENCY;
- }
- else
- {
- dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN|DSBCAPS_CTRLFREQUENCY;
- }
- dsbdesc.dwBufferBytes = size;
- dsbdesc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf;
-
- hr = m_lpDS->CreateSoundBuffer(&dsbdesc, &m_channel[channel].soundBuffer, NULL);
- if ( hr != DS_OK ) return false;
-
- if ( m_ctrl3D )
- {
- hr = m_channel[channel].soundBuffer->QueryInterface
- (
- IID_IDirectSound3DBuffer,
- (VOID**)&m_channel[channel].soundBuffer3D
- );
- if ( hr != DS_OK ) return false;
- }
-
- m_channel[channel].bUsed = true;
- m_channel[channel].bMute = false;
- return true;
-}
-
-// Creates a DirectSound buffer from a wave file.
-
-bool CSound::CreateBuffer(int channel, Sound sound)
-{
- WaveHeader* wavHdr;
- DWORD size;
- bool bStereo;
-
- if ( m_files[sound] == 0 ) return false;
-
- wavHdr = (WaveHeader*)m_files[sound];
- size = wavHdr->dwDSize;
- bStereo = wavHdr->wChnls > 1 ? true : false;
-
- // Create the sound buffer for the wave file.
- if ( !CreateSoundBuffer(channel, size, wavHdr->dwSRate,
- wavHdr->BitsPerSample, wavHdr->wBlkAlign, bStereo) )
- {
- return false;
- }
-
- // Read the data for the wave file into the sound buffer.
- if ( !ReadData(m_channel[channel].soundBuffer, sound, size) )
- {
- return false;
- }
-
- m_channel[channel].type = sound;
-
- // Close out the wave file.
- return true;
-}
-
-// Calculates the volume and pan of a sound, non-3D mode.
-
-void CSound::ComputeVolumePan2D(int channel, const Math::Vector &pos)
-{
- float dist, a, g;
-
- if ( pos.x == m_eye.x &&
- pos.y == m_eye.y &&
- pos.z == m_eye.z )
- {
- m_channel[channel].volume = 1.0f; // maximum volume
- m_channel[channel].pan = 0.0f; // at the center
- return;
- }
-
-#if _TEEN
- dist = Math::Distance(pos, m_eye);
- if ( dist >= 210.0f ) // very far?
- {
- m_channel[channel].volume = 0.0f; // silence
- m_channel[channel].pan = 0.0f; // at the center
- return;
- }
- if ( dist <= 10.0f ) // very close?
- {
- m_channel[channel].volume = 1.0f; // maximum volume
- m_channel[channel].pan = 0.0f; // at the center
- return;
- }
- m_channel[channel].volume = 1.0f-((dist-10.0f)/200.0f);
-#else
- dist = Math::Distance(pos, m_eye);
- if ( dist >= 110.0f ) // very far?
- {
- m_channel[channel].volume = 0.0f; // silence
- m_channel[channel].pan = 0.0f; // at the center
- return;
- }
- if ( dist <= 10.0f ) // very close?
- {
- m_channel[channel].volume = 1.0f; // maximum volume
- m_channel[channel].pan = 0.0f; // at the center
- return;
- }
- m_channel[channel].volume = 1.0f-((dist-10.0f)/100.0f);
-#endif
-
- a = Math::RotateAngle(m_lookat.x-m_eye.x, m_eye.z-m_lookat.z);
- g = Math::RotateAngle(pos.x-m_eye.x, m_eye.z-pos.z);
- m_channel[channel].pan = sinf(Math::Direction(a, g));
-}
-
-// Sounds in the middle.
-// Returns the associated channel or -1.
-
-int CSound::Play(Sound sound, float amplitude, float frequency, bool bLoop)
-{
- return Play(sound, m_lookat, amplitude, frequency, bLoop);
-}
-
-// Sounds at a given position.
-// Returns the associated channel or -1.
-
-int CSound::Play(Sound sound, Math::Vector pos,
- float amplitude, float frequency, bool bLoop)
-{
- DS3DBUFFER sb;
- int channel, iVolume, iPan, iFreq, uniqueStamp;
- bool bAlreadyLoaded;
- DWORD flag, freq;
- HRESULT err;
-
- if ( !m_bEnable ) return -1;
- if ( !m_bState || m_audioVolume == 0 ) return -1;
-
-//? if ( Math::Distance(pos, m_eye) > 100.0f ) return -1;
-
- if ( !SearchFreeBuffer(sound, channel, bAlreadyLoaded) ) return -1;
-
- if ( !bAlreadyLoaded )
- {
- if ( !CreateBuffer(channel, sound) )
- {
- if ( m_channel[channel].bUsed &&
- m_channel[channel].soundBuffer != 0 )
- {
- m_channel[channel].soundBuffer->Release();
- m_channel[channel].soundBuffer = 0;
- }
- m_channel[channel].bUsed = false;
- return -1;
- }
- }
-
- m_channel[channel].pos = pos;
-
- if ( m_ctrl3D )
- {
- m_channel[channel].volume = 1.0f;
- m_channel[channel].pan = 0.0f;
- }
- else
- {
- ComputeVolumePan2D(channel, pos);
- }
-
-#if 0
- DWORD status;
- m_channel[channel].soundBuffer->GetStatus(&status);
- char s[100];
- sprintf(s, "Play sound=%d status=%d channel=%d flag=%d\n", sound, status, channel, bAlreadyLoaded);
- OutputDebugString(s);
-#endif
-
- m_channel[channel].oper[0].bUsed = false;
- m_channel[channel].startAmplitude = amplitude;
- m_channel[channel].startFrequency = frequency;
- m_channel[channel].changeFrequency = 1.0f;
-
- if ( m_ctrl3D )
- {
- sb.dwSize = sizeof(DS3DBUFFER);
- err = m_channel[channel].soundBuffer3D->GetAllParameters(&sb);
- DisplayError("GetAllParameters", sound, err);
-
- sb.vPosition = VEC_TO_D3DVEC(pos);
-//? sb.dwInsideConeAngle = 90;
-//? sb.dwOutsideConeAngle = 180;
-//? sb.vConeOrientation = Math::Vector(0.0f, 1.0f, 0.0f);
- sb.lConeOutsideVolume = DSBVOLUME_MIN;
-#if _TEEN
- sb.flMinDistance = 50.0f;
-#else
- sb.flMinDistance = 20.0f;
-#endif
- sb.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
-
- err = m_channel[channel].soundBuffer3D->SetAllParameters(&sb, DS3D_IMMEDIATE);
- DisplayError("SetAllParameters", sound, err);
- }
-
- amplitude *= m_channel[channel].volume;
- amplitude *= (float)m_audioVolume/MAXVOLUME;
- iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
- if ( iVolume > 0 ) iVolume = 0;
- err = m_channel[channel].soundBuffer->SetVolume(iVolume);
- DisplayError("SetVolume", sound, err);
-
- if ( !m_ctrl3D )
- {
- iPan = (int)(m_channel[channel].pan*10000.0f);
- err = m_channel[channel].soundBuffer->SetPan(iPan);
- DisplayError("SetPan", sound, err);
- }
-
- if ( !bAlreadyLoaded )
- {
- err = m_channel[channel].soundBuffer->GetFrequency(&freq);
- DisplayError("GetFrequency", sound, err);
- m_channel[channel].initFrequency = freq;
- }
- iFreq = (int)(frequency*m_channel[channel].initFrequency);
- err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
- DisplayError("SetFrequency", sound, err);
-
- err = m_channel[channel].soundBuffer->SetCurrentPosition(0);
- DisplayError("SetCurrentPosition", sound, err);
-
- flag = bLoop?DSBPLAY_LOOPING:0;
-//? flag |= DSBPLAY_LOCHARDWARE|DSBPLAY_TERMINATEBY_DISTANCE;
-//? flag |= DSBPLAY_TERMINATEBY_DISTANCE;
- err = m_channel[channel].soundBuffer->Play(0, 0, flag);
- DisplayError("Play", sound, err);
- if ( err == DSERR_BADFORMAT )
- {
- iFreq = m_channel[channel].initFrequency;
- err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
- DisplayError("SetFrequency (repeat)", sound, err);
-
- err = m_channel[channel].soundBuffer->Play(0, 0, flag);
- DisplayError("Play (repeat)", sound, err);
- }
-
- uniqueStamp = m_channel[channel].uniqueStamp;
- return channel | ((uniqueStamp&0xffff)<<16);
-}
-
-// Check a channel number.
-// Adapts the channel, so it can be used as an offset in m_channel.
-
-bool CSound::CheckChannel(int &channel)
-{
- int uniqueStamp;
-
- uniqueStamp = (channel>>16)&0xffff;
- channel &= 0xffff;
-
- if ( !m_bEnable ) return false;
- if ( !m_bState || m_audioVolume == 0 ) return false;
-
- if ( channel < 0 || channel >= m_maxSound ) return false;
- if ( !m_channel[channel].bUsed ) return false;
-
- if ( m_channel[channel].uniqueStamp != uniqueStamp ) return false;
-
- return true;
-}
-
-// Removes all envelopes.
-
-bool CSound::FlushEnvelope(int channel)
-{
- if ( !CheckChannel(channel) ) return false;
-
- m_channel[channel].oper[0].bUsed = false;
- return true;
-}
-
-// Adds an operation envelope.
-
-bool CSound::AddEnvelope(int channel, float amplitude, float frequency,
- float time, SoundNext oper)
-{
- int i;
-
- if ( !CheckChannel(channel) ) return false;
-
- for ( i=0 ; i<MAXOPER ; i++ )
- {
- if ( m_channel[channel].oper[i].bUsed ) continue;
-
- m_channel[channel].oper[i].bUsed = true;
- m_channel[channel].oper[i].finalAmplitude = amplitude;
- m_channel[channel].oper[i].finalFrequency = frequency;
- m_channel[channel].oper[i].totalTime = time;
- m_channel[channel].oper[i].currentTime = 0;
- m_channel[channel].oper[i].nextOper = oper;
-
- if ( i < MAXOPER-1 )
- {
- m_channel[channel].oper[i+1].bUsed = false;
- }
- return true;
- }
- return false;
-}
-
-// Changes the position of a sound.
-
-bool CSound::Position(int channel, Math::Vector pos)
-{
- float amplitude, pan;
- int iVolume, iPan;
- HRESULT err;
-
- if ( !CheckChannel(channel) ) return false;
-
- m_channel[channel].pos = pos;
-
- if ( m_ctrl3D )
- {
- m_channel[channel].soundBuffer3D->SetPosition(pos.x, pos.y, pos.z, DS3D_DEFERRED);
- }
- else
- {
- ComputeVolumePan2D(channel, pos);
-
- if ( !m_channel[channel].oper[0].bUsed )
- {
- amplitude = m_channel[channel].startAmplitude;
- amplitude *= m_channel[channel].volume;
- amplitude *= (float)m_audioVolume/MAXVOLUME;
- iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
- if ( iVolume > 0 ) iVolume = 0;
- err = m_channel[channel].soundBuffer->SetVolume(iVolume);
- DisplayError("SetVolume", m_channel[channel].type, err);
- }
-
- pan = m_channel[channel].pan;
- iPan = (int)(pan*10000.0f);
- err = m_channel[channel].soundBuffer->SetPan(iPan);
- DisplayError("SetPan", m_channel[channel].type, err);
- }
- return true;
-}
-
-// Changes the frequency of a sound.
-// 0.5 down of an octave and 2.0 up of an octave.
-
-bool CSound::Frequency(int channel, float frequency)
-{
- HRESULT err;
- int iFreq;
-
- if ( !CheckChannel(channel) ) return false;
-
- m_channel[channel].changeFrequency = frequency;
-
- if ( !m_channel[channel].oper[0].bUsed )
- {
- iFreq = (int)(frequency*m_channel[channel].initFrequency);
- err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
- DisplayError("Frequency", m_channel[channel].type, err);
- }
-
- return true;
-}
-
-// Stops sound.
-
-bool CSound::Stop(int channel)
-{
- if ( !CheckChannel(channel) ) return false;
-
- m_channel[channel].soundBuffer->Stop();
- return true;
-}
-
-// Stops all sounds.
-
-bool CSound::StopAll()
-{
- DWORD status;
- int i;
-
- for ( i=0 ; i<MAXSOUND ; i++ )
- {
- if ( !m_channel[i].bUsed ) continue;
-
- m_channel[i].soundBuffer->GetStatus(&status);
- if ( (status&DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING )
- {
- m_channel[i].soundBuffer->Stop();
- }
- m_channel[i].soundBuffer->Stop();
- m_channel[i].soundBuffer->Release();
- m_channel[i].soundBuffer = 0;
-
- m_channel[i].bUsed = false;
- }
- return true;
-}
-
-// Silent all sounds.
-
-bool CSound::MuteAll(bool bMute)
-{
- int i;
-
- for ( i=0 ; i<MAXSOUND ; i++ )
- {
- if ( !m_channel[i].bUsed ) continue;
-
- m_channel[i].bMute = bMute;
- }
- return true;
-}
-
-
-// Passes the following operation for a channel.
-
-void CSound::OperNext(int channel)
-{
- int i;
-
- m_channel[channel].startAmplitude = m_channel[channel].oper[0].finalAmplitude;
- m_channel[channel].startFrequency = m_channel[channel].oper[0].finalFrequency;
-
- for ( i=0 ; i<MAXOPER-1 ; i++ )
- {
- if ( !m_channel[channel].oper[i+1].bUsed ) break;
-
- m_channel[channel].oper[i] = m_channel[channel].oper[i+1];
- }
-
- m_channel[channel].oper[i].bUsed = false;
-}
-
-// Updates the sound buffers.
-
-void CSound::FrameMove(float rTime)
-{
- HRESULT err;
- SoundNext next;
- float progress, volume, freq;
- int i, iVolume, iFreq;
-
- m_playTime += rTime;
-
- for ( i=0 ; i<m_maxSound ; i++ )
- {
- if ( !m_channel[i].bUsed ) continue;
- if ( !m_channel[i].oper[0].bUsed ) continue;
-
- if ( m_channel[i].bMute )
- {
- m_channel[i].soundBuffer->SetVolume(-10000); // silence
- continue;
- }
-
- m_channel[i].oper[0].currentTime += rTime;
-
- progress = m_channel[i].oper[0].currentTime / m_channel[i].oper[0].totalTime;
- if ( progress > 1.0f ) progress = 1.0f;
-
- volume = progress;
- volume *= m_channel[i].oper[0].finalAmplitude-m_channel[i].startAmplitude;
- volume += m_channel[i].startAmplitude;
- volume *= m_channel[i].volume;
- volume *= (float)m_audioVolume/MAXVOLUME;
- iVolume = (int)((powf(volume, 0.2f)-1.0f)*10000.0f);
- if ( iVolume > 0 ) iVolume = 0;
- m_channel[i].soundBuffer->SetVolume(iVolume);
-
- freq = progress;
- freq *= m_channel[i].oper[0].finalFrequency-m_channel[i].startFrequency;
- freq += m_channel[i].startFrequency;
- freq *= m_channel[i].changeFrequency;
- iFreq = (int)(freq*m_channel[i].initFrequency);
- err = m_channel[i].soundBuffer->SetFrequency(iFreq);
- DisplayError("FrameMove::Frequency", m_channel[i].type, err);
-
- if ( m_channel[i].oper[0].currentTime >=
- m_channel[i].oper[0].totalTime )
- {
- next = m_channel[i].oper[0].nextOper;
-
- if ( next == SOPER_LOOP )
- {
- m_channel[i].oper[0].currentTime = 0.0f;
- }
- else
- {
- OperNext(i);
-
- if ( next == SOPER_STOP )
- {
- m_channel[i].soundBuffer->Stop();
- }
- }
- }
- }
-
- m_lastTime += rTime;
- if ( m_lastTime >= 0.05f && m_listener != 0 )
- {
- m_lastTime = 0.0f;
- m_listener->CommitDeferredSettings();
- }
-}
-
-// Specifies the position of the listener.
-// Must be called whenever the camera moves.
-
-void CSound::SetListener(Math::Vector eye, Math::Vector lookat)
-{
- DS3DLISTENER listenerParams;
- HRESULT err;
- float amplitude, pan;
- int i, iVolume, iPan;
-
- m_eye = eye;
- m_lookat = lookat;
-
- if ( m_listener == 0 )
- {
- if ( m_ctrl3D ) return;
-
- for ( i=0 ; i<m_maxSound ; i++ )
- {
- if ( !m_channel[i].bUsed ) continue;
-
- ComputeVolumePan2D(i, m_channel[i].pos);
-
- if ( !m_channel[i].oper[0].bUsed )
- {
- amplitude = m_channel[i].startAmplitude;
- amplitude *= m_channel[i].volume;
- amplitude *= (float)m_audioVolume/MAXVOLUME;
- iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
- if ( iVolume > 0 ) iVolume = 0;
- err = m_channel[i].soundBuffer->SetVolume(iVolume);
- DisplayError("SetVolume", m_channel[i].type, err);
- }
-
- pan = m_channel[i].pan;
- iPan = (int)(pan*10000.0f);
- err = m_channel[i].soundBuffer->SetPan(iPan);
- DisplayError("SetPan", m_channel[i].type, err);
- }
- return;
- }
-
- // Get listener parameters.
- listenerParams.dwSize = sizeof(DS3DLISTENER);
- m_listener->GetAllParameters(&listenerParams);
-
- listenerParams.vPosition = VEC_TO_D3DVEC(eye);
- listenerParams.vOrientFront = VEC_TO_D3DVEC(lookat-eye);
- listenerParams.vOrientTop = D3DVECTOR(0.0f, 1.0f, 0.0f);
- listenerParams.flDistanceFactor = 10.0f;
- listenerParams.flRolloffFactor = 1.0f;
-
- m_listener->SetAllParameters(&listenerParams, DS3D_DEFERRED);
-}
-
-
-
-
-// Uses MCI to play a MIDI file. The window procedure
-// is notified when playback is complete.
-
-bool CSound::PlayMusic(int rank, bool bRepeat)
-{
- MCI_OPEN_PARMS mciOpenParms;
- MCI_PLAY_PARMS mciPlayParms;
- DWORD dwReturn;
- char filename[MAX_PATH];
-
- m_bRepeatMusic = bRepeat;
- m_playTime = 0.0f;
-
- if ( m_midiVolume == 0 ) return true;
-
- if ( m_bAudioTrack )
- {
- return PlayAudioTrack(rank);
- }
-
- if ( !m_bEnable ) return true;
- InitMidiVolume(m_midiVolume);
- m_lastMidiVolume = m_midiVolume;
-
- GetCurrentDir(filename, MAX_PATH-30);
- sprintf(filename+strlen(filename), "sound\\music%.3d.blp", rank-1);
-
- // Open the device by specifying the device and filename.
- // MCI will attempt to choose the MIDI mapper as the output port.
- mciOpenParms.lpstrDeviceType = "sequencer";
- mciOpenParms.lpstrElementName = filename;
- dwReturn = mciSendCommand(NULL,
- MCI_OPEN,
- MCI_OPEN_TYPE|MCI_OPEN_ELEMENT,
- (DWORD)(LPVOID)&mciOpenParms);
- if ( dwReturn != 0 )
- {
- mciGetErrorString(dwReturn, filename, 128);
- // Failed to open device. Don't close it; just return error.
- return false;
- }
-
- // The device opened successfully; get the device ID.
- m_MidiDeviceID = mciOpenParms.wDeviceID;
-
- // Begin playback.
- mciPlayParms.dwCallback = (DWORD)m_hWnd;
- dwReturn = mciSendCommand(m_MidiDeviceID,
- MCI_PLAY,
- MCI_NOTIFY,
- (DWORD)(LPVOID)&mciPlayParms);
- if ( dwReturn != 0 )
- {
- mciGetErrorString(dwReturn, filename, 128);
- StopMusic();
- return false;
- }
-
- m_MIDIMusic = rank;
- return true;
-}
-
-// Uses MCI to play a CD-audio track. The window procedure
-// is notified when playback is complete.
-// The rank parameter is in space [1..n] !
-// For CD mix (data/audio), it will be [2..n] !
-
-bool CSound::PlayAudioTrack(int rank)
-{
-#if _SOUNDTRACKS
- MCI_OPEN_PARMS mciOpenParms;
- MCI_PLAY_PARMS mciPlayParms;
- MCI_SET_PARMS mciSetParms;
- DWORD dwReturn;
- char filename[MAX_PATH];
- char device[10];
-
- if ( !m_bEnable ) return true;
-//? if ( m_midiVolume == 0 ) return true;
- InitAudioTrackVolume(m_midiVolume);
- m_lastMidiVolume = m_midiVolume;
-
- // Open the device by specifying the device and filename.
- // MCI will attempt to choose the MIDI mapper as the output port.
- memset(&mciOpenParms, 0, sizeof(MCI_OPEN_PARMS));
-//? mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
-//? dwReturn = mciSendCommand(NULL,
-//? MCI_OPEN,
-//? MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,
-//? (DWORD)(LPVOID)&mciOpenParms);
- mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
- if ( m_CDpath[0] == 0 )
- {
- dwReturn = mciSendCommand(NULL,
- MCI_OPEN,
- MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,
- (DWORD)(LPVOID)&mciOpenParms);
- }
- else
- {
- device[0] = m_CDpath[0];
- device[1] = ':';
- device[2] = 0;
- mciOpenParms.lpstrElementName = device;
- dwReturn = mciSendCommand(NULL,
- MCI_OPEN,
- MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_OPEN_ELEMENT,
- (DWORD)(LPVOID)&mciOpenParms);
- }
- if ( dwReturn != 0 )
- {
- mciGetErrorString(dwReturn, filename, 128);
- // Failed to open device. Don't close it; just return error.
- return false;
- }
-
- // The device opened successfully; get the device ID.
- m_MidiDeviceID = mciOpenParms.wDeviceID;
-
- // Set the time format to track/minute/second/frame (TMSF).
- memset(&mciSetParms, 0, sizeof(MCI_SET_PARMS));
- mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
- dwReturn = mciSendCommand(m_MidiDeviceID,
- MCI_SET,
- MCI_SET_TIME_FORMAT,
- (DWORD)&mciSetParms);
- if ( dwReturn != 0 )
- {
- mciGetErrorString(dwReturn, filename, 128);
- StopMusic();
- return false;
- }
-
- // Begin playback.
- memset(&mciPlayParms, 0, sizeof(MCI_PLAY_PARMS));
- mciPlayParms.dwCallback = (DWORD)m_hWnd;
- mciPlayParms.dwFrom = MCI_MAKE_TMSF(rank+0, 0, 0, 0);
- mciPlayParms.dwTo = MCI_MAKE_TMSF(rank+1, 0, 0, 0);
- dwReturn = mciSendCommand(m_MidiDeviceID,
- MCI_PLAY,
- MCI_NOTIFY|MCI_FROM|MCI_TO,
- (DWORD)(LPVOID)&mciPlayParms);
- if ( dwReturn != 0 )
- {
- mciGetErrorString(dwReturn, filename, 128);
- StopMusic();
- return false;
- }
-
- m_MIDIMusic = rank;
-#endif
- return true;
-}
-
-// Restart the MIDI player.
-
-bool CSound::RestartMusic()
-{
- if ( !m_bRepeatMusic ) return false;
-
- OutputDebugString("RestartMusic\n");
- if ( !m_bEnable ) return true;
-//? if ( m_midiVolume == 0 ) return true;
- if ( m_MIDIMusic == 0 ) return false;
- if ( m_playTime < 5.0f ) return false;
-
- return PlayMusic(m_MIDIMusic, true);
-}
-
-// Shuts down the MIDI player.
-
-void CSound::SuspendMusic()
-{
- if ( !m_bEnable ) return;
-
-//? if ( m_MidiDeviceID && m_midiVolume != 0 )
- if ( m_MidiDeviceID )
- {
- if ( m_bAudioTrack ) mciSendCommand(m_MidiDeviceID, MCI_STOP, 0, NULL);
- mciSendCommand(m_MidiDeviceID, MCI_CLOSE, 0, NULL);
- }
- m_MidiDeviceID = 0;
-}
-
-// Shuts down the MIDI player.
-
-void CSound::StopMusic()
-{
- SuspendMusic();
- m_MIDIMusic = 0;
-}
-
-// Returns true if the music is in progress.
-
-bool CSound::IsPlayingMusic()
-{
- return (m_MIDIMusic != 0);
-}
-
-// Adjusts the volume of currently music, if necessary.
-
-void CSound::AdaptVolumeMusic()
-{
- if ( m_midiVolume != m_lastMidiVolume )
- {
- if ( m_bAudioTrack )
- {
- InitAudioTrackVolume(m_midiVolume);
- }
- else
- {
- InitMidiVolume(m_midiVolume);
- }
- m_lastMidiVolume = m_midiVolume;
- RestartMusic();
- }
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// sound.cpp
+
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <d3dtypes.h>
+#include <dsound.h>
+#include <stdio.h>
+
+#include "common/language.h"
+#include "common/struct.h"
+#include "common/iman.h"
+#include "math/geometry.h"
+#include "math/conv.h"
+#include "old/math3d.h"
+#include "old/sound.h"
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+const int LXIMAGE = 640;
+const int LYIMAGE = 480;
+
+
+
+// Header .WAV file.
+
+struct WaveHeader
+{
+ BYTE RIFF[4]; // "RIFF"
+ DWORD dwSize; // size of data to follow
+ BYTE WAVE[4]; // "WAVE"
+ BYTE fmt_[4]; // "fmt "
+ DWORD dw16; // 16
+ WORD wOne_0; // 1
+ WORD wChnls; // number of Channels
+ DWORD dwSRate; // sample Rate
+ DWORD BytesPerSec; // sample Rate
+ WORD wBlkAlign; // 1
+ WORD BitsPerSample; // sample size
+ BYTE DATA[4]; // "DATA"
+ DWORD dwDSize; // number of Samples
+};
+
+
+
+
+// Displays an error DirectSound.
+
+void DisplayError(char *name, Sound sound, HRESULT err)
+{
+ char s[100];
+ unsigned int i = err;
+ if ( err == DS_OK ) return;
+ sprintf(s, "SoundError in %s, sound=%d err=%d\n", name, sound, i);
+ OutputDebugString(s);
+
+ if ( err == DSERR_ALLOCATED ) OutputDebugString("DSERR_ALLOCATED\n");
+ if ( err == DSERR_CONTROLUNAVAIL ) OutputDebugString("DSERR_CONTROLUNAVAIL\n");
+ if ( err == DSERR_INVALIDPARAM ) OutputDebugString("DSERR_INVALIDPARAM\n");
+ if ( err == DSERR_INVALIDCALL ) OutputDebugString("DSERR_INVALIDCALL\n");
+ if ( err == DSERR_GENERIC ) OutputDebugString("DSERR_GENERIC\n");
+ if ( err == DSERR_PRIOLEVELNEEDED ) OutputDebugString("DSERR_PRIOLEVELNEEDED\n");
+ if ( err == DSERR_OUTOFMEMORY ) OutputDebugString("DSERR_OUTOFMEMORY\n");
+ if ( err == DSERR_BADFORMAT ) OutputDebugString("DSERR_BADFORMAT\n");
+ if ( err == DSERR_UNSUPPORTED ) OutputDebugString("DSERR_UNSUPPORTED\n");
+ if ( err == DSERR_NODRIVER ) OutputDebugString("DSERR_NODRIVER\n");
+ if ( err == DSERR_ALREADYINITIALIZED ) OutputDebugString("DSERR_ALREADYINITIALIZED\n");
+ if ( err == DSERR_NOAGGREGATION ) OutputDebugString("DSERR_NOAGGREGATION\n");
+ if ( err == DSERR_BUFFERLOST ) OutputDebugString("DSERR_BUFFERLOST\n");
+ if ( err == DSERR_OTHERAPPHASPRIO ) OutputDebugString("DSERR_OTHERAPPHASPRIO\n");
+ if ( err == DSERR_UNINITIALIZED ) OutputDebugString("DSERR_UNINITIALIZED\n");
+ if ( err == DSERR_NOINTERFACE ) OutputDebugString("DSERR_NOINTERFACE\n");
+ if ( err == DSERR_ACCESSDENIED ) OutputDebugString("DSERR_ACCESSDENIED\n");
+}
+
+// Returns the name of the current folder.
+
+void GetCurrentDir(char *pName, int lg)
+{
+ int i;
+
+ strncpy(pName, _pgmptr, lg-1);
+ pName[lg-1] = 0;
+
+ lg = strlen(pName);
+ if ( lg == 0 ) return;
+
+ for ( i=0 ; i<lg ; i++ )
+ {
+ pName[i] = tolower(pName[i]);
+ }
+
+ while ( lg > 0 )
+ {
+ lg --;
+ if ( pName[lg] == '\\' )
+ {
+ pName[lg+1] = 0;
+ break;
+ }
+ }
+
+ if ( lg > 6 && strcmp(pName+lg-6, "\\debug\\") == 0 )
+ {
+ pName[lg-5] = 0; // ignores the folder \debug!
+ }
+
+ if ( lg > 6 && strcmp(pName+lg-6, "\\release\\") == 0 )
+ {
+ pName[lg-7] = 0; // ignores the folder \release !
+ }
+}
+
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+// Changes the volume of midi.
+// The volume is between 0 and 20!
+
+void InitMidiVolume(int volume)
+{
+ int nb, i, n;
+ MMRESULT result;
+ HMIDIOUT hmo = 0;
+
+ static int table[21] =
+ {
+ 0x00000000,
+ 0x11111111,
+ 0x22222222,
+ 0x33333333,
+ 0x44444444,
+ 0x55555555,
+ 0x66666666,
+ 0x77777777,
+ 0x88888888,
+ 0x99999999,
+ 0xAAAAAAAA,
+ 0xBBBBBBBB,
+ 0xCCCCCCCC,
+ 0xDDDDDDDD,
+ 0xEEEEEEEE,
+ 0xF222F222,
+ 0xF555F555,
+ 0xF777F777,
+ 0xFAAAFAAA,
+ 0xFDDDFDDD,
+ 0xFFFFFFFF,
+ };
+
+ if ( volume < 0 ) volume = 0;
+ if ( volume > MAXVOLUME ) volume = MAXVOLUME;
+
+ nb = midiOutGetNumDevs();
+ for ( i=0 ; i<nb ; i++ )
+ {
+ result = midiOutOpen((LPHMIDIOUT)&hmo, i, 0L, 0L, 0L);
+ if ( result != MMSYSERR_NOERROR )
+ {
+ continue;
+ }
+
+ result = midiOutSetVolume(hmo, table[volume]);
+ if ( result != MMSYSERR_NOERROR )
+ {
+ n = 1;
+ }
+ midiOutClose(hmo);
+ hmo = 0;
+ }
+}
+
+// Changes the volume of audio CD.
+// The volume is between 0 and 20!
+// Crashing in Vista. The current craft (if _SOUNDTRACKS = true) no longer crashes,
+// but this is not the correct volume which is modified!
+
+bool InitAudioTrackVolume(int volume)
+{
+#if _SOUNDTRACKS
+ MMRESULT rc; // Return code.
+ HMIXER hMixer; // Mixer handle used in mixer API calls.
+ MIXERCONTROL mxc; // Holds the mixer control data.
+ MIXERLINE mxl; // Holds the mixer line data.
+ MIXERLINECONTROLS mxlc; // Obtains the mixer control.
+
+ if ( volume < 0 ) volume = 0;
+ if ( volume > MAXVOLUME ) volume = MAXVOLUME;
+
+ // Open the mixer. This opens the mixer with a deviceID of 0. If you
+ // have a single sound card/mixer, then this will open it. If you have
+ // multiple sound cards/mixers, the deviceIDs will be 0, 1, 2, and
+ // so on.
+ rc = mixerOpen(&hMixer, 0,0,0,0);
+ if ( rc != MMSYSERR_NOERROR )
+ {
+ return false; // Couldn't open the mixer.
+ }
+
+ // Initialize MIXERLINE structure.
+ ZeroMemory(&mxl,sizeof(mxl));
+ mxl.cbStruct = sizeof(mxl);
+
+ // Specify the line you want to get. You are getting the input line
+ // here. If you want to get the output line, you need to use
+ // MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT.
+ mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
+
+ rc = mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl,
+ MIXER_GETLINEINFOF_COMPONENTTYPE);
+ if ( rc != MMSYSERR_NOERROR )
+ {
+ return false; // Couldn't get the mixer line.
+ }
+
+ // Get the control.
+ ZeroMemory(&mxlc, sizeof(mxlc));
+ mxlc.cbStruct = sizeof(mxlc);
+ mxlc.dwLineID = mxl.dwLineID;
+//? mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_PEAKMETER;
+//? mxlc.dwControlType = MIXERCONTROL_CONTROLF_UNIFORM;
+ mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
+ mxlc.cControls = 1;
+ mxlc.cbmxctrl = sizeof(mxc);
+ mxlc.pamxctrl = &mxc;
+ ZeroMemory(&mxc, sizeof(mxc));
+ mxc.cbStruct = sizeof(mxc);
+ rc = mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc,
+ MIXER_GETLINECONTROLSF_ONEBYTYPE);
+//? MIXER_GETLINECONTROLSF_ALL);
+ if ( rc != MMSYSERR_NOERROR )
+ {
+ return false; // Couldn't get the control.
+ }
+
+ // After successfully getting the peakmeter control, the volume range
+ // will be specified by mxc.Bounds.lMinimum to mxc.Bounds.lMaximum.
+
+ MIXERCONTROLDETAILS mxcd; // Gets the control values.
+ MIXERCONTROLDETAILS_SIGNED volStruct; // Gets the control values.
+
+ volStruct.lValue = volume*(mxc.Bounds.lMaximum-mxc.Bounds.lMinimum);
+ volStruct.lValue /= MAXVOLUME;
+ volStruct.lValue += mxc.Bounds.lMinimum;
+
+ // Initialize the MIXERCONTROLDETAILS structure
+ ZeroMemory(&mxcd, sizeof(mxcd));
+ mxcd.cbStruct = sizeof(mxcd);
+ mxcd.cbDetails = sizeof(volStruct);
+ mxcd.dwControlID = mxc.dwControlID;
+ mxcd.paDetails = &volStruct;
+ mxcd.cChannels = 1;
+
+ // Get the current value of the peakmeter control. Typically, you
+ // would set a timer in your program to query the volume every 10th
+ // of a second or so.
+ rc = mixerSetControlDetails((HMIXEROBJ)hMixer, &mxcd,
+ MIXER_SETCONTROLDETAILSF_VALUE);
+ if ( rc != MMSYSERR_NOERROR )
+ {
+ return false; // Couldn't get the current volume.
+ }
+#endif
+
+ return true;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+// Constructor.
+
+CSound::CSound(CInstanceManager* iMan)
+{
+ int i;
+
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_SOUND, this);
+
+ m_bEnable = false;
+ m_bState = false;
+ m_bAudioTrack = true;
+ m_ctrl3D = true;
+ m_bDebugMode = false;
+ m_MidiDeviceID = 0;
+ m_MIDIMusic = 0;
+ m_audioVolume = 20;
+ m_midiVolume = 15;
+ m_lastMidiVolume = 0;
+ m_listener = 0;
+ m_lastTime = 0.0f;
+ m_playTime = 0.0f;
+ m_uniqueStamp = 0;
+ m_maxSound = MAXSOUND;
+ m_eye = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_hWnd = 0;
+
+ m_lpDS = NULL;
+
+ ZeroMemory(m_channel, sizeof(SoundChannel)*MAXSOUND);
+ for ( i=0 ; i<MAXSOUND ; i++ )
+ {
+ m_channel[i].bUsed = false;
+ }
+
+ for ( i=0 ; i<MAXFILES ; i++ )
+ {
+ m_files[i] = 0;
+ }
+}
+
+// Destructor.
+
+CSound::~CSound()
+{
+ int i;
+
+ if ( m_bEnable )
+ {
+ InitMidiVolume(15); // gives an average volume!
+ InitAudioTrackVolume(15); // gives an average volume!
+ }
+
+ for ( i=0 ; i<MAXSOUND ; i++ )
+ {
+ if ( m_channel[i].bUsed )
+ {
+ m_channel[i].soundBuffer->Stop();
+ m_channel[i].soundBuffer->Release();
+ m_channel[i].soundBuffer = 0;
+ m_channel[i].bUsed = false;
+ }
+ }
+
+ if ( m_listener != NULL )
+ {
+ m_listener->Release();
+ m_listener = NULL;
+ }
+
+ if ( m_lpDS != NULL )
+ {
+ m_lpDS->Release();
+ m_lpDS = NULL;
+ }
+}
+
+
+// Specifies whether you are in debug mode.
+
+void CSound::SetDebugMode(bool bMode)
+{
+ m_bDebugMode = bMode;
+}
+
+
+// Initializes DirectSound.
+
+bool CSound::Create(HWND hWnd, bool b3D)
+{
+ LPDIRECTSOUNDBUFFER primary;
+ DSBUFFERDESC dsbdesc;
+ DSCAPS dscaps;
+ WAVEFORMATEX wfx;
+ HRESULT hr;
+
+ if ( !DirectSoundCreate(NULL, &m_lpDS, NULL) == DS_OK )
+ {
+ OutputDebugString("Fatal error: DirectSoundCreate\n");
+ m_bEnable = false;
+ return false;
+ }
+
+//? m_lpDS->SetCooperativeLevel(hWnd, DSSCL_NORMAL);
+ m_lpDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);
+
+ if ( !RetSound3DCap() ) b3D = false;
+
+ m_ctrl3D = false;
+ if ( b3D )
+ {
+ // Obtain primary buffer, asking it for 3D control.
+ ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
+ dsbdesc.dwSize = sizeof(DSBUFFERDESC);
+ dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
+ hr = m_lpDS->CreateSoundBuffer( &dsbdesc, &primary, NULL );
+ if ( hr == S_OK )
+ {
+ m_ctrl3D = true;
+ }
+ }
+
+ if ( !m_ctrl3D )
+ {
+ // Obtain primary buffer, without 3D control.
+ ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
+ dsbdesc.dwSize = sizeof(DSBUFFERDESC);
+ dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
+ hr = m_lpDS->CreateSoundBuffer( &dsbdesc, &primary, NULL );
+ if ( hr != S_OK )
+ {
+ return false;
+ }
+ m_ctrl3D = false;
+ }
+
+ if ( m_ctrl3D )
+ {
+ hr = primary->QueryInterface( IID_IDirectSound3DListener,
+ (VOID**)&m_listener );
+ if ( hr != S_OK )
+ {
+ primary->Release();
+ return false;
+ }
+ }
+
+ // Set primary buffer format to 44kHz and 16-bit output.
+ ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
+ wfx.wFormatTag = WAVE_FORMAT_PCM;
+ wfx.nChannels = 2;
+ wfx.nSamplesPerSec = 22050;
+//? wfx.nSamplesPerSec = 44100;
+ wfx.wBitsPerSample = 16;
+ wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
+ wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
+ hr = primary->SetFormat(&wfx);
+ if ( hr != S_OK )
+ {
+ DisplayError("SetFormat", SOUND_CLICK, hr);
+ }
+
+ // Release the primary buffer, since it is not need anymore.
+ primary->Release();
+
+ // Search the maximum possible voices.
+ if ( m_ctrl3D )
+ {
+ ZeroMemory( &dscaps, sizeof(DSCAPS) );
+ dscaps.dwSize = sizeof(DSCAPS);
+ hr = m_lpDS->GetCaps(&dscaps);
+ if ( hr == DS_OK )
+ {
+ m_maxSound = dscaps.dwMaxHwMixingAllBuffers;
+ if ( dscaps.dwMaxHw3DAllBuffers > 0 &&
+ m_maxSound > (int)dscaps.dwMaxHw3DAllBuffers )
+ {
+ m_maxSound = dscaps.dwMaxHw3DAllBuffers;
+ }
+ if ( m_maxSound > MAXSOUND ) m_maxSound = MAXSOUND;
+ }
+ }
+
+ m_bEnable = true;
+ m_hWnd = hWnd;
+ return true;
+}
+
+
+// Indicates whether to play sounds in 3D or not.
+
+void CSound::SetSound3D(bool bMode)
+{
+ StopAll();
+
+ if ( m_listener != NULL )
+ {
+ m_listener->Release();
+ m_listener = NULL;
+ }
+
+ if ( m_lpDS != NULL )
+ {
+ m_lpDS->Release();
+ m_lpDS = NULL;
+ }
+
+ Create(m_hWnd, bMode);
+}
+
+bool CSound::RetSound3D()
+{
+ return m_ctrl3D;
+}
+
+// Indicates whether it is possible to play sounds in 3D.
+
+bool CSound::RetSound3DCap()
+{
+ DSCAPS dscaps;
+ HRESULT hr;
+
+ ZeroMemory( &dscaps, sizeof(DSCAPS) );
+ dscaps.dwSize = sizeof(DSCAPS);
+ hr = m_lpDS->GetCaps(&dscaps);
+ if ( hr != DS_OK ) return false;
+
+ return ( dscaps.dwMaxHw3DAllBuffers > 0 );
+}
+
+
+
+// Returns the state of DirectSound.
+
+bool CSound::RetEnable()
+{
+ return m_bEnable;
+}
+
+
+// Switches on or off the sound.
+
+void CSound::SetState(bool bState)
+{
+ m_bState = bState;
+}
+
+// Specifies the pathname to the CD.
+
+void CSound::SetCDpath(char *path)
+{
+ strcpy(m_CDpath, path);
+}
+
+// Switches on or off the CD-audio music.
+
+void CSound::SetAudioTrack(bool bAudio)
+{
+ m_bAudioTrack = bAudio;
+}
+
+
+// Manages volumes of audio (. Wav) and midi (. Mid).
+
+void CSound::SetAudioVolume(int volume)
+{
+ m_audioVolume = volume;
+}
+
+int CSound::RetAudioVolume()
+{
+ if ( !m_bEnable ) return 0;
+ return m_audioVolume;
+}
+
+void CSound::SetMidiVolume(int volume)
+{
+ m_midiVolume = volume;
+
+ if ( m_bAudioTrack )
+ {
+ InitAudioTrackVolume(m_midiVolume);
+ }
+}
+
+int CSound::RetMidiVolume()
+{
+ if ( !m_bEnable ) return 0;
+ return m_midiVolume;
+}
+
+
+// Reads a file.
+
+bool CSound::ReadFile(Sound sound, char *metaname, char *filename)
+{
+ WaveHeader wavHdr;
+ DWORD size;
+ int err;
+
+ // Open the wave file.
+ err = g_metafile.Open(metaname, filename);
+ if ( err != 0 ) return false;
+
+ // Read in the wave header.
+ g_metafile.Read(&wavHdr, sizeof(wavHdr));
+
+ // Figure out the size of the data region.
+ size = wavHdr.dwDSize;
+
+ if ( m_files[sound] != 0 )
+ {
+ free(m_files[sound]);
+ }
+ m_files[sound] = (char*)malloc(sizeof(WaveHeader)+size);
+
+ memcpy(m_files[sound], &wavHdr, sizeof(WaveHeader));
+ g_metafile.Read(m_files[sound]+sizeof(WaveHeader), size);
+
+ // Close out the wave file.
+ g_metafile.Close();
+ return true;
+}
+
+// Hides all sound files (. Wav).
+
+void CSound::CacheAll()
+{
+ int i;
+ char meta[50];
+ char name[50];
+
+ if ( !m_bEnable ) return;
+
+ if ( m_bDebugMode )
+ {
+ strcpy(meta, "");
+ }
+ else
+ {
+#if _SCHOOL
+ strcpy(meta, "ceebot3.dat");
+#else
+ strcpy(meta, "colobot3.dat");
+#endif
+ }
+
+ for ( i=0 ; i<MAXFILES ; i++ )
+ {
+ if ( m_bDebugMode )
+ {
+ sprintf(name, "sound\\sound%.3d.wav", i);
+ }
+ else
+ {
+ sprintf(name, "sound%.3d.wav", i);
+ }
+ if ( !ReadFile((Sound)i, meta, name) ) break;
+ }
+}
+
+
+// Return the priority of a sound.
+// The higher the value, the greater the sound is important.
+
+int CSound::RetPriority(Sound sound)
+{
+ if ( sound == SOUND_FLYh ||
+ sound == SOUND_FLY ||
+ sound == SOUND_MOTORw ||
+ sound == SOUND_MOTORt ||
+ sound == SOUND_MOTORr ||
+ sound == SOUND_MOTORs ||
+ sound == SOUND_SLIDE ||
+ sound == SOUND_ERROR )
+ {
+ return 30;
+ }
+
+ if ( sound == SOUND_CONVERT ||
+ sound == SOUND_ENERGY ||
+ sound == SOUND_DERRICK ||
+ sound == SOUND_STATION ||
+ sound == SOUND_REPAIR ||
+ sound == SOUND_RESEARCH ||
+ sound == SOUND_BURN ||
+ sound == SOUND_BUILD ||
+ sound == SOUND_TREMBLE ||
+ sound == SOUND_NUCLEAR ||
+ sound == SOUND_EXPLO ||
+ sound == SOUND_EXPLOl ||
+ sound == SOUND_EXPLOlp ||
+ sound == SOUND_EXPLOp ||
+ sound == SOUND_EXPLOi )
+ {
+ return 20;
+ }
+
+ if ( sound == SOUND_BLUP ||
+ sound == SOUND_INSECTs ||
+ sound == SOUND_INSECTa ||
+ sound == SOUND_INSECTb ||
+ sound == SOUND_INSECTw ||
+ sound == SOUND_INSECTm ||
+ sound == SOUND_PSHHH ||
+ sound == SOUND_EGG )
+ {
+ return 0;
+ }
+
+ return 10;
+}
+
+// Seeks a free buffer.
+
+bool CSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded)
+{
+ DWORD status;
+ int i, priority;
+
+ priority = RetPriority(sound);
+
+#if 1
+ // Seeks a channel used which sound is stopped.
+ for ( i=0 ; i<m_maxSound ; i++ )
+ {
+ if ( !m_channel[i].bUsed ) continue;
+ if ( m_channel[i].type != sound ) continue;
+
+ m_channel[i].soundBuffer->GetStatus(&status);
+ if ( (status&DSBSTATUS_PLAYING) == 0 )
+ {
+ m_channel[i].priority = priority;
+ m_channel[i].uniqueStamp = m_uniqueStamp++;
+ channel = i;
+ bAlreadyLoaded = true;
+ return true;
+ }
+ }
+#endif
+
+ // Seeks a channel completely free.
+ for ( i=0 ; i<m_maxSound ; i++ )
+ {
+ if ( !m_channel[i].bUsed )
+ {
+ m_channel[i].priority = priority;
+ m_channel[i].uniqueStamp = m_uniqueStamp++;
+ channel = i;
+ bAlreadyLoaded = false;
+ return true;
+ }
+ }
+
+ // Seeks a channel used which sound is stopped.
+ for ( i=0 ; i<m_maxSound ; i++ )
+ {
+ if ( !m_channel[i].bUsed ) continue;
+
+ m_channel[i].soundBuffer->GetStatus(&status);
+ if ( (status&DSBSTATUS_PLAYING) == 0 )
+ {
+ m_channel[i].soundBuffer->Release();
+ m_channel[i].soundBuffer = 0;
+ m_channel[i].priority = priority;
+ m_channel[i].uniqueStamp = m_uniqueStamp++;
+
+ channel = i;
+ bAlreadyLoaded = false;
+ return true;
+ }
+ }
+
+ // Seeks a lower priority channel used.
+ for ( i=0 ; i<m_maxSound ; i++ )
+ {
+ if ( !m_channel[i].bUsed ) continue;
+ if ( m_channel[i].priority >= priority ) continue;
+
+ m_channel[i].soundBuffer->Stop();
+ m_channel[i].soundBuffer->Release();
+ m_channel[i].soundBuffer = 0;
+ m_channel[i].priority = priority;
+ m_channel[i].uniqueStamp = m_uniqueStamp++;
+
+ channel = i;
+ bAlreadyLoaded = false;
+ return true;
+ }
+
+ // Seeks a channel used the same or lower priority.
+ for ( i=0 ; i<m_maxSound ; i++ )
+ {
+ if ( !m_channel[i].bUsed ) continue;
+ if ( m_channel[i].priority > priority ) continue;
+
+ m_channel[i].soundBuffer->Stop();
+ m_channel[i].soundBuffer->Release();
+ m_channel[i].soundBuffer = 0;
+ m_channel[i].priority = priority;
+ m_channel[i].uniqueStamp = m_uniqueStamp++;
+
+ channel = i;
+ bAlreadyLoaded = false;
+ return true;
+ }
+
+ char s[100];
+ sprintf(s, "Sound %d forget (priority=%d)\n", sound, priority);
+ OutputDebugString(s);
+
+ return false;
+}
+
+// Reads in data from a wave file.
+
+bool CSound::ReadData(LPDIRECTSOUNDBUFFER lpDSB, Sound sound, DWORD size)
+{
+ LPVOID pData1;
+ DWORD dwData1Size;
+ LPVOID pData2;
+ DWORD dwData2Size;
+ HRESULT hr;
+
+ // Lock data in buffer for writing.
+ hr = lpDSB->Lock(0, size, &pData1, &dwData1Size, &pData2, &dwData2Size, DSBLOCK_FROMWRITECURSOR);
+ if ( hr != DS_OK )
+ {
+ return false;
+ }
+
+ // Read in first chunk of data.
+ if ( dwData1Size > 0 )
+ {
+ memcpy(pData1, m_files[sound]+sizeof(WaveHeader), dwData1Size);
+ }
+
+ // Read in second chunk if necessary.
+ if ( dwData2Size > 0 )
+ {
+ memcpy(pData2, m_files[sound]+sizeof(WaveHeader)+dwData1Size, dwData2Size);
+ }
+
+ // Unlock data in buffer.
+ hr = lpDSB->Unlock(pData1, dwData1Size, pData2, dwData2Size);
+ if ( hr != DS_OK )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Creates a DirectSound buffer.
+
+bool CSound::CreateSoundBuffer(int channel, DWORD size, DWORD freq,
+ DWORD bitsPerSample, DWORD blkAlign,
+ bool bStereo)
+{
+ PCMWAVEFORMAT pcmwf;
+ DSBUFFERDESC dsbdesc;
+ DS3DBUFFER bufferParams; // 3D buffer properties
+ HRESULT hr;
+
+ // Set up wave format structure.
+ memset( &pcmwf, 0, sizeof(PCMWAVEFORMAT) );
+ pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
+ pcmwf.wf.nChannels = bStereo ? 2 : 1;
+ pcmwf.wf.nSamplesPerSec = freq;
+ pcmwf.wf.nBlockAlign = (WORD)blkAlign;
+ pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
+ pcmwf.wBitsPerSample = (WORD)bitsPerSample;
+
+ // Set up DSBUFFERDESC structure.
+ memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
+ dsbdesc.dwSize = sizeof(DSBUFFERDESC);
+ if ( m_ctrl3D )
+ {
+ dsbdesc.dwFlags = DSBCAPS_CTRL3D|DSBCAPS_MUTE3DATMAXDISTANCE|
+ DSBCAPS_LOCDEFER|
+ DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLFREQUENCY;
+ }
+ else
+ {
+ dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN|DSBCAPS_CTRLFREQUENCY;
+ }
+ dsbdesc.dwBufferBytes = size;
+ dsbdesc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf;
+
+ hr = m_lpDS->CreateSoundBuffer(&dsbdesc, &m_channel[channel].soundBuffer, NULL);
+ if ( hr != DS_OK ) return false;
+
+ if ( m_ctrl3D )
+ {
+ hr = m_channel[channel].soundBuffer->QueryInterface
+ (
+ IID_IDirectSound3DBuffer,
+ (VOID**)&m_channel[channel].soundBuffer3D
+ );
+ if ( hr != DS_OK ) return false;
+ }
+
+ m_channel[channel].bUsed = true;
+ m_channel[channel].bMute = false;
+ return true;
+}
+
+// Creates a DirectSound buffer from a wave file.
+
+bool CSound::CreateBuffer(int channel, Sound sound)
+{
+ WaveHeader* wavHdr;
+ DWORD size;
+ bool bStereo;
+
+ if ( m_files[sound] == 0 ) return false;
+
+ wavHdr = (WaveHeader*)m_files[sound];
+ size = wavHdr->dwDSize;
+ bStereo = wavHdr->wChnls > 1 ? true : false;
+
+ // Create the sound buffer for the wave file.
+ if ( !CreateSoundBuffer(channel, size, wavHdr->dwSRate,
+ wavHdr->BitsPerSample, wavHdr->wBlkAlign, bStereo) )
+ {
+ return false;
+ }
+
+ // Read the data for the wave file into the sound buffer.
+ if ( !ReadData(m_channel[channel].soundBuffer, sound, size) )
+ {
+ return false;
+ }
+
+ m_channel[channel].type = sound;
+
+ // Close out the wave file.
+ return true;
+}
+
+// Calculates the volume and pan of a sound, non-3D mode.
+
+void CSound::ComputeVolumePan2D(int channel, const Math::Vector &pos)
+{
+ float dist, a, g;
+
+ if ( pos.x == m_eye.x &&
+ pos.y == m_eye.y &&
+ pos.z == m_eye.z )
+ {
+ m_channel[channel].volume = 1.0f; // maximum volume
+ m_channel[channel].pan = 0.0f; // at the center
+ return;
+ }
+
+#if _TEEN
+ dist = Math::Distance(pos, m_eye);
+ if ( dist >= 210.0f ) // very far?
+ {
+ m_channel[channel].volume = 0.0f; // silence
+ m_channel[channel].pan = 0.0f; // at the center
+ return;
+ }
+ if ( dist <= 10.0f ) // very close?
+ {
+ m_channel[channel].volume = 1.0f; // maximum volume
+ m_channel[channel].pan = 0.0f; // at the center
+ return;
+ }
+ m_channel[channel].volume = 1.0f-((dist-10.0f)/200.0f);
+#else
+ dist = Math::Distance(pos, m_eye);
+ if ( dist >= 110.0f ) // very far?
+ {
+ m_channel[channel].volume = 0.0f; // silence
+ m_channel[channel].pan = 0.0f; // at the center
+ return;
+ }
+ if ( dist <= 10.0f ) // very close?
+ {
+ m_channel[channel].volume = 1.0f; // maximum volume
+ m_channel[channel].pan = 0.0f; // at the center
+ return;
+ }
+ m_channel[channel].volume = 1.0f-((dist-10.0f)/100.0f);
+#endif
+
+ a = Math::RotateAngle(m_lookat.x-m_eye.x, m_eye.z-m_lookat.z);
+ g = Math::RotateAngle(pos.x-m_eye.x, m_eye.z-pos.z);
+ m_channel[channel].pan = sinf(Math::Direction(a, g));
+}
+
+// Sounds in the middle.
+// Returns the associated channel or -1.
+
+int CSound::Play(Sound sound, float amplitude, float frequency, bool bLoop)
+{
+ return Play(sound, m_lookat, amplitude, frequency, bLoop);
+}
+
+// Sounds at a given position.
+// Returns the associated channel or -1.
+
+int CSound::Play(Sound sound, Math::Vector pos,
+ float amplitude, float frequency, bool bLoop)
+{
+ DS3DBUFFER sb;
+ int channel, iVolume, iPan, iFreq, uniqueStamp;
+ bool bAlreadyLoaded;
+ DWORD flag, freq;
+ HRESULT err;
+
+ if ( !m_bEnable ) return -1;
+ if ( !m_bState || m_audioVolume == 0 ) return -1;
+
+//? if ( Math::Distance(pos, m_eye) > 100.0f ) return -1;
+
+ if ( !SearchFreeBuffer(sound, channel, bAlreadyLoaded) ) return -1;
+
+ if ( !bAlreadyLoaded )
+ {
+ if ( !CreateBuffer(channel, sound) )
+ {
+ if ( m_channel[channel].bUsed &&
+ m_channel[channel].soundBuffer != 0 )
+ {
+ m_channel[channel].soundBuffer->Release();
+ m_channel[channel].soundBuffer = 0;
+ }
+ m_channel[channel].bUsed = false;
+ return -1;
+ }
+ }
+
+ m_channel[channel].pos = pos;
+
+ if ( m_ctrl3D )
+ {
+ m_channel[channel].volume = 1.0f;
+ m_channel[channel].pan = 0.0f;
+ }
+ else
+ {
+ ComputeVolumePan2D(channel, pos);
+ }
+
+#if 0
+ DWORD status;
+ m_channel[channel].soundBuffer->GetStatus(&status);
+ char s[100];
+ sprintf(s, "Play sound=%d status=%d channel=%d flag=%d\n", sound, status, channel, bAlreadyLoaded);
+ OutputDebugString(s);
+#endif
+
+ m_channel[channel].oper[0].bUsed = false;
+ m_channel[channel].startAmplitude = amplitude;
+ m_channel[channel].startFrequency = frequency;
+ m_channel[channel].changeFrequency = 1.0f;
+
+ if ( m_ctrl3D )
+ {
+ sb.dwSize = sizeof(DS3DBUFFER);
+ err = m_channel[channel].soundBuffer3D->GetAllParameters(&sb);
+ DisplayError("GetAllParameters", sound, err);
+
+ sb.vPosition = VEC_TO_D3DVEC(pos);
+//? sb.dwInsideConeAngle = 90;
+//? sb.dwOutsideConeAngle = 180;
+//? sb.vConeOrientation = Math::Vector(0.0f, 1.0f, 0.0f);
+ sb.lConeOutsideVolume = DSBVOLUME_MIN;
+#if _TEEN
+ sb.flMinDistance = 50.0f;
+#else
+ sb.flMinDistance = 20.0f;
+#endif
+ sb.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
+
+ err = m_channel[channel].soundBuffer3D->SetAllParameters(&sb, DS3D_IMMEDIATE);
+ DisplayError("SetAllParameters", sound, err);
+ }
+
+ amplitude *= m_channel[channel].volume;
+ amplitude *= (float)m_audioVolume/MAXVOLUME;
+ iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
+ if ( iVolume > 0 ) iVolume = 0;
+ err = m_channel[channel].soundBuffer->SetVolume(iVolume);
+ DisplayError("SetVolume", sound, err);
+
+ if ( !m_ctrl3D )
+ {
+ iPan = (int)(m_channel[channel].pan*10000.0f);
+ err = m_channel[channel].soundBuffer->SetPan(iPan);
+ DisplayError("SetPan", sound, err);
+ }
+
+ if ( !bAlreadyLoaded )
+ {
+ err = m_channel[channel].soundBuffer->GetFrequency(&freq);
+ DisplayError("GetFrequency", sound, err);
+ m_channel[channel].initFrequency = freq;
+ }
+ iFreq = (int)(frequency*m_channel[channel].initFrequency);
+ err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
+ DisplayError("SetFrequency", sound, err);
+
+ err = m_channel[channel].soundBuffer->SetCurrentPosition(0);
+ DisplayError("SetCurrentPosition", sound, err);
+
+ flag = bLoop?DSBPLAY_LOOPING:0;
+//? flag |= DSBPLAY_LOCHARDWARE|DSBPLAY_TERMINATEBY_DISTANCE;
+//? flag |= DSBPLAY_TERMINATEBY_DISTANCE;
+ err = m_channel[channel].soundBuffer->Play(0, 0, flag);
+ DisplayError("Play", sound, err);
+ if ( err == DSERR_BADFORMAT )
+ {
+ iFreq = m_channel[channel].initFrequency;
+ err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
+ DisplayError("SetFrequency (repeat)", sound, err);
+
+ err = m_channel[channel].soundBuffer->Play(0, 0, flag);
+ DisplayError("Play (repeat)", sound, err);
+ }
+
+ uniqueStamp = m_channel[channel].uniqueStamp;
+ return channel | ((uniqueStamp&0xffff)<<16);
+}
+
+// Check a channel number.
+// Adapts the channel, so it can be used as an offset in m_channel.
+
+bool CSound::CheckChannel(int &channel)
+{
+ int uniqueStamp;
+
+ uniqueStamp = (channel>>16)&0xffff;
+ channel &= 0xffff;
+
+ if ( !m_bEnable ) return false;
+ if ( !m_bState || m_audioVolume == 0 ) return false;
+
+ if ( channel < 0 || channel >= m_maxSound ) return false;
+ if ( !m_channel[channel].bUsed ) return false;
+
+ if ( m_channel[channel].uniqueStamp != uniqueStamp ) return false;
+
+ return true;
+}
+
+// Removes all envelopes.
+
+bool CSound::FlushEnvelope(int channel)
+{
+ if ( !CheckChannel(channel) ) return false;
+
+ m_channel[channel].oper[0].bUsed = false;
+ return true;
+}
+
+// Adds an operation envelope.
+
+bool CSound::AddEnvelope(int channel, float amplitude, float frequency,
+ float time, SoundNext oper)
+{
+ int i;
+
+ if ( !CheckChannel(channel) ) return false;
+
+ for ( i=0 ; i<MAXOPER ; i++ )
+ {
+ if ( m_channel[channel].oper[i].bUsed ) continue;
+
+ m_channel[channel].oper[i].bUsed = true;
+ m_channel[channel].oper[i].finalAmplitude = amplitude;
+ m_channel[channel].oper[i].finalFrequency = frequency;
+ m_channel[channel].oper[i].totalTime = time;
+ m_channel[channel].oper[i].currentTime = 0;
+ m_channel[channel].oper[i].nextOper = oper;
+
+ if ( i < MAXOPER-1 )
+ {
+ m_channel[channel].oper[i+1].bUsed = false;
+ }
+ return true;
+ }
+ return false;
+}
+
+// Changes the position of a sound.
+
+bool CSound::Position(int channel, Math::Vector pos)
+{
+ float amplitude, pan;
+ int iVolume, iPan;
+ HRESULT err;
+
+ if ( !CheckChannel(channel) ) return false;
+
+ m_channel[channel].pos = pos;
+
+ if ( m_ctrl3D )
+ {
+ m_channel[channel].soundBuffer3D->SetPosition(pos.x, pos.y, pos.z, DS3D_DEFERRED);
+ }
+ else
+ {
+ ComputeVolumePan2D(channel, pos);
+
+ if ( !m_channel[channel].oper[0].bUsed )
+ {
+ amplitude = m_channel[channel].startAmplitude;
+ amplitude *= m_channel[channel].volume;
+ amplitude *= (float)m_audioVolume/MAXVOLUME;
+ iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
+ if ( iVolume > 0 ) iVolume = 0;
+ err = m_channel[channel].soundBuffer->SetVolume(iVolume);
+ DisplayError("SetVolume", m_channel[channel].type, err);
+ }
+
+ pan = m_channel[channel].pan;
+ iPan = (int)(pan*10000.0f);
+ err = m_channel[channel].soundBuffer->SetPan(iPan);
+ DisplayError("SetPan", m_channel[channel].type, err);
+ }
+ return true;
+}
+
+// Changes the frequency of a sound.
+// 0.5 down of an octave and 2.0 up of an octave.
+
+bool CSound::Frequency(int channel, float frequency)
+{
+ HRESULT err;
+ int iFreq;
+
+ if ( !CheckChannel(channel) ) return false;
+
+ m_channel[channel].changeFrequency = frequency;
+
+ if ( !m_channel[channel].oper[0].bUsed )
+ {
+ iFreq = (int)(frequency*m_channel[channel].initFrequency);
+ err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
+ DisplayError("Frequency", m_channel[channel].type, err);
+ }
+
+ return true;
+}
+
+// Stops sound.
+
+bool CSound::Stop(int channel)
+{
+ if ( !CheckChannel(channel) ) return false;
+
+ m_channel[channel].soundBuffer->Stop();
+ return true;
+}
+
+// Stops all sounds.
+
+bool CSound::StopAll()
+{
+ DWORD status;
+ int i;
+
+ for ( i=0 ; i<MAXSOUND ; i++ )
+ {
+ if ( !m_channel[i].bUsed ) continue;
+
+ m_channel[i].soundBuffer->GetStatus(&status);
+ if ( (status&DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING )
+ {
+ m_channel[i].soundBuffer->Stop();
+ }
+ m_channel[i].soundBuffer->Stop();
+ m_channel[i].soundBuffer->Release();
+ m_channel[i].soundBuffer = 0;
+
+ m_channel[i].bUsed = false;
+ }
+ return true;
+}
+
+// Silent all sounds.
+
+bool CSound::MuteAll(bool bMute)
+{
+ int i;
+
+ for ( i=0 ; i<MAXSOUND ; i++ )
+ {
+ if ( !m_channel[i].bUsed ) continue;
+
+ m_channel[i].bMute = bMute;
+ }
+ return true;
+}
+
+
+// Passes the following operation for a channel.
+
+void CSound::OperNext(int channel)
+{
+ int i;
+
+ m_channel[channel].startAmplitude = m_channel[channel].oper[0].finalAmplitude;
+ m_channel[channel].startFrequency = m_channel[channel].oper[0].finalFrequency;
+
+ for ( i=0 ; i<MAXOPER-1 ; i++ )
+ {
+ if ( !m_channel[channel].oper[i+1].bUsed ) break;
+
+ m_channel[channel].oper[i] = m_channel[channel].oper[i+1];
+ }
+
+ m_channel[channel].oper[i].bUsed = false;
+}
+
+// Updates the sound buffers.
+
+void CSound::FrameMove(float rTime)
+{
+ HRESULT err;
+ SoundNext next;
+ float progress, volume, freq;
+ int i, iVolume, iFreq;
+
+ m_playTime += rTime;
+
+ for ( i=0 ; i<m_maxSound ; i++ )
+ {
+ if ( !m_channel[i].bUsed ) continue;
+ if ( !m_channel[i].oper[0].bUsed ) continue;
+
+ if ( m_channel[i].bMute )
+ {
+ m_channel[i].soundBuffer->SetVolume(-10000); // silence
+ continue;
+ }
+
+ m_channel[i].oper[0].currentTime += rTime;
+
+ progress = m_channel[i].oper[0].currentTime / m_channel[i].oper[0].totalTime;
+ if ( progress > 1.0f ) progress = 1.0f;
+
+ volume = progress;
+ volume *= m_channel[i].oper[0].finalAmplitude-m_channel[i].startAmplitude;
+ volume += m_channel[i].startAmplitude;
+ volume *= m_channel[i].volume;
+ volume *= (float)m_audioVolume/MAXVOLUME;
+ iVolume = (int)((powf(volume, 0.2f)-1.0f)*10000.0f);
+ if ( iVolume > 0 ) iVolume = 0;
+ m_channel[i].soundBuffer->SetVolume(iVolume);
+
+ freq = progress;
+ freq *= m_channel[i].oper[0].finalFrequency-m_channel[i].startFrequency;
+ freq += m_channel[i].startFrequency;
+ freq *= m_channel[i].changeFrequency;
+ iFreq = (int)(freq*m_channel[i].initFrequency);
+ err = m_channel[i].soundBuffer->SetFrequency(iFreq);
+ DisplayError("FrameMove::Frequency", m_channel[i].type, err);
+
+ if ( m_channel[i].oper[0].currentTime >=
+ m_channel[i].oper[0].totalTime )
+ {
+ next = m_channel[i].oper[0].nextOper;
+
+ if ( next == SOPER_LOOP )
+ {
+ m_channel[i].oper[0].currentTime = 0.0f;
+ }
+ else
+ {
+ OperNext(i);
+
+ if ( next == SOPER_STOP )
+ {
+ m_channel[i].soundBuffer->Stop();
+ }
+ }
+ }
+ }
+
+ m_lastTime += rTime;
+ if ( m_lastTime >= 0.05f && m_listener != 0 )
+ {
+ m_lastTime = 0.0f;
+ m_listener->CommitDeferredSettings();
+ }
+}
+
+// Specifies the position of the listener.
+// Must be called whenever the camera moves.
+
+void CSound::SetListener(Math::Vector eye, Math::Vector lookat)
+{
+ DS3DLISTENER listenerParams;
+ HRESULT err;
+ float amplitude, pan;
+ int i, iVolume, iPan;
+
+ m_eye = eye;
+ m_lookat = lookat;
+
+ if ( m_listener == 0 )
+ {
+ if ( m_ctrl3D ) return;
+
+ for ( i=0 ; i<m_maxSound ; i++ )
+ {
+ if ( !m_channel[i].bUsed ) continue;
+
+ ComputeVolumePan2D(i, m_channel[i].pos);
+
+ if ( !m_channel[i].oper[0].bUsed )
+ {
+ amplitude = m_channel[i].startAmplitude;
+ amplitude *= m_channel[i].volume;
+ amplitude *= (float)m_audioVolume/MAXVOLUME;
+ iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
+ if ( iVolume > 0 ) iVolume = 0;
+ err = m_channel[i].soundBuffer->SetVolume(iVolume);
+ DisplayError("SetVolume", m_channel[i].type, err);
+ }
+
+ pan = m_channel[i].pan;
+ iPan = (int)(pan*10000.0f);
+ err = m_channel[i].soundBuffer->SetPan(iPan);
+ DisplayError("SetPan", m_channel[i].type, err);
+ }
+ return;
+ }
+
+ // Get listener parameters.
+ listenerParams.dwSize = sizeof(DS3DLISTENER);
+ m_listener->GetAllParameters(&listenerParams);
+
+ listenerParams.vPosition = VEC_TO_D3DVEC(eye);
+ listenerParams.vOrientFront = VEC_TO_D3DVEC(lookat-eye);
+ listenerParams.vOrientTop = D3DVECTOR(0.0f, 1.0f, 0.0f);
+ listenerParams.flDistanceFactor = 10.0f;
+ listenerParams.flRolloffFactor = 1.0f;
+
+ m_listener->SetAllParameters(&listenerParams, DS3D_DEFERRED);
+}
+
+
+
+
+// Uses MCI to play a MIDI file. The window procedure
+// is notified when playback is complete.
+
+bool CSound::PlayMusic(int rank, bool bRepeat)
+{
+ MCI_OPEN_PARMS mciOpenParms;
+ MCI_PLAY_PARMS mciPlayParms;
+ DWORD dwReturn;
+ char filename[MAX_PATH];
+
+ m_bRepeatMusic = bRepeat;
+ m_playTime = 0.0f;
+
+ if ( m_midiVolume == 0 ) return true;
+
+ if ( m_bAudioTrack )
+ {
+ return PlayAudioTrack(rank);
+ }
+
+ if ( !m_bEnable ) return true;
+ InitMidiVolume(m_midiVolume);
+ m_lastMidiVolume = m_midiVolume;
+
+ GetCurrentDir(filename, MAX_PATH-30);
+ sprintf(filename+strlen(filename), "sound\\music%.3d.blp", rank-1);
+
+ // Open the device by specifying the device and filename.
+ // MCI will attempt to choose the MIDI mapper as the output port.
+ mciOpenParms.lpstrDeviceType = "sequencer";
+ mciOpenParms.lpstrElementName = filename;
+ dwReturn = mciSendCommand(NULL,
+ MCI_OPEN,
+ MCI_OPEN_TYPE|MCI_OPEN_ELEMENT,
+ (DWORD)(LPVOID)&mciOpenParms);
+ if ( dwReturn != 0 )
+ {
+ mciGetErrorString(dwReturn, filename, 128);
+ // Failed to open device. Don't close it; just return error.
+ return false;
+ }
+
+ // The device opened successfully; get the device ID.
+ m_MidiDeviceID = mciOpenParms.wDeviceID;
+
+ // Begin playback.
+ mciPlayParms.dwCallback = (DWORD)m_hWnd;
+ dwReturn = mciSendCommand(m_MidiDeviceID,
+ MCI_PLAY,
+ MCI_NOTIFY,
+ (DWORD)(LPVOID)&mciPlayParms);
+ if ( dwReturn != 0 )
+ {
+ mciGetErrorString(dwReturn, filename, 128);
+ StopMusic();
+ return false;
+ }
+
+ m_MIDIMusic = rank;
+ return true;
+}
+
+// Uses MCI to play a CD-audio track. The window procedure
+// is notified when playback is complete.
+// The rank parameter is in space [1..n] !
+// For CD mix (data/audio), it will be [2..n] !
+
+bool CSound::PlayAudioTrack(int rank)
+{
+#if _SOUNDTRACKS
+ MCI_OPEN_PARMS mciOpenParms;
+ MCI_PLAY_PARMS mciPlayParms;
+ MCI_SET_PARMS mciSetParms;
+ DWORD dwReturn;
+ char filename[MAX_PATH];
+ char device[10];
+
+ if ( !m_bEnable ) return true;
+//? if ( m_midiVolume == 0 ) return true;
+ InitAudioTrackVolume(m_midiVolume);
+ m_lastMidiVolume = m_midiVolume;
+
+ // Open the device by specifying the device and filename.
+ // MCI will attempt to choose the MIDI mapper as the output port.
+ memset(&mciOpenParms, 0, sizeof(MCI_OPEN_PARMS));
+//? mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
+//? dwReturn = mciSendCommand(NULL,
+//? MCI_OPEN,
+//? MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,
+//? (DWORD)(LPVOID)&mciOpenParms);
+ mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
+ if ( m_CDpath[0] == 0 )
+ {
+ dwReturn = mciSendCommand(NULL,
+ MCI_OPEN,
+ MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,
+ (DWORD)(LPVOID)&mciOpenParms);
+ }
+ else
+ {
+ device[0] = m_CDpath[0];
+ device[1] = ':';
+ device[2] = 0;
+ mciOpenParms.lpstrElementName = device;
+ dwReturn = mciSendCommand(NULL,
+ MCI_OPEN,
+ MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_OPEN_ELEMENT,
+ (DWORD)(LPVOID)&mciOpenParms);
+ }
+ if ( dwReturn != 0 )
+ {
+ mciGetErrorString(dwReturn, filename, 128);
+ // Failed to open device. Don't close it; just return error.
+ return false;
+ }
+
+ // The device opened successfully; get the device ID.
+ m_MidiDeviceID = mciOpenParms.wDeviceID;
+
+ // Set the time format to track/minute/second/frame (TMSF).
+ memset(&mciSetParms, 0, sizeof(MCI_SET_PARMS));
+ mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
+ dwReturn = mciSendCommand(m_MidiDeviceID,
+ MCI_SET,
+ MCI_SET_TIME_FORMAT,
+ (DWORD)&mciSetParms);
+ if ( dwReturn != 0 )
+ {
+ mciGetErrorString(dwReturn, filename, 128);
+ StopMusic();
+ return false;
+ }
+
+ // Begin playback.
+ memset(&mciPlayParms, 0, sizeof(MCI_PLAY_PARMS));
+ mciPlayParms.dwCallback = (DWORD)m_hWnd;
+ mciPlayParms.dwFrom = MCI_MAKE_TMSF(rank+0, 0, 0, 0);
+ mciPlayParms.dwTo = MCI_MAKE_TMSF(rank+1, 0, 0, 0);
+ dwReturn = mciSendCommand(m_MidiDeviceID,
+ MCI_PLAY,
+ MCI_NOTIFY|MCI_FROM|MCI_TO,
+ (DWORD)(LPVOID)&mciPlayParms);
+ if ( dwReturn != 0 )
+ {
+ mciGetErrorString(dwReturn, filename, 128);
+ StopMusic();
+ return false;
+ }
+
+ m_MIDIMusic = rank;
+#endif
+ return true;
+}
+
+// Restart the MIDI player.
+
+bool CSound::RestartMusic()
+{
+ if ( !m_bRepeatMusic ) return false;
+
+ OutputDebugString("RestartMusic\n");
+ if ( !m_bEnable ) return true;
+//? if ( m_midiVolume == 0 ) return true;
+ if ( m_MIDIMusic == 0 ) return false;
+ if ( m_playTime < 5.0f ) return false;
+
+ return PlayMusic(m_MIDIMusic, true);
+}
+
+// Shuts down the MIDI player.
+
+void CSound::SuspendMusic()
+{
+ if ( !m_bEnable ) return;
+
+//? if ( m_MidiDeviceID && m_midiVolume != 0 )
+ if ( m_MidiDeviceID )
+ {
+ if ( m_bAudioTrack ) mciSendCommand(m_MidiDeviceID, MCI_STOP, 0, NULL);
+ mciSendCommand(m_MidiDeviceID, MCI_CLOSE, 0, NULL);
+ }
+ m_MidiDeviceID = 0;
+}
+
+// Shuts down the MIDI player.
+
+void CSound::StopMusic()
+{
+ SuspendMusic();
+ m_MIDIMusic = 0;
+}
+
+// Returns true if the music is in progress.
+
+bool CSound::IsPlayingMusic()
+{
+ return (m_MIDIMusic != 0);
+}
+
+// Adjusts the volume of currently music, if necessary.
+
+void CSound::AdaptVolumeMusic()
+{
+ if ( m_midiVolume != m_lastMidiVolume )
+ {
+ if ( m_bAudioTrack )
+ {
+ InitAudioTrackVolume(m_midiVolume);
+ }
+ else
+ {
+ InitMidiVolume(m_midiVolume);
+ }
+ m_lastMidiVolume = m_midiVolume;
+ RestartMusic();
+ }
+}
+
diff --git a/src/old/sound.h b/src/old/sound.h
index 2dcdc2c..157eb2e 100644
--- a/src/old/sound.h
+++ b/src/old/sound.h
@@ -1,242 +1,242 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// sound.h
-
-#pragma once
-
-
-#include <dsound.h>
-
-
-const int MAXFILES = 200;
-const int MAXSOUND = 32;
-const int MAXVOLUME = 20;
-const int MAXOPER = 4;
-
-class CInstanceManager;
-
-
-enum Sound
-{
- SOUND_CLICK = 0,
- SOUND_BOUM = 1,
- SOUND_EXPLO = 2,
- SOUND_FLYh = 3, // human
- SOUND_FLY = 4,
- SOUND_STEPs = 5, // smooth
- SOUND_MOTORw = 6, // wheel
- SOUND_MOTORt = 7, // tank
- SOUND_MOTORr = 8, // roller
- SOUND_ERROR = 9,
- SOUND_CONVERT = 10,
- SOUND_ENERGY = 11,
- SOUND_PLOUF = 12,
- SOUND_BLUP = 13,
- SOUND_WARNING = 14,
- SOUND_DERRICK = 15,
- SOUND_LABO = 16,
- SOUND_STATION = 17,
- SOUND_REPAIR = 18,
- SOUND_RESEARCH = 19,
- SOUND_INSECTs = 20, // spider
- SOUND_BURN = 21,
- SOUND_TZOING = 22,
- SOUND_GGG = 23,
- SOUND_MANIP = 24,
- SOUND_FIRE = 25, // shooting with fireball
- SOUND_HUMAN1 = 26, // breathing
- SOUND_STEPw = 27, // water
- SOUND_SWIM = 28,
- SOUND_RADAR = 29,
- SOUND_BUILD = 30,
- SOUND_ALARM = 31, // energy alarm
- SOUND_SLIDE = 32,
- SOUND_EXPLOi = 33, // insect
- SOUND_INSECTa = 34, // ant
- SOUND_INSECTb = 35, // bee
- SOUND_INSECTw = 36, // worm
- SOUND_INSECTm = 37, // mother
- SOUND_TREMBLE = 38,
- SOUND_PSHHH = 39,
- SOUND_NUCLEAR = 40,
- SOUND_INFO = 41,
- SOUND_OPEN = 42,
- SOUND_CLOSE = 43,
- SOUND_FACTORY = 44,
- SOUND_EGG = 45,
- SOUND_MOTORs = 46, // submarine
- SOUND_MOTORi = 47, // insect (legs)
- SOUND_SHIELD = 48,
- SOUND_FIREi = 49, // shooting with orgaball (insect)
- SOUND_GUNDEL = 50,
- SOUND_PSHHH2 = 51, // shield
- SOUND_MESSAGE = 52,
- SOUND_BOUMm = 53, // metal
- SOUND_BOUMv = 54, // plant
- SOUND_BOUMs = 55, // smooth
- SOUND_EXPLOl = 56, // little
- SOUND_EXPLOlp = 57, // little power
- SOUND_EXPLOp = 58, // power
- SOUND_STEPh = 59, // hard
- SOUND_STEPm = 60, // metal
- SOUND_POWERON = 61,
- SOUND_POWEROFF = 62,
- SOUND_AIE = 63,
- SOUND_WAYPOINT = 64,
- SOUND_RECOVER = 65,
- SOUND_DEADi = 66,
- SOUND_JOSTLE = 67,
- SOUND_GFLAT = 68,
- SOUND_DEADg = 69, // shooting death
- SOUND_DEADw = 70, // drowning
- SOUND_FLYf = 71, // reactor fail
- SOUND_ALARMt = 72, // temperature alarm
- SOUND_FINDING = 73, // finds a cache object
- SOUND_THUMP = 74,
- SOUND_TOUCH = 75,
- SOUND_BLITZ = 76,
- SOUND_MUSHROOM = 77,
- SOUND_FIREp = 78, // shooting with phazer
- SOUND_EXPLOg1 = 79, // impact gun 1
- SOUND_EXPLOg2 = 80, // impact gun 2
- SOUND_MOTORd = 81, // engine friction
-};
-
-enum SoundNext
-{
- SOPER_CONTINUE = 1,
- SOPER_STOP = 2,
- SOPER_LOOP = 3,
-};
-
-struct SoundOper
-{
- char bUsed;
- float finalAmplitude;
- float finalFrequency;
- float totalTime;
- float currentTime;
- SoundNext nextOper;
-};
-
-struct SoundChannel
-{
- char bUsed; // buffer used?
- char bMute; // silence?
- Sound type; // SOUND_*
- int priority; // so great -> important
- Math::Vector pos; // position in space
- unsigned short uniqueStamp; // unique marker
- LPDIRECTSOUNDBUFFER soundBuffer;
- LPDIRECTSOUND3DBUFFER soundBuffer3D;
- float startAmplitude;
- float startFrequency;
- float changeFrequency;
- int initFrequency;
- float volume; // 2D: volume 1..0 depending on position
- float pan; // 2D: pan -1..+1 depending on position
- SoundOper oper[MAXOPER];
-};
-
-
-
-class CSound
-{
-public:
- CSound(CInstanceManager* iMan);
- ~CSound();
-
- void SetDebugMode(bool bMode);
- bool Create(HWND hWnd, bool b3D);
- void CacheAll();
-
- void SetState(bool bState);
- bool RetEnable();
-
- void SetCDpath(char *path);
- void SetAudioTrack(bool bAudio);
-
- void SetSound3D(bool bMode);
- bool RetSound3D();
- bool RetSound3DCap();
-
- void SetAudioVolume(int volume);
- int RetAudioVolume();
- void SetMidiVolume(int volume);
- int RetMidiVolume();
-
- void SetListener(Math::Vector eye, Math::Vector lookat);
- void FrameMove(float rTime);
-
- int Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop=false);
- int Play(Sound sound, Math::Vector pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop=false);
- bool FlushEnvelope(int channel);
- bool AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper);
- bool Position(int channel, Math::Vector pos);
- bool Frequency(int channel, float frequency);
- bool Stop(int channel);
- bool StopAll();
- bool MuteAll(bool bMute);
-
- bool PlayMusic(int rank, bool bRepeat);
- bool RestartMusic();
- void SuspendMusic();
- void StopMusic();
- bool IsPlayingMusic();
- void AdaptVolumeMusic();
-
-protected:
- bool CheckChannel(int &channel);
- bool CreateSoundBuffer(int channel, DWORD size, DWORD freq, DWORD bitsPerSample, DWORD blkAlign, bool bStereo);
- bool ReadData(LPDIRECTSOUNDBUFFER lpDSB, Sound sound, DWORD size);
- bool CreateBuffer(int channel, Sound sound);
- void ComputeVolumePan2D(int channel, const Math::Vector &pos);
- bool ReadFile(Sound sound, char *metaname, char *filename);
- int RetPriority(Sound sound);
- bool SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded);
- void OperNext(int channel);
- bool PlayAudioTrack(int rank);
-
-protected:
- CInstanceManager* m_iMan;
-
- HWND m_hWnd;
- bool m_bEnable;
- bool m_bState;
- bool m_bAudioTrack;
- bool m_ctrl3D;
- bool m_bDebugMode;
- LPDIRECTSOUND m_lpDS;
- LPDIRECTSOUND3DLISTENER m_listener;
- SoundChannel m_channel[MAXSOUND];
- char* m_files[MAXFILES];
- UINT m_MidiDeviceID;
- int m_MIDIMusic;
- bool m_bRepeatMusic;
- int m_audioVolume;
- int m_midiVolume;
- int m_lastMidiVolume;
- Math::Vector m_eye;
- Math::Vector m_lookat;
- float m_lastTime;
- float m_playTime;
- int m_uniqueStamp;
- int m_maxSound;
- char m_CDpath[100];
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// sound.h
+
+#pragma once
+
+
+#include <dsound.h>
+
+
+const int MAXFILES = 200;
+const int MAXSOUND = 32;
+const int MAXVOLUME = 20;
+const int MAXOPER = 4;
+
+class CInstanceManager;
+
+
+enum Sound
+{
+ SOUND_CLICK = 0,
+ SOUND_BOUM = 1,
+ SOUND_EXPLO = 2,
+ SOUND_FLYh = 3, // human
+ SOUND_FLY = 4,
+ SOUND_STEPs = 5, // smooth
+ SOUND_MOTORw = 6, // wheel
+ SOUND_MOTORt = 7, // tank
+ SOUND_MOTORr = 8, // roller
+ SOUND_ERROR = 9,
+ SOUND_CONVERT = 10,
+ SOUND_ENERGY = 11,
+ SOUND_PLOUF = 12,
+ SOUND_BLUP = 13,
+ SOUND_WARNING = 14,
+ SOUND_DERRICK = 15,
+ SOUND_LABO = 16,
+ SOUND_STATION = 17,
+ SOUND_REPAIR = 18,
+ SOUND_RESEARCH = 19,
+ SOUND_INSECTs = 20, // spider
+ SOUND_BURN = 21,
+ SOUND_TZOING = 22,
+ SOUND_GGG = 23,
+ SOUND_MANIP = 24,
+ SOUND_FIRE = 25, // shooting with fireball
+ SOUND_HUMAN1 = 26, // breathing
+ SOUND_STEPw = 27, // water
+ SOUND_SWIM = 28,
+ SOUND_RADAR = 29,
+ SOUND_BUILD = 30,
+ SOUND_ALARM = 31, // energy alarm
+ SOUND_SLIDE = 32,
+ SOUND_EXPLOi = 33, // insect
+ SOUND_INSECTa = 34, // ant
+ SOUND_INSECTb = 35, // bee
+ SOUND_INSECTw = 36, // worm
+ SOUND_INSECTm = 37, // mother
+ SOUND_TREMBLE = 38,
+ SOUND_PSHHH = 39,
+ SOUND_NUCLEAR = 40,
+ SOUND_INFO = 41,
+ SOUND_OPEN = 42,
+ SOUND_CLOSE = 43,
+ SOUND_FACTORY = 44,
+ SOUND_EGG = 45,
+ SOUND_MOTORs = 46, // submarine
+ SOUND_MOTORi = 47, // insect (legs)
+ SOUND_SHIELD = 48,
+ SOUND_FIREi = 49, // shooting with orgaball (insect)
+ SOUND_GUNDEL = 50,
+ SOUND_PSHHH2 = 51, // shield
+ SOUND_MESSAGE = 52,
+ SOUND_BOUMm = 53, // metal
+ SOUND_BOUMv = 54, // plant
+ SOUND_BOUMs = 55, // smooth
+ SOUND_EXPLOl = 56, // little
+ SOUND_EXPLOlp = 57, // little power
+ SOUND_EXPLOp = 58, // power
+ SOUND_STEPh = 59, // hard
+ SOUND_STEPm = 60, // metal
+ SOUND_POWERON = 61,
+ SOUND_POWEROFF = 62,
+ SOUND_AIE = 63,
+ SOUND_WAYPOINT = 64,
+ SOUND_RECOVER = 65,
+ SOUND_DEADi = 66,
+ SOUND_JOSTLE = 67,
+ SOUND_GFLAT = 68,
+ SOUND_DEADg = 69, // shooting death
+ SOUND_DEADw = 70, // drowning
+ SOUND_FLYf = 71, // reactor fail
+ SOUND_ALARMt = 72, // temperature alarm
+ SOUND_FINDING = 73, // finds a cache object
+ SOUND_THUMP = 74,
+ SOUND_TOUCH = 75,
+ SOUND_BLITZ = 76,
+ SOUND_MUSHROOM = 77,
+ SOUND_FIREp = 78, // shooting with phazer
+ SOUND_EXPLOg1 = 79, // impact gun 1
+ SOUND_EXPLOg2 = 80, // impact gun 2
+ SOUND_MOTORd = 81, // engine friction
+};
+
+enum SoundNext
+{
+ SOPER_CONTINUE = 1,
+ SOPER_STOP = 2,
+ SOPER_LOOP = 3,
+};
+
+struct SoundOper
+{
+ char bUsed;
+ float finalAmplitude;
+ float finalFrequency;
+ float totalTime;
+ float currentTime;
+ SoundNext nextOper;
+};
+
+struct SoundChannel
+{
+ char bUsed; // buffer used?
+ char bMute; // silence?
+ Sound type; // SOUND_*
+ int priority; // so great -> important
+ Math::Vector pos; // position in space
+ unsigned short uniqueStamp; // unique marker
+ LPDIRECTSOUNDBUFFER soundBuffer;
+ LPDIRECTSOUND3DBUFFER soundBuffer3D;
+ float startAmplitude;
+ float startFrequency;
+ float changeFrequency;
+ int initFrequency;
+ float volume; // 2D: volume 1..0 depending on position
+ float pan; // 2D: pan -1..+1 depending on position
+ SoundOper oper[MAXOPER];
+};
+
+
+
+class CSound
+{
+public:
+ CSound(CInstanceManager* iMan);
+ ~CSound();
+
+ void SetDebugMode(bool bMode);
+ bool Create(HWND hWnd, bool b3D);
+ void CacheAll();
+
+ void SetState(bool bState);
+ bool RetEnable();
+
+ void SetCDpath(char *path);
+ void SetAudioTrack(bool bAudio);
+
+ void SetSound3D(bool bMode);
+ bool RetSound3D();
+ bool RetSound3DCap();
+
+ void SetAudioVolume(int volume);
+ int RetAudioVolume();
+ void SetMidiVolume(int volume);
+ int RetMidiVolume();
+
+ void SetListener(Math::Vector eye, Math::Vector lookat);
+ void FrameMove(float rTime);
+
+ int Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop=false);
+ int Play(Sound sound, Math::Vector pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop=false);
+ bool FlushEnvelope(int channel);
+ bool AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper);
+ bool Position(int channel, Math::Vector pos);
+ bool Frequency(int channel, float frequency);
+ bool Stop(int channel);
+ bool StopAll();
+ bool MuteAll(bool bMute);
+
+ bool PlayMusic(int rank, bool bRepeat);
+ bool RestartMusic();
+ void SuspendMusic();
+ void StopMusic();
+ bool IsPlayingMusic();
+ void AdaptVolumeMusic();
+
+protected:
+ bool CheckChannel(int &channel);
+ bool CreateSoundBuffer(int channel, DWORD size, DWORD freq, DWORD bitsPerSample, DWORD blkAlign, bool bStereo);
+ bool ReadData(LPDIRECTSOUNDBUFFER lpDSB, Sound sound, DWORD size);
+ bool CreateBuffer(int channel, Sound sound);
+ void ComputeVolumePan2D(int channel, const Math::Vector &pos);
+ bool ReadFile(Sound sound, char *metaname, char *filename);
+ int RetPriority(Sound sound);
+ bool SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded);
+ void OperNext(int channel);
+ bool PlayAudioTrack(int rank);
+
+protected:
+ CInstanceManager* m_iMan;
+
+ HWND m_hWnd;
+ bool m_bEnable;
+ bool m_bState;
+ bool m_bAudioTrack;
+ bool m_ctrl3D;
+ bool m_bDebugMode;
+ LPDIRECTSOUND m_lpDS;
+ LPDIRECTSOUND3DLISTENER m_listener;
+ SoundChannel m_channel[MAXSOUND];
+ char* m_files[MAXFILES];
+ UINT m_MidiDeviceID;
+ int m_MIDIMusic;
+ bool m_bRepeatMusic;
+ int m_audioVolume;
+ int m_midiVolume;
+ int m_lastMidiVolume;
+ Math::Vector m_eye;
+ Math::Vector m_lookat;
+ float m_lastTime;
+ float m_playTime;
+ int m_uniqueStamp;
+ int m_maxSound;
+ char m_CDpath[100];
+};
+
+
diff --git a/src/old/terrain.cpp b/src/old/terrain.cpp
index b558e71..2f2250c 100644
--- a/src/old/terrain.cpp
+++ b/src/old/terrain.cpp
@@ -1,2270 +1,2270 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// terrain.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "old/d3dutil.h"
-#include "common/language.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "old/modfile.h"
-#include "old/water.h"
-#include "old/terrain.h"
-
-
-const int BMPHEAD = 1078;
-
-
-
-// Constructor of the terrain.
-
-CTerrain::CTerrain(CInstanceManager* iMan)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_TERRAIN, this);
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
-
- m_mosaic = 20;
- m_brick = 1<<4;
- m_size = 10.0f;
- m_vision = 200.0f;
- m_relief = 0;
- m_texture = 0;
- m_objRank = 0;
- m_scaleMapping = 0.01f;
- m_scaleRelief = 1.0f;
- m_subdivMapping = 1;
- m_depth = 2;
- m_texBaseName[0]= 0;
- m_texBaseExt[0] = 0;
- m_bMultiText = true;
- m_bLevelText = false;
- m_resources = 0;
- m_levelMatTotal = 0;
- m_levelMatMax = 0;
- m_levelDot = 0;
- m_wind = Math::Vector(0.0f, 0.0f, 0.0f);
- m_defHardness = 0.5f;
-
- FlushBuildingLevel();
- FlushFlyingLimit();
-}
-
-// Destructor of the terrain.
-
-CTerrain::~CTerrain()
-{
- free(m_relief);
- free(m_texture);
- free(m_objRank);
- free(m_resources);
-}
-
-
-// Generates a new flat terrain.
-// The terrain is composed of mosaics, themselves composed of bricks.
-// Each brick is composed of two triangles.
-// mosaic: number of mosaics along the axes X and Z
-// brick: number of bricks (power of 2)
-// size: size of a brick along the axes X and Z
-// vision: vision before a change of resolution
-// scaleMapping: scale textures for mapping
-//
-// ^ z
-// | <---> brick*size
-// +---+---+---+---+
-// | | | |_|_| mosaic = 4
-// | | | | | | brick = 2 (brickP2=1)
-// +---+---+---+---+
-// |\ \| | | |
-// |\ \| | | |
-// +---+---o---+---+---> x
-// | | | | |
-// | | | | |
-// +---+---+---+---+
-// | | | | | The land is viewed from above here.
-// | | | | |
-// +---+---+---+---+
-// <---------------> mosaic*brick*size
-
-bool CTerrain::Generate(int mosaic, int brickP2, float size, float vision,
- int depth, float hardness)
-{
- int dim;
-
- m_mosaic = mosaic;
- m_brick = 1<<brickP2;
- m_size = size;
- m_vision = vision;
- m_depth = depth;
- m_defHardness = hardness;
-
- m_engine->SetTerrainVision(vision);
-
- m_bMultiText = true;
- m_bLevelText = false;
- m_scaleMapping = 1.0f/(m_brick*m_size);
- m_subdivMapping = 1;
-
- dim = (m_mosaic*m_brick+1)*(m_mosaic*m_brick+1);
- m_relief = (float*)malloc(sizeof(float)*dim);
- ZeroMemory(m_relief, sizeof(float)*dim);
-
- dim = m_mosaic*m_subdivMapping*m_mosaic*m_subdivMapping;
- m_texture = (int*)malloc(sizeof(int)*dim);
- ZeroMemory(m_texture, sizeof(int)*dim);
-
- dim = m_mosaic*m_mosaic;
- m_objRank = (int*)malloc(sizeof(int)*dim);
- ZeroMemory(m_objRank, sizeof(int)*dim);
-
- return true;
-}
-
-
-int CTerrain::RetMosaic()
-{
- return m_mosaic;
-}
-
-int CTerrain::RetBrick()
-{
- return m_brick;
-}
-
-float CTerrain::RetSize()
-{
- return m_size;
-}
-
-float CTerrain::RetScaleRelief()
-{
- return m_scaleRelief;
-}
-
-
-// Initializes the names of textures to use for the land.
-
-bool CTerrain::InitTextures(char* baseName, int* table, int dx, int dy)
-{
- int x, y;
- char* p;
-
- m_bLevelText = false;
-
- strcpy(m_texBaseName, baseName);
- p = strchr(m_texBaseName, '.'); // p <- ^beginning of the extension
- if ( p == 0 )
- {
- strcpy(m_texBaseExt, ".tga");
- }
- else
- {
- strcpy(m_texBaseExt, p); // m_texBaseExt <- ".tga" or ".bmp"
- *p = 0; // m_texBaseName <- name without extension
- }
-
- for ( y=0 ; y<m_mosaic*m_subdivMapping ; y++ )
- {
- for ( x=0 ; x<m_mosaic*m_subdivMapping ; x++ )
- {
- m_texture[x+y*m_mosaic] = table[(x%dx)+(y%dy)*dx];
- }
- }
- return true;
-}
-
-
-// Empties level.
-
-void CTerrain::LevelFlush()
-{
- m_levelMatTotal = 0;
- m_levelMatMax = 0;
- m_levelID = 1000;
- LevelCloseTable();
-}
-
-// Initializes the names of textures to use for the land.
-
-bool CTerrain::LevelMaterial(int id, char* baseName, float u, float v,
- int up, int right, int down, int left,
- float hardness)
-{
- int i;
-
- i = m_levelMatTotal;
- if ( i >= MAXMATTERRAIN-1 ) return false;
-
- LevelOpenTable();
-
- if ( id == 0 )
- {
- id = m_levelID++; // puts an ID internal standard
- }
-
- strcpy(m_levelMat[i].texName, baseName);
- m_levelMat[i].id = id;
- m_levelMat[i].u = u;
- m_levelMat[i].v = v;
- m_levelMat[i].mat[0] = up;
- m_levelMat[i].mat[1] = right;
- m_levelMat[i].mat[2] = down;
- m_levelMat[i].mat[3] = left;
- m_levelMat[i].hardness = hardness;
-
- if ( m_levelMatMax < up+1 ) m_levelMatMax = up+1;
- if ( m_levelMatMax < right+1 ) m_levelMatMax = right+1;
- if ( m_levelMatMax < down+1 ) m_levelMatMax = down+1;
- if ( m_levelMatMax < left+1 ) m_levelMatMax = left+1;
-
- m_bLevelText = true;
- m_subdivMapping = 4;
-
- m_levelMatTotal ++;
- return true;
-}
-
-
-// Load relief from a BMP file.
-// The size of the image must be dimension dx and dy with dx=dy=(mosaic*brick)+1.
-// The image must be 8 bits/pixel, 256 colors with a standard pallet.
-
-// Converts coordinated image (x;y) -> world (x;-;z) :
-// Wx = 5*Ix-400
-// Wz = -(5*Iy-400)
-
-// Converts coordinated world (x;-;z) -> image (x;y) :
-// Ix = (400+Wx)/5
-// Iy = (400-Wz)/5
-
-bool CTerrain::ResFromBMP(const char* filename)
-{
- FILE* file;
- int size, sizem;
-
- file = fopen(filename, "rb");
- if ( file == NULL ) return false;
-
- size = (m_mosaic*m_brick)+1;
- sizem = ((size+4-1)/4)*4; // upper size multiple of 4
-
- if ( m_resources != 0 )
- {
- free(m_resources);
- }
-
- m_resources = (unsigned char*)malloc(BMPHEAD+sizem*size);
- fread(m_resources, BMPHEAD+sizem*size, 1, file);
-
- if ( m_resources[18] != (size&0xff) || m_resources[19] != (size>>8) ||
- m_resources[22] != (size&0xff) || m_resources[23] != (size>>8) )
- {
- free(m_resources);
- m_resources = 0;
- fclose(file);
- return false;
- }
-
- fclose(file);
- return true;
-}
-
-// Returns the resource type available underground.
-
-TerrainRes CTerrain::RetResource(const Math::Vector &p)
-{
- int x, y, size, sizem, ress;
-
- if ( m_resources == 0 ) return TR_NULL;
-
- x = (int)((p.x + (m_mosaic*m_brick*m_size)/2.0f)/m_size);
- y = (int)((p.z + (m_mosaic*m_brick*m_size)/2.0f)/m_size);
-
- if ( x < 0 || x > m_mosaic*m_brick ||
- y < 0 || y > m_mosaic*m_brick ) return TR_NULL;
-
- size = (m_mosaic*m_brick)+1;
- sizem = ((size+4-1)/4)*4; // upper size multiple of 4
-
- ress = m_resources[BMPHEAD+x+sizem*y];
- if ( ress == 5 ) return TR_STONE; // red?
- if ( ress == 35 ) return TR_URANIUM; // yellow?
- if ( ress == 30 ) return TR_POWER; // green?
- if ( ress == 24 ) return TR_KEYa; // ~green?
- if ( ress == 25 ) return TR_KEYb; // ~green?
- if ( ress == 26 ) return TR_KEYc; // ~green?
- if ( ress == 27 ) return TR_KEYd; // ~green?
-
- return TR_NULL;
-}
-
-
-// Initializes a completely flat terrain.
-
-void CTerrain::FlushRelief()
-{
- free(m_relief);
- m_relief = 0;
-}
-
-// Load relief from a BMP file.
-// The size of the image must be dimension dx and dy with dx=dy=(mosaic*brick)+1.
-// The image must be 8 bits/pixel, 256 gray scale:
-// white = ground (y=0)
-// black = mountain (y=255*scaleRelief)
-
-// Converts coordinated image(x;y) -> world (x;-;z) :
-// Wx = 5*Ix-400
-// Wz = -(5*Iy-400)
-
-// Converts coordinated world (x;-;z) -> image (x;y) :
-// Ix = (400+Wx)/5
-// Iy = (400-Wz)/5
-
-bool CTerrain::ReliefFromBMP(const char* filename, float scaleRelief,
- bool adjustBorder)
-{
- FILE* file;
- unsigned char* buffer;
- int size, sizem, x, y;
- float level, limit, dist, border;
-
- m_scaleRelief = scaleRelief;
-
- file = fopen(filename, "rb");
- if ( file == NULL ) return false;
-
- size = (m_mosaic*m_brick)+1;
- sizem = ((size+4-1)/4)*4; // upper size multiple of 4
-
- buffer = (unsigned char*)malloc(BMPHEAD+sizem*size);
- fread(buffer, BMPHEAD+sizem*size, 1, file);
-
- if ( buffer[18] != (size&0xff) || buffer[19] != (size>>8) ||
- buffer[22] != (size&0xff) || buffer[23] != (size>>8) )
- {
- free(buffer);
- fclose(file);
- return false;
- }
-
- limit = 0.9f;
- for ( y=0 ; y<size ; y++ )
- {
- for ( x=0 ; x<size ; x++ )
- {
- level = (255-buffer[BMPHEAD+x+sizem*y])*scaleRelief;
-
-//? dist = Length((float)(x-size/2), (float)(y-size/2));
- dist = Math::Max(fabs((float)(x-size/2)), fabs((float)(y-size/2)));
- dist = dist/(float)(size/2);
- if ( dist > limit && adjustBorder )
- {
- dist = (dist-limit)/(1.0f-limit); // 0..1
- if ( dist > 1.0f ) dist = 1.0f;
- border = 300.0f+Math::Rand()*20.0f;
- level = level+dist*(border-level);
- }
-
- m_relief[x+y*size] = level;
- }
- }
-
- free(buffer);
- fclose(file);
- return true;
-}
-
-// Adds a point of elevation in the buffer of relief.
-
-bool CTerrain::ReliefAddDot(Math::Vector pos, float scaleRelief)
-{
- float dim;
- int size, x, y;
-
- dim = (m_mosaic*m_brick*m_size)/2.0f;
- size = (m_mosaic*m_brick)+1;
-
- pos.x = (pos.x+dim)/m_size;
- pos.z = (pos.z+dim)/m_size;
-
- x = (int)pos.x;
- y = (int)pos.z;
-
- if ( x < 0 || x >= size ||
- y < 0 || y >= size ) return false;
-
- if ( m_relief[x+y*size] < pos.y*scaleRelief )
- {
- m_relief[x+y*size] = pos.y*scaleRelief;
- }
- return true;
-}
-
-// Load relief from a DXF file.
-
-bool CTerrain::ReliefFromDXF(const char* filename, float scaleRelief)
-{
- FILE* file = NULL;
- char line[100];
- int command, rankSommet, nbSommet, nbFace, size;
- Math::Vector* table;
- bool bWaitNbSommet;
- bool bWaitNbFace;
- bool bWaitSommetX;
- bool bWaitSommetY;
- bool bWaitSommetZ;
- bool bWaitFaceX;
- bool bWaitFaceY;
- bool bWaitFaceZ;
- float x,y,z;
- int p1,p2,p3;
-
- ZeroMemory(m_relief, sizeof(float)*(m_mosaic*m_brick+1)*(m_mosaic*m_brick+1));
-
- file = fopen(filename, "r");
- if ( file == NULL ) return false;
-
- size = (m_mosaic*m_brick)+1;
- table = (Math::Vector*)malloc(sizeof(Math::Vector)*size*size);
-
- rankSommet = 0;
- bWaitNbSommet = false;
- bWaitNbFace = false;
- bWaitSommetX = false;
- bWaitSommetY = false;
- bWaitSommetZ = false;
- bWaitFaceX = false;
- bWaitFaceY = false;
- bWaitFaceZ = false;
-
- while ( fgets(line, 100, file) != NULL )
- {
- sscanf(line, "%d", &command);
- if ( fgets(line, 100, file) == NULL ) break;
-
- if ( command == 66 )
- {
- bWaitNbSommet = true;
- }
-
- if ( command == 71 && bWaitNbSommet )
- {
- bWaitNbSommet = false;
- sscanf(line, "%d", &nbSommet);
- if ( nbSommet > size*size ) nbSommet = size*size;
- rankSommet = 0;
- bWaitNbFace = true;
- }
-
- if ( command == 72 && bWaitNbFace )
- {
- bWaitNbFace = false;
- sscanf(line, "%d", &nbFace);
- bWaitSommetX = true;
- }
-
- if ( command == 10 && bWaitSommetX )
- {
- bWaitSommetX = false;
- sscanf(line, "%f", &x);
- bWaitSommetY = true;
- }
-
- if ( command == 20 && bWaitSommetY )
- {
- bWaitSommetY = false;
- sscanf(line, "%f", &y);
- bWaitSommetZ = true;
- }
-
- if ( command == 30 && bWaitSommetZ )
- {
- bWaitSommetZ = false;
- sscanf(line, "%f", &z);
-
- nbSommet --;
- if ( nbSommet >= 0 )
- {
- Math::Vector p(x,z,y); // permutation of Y and Z!
- table[rankSommet++] = p;
- bWaitSommetX = true;
- }
- else
- {
- bWaitFaceX = true;
- }
- }
-
- if ( command == 71 && bWaitFaceX )
- {
- bWaitFaceX = false;
- sscanf(line, "%d", &p1);
- if ( p1 < 0 ) p1 = -p1;
- bWaitFaceY = true;
- }
-
- if ( command == 72 && bWaitFaceY )
- {
- bWaitFaceY = false;
- sscanf(line, "%d", &p2);
- if ( p2 < 0 ) p2 = -p2;
- bWaitFaceZ = true;
- }
-
- if ( command == 73 && bWaitFaceZ )
- {
- bWaitFaceZ = false;
- sscanf(line, "%d", &p3);
- if ( p3 < 0 ) p3 = -p3;
-
- nbFace --;
- if ( nbFace >= 0 )
- {
- ReliefAddDot(table[p3-1], scaleRelief);
- ReliefAddDot(table[p2-1], scaleRelief);
- ReliefAddDot(table[p1-1], scaleRelief);
- bWaitFaceX = true;
- }
- }
-
- }
-
- free(table);
- fclose(file);
- return true;
-}
-
-
-// Adjusts a position so that it does not exceed the boundaries.
-
-void CTerrain::LimitPos(Math::Vector &pos)
-{
- float dim;
-
-#if _TEEN
- dim = (m_mosaic*m_brick*m_size)/2.0f*0.98f;
-#else
- dim = (m_mosaic*m_brick*m_size)/2.0f*0.92f;
-#endif
-
- if ( pos.x < -dim ) pos.x = -dim;
- if ( pos.x > dim ) pos.x = dim;
- if ( pos.z < -dim ) pos.z = -dim;
- if ( pos.z > dim ) pos.z = dim;
-}
-
-
-// Adjust the edges of each mosaic to be compatible with all lower resolutions.
-
-void CTerrain::AdjustRelief()
-{
- int x, y, xx, yy, ii, b;
- float level1, level2;
-
- if ( m_depth == 1 ) return;
-
- ii = m_mosaic*m_brick+1;
- b = 1<<(m_depth-1);
-
- for ( y=0 ; y<m_mosaic*m_brick ; y+=b )
- {
- for ( x=0 ; x<m_mosaic*m_brick ; x+=b )
- {
- yy = 0;
- if ( (y+yy)%m_brick == 0 )
- {
- level1 = m_relief[(x+0)+(y+yy)*ii];
- level2 = m_relief[(x+b)+(y+yy)*ii];
- for ( xx=1 ; xx<b ; xx++ )
- {
- m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*xx+level1;
- }
- }
-
- yy = b;
- if ( (y+yy)%m_brick == 0 )
- {
- level1 = m_relief[(x+0)+(y+yy)*ii];
- level2 = m_relief[(x+b)+(y+yy)*ii];
- for ( xx=1 ; xx<b ; xx++ )
- {
- m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*xx+level1;
- }
- }
-
- xx = 0;
- if ( (x+xx)%m_brick == 0 )
- {
- level1 = m_relief[(x+xx)+(y+0)*ii];
- level2 = m_relief[(x+xx)+(y+b)*ii];
- for ( yy=1 ; yy<b ; yy++ )
- {
- m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*yy+level1;
- }
- }
-
- xx = b;
- if ( (x+xx)%m_brick == 0 )
- {
- level1 = m_relief[(x+xx)+(y+0)*ii];
- level2 = m_relief[(x+xx)+(y+b)*ii];
- for ( yy=1 ; yy<b ; yy++ )
- {
- m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*yy+level1;
- }
- }
- }
- }
-}
-
-
-// Calculates a vector of the terrain.
-
-Math::Vector CTerrain::RetVector(int x, int y)
-{
- Math::Vector p;
-
- p.x = x*m_size - (m_mosaic*m_brick*m_size)/2;
- p.z = y*m_size - (m_mosaic*m_brick*m_size)/2;
-
- if ( m_relief != 0 &&
- x >= 0 && x <= m_mosaic*m_brick &&
- y >= 0 && y <= m_mosaic*m_brick )
- {
- p.y = m_relief[x+y*(m_mosaic*m_brick+1)];
- }
- else
- {
- p.y = 0.0f;
- }
-
- return p;
-}
-
-// Calculates a vertex of the terrain.
-// Calculates a normal soft, taking into account the six adjacent triangles:
-//
-// ^ y
-// |
-// b---c---+
-// |\ |\ |
-// | \| \|
-// a---o---d
-// |\ |\ |
-// | \| \|
-// +---f---e--> x
-
-D3DVERTEX2 CTerrain::RetVertex(int x, int y, int step)
-{
- D3DVERTEX2 v;
- Math::Vector o, oo, a,b,c,d,e,f, n, s;
- int brick;
-
- o = RetVector(x, y);
- v.x = o.x;
- v.y = o.y;
- v.z = o.z;
-
- a = RetVector(x-step, y );
- b = RetVector(x-step, y+step);
- c = RetVector(x, y+step);
- d = RetVector(x+step, y );
- e = RetVector(x+step, y-step);
- f = RetVector(x, y-step);
-
- s = Math::Vector(0.0f, 0.0f, 0.0f);
-
- if ( x-step >= 0 && y+step <= m_mosaic*m_brick+1 )
- {
- s += Math::NormalToPlane(b,a,o);
- s += Math::NormalToPlane(c,b,o);
- }
-
- if ( x+step <= m_mosaic*m_brick+1 && y+step <= m_mosaic*m_brick+1 )
- {
- s += Math::NormalToPlane(d,c,o);
- }
-
- if ( x+step <= m_mosaic*m_brick+1 && y-step >= 0 )
- {
- s += Math::NormalToPlane(e,d,o);
- s += Math::NormalToPlane(f,e,o);
- }
-
- if ( x-step >= 0 && y-step >= 0 )
- {
- s += Math::NormalToPlane(a,f,o);
- }
-
- s = Normalize(s);
- v.nx = s.x;
- v.ny = s.y;
- v.nz = s.z;
-
- if ( m_bMultiText )
- {
- brick = m_brick/m_subdivMapping;
- oo = RetVector((x/brick)*brick, (y/brick)*brick);
- o = RetVector(x, y);
- v.tu = (o.x-oo.x)*m_scaleMapping*m_subdivMapping;
- v.tv = 1.0f - (o.z-oo.z)*m_scaleMapping*m_subdivMapping;
- }
- else
- {
- v.tu = o.x*m_scaleMapping;
- v.tv = o.z*m_scaleMapping;
- }
-
- return v;
-}
-
-// Creates all objects of a mosaic.
-// The origin of mosaic is his center.
-//
-// ^ z
-// |
-// | 2---4---6--
-// | |\ |\ |\
-// | | \| \|
-// | 1---3---5--- ...
-// |
-// +-------------------> x
-
-bool CTerrain::CreateMosaic(int ox, int oy, int step, int objRank,
- const D3DMATERIAL7 &mat,
- float min, float max)
-{
- Math::Matrix transform;
- D3DVERTEX2 o, p1, p2;
- D3DObjLevel6* buffer;
- Math::Point uv;
- int brick, total, size, mx, my, x, y, xx, yy, i;
- char texName1[20];
- char texName2[20];
- float pixel, dp;
-
- if ( step == 1 && m_engine->RetGroundSpot() )
- {
- i = (ox/5) + (oy/5)*(m_mosaic/5);
- sprintf(texName2, "shadow%.2d.tga", i);
- }
- else
- {
- texName2[0] = 0;
- }
-
- brick = m_brick/m_subdivMapping;
-
- o = RetVertex(ox*m_brick+m_brick/2, oy*m_brick+m_brick/2, step);
- total = ((brick/step)+1)*2;
- size = sizeof(D3DObjLevel6)+sizeof(D3DVERTEX2)*(total-1);
-
- pixel = 1.0f/256.0f; // 1 pixel cover (*)
-//? dp = 0.5f/512.0f;
- dp = 1.0f/512.0f;
-
- for ( my=0 ; my<m_subdivMapping ; my++ )
- {
- for ( mx=0 ; mx<m_subdivMapping ; mx++ )
- {
- if ( m_bLevelText )
- {
- xx = ox*m_brick + mx*(m_brick/m_subdivMapping);
- yy = oy*m_brick + my*(m_brick/m_subdivMapping);
- LevelTextureName(xx, yy, texName1, uv);
- }
- else
- {
- i = (ox*m_subdivMapping+mx)+(oy*m_subdivMapping+my)*m_mosaic;
- sprintf(texName1, "%s%.3d%s", m_texBaseName, m_texture[i], m_texBaseExt);
- }
-
- for ( y=0 ; y<brick ; y+=step )
- {
- buffer = (D3DObjLevel6*)malloc(size);
- ZeroMemory(buffer, sizeof(D3DObjLevel6));
- buffer->totalPossible = total;
- buffer->totalUsed = total;
- buffer->type = D3DTYPE6S;
- buffer->material = mat;
- if ( m_bMultiText )
- {
-//? buffer->state = D3DSTATENORMAL;
- buffer->state = D3DSTATEWRAP;
- }
- else
- {
- buffer->state = D3DSTATEWRAP;
- }
- buffer->state |= D3DSTATESECOND;
- if ( step == 1 )
- {
- buffer->state |= D3DSTATEDUALb;
- }
- i = 0;
- for ( x=0 ; x<=brick ; x+=step )
- {
- p1 = RetVertex(ox*m_brick+mx*brick+x, oy*m_brick+my*brick+y+0 , step);
- p2 = RetVertex(ox*m_brick+mx*brick+x, oy*m_brick+my*brick+y+step, step);
- p1.x -= o.x; p1.z -= o.z;
- p2.x -= o.x; p2.z -= o.z;
-
- if ( m_bMultiText )
- {
- if ( x == 0 )
- {
- p1.tu = 0.0f+(0.5f/256.0f);
- p2.tu = 0.0f+(0.5f/256.0f);
- }
- if ( x == brick )
- {
- p1.tu = 1.0f-(0.5f/256.0f);
- p2.tu = 1.0f-(0.5f/256.0f);
- }
- if ( y == 0 )
- {
- p1.tv = 1.0f-(0.5f/256.0f);
- }
- if ( y == brick-step )
- {
- p2.tv = 0.0f+(0.5f/256.0f);
- }
- }
-
- if ( m_bLevelText )
- {
- p1.tu /= m_subdivMapping; // 0..1 -> 0..0.25
- p1.tv /= m_subdivMapping;
- p2.tu /= m_subdivMapping;
- p2.tv /= m_subdivMapping;
-
- if ( x == 0 )
- {
- p1.tu = 0.0f+dp;
- p2.tu = 0.0f+dp;
- }
- if ( x == brick )
- {
- p1.tu = (1.0f/m_subdivMapping)-dp;
- p2.tu = (1.0f/m_subdivMapping)-dp;
- }
- if ( y == 0 )
- {
- p1.tv = (1.0f/m_subdivMapping)-dp;
- }
- if ( y == brick-step )
- {
- p2.tv = 0.0f+dp;
- }
-
- p1.tu += uv.x;
- p1.tv += uv.y;
- p2.tu += uv.x;
- p2.tv += uv.y;
- }
-
-#if 1
- xx = mx*(m_brick/m_subdivMapping) + x;
- yy = my*(m_brick/m_subdivMapping) + y;
- p1.tu2 = ((float)(ox%5)*m_brick+xx+0.0f)/(m_brick*5);
- p1.tv2 = ((float)(oy%5)*m_brick+yy+0.0f)/(m_brick*5);
- p2.tu2 = ((float)(ox%5)*m_brick+xx+0.0f)/(m_brick*5);
- p2.tv2 = ((float)(oy%5)*m_brick+yy+1.0f)/(m_brick*5);
-
- // Correction for 1 pixel cover (*).
- p1.tu2 = (p1.tu2+pixel)*(1.0f-pixel)/(1.0f+pixel);
- p1.tv2 = (p1.tv2+pixel)*(1.0f-pixel)/(1.0f+pixel);
- p2.tu2 = (p2.tu2+pixel)*(1.0f-pixel)/(1.0f+pixel);
- p2.tv2 = (p2.tv2+pixel)*(1.0f-pixel)/(1.0f+pixel);
-#endif
-
- buffer->vertex[i++] = p1;
- buffer->vertex[i++] = p2;
- }
- m_engine->AddQuick(objRank, buffer, texName1, texName2, min, max, true);
- }
- }
- }
-
- transform.LoadIdentity();
- transform.Set(1, 4, o.x);
- transform.Set(3, 4, o.z);
- m_engine->SetObjectTransform(objRank, transform);
-
- return true;
-}
-
-// (*) There is 1 pixel cover around each of the 16 surfaces:
-//
-// |<--------------256-------------->|
-// | |<----------254---------->| |
-// |---|---|---|-- ... --|---|---|---|
-// | 0.0 1.0 |
-// | | | |
-// 0.0 min max 1.0
-//
-// The uv coordinates used for texturing are between min and max (instead of 0 and 1).
-// This allows to exclude the pixels situated in a margin of a pixel around the surface.
-
-
-// Seeks a materials based on theirs identifier.
-
-TerrainMaterial* CTerrain::LevelSearchMat(int id)
-{
- int i;
-
- for ( i=0 ; i<m_levelMatTotal ; i++ )
- {
- if ( id == m_levelMat[i].id )
- {
- return &m_levelMat[i];
- }
- }
-
- return 0;
-}
-
-// Chooses texture to use for a given square.
-
-void CTerrain::LevelTextureName(int x, int y, char *name, Math::Point &uv)
-{
- TerrainMaterial* tm;
-
- x /= m_brick/m_subdivMapping;
- y /= m_brick/m_subdivMapping;
-
- tm = LevelSearchMat(m_levelDot[x+y*m_levelDotSize].id);
- if ( tm == 0 )
- {
- strcpy(name, "xxx.tga");
- uv.x = 0.0f;
- uv.y = 0.0f;
- }
- else
- {
-//? sprintf(name, "%s.tga", tm->texName);
- strcpy(name, tm->texName);
- uv.x = tm->u;
- uv.y = tm->v;
- }
-}
-
-// Returns the height of the terrain.
-
-float CTerrain::LevelRetHeight(int x, int y)
-{
- int size;
-
- size = (m_mosaic*m_brick+1);
-
- if ( x < 0 ) x = 0;
- if ( x >= size ) x = size-1;
- if ( y < 0 ) y = 0;
- if ( y >= size ) y = size-1;
-
- return m_relief[x+y*size];
-}
-
-// Decide whether a point is using the materials.
-
-bool CTerrain::LevelGetDot(int x, int y, float min, float max, float slope)
-{
- float hc, h[4];
- int i;
-
- hc = LevelRetHeight(x, y);
- h[0] = LevelRetHeight(x+0, y+1);
- h[1] = LevelRetHeight(x+1, y+0);
- h[2] = LevelRetHeight(x+0, y-1);
- h[3] = LevelRetHeight(x-1, y+0);
-
- if ( hc < min ||
- hc > max ) return false;
-
- if ( slope == 0.0f )
- {
- return true;
- }
-
- if ( slope > 0.0f )
- {
- for ( i=0 ; i<4 ; i++ )
- {
- if ( fabs(hc-h[i]) >= slope )
- {
- return false;
- }
- }
- return true;
- }
-
- if ( slope < 0.0f )
- {
- for ( i=0 ; i<4 ; i++ )
- {
- if ( fabs(hc-h[i]) < -slope )
- {
- return false;
- }
- }
- return true;
- }
-
- return false;
-}
-
-// Seeks if material exists.
-// Returns the index within m_levelMat or -1 if there is not.
-// m_levelMat[i].id gives the identifier.
-
-int CTerrain::LevelTestMat(char *mat)
-{
- int i;
-
- for ( i=0 ; i<m_levelMatTotal ; i++ )
- {
- if ( m_levelMat[i].mat[0] == mat[0] &&
- m_levelMat[i].mat[1] == mat[1] &&
- m_levelMat[i].mat[2] == mat[2] &&
- m_levelMat[i].mat[3] == mat[3] ) return i;
- }
-
- return -1;
-}
-
-// Modifies the state of a point and its four neighbors, without testing if possible.
-
-void CTerrain::LevelSetDot(int x, int y, int id, char *mat)
-{
- TerrainMaterial* tm;
- int i, ii;
-
- tm = LevelSearchMat(id);
- if ( tm == 0 ) return;
-
- if ( tm->mat[0] != mat[0] ||
- tm->mat[1] != mat[1] ||
- tm->mat[2] != mat[2] ||
- tm->mat[3] != mat[3] ) // id incompatible with mat?
- {
- ii = LevelTestMat(mat);
- if ( ii == -1 ) return;
- id = m_levelMat[ii].id; // looking for a id compatible with mat
- }
-
- // Changes the point.
- m_levelDot[x+y*m_levelDotSize].id = id;
- m_levelDot[x+y*m_levelDotSize].mat[0] = mat[0];
- m_levelDot[x+y*m_levelDotSize].mat[1] = mat[1];
- m_levelDot[x+y*m_levelDotSize].mat[2] = mat[2];
- m_levelDot[x+y*m_levelDotSize].mat[3] = mat[3];
-
- // Changes the lower neighbor.
- if ( (x+0) >= 0 && (x+0) < m_levelDotSize &&
- (y-1) >= 0 && (y-1) < m_levelDotSize )
- {
- i = (x+0)+(y-1)*m_levelDotSize;
- if ( m_levelDot[i].mat[0] != mat[2] )
- {
- m_levelDot[i].mat[0] = mat[2];
- ii = LevelTestMat(m_levelDot[i].mat);
- if ( ii != -1 )
- {
- m_levelDot[i].id = m_levelMat[ii].id;
- }
- }
- }
-
- // Modifies the left neighbor.
- if ( (x-1) >= 0 && (x-1) < m_levelDotSize &&
- (y+0) >= 0 && (y+0) < m_levelDotSize )
- {
- i = (x-1)+(y+0)*m_levelDotSize;
- if ( m_levelDot[i].mat[1] != mat[3] )
- {
- m_levelDot[i].mat[1] = mat[3];
- ii = LevelTestMat(m_levelDot[i].mat);
- if ( ii != -1 )
- {
- m_levelDot[i].id = m_levelMat[ii].id;
- }
- }
- }
-
- // Changes the upper neighbor.
- if ( (x+0) >= 0 && (x+0) < m_levelDotSize &&
- (y+1) >= 0 && (y+1) < m_levelDotSize )
- {
- i = (x+0)+(y+1)*m_levelDotSize;
- if ( m_levelDot[i].mat[2] != mat[0] )
- {
- m_levelDot[i].mat[2] = mat[0];
- ii = LevelTestMat(m_levelDot[i].mat);
- if ( ii != -1 )
- {
- m_levelDot[i].id = m_levelMat[ii].id;
- }
- }
- }
-
- // Changes the right neighbor.
- if ( (x+1) >= 0 && (x+1) < m_levelDotSize &&
- (y+0) >= 0 && (y+0) < m_levelDotSize )
- {
- i = (x+1)+(y+0)*m_levelDotSize;
- if ( m_levelDot[i].mat[3] != mat[1] )
- {
- m_levelDot[i].mat[3] = mat[1];
- ii = LevelTestMat(m_levelDot[i].mat);
- if ( ii != -1 )
- {
- m_levelDot[i].id = m_levelMat[ii].id;
- }
- }
- }
-}
-
-// Tests if a material can give a place, according to its four neighbors.
-// If yes, puts the point.
-
-bool CTerrain::LevelIfDot(int x, int y, int id, char *mat)
-{
- char test[4];
-
- // Compatible with lower neighbor?
- if ( x+0 >= 0 && x+0 < m_levelDotSize &&
- y-1 >= 0 && y-1 < m_levelDotSize )
- {
- test[0] = mat[2];
- test[1] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[1];
- test[2] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[2];
- test[3] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[3];
-
- if ( LevelTestMat(test) == -1 ) return false;
- }
-
- // Compatible with left neighbor?
- if ( x-1 >= 0 && x-1 < m_levelDotSize &&
- y+0 >= 0 && y+0 < m_levelDotSize )
- {
- test[0] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[0];
- test[1] = mat[3];
- test[2] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[2];
- test[3] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[3];
-
- if ( LevelTestMat(test) == -1 ) return false;
- }
-
- // Compatible with upper neighbor?
- if ( x+0 >= 0 && x+0 < m_levelDotSize &&
- y+1 >= 0 && y+1 < m_levelDotSize )
- {
- test[0] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[0];
- test[1] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[1];
- test[2] = mat[0];
- test[3] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[3];
-
- if ( LevelTestMat(test) == -1 ) return false;
- }
-
- // Compatible with right neighbor?
- if ( x+1 >= 0 && x+1 < m_levelDotSize &&
- y+0 >= 0 && y+0 < m_levelDotSize )
- {
- test[0] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[0];
- test[1] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[1];
- test[2] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[2];
- test[3] = mat[1];
-
- if ( LevelTestMat(test) == -1 ) return false;
- }
-
- LevelSetDot(x, y, id, mat); // puts the point
- return true;
-}
-
-// Modifies the state of a point.
-
-bool CTerrain::LevelPutDot(int x, int y, int id)
-{
- TerrainMaterial *tm;
- char mat[4];
- int up, right, down, left;
-
- x /= m_brick/m_subdivMapping;
- y /= m_brick/m_subdivMapping;
-
- if ( x < 0 || x >= m_levelDotSize ||
- y < 0 || y >= m_levelDotSize ) return false;
-
- tm = LevelSearchMat(id);
- if ( tm == 0 ) return false;
-
- // Tries without changing neighbors.
- if ( LevelIfDot(x, y, id, tm->mat) ) return true;
-
- // Tries changing a single neighbor (4x).
- for ( up=0 ; up<m_levelMatMax ; up++ )
- {
- mat[0] = up;
- mat[1] = tm->mat[1];
- mat[2] = tm->mat[2];
- mat[3] = tm->mat[3];
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
-
- for ( right=0 ; right<m_levelMatMax ; right++ )
- {
- mat[0] = tm->mat[0];
- mat[1] = right;
- mat[2] = tm->mat[2];
- mat[3] = tm->mat[3];
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
-
- for ( down=0 ; down<m_levelMatMax ; down++ )
- {
- mat[0] = tm->mat[0];
- mat[1] = tm->mat[1];
- mat[2] = down;
- mat[3] = tm->mat[3];
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
-
- for ( left=0 ; left<m_levelMatMax ; left++ )
- {
- mat[0] = tm->mat[0];
- mat[1] = tm->mat[1];
- mat[2] = tm->mat[2];
- mat[3] = left;
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
-
- // Tries changing two neighbors (6x).
- for ( up=0 ; up<m_levelMatMax ; up++ )
- {
- for ( down=0 ; down<m_levelMatMax ; down++ )
- {
- mat[0] = up;
- mat[1] = tm->mat[1];
- mat[2] = down;
- mat[3] = tm->mat[3];
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
-
- for ( right=0 ; right<m_levelMatMax ; right++ )
- {
- for ( left=0 ; left<m_levelMatMax ; left++ )
- {
- mat[0] = tm->mat[0];
- mat[1] = right;
- mat[2] = tm->mat[2];
- mat[3] = left;
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
-
- for ( up=0 ; up<m_levelMatMax ; up++ )
- {
- for ( right=0 ; right<m_levelMatMax ; right++ )
- {
- mat[0] = up;
- mat[1] = right;
- mat[2] = tm->mat[2];
- mat[3] = tm->mat[3];
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
-
- for ( right=0 ; right<m_levelMatMax ; right++ )
- {
- for ( down=0 ; down<m_levelMatMax ; down++ )
- {
- mat[0] = tm->mat[0];
- mat[1] = right;
- mat[2] = down;
- mat[3] = tm->mat[3];
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
-
- for ( down=0 ; down<m_levelMatMax ; down++ )
- {
- for ( left=0 ; left<m_levelMatMax ; left++ )
- {
- mat[0] = tm->mat[0];
- mat[1] = tm->mat[1];
- mat[2] = down;
- mat[3] = left;
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
-
- for ( up=0 ; up<m_levelMatMax ; up++ )
- {
- for ( left=0 ; left<m_levelMatMax ; left++ )
- {
- mat[0] = up;
- mat[1] = tm->mat[1];
- mat[2] = tm->mat[2];
- mat[3] = left;
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
-
- // Tries changing all the neighbors.
- for ( up=0 ; up<m_levelMatMax ; up++ )
- {
- for ( right=0 ; right<m_levelMatMax ; right++ )
- {
- for ( down=0 ; down<m_levelMatMax ; down++ )
- {
- for ( left=0 ; left<m_levelMatMax ; left++ )
- {
- mat[0] = up;
- mat[1] = right;
- mat[2] = down;
- mat[3] = left;
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
- }
- }
-
- OutputDebugString("LevelPutDot error\n");
- return false;
-}
-
-// Initializes all the ground with a material.
-
-bool CTerrain::LevelInit(int id)
-{
- TerrainMaterial* tm;
- int i, j;
-
- tm = LevelSearchMat(id);
- if ( tm == 0 ) return false;
-
- for ( i=0 ; i<m_levelDotSize*m_levelDotSize ; i++ )
- {
- m_levelDot[i].id = id;
-
- for ( j=0 ; j<4 ; j++ )
- {
- m_levelDot[i].mat[j] = tm->mat[j];
- }
- }
-
- return true;
-}
-
-// Generates a level in the terrain.
-
-bool CTerrain::LevelGenerate(int *id, float min, float max,
- float slope, float freq,
- Math::Vector center, float radius)
-{
- TerrainMaterial *tm;
- Math::Vector pos;
- int i, numID, x, y, xx, yy, group, rnd;
- float dim;
-
- static char random[100] =
- {
- 84,25,12, 6,34,52,85,38,97,16,
- 21,31,65,19,62,40,72,22,48,61,
- 56,47, 8,53,73,77, 4,91,26,88,
- 76, 1,44,93,39,11,71,17,98,95,
- 88,83,18,30, 3,57,28,49,74, 9,
- 32,13,96,66,15,70,36,10,59,94,
- 45,86, 2,29,63,42,51, 0,79,27,
- 54, 7,20,69,89,23,64,43,81,92,
- 90,33,46,14,67,35,50, 5,87,60,
- 68,55,24,78,41,75,58,80,37,82,
- };
-
- i = 0;
- while ( id[i] != 0 )
- {
- tm = LevelSearchMat(id[i++]);
- if ( tm == 0 ) return false;
- }
- numID = i;
-
- group = m_brick/m_subdivMapping;
-
- if ( radius > 0.0f && radius < 5.0f ) // just a square?
- {
- dim = (m_mosaic*m_brick*m_size)/2.0f;
-
- xx = (int)((center.x+dim)/m_size);
- yy = (int)((center.z+dim)/m_size);
-
- x = xx/group;
- y = yy/group;
-
- tm = LevelSearchMat(id[0]);
- if ( tm != 0 )
- {
- LevelSetDot(x, y, id[0], tm->mat); // puts the point
- }
-//? LevelPutDot(xx,yy, id[0]);
- }
- else
- {
- for ( y=0 ; y<m_levelDotSize ; y++ )
- {
- for ( x=0 ; x<m_levelDotSize ; x++ )
- {
- if ( radius != 0.0f )
- {
- pos.x = ((float)x-m_levelDotSize/2.0f)*group*m_size;
- pos.z = ((float)y-m_levelDotSize/2.0f)*group*m_size;
- if ( Math::DistanceProjected(pos, center) > radius ) continue;
- }
-
- if ( freq < 100.0f )
- {
- rnd = random[(x%10)+(y%10)*10];
- if ( (float)rnd > freq ) continue;
- }
-
- xx = x*group + group/2;
- yy = y*group + group/2;
-
- if ( LevelGetDot(xx,yy, min, max, slope) )
- {
- rnd = random[(x%10)+(y%10)*10];
- i = rnd%numID;
- LevelPutDot(xx,yy, id[i]);
- }
- }
- }
- }
-
- return true;
-}
-
-// Initializes an table with empty levels.
-
-void CTerrain::LevelOpenTable()
-{
- int i, j;
-
- if ( !m_bLevelText ) return;
- if ( m_levelDot != 0 ) return; // already allocated
-
- m_levelDotSize = (m_mosaic*m_brick)/(m_brick/m_subdivMapping)+1;
- m_levelDot = (DotLevel*)malloc(m_levelDotSize*m_levelDotSize*sizeof(DotLevel));
-
- for ( i=0 ; i<m_levelDotSize*m_levelDotSize ; i++ )
- {
- for ( j=0 ; j<4 ; j++ )
- {
- m_levelDot[i].mat[j] = 0;
- }
- }
-}
-
-// Closes the level table.
-
-void CTerrain::LevelCloseTable()
-{
- free(m_levelDot);
- m_levelDot = 0;
-}
-
-
-
-// Creates all objects in a mesh square ground.
-
-bool CTerrain::CreateSquare(bool bMultiRes, int x, int y)
-{
- D3DMATERIAL7 mat;
- float min, max;
- int step, objRank;
-
- ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
- mat.diffuse.r = 1.0f;
- mat.diffuse.g = 1.0f;
- mat.diffuse.b = 1.0f;
- mat.ambient.r = 0.0f;
- mat.ambient.g = 0.0f;
- mat.ambient.b = 0.0f;
-
- objRank = m_engine->CreateObject();
- m_engine->SetObjectType(objRank, TYPETERRAIN); // it is a terrain
-
- m_objRank[x+y*m_mosaic] = objRank;
-
- if ( bMultiRes )
- {
- min = 0.0f;
- max = m_vision;
- max *= m_engine->RetClippingDistance();
- for ( step=0 ; step<m_depth ; step++ )
- {
- CreateMosaic(x, y, 1<<step, objRank, mat, min, max);
- min = max;
- max *= 2;
- if ( step == m_depth-1 ) max = g_HUGE;
- }
- }
- else
- {
- CreateMosaic(x, y, 1, objRank, mat, 0.0f, g_HUGE);
- }
-
- return true;
-}
-
-// Creates all objects of the terrain within the 3D engine.
-
-bool CTerrain::CreateObjects(bool bMultiRes)
-{
- int x, y;
-
- AdjustRelief();
-
- for ( y=0 ; y<m_mosaic ; y++ )
- {
- for ( x=0 ; x<m_mosaic ; x++ )
- {
- CreateSquare(bMultiRes, x, y);
- }
- }
-
- return true;
-}
-
-
-// Modifies the terrain's relief.
-// ATTENTION: ok only with m_depth = 2!
-
-bool CTerrain::Terraform(const Math::Vector &p1, const Math::Vector &p2, float height)
-{
- POINT tp1, tp2, pp1, pp2;
- float dim, avg;
- int x, y, size, nb;
-
- dim = (m_mosaic*m_brick*m_size)/2.0f;
- tp1.x = (int)((p1.x+dim+m_size/2.0f)/m_size);
- tp1.y = (int)((p1.z+dim+m_size/2.0f)/m_size);
- tp2.x = (int)((p2.x+dim+m_size/2.0f)/m_size);
- tp2.y = (int)((p2.z+dim+m_size/2.0f)/m_size);
-
- if ( tp1.x > tp2.x )
- {
- x = tp1.x;
- tp1.x = tp2.x;
- tp2.x = x;
- }
-
- if ( tp1.y > tp2.y )
- {
- y = tp1.y;
- tp1.y = tp2.y;
- tp2.y = y;
- }
-
- size = (m_mosaic*m_brick)+1;
-
- // Calculates the current average height.
- avg = 0.0f;
- nb = 0;
- for ( y=tp1.y ; y<=tp2.y ; y++ )
- {
- for ( x=tp1.x ; x<=tp2.x ; x++ )
- {
- avg += m_relief[x+y*size];
- nb ++;
- }
- }
- avg /= (float)nb;
-
- // Changes the description of the relief.
- for ( y=tp1.y ; y<=tp2.y ; y++ )
- {
- for ( x=tp1.x ; x<=tp2.x ; x++ )
- {
- m_relief[x+y*size] = avg+height;
-
- if ( x%m_brick == 0 && y%m_depth != 0 )
- {
- m_relief[(x+0)+(y-1)*size] = avg+height;
- m_relief[(x+0)+(y+1)*size] = avg+height;
- }
-
- if ( y%m_brick == 0 && x%m_depth != 0 )
- {
- m_relief[(x-1)+(y+0)*size] = avg+height;
- m_relief[(x+1)+(y+0)*size] = avg+height;
- }
- }
- }
- AdjustRelief();
-
- pp1.x = (tp1.x-2)/m_brick;
- pp1.y = (tp1.y-2)/m_brick;
- pp2.x = (tp2.x+1)/m_brick;
- pp2.y = (tp2.y+1)/m_brick;
-
- if ( pp1.x < 0 ) pp1.x = 0;
- if ( pp1.x >= m_mosaic ) pp1.x = m_mosaic-1;
- if ( pp1.y < 0 ) pp1.y = 0;
- if ( pp1.y >= m_mosaic ) pp1.y = m_mosaic-1;
-
- for ( y=pp1.y ; y<=pp2.y ; y++ )
- {
- for ( x=pp1.x ; x<=pp2.x ; x++ )
- {
- m_engine->DeleteObject(m_objRank[x+y*m_mosaic]);
- CreateSquare(m_bMultiText, x, y); // recreates the square
- }
- }
- m_engine->Update();
-
- return true;
-}
-
-
-// Management of the wind.
-
-void CTerrain::SetWind(Math::Vector speed)
-{
- m_wind = speed;
-}
-
-Math::Vector CTerrain::RetWind()
-{
- return m_wind;
-}
-
-
-// Gives the exact slope of the terrain of a place given.
-
-float CTerrain::RetFineSlope(const Math::Vector &pos)
-{
- Math::Vector n;
-
- if ( !GetNormal(n, pos) ) return 0.0f;
- return fabs(Math::RotateAngle(Math::Point(n.x, n.z).Length(), n.y)-Math::PI/2.0f);
-}
-
-// Gives the approximate slope of the terrain of a specific location.
-
-float CTerrain::RetCoarseSlope(const Math::Vector &pos)
-{
- float dim, level[4], min, max;
- int x, y;
-
- if ( m_relief == 0 ) return 0.0f;
-
- dim = (m_mosaic*m_brick*m_size)/2.0f;
-
- x = (int)((pos.x+dim)/m_size);
- y = (int)((pos.z+dim)/m_size);
-
- if ( x < 0 || x >= m_mosaic*m_brick ||
- y < 0 || y >= m_mosaic*m_brick ) return 0.0f;
-
- level[0] = m_relief[(x+0)+(y+0)*(m_mosaic*m_brick+1)];
- level[1] = m_relief[(x+1)+(y+0)*(m_mosaic*m_brick+1)];
- level[2] = m_relief[(x+0)+(y+1)*(m_mosaic*m_brick+1)];
- level[3] = m_relief[(x+1)+(y+1)*(m_mosaic*m_brick+1)];
-
- min = Math::Min(level[0], level[1], level[2], level[3]);
- max = Math::Max(level[0], level[1], level[2], level[3]);
-
- return atanf((max-min)/m_size);
-}
-
-// Gives the normal vector at the position p (x,-,z) of the ground.
-
-bool CTerrain::GetNormal(Math::Vector &n, const Math::Vector &p)
-{
- Math::Vector p1, p2, p3, p4;
- float dim;
- int x, y;
-
- dim = (m_mosaic*m_brick*m_size)/2.0f;
-
- x = (int)((p.x+dim)/m_size);
- y = (int)((p.z+dim)/m_size);
-
- if ( x < 0 || x > m_mosaic*m_brick ||
- y < 0 || y > m_mosaic*m_brick ) return false;
-
- p1 = RetVector(x+0, y+0);
- p2 = RetVector(x+1, y+0);
- p3 = RetVector(x+0, y+1);
- p4 = RetVector(x+1, y+1);
-
- if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) )
- {
- n = Math::NormalToPlane(p1,p2,p3);
- }
- else
- {
- n = Math::NormalToPlane(p2,p4,p3);
- }
- return true;
-}
-
-// Returns the height of the ground.
-
-float CTerrain::RetFloorLevel(const Math::Vector &p, bool bBrut, bool bWater)
-{
- Math::Vector p1, p2, p3, p4, ps;
- float dim, level;
- int x, y;
-
- dim = (m_mosaic*m_brick*m_size)/2.0f;
-
- x = (int)((p.x+dim)/m_size);
- y = (int)((p.z+dim)/m_size);
-
- if ( x < 0 || x > m_mosaic*m_brick ||
- y < 0 || y > m_mosaic*m_brick ) return false;
-
- p1 = RetVector(x+0, y+0);
- p2 = RetVector(x+1, y+0);
- p3 = RetVector(x+0, y+1);
- p4 = RetVector(x+1, y+1);
-
- ps = p;
- if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) )
- {
- if ( !IntersectY(p1, p2, p3, ps) ) return 0.0f;
- }
- else
- {
- if ( !IntersectY(p2, p4, p3, ps) ) return 0.0f;
- }
-
- if ( !bBrut ) AdjustBuildingLevel(ps);
-
- if ( bWater ) // not going underwater?
- {
- level = m_water->RetLevel();
- if ( ps.y < level ) ps.y = level; // not under water
- }
-
- return ps.y;
-}
-
-// Returns the height to the ground.
-// This height is positive when you are above the ground.
-
-float CTerrain::RetFloorHeight(const Math::Vector &p, bool bBrut, bool bWater)
-{
- Math::Vector p1, p2, p3, p4, ps;
- float dim, level;
- int x, y;
-
- dim = (m_mosaic*m_brick*m_size)/2.0f;
-
- x = (int)((p.x+dim)/m_size);
- y = (int)((p.z+dim)/m_size);
-
- if ( x < 0 || x > m_mosaic*m_brick ||
- y < 0 || y > m_mosaic*m_brick ) return false;
-
- p1 = RetVector(x+0, y+0);
- p2 = RetVector(x+1, y+0);
- p3 = RetVector(x+0, y+1);
- p4 = RetVector(x+1, y+1);
-
- ps = p;
- if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) )
- {
- if ( !IntersectY(p1, p2, p3, ps) ) return 0.0f;
- }
- else
- {
- if ( !IntersectY(p2, p4, p3, ps) ) return 0.0f;
- }
-
- if ( !bBrut ) AdjustBuildingLevel(ps);
-
- if ( bWater ) // not going underwater?
- {
- level = m_water->RetLevel();
- if ( ps.y < level ) ps.y = level; // not under water
- }
-
- return p.y-ps.y;
-}
-
-// Modifies the coordinate "y" of point "p" to rest on the ground floor.
-
-bool CTerrain::MoveOnFloor(Math::Vector &p, bool bBrut, bool bWater)
-{
- Math::Vector p1, p2, p3, p4;
- float dim, level;
- int x, y;
-
- dim = (m_mosaic*m_brick*m_size)/2.0f;
-
- x = (int)((p.x+dim)/m_size);
- y = (int)((p.z+dim)/m_size);
-
- if ( x < 0 || x > m_mosaic*m_brick ||
- y < 0 || y > m_mosaic*m_brick ) return false;
-
- p1 = RetVector(x+0, y+0);
- p2 = RetVector(x+1, y+0);
- p3 = RetVector(x+0, y+1);
- p4 = RetVector(x+1, y+1);
-
- if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) )
- {
- if ( !IntersectY(p1, p2, p3, p) ) return false;
- }
- else
- {
- if ( !IntersectY(p2, p4, p3, p) ) return false;
- }
-
- if ( !bBrut ) AdjustBuildingLevel(p);
-
- if ( bWater ) // not going underwater?
- {
- level = m_water->RetLevel();
- if ( p.y < level ) p.y = level; // not under water
- }
-
- return true;
-}
-
-// Modifies a coordinate so that it is on the ground.
-// Returns false if the initial coordinate was too far.
-
-bool CTerrain::ValidPosition(Math::Vector &p, float marging)
-{
- bool bOK = true;
- float limit;
-
- limit = m_mosaic*m_brick*m_size/2.0f - marging;
-
- if ( p.x < -limit )
- {
- p.x = -limit;
- bOK = false;
- }
-
- if ( p.z < -limit )
- {
- p.z = -limit;
- bOK = false;
- }
-
- if ( p.x > limit )
- {
- p.x = limit;
- bOK = false;
- }
-
- if ( p.z > limit )
- {
- p.z = limit;
- bOK = false;
- }
-
- return bOK;
-}
-
-
-
-// Empty the table of elevations.
-
-void CTerrain::FlushBuildingLevel()
-{
- m_buildingUsed = 0;
-}
-
-// Adds a new elevation for a building.
-
-bool CTerrain::AddBuildingLevel(Math::Vector center, float min, float max,
- float height, float factor)
-{
- int i;
-
- for ( i=0 ; i<m_buildingUsed ; i++ )
- {
- if ( center.x == m_buildingTable[i].center.x &&
- center.z == m_buildingTable[i].center.z )
- {
- goto update;
- }
- }
-
- if ( m_buildingUsed >= MAXBUILDINGLEVEL ) return false;
- i = m_buildingUsed++;
-
- update:
- m_buildingTable[i].center = center;
- m_buildingTable[i].min = min;
- m_buildingTable[i].max = max;
- m_buildingTable[i].level = RetFloorLevel(center, true);
- m_buildingTable[i].height = height;
- m_buildingTable[i].factor = factor;
- m_buildingTable[i].bboxMinX = center.x-max;
- m_buildingTable[i].bboxMaxX = center.x+max;
- m_buildingTable[i].bboxMinZ = center.z-max;
- m_buildingTable[i].bboxMaxZ = center.z+max;
-
- return true;
-}
-
-// Updates the elevation for a building when it was moved up (after a terraforming).
-
-bool CTerrain::UpdateBuildingLevel(Math::Vector center)
-{
- int i;
-
- for ( i=0 ; i<m_buildingUsed ; i++ )
- {
- if ( center.x == m_buildingTable[i].center.x &&
- center.z == m_buildingTable[i].center.z )
- {
- m_buildingTable[i].center = center;
- m_buildingTable[i].level = RetFloorLevel(center, true);
- return true;
- }
- }
- return false;
-}
-
-// Removes the elevation for a building when it was destroyed.
-
-bool CTerrain::DeleteBuildingLevel(Math::Vector center)
-{
- int i, j;
-
- for ( i=0 ; i<m_buildingUsed ; i++ )
- {
- if ( center.x == m_buildingTable[i].center.x &&
- center.z == m_buildingTable[i].center.z )
- {
- for ( j=i+1 ; j<m_buildingUsed ; j++ )
- {
- m_buildingTable[j-1] = m_buildingTable[j];
- }
- m_buildingUsed --;
- return true;
- }
- }
- return false;
-}
-
-// Returns the influence factor whether a position is on a possible rise.
-
-float CTerrain::RetBuildingFactor(const Math::Vector &p)
-{
- float dist;
- int i;
-
- for ( i=0 ; i<m_buildingUsed ; i++ )
- {
- if ( p.x < m_buildingTable[i].bboxMinX ||
- p.x > m_buildingTable[i].bboxMaxX ||
- p.z < m_buildingTable[i].bboxMinZ ||
- p.z > m_buildingTable[i].bboxMaxZ ) continue;
-
- dist = Math::DistanceProjected(p, m_buildingTable[i].center);
-
- if ( dist <= m_buildingTable[i].max )
- {
- return m_buildingTable[i].factor;
- }
- }
- return 1.0f; // it is normal on the ground
-}
-
-// Adjusts a position according to a possible rise.
-
-void CTerrain::AdjustBuildingLevel(Math::Vector &p)
-{
- Math::Vector border;
- float dist, base;
- int i;
-
- for ( i=0 ; i<m_buildingUsed ; i++ )
- {
- if ( p.x < m_buildingTable[i].bboxMinX ||
- p.x > m_buildingTable[i].bboxMaxX ||
- p.z < m_buildingTable[i].bboxMinZ ||
- p.z > m_buildingTable[i].bboxMaxZ ) continue;
-
- dist = Math::DistanceProjected(p, m_buildingTable[i].center);
-
- if ( dist > m_buildingTable[i].max ) continue;
-
- if ( dist < m_buildingTable[i].min )
- {
- p.y = m_buildingTable[i].level+m_buildingTable[i].height;
- return;
- }
-
-#if 0
- p.y = m_buildingTable[i].level;
- p.y += (m_buildingTable[i].max-dist)/
- (m_buildingTable[i].max-m_buildingTable[i].min)*
- m_buildingTable[i].height;
-
- base = RetFloorLevel(p, true);
- if ( p.y < base ) p.y = base;
-#else
- border.x = ((p.x-m_buildingTable[i].center.x)*m_buildingTable[i].max)/
- dist+m_buildingTable[i].center.x;
- border.z = ((p.z-m_buildingTable[i].center.z)*m_buildingTable[i].max)/
- dist+m_buildingTable[i].center.z;
-
- base = RetFloorLevel(border, true);
-
- p.y = (m_buildingTable[i].max-dist)/
- (m_buildingTable[i].max-m_buildingTable[i].min)*
- (m_buildingTable[i].level+m_buildingTable[i].height-base)+
- base;
-#endif
- return;
- }
-}
-
-
-// Returns the hardness of the ground in a given place.
-// The hardness determines the noise (SOUND_STEP and SOUND_BOUM).
-
-float CTerrain::RetHardness(const Math::Vector &p)
-{
- TerrainMaterial* tm;
- float factor, dim;
- int x, y, id;
-
- factor = RetBuildingFactor(p);
- if ( factor != 1.0f ) return 1.0f; // on building
-
- if ( m_levelDot == 0 ) return m_defHardness;
-
- dim = (m_mosaic*m_brick*m_size)/2.0f;
-
- x = (int)((p.x+dim)/m_size);
- y = (int)((p.z+dim)/m_size);
-
- if ( x < 0 || x > m_mosaic*m_brick ||
- y < 0 || y > m_mosaic*m_brick ) return m_defHardness;
-
- x /= m_brick/m_subdivMapping;
- y /= m_brick/m_subdivMapping;
-
- if ( x < 0 || x >= m_levelDotSize ||
- y < 0 || y >= m_levelDotSize ) return m_defHardness;
-
- id = m_levelDot[x+y*m_levelDotSize].id;
- tm = LevelSearchMat(id);
- if ( tm == 0 ) return m_defHardness;
-
- return tm->hardness;
-}
-
-
-// Shows the flat areas on the ground.
-
-void CTerrain::GroundFlat(Math::Vector pos)
-{
- Math::Vector p;
- float rapport, angle;
- int x, y, i;
- static char table[41*41];
-
-
- rapport = 3200.0f/1024.0f;
-
- for ( y=0 ; y<=40 ; y++ )
- {
- for ( x=0 ; x<=40 ; x++ )
- {
- i = x + y*41;
- table[i] = 0;
-
- p.x = (x-20)*rapport;
- p.z = (y-20)*rapport;
- p.y = 0.0f;
- if ( Math::Point(p.x, p.y).Length() > 20.0f*rapport ) continue;
-
- angle = RetFineSlope(pos+p);
-
- if ( angle < FLATLIMIT )
- {
- table[i] = 1;
- }
- else
- {
- table[i] = 2;
- }
- }
- }
-
- m_engine->GroundMarkCreate(pos, 40.0f, 0.001f, 15.0f, 0.001f, 41, 41, table);
-}
-
-
-// Calculates the radius of the largest flat area available.
-// This calculation is not optimized!
-
-float CTerrain::RetFlatZoneRadius(Math::Vector center, float max)
-{
- Math::Vector pos;
- Math::Point c, p;
- float ref, radius, angle, h;
- int i, nb;
-
- angle = RetFineSlope(center);
- if ( angle >= FLATLIMIT ) return 0.0f;
-
- ref = RetFloorLevel(center, true);
-
- radius = 1.0f;
- while ( radius <= max )
- {
- angle = 0.0f;
- nb = (int)(2.0f*Math::PI*radius);
- if ( nb < 8 ) nb = 8;
- for ( i=0 ; i<nb ; i++ )
- {
- c.x = center.x;
- c.y = center.z;
- p.x = center.x+radius;
- p.y = center.z;
- p = Math::RotatePoint(c, angle, p);
- pos.x = p.x;
- pos.z = p.y;
- h = RetFloorLevel(pos, true);
- if ( fabs(h-ref) > 1.0f ) return radius;
-
- angle += Math::PI*2.0f/8.0f;
- }
- radius += 1.0f;
- }
- return max;
-}
-
-
-
-// Specifies the maximum height of flight.
-
-void CTerrain::SetFlyingMaxHeight(float height)
-{
- m_flyingMaxHeight = height;
-}
-
-// Returns the maximum height of flight.
-
-float CTerrain::RetFlyingMaxHeight()
-{
- return m_flyingMaxHeight;
-}
-
-
-// Empty the limits table of flight.
-
-void CTerrain::FlushFlyingLimit()
-{
- m_flyingMaxHeight = 280.0f;
- m_flyingLimitTotal = 0;
-}
-
-// Empty the limits table of flight.
-
-bool CTerrain::AddFlyingLimit(Math::Vector center,
- float extRadius, float intRadius,
- float maxHeight)
-{
- int i;
-
- if ( m_flyingLimitTotal >= MAXFLYINGLIMIT ) return false;
-
- i = m_flyingLimitTotal;
- m_flyingLimit[i].center = center;
- m_flyingLimit[i].extRadius = extRadius;
- m_flyingLimit[i].intRadius = intRadius;
- m_flyingLimit[i].maxHeight = maxHeight;
- m_flyingLimitTotal = i+1;
-
- return true;
-}
-
-// Returns the maximum height of flight.
-
-float CTerrain::RetFlyingLimit(Math::Vector pos, bool bNoLimit)
-{
- float dist, h;
- int i;
-
- if ( bNoLimit ) return 280.0f;
- if ( m_flyingLimitTotal == 0 ) return m_flyingMaxHeight;
-
- for ( i=0 ; i<m_flyingLimitTotal ; i++ )
- {
- dist = Math::DistanceProjected(pos, m_flyingLimit[i].center);
-
- if ( dist >= m_flyingLimit[i].extRadius ) continue;
-
- if ( dist <= m_flyingLimit[i].intRadius )
- {
- return m_flyingLimit[i].maxHeight;
- }
-
- dist -= m_flyingLimit[i].intRadius;
-
- h = dist*(m_flyingMaxHeight-m_flyingLimit[i].maxHeight)/
- (m_flyingLimit[i].extRadius-m_flyingLimit[i].intRadius);
-
- return h + m_flyingLimit[i].maxHeight;
- }
-
- return m_flyingMaxHeight;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// terrain.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "old/d3dutil.h"
+#include "common/language.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "old/modfile.h"
+#include "old/water.h"
+#include "old/terrain.h"
+
+
+const int BMPHEAD = 1078;
+
+
+
+// Constructor of the terrain.
+
+CTerrain::CTerrain(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_TERRAIN, this);
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+
+ m_mosaic = 20;
+ m_brick = 1<<4;
+ m_size = 10.0f;
+ m_vision = 200.0f;
+ m_relief = 0;
+ m_texture = 0;
+ m_objRank = 0;
+ m_scaleMapping = 0.01f;
+ m_scaleRelief = 1.0f;
+ m_subdivMapping = 1;
+ m_depth = 2;
+ m_texBaseName[0]= 0;
+ m_texBaseExt[0] = 0;
+ m_bMultiText = true;
+ m_bLevelText = false;
+ m_resources = 0;
+ m_levelMatTotal = 0;
+ m_levelMatMax = 0;
+ m_levelDot = 0;
+ m_wind = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_defHardness = 0.5f;
+
+ FlushBuildingLevel();
+ FlushFlyingLimit();
+}
+
+// Destructor of the terrain.
+
+CTerrain::~CTerrain()
+{
+ free(m_relief);
+ free(m_texture);
+ free(m_objRank);
+ free(m_resources);
+}
+
+
+// Generates a new flat terrain.
+// The terrain is composed of mosaics, themselves composed of bricks.
+// Each brick is composed of two triangles.
+// mosaic: number of mosaics along the axes X and Z
+// brick: number of bricks (power of 2)
+// size: size of a brick along the axes X and Z
+// vision: vision before a change of resolution
+// scaleMapping: scale textures for mapping
+//
+// ^ z
+// | <---> brick*size
+// +---+---+---+---+
+// | | | |_|_| mosaic = 4
+// | | | | | | brick = 2 (brickP2=1)
+// +---+---+---+---+
+// |\ \| | | |
+// |\ \| | | |
+// +---+---o---+---+---> x
+// | | | | |
+// | | | | |
+// +---+---+---+---+
+// | | | | | The land is viewed from above here.
+// | | | | |
+// +---+---+---+---+
+// <---------------> mosaic*brick*size
+
+bool CTerrain::Generate(int mosaic, int brickP2, float size, float vision,
+ int depth, float hardness)
+{
+ int dim;
+
+ m_mosaic = mosaic;
+ m_brick = 1<<brickP2;
+ m_size = size;
+ m_vision = vision;
+ m_depth = depth;
+ m_defHardness = hardness;
+
+ m_engine->SetTerrainVision(vision);
+
+ m_bMultiText = true;
+ m_bLevelText = false;
+ m_scaleMapping = 1.0f/(m_brick*m_size);
+ m_subdivMapping = 1;
+
+ dim = (m_mosaic*m_brick+1)*(m_mosaic*m_brick+1);
+ m_relief = (float*)malloc(sizeof(float)*dim);
+ ZeroMemory(m_relief, sizeof(float)*dim);
+
+ dim = m_mosaic*m_subdivMapping*m_mosaic*m_subdivMapping;
+ m_texture = (int*)malloc(sizeof(int)*dim);
+ ZeroMemory(m_texture, sizeof(int)*dim);
+
+ dim = m_mosaic*m_mosaic;
+ m_objRank = (int*)malloc(sizeof(int)*dim);
+ ZeroMemory(m_objRank, sizeof(int)*dim);
+
+ return true;
+}
+
+
+int CTerrain::RetMosaic()
+{
+ return m_mosaic;
+}
+
+int CTerrain::RetBrick()
+{
+ return m_brick;
+}
+
+float CTerrain::RetSize()
+{
+ return m_size;
+}
+
+float CTerrain::RetScaleRelief()
+{
+ return m_scaleRelief;
+}
+
+
+// Initializes the names of textures to use for the land.
+
+bool CTerrain::InitTextures(char* baseName, int* table, int dx, int dy)
+{
+ int x, y;
+ char* p;
+
+ m_bLevelText = false;
+
+ strcpy(m_texBaseName, baseName);
+ p = strchr(m_texBaseName, '.'); // p <- ^beginning of the extension
+ if ( p == 0 )
+ {
+ strcpy(m_texBaseExt, ".tga");
+ }
+ else
+ {
+ strcpy(m_texBaseExt, p); // m_texBaseExt <- ".tga" or ".bmp"
+ *p = 0; // m_texBaseName <- name without extension
+ }
+
+ for ( y=0 ; y<m_mosaic*m_subdivMapping ; y++ )
+ {
+ for ( x=0 ; x<m_mosaic*m_subdivMapping ; x++ )
+ {
+ m_texture[x+y*m_mosaic] = table[(x%dx)+(y%dy)*dx];
+ }
+ }
+ return true;
+}
+
+
+// Empties level.
+
+void CTerrain::LevelFlush()
+{
+ m_levelMatTotal = 0;
+ m_levelMatMax = 0;
+ m_levelID = 1000;
+ LevelCloseTable();
+}
+
+// Initializes the names of textures to use for the land.
+
+bool CTerrain::LevelMaterial(int id, char* baseName, float u, float v,
+ int up, int right, int down, int left,
+ float hardness)
+{
+ int i;
+
+ i = m_levelMatTotal;
+ if ( i >= MAXMATTERRAIN-1 ) return false;
+
+ LevelOpenTable();
+
+ if ( id == 0 )
+ {
+ id = m_levelID++; // puts an ID internal standard
+ }
+
+ strcpy(m_levelMat[i].texName, baseName);
+ m_levelMat[i].id = id;
+ m_levelMat[i].u = u;
+ m_levelMat[i].v = v;
+ m_levelMat[i].mat[0] = up;
+ m_levelMat[i].mat[1] = right;
+ m_levelMat[i].mat[2] = down;
+ m_levelMat[i].mat[3] = left;
+ m_levelMat[i].hardness = hardness;
+
+ if ( m_levelMatMax < up+1 ) m_levelMatMax = up+1;
+ if ( m_levelMatMax < right+1 ) m_levelMatMax = right+1;
+ if ( m_levelMatMax < down+1 ) m_levelMatMax = down+1;
+ if ( m_levelMatMax < left+1 ) m_levelMatMax = left+1;
+
+ m_bLevelText = true;
+ m_subdivMapping = 4;
+
+ m_levelMatTotal ++;
+ return true;
+}
+
+
+// Load relief from a BMP file.
+// The size of the image must be dimension dx and dy with dx=dy=(mosaic*brick)+1.
+// The image must be 8 bits/pixel, 256 colors with a standard pallet.
+
+// Converts coordinated image (x;y) -> world (x;-;z) :
+// Wx = 5*Ix-400
+// Wz = -(5*Iy-400)
+
+// Converts coordinated world (x;-;z) -> image (x;y) :
+// Ix = (400+Wx)/5
+// Iy = (400-Wz)/5
+
+bool CTerrain::ResFromBMP(const char* filename)
+{
+ FILE* file;
+ int size, sizem;
+
+ file = fopen(filename, "rb");
+ if ( file == NULL ) return false;
+
+ size = (m_mosaic*m_brick)+1;
+ sizem = ((size+4-1)/4)*4; // upper size multiple of 4
+
+ if ( m_resources != 0 )
+ {
+ free(m_resources);
+ }
+
+ m_resources = (unsigned char*)malloc(BMPHEAD+sizem*size);
+ fread(m_resources, BMPHEAD+sizem*size, 1, file);
+
+ if ( m_resources[18] != (size&0xff) || m_resources[19] != (size>>8) ||
+ m_resources[22] != (size&0xff) || m_resources[23] != (size>>8) )
+ {
+ free(m_resources);
+ m_resources = 0;
+ fclose(file);
+ return false;
+ }
+
+ fclose(file);
+ return true;
+}
+
+// Returns the resource type available underground.
+
+TerrainRes CTerrain::RetResource(const Math::Vector &p)
+{
+ int x, y, size, sizem, ress;
+
+ if ( m_resources == 0 ) return TR_NULL;
+
+ x = (int)((p.x + (m_mosaic*m_brick*m_size)/2.0f)/m_size);
+ y = (int)((p.z + (m_mosaic*m_brick*m_size)/2.0f)/m_size);
+
+ if ( x < 0 || x > m_mosaic*m_brick ||
+ y < 0 || y > m_mosaic*m_brick ) return TR_NULL;
+
+ size = (m_mosaic*m_brick)+1;
+ sizem = ((size+4-1)/4)*4; // upper size multiple of 4
+
+ ress = m_resources[BMPHEAD+x+sizem*y];
+ if ( ress == 5 ) return TR_STONE; // red?
+ if ( ress == 35 ) return TR_URANIUM; // yellow?
+ if ( ress == 30 ) return TR_POWER; // green?
+ if ( ress == 24 ) return TR_KEYa; // ~green?
+ if ( ress == 25 ) return TR_KEYb; // ~green?
+ if ( ress == 26 ) return TR_KEYc; // ~green?
+ if ( ress == 27 ) return TR_KEYd; // ~green?
+
+ return TR_NULL;
+}
+
+
+// Initializes a completely flat terrain.
+
+void CTerrain::FlushRelief()
+{
+ free(m_relief);
+ m_relief = 0;
+}
+
+// Load relief from a BMP file.
+// The size of the image must be dimension dx and dy with dx=dy=(mosaic*brick)+1.
+// The image must be 8 bits/pixel, 256 gray scale:
+// white = ground (y=0)
+// black = mountain (y=255*scaleRelief)
+
+// Converts coordinated image(x;y) -> world (x;-;z) :
+// Wx = 5*Ix-400
+// Wz = -(5*Iy-400)
+
+// Converts coordinated world (x;-;z) -> image (x;y) :
+// Ix = (400+Wx)/5
+// Iy = (400-Wz)/5
+
+bool CTerrain::ReliefFromBMP(const char* filename, float scaleRelief,
+ bool adjustBorder)
+{
+ FILE* file;
+ unsigned char* buffer;
+ int size, sizem, x, y;
+ float level, limit, dist, border;
+
+ m_scaleRelief = scaleRelief;
+
+ file = fopen(filename, "rb");
+ if ( file == NULL ) return false;
+
+ size = (m_mosaic*m_brick)+1;
+ sizem = ((size+4-1)/4)*4; // upper size multiple of 4
+
+ buffer = (unsigned char*)malloc(BMPHEAD+sizem*size);
+ fread(buffer, BMPHEAD+sizem*size, 1, file);
+
+ if ( buffer[18] != (size&0xff) || buffer[19] != (size>>8) ||
+ buffer[22] != (size&0xff) || buffer[23] != (size>>8) )
+ {
+ free(buffer);
+ fclose(file);
+ return false;
+ }
+
+ limit = 0.9f;
+ for ( y=0 ; y<size ; y++ )
+ {
+ for ( x=0 ; x<size ; x++ )
+ {
+ level = (255-buffer[BMPHEAD+x+sizem*y])*scaleRelief;
+
+//? dist = Length((float)(x-size/2), (float)(y-size/2));
+ dist = Math::Max(fabs((float)(x-size/2)), fabs((float)(y-size/2)));
+ dist = dist/(float)(size/2);
+ if ( dist > limit && adjustBorder )
+ {
+ dist = (dist-limit)/(1.0f-limit); // 0..1
+ if ( dist > 1.0f ) dist = 1.0f;
+ border = 300.0f+Math::Rand()*20.0f;
+ level = level+dist*(border-level);
+ }
+
+ m_relief[x+y*size] = level;
+ }
+ }
+
+ free(buffer);
+ fclose(file);
+ return true;
+}
+
+// Adds a point of elevation in the buffer of relief.
+
+bool CTerrain::ReliefAddDot(Math::Vector pos, float scaleRelief)
+{
+ float dim;
+ int size, x, y;
+
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+ size = (m_mosaic*m_brick)+1;
+
+ pos.x = (pos.x+dim)/m_size;
+ pos.z = (pos.z+dim)/m_size;
+
+ x = (int)pos.x;
+ y = (int)pos.z;
+
+ if ( x < 0 || x >= size ||
+ y < 0 || y >= size ) return false;
+
+ if ( m_relief[x+y*size] < pos.y*scaleRelief )
+ {
+ m_relief[x+y*size] = pos.y*scaleRelief;
+ }
+ return true;
+}
+
+// Load relief from a DXF file.
+
+bool CTerrain::ReliefFromDXF(const char* filename, float scaleRelief)
+{
+ FILE* file = NULL;
+ char line[100];
+ int command, rankSommet, nbSommet, nbFace, size;
+ Math::Vector* table;
+ bool bWaitNbSommet;
+ bool bWaitNbFace;
+ bool bWaitSommetX;
+ bool bWaitSommetY;
+ bool bWaitSommetZ;
+ bool bWaitFaceX;
+ bool bWaitFaceY;
+ bool bWaitFaceZ;
+ float x,y,z;
+ int p1,p2,p3;
+
+ ZeroMemory(m_relief, sizeof(float)*(m_mosaic*m_brick+1)*(m_mosaic*m_brick+1));
+
+ file = fopen(filename, "r");
+ if ( file == NULL ) return false;
+
+ size = (m_mosaic*m_brick)+1;
+ table = (Math::Vector*)malloc(sizeof(Math::Vector)*size*size);
+
+ rankSommet = 0;
+ bWaitNbSommet = false;
+ bWaitNbFace = false;
+ bWaitSommetX = false;
+ bWaitSommetY = false;
+ bWaitSommetZ = false;
+ bWaitFaceX = false;
+ bWaitFaceY = false;
+ bWaitFaceZ = false;
+
+ while ( fgets(line, 100, file) != NULL )
+ {
+ sscanf(line, "%d", &command);
+ if ( fgets(line, 100, file) == NULL ) break;
+
+ if ( command == 66 )
+ {
+ bWaitNbSommet = true;
+ }
+
+ if ( command == 71 && bWaitNbSommet )
+ {
+ bWaitNbSommet = false;
+ sscanf(line, "%d", &nbSommet);
+ if ( nbSommet > size*size ) nbSommet = size*size;
+ rankSommet = 0;
+ bWaitNbFace = true;
+ }
+
+ if ( command == 72 && bWaitNbFace )
+ {
+ bWaitNbFace = false;
+ sscanf(line, "%d", &nbFace);
+ bWaitSommetX = true;
+ }
+
+ if ( command == 10 && bWaitSommetX )
+ {
+ bWaitSommetX = false;
+ sscanf(line, "%f", &x);
+ bWaitSommetY = true;
+ }
+
+ if ( command == 20 && bWaitSommetY )
+ {
+ bWaitSommetY = false;
+ sscanf(line, "%f", &y);
+ bWaitSommetZ = true;
+ }
+
+ if ( command == 30 && bWaitSommetZ )
+ {
+ bWaitSommetZ = false;
+ sscanf(line, "%f", &z);
+
+ nbSommet --;
+ if ( nbSommet >= 0 )
+ {
+ Math::Vector p(x,z,y); // permutation of Y and Z!
+ table[rankSommet++] = p;
+ bWaitSommetX = true;
+ }
+ else
+ {
+ bWaitFaceX = true;
+ }
+ }
+
+ if ( command == 71 && bWaitFaceX )
+ {
+ bWaitFaceX = false;
+ sscanf(line, "%d", &p1);
+ if ( p1 < 0 ) p1 = -p1;
+ bWaitFaceY = true;
+ }
+
+ if ( command == 72 && bWaitFaceY )
+ {
+ bWaitFaceY = false;
+ sscanf(line, "%d", &p2);
+ if ( p2 < 0 ) p2 = -p2;
+ bWaitFaceZ = true;
+ }
+
+ if ( command == 73 && bWaitFaceZ )
+ {
+ bWaitFaceZ = false;
+ sscanf(line, "%d", &p3);
+ if ( p3 < 0 ) p3 = -p3;
+
+ nbFace --;
+ if ( nbFace >= 0 )
+ {
+ ReliefAddDot(table[p3-1], scaleRelief);
+ ReliefAddDot(table[p2-1], scaleRelief);
+ ReliefAddDot(table[p1-1], scaleRelief);
+ bWaitFaceX = true;
+ }
+ }
+
+ }
+
+ free(table);
+ fclose(file);
+ return true;
+}
+
+
+// Adjusts a position so that it does not exceed the boundaries.
+
+void CTerrain::LimitPos(Math::Vector &pos)
+{
+ float dim;
+
+#if _TEEN
+ dim = (m_mosaic*m_brick*m_size)/2.0f*0.98f;
+#else
+ dim = (m_mosaic*m_brick*m_size)/2.0f*0.92f;
+#endif
+
+ if ( pos.x < -dim ) pos.x = -dim;
+ if ( pos.x > dim ) pos.x = dim;
+ if ( pos.z < -dim ) pos.z = -dim;
+ if ( pos.z > dim ) pos.z = dim;
+}
+
+
+// Adjust the edges of each mosaic to be compatible with all lower resolutions.
+
+void CTerrain::AdjustRelief()
+{
+ int x, y, xx, yy, ii, b;
+ float level1, level2;
+
+ if ( m_depth == 1 ) return;
+
+ ii = m_mosaic*m_brick+1;
+ b = 1<<(m_depth-1);
+
+ for ( y=0 ; y<m_mosaic*m_brick ; y+=b )
+ {
+ for ( x=0 ; x<m_mosaic*m_brick ; x+=b )
+ {
+ yy = 0;
+ if ( (y+yy)%m_brick == 0 )
+ {
+ level1 = m_relief[(x+0)+(y+yy)*ii];
+ level2 = m_relief[(x+b)+(y+yy)*ii];
+ for ( xx=1 ; xx<b ; xx++ )
+ {
+ m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*xx+level1;
+ }
+ }
+
+ yy = b;
+ if ( (y+yy)%m_brick == 0 )
+ {
+ level1 = m_relief[(x+0)+(y+yy)*ii];
+ level2 = m_relief[(x+b)+(y+yy)*ii];
+ for ( xx=1 ; xx<b ; xx++ )
+ {
+ m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*xx+level1;
+ }
+ }
+
+ xx = 0;
+ if ( (x+xx)%m_brick == 0 )
+ {
+ level1 = m_relief[(x+xx)+(y+0)*ii];
+ level2 = m_relief[(x+xx)+(y+b)*ii];
+ for ( yy=1 ; yy<b ; yy++ )
+ {
+ m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*yy+level1;
+ }
+ }
+
+ xx = b;
+ if ( (x+xx)%m_brick == 0 )
+ {
+ level1 = m_relief[(x+xx)+(y+0)*ii];
+ level2 = m_relief[(x+xx)+(y+b)*ii];
+ for ( yy=1 ; yy<b ; yy++ )
+ {
+ m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*yy+level1;
+ }
+ }
+ }
+ }
+}
+
+
+// Calculates a vector of the terrain.
+
+Math::Vector CTerrain::RetVector(int x, int y)
+{
+ Math::Vector p;
+
+ p.x = x*m_size - (m_mosaic*m_brick*m_size)/2;
+ p.z = y*m_size - (m_mosaic*m_brick*m_size)/2;
+
+ if ( m_relief != 0 &&
+ x >= 0 && x <= m_mosaic*m_brick &&
+ y >= 0 && y <= m_mosaic*m_brick )
+ {
+ p.y = m_relief[x+y*(m_mosaic*m_brick+1)];
+ }
+ else
+ {
+ p.y = 0.0f;
+ }
+
+ return p;
+}
+
+// Calculates a vertex of the terrain.
+// Calculates a normal soft, taking into account the six adjacent triangles:
+//
+// ^ y
+// |
+// b---c---+
+// |\ |\ |
+// | \| \|
+// a---o---d
+// |\ |\ |
+// | \| \|
+// +---f---e--> x
+
+D3DVERTEX2 CTerrain::RetVertex(int x, int y, int step)
+{
+ D3DVERTEX2 v;
+ Math::Vector o, oo, a,b,c,d,e,f, n, s;
+ int brick;
+
+ o = RetVector(x, y);
+ v.x = o.x;
+ v.y = o.y;
+ v.z = o.z;
+
+ a = RetVector(x-step, y );
+ b = RetVector(x-step, y+step);
+ c = RetVector(x, y+step);
+ d = RetVector(x+step, y );
+ e = RetVector(x+step, y-step);
+ f = RetVector(x, y-step);
+
+ s = Math::Vector(0.0f, 0.0f, 0.0f);
+
+ if ( x-step >= 0 && y+step <= m_mosaic*m_brick+1 )
+ {
+ s += Math::NormalToPlane(b,a,o);
+ s += Math::NormalToPlane(c,b,o);
+ }
+
+ if ( x+step <= m_mosaic*m_brick+1 && y+step <= m_mosaic*m_brick+1 )
+ {
+ s += Math::NormalToPlane(d,c,o);
+ }
+
+ if ( x+step <= m_mosaic*m_brick+1 && y-step >= 0 )
+ {
+ s += Math::NormalToPlane(e,d,o);
+ s += Math::NormalToPlane(f,e,o);
+ }
+
+ if ( x-step >= 0 && y-step >= 0 )
+ {
+ s += Math::NormalToPlane(a,f,o);
+ }
+
+ s = Normalize(s);
+ v.nx = s.x;
+ v.ny = s.y;
+ v.nz = s.z;
+
+ if ( m_bMultiText )
+ {
+ brick = m_brick/m_subdivMapping;
+ oo = RetVector((x/brick)*brick, (y/brick)*brick);
+ o = RetVector(x, y);
+ v.tu = (o.x-oo.x)*m_scaleMapping*m_subdivMapping;
+ v.tv = 1.0f - (o.z-oo.z)*m_scaleMapping*m_subdivMapping;
+ }
+ else
+ {
+ v.tu = o.x*m_scaleMapping;
+ v.tv = o.z*m_scaleMapping;
+ }
+
+ return v;
+}
+
+// Creates all objects of a mosaic.
+// The origin of mosaic is his center.
+//
+// ^ z
+// |
+// | 2---4---6--
+// | |\ |\ |\
+// | | \| \|
+// | 1---3---5--- ...
+// |
+// +-------------------> x
+
+bool CTerrain::CreateMosaic(int ox, int oy, int step, int objRank,
+ const D3DMATERIAL7 &mat,
+ float min, float max)
+{
+ Math::Matrix transform;
+ D3DVERTEX2 o, p1, p2;
+ D3DObjLevel6* buffer;
+ Math::Point uv;
+ int brick, total, size, mx, my, x, y, xx, yy, i;
+ char texName1[20];
+ char texName2[20];
+ float pixel, dp;
+
+ if ( step == 1 && m_engine->RetGroundSpot() )
+ {
+ i = (ox/5) + (oy/5)*(m_mosaic/5);
+ sprintf(texName2, "shadow%.2d.tga", i);
+ }
+ else
+ {
+ texName2[0] = 0;
+ }
+
+ brick = m_brick/m_subdivMapping;
+
+ o = RetVertex(ox*m_brick+m_brick/2, oy*m_brick+m_brick/2, step);
+ total = ((brick/step)+1)*2;
+ size = sizeof(D3DObjLevel6)+sizeof(D3DVERTEX2)*(total-1);
+
+ pixel = 1.0f/256.0f; // 1 pixel cover (*)
+//? dp = 0.5f/512.0f;
+ dp = 1.0f/512.0f;
+
+ for ( my=0 ; my<m_subdivMapping ; my++ )
+ {
+ for ( mx=0 ; mx<m_subdivMapping ; mx++ )
+ {
+ if ( m_bLevelText )
+ {
+ xx = ox*m_brick + mx*(m_brick/m_subdivMapping);
+ yy = oy*m_brick + my*(m_brick/m_subdivMapping);
+ LevelTextureName(xx, yy, texName1, uv);
+ }
+ else
+ {
+ i = (ox*m_subdivMapping+mx)+(oy*m_subdivMapping+my)*m_mosaic;
+ sprintf(texName1, "%s%.3d%s", m_texBaseName, m_texture[i], m_texBaseExt);
+ }
+
+ for ( y=0 ; y<brick ; y+=step )
+ {
+ buffer = (D3DObjLevel6*)malloc(size);
+ ZeroMemory(buffer, sizeof(D3DObjLevel6));
+ buffer->totalPossible = total;
+ buffer->totalUsed = total;
+ buffer->type = D3DTYPE6S;
+ buffer->material = mat;
+ if ( m_bMultiText )
+ {
+//? buffer->state = D3DSTATENORMAL;
+ buffer->state = D3DSTATEWRAP;
+ }
+ else
+ {
+ buffer->state = D3DSTATEWRAP;
+ }
+ buffer->state |= D3DSTATESECOND;
+ if ( step == 1 )
+ {
+ buffer->state |= D3DSTATEDUALb;
+ }
+ i = 0;
+ for ( x=0 ; x<=brick ; x+=step )
+ {
+ p1 = RetVertex(ox*m_brick+mx*brick+x, oy*m_brick+my*brick+y+0 , step);
+ p2 = RetVertex(ox*m_brick+mx*brick+x, oy*m_brick+my*brick+y+step, step);
+ p1.x -= o.x; p1.z -= o.z;
+ p2.x -= o.x; p2.z -= o.z;
+
+ if ( m_bMultiText )
+ {
+ if ( x == 0 )
+ {
+ p1.tu = 0.0f+(0.5f/256.0f);
+ p2.tu = 0.0f+(0.5f/256.0f);
+ }
+ if ( x == brick )
+ {
+ p1.tu = 1.0f-(0.5f/256.0f);
+ p2.tu = 1.0f-(0.5f/256.0f);
+ }
+ if ( y == 0 )
+ {
+ p1.tv = 1.0f-(0.5f/256.0f);
+ }
+ if ( y == brick-step )
+ {
+ p2.tv = 0.0f+(0.5f/256.0f);
+ }
+ }
+
+ if ( m_bLevelText )
+ {
+ p1.tu /= m_subdivMapping; // 0..1 -> 0..0.25
+ p1.tv /= m_subdivMapping;
+ p2.tu /= m_subdivMapping;
+ p2.tv /= m_subdivMapping;
+
+ if ( x == 0 )
+ {
+ p1.tu = 0.0f+dp;
+ p2.tu = 0.0f+dp;
+ }
+ if ( x == brick )
+ {
+ p1.tu = (1.0f/m_subdivMapping)-dp;
+ p2.tu = (1.0f/m_subdivMapping)-dp;
+ }
+ if ( y == 0 )
+ {
+ p1.tv = (1.0f/m_subdivMapping)-dp;
+ }
+ if ( y == brick-step )
+ {
+ p2.tv = 0.0f+dp;
+ }
+
+ p1.tu += uv.x;
+ p1.tv += uv.y;
+ p2.tu += uv.x;
+ p2.tv += uv.y;
+ }
+
+#if 1
+ xx = mx*(m_brick/m_subdivMapping) + x;
+ yy = my*(m_brick/m_subdivMapping) + y;
+ p1.tu2 = ((float)(ox%5)*m_brick+xx+0.0f)/(m_brick*5);
+ p1.tv2 = ((float)(oy%5)*m_brick+yy+0.0f)/(m_brick*5);
+ p2.tu2 = ((float)(ox%5)*m_brick+xx+0.0f)/(m_brick*5);
+ p2.tv2 = ((float)(oy%5)*m_brick+yy+1.0f)/(m_brick*5);
+
+ // Correction for 1 pixel cover (*).
+ p1.tu2 = (p1.tu2+pixel)*(1.0f-pixel)/(1.0f+pixel);
+ p1.tv2 = (p1.tv2+pixel)*(1.0f-pixel)/(1.0f+pixel);
+ p2.tu2 = (p2.tu2+pixel)*(1.0f-pixel)/(1.0f+pixel);
+ p2.tv2 = (p2.tv2+pixel)*(1.0f-pixel)/(1.0f+pixel);
+#endif
+
+ buffer->vertex[i++] = p1;
+ buffer->vertex[i++] = p2;
+ }
+ m_engine->AddQuick(objRank, buffer, texName1, texName2, min, max, true);
+ }
+ }
+ }
+
+ transform.LoadIdentity();
+ transform.Set(1, 4, o.x);
+ transform.Set(3, 4, o.z);
+ m_engine->SetObjectTransform(objRank, transform);
+
+ return true;
+}
+
+// (*) There is 1 pixel cover around each of the 16 surfaces:
+//
+// |<--------------256-------------->|
+// | |<----------254---------->| |
+// |---|---|---|-- ... --|---|---|---|
+// | 0.0 1.0 |
+// | | | |
+// 0.0 min max 1.0
+//
+// The uv coordinates used for texturing are between min and max (instead of 0 and 1).
+// This allows to exclude the pixels situated in a margin of a pixel around the surface.
+
+
+// Seeks a materials based on theirs identifier.
+
+TerrainMaterial* CTerrain::LevelSearchMat(int id)
+{
+ int i;
+
+ for ( i=0 ; i<m_levelMatTotal ; i++ )
+ {
+ if ( id == m_levelMat[i].id )
+ {
+ return &m_levelMat[i];
+ }
+ }
+
+ return 0;
+}
+
+// Chooses texture to use for a given square.
+
+void CTerrain::LevelTextureName(int x, int y, char *name, Math::Point &uv)
+{
+ TerrainMaterial* tm;
+
+ x /= m_brick/m_subdivMapping;
+ y /= m_brick/m_subdivMapping;
+
+ tm = LevelSearchMat(m_levelDot[x+y*m_levelDotSize].id);
+ if ( tm == 0 )
+ {
+ strcpy(name, "xxx.tga");
+ uv.x = 0.0f;
+ uv.y = 0.0f;
+ }
+ else
+ {
+//? sprintf(name, "%s.tga", tm->texName);
+ strcpy(name, tm->texName);
+ uv.x = tm->u;
+ uv.y = tm->v;
+ }
+}
+
+// Returns the height of the terrain.
+
+float CTerrain::LevelRetHeight(int x, int y)
+{
+ int size;
+
+ size = (m_mosaic*m_brick+1);
+
+ if ( x < 0 ) x = 0;
+ if ( x >= size ) x = size-1;
+ if ( y < 0 ) y = 0;
+ if ( y >= size ) y = size-1;
+
+ return m_relief[x+y*size];
+}
+
+// Decide whether a point is using the materials.
+
+bool CTerrain::LevelGetDot(int x, int y, float min, float max, float slope)
+{
+ float hc, h[4];
+ int i;
+
+ hc = LevelRetHeight(x, y);
+ h[0] = LevelRetHeight(x+0, y+1);
+ h[1] = LevelRetHeight(x+1, y+0);
+ h[2] = LevelRetHeight(x+0, y-1);
+ h[3] = LevelRetHeight(x-1, y+0);
+
+ if ( hc < min ||
+ hc > max ) return false;
+
+ if ( slope == 0.0f )
+ {
+ return true;
+ }
+
+ if ( slope > 0.0f )
+ {
+ for ( i=0 ; i<4 ; i++ )
+ {
+ if ( fabs(hc-h[i]) >= slope )
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ if ( slope < 0.0f )
+ {
+ for ( i=0 ; i<4 ; i++ )
+ {
+ if ( fabs(hc-h[i]) < -slope )
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
+
+// Seeks if material exists.
+// Returns the index within m_levelMat or -1 if there is not.
+// m_levelMat[i].id gives the identifier.
+
+int CTerrain::LevelTestMat(char *mat)
+{
+ int i;
+
+ for ( i=0 ; i<m_levelMatTotal ; i++ )
+ {
+ if ( m_levelMat[i].mat[0] == mat[0] &&
+ m_levelMat[i].mat[1] == mat[1] &&
+ m_levelMat[i].mat[2] == mat[2] &&
+ m_levelMat[i].mat[3] == mat[3] ) return i;
+ }
+
+ return -1;
+}
+
+// Modifies the state of a point and its four neighbors, without testing if possible.
+
+void CTerrain::LevelSetDot(int x, int y, int id, char *mat)
+{
+ TerrainMaterial* tm;
+ int i, ii;
+
+ tm = LevelSearchMat(id);
+ if ( tm == 0 ) return;
+
+ if ( tm->mat[0] != mat[0] ||
+ tm->mat[1] != mat[1] ||
+ tm->mat[2] != mat[2] ||
+ tm->mat[3] != mat[3] ) // id incompatible with mat?
+ {
+ ii = LevelTestMat(mat);
+ if ( ii == -1 ) return;
+ id = m_levelMat[ii].id; // looking for a id compatible with mat
+ }
+
+ // Changes the point.
+ m_levelDot[x+y*m_levelDotSize].id = id;
+ m_levelDot[x+y*m_levelDotSize].mat[0] = mat[0];
+ m_levelDot[x+y*m_levelDotSize].mat[1] = mat[1];
+ m_levelDot[x+y*m_levelDotSize].mat[2] = mat[2];
+ m_levelDot[x+y*m_levelDotSize].mat[3] = mat[3];
+
+ // Changes the lower neighbor.
+ if ( (x+0) >= 0 && (x+0) < m_levelDotSize &&
+ (y-1) >= 0 && (y-1) < m_levelDotSize )
+ {
+ i = (x+0)+(y-1)*m_levelDotSize;
+ if ( m_levelDot[i].mat[0] != mat[2] )
+ {
+ m_levelDot[i].mat[0] = mat[2];
+ ii = LevelTestMat(m_levelDot[i].mat);
+ if ( ii != -1 )
+ {
+ m_levelDot[i].id = m_levelMat[ii].id;
+ }
+ }
+ }
+
+ // Modifies the left neighbor.
+ if ( (x-1) >= 0 && (x-1) < m_levelDotSize &&
+ (y+0) >= 0 && (y+0) < m_levelDotSize )
+ {
+ i = (x-1)+(y+0)*m_levelDotSize;
+ if ( m_levelDot[i].mat[1] != mat[3] )
+ {
+ m_levelDot[i].mat[1] = mat[3];
+ ii = LevelTestMat(m_levelDot[i].mat);
+ if ( ii != -1 )
+ {
+ m_levelDot[i].id = m_levelMat[ii].id;
+ }
+ }
+ }
+
+ // Changes the upper neighbor.
+ if ( (x+0) >= 0 && (x+0) < m_levelDotSize &&
+ (y+1) >= 0 && (y+1) < m_levelDotSize )
+ {
+ i = (x+0)+(y+1)*m_levelDotSize;
+ if ( m_levelDot[i].mat[2] != mat[0] )
+ {
+ m_levelDot[i].mat[2] = mat[0];
+ ii = LevelTestMat(m_levelDot[i].mat);
+ if ( ii != -1 )
+ {
+ m_levelDot[i].id = m_levelMat[ii].id;
+ }
+ }
+ }
+
+ // Changes the right neighbor.
+ if ( (x+1) >= 0 && (x+1) < m_levelDotSize &&
+ (y+0) >= 0 && (y+0) < m_levelDotSize )
+ {
+ i = (x+1)+(y+0)*m_levelDotSize;
+ if ( m_levelDot[i].mat[3] != mat[1] )
+ {
+ m_levelDot[i].mat[3] = mat[1];
+ ii = LevelTestMat(m_levelDot[i].mat);
+ if ( ii != -1 )
+ {
+ m_levelDot[i].id = m_levelMat[ii].id;
+ }
+ }
+ }
+}
+
+// Tests if a material can give a place, according to its four neighbors.
+// If yes, puts the point.
+
+bool CTerrain::LevelIfDot(int x, int y, int id, char *mat)
+{
+ char test[4];
+
+ // Compatible with lower neighbor?
+ if ( x+0 >= 0 && x+0 < m_levelDotSize &&
+ y-1 >= 0 && y-1 < m_levelDotSize )
+ {
+ test[0] = mat[2];
+ test[1] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[1];
+ test[2] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[2];
+ test[3] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[3];
+
+ if ( LevelTestMat(test) == -1 ) return false;
+ }
+
+ // Compatible with left neighbor?
+ if ( x-1 >= 0 && x-1 < m_levelDotSize &&
+ y+0 >= 0 && y+0 < m_levelDotSize )
+ {
+ test[0] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[0];
+ test[1] = mat[3];
+ test[2] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[2];
+ test[3] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[3];
+
+ if ( LevelTestMat(test) == -1 ) return false;
+ }
+
+ // Compatible with upper neighbor?
+ if ( x+0 >= 0 && x+0 < m_levelDotSize &&
+ y+1 >= 0 && y+1 < m_levelDotSize )
+ {
+ test[0] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[0];
+ test[1] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[1];
+ test[2] = mat[0];
+ test[3] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[3];
+
+ if ( LevelTestMat(test) == -1 ) return false;
+ }
+
+ // Compatible with right neighbor?
+ if ( x+1 >= 0 && x+1 < m_levelDotSize &&
+ y+0 >= 0 && y+0 < m_levelDotSize )
+ {
+ test[0] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[0];
+ test[1] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[1];
+ test[2] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[2];
+ test[3] = mat[1];
+
+ if ( LevelTestMat(test) == -1 ) return false;
+ }
+
+ LevelSetDot(x, y, id, mat); // puts the point
+ return true;
+}
+
+// Modifies the state of a point.
+
+bool CTerrain::LevelPutDot(int x, int y, int id)
+{
+ TerrainMaterial *tm;
+ char mat[4];
+ int up, right, down, left;
+
+ x /= m_brick/m_subdivMapping;
+ y /= m_brick/m_subdivMapping;
+
+ if ( x < 0 || x >= m_levelDotSize ||
+ y < 0 || y >= m_levelDotSize ) return false;
+
+ tm = LevelSearchMat(id);
+ if ( tm == 0 ) return false;
+
+ // Tries without changing neighbors.
+ if ( LevelIfDot(x, y, id, tm->mat) ) return true;
+
+ // Tries changing a single neighbor (4x).
+ for ( up=0 ; up<m_levelMatMax ; up++ )
+ {
+ mat[0] = up;
+ mat[1] = tm->mat[1];
+ mat[2] = tm->mat[2];
+ mat[3] = tm->mat[3];
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+
+ for ( right=0 ; right<m_levelMatMax ; right++ )
+ {
+ mat[0] = tm->mat[0];
+ mat[1] = right;
+ mat[2] = tm->mat[2];
+ mat[3] = tm->mat[3];
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+
+ for ( down=0 ; down<m_levelMatMax ; down++ )
+ {
+ mat[0] = tm->mat[0];
+ mat[1] = tm->mat[1];
+ mat[2] = down;
+ mat[3] = tm->mat[3];
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+
+ for ( left=0 ; left<m_levelMatMax ; left++ )
+ {
+ mat[0] = tm->mat[0];
+ mat[1] = tm->mat[1];
+ mat[2] = tm->mat[2];
+ mat[3] = left;
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+
+ // Tries changing two neighbors (6x).
+ for ( up=0 ; up<m_levelMatMax ; up++ )
+ {
+ for ( down=0 ; down<m_levelMatMax ; down++ )
+ {
+ mat[0] = up;
+ mat[1] = tm->mat[1];
+ mat[2] = down;
+ mat[3] = tm->mat[3];
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+ }
+
+ for ( right=0 ; right<m_levelMatMax ; right++ )
+ {
+ for ( left=0 ; left<m_levelMatMax ; left++ )
+ {
+ mat[0] = tm->mat[0];
+ mat[1] = right;
+ mat[2] = tm->mat[2];
+ mat[3] = left;
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+ }
+
+ for ( up=0 ; up<m_levelMatMax ; up++ )
+ {
+ for ( right=0 ; right<m_levelMatMax ; right++ )
+ {
+ mat[0] = up;
+ mat[1] = right;
+ mat[2] = tm->mat[2];
+ mat[3] = tm->mat[3];
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+ }
+
+ for ( right=0 ; right<m_levelMatMax ; right++ )
+ {
+ for ( down=0 ; down<m_levelMatMax ; down++ )
+ {
+ mat[0] = tm->mat[0];
+ mat[1] = right;
+ mat[2] = down;
+ mat[3] = tm->mat[3];
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+ }
+
+ for ( down=0 ; down<m_levelMatMax ; down++ )
+ {
+ for ( left=0 ; left<m_levelMatMax ; left++ )
+ {
+ mat[0] = tm->mat[0];
+ mat[1] = tm->mat[1];
+ mat[2] = down;
+ mat[3] = left;
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+ }
+
+ for ( up=0 ; up<m_levelMatMax ; up++ )
+ {
+ for ( left=0 ; left<m_levelMatMax ; left++ )
+ {
+ mat[0] = up;
+ mat[1] = tm->mat[1];
+ mat[2] = tm->mat[2];
+ mat[3] = left;
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+ }
+
+ // Tries changing all the neighbors.
+ for ( up=0 ; up<m_levelMatMax ; up++ )
+ {
+ for ( right=0 ; right<m_levelMatMax ; right++ )
+ {
+ for ( down=0 ; down<m_levelMatMax ; down++ )
+ {
+ for ( left=0 ; left<m_levelMatMax ; left++ )
+ {
+ mat[0] = up;
+ mat[1] = right;
+ mat[2] = down;
+ mat[3] = left;
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+ }
+ }
+ }
+
+ OutputDebugString("LevelPutDot error\n");
+ return false;
+}
+
+// Initializes all the ground with a material.
+
+bool CTerrain::LevelInit(int id)
+{
+ TerrainMaterial* tm;
+ int i, j;
+
+ tm = LevelSearchMat(id);
+ if ( tm == 0 ) return false;
+
+ for ( i=0 ; i<m_levelDotSize*m_levelDotSize ; i++ )
+ {
+ m_levelDot[i].id = id;
+
+ for ( j=0 ; j<4 ; j++ )
+ {
+ m_levelDot[i].mat[j] = tm->mat[j];
+ }
+ }
+
+ return true;
+}
+
+// Generates a level in the terrain.
+
+bool CTerrain::LevelGenerate(int *id, float min, float max,
+ float slope, float freq,
+ Math::Vector center, float radius)
+{
+ TerrainMaterial *tm;
+ Math::Vector pos;
+ int i, numID, x, y, xx, yy, group, rnd;
+ float dim;
+
+ static char random[100] =
+ {
+ 84,25,12, 6,34,52,85,38,97,16,
+ 21,31,65,19,62,40,72,22,48,61,
+ 56,47, 8,53,73,77, 4,91,26,88,
+ 76, 1,44,93,39,11,71,17,98,95,
+ 88,83,18,30, 3,57,28,49,74, 9,
+ 32,13,96,66,15,70,36,10,59,94,
+ 45,86, 2,29,63,42,51, 0,79,27,
+ 54, 7,20,69,89,23,64,43,81,92,
+ 90,33,46,14,67,35,50, 5,87,60,
+ 68,55,24,78,41,75,58,80,37,82,
+ };
+
+ i = 0;
+ while ( id[i] != 0 )
+ {
+ tm = LevelSearchMat(id[i++]);
+ if ( tm == 0 ) return false;
+ }
+ numID = i;
+
+ group = m_brick/m_subdivMapping;
+
+ if ( radius > 0.0f && radius < 5.0f ) // just a square?
+ {
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+
+ xx = (int)((center.x+dim)/m_size);
+ yy = (int)((center.z+dim)/m_size);
+
+ x = xx/group;
+ y = yy/group;
+
+ tm = LevelSearchMat(id[0]);
+ if ( tm != 0 )
+ {
+ LevelSetDot(x, y, id[0], tm->mat); // puts the point
+ }
+//? LevelPutDot(xx,yy, id[0]);
+ }
+ else
+ {
+ for ( y=0 ; y<m_levelDotSize ; y++ )
+ {
+ for ( x=0 ; x<m_levelDotSize ; x++ )
+ {
+ if ( radius != 0.0f )
+ {
+ pos.x = ((float)x-m_levelDotSize/2.0f)*group*m_size;
+ pos.z = ((float)y-m_levelDotSize/2.0f)*group*m_size;
+ if ( Math::DistanceProjected(pos, center) > radius ) continue;
+ }
+
+ if ( freq < 100.0f )
+ {
+ rnd = random[(x%10)+(y%10)*10];
+ if ( (float)rnd > freq ) continue;
+ }
+
+ xx = x*group + group/2;
+ yy = y*group + group/2;
+
+ if ( LevelGetDot(xx,yy, min, max, slope) )
+ {
+ rnd = random[(x%10)+(y%10)*10];
+ i = rnd%numID;
+ LevelPutDot(xx,yy, id[i]);
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+// Initializes an table with empty levels.
+
+void CTerrain::LevelOpenTable()
+{
+ int i, j;
+
+ if ( !m_bLevelText ) return;
+ if ( m_levelDot != 0 ) return; // already allocated
+
+ m_levelDotSize = (m_mosaic*m_brick)/(m_brick/m_subdivMapping)+1;
+ m_levelDot = (DotLevel*)malloc(m_levelDotSize*m_levelDotSize*sizeof(DotLevel));
+
+ for ( i=0 ; i<m_levelDotSize*m_levelDotSize ; i++ )
+ {
+ for ( j=0 ; j<4 ; j++ )
+ {
+ m_levelDot[i].mat[j] = 0;
+ }
+ }
+}
+
+// Closes the level table.
+
+void CTerrain::LevelCloseTable()
+{
+ free(m_levelDot);
+ m_levelDot = 0;
+}
+
+
+
+// Creates all objects in a mesh square ground.
+
+bool CTerrain::CreateSquare(bool bMultiRes, int x, int y)
+{
+ D3DMATERIAL7 mat;
+ float min, max;
+ int step, objRank;
+
+ ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
+ mat.diffuse.r = 1.0f;
+ mat.diffuse.g = 1.0f;
+ mat.diffuse.b = 1.0f;
+ mat.ambient.r = 0.0f;
+ mat.ambient.g = 0.0f;
+ mat.ambient.b = 0.0f;
+
+ objRank = m_engine->CreateObject();
+ m_engine->SetObjectType(objRank, TYPETERRAIN); // it is a terrain
+
+ m_objRank[x+y*m_mosaic] = objRank;
+
+ if ( bMultiRes )
+ {
+ min = 0.0f;
+ max = m_vision;
+ max *= m_engine->RetClippingDistance();
+ for ( step=0 ; step<m_depth ; step++ )
+ {
+ CreateMosaic(x, y, 1<<step, objRank, mat, min, max);
+ min = max;
+ max *= 2;
+ if ( step == m_depth-1 ) max = g_HUGE;
+ }
+ }
+ else
+ {
+ CreateMosaic(x, y, 1, objRank, mat, 0.0f, g_HUGE);
+ }
+
+ return true;
+}
+
+// Creates all objects of the terrain within the 3D engine.
+
+bool CTerrain::CreateObjects(bool bMultiRes)
+{
+ int x, y;
+
+ AdjustRelief();
+
+ for ( y=0 ; y<m_mosaic ; y++ )
+ {
+ for ( x=0 ; x<m_mosaic ; x++ )
+ {
+ CreateSquare(bMultiRes, x, y);
+ }
+ }
+
+ return true;
+}
+
+
+// Modifies the terrain's relief.
+// ATTENTION: ok only with m_depth = 2!
+
+bool CTerrain::Terraform(const Math::Vector &p1, const Math::Vector &p2, float height)
+{
+ POINT tp1, tp2, pp1, pp2;
+ float dim, avg;
+ int x, y, size, nb;
+
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+ tp1.x = (int)((p1.x+dim+m_size/2.0f)/m_size);
+ tp1.y = (int)((p1.z+dim+m_size/2.0f)/m_size);
+ tp2.x = (int)((p2.x+dim+m_size/2.0f)/m_size);
+ tp2.y = (int)((p2.z+dim+m_size/2.0f)/m_size);
+
+ if ( tp1.x > tp2.x )
+ {
+ x = tp1.x;
+ tp1.x = tp2.x;
+ tp2.x = x;
+ }
+
+ if ( tp1.y > tp2.y )
+ {
+ y = tp1.y;
+ tp1.y = tp2.y;
+ tp2.y = y;
+ }
+
+ size = (m_mosaic*m_brick)+1;
+
+ // Calculates the current average height.
+ avg = 0.0f;
+ nb = 0;
+ for ( y=tp1.y ; y<=tp2.y ; y++ )
+ {
+ for ( x=tp1.x ; x<=tp2.x ; x++ )
+ {
+ avg += m_relief[x+y*size];
+ nb ++;
+ }
+ }
+ avg /= (float)nb;
+
+ // Changes the description of the relief.
+ for ( y=tp1.y ; y<=tp2.y ; y++ )
+ {
+ for ( x=tp1.x ; x<=tp2.x ; x++ )
+ {
+ m_relief[x+y*size] = avg+height;
+
+ if ( x%m_brick == 0 && y%m_depth != 0 )
+ {
+ m_relief[(x+0)+(y-1)*size] = avg+height;
+ m_relief[(x+0)+(y+1)*size] = avg+height;
+ }
+
+ if ( y%m_brick == 0 && x%m_depth != 0 )
+ {
+ m_relief[(x-1)+(y+0)*size] = avg+height;
+ m_relief[(x+1)+(y+0)*size] = avg+height;
+ }
+ }
+ }
+ AdjustRelief();
+
+ pp1.x = (tp1.x-2)/m_brick;
+ pp1.y = (tp1.y-2)/m_brick;
+ pp2.x = (tp2.x+1)/m_brick;
+ pp2.y = (tp2.y+1)/m_brick;
+
+ if ( pp1.x < 0 ) pp1.x = 0;
+ if ( pp1.x >= m_mosaic ) pp1.x = m_mosaic-1;
+ if ( pp1.y < 0 ) pp1.y = 0;
+ if ( pp1.y >= m_mosaic ) pp1.y = m_mosaic-1;
+
+ for ( y=pp1.y ; y<=pp2.y ; y++ )
+ {
+ for ( x=pp1.x ; x<=pp2.x ; x++ )
+ {
+ m_engine->DeleteObject(m_objRank[x+y*m_mosaic]);
+ CreateSquare(m_bMultiText, x, y); // recreates the square
+ }
+ }
+ m_engine->Update();
+
+ return true;
+}
+
+
+// Management of the wind.
+
+void CTerrain::SetWind(Math::Vector speed)
+{
+ m_wind = speed;
+}
+
+Math::Vector CTerrain::RetWind()
+{
+ return m_wind;
+}
+
+
+// Gives the exact slope of the terrain of a place given.
+
+float CTerrain::RetFineSlope(const Math::Vector &pos)
+{
+ Math::Vector n;
+
+ if ( !GetNormal(n, pos) ) return 0.0f;
+ return fabs(Math::RotateAngle(Math::Point(n.x, n.z).Length(), n.y)-Math::PI/2.0f);
+}
+
+// Gives the approximate slope of the terrain of a specific location.
+
+float CTerrain::RetCoarseSlope(const Math::Vector &pos)
+{
+ float dim, level[4], min, max;
+ int x, y;
+
+ if ( m_relief == 0 ) return 0.0f;
+
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+
+ x = (int)((pos.x+dim)/m_size);
+ y = (int)((pos.z+dim)/m_size);
+
+ if ( x < 0 || x >= m_mosaic*m_brick ||
+ y < 0 || y >= m_mosaic*m_brick ) return 0.0f;
+
+ level[0] = m_relief[(x+0)+(y+0)*(m_mosaic*m_brick+1)];
+ level[1] = m_relief[(x+1)+(y+0)*(m_mosaic*m_brick+1)];
+ level[2] = m_relief[(x+0)+(y+1)*(m_mosaic*m_brick+1)];
+ level[3] = m_relief[(x+1)+(y+1)*(m_mosaic*m_brick+1)];
+
+ min = Math::Min(level[0], level[1], level[2], level[3]);
+ max = Math::Max(level[0], level[1], level[2], level[3]);
+
+ return atanf((max-min)/m_size);
+}
+
+// Gives the normal vector at the position p (x,-,z) of the ground.
+
+bool CTerrain::GetNormal(Math::Vector &n, const Math::Vector &p)
+{
+ Math::Vector p1, p2, p3, p4;
+ float dim;
+ int x, y;
+
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+
+ x = (int)((p.x+dim)/m_size);
+ y = (int)((p.z+dim)/m_size);
+
+ if ( x < 0 || x > m_mosaic*m_brick ||
+ y < 0 || y > m_mosaic*m_brick ) return false;
+
+ p1 = RetVector(x+0, y+0);
+ p2 = RetVector(x+1, y+0);
+ p3 = RetVector(x+0, y+1);
+ p4 = RetVector(x+1, y+1);
+
+ if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) )
+ {
+ n = Math::NormalToPlane(p1,p2,p3);
+ }
+ else
+ {
+ n = Math::NormalToPlane(p2,p4,p3);
+ }
+ return true;
+}
+
+// Returns the height of the ground.
+
+float CTerrain::RetFloorLevel(const Math::Vector &p, bool bBrut, bool bWater)
+{
+ Math::Vector p1, p2, p3, p4, ps;
+ float dim, level;
+ int x, y;
+
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+
+ x = (int)((p.x+dim)/m_size);
+ y = (int)((p.z+dim)/m_size);
+
+ if ( x < 0 || x > m_mosaic*m_brick ||
+ y < 0 || y > m_mosaic*m_brick ) return false;
+
+ p1 = RetVector(x+0, y+0);
+ p2 = RetVector(x+1, y+0);
+ p3 = RetVector(x+0, y+1);
+ p4 = RetVector(x+1, y+1);
+
+ ps = p;
+ if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) )
+ {
+ if ( !IntersectY(p1, p2, p3, ps) ) return 0.0f;
+ }
+ else
+ {
+ if ( !IntersectY(p2, p4, p3, ps) ) return 0.0f;
+ }
+
+ if ( !bBrut ) AdjustBuildingLevel(ps);
+
+ if ( bWater ) // not going underwater?
+ {
+ level = m_water->RetLevel();
+ if ( ps.y < level ) ps.y = level; // not under water
+ }
+
+ return ps.y;
+}
+
+// Returns the height to the ground.
+// This height is positive when you are above the ground.
+
+float CTerrain::RetFloorHeight(const Math::Vector &p, bool bBrut, bool bWater)
+{
+ Math::Vector p1, p2, p3, p4, ps;
+ float dim, level;
+ int x, y;
+
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+
+ x = (int)((p.x+dim)/m_size);
+ y = (int)((p.z+dim)/m_size);
+
+ if ( x < 0 || x > m_mosaic*m_brick ||
+ y < 0 || y > m_mosaic*m_brick ) return false;
+
+ p1 = RetVector(x+0, y+0);
+ p2 = RetVector(x+1, y+0);
+ p3 = RetVector(x+0, y+1);
+ p4 = RetVector(x+1, y+1);
+
+ ps = p;
+ if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) )
+ {
+ if ( !IntersectY(p1, p2, p3, ps) ) return 0.0f;
+ }
+ else
+ {
+ if ( !IntersectY(p2, p4, p3, ps) ) return 0.0f;
+ }
+
+ if ( !bBrut ) AdjustBuildingLevel(ps);
+
+ if ( bWater ) // not going underwater?
+ {
+ level = m_water->RetLevel();
+ if ( ps.y < level ) ps.y = level; // not under water
+ }
+
+ return p.y-ps.y;
+}
+
+// Modifies the coordinate "y" of point "p" to rest on the ground floor.
+
+bool CTerrain::MoveOnFloor(Math::Vector &p, bool bBrut, bool bWater)
+{
+ Math::Vector p1, p2, p3, p4;
+ float dim, level;
+ int x, y;
+
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+
+ x = (int)((p.x+dim)/m_size);
+ y = (int)((p.z+dim)/m_size);
+
+ if ( x < 0 || x > m_mosaic*m_brick ||
+ y < 0 || y > m_mosaic*m_brick ) return false;
+
+ p1 = RetVector(x+0, y+0);
+ p2 = RetVector(x+1, y+0);
+ p3 = RetVector(x+0, y+1);
+ p4 = RetVector(x+1, y+1);
+
+ if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) )
+ {
+ if ( !IntersectY(p1, p2, p3, p) ) return false;
+ }
+ else
+ {
+ if ( !IntersectY(p2, p4, p3, p) ) return false;
+ }
+
+ if ( !bBrut ) AdjustBuildingLevel(p);
+
+ if ( bWater ) // not going underwater?
+ {
+ level = m_water->RetLevel();
+ if ( p.y < level ) p.y = level; // not under water
+ }
+
+ return true;
+}
+
+// Modifies a coordinate so that it is on the ground.
+// Returns false if the initial coordinate was too far.
+
+bool CTerrain::ValidPosition(Math::Vector &p, float marging)
+{
+ bool bOK = true;
+ float limit;
+
+ limit = m_mosaic*m_brick*m_size/2.0f - marging;
+
+ if ( p.x < -limit )
+ {
+ p.x = -limit;
+ bOK = false;
+ }
+
+ if ( p.z < -limit )
+ {
+ p.z = -limit;
+ bOK = false;
+ }
+
+ if ( p.x > limit )
+ {
+ p.x = limit;
+ bOK = false;
+ }
+
+ if ( p.z > limit )
+ {
+ p.z = limit;
+ bOK = false;
+ }
+
+ return bOK;
+}
+
+
+
+// Empty the table of elevations.
+
+void CTerrain::FlushBuildingLevel()
+{
+ m_buildingUsed = 0;
+}
+
+// Adds a new elevation for a building.
+
+bool CTerrain::AddBuildingLevel(Math::Vector center, float min, float max,
+ float height, float factor)
+{
+ int i;
+
+ for ( i=0 ; i<m_buildingUsed ; i++ )
+ {
+ if ( center.x == m_buildingTable[i].center.x &&
+ center.z == m_buildingTable[i].center.z )
+ {
+ goto update;
+ }
+ }
+
+ if ( m_buildingUsed >= MAXBUILDINGLEVEL ) return false;
+ i = m_buildingUsed++;
+
+ update:
+ m_buildingTable[i].center = center;
+ m_buildingTable[i].min = min;
+ m_buildingTable[i].max = max;
+ m_buildingTable[i].level = RetFloorLevel(center, true);
+ m_buildingTable[i].height = height;
+ m_buildingTable[i].factor = factor;
+ m_buildingTable[i].bboxMinX = center.x-max;
+ m_buildingTable[i].bboxMaxX = center.x+max;
+ m_buildingTable[i].bboxMinZ = center.z-max;
+ m_buildingTable[i].bboxMaxZ = center.z+max;
+
+ return true;
+}
+
+// Updates the elevation for a building when it was moved up (after a terraforming).
+
+bool CTerrain::UpdateBuildingLevel(Math::Vector center)
+{
+ int i;
+
+ for ( i=0 ; i<m_buildingUsed ; i++ )
+ {
+ if ( center.x == m_buildingTable[i].center.x &&
+ center.z == m_buildingTable[i].center.z )
+ {
+ m_buildingTable[i].center = center;
+ m_buildingTable[i].level = RetFloorLevel(center, true);
+ return true;
+ }
+ }
+ return false;
+}
+
+// Removes the elevation for a building when it was destroyed.
+
+bool CTerrain::DeleteBuildingLevel(Math::Vector center)
+{
+ int i, j;
+
+ for ( i=0 ; i<m_buildingUsed ; i++ )
+ {
+ if ( center.x == m_buildingTable[i].center.x &&
+ center.z == m_buildingTable[i].center.z )
+ {
+ for ( j=i+1 ; j<m_buildingUsed ; j++ )
+ {
+ m_buildingTable[j-1] = m_buildingTable[j];
+ }
+ m_buildingUsed --;
+ return true;
+ }
+ }
+ return false;
+}
+
+// Returns the influence factor whether a position is on a possible rise.
+
+float CTerrain::RetBuildingFactor(const Math::Vector &p)
+{
+ float dist;
+ int i;
+
+ for ( i=0 ; i<m_buildingUsed ; i++ )
+ {
+ if ( p.x < m_buildingTable[i].bboxMinX ||
+ p.x > m_buildingTable[i].bboxMaxX ||
+ p.z < m_buildingTable[i].bboxMinZ ||
+ p.z > m_buildingTable[i].bboxMaxZ ) continue;
+
+ dist = Math::DistanceProjected(p, m_buildingTable[i].center);
+
+ if ( dist <= m_buildingTable[i].max )
+ {
+ return m_buildingTable[i].factor;
+ }
+ }
+ return 1.0f; // it is normal on the ground
+}
+
+// Adjusts a position according to a possible rise.
+
+void CTerrain::AdjustBuildingLevel(Math::Vector &p)
+{
+ Math::Vector border;
+ float dist, base;
+ int i;
+
+ for ( i=0 ; i<m_buildingUsed ; i++ )
+ {
+ if ( p.x < m_buildingTable[i].bboxMinX ||
+ p.x > m_buildingTable[i].bboxMaxX ||
+ p.z < m_buildingTable[i].bboxMinZ ||
+ p.z > m_buildingTable[i].bboxMaxZ ) continue;
+
+ dist = Math::DistanceProjected(p, m_buildingTable[i].center);
+
+ if ( dist > m_buildingTable[i].max ) continue;
+
+ if ( dist < m_buildingTable[i].min )
+ {
+ p.y = m_buildingTable[i].level+m_buildingTable[i].height;
+ return;
+ }
+
+#if 0
+ p.y = m_buildingTable[i].level;
+ p.y += (m_buildingTable[i].max-dist)/
+ (m_buildingTable[i].max-m_buildingTable[i].min)*
+ m_buildingTable[i].height;
+
+ base = RetFloorLevel(p, true);
+ if ( p.y < base ) p.y = base;
+#else
+ border.x = ((p.x-m_buildingTable[i].center.x)*m_buildingTable[i].max)/
+ dist+m_buildingTable[i].center.x;
+ border.z = ((p.z-m_buildingTable[i].center.z)*m_buildingTable[i].max)/
+ dist+m_buildingTable[i].center.z;
+
+ base = RetFloorLevel(border, true);
+
+ p.y = (m_buildingTable[i].max-dist)/
+ (m_buildingTable[i].max-m_buildingTable[i].min)*
+ (m_buildingTable[i].level+m_buildingTable[i].height-base)+
+ base;
+#endif
+ return;
+ }
+}
+
+
+// Returns the hardness of the ground in a given place.
+// The hardness determines the noise (SOUND_STEP and SOUND_BOUM).
+
+float CTerrain::RetHardness(const Math::Vector &p)
+{
+ TerrainMaterial* tm;
+ float factor, dim;
+ int x, y, id;
+
+ factor = RetBuildingFactor(p);
+ if ( factor != 1.0f ) return 1.0f; // on building
+
+ if ( m_levelDot == 0 ) return m_defHardness;
+
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+
+ x = (int)((p.x+dim)/m_size);
+ y = (int)((p.z+dim)/m_size);
+
+ if ( x < 0 || x > m_mosaic*m_brick ||
+ y < 0 || y > m_mosaic*m_brick ) return m_defHardness;
+
+ x /= m_brick/m_subdivMapping;
+ y /= m_brick/m_subdivMapping;
+
+ if ( x < 0 || x >= m_levelDotSize ||
+ y < 0 || y >= m_levelDotSize ) return m_defHardness;
+
+ id = m_levelDot[x+y*m_levelDotSize].id;
+ tm = LevelSearchMat(id);
+ if ( tm == 0 ) return m_defHardness;
+
+ return tm->hardness;
+}
+
+
+// Shows the flat areas on the ground.
+
+void CTerrain::GroundFlat(Math::Vector pos)
+{
+ Math::Vector p;
+ float rapport, angle;
+ int x, y, i;
+ static char table[41*41];
+
+
+ rapport = 3200.0f/1024.0f;
+
+ for ( y=0 ; y<=40 ; y++ )
+ {
+ for ( x=0 ; x<=40 ; x++ )
+ {
+ i = x + y*41;
+ table[i] = 0;
+
+ p.x = (x-20)*rapport;
+ p.z = (y-20)*rapport;
+ p.y = 0.0f;
+ if ( Math::Point(p.x, p.y).Length() > 20.0f*rapport ) continue;
+
+ angle = RetFineSlope(pos+p);
+
+ if ( angle < FLATLIMIT )
+ {
+ table[i] = 1;
+ }
+ else
+ {
+ table[i] = 2;
+ }
+ }
+ }
+
+ m_engine->GroundMarkCreate(pos, 40.0f, 0.001f, 15.0f, 0.001f, 41, 41, table);
+}
+
+
+// Calculates the radius of the largest flat area available.
+// This calculation is not optimized!
+
+float CTerrain::RetFlatZoneRadius(Math::Vector center, float max)
+{
+ Math::Vector pos;
+ Math::Point c, p;
+ float ref, radius, angle, h;
+ int i, nb;
+
+ angle = RetFineSlope(center);
+ if ( angle >= FLATLIMIT ) return 0.0f;
+
+ ref = RetFloorLevel(center, true);
+
+ radius = 1.0f;
+ while ( radius <= max )
+ {
+ angle = 0.0f;
+ nb = (int)(2.0f*Math::PI*radius);
+ if ( nb < 8 ) nb = 8;
+ for ( i=0 ; i<nb ; i++ )
+ {
+ c.x = center.x;
+ c.y = center.z;
+ p.x = center.x+radius;
+ p.y = center.z;
+ p = Math::RotatePoint(c, angle, p);
+ pos.x = p.x;
+ pos.z = p.y;
+ h = RetFloorLevel(pos, true);
+ if ( fabs(h-ref) > 1.0f ) return radius;
+
+ angle += Math::PI*2.0f/8.0f;
+ }
+ radius += 1.0f;
+ }
+ return max;
+}
+
+
+
+// Specifies the maximum height of flight.
+
+void CTerrain::SetFlyingMaxHeight(float height)
+{
+ m_flyingMaxHeight = height;
+}
+
+// Returns the maximum height of flight.
+
+float CTerrain::RetFlyingMaxHeight()
+{
+ return m_flyingMaxHeight;
+}
+
+
+// Empty the limits table of flight.
+
+void CTerrain::FlushFlyingLimit()
+{
+ m_flyingMaxHeight = 280.0f;
+ m_flyingLimitTotal = 0;
+}
+
+// Empty the limits table of flight.
+
+bool CTerrain::AddFlyingLimit(Math::Vector center,
+ float extRadius, float intRadius,
+ float maxHeight)
+{
+ int i;
+
+ if ( m_flyingLimitTotal >= MAXFLYINGLIMIT ) return false;
+
+ i = m_flyingLimitTotal;
+ m_flyingLimit[i].center = center;
+ m_flyingLimit[i].extRadius = extRadius;
+ m_flyingLimit[i].intRadius = intRadius;
+ m_flyingLimit[i].maxHeight = maxHeight;
+ m_flyingLimitTotal = i+1;
+
+ return true;
+}
+
+// Returns the maximum height of flight.
+
+float CTerrain::RetFlyingLimit(Math::Vector pos, bool bNoLimit)
+{
+ float dist, h;
+ int i;
+
+ if ( bNoLimit ) return 280.0f;
+ if ( m_flyingLimitTotal == 0 ) return m_flyingMaxHeight;
+
+ for ( i=0 ; i<m_flyingLimitTotal ; i++ )
+ {
+ dist = Math::DistanceProjected(pos, m_flyingLimit[i].center);
+
+ if ( dist >= m_flyingLimit[i].extRadius ) continue;
+
+ if ( dist <= m_flyingLimit[i].intRadius )
+ {
+ return m_flyingLimit[i].maxHeight;
+ }
+
+ dist -= m_flyingLimit[i].intRadius;
+
+ h = dist*(m_flyingMaxHeight-m_flyingLimit[i].maxHeight)/
+ (m_flyingLimit[i].extRadius-m_flyingLimit[i].intRadius);
+
+ return h + m_flyingLimit[i].maxHeight;
+ }
+
+ return m_flyingMaxHeight;
+}
+
diff --git a/src/old/terrain.h b/src/old/terrain.h
index e2ca566..38e7287 100644
--- a/src/old/terrain.h
+++ b/src/old/terrain.h
@@ -1,209 +1,209 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// terrain.h
-
-#pragma once
-
-
-#include "common/struct.h"
-#include "math/point.h"
-#include "old/d3dengine.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CWater;
-
-
-
-const float FLATLIMIT = (5.0f*Math::PI/180.0f);
-
-
-enum TerrainRes
-{
- TR_NULL = 0,
- TR_STONE = 1,
- TR_URANIUM = 2,
- TR_POWER = 3,
- TR_KEYa = 4,
- TR_KEYb = 5,
- TR_KEYc = 6,
- TR_KEYd = 7,
-};
-
-
-const int MAXBUILDINGLEVEL = 100;
-
-struct BuildingLevel
-{
- Math::Vector center;
- float factor;
- float min;
- float max;
- float level;
- float height;
- float bboxMinX;
- float bboxMaxX;
- float bboxMinZ;
- float bboxMaxZ;
-};
-
-
-const int MAXMATTERRAIN = 100;
-
-struct TerrainMaterial
-{
- short id;
- char texName[20];
- float u,v;
- float hardness;
- char mat[4]; // up, right, down, left
-};
-
-struct DotLevel
-{
- short id;
- char mat[4]; // up, right, down, left
-};
-
-
-const int MAXFLYINGLIMIT = 10;
-
-struct FlyingLimit
-{
- Math::Vector center;
- float extRadius;
- float intRadius;
- float maxHeight;
-};
-
-
-
-class CTerrain
-{
-public:
- CTerrain(CInstanceManager* iMan);
- ~CTerrain();
-
- bool Generate(int mosaic, int brickP2, float size, float vision, int depth, float hardness);
- bool InitTextures(char* baseName, int* table, int dx, int dy);
- void LevelFlush();
- bool LevelMaterial(int id, char* baseName, float u, float v, int up, int right, int down, int left, float hardness);
- bool LevelInit(int id);
- bool LevelGenerate(int *id, float min, float max, float slope, float freq, Math::Vector center, float radius);
- void FlushRelief();
- bool ReliefFromBMP(const char* filename, float scaleRelief, bool adjustBorder);
- bool ReliefFromDXF(const char* filename, float scaleRelief);
- bool ResFromBMP(const char* filename);
- bool CreateObjects(bool bMultiRes);
- bool Terraform(const Math::Vector &p1, const Math::Vector &p2, float height);
-
- void SetWind(Math::Vector speed);
- Math::Vector RetWind();
-
- float RetFineSlope(const Math::Vector &pos);
- float RetCoarseSlope(const Math::Vector &pos);
- bool GetNormal(Math::Vector &n, const Math::Vector &p);
- float RetFloorLevel(const Math::Vector &p, bool bBrut=false, bool bWater=false);
- float RetFloorHeight(const Math::Vector &p, bool bBrut=false, bool bWater=false);
- bool MoveOnFloor(Math::Vector &p, bool bBrut=false, bool bWater=false);
- bool ValidPosition(Math::Vector &p, float marging);
- TerrainRes RetResource(const Math::Vector &p);
- void LimitPos(Math::Vector &pos);
-
- void FlushBuildingLevel();
- bool AddBuildingLevel(Math::Vector center, float min, float max, float height, float factor);
- bool UpdateBuildingLevel(Math::Vector center);
- bool DeleteBuildingLevel(Math::Vector center);
- float RetBuildingFactor(const Math::Vector &p);
- float RetHardness(const Math::Vector &p);
-
- int RetMosaic();
- int RetBrick();
- float RetSize();
- float RetScaleRelief();
-
- void GroundFlat(Math::Vector pos);
- float RetFlatZoneRadius(Math::Vector center, float max);
-
- void SetFlyingMaxHeight(float height);
- float RetFlyingMaxHeight();
- void FlushFlyingLimit();
- bool AddFlyingLimit(Math::Vector center, float extRadius, float intRadius, float maxHeight);
- float RetFlyingLimit(Math::Vector pos, bool bNoLimit);
-
-protected:
- bool ReliefAddDot(Math::Vector pos, float scaleRelief);
- void AdjustRelief();
- Math::Vector RetVector(int x, int y);
- D3DVERTEX2 RetVertex(int x, int y, int step);
- bool CreateMosaic(int ox, int oy, int step, int objRank, const D3DMATERIAL7 &mat, float min, float max);
- bool CreateSquare(bool bMultiRes, int x, int y);
-
- TerrainMaterial* LevelSearchMat(int id);
- void LevelTextureName(int x, int y, char *name, Math::Point &uv);
- float LevelRetHeight(int x, int y);
- bool LevelGetDot(int x, int y, float min, float max, float slope);
- int LevelTestMat(char *mat);
- void LevelSetDot(int x, int y, int id, char *mat);
- bool LevelIfDot(int x, int y, int id, char *mat);
- bool LevelPutDot(int x, int y, int id);
- void LevelOpenTable();
- void LevelCloseTable();
-
- void AdjustBuildingLevel(Math::Vector &p);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CWater* m_water;
-
- int m_mosaic; // number of mosaics
- int m_brick; // number of bricks per mosaics
- float m_size; // size of an item in an brick
- float m_vision; // vision before a change of resolution
- float* m_relief; // table of the relief
- int* m_texture; // table of textures
- int* m_objRank; // table of rows of objects
- bool m_bMultiText;
- bool m_bLevelText;
- float m_scaleMapping; // scale of the mapping
- float m_scaleRelief;
- int m_subdivMapping;
- int m_depth; // number of different resolutions (1,2,3,4)
- char m_texBaseName[20];
- char m_texBaseExt[10];
- float m_defHardness;
-
- TerrainMaterial m_levelMat[MAXMATTERRAIN+1];
- int m_levelMatTotal;
- int m_levelMatMax;
- int m_levelDotSize;
- DotLevel* m_levelDot;
- int m_levelID;
-
- int m_buildingUsed;
- BuildingLevel m_buildingTable[MAXBUILDINGLEVEL];
-
- unsigned char* m_resources;
- Math::Vector m_wind; // wind speed
-
- float m_flyingMaxHeight;
- int m_flyingLimitTotal;
- FlyingLimit m_flyingLimit[MAXFLYINGLIMIT];
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// terrain.h
+
+#pragma once
+
+
+#include "common/struct.h"
+#include "math/point.h"
+#include "old/d3dengine.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CWater;
+
+
+
+const float FLATLIMIT = (5.0f*Math::PI/180.0f);
+
+
+enum TerrainRes
+{
+ TR_NULL = 0,
+ TR_STONE = 1,
+ TR_URANIUM = 2,
+ TR_POWER = 3,
+ TR_KEYa = 4,
+ TR_KEYb = 5,
+ TR_KEYc = 6,
+ TR_KEYd = 7,
+};
+
+
+const int MAXBUILDINGLEVEL = 100;
+
+struct BuildingLevel
+{
+ Math::Vector center;
+ float factor;
+ float min;
+ float max;
+ float level;
+ float height;
+ float bboxMinX;
+ float bboxMaxX;
+ float bboxMinZ;
+ float bboxMaxZ;
+};
+
+
+const int MAXMATTERRAIN = 100;
+
+struct TerrainMaterial
+{
+ short id;
+ char texName[20];
+ float u,v;
+ float hardness;
+ char mat[4]; // up, right, down, left
+};
+
+struct DotLevel
+{
+ short id;
+ char mat[4]; // up, right, down, left
+};
+
+
+const int MAXFLYINGLIMIT = 10;
+
+struct FlyingLimit
+{
+ Math::Vector center;
+ float extRadius;
+ float intRadius;
+ float maxHeight;
+};
+
+
+
+class CTerrain
+{
+public:
+ CTerrain(CInstanceManager* iMan);
+ ~CTerrain();
+
+ bool Generate(int mosaic, int brickP2, float size, float vision, int depth, float hardness);
+ bool InitTextures(char* baseName, int* table, int dx, int dy);
+ void LevelFlush();
+ bool LevelMaterial(int id, char* baseName, float u, float v, int up, int right, int down, int left, float hardness);
+ bool LevelInit(int id);
+ bool LevelGenerate(int *id, float min, float max, float slope, float freq, Math::Vector center, float radius);
+ void FlushRelief();
+ bool ReliefFromBMP(const char* filename, float scaleRelief, bool adjustBorder);
+ bool ReliefFromDXF(const char* filename, float scaleRelief);
+ bool ResFromBMP(const char* filename);
+ bool CreateObjects(bool bMultiRes);
+ bool Terraform(const Math::Vector &p1, const Math::Vector &p2, float height);
+
+ void SetWind(Math::Vector speed);
+ Math::Vector RetWind();
+
+ float RetFineSlope(const Math::Vector &pos);
+ float RetCoarseSlope(const Math::Vector &pos);
+ bool GetNormal(Math::Vector &n, const Math::Vector &p);
+ float RetFloorLevel(const Math::Vector &p, bool bBrut=false, bool bWater=false);
+ float RetFloorHeight(const Math::Vector &p, bool bBrut=false, bool bWater=false);
+ bool MoveOnFloor(Math::Vector &p, bool bBrut=false, bool bWater=false);
+ bool ValidPosition(Math::Vector &p, float marging);
+ TerrainRes RetResource(const Math::Vector &p);
+ void LimitPos(Math::Vector &pos);
+
+ void FlushBuildingLevel();
+ bool AddBuildingLevel(Math::Vector center, float min, float max, float height, float factor);
+ bool UpdateBuildingLevel(Math::Vector center);
+ bool DeleteBuildingLevel(Math::Vector center);
+ float RetBuildingFactor(const Math::Vector &p);
+ float RetHardness(const Math::Vector &p);
+
+ int RetMosaic();
+ int RetBrick();
+ float RetSize();
+ float RetScaleRelief();
+
+ void GroundFlat(Math::Vector pos);
+ float RetFlatZoneRadius(Math::Vector center, float max);
+
+ void SetFlyingMaxHeight(float height);
+ float RetFlyingMaxHeight();
+ void FlushFlyingLimit();
+ bool AddFlyingLimit(Math::Vector center, float extRadius, float intRadius, float maxHeight);
+ float RetFlyingLimit(Math::Vector pos, bool bNoLimit);
+
+protected:
+ bool ReliefAddDot(Math::Vector pos, float scaleRelief);
+ void AdjustRelief();
+ Math::Vector RetVector(int x, int y);
+ D3DVERTEX2 RetVertex(int x, int y, int step);
+ bool CreateMosaic(int ox, int oy, int step, int objRank, const D3DMATERIAL7 &mat, float min, float max);
+ bool CreateSquare(bool bMultiRes, int x, int y);
+
+ TerrainMaterial* LevelSearchMat(int id);
+ void LevelTextureName(int x, int y, char *name, Math::Point &uv);
+ float LevelRetHeight(int x, int y);
+ bool LevelGetDot(int x, int y, float min, float max, float slope);
+ int LevelTestMat(char *mat);
+ void LevelSetDot(int x, int y, int id, char *mat);
+ bool LevelIfDot(int x, int y, int id, char *mat);
+ bool LevelPutDot(int x, int y, int id);
+ void LevelOpenTable();
+ void LevelCloseTable();
+
+ void AdjustBuildingLevel(Math::Vector &p);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CWater* m_water;
+
+ int m_mosaic; // number of mosaics
+ int m_brick; // number of bricks per mosaics
+ float m_size; // size of an item in an brick
+ float m_vision; // vision before a change of resolution
+ float* m_relief; // table of the relief
+ int* m_texture; // table of textures
+ int* m_objRank; // table of rows of objects
+ bool m_bMultiText;
+ bool m_bLevelText;
+ float m_scaleMapping; // scale of the mapping
+ float m_scaleRelief;
+ int m_subdivMapping;
+ int m_depth; // number of different resolutions (1,2,3,4)
+ char m_texBaseName[20];
+ char m_texBaseExt[10];
+ float m_defHardness;
+
+ TerrainMaterial m_levelMat[MAXMATTERRAIN+1];
+ int m_levelMatTotal;
+ int m_levelMatMax;
+ int m_levelDotSize;
+ DotLevel* m_levelDot;
+ int m_levelID;
+
+ int m_buildingUsed;
+ BuildingLevel m_buildingTable[MAXBUILDINGLEVEL];
+
+ unsigned char* m_resources;
+ Math::Vector m_wind; // wind speed
+
+ float m_flyingMaxHeight;
+ int m_flyingLimitTotal;
+ FlyingLimit m_flyingLimit[MAXFLYINGLIMIT];
+};
+
diff --git a/src/old/text.cpp b/src/old/text.cpp
index a7faa95..d174358 100644
--- a/src/old/text.cpp
+++ b/src/old/text.cpp
@@ -1,1879 +1,1879 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// text.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "common/language.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "old/text.h"
-
-
-
-static short table_text_colobot[] =
-{
-// x1, y1, x2, y2
- 219,34, 225,50, // 0
- 1,188, 9,203, // .
- 51,188,59,203, // square
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 11,188,19,203, // \t
- 21,188,29,203, // \n
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50, // \r
- 219,34, 225,50,
- 219,34, 225,50,
- 41,188,49,203, // >
- 31,188,39,203, // <
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
-#if _NEWLOOK
- 0, 0, 4, 16, // 32
- 7, 0, 9, 16, // !
- 9, 0, 13, 16, // "
- 13, 0, 24, 16, // #
- 24, 0, 31, 16, // $
- 31, 0, 43, 16, // %
- 43, 0, 54, 16, // &
- 54, 0, 56, 16, // '
- 56, 0, 61, 16, // (
- 61, 0, 67, 16, // )
- 67, 0, 73, 16, // *
- 73, 0, 83, 16, // +
- 83, 0, 87, 16, // ,
- 87, 0, 92, 16, // -
- 92, 0, 94, 16, // .
- 94, 0, 101,16, // /
- 101,0, 109,16, // 0
- 109,0, 114,16, // 1
- 114,0, 122,16, // 2
- 122,0, 129,16, // 3
- 129,0, 138,16, // 4
- 138,0, 146,16, // 5
- 146,0, 154,16, // 6
- 154,0, 161,16, // 7
- 161,0, 169,16, // 8
- 169,0, 177,16, // 9
- 177,0, 179,16, // :
- 179,0, 183,16, // ;
- 183,0, 193,16, // <
- 193,0, 203,16, // =
- 203,0, 213,16, // >
- 213,0, 219,16, // ?
-
- 0, 17, 14, 33, // @ 64
- 14, 17, 26, 33, // A
- 26, 17, 33, 33, // B
- 33, 17, 42, 33, // C
- 42, 17, 51, 33, // D
- 51, 17, 58, 33, // E
- 58, 17, 63, 33, // F
- 63, 17, 73, 33, // G
- 73, 17, 82, 33, // H
- 82, 17, 84, 33, // I
- 84, 17, 90, 33, // J
- 90, 17, 98, 33, // K
- 98, 17, 103,33, // L
- 103,17, 115,33, // M
- 115,17, 124,33, // N
- 124,17, 136,33, // O
- 136,17, 142,33, // P
- 142,17, 154,33, // Q
- 154,17, 160,33, // R
- 160,17, 167,33, // S
- 167,17, 175,33, // T
- 175,17, 183,33, // U
- 183,17, 194,33, // V
- 194,17, 208,33, // W
- 208,17, 218,33, // X
- 218,17, 227,33, // Y
- 227,17, 236,33, // Z
- 236,17, 241,33, // [
- 241,17, 248,33, // \
- 248,17, 252,33, // ]
- 219,0, 229,16, // ^
- 0, 34, 9, 50, // _
-
- 54, 0, 56, 16, // ` 96
- 9, 34, 16, 50, // a
- 16, 34, 25, 50, // b
- 25, 34, 33, 50, // c
- 33, 34, 42, 50, // d
- 42, 34, 50, 50, // e
- 50, 34, 55, 50, // f
- 55, 34, 62, 50, // g
- 62, 34, 69, 50, // h
- 69, 34, 71, 50, // i
- 71, 34, 75, 50, // j
- 75, 34, 81, 50, // k
- 81, 34, 83, 50, // l
- 83, 34, 93, 50, // m
- 93, 34, 100,50, // n
- 100,34, 109,50, // o
- 109,34, 118,50, // p
- 118,34, 127,50, // q
- 127,34, 132,50, // r
- 132,34, 138,50, // s
- 138,34, 143,50, // t
- 143,34, 150,50, // u
- 150,34, 158,50, // v
- 158,34, 171,50, // w
- 171,34, 179,50, // x
- 179,34, 187,50, // y
- 187,34, 195,50, // z
- 195,34, 201,50, // {
- 201,34, 203,50, // |
- 203,34, 209,50, // }
- 209,34, 219,50, // ~
- 219,34, 228,50, //
-
- 219,34, 225,50, // 128
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 144
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 160
- 219,34, 225,50, // 161 A1 ! reverse
- 219,34, 225,50,
- 219,34, 225,50, // 163 A3 Å
- 219,34, 225,50,
- 219,34, 225,50,
- 0, 0, 4, 16, // 166 A6 ¦ (space)
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 176
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50, // 191 BF ? reverse
-
- 12, 51, 24, 67, // 192 C0 Å• big
- 0, 51, 12, 67, // 193 C1 á big
- 24, 51, 36, 67, // 194 C2 â big
- 48, 51, 60, 67, // 195 C3 ă big
- 36, 51, 48, 67, // 196 C4 ä big
- 219,34, 225,50,
- 219,34, 225,50,
- 60, 51, 69, 67, // 199 C7 ç big
- 77, 51, 84, 67, // 200 C8 Ä big
- 70, 51, 77, 67, // 201 C9 é big
- 85, 51, 92, 67, // 202 CA Ä™ big
- 93, 51, 100,67, // 203 CB ë big
- 219,34, 225,50,
- 100,51, 104,67, // 205 CD í big
- 108,51, 113,67, // 206 CE î big
- 113,51, 117,67, // 207 CF Ä big
-
- 219,34, 225,50, // 208
- 117,51, 126,67, // 209 D1 Å„ big
- 219,34, 225,50,
- 126,51, 138,67, // 211 D3 ó big
- 150,51, 162,67, // 212 D4 ô big
- 219,34, 225,50,
- 162,51, 174,67, // 214 D6 ö big
- 219,34, 225,50,
- 219,34, 225,50,
- 194,51, 202,67, // 217 D9 ů big
- 186,51, 194,67, // 218 DA ú big
- 202,51, 210,67, // 219 DB ű big
- 210,51, 218,67, // 220 DC ü big
- 219,34, 225,50,
- 219,34, 225,50,
- 218,51, 227,67, // 223 DF German SS
-
- 7, 68, 14, 84, // 224 E0 Å• small
- 0, 68, 7, 84, // 225 E1 á small
- 14, 68, 21, 84, // 226 E2 â small
- 28, 68, 35, 84, // 227 E3 ă small
- 21, 68, 28, 84, // 228 E4 ä small
- 219,34, 225,50,
- 219,34, 225,50,
- 35, 68, 43, 84, // 231 E7 ç small
- 51, 68, 59, 84, // 232 E8 Ä small
- 43, 68, 51, 84, // 233 E9 é small
- 59, 68, 67, 84, // 234 EA Ä™ small
- 67, 68, 75, 84, // 235 EB ë small
- 219,34, 225,50,
- 75, 68, 79, 84, // 237 ED í small
- 83, 68, 88, 84, // 238 EE î small
- 88, 68, 92, 84, // 239 EF Ä small
-
- 219,34, 225,50, // 240
- 92, 68, 99, 84, // 241 F1 Å„ small
- 219,34, 225,50,
- 99, 68, 108,84, // 243 F3 ó small
- 117,68, 126,84, // 244 F4 ô small
- 219,34, 225,50,
- 126,68, 135,84, // 246 F6 ö small
- 219,34, 225,50,
- 219,34, 225,50,
- 151,68, 158,84, // 249 F9 ů small
- 144,68, 151,84, // 250 FA ú small
- 158,68, 165,84, // 251 FB ű small
- 165,68, 172,84, // 252 FC ü small
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-#else
- 0, 0, 4, 16, // 32
- 4, 0, 7, 16, // !
- 7, 0, 13, 16,
- 14, 0, 21, 16,
- 22, 0, 28, 16,
- 29, 0, 38, 16,
- 39, 0, 48, 16,
- 48, 0, 51, 16,
- 51, 0, 55, 16,
- 55, 0, 59, 16,
- 59, 0, 65, 16,
- 66, 0, 72, 16,
- 73, 0, 76, 16,
- 76, 0, 82, 16,
- 82, 0, 85, 16,
- 85, 0, 90, 16,
- 90, 0, 97, 16,
- 98, 0, 103,16,
- 104,0, 111,16,
- 111,0, 118,16,
- 118,0, 125,16,
- 125,0, 132,16,
- 132,0, 139,16,
- 139,0, 146,16,
- 146,0, 153,16,
- 153,0, 160,16,
- 160,0, 165,16, // :
- 164,0, 169,16, // ;
- 169,0, 177,16, // <
- 177,0, 185,16, // =
- 185,0, 193,16, // >
- 193,0, 201,16, // ?
-
- 201,0, 215,16, // 64
- 0, 17, 10, 33, // A
- 10, 17, 18, 33,
- 19, 17, 28, 33,
- 28, 17, 36, 33,
- 37, 17, 44, 33,
- 45, 17, 52, 33,
- 53, 17, 62, 33,
- 63, 17, 71, 33,
- 72, 17, 75, 33,
- 75, 17, 82, 33,
- 83, 17, 91, 33,
- 92, 17, 99, 33,
- 100,17, 110,33,
- 111,17, 119,33,
-//? 120,17, 129,33, // O
- 216,0, 227,16, // O
- 130,17, 138,33,
- 139,17, 148,33,
- 149,17, 158,33,
- 158,17, 166,33,
- 166,17, 175,33,
- 175,17, 183,33,
- 183,17, 193,33,
- 193,17, 207,33,
- 207,17, 215,33,
- 215,17, 224,33,
- 224,17, 232,33, // Z
- 232,17, 236,33,
- 236,17, 241,33,
- 241,17, 245,33,
- 245,17, 252,33, // ^
- 0, 34, 8, 50, // _
-
- 45, 17, 52, 33, // 96
- 8, 34, 15, 50, // a
- 16, 34, 23, 50,
- 24, 34, 31, 50,
- 31, 34, 38, 50,
- 39, 34, 46, 50,
- 46, 34, 52, 50,
- 52, 34, 59, 50,
- 60, 34, 67, 50,
- 68, 34, 71, 50,
- 71, 34, 76, 50,
- 77, 34, 84, 50,
- 84, 34, 87, 50,
- 88, 34, 99, 50,
- 100,34, 107,50,
-//? 108,34, 115,50, // o
- 238,0, 246,16, // o
- 116,34, 123,50,
- 124,34, 131,50,
- 132,34, 137,50,
- 137,34, 144,50,
- 144,34, 149,50,
- 149,34, 156,50,
- 156,34, 164,50,
- 164,34, 176,50,
- 176,34, 183,50,
- 183,34, 191,50,
- 191,34, 197,50, // z
- 197,34, 203,50,
- 203,34, 205,50,
- 205,34, 211,50,
- 211,34, 219,50,
- 219,34, 225,50,
-
-#if _POLISH
- 219,34, 225,50, // 128
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 0, 51, 8, 67, // 140 S´
- 219,34, 225,50,
- 219,34, 225,50,
- 9, 51, 17, 67, // 143 Z´
-
- 219,34, 225,50, // 144
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 0, 68, 7, 84, // 156 s´
- 219,34, 225,50,
- 219,34, 225,50,
- 8, 68, 14, 84, // 159 z´
-
- 219,34, 225,50, // 160
- 219,34, 225,50,
- 219,34, 225,50,
- 18, 51, 27, 67, // 163 L/
- 219,34, 225,50,
- 28, 51, 39, 67, // 165 A,
- 0, 0, 4, 16, // 166 A6 ¦ (space)
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 40, 51, 48, 67, // 175 Zo
-
- 219,34, 225,50, // 176
- 219,34, 225,50,
- 219,34, 225,50,
- 16, 68, 21, 84, // 179 l/
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 23, 68, 31, 84, // 185 a,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 32, 68, 38, 84, // 191 zo
-
- 219,34, 225,50, // 192
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 49, 51, 58, 67, // 198 C´
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 59, 51, 66, 67, // 202 E,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 208
- 67, 51, 75, 67, // 209 N´
- 219,34, 225,50,
-//? 76, 51, 85, 67, // 211 O´
- 86, 51, 97, 67, // 211 O´
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 224
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 39, 68, 46, 84, // 230 c´
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 47, 68, 54, 84, // 234 e,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 240
- 55, 68, 62, 84, // 241 n´
- 219,34, 225,50,
-//? 63, 68, 70, 84, // 243 o´
- 71, 68, 79, 84, // 243 o´
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-#else
- 219,34, 225,50, // 128
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 144
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 160
- 219,34, 225,50, // 161 A1 ! reverse
- 219,34, 225,50,
- 219,34, 225,50, // 163 A3 Å
- 219,34, 225,50,
- 219,34, 225,50,
- 0, 0, 4, 16, // 166 A6 ¦ (space)
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 176
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50, // 191 BF ? reverse
-
- 10, 51, 20, 67, // 192 C0 Å• big
- 0, 51, 10, 67, // 193 C1 á big
- 20, 51, 30, 67, // 194 C2 â big
- 40, 51, 50, 67, // 195 C3 ă big
- 30, 51, 40, 67, // 196 C4 ä big
- 219,34, 225,50,
- 219,34, 225,50,
- 50, 51, 59, 67, // 199 C7 ç big
- 67, 51, 74, 67, // 200 C8 Ä big
- 59, 51, 66, 67, // 201 C9 é big
- 75, 51, 82, 67, // 202 CA Ä™ big
- 83, 51, 90, 67, // 203 CB ë big
- 219,34, 225,50,
- 91, 51, 95, 67, // 205 CD í big
- 100,51, 103,67, // 206 CE î big
- 104,51, 109,67, // 207 CF Ä big
-
- 219,34, 225,50, // 208
- 109,51, 117,67, // 209 D1 Å„ big
- 219,34, 225,50,
- 118,51, 127,67, // 211 D3 ó big
- 138,51, 147,67, // 212 D4 ô big
- 219,34, 225,50,
- 148,51, 157,67, // 214 D6 ö big
- 219,34, 225,50,
- 219,34, 225,50,
- 177,51, 185,67, // 217 D9 ů big
- 168,51, 176,67, // 218 DA ú big
- 186,51, 194,67, // 219 DB ű big
- 195,51, 203,67, // 220 DC ü big
- 219,34, 225,50,
- 219,34, 225,50,
- 211,51, 220,67, // 223 DF German SS
-
- 8, 68, 15, 84, // 224 E0 Å• small
- 0, 68, 7, 84, // 225 E1 á small
- 16, 68, 23, 84, // 226 E2 â small
- 32, 68, 39, 84, // 227 E3 ă small
- 24, 68, 31, 84, // 228 E4 ä small
- 219,34, 225,50,
- 219,34, 225,50,
- 40, 68, 47, 84, // 231 E7 ç small
- 55, 68, 62, 84, // 232 E8 Ä small
- 47, 68, 54, 84, // 233 E9 é small
- 63, 68, 70, 84, // 234 EA Ä™ small
- 71, 68, 78, 84, // 235 EB ë small
- 219,34, 225,50,
- 79, 68, 83, 84, // 237 ED í small
- 88, 68, 92, 84, // 238 EE î small
- 92, 68, 97, 84, // 239 EF Ä small
-
- 219,34, 225,50, // 240
- 97, 68, 104,84, // 241 F1 Å„ small
- 219,34, 225,50,
- 105,68, 112,84, // 243 F3 ó small
- 121,68, 128,84, // 244 F4 ô small
- 219,34, 225,50,
- 129,68, 136,84, // 246 F6 ö small
- 219,34, 225,50,
- 219,34, 225,50,
- 153,68, 160,84, // 249 F9 ů small
- 145,68, 152,84, // 250 FA ú small
- 161,68, 168,84, // 251 FB ű small
- 169,68, 176,84, // 252 FC ü small
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-#endif
-#endif
-};
-
-
-static short table_text_courier[] =
-{
-// x1, y1, x2, y2
- 231,137,239,153, // 0
- 1,188, 9,204, // .
- 51,188,59,204, // square
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 11,188,19,204, // \t
- 21,188,29,204, // \n
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153, // \r
- 231,137,239,153,
- 231,137,239,153,
- 41,188,49,204, // >
- 31,188,39,204, // <
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-
- 1, 86, 9,102, // 32
- 11, 86, 19,102,
- 21, 86, 29,102,
- 31, 86, 39,102,
- 41, 86, 49,102,
- 51, 86, 59,102,
- 61, 86, 69,102,
- 71, 86, 79,102,
- 81, 86, 89,102,
- 91, 86, 99,102,
- 101, 86,109,102,
- 111, 86,119,102,
- 121, 86,129,102,
- 131, 86,139,102,
- 141, 86,149,102,
- 151, 86,159,102,
- 161, 86,169,102,
- 171, 86,179,102,
- 181, 86,189,102,
- 191, 86,199,102,
- 201, 86,209,102,
- 211, 86,219,102,
- 221, 86,229,102,
- 231, 86,239,102,
- 1,103, 9,119, // 56
- 11,103, 19,119,
- 21,103, 29,119,
- 31,103, 39,119,
- 41,103, 49,119,
- 51,103, 59,119,
- 61,103, 69,119,
- 71,103, 79,119,
-
- 81,103, 89,119, // @
- 91,103, 99,119,
- 101,103,109,119,
- 111,103,119,119,
- 121,103,129,119,
- 131,103,139,119,
- 141,103,149,119,
- 151,103,159,119,
- 161,103,169,119,
- 171,103,179,119,
- 181,103,189,119,
- 191,103,199,119,
- 201,103,209,119,
- 211,103,219,119,
- 221,103,229,119,
- 231,103,239,119,
- 1,120, 9,136, // P
- 11,120, 19,136,
- 21,120, 29,136,
- 31,120, 39,136,
- 41,120, 49,136,
- 51,120, 59,136,
- 61,120, 69,136,
- 71,120, 79,136,
- 81,120, 89,136,
- 91,120, 99,136,
- 101,120,109,136,
- 111,120,119,136, // [
- 121,120,129,136,
- 131,120,139,136,
- 141,120,149,136,
- 151,120,159,136, // _
-
- 161,120,169,136,
- 171,120,179,136, // a
- 181,120,189,136,
- 191,120,199,136,
- 201,120,209,136,
- 211,120,219,136,
- 221,120,229,136,
- 231,120,239,136,
- 1,137, 9,153,
- 11,137, 19,153,
- 21,137, 29,153,
- 31,137, 39,153,
- 41,137, 49,153,
- 51,137, 59,153,
- 61,137, 69,153,
- 71,137, 79,153, // o
- 81,137, 89,153,
- 91,137, 99,153,
- 101,137,109,153,
- 111,137,119,153,
- 121,137,129,153,
- 131,137,139,153,
- 141,137,149,153,
- 151,137,159,153,
- 161,137,169,153,
- 171,137,179,153,
- 181,137,189,153,
- 191,137,199,153,
- 201,137,209,153,
- 211,137,219,153,
- 221,137,229,153, // ~
- 231,137,239,153,
-
-#if _POLISH
- 231,137,239,153, // 128
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 1,154, 9,170, // 140 S´
- 231,137,239,153,
- 231,137,239,153,
- 11,154, 19,170, // 143 Z´
-
- 231,137,239,153, // 144
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 1,171, 9,187, // 156 s´
- 231,137,239,153,
- 231,137,239,153,
- 11,171, 19,187, // 159 z´
-
- 231,137,239,153, // 160
- 231,137,239,153,
- 231,137,239,153,
- 21,154, 29,170, // 163 L/
- 231,137,239,153,
- 31,154, 39,170, // 165 A,
- 1, 86, 9,102, // 166 A6 ¦ (space)
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 41,154, 49,170, // 175 Zo
-
- 231,137,239,153, // 176
- 231,137,239,153,
- 231,137,239,153,
- 21,171, 29,187, // 179 l/
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 31,171, 39,187, // 185 a,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 41,171, 49,187, // 191 zo
-
- 231,137,239,153, // 192
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 51,154, 59,170, // 198 C´
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 61,154, 69,170, // 202 E,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-
- 231,137,239,153, // 208
- 71,154, 79,170, // 209 N´
- 231,137,239,153,
- 81,171, 89,187, // 211 O´
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-
- 231,137,239,153, // 224
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 51,171, 59,187, // 230 c´
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 61,171, 69,187, // 234 e,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-
- 231,137,239,153, // 240
- 71,171, 79,187, // 241 n´
- 231,137,239,153,
- 81,171, 89,187, // 243 ó small
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-#else
- 231,137,239,153, // 128
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-
- 231,137,239,153, // 144
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-
- 231,137,239,153, // 160
- 231,137,239,153, // 161 A1 ! reverse
- 231,137,239,153,
- 231,137,239,153, // 163 A3 Å
- 231,137,239,153,
- 231,137,239,153,
- 1, 86, 9,102, // 166 A6 ¦ (space)
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-
- 231,137,239,153, // 176
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153, // 191 BF ? reverse
-
- 11,154, 19,170, // Å• big
- 1,154, 9,170, // á big
- 21,154, 29,170, // â big
- 41,154, 49,170, // ă big
- 31,154, 39,170, // ä big
- 231,137,239,153,
- 231,137,239,153,
- 51,154, 59,170, // ç big
- 71,154, 79,170, // Ä big
- 61,154, 69,170, // é big
- 81,154, 89,170, // Ä™ big
- 91,154, 99,170, // ë big
- 231,137,239,153,
- 101,154,109,170, // í big
- 121,154,129,170, // î big
- 131,154,139,170, // Ä big
- 231,137,239,153,
- 141,154,149,170, // Å„ big
- 231,137,239,153,
- 151,154,159,170, // ó big
- 171,154,179,170, // ô big
- 231,137,239,153,
- 181,154,189,170, // ö big
- 231,137,239,153,
- 231,137,239,153,
- 211,154,219,170, // ů big
- 201,154,209,170, // ú big
- 221,154,229,170, // ű big
- 231,154,239,170, // ü big
- 231,137,239,153,
- 231,137,239,153,
- 241,154,249,170, // 223 DF German SS
-
- 11,171, 19,187, // Å• small
- 1,171, 9,187, // á small
- 21,171, 29,187, // â small
- 41,171, 49,187, // ă small
- 31,171, 39,187, // ä small
- 231,137,239,153,
- 231,137,239,153,
- 51,171, 59,187, // ç small
- 71,171, 79,187, // Ä small
- 61,171, 69,187, // é small
- 81,171, 89,187, // Ä™ small
- 91,171, 99,187, // ë small
- 231,137,239,153,
- 111,171,119,187, // Ä› small
- 121,171,129,187, // î small
- 131,171,139,187, // Ä small
- 231,137,239,153,
- 141,171,149,187, // Å„ small
- 231,137,239,153,
- 151,171,159,187, // ó small
- 171,171,179,187, // ô small
- 231,137,239,153,
- 181,171,189,187, // ö small
- 231,137,239,153,
- 231,137,239,153,
- 211,171,219,187, // ů small
- 201,171,209,187, // ú small
- 221,171,229,187, // ű small
- 231,171,239,187, // ü small
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-#endif
-};
-
-
-// Returns the pointer to the table by the font.
-
-short* RetTable(FontType font)
-{
- if ( font == FONT_COLOBOT ) return table_text_colobot;
- else return table_text_courier;
-}
-
-
-
-// Object's constructor.
-
-CText::CText(CInstanceManager* iMan, CD3DEngine* engine)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_TEXT, this);
-
- m_pD3DDevice = 0;
- m_engine = engine;
-}
-
-// Object's destructor.
-
-CText::~CText()
-{
- m_iMan->DeleteInstance(CLASS_TEXT, this);
-}
-
-
-void CText::SetD3DDevice(LPDIRECT3DDEVICE7 device)
-{
- m_pD3DDevice = device;
-}
-
-
-// Displays multi-font text.
-// The vertical position is at the bottom of the box of the character.
-
-void CText::DrawText(char *string, char *format, int len, Math::Point pos,
- float width, int justif, float size, float stretch,
- int eol)
-{
- float sw;
-
- if ( justif == 0 ) // center?
- {
- sw = RetStringWidth(string, format, len, size, stretch);
- if ( sw > width ) sw = width;
- pos.x -= sw/2.0f;
- }
- if ( justif < 0 ) // flag was left?
- {
- sw = RetStringWidth(string, format, len, size, stretch);
- if ( sw > width ) sw = width;
- pos.x -= sw;
- }
- DrawString(string, format, len, pos, width, size, stretch, eol);
-}
-
-// Displays multi-font text.
-// The vertical position is at the bottom of the box of the character.
-
-void CText::DrawText(char *string, char *format, Math::Point pos, float width,
- int justif, float size, float stretch,
- int eol)
-{
- DrawText(string, format, strlen(string), pos, width, justif, size, stretch, eol);
-}
-
-// Displays text.
-// The vertical position is at the bottom of the box of the character.
-
-void CText::DrawText(char *string, int len, Math::Point pos, float width,
- int justif, float size, float stretch, FontType font,
- int eol)
-{
- float sw;
-
- if ( justif == 0 ) // center?
- {
- sw = RetStringWidth(string, len, size, stretch, font);
- if ( sw > width ) sw = width;
- pos.x -= sw/2.0f;
- }
- if ( justif < 0 ) // flag was left?
- {
- sw = RetStringWidth(string, len, size, stretch, font);
- if ( sw > width ) sw = width;
- pos.x -= sw;
- }
- DrawString(string, len, pos, width, size, stretch, font, eol);
-}
-
-// Displays text.
-// The vertical position is at the bottom of the box of the character.
-
-void CText::DrawText(char *string, Math::Point pos, float width,
- int justif, float size, float stretch, FontType font,
- int eol)
-{
- DrawText(string, strlen(string), pos, width, justif, size, stretch, font, eol);
-}
-
-
-// Returns the size of a multi-font text.
-
-void CText::DimText(char *string, char *format, int len, Math::Point pos,
- int justif, float size, float stretch,
- Math::Point &start, Math::Point &end)
-{
- float sw;
-
- start = end = pos;
-
- sw = RetStringWidth(string, format, len, size, stretch);
- end.x += sw;
- if ( justif == 0 ) // center?
- {
- start.x -= sw/2.0f;
- end.x -= sw/2.0f;
- }
- if ( justif < 0 ) // flag was left?
- {
- start.x -= sw;
- end.x -= sw;
- }
-
- start.y -= RetDescent(size, FONT_COLOBOT);
- end.y += RetAscent(size, FONT_COLOBOT);
-}
-
-// Returns the size of a multi-font text.
-
-void CText::DimText(char *string, char *format, Math::Point pos, int justif,
- float size, float stretch,
- Math::Point &start, Math::Point &end)
-{
- DimText(string, format, strlen(string), pos, justif, size, stretch, start, end);
-}
-
-// Returns the size of a text.
-
-void CText::DimText(char *string, int len, Math::Point pos, int justif,
- float size, float stretch, FontType font,
- Math::Point &start, Math::Point &end)
-{
- float sw;
-
- start = end = pos;
-
- sw = RetStringWidth(string, len, size, stretch, font);
- end.x += sw;
- if ( justif == 0 ) // center?
- {
- start.x -= sw/2.0f;
- end.x -= sw/2.0f;
- }
- if ( justif < 0 ) // flag was left?
- {
- start.x -= sw;
- end.x -= sw;
- }
-
- start.y -= RetDescent(size, font);
- end.y += RetAscent(size, font);
-}
-
-// Returns the size of a text.
-
-void CText::DimText(char *string, Math::Point pos, int justif,
- float size, float stretch, FontType font,
- Math::Point &start, Math::Point &end)
-{
- DimText(string, strlen(string), pos, justif, size, stretch, font, start, end);
-}
-
-
-// Returns the height above the baseline.
-
-float CText::RetAscent(float size, FontType font)
-{
- return (13.0f/256.0f)*(size/20.0f);
-}
-
-// Returns the height below the baseline.
-
-float CText::RetDescent(float size, FontType font)
-{
- return (3.0f/256.0f)*(size/20.0f);
-}
-
-// Returns the total height of the character.
-
-float CText::RetHeight(float size, FontType font)
-{
- return (16.0f/256.0f)*(size/20.0f);
-}
-
-
-// Returns the width of a string of multi-font characters.
-
-float CText::RetStringWidth(char *string, char *format, int len,
- float size, float stretch)
-{
- FontType font;
- float st, tab, w, width = 0.0f;
- short *table, *pt;
- int i, c;
-
- for ( i=0 ; i<len ; i++ )
- {
- font = (FontType)(format[i]&FONT_MASK);
- if ( font == FONT_BUTTON )
- {
- width += (12.0f/256.0f)*(size/20.0f);
- }
- else
- {
- table = RetTable(font);
- c = (unsigned char)string[i];
-
- if ( c == '\t' )
- {
- pt = table+' '*4;
- tab = (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*stretch*m_engine->RetEditIndentValue();
- w = tab-Math::Mod(width, tab);
- if ( w < tab*0.1f ) w += tab;
- width += w;
- continue;
- }
-
- if ( c > 255 ) continue;
-
- pt = table+c*4;
- st = stretch;
- if ( font == FONT_COLOBOT && (c == 'O' || c == 'o') ) st = 0.8f;
- width += (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*st;
- }
- }
-
- return width;
-}
-
-// Returns the width of a string of characters.
-
-float CText::RetStringWidth(char *string, int len,
- float size, float stretch, FontType font)
-{
- float st, tab, w, width = 0.0f;
- short *table, *pt;
- int i, c;
-
- table = RetTable(font);
- for ( i=0 ; i<len ; i++ )
- {
- c = (unsigned char)string[i];
-
- if ( c == '\t' )
- {
- pt = table+' '*4;
- tab = (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*stretch*m_engine->RetEditIndentValue();
- w = tab-Math::Mod(width, tab);
- if ( w < tab*0.1f ) w += tab;
- width += w;
- continue;
- }
-
- if ( c > 255 ) continue;
-
- pt = table+c*4;
- st = stretch;
- if ( font == FONT_COLOBOT && (c == 'O' || c == 'o') ) st = 0.8f;
- width += (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*st;
- }
-
- return width;
-}
-
-// Returns the width of a character.
-// 'offset' is the current position in the line.
-
-float CText::RetCharWidth(int character, float offset,
- float size, float stretch, FontType font)
-{
- float st, tab, w;
- short* pt;
-
- if ( font == FONT_BUTTON ) return (12.0f/256.0f)*(size/20.0f);
-
- if ( character == '\t' )
- {
- pt = RetTable(font)+' '*4;
- tab = (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*stretch*m_engine->RetEditIndentValue();
- w = tab-Math::Mod(offset, tab);
- if ( w < tab*0.1f ) w += tab;
- return w;
- }
-
- if ( character > 255 ) return 0.0f;
-
- pt = RetTable(font)+character*4;
- st = stretch;
-#if !_NEWLOOK
- if ( font == FONT_COLOBOT && (character == 'O' || character == 'o') ) st = 0.8f;
-#endif
- return (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*st;
-}
-
-
-// Justifies a line of multi-font text. Returns the offset of the cut.
-
-int CText::Justif(char *string, char *format, int len, float width,
- float size, float stretch)
-{
- FontType font;
- float pos;
- int i, character, cut;
-
- pos = 0.0f;
- cut = 0;
- for ( i=0 ; i<len ; i++ )
- {
- font = (FontType)(format[i]&FONT_MASK);
- character = (unsigned char)string[i];
-
- if ( character == 0 )
- {
- return i;
- }
- if ( font != FONT_BUTTON )
- {
- if ( character == '\n' )
- {
- return i+1;
- }
- if ( character == ' ' )
- {
- cut = i+1;
- }
- }
-
- pos += RetCharWidth(character, pos, size, stretch, font);
- if ( pos > width )
- {
- if ( cut == 0 ) return i;
- else return cut;
- }
- }
- return i;
-}
-
-// Justify a line of text. Returns the offset of the cut.
-
-int CText::Justif(char *string, int len, float width,
- float size, float stretch, FontType font)
-{
- float pos;
- int i, character, cut;
-
- pos = 0.0f;
- cut = 0;
- for ( i=0 ; i<len ; i++ )
- {
- character = (unsigned char)string[i];
-
- if ( character == 0 )
- {
- return i;
- }
- if ( character == '\n' )
- {
- return i+1;
- }
- if ( character == ' ' )
- {
- cut = i+1;
- }
-
- pos += RetCharWidth(character, pos, size, stretch, font);
- if ( pos > width )
- {
- if ( cut == 0 ) return i;
- else return cut;
- }
- }
- return i;
-}
-
-// Returns the most suitable position to a given offset (multi-font).
-
-int CText::Detect(char *string, char *format, int len, float offset,
- float size, float stretch)
-{
- FontType font;
- float pos, width;
- int i, character, cut;
-
- pos = 0.0f;
- cut = 0;
- for ( i=0 ; i<len ; i++ )
- {
- font = (FontType)(format[i]&FONT_MASK);
- character = (unsigned char)string[i];
-
- if ( character == 0 )
- {
- return i;
- }
- if ( font != FONT_BUTTON )
- {
- if ( character == '\n' )
- {
- return i;
- }
- }
-
- width = RetCharWidth(character, pos, size, stretch, font);
- if ( offset <= pos+width/2.0f )
- {
- return i;
- }
- pos += width;
- }
- return i;
-}
-
-// Returns the most suitable position to a given offset (multi-font).
-
-int CText::Detect(char *string, int len, float offset,
- float size, float stretch, FontType font)
-{
- float pos, width;
- int i, character, cut;
-
- pos = 0.0f;
- cut = 0;
- for ( i=0 ; i<len ; i++ )
- {
- character = (unsigned char)string[i];
-
- if ( character == 0 ||
- character == '\n' )
- {
- return i;
- }
-
- width = RetCharWidth(character, pos, size, stretch, font);
- if ( offset <= pos+width/2.0f )
- {
- return i;
- }
- pos += width;
- }
- return i;
-}
-
-
-// Displays multi-font text.
-
-void CText::DrawString(char *string, char *format, int len, Math::Point pos,
- float width, float size, float stretch, int eol)
-{
- FontType font;
- float start, offset, cw;
- int i, c;
-
-#if _POLISH
- m_engine->SetTexture("textp.tga");
-#else
- m_engine->SetTexture("text.tga");
-#endif
- m_engine->SetState(D3DSTATETTw);
-
- font = FONT_COLOBOT;
-
- start = pos.x;
- offset = 0.0f;
- for ( i=0 ; i<len ; i++ )
- {
- font = (FontType)(format[i]&FONT_MASK);
- c = (unsigned char)string[i];
- cw = RetCharWidth(c, offset, size, stretch, font);
-
- if ( offset+cw > width ) // exceeds the maximum width?
- {
- cw = RetCharWidth(16, offset, size, stretch, font);
- pos.x = start+width-cw;
- DrawChar(16, pos, size, stretch, font); // >
- break;
- }
-
- if ( (format[i]&COLOR_MASK) != 0 )
- {
- DrawColor(pos, size, cw, format[i]&COLOR_MASK);
- }
- DrawChar(c, pos, size, stretch, font);
- offset += cw;
- pos.x += cw;
- }
-
- if ( eol != 0 )
- {
- DrawChar(eol, pos, size, stretch, font);
- }
-}
-
-// Displays text.
-
-void CText::DrawString(char *string, int len, Math::Point pos, float width,
- float size, float stretch, FontType font,
- int eol)
-{
- float start, offset, cw;
- int i, c;
-
-#if _POLISH
- m_engine->SetTexture("textp.tga");
-#else
- m_engine->SetTexture("text.tga");
-#endif
- m_engine->SetState(D3DSTATETTw);
-
- start = pos.x;
- offset = 0.0f;
- for ( i=0 ; i<len ; i++ )
- {
- c = (unsigned char)string[i];
- cw = RetCharWidth(c, offset, size, stretch, font);
-
- if ( offset+cw > width ) // exceeds the maximum width?
- {
- cw = RetCharWidth(16, offset, size, stretch, font);
- pos.x = start+width-cw;
- DrawChar(16, pos, size, stretch, font); // >
- break;
- }
-
- DrawChar(c, pos, size, stretch, font);
- offset += cw;
- pos.x += cw;
- }
-
- if ( eol != 0 )
- {
- DrawChar(eol, pos, size, stretch, font);
- }
-}
-
-// Displays the link to a character.
-
-void CText::DrawColor(Math::Point pos, float size, float width, int color)
-{
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Point p1, p2;
- POINT dim;
- Math::Vector n;
- float h, u1, u2, v1, v2, dp;
- int icon;
-
- icon = -1;
- if ( color == COLOR_LINK ) icon = 9; // blue
- if ( color == COLOR_TOKEN ) icon = 4; // orange
- if ( color == COLOR_TYPE ) icon = 5; // green
- if ( color == COLOR_CONST ) icon = 8; // red
- if ( color == COLOR_REM ) icon = 6; // magenta
- if ( color == COLOR_KEY ) icon = 10; // gray
- if ( icon == -1 ) return;
-
- if ( color == COLOR_LINK )
- {
- m_engine->SetState(D3DSTATENORMAL);
- }
-
- dim = m_engine->RetDim();
- if ( dim.y <= 768.0f ) // 1024x768 or less?
- {
- h = 1.01f/dim.y; // 1 pixel
- }
- else // more than 1024x768?
- {
- h = 2.0f/dim.y; // 2 pixels
- }
-
- p1.x = pos.x;
- p2.x = pos.x + width;
-
- if ( color == COLOR_LINK )
- {
- p1.y = pos.y;
- p2.y = pos.y + h; // just emphasized
- }
- else
- {
-#if 1
- p1.y = pos.y;
- p2.y = pos.y + (16.0f/256.0f)*(size/20.0f);
-//? p2.y = pos.y + h*4.0f; // just emphasized thick
-#else
- p1.y = pos.y;
- p2.y = pos.y + (16.0f/256.0f)*(size/20.0f)/4.0f;
-#endif
- }
-
- u1 = (16.0f/256.0f)*(icon%16);
- v1 = (240.0f/256.0f);
- u2 = (16.0f/256.0f)+u1;
- v2 = (16.0f/256.0f)+v1;
-
- dp = 0.5f/256.0f;
- u1 += dp;
- v1 += dp;
- u2 -= dp;
- v2 -= dp;
-
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-
- if ( color == COLOR_LINK )
- {
- m_engine->SetState(D3DSTATETTw);
- }
-}
-
-// Displays a character.
-
-void CText::DrawChar(int character, Math::Point pos, float size,
- float stretch, FontType font)
-{
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Point p1, p2;
- Math::Vector n;
- float width, height, u1, u2, v1, v2, dp;
- short* pt;
-
- dp = 0.5f/256.0f;
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
-
- if ( font == FONT_BUTTON )
- {
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATENORMAL);
-
- p1.x = pos.x;
- p1.y = pos.y;
- p2.x = pos.x + (12.0f/256.0f)*(size/20.0f);
- p2.y = pos.y + (16.0f/256.0f)*(size/20.0f);
-
- if ( character <= 64 || character >= 128+56 )
- {
- u1 = 66.0f/256.0f;
- v1 = 2.0f/256.0f;
- u2 = 94.0f/256.0f;
- v2 = 30.0f/256.0f;
- }
- else
- {
- u1 = 224.0f/256.0f;
- v1 = 32.0f/256.0f;
- u2 = 256.0f/256.0f;
- v2 = 64.0f/256.0f;
- }
-
- u1 += dp;
- v1 += dp;
- u2 -= dp;
- v2 -= dp;
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-
-//? p1.x += (12.0f/256.0f)*(size/20.0f)*0.1f;
-//? p1.y += (16.0f/256.0f)*(size/20.0f)*0.1f;
-//? p2.x -= (12.0f/256.0f)*(size/20.0f)*0.1f;
-//? p2.y -= (16.0f/256.0f)*(size/20.0f)*0.1f;
-
- if ( character >= 64 && character < 64+64 )
- {
- character -= 64;
- m_engine->SetTexture("button2.tga");
- }
- if ( character >= 128 && character < 128+64 )
- {
- character -= 128;
- m_engine->SetTexture("button3.tga");
- }
-
- m_engine->SetState(D3DSTATETTw);
-
- u1 = (32.0f/256.0f)*(character%8);
- v1 = (32.0f/256.0f)*(character/8); // uv texture
- u2 = (32.0f/256.0f)+u1;
- v2 = (32.0f/256.0f)+v1;
-
- u1 += dp;
- v1 += dp;
- u2 -= dp;
- v2 -= dp;
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-
-
-#if _POLISH
- m_engine->SetTexture("textp.tga");
-#else
- m_engine->SetTexture("text.tga");
-#endif
- return;
- }
-
- if ( character > 255 ) return;
-
-//? if ( character == '\t' ) character = ' '; // if tab, does not display ->
-
-#if !_NEWLOOK
- if ( font == FONT_COLOBOT && (character == 'O' || character == 'o') )
- {
- stretch = 0.8f;
- }
-#endif
- if ( font == FONT_COURIER )
- {
- stretch *= 1.2f;
- }
-
- pt = RetTable(font)+character*4;
- width = (float)(pt[2]-pt[0])/256.0f*stretch*0.9f;
-//? width = (float)(pt[2]-pt[0])/256.0f*stretch;
- height = (float)(pt[3]-pt[1])/256.0f;
-
-#if _NEWLOOK
- pos.y += height*(size/20.0f)/17.0f;
-#endif
- p1.x = pos.x;
- p1.y = pos.y;
- p2.x = pos.x + width*(size/20.0f);
- p2.y = pos.y + height*(size/20.0f);
-
- u1 = (float)pt[0]/256.0f;
- v1 = (float)pt[1]/256.0f;
- u2 = (float)pt[2]/256.0f;
- v2 = (float)pt[3]/256.0f;
-
- if ( font == FONT_COLOBOT )
- {
- u1 += dp;
- u2 += dp;
-#if _NEWLOOK
- v2 += dp;
-#endif
- }
- if ( font == FONT_COURIER )
- {
- u1 -= dp;
- u2 += dp*2.0f;
- }
-
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// text.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "common/language.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "old/text.h"
+
+
+
+static short table_text_colobot[] =
+{
+// x1, y1, x2, y2
+ 219,34, 225,50, // 0
+ 1,188, 9,203, // .
+ 51,188,59,203, // square
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 11,188,19,203, // \t
+ 21,188,29,203, // \n
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50, // \r
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 41,188,49,203, // >
+ 31,188,39,203, // <
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+#if _NEWLOOK
+ 0, 0, 4, 16, // 32
+ 7, 0, 9, 16, // !
+ 9, 0, 13, 16, // "
+ 13, 0, 24, 16, // #
+ 24, 0, 31, 16, // $
+ 31, 0, 43, 16, // %
+ 43, 0, 54, 16, // &
+ 54, 0, 56, 16, // '
+ 56, 0, 61, 16, // (
+ 61, 0, 67, 16, // )
+ 67, 0, 73, 16, // *
+ 73, 0, 83, 16, // +
+ 83, 0, 87, 16, // ,
+ 87, 0, 92, 16, // -
+ 92, 0, 94, 16, // .
+ 94, 0, 101,16, // /
+ 101,0, 109,16, // 0
+ 109,0, 114,16, // 1
+ 114,0, 122,16, // 2
+ 122,0, 129,16, // 3
+ 129,0, 138,16, // 4
+ 138,0, 146,16, // 5
+ 146,0, 154,16, // 6
+ 154,0, 161,16, // 7
+ 161,0, 169,16, // 8
+ 169,0, 177,16, // 9
+ 177,0, 179,16, // :
+ 179,0, 183,16, // ;
+ 183,0, 193,16, // <
+ 193,0, 203,16, // =
+ 203,0, 213,16, // >
+ 213,0, 219,16, // ?
+
+ 0, 17, 14, 33, // @ 64
+ 14, 17, 26, 33, // A
+ 26, 17, 33, 33, // B
+ 33, 17, 42, 33, // C
+ 42, 17, 51, 33, // D
+ 51, 17, 58, 33, // E
+ 58, 17, 63, 33, // F
+ 63, 17, 73, 33, // G
+ 73, 17, 82, 33, // H
+ 82, 17, 84, 33, // I
+ 84, 17, 90, 33, // J
+ 90, 17, 98, 33, // K
+ 98, 17, 103,33, // L
+ 103,17, 115,33, // M
+ 115,17, 124,33, // N
+ 124,17, 136,33, // O
+ 136,17, 142,33, // P
+ 142,17, 154,33, // Q
+ 154,17, 160,33, // R
+ 160,17, 167,33, // S
+ 167,17, 175,33, // T
+ 175,17, 183,33, // U
+ 183,17, 194,33, // V
+ 194,17, 208,33, // W
+ 208,17, 218,33, // X
+ 218,17, 227,33, // Y
+ 227,17, 236,33, // Z
+ 236,17, 241,33, // [
+ 241,17, 248,33, // \
+ 248,17, 252,33, // ]
+ 219,0, 229,16, // ^
+ 0, 34, 9, 50, // _
+
+ 54, 0, 56, 16, // ` 96
+ 9, 34, 16, 50, // a
+ 16, 34, 25, 50, // b
+ 25, 34, 33, 50, // c
+ 33, 34, 42, 50, // d
+ 42, 34, 50, 50, // e
+ 50, 34, 55, 50, // f
+ 55, 34, 62, 50, // g
+ 62, 34, 69, 50, // h
+ 69, 34, 71, 50, // i
+ 71, 34, 75, 50, // j
+ 75, 34, 81, 50, // k
+ 81, 34, 83, 50, // l
+ 83, 34, 93, 50, // m
+ 93, 34, 100,50, // n
+ 100,34, 109,50, // o
+ 109,34, 118,50, // p
+ 118,34, 127,50, // q
+ 127,34, 132,50, // r
+ 132,34, 138,50, // s
+ 138,34, 143,50, // t
+ 143,34, 150,50, // u
+ 150,34, 158,50, // v
+ 158,34, 171,50, // w
+ 171,34, 179,50, // x
+ 179,34, 187,50, // y
+ 187,34, 195,50, // z
+ 195,34, 201,50, // {
+ 201,34, 203,50, // |
+ 203,34, 209,50, // }
+ 209,34, 219,50, // ~
+ 219,34, 228,50, //
+
+ 219,34, 225,50, // 128
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 144
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 160
+ 219,34, 225,50, // 161 A1 ! reverse
+ 219,34, 225,50,
+ 219,34, 225,50, // 163 A3 Å
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 0, 0, 4, 16, // 166 A6 ¦ (space)
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 176
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50, // 191 BF ? reverse
+
+ 12, 51, 24, 67, // 192 C0 Å• big
+ 0, 51, 12, 67, // 193 C1 á big
+ 24, 51, 36, 67, // 194 C2 â big
+ 48, 51, 60, 67, // 195 C3 ă big
+ 36, 51, 48, 67, // 196 C4 ä big
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 60, 51, 69, 67, // 199 C7 ç big
+ 77, 51, 84, 67, // 200 C8 Ä big
+ 70, 51, 77, 67, // 201 C9 é big
+ 85, 51, 92, 67, // 202 CA Ä™ big
+ 93, 51, 100,67, // 203 CB ë big
+ 219,34, 225,50,
+ 100,51, 104,67, // 205 CD í big
+ 108,51, 113,67, // 206 CE î big
+ 113,51, 117,67, // 207 CF Ä big
+
+ 219,34, 225,50, // 208
+ 117,51, 126,67, // 209 D1 Å„ big
+ 219,34, 225,50,
+ 126,51, 138,67, // 211 D3 ó big
+ 150,51, 162,67, // 212 D4 ô big
+ 219,34, 225,50,
+ 162,51, 174,67, // 214 D6 ö big
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 194,51, 202,67, // 217 D9 ů big
+ 186,51, 194,67, // 218 DA ú big
+ 202,51, 210,67, // 219 DB ű big
+ 210,51, 218,67, // 220 DC ü big
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 218,51, 227,67, // 223 DF German SS
+
+ 7, 68, 14, 84, // 224 E0 Å• small
+ 0, 68, 7, 84, // 225 E1 á small
+ 14, 68, 21, 84, // 226 E2 â small
+ 28, 68, 35, 84, // 227 E3 ă small
+ 21, 68, 28, 84, // 228 E4 ä small
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 35, 68, 43, 84, // 231 E7 ç small
+ 51, 68, 59, 84, // 232 E8 Ä small
+ 43, 68, 51, 84, // 233 E9 é small
+ 59, 68, 67, 84, // 234 EA Ä™ small
+ 67, 68, 75, 84, // 235 EB ë small
+ 219,34, 225,50,
+ 75, 68, 79, 84, // 237 ED í small
+ 83, 68, 88, 84, // 238 EE î small
+ 88, 68, 92, 84, // 239 EF Ä small
+
+ 219,34, 225,50, // 240
+ 92, 68, 99, 84, // 241 F1 Å„ small
+ 219,34, 225,50,
+ 99, 68, 108,84, // 243 F3 ó small
+ 117,68, 126,84, // 244 F4 ô small
+ 219,34, 225,50,
+ 126,68, 135,84, // 246 F6 ö small
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 151,68, 158,84, // 249 F9 ů small
+ 144,68, 151,84, // 250 FA ú small
+ 158,68, 165,84, // 251 FB ű small
+ 165,68, 172,84, // 252 FC ü small
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+#else
+ 0, 0, 4, 16, // 32
+ 4, 0, 7, 16, // !
+ 7, 0, 13, 16,
+ 14, 0, 21, 16,
+ 22, 0, 28, 16,
+ 29, 0, 38, 16,
+ 39, 0, 48, 16,
+ 48, 0, 51, 16,
+ 51, 0, 55, 16,
+ 55, 0, 59, 16,
+ 59, 0, 65, 16,
+ 66, 0, 72, 16,
+ 73, 0, 76, 16,
+ 76, 0, 82, 16,
+ 82, 0, 85, 16,
+ 85, 0, 90, 16,
+ 90, 0, 97, 16,
+ 98, 0, 103,16,
+ 104,0, 111,16,
+ 111,0, 118,16,
+ 118,0, 125,16,
+ 125,0, 132,16,
+ 132,0, 139,16,
+ 139,0, 146,16,
+ 146,0, 153,16,
+ 153,0, 160,16,
+ 160,0, 165,16, // :
+ 164,0, 169,16, // ;
+ 169,0, 177,16, // <
+ 177,0, 185,16, // =
+ 185,0, 193,16, // >
+ 193,0, 201,16, // ?
+
+ 201,0, 215,16, // 64
+ 0, 17, 10, 33, // A
+ 10, 17, 18, 33,
+ 19, 17, 28, 33,
+ 28, 17, 36, 33,
+ 37, 17, 44, 33,
+ 45, 17, 52, 33,
+ 53, 17, 62, 33,
+ 63, 17, 71, 33,
+ 72, 17, 75, 33,
+ 75, 17, 82, 33,
+ 83, 17, 91, 33,
+ 92, 17, 99, 33,
+ 100,17, 110,33,
+ 111,17, 119,33,
+//? 120,17, 129,33, // O
+ 216,0, 227,16, // O
+ 130,17, 138,33,
+ 139,17, 148,33,
+ 149,17, 158,33,
+ 158,17, 166,33,
+ 166,17, 175,33,
+ 175,17, 183,33,
+ 183,17, 193,33,
+ 193,17, 207,33,
+ 207,17, 215,33,
+ 215,17, 224,33,
+ 224,17, 232,33, // Z
+ 232,17, 236,33,
+ 236,17, 241,33,
+ 241,17, 245,33,
+ 245,17, 252,33, // ^
+ 0, 34, 8, 50, // _
+
+ 45, 17, 52, 33, // 96
+ 8, 34, 15, 50, // a
+ 16, 34, 23, 50,
+ 24, 34, 31, 50,
+ 31, 34, 38, 50,
+ 39, 34, 46, 50,
+ 46, 34, 52, 50,
+ 52, 34, 59, 50,
+ 60, 34, 67, 50,
+ 68, 34, 71, 50,
+ 71, 34, 76, 50,
+ 77, 34, 84, 50,
+ 84, 34, 87, 50,
+ 88, 34, 99, 50,
+ 100,34, 107,50,
+//? 108,34, 115,50, // o
+ 238,0, 246,16, // o
+ 116,34, 123,50,
+ 124,34, 131,50,
+ 132,34, 137,50,
+ 137,34, 144,50,
+ 144,34, 149,50,
+ 149,34, 156,50,
+ 156,34, 164,50,
+ 164,34, 176,50,
+ 176,34, 183,50,
+ 183,34, 191,50,
+ 191,34, 197,50, // z
+ 197,34, 203,50,
+ 203,34, 205,50,
+ 205,34, 211,50,
+ 211,34, 219,50,
+ 219,34, 225,50,
+
+#if _POLISH
+ 219,34, 225,50, // 128
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 0, 51, 8, 67, // 140 S´
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 9, 51, 17, 67, // 143 Z´
+
+ 219,34, 225,50, // 144
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 0, 68, 7, 84, // 156 s´
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 8, 68, 14, 84, // 159 z´
+
+ 219,34, 225,50, // 160
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 18, 51, 27, 67, // 163 L/
+ 219,34, 225,50,
+ 28, 51, 39, 67, // 165 A,
+ 0, 0, 4, 16, // 166 A6 ¦ (space)
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 40, 51, 48, 67, // 175 Zo
+
+ 219,34, 225,50, // 176
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 16, 68, 21, 84, // 179 l/
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 23, 68, 31, 84, // 185 a,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 32, 68, 38, 84, // 191 zo
+
+ 219,34, 225,50, // 192
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 49, 51, 58, 67, // 198 C´
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 59, 51, 66, 67, // 202 E,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 208
+ 67, 51, 75, 67, // 209 N´
+ 219,34, 225,50,
+//? 76, 51, 85, 67, // 211 O´
+ 86, 51, 97, 67, // 211 O´
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 224
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 39, 68, 46, 84, // 230 c´
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 47, 68, 54, 84, // 234 e,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 240
+ 55, 68, 62, 84, // 241 n´
+ 219,34, 225,50,
+//? 63, 68, 70, 84, // 243 o´
+ 71, 68, 79, 84, // 243 o´
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+#else
+ 219,34, 225,50, // 128
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 144
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 160
+ 219,34, 225,50, // 161 A1 ! reverse
+ 219,34, 225,50,
+ 219,34, 225,50, // 163 A3 Å
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 0, 0, 4, 16, // 166 A6 ¦ (space)
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 176
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50, // 191 BF ? reverse
+
+ 10, 51, 20, 67, // 192 C0 Å• big
+ 0, 51, 10, 67, // 193 C1 á big
+ 20, 51, 30, 67, // 194 C2 â big
+ 40, 51, 50, 67, // 195 C3 ă big
+ 30, 51, 40, 67, // 196 C4 ä big
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 50, 51, 59, 67, // 199 C7 ç big
+ 67, 51, 74, 67, // 200 C8 Ä big
+ 59, 51, 66, 67, // 201 C9 é big
+ 75, 51, 82, 67, // 202 CA Ä™ big
+ 83, 51, 90, 67, // 203 CB ë big
+ 219,34, 225,50,
+ 91, 51, 95, 67, // 205 CD í big
+ 100,51, 103,67, // 206 CE î big
+ 104,51, 109,67, // 207 CF Ä big
+
+ 219,34, 225,50, // 208
+ 109,51, 117,67, // 209 D1 Å„ big
+ 219,34, 225,50,
+ 118,51, 127,67, // 211 D3 ó big
+ 138,51, 147,67, // 212 D4 ô big
+ 219,34, 225,50,
+ 148,51, 157,67, // 214 D6 ö big
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 177,51, 185,67, // 217 D9 ů big
+ 168,51, 176,67, // 218 DA ú big
+ 186,51, 194,67, // 219 DB ű big
+ 195,51, 203,67, // 220 DC ü big
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 211,51, 220,67, // 223 DF German SS
+
+ 8, 68, 15, 84, // 224 E0 Å• small
+ 0, 68, 7, 84, // 225 E1 á small
+ 16, 68, 23, 84, // 226 E2 â small
+ 32, 68, 39, 84, // 227 E3 ă small
+ 24, 68, 31, 84, // 228 E4 ä small
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 40, 68, 47, 84, // 231 E7 ç small
+ 55, 68, 62, 84, // 232 E8 Ä small
+ 47, 68, 54, 84, // 233 E9 é small
+ 63, 68, 70, 84, // 234 EA Ä™ small
+ 71, 68, 78, 84, // 235 EB ë small
+ 219,34, 225,50,
+ 79, 68, 83, 84, // 237 ED í small
+ 88, 68, 92, 84, // 238 EE î small
+ 92, 68, 97, 84, // 239 EF Ä small
+
+ 219,34, 225,50, // 240
+ 97, 68, 104,84, // 241 F1 Å„ small
+ 219,34, 225,50,
+ 105,68, 112,84, // 243 F3 ó small
+ 121,68, 128,84, // 244 F4 ô small
+ 219,34, 225,50,
+ 129,68, 136,84, // 246 F6 ö small
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 153,68, 160,84, // 249 F9 ů small
+ 145,68, 152,84, // 250 FA ú small
+ 161,68, 168,84, // 251 FB ű small
+ 169,68, 176,84, // 252 FC ü small
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+#endif
+#endif
+};
+
+
+static short table_text_courier[] =
+{
+// x1, y1, x2, y2
+ 231,137,239,153, // 0
+ 1,188, 9,204, // .
+ 51,188,59,204, // square
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 11,188,19,204, // \t
+ 21,188,29,204, // \n
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153, // \r
+ 231,137,239,153,
+ 231,137,239,153,
+ 41,188,49,204, // >
+ 31,188,39,204, // <
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+
+ 1, 86, 9,102, // 32
+ 11, 86, 19,102,
+ 21, 86, 29,102,
+ 31, 86, 39,102,
+ 41, 86, 49,102,
+ 51, 86, 59,102,
+ 61, 86, 69,102,
+ 71, 86, 79,102,
+ 81, 86, 89,102,
+ 91, 86, 99,102,
+ 101, 86,109,102,
+ 111, 86,119,102,
+ 121, 86,129,102,
+ 131, 86,139,102,
+ 141, 86,149,102,
+ 151, 86,159,102,
+ 161, 86,169,102,
+ 171, 86,179,102,
+ 181, 86,189,102,
+ 191, 86,199,102,
+ 201, 86,209,102,
+ 211, 86,219,102,
+ 221, 86,229,102,
+ 231, 86,239,102,
+ 1,103, 9,119, // 56
+ 11,103, 19,119,
+ 21,103, 29,119,
+ 31,103, 39,119,
+ 41,103, 49,119,
+ 51,103, 59,119,
+ 61,103, 69,119,
+ 71,103, 79,119,
+
+ 81,103, 89,119, // @
+ 91,103, 99,119,
+ 101,103,109,119,
+ 111,103,119,119,
+ 121,103,129,119,
+ 131,103,139,119,
+ 141,103,149,119,
+ 151,103,159,119,
+ 161,103,169,119,
+ 171,103,179,119,
+ 181,103,189,119,
+ 191,103,199,119,
+ 201,103,209,119,
+ 211,103,219,119,
+ 221,103,229,119,
+ 231,103,239,119,
+ 1,120, 9,136, // P
+ 11,120, 19,136,
+ 21,120, 29,136,
+ 31,120, 39,136,
+ 41,120, 49,136,
+ 51,120, 59,136,
+ 61,120, 69,136,
+ 71,120, 79,136,
+ 81,120, 89,136,
+ 91,120, 99,136,
+ 101,120,109,136,
+ 111,120,119,136, // [
+ 121,120,129,136,
+ 131,120,139,136,
+ 141,120,149,136,
+ 151,120,159,136, // _
+
+ 161,120,169,136,
+ 171,120,179,136, // a
+ 181,120,189,136,
+ 191,120,199,136,
+ 201,120,209,136,
+ 211,120,219,136,
+ 221,120,229,136,
+ 231,120,239,136,
+ 1,137, 9,153,
+ 11,137, 19,153,
+ 21,137, 29,153,
+ 31,137, 39,153,
+ 41,137, 49,153,
+ 51,137, 59,153,
+ 61,137, 69,153,
+ 71,137, 79,153, // o
+ 81,137, 89,153,
+ 91,137, 99,153,
+ 101,137,109,153,
+ 111,137,119,153,
+ 121,137,129,153,
+ 131,137,139,153,
+ 141,137,149,153,
+ 151,137,159,153,
+ 161,137,169,153,
+ 171,137,179,153,
+ 181,137,189,153,
+ 191,137,199,153,
+ 201,137,209,153,
+ 211,137,219,153,
+ 221,137,229,153, // ~
+ 231,137,239,153,
+
+#if _POLISH
+ 231,137,239,153, // 128
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 1,154, 9,170, // 140 S´
+ 231,137,239,153,
+ 231,137,239,153,
+ 11,154, 19,170, // 143 Z´
+
+ 231,137,239,153, // 144
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 1,171, 9,187, // 156 s´
+ 231,137,239,153,
+ 231,137,239,153,
+ 11,171, 19,187, // 159 z´
+
+ 231,137,239,153, // 160
+ 231,137,239,153,
+ 231,137,239,153,
+ 21,154, 29,170, // 163 L/
+ 231,137,239,153,
+ 31,154, 39,170, // 165 A,
+ 1, 86, 9,102, // 166 A6 ¦ (space)
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 41,154, 49,170, // 175 Zo
+
+ 231,137,239,153, // 176
+ 231,137,239,153,
+ 231,137,239,153,
+ 21,171, 29,187, // 179 l/
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 31,171, 39,187, // 185 a,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 41,171, 49,187, // 191 zo
+
+ 231,137,239,153, // 192
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 51,154, 59,170, // 198 C´
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 61,154, 69,170, // 202 E,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+
+ 231,137,239,153, // 208
+ 71,154, 79,170, // 209 N´
+ 231,137,239,153,
+ 81,171, 89,187, // 211 O´
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+
+ 231,137,239,153, // 224
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 51,171, 59,187, // 230 c´
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 61,171, 69,187, // 234 e,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+
+ 231,137,239,153, // 240
+ 71,171, 79,187, // 241 n´
+ 231,137,239,153,
+ 81,171, 89,187, // 243 ó small
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+#else
+ 231,137,239,153, // 128
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+
+ 231,137,239,153, // 144
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+
+ 231,137,239,153, // 160
+ 231,137,239,153, // 161 A1 ! reverse
+ 231,137,239,153,
+ 231,137,239,153, // 163 A3 Å
+ 231,137,239,153,
+ 231,137,239,153,
+ 1, 86, 9,102, // 166 A6 ¦ (space)
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+
+ 231,137,239,153, // 176
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153, // 191 BF ? reverse
+
+ 11,154, 19,170, // Å• big
+ 1,154, 9,170, // á big
+ 21,154, 29,170, // â big
+ 41,154, 49,170, // ă big
+ 31,154, 39,170, // ä big
+ 231,137,239,153,
+ 231,137,239,153,
+ 51,154, 59,170, // ç big
+ 71,154, 79,170, // Ä big
+ 61,154, 69,170, // é big
+ 81,154, 89,170, // Ä™ big
+ 91,154, 99,170, // ë big
+ 231,137,239,153,
+ 101,154,109,170, // í big
+ 121,154,129,170, // î big
+ 131,154,139,170, // Ä big
+ 231,137,239,153,
+ 141,154,149,170, // Å„ big
+ 231,137,239,153,
+ 151,154,159,170, // ó big
+ 171,154,179,170, // ô big
+ 231,137,239,153,
+ 181,154,189,170, // ö big
+ 231,137,239,153,
+ 231,137,239,153,
+ 211,154,219,170, // ů big
+ 201,154,209,170, // ú big
+ 221,154,229,170, // ű big
+ 231,154,239,170, // ü big
+ 231,137,239,153,
+ 231,137,239,153,
+ 241,154,249,170, // 223 DF German SS
+
+ 11,171, 19,187, // Å• small
+ 1,171, 9,187, // á small
+ 21,171, 29,187, // â small
+ 41,171, 49,187, // ă small
+ 31,171, 39,187, // ä small
+ 231,137,239,153,
+ 231,137,239,153,
+ 51,171, 59,187, // ç small
+ 71,171, 79,187, // Ä small
+ 61,171, 69,187, // é small
+ 81,171, 89,187, // Ä™ small
+ 91,171, 99,187, // ë small
+ 231,137,239,153,
+ 111,171,119,187, // Ä› small
+ 121,171,129,187, // î small
+ 131,171,139,187, // Ä small
+ 231,137,239,153,
+ 141,171,149,187, // Å„ small
+ 231,137,239,153,
+ 151,171,159,187, // ó small
+ 171,171,179,187, // ô small
+ 231,137,239,153,
+ 181,171,189,187, // ö small
+ 231,137,239,153,
+ 231,137,239,153,
+ 211,171,219,187, // ů small
+ 201,171,209,187, // ú small
+ 221,171,229,187, // ű small
+ 231,171,239,187, // ü small
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+#endif
+};
+
+
+// Returns the pointer to the table by the font.
+
+short* RetTable(FontType font)
+{
+ if ( font == FONT_COLOBOT ) return table_text_colobot;
+ else return table_text_courier;
+}
+
+
+
+// Object's constructor.
+
+CText::CText(CInstanceManager* iMan, CD3DEngine* engine)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_TEXT, this);
+
+ m_pD3DDevice = 0;
+ m_engine = engine;
+}
+
+// Object's destructor.
+
+CText::~CText()
+{
+ m_iMan->DeleteInstance(CLASS_TEXT, this);
+}
+
+
+void CText::SetD3DDevice(LPDIRECT3DDEVICE7 device)
+{
+ m_pD3DDevice = device;
+}
+
+
+// Displays multi-font text.
+// The vertical position is at the bottom of the box of the character.
+
+void CText::DrawText(char *string, char *format, int len, Math::Point pos,
+ float width, int justif, float size, float stretch,
+ int eol)
+{
+ float sw;
+
+ if ( justif == 0 ) // center?
+ {
+ sw = RetStringWidth(string, format, len, size, stretch);
+ if ( sw > width ) sw = width;
+ pos.x -= sw/2.0f;
+ }
+ if ( justif < 0 ) // flag was left?
+ {
+ sw = RetStringWidth(string, format, len, size, stretch);
+ if ( sw > width ) sw = width;
+ pos.x -= sw;
+ }
+ DrawString(string, format, len, pos, width, size, stretch, eol);
+}
+
+// Displays multi-font text.
+// The vertical position is at the bottom of the box of the character.
+
+void CText::DrawText(char *string, char *format, Math::Point pos, float width,
+ int justif, float size, float stretch,
+ int eol)
+{
+ DrawText(string, format, strlen(string), pos, width, justif, size, stretch, eol);
+}
+
+// Displays text.
+// The vertical position is at the bottom of the box of the character.
+
+void CText::DrawText(char *string, int len, Math::Point pos, float width,
+ int justif, float size, float stretch, FontType font,
+ int eol)
+{
+ float sw;
+
+ if ( justif == 0 ) // center?
+ {
+ sw = RetStringWidth(string, len, size, stretch, font);
+ if ( sw > width ) sw = width;
+ pos.x -= sw/2.0f;
+ }
+ if ( justif < 0 ) // flag was left?
+ {
+ sw = RetStringWidth(string, len, size, stretch, font);
+ if ( sw > width ) sw = width;
+ pos.x -= sw;
+ }
+ DrawString(string, len, pos, width, size, stretch, font, eol);
+}
+
+// Displays text.
+// The vertical position is at the bottom of the box of the character.
+
+void CText::DrawText(char *string, Math::Point pos, float width,
+ int justif, float size, float stretch, FontType font,
+ int eol)
+{
+ DrawText(string, strlen(string), pos, width, justif, size, stretch, font, eol);
+}
+
+
+// Returns the size of a multi-font text.
+
+void CText::DimText(char *string, char *format, int len, Math::Point pos,
+ int justif, float size, float stretch,
+ Math::Point &start, Math::Point &end)
+{
+ float sw;
+
+ start = end = pos;
+
+ sw = RetStringWidth(string, format, len, size, stretch);
+ end.x += sw;
+ if ( justif == 0 ) // center?
+ {
+ start.x -= sw/2.0f;
+ end.x -= sw/2.0f;
+ }
+ if ( justif < 0 ) // flag was left?
+ {
+ start.x -= sw;
+ end.x -= sw;
+ }
+
+ start.y -= RetDescent(size, FONT_COLOBOT);
+ end.y += RetAscent(size, FONT_COLOBOT);
+}
+
+// Returns the size of a multi-font text.
+
+void CText::DimText(char *string, char *format, Math::Point pos, int justif,
+ float size, float stretch,
+ Math::Point &start, Math::Point &end)
+{
+ DimText(string, format, strlen(string), pos, justif, size, stretch, start, end);
+}
+
+// Returns the size of a text.
+
+void CText::DimText(char *string, int len, Math::Point pos, int justif,
+ float size, float stretch, FontType font,
+ Math::Point &start, Math::Point &end)
+{
+ float sw;
+
+ start = end = pos;
+
+ sw = RetStringWidth(string, len, size, stretch, font);
+ end.x += sw;
+ if ( justif == 0 ) // center?
+ {
+ start.x -= sw/2.0f;
+ end.x -= sw/2.0f;
+ }
+ if ( justif < 0 ) // flag was left?
+ {
+ start.x -= sw;
+ end.x -= sw;
+ }
+
+ start.y -= RetDescent(size, font);
+ end.y += RetAscent(size, font);
+}
+
+// Returns the size of a text.
+
+void CText::DimText(char *string, Math::Point pos, int justif,
+ float size, float stretch, FontType font,
+ Math::Point &start, Math::Point &end)
+{
+ DimText(string, strlen(string), pos, justif, size, stretch, font, start, end);
+}
+
+
+// Returns the height above the baseline.
+
+float CText::RetAscent(float size, FontType font)
+{
+ return (13.0f/256.0f)*(size/20.0f);
+}
+
+// Returns the height below the baseline.
+
+float CText::RetDescent(float size, FontType font)
+{
+ return (3.0f/256.0f)*(size/20.0f);
+}
+
+// Returns the total height of the character.
+
+float CText::RetHeight(float size, FontType font)
+{
+ return (16.0f/256.0f)*(size/20.0f);
+}
+
+
+// Returns the width of a string of multi-font characters.
+
+float CText::RetStringWidth(char *string, char *format, int len,
+ float size, float stretch)
+{
+ FontType font;
+ float st, tab, w, width = 0.0f;
+ short *table, *pt;
+ int i, c;
+
+ for ( i=0 ; i<len ; i++ )
+ {
+ font = (FontType)(format[i]&FONT_MASK);
+ if ( font == FONT_BUTTON )
+ {
+ width += (12.0f/256.0f)*(size/20.0f);
+ }
+ else
+ {
+ table = RetTable(font);
+ c = (unsigned char)string[i];
+
+ if ( c == '\t' )
+ {
+ pt = table+' '*4;
+ tab = (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*stretch*m_engine->RetEditIndentValue();
+ w = tab-Math::Mod(width, tab);
+ if ( w < tab*0.1f ) w += tab;
+ width += w;
+ continue;
+ }
+
+ if ( c > 255 ) continue;
+
+ pt = table+c*4;
+ st = stretch;
+ if ( font == FONT_COLOBOT && (c == 'O' || c == 'o') ) st = 0.8f;
+ width += (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*st;
+ }
+ }
+
+ return width;
+}
+
+// Returns the width of a string of characters.
+
+float CText::RetStringWidth(char *string, int len,
+ float size, float stretch, FontType font)
+{
+ float st, tab, w, width = 0.0f;
+ short *table, *pt;
+ int i, c;
+
+ table = RetTable(font);
+ for ( i=0 ; i<len ; i++ )
+ {
+ c = (unsigned char)string[i];
+
+ if ( c == '\t' )
+ {
+ pt = table+' '*4;
+ tab = (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*stretch*m_engine->RetEditIndentValue();
+ w = tab-Math::Mod(width, tab);
+ if ( w < tab*0.1f ) w += tab;
+ width += w;
+ continue;
+ }
+
+ if ( c > 255 ) continue;
+
+ pt = table+c*4;
+ st = stretch;
+ if ( font == FONT_COLOBOT && (c == 'O' || c == 'o') ) st = 0.8f;
+ width += (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*st;
+ }
+
+ return width;
+}
+
+// Returns the width of a character.
+// 'offset' is the current position in the line.
+
+float CText::RetCharWidth(int character, float offset,
+ float size, float stretch, FontType font)
+{
+ float st, tab, w;
+ short* pt;
+
+ if ( font == FONT_BUTTON ) return (12.0f/256.0f)*(size/20.0f);
+
+ if ( character == '\t' )
+ {
+ pt = RetTable(font)+' '*4;
+ tab = (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*stretch*m_engine->RetEditIndentValue();
+ w = tab-Math::Mod(offset, tab);
+ if ( w < tab*0.1f ) w += tab;
+ return w;
+ }
+
+ if ( character > 255 ) return 0.0f;
+
+ pt = RetTable(font)+character*4;
+ st = stretch;
+#if !_NEWLOOK
+ if ( font == FONT_COLOBOT && (character == 'O' || character == 'o') ) st = 0.8f;
+#endif
+ return (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*st;
+}
+
+
+// Justifies a line of multi-font text. Returns the offset of the cut.
+
+int CText::Justif(char *string, char *format, int len, float width,
+ float size, float stretch)
+{
+ FontType font;
+ float pos;
+ int i, character, cut;
+
+ pos = 0.0f;
+ cut = 0;
+ for ( i=0 ; i<len ; i++ )
+ {
+ font = (FontType)(format[i]&FONT_MASK);
+ character = (unsigned char)string[i];
+
+ if ( character == 0 )
+ {
+ return i;
+ }
+ if ( font != FONT_BUTTON )
+ {
+ if ( character == '\n' )
+ {
+ return i+1;
+ }
+ if ( character == ' ' )
+ {
+ cut = i+1;
+ }
+ }
+
+ pos += RetCharWidth(character, pos, size, stretch, font);
+ if ( pos > width )
+ {
+ if ( cut == 0 ) return i;
+ else return cut;
+ }
+ }
+ return i;
+}
+
+// Justify a line of text. Returns the offset of the cut.
+
+int CText::Justif(char *string, int len, float width,
+ float size, float stretch, FontType font)
+{
+ float pos;
+ int i, character, cut;
+
+ pos = 0.0f;
+ cut = 0;
+ for ( i=0 ; i<len ; i++ )
+ {
+ character = (unsigned char)string[i];
+
+ if ( character == 0 )
+ {
+ return i;
+ }
+ if ( character == '\n' )
+ {
+ return i+1;
+ }
+ if ( character == ' ' )
+ {
+ cut = i+1;
+ }
+
+ pos += RetCharWidth(character, pos, size, stretch, font);
+ if ( pos > width )
+ {
+ if ( cut == 0 ) return i;
+ else return cut;
+ }
+ }
+ return i;
+}
+
+// Returns the most suitable position to a given offset (multi-font).
+
+int CText::Detect(char *string, char *format, int len, float offset,
+ float size, float stretch)
+{
+ FontType font;
+ float pos, width;
+ int i, character, cut;
+
+ pos = 0.0f;
+ cut = 0;
+ for ( i=0 ; i<len ; i++ )
+ {
+ font = (FontType)(format[i]&FONT_MASK);
+ character = (unsigned char)string[i];
+
+ if ( character == 0 )
+ {
+ return i;
+ }
+ if ( font != FONT_BUTTON )
+ {
+ if ( character == '\n' )
+ {
+ return i;
+ }
+ }
+
+ width = RetCharWidth(character, pos, size, stretch, font);
+ if ( offset <= pos+width/2.0f )
+ {
+ return i;
+ }
+ pos += width;
+ }
+ return i;
+}
+
+// Returns the most suitable position to a given offset (multi-font).
+
+int CText::Detect(char *string, int len, float offset,
+ float size, float stretch, FontType font)
+{
+ float pos, width;
+ int i, character, cut;
+
+ pos = 0.0f;
+ cut = 0;
+ for ( i=0 ; i<len ; i++ )
+ {
+ character = (unsigned char)string[i];
+
+ if ( character == 0 ||
+ character == '\n' )
+ {
+ return i;
+ }
+
+ width = RetCharWidth(character, pos, size, stretch, font);
+ if ( offset <= pos+width/2.0f )
+ {
+ return i;
+ }
+ pos += width;
+ }
+ return i;
+}
+
+
+// Displays multi-font text.
+
+void CText::DrawString(char *string, char *format, int len, Math::Point pos,
+ float width, float size, float stretch, int eol)
+{
+ FontType font;
+ float start, offset, cw;
+ int i, c;
+
+#if _POLISH
+ m_engine->SetTexture("textp.tga");
+#else
+ m_engine->SetTexture("text.tga");
+#endif
+ m_engine->SetState(D3DSTATETTw);
+
+ font = FONT_COLOBOT;
+
+ start = pos.x;
+ offset = 0.0f;
+ for ( i=0 ; i<len ; i++ )
+ {
+ font = (FontType)(format[i]&FONT_MASK);
+ c = (unsigned char)string[i];
+ cw = RetCharWidth(c, offset, size, stretch, font);
+
+ if ( offset+cw > width ) // exceeds the maximum width?
+ {
+ cw = RetCharWidth(16, offset, size, stretch, font);
+ pos.x = start+width-cw;
+ DrawChar(16, pos, size, stretch, font); // >
+ break;
+ }
+
+ if ( (format[i]&COLOR_MASK) != 0 )
+ {
+ DrawColor(pos, size, cw, format[i]&COLOR_MASK);
+ }
+ DrawChar(c, pos, size, stretch, font);
+ offset += cw;
+ pos.x += cw;
+ }
+
+ if ( eol != 0 )
+ {
+ DrawChar(eol, pos, size, stretch, font);
+ }
+}
+
+// Displays text.
+
+void CText::DrawString(char *string, int len, Math::Point pos, float width,
+ float size, float stretch, FontType font,
+ int eol)
+{
+ float start, offset, cw;
+ int i, c;
+
+#if _POLISH
+ m_engine->SetTexture("textp.tga");
+#else
+ m_engine->SetTexture("text.tga");
+#endif
+ m_engine->SetState(D3DSTATETTw);
+
+ start = pos.x;
+ offset = 0.0f;
+ for ( i=0 ; i<len ; i++ )
+ {
+ c = (unsigned char)string[i];
+ cw = RetCharWidth(c, offset, size, stretch, font);
+
+ if ( offset+cw > width ) // exceeds the maximum width?
+ {
+ cw = RetCharWidth(16, offset, size, stretch, font);
+ pos.x = start+width-cw;
+ DrawChar(16, pos, size, stretch, font); // >
+ break;
+ }
+
+ DrawChar(c, pos, size, stretch, font);
+ offset += cw;
+ pos.x += cw;
+ }
+
+ if ( eol != 0 )
+ {
+ DrawChar(eol, pos, size, stretch, font);
+ }
+}
+
+// Displays the link to a character.
+
+void CText::DrawColor(Math::Point pos, float size, float width, int color)
+{
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Point p1, p2;
+ POINT dim;
+ Math::Vector n;
+ float h, u1, u2, v1, v2, dp;
+ int icon;
+
+ icon = -1;
+ if ( color == COLOR_LINK ) icon = 9; // blue
+ if ( color == COLOR_TOKEN ) icon = 4; // orange
+ if ( color == COLOR_TYPE ) icon = 5; // green
+ if ( color == COLOR_CONST ) icon = 8; // red
+ if ( color == COLOR_REM ) icon = 6; // magenta
+ if ( color == COLOR_KEY ) icon = 10; // gray
+ if ( icon == -1 ) return;
+
+ if ( color == COLOR_LINK )
+ {
+ m_engine->SetState(D3DSTATENORMAL);
+ }
+
+ dim = m_engine->RetDim();
+ if ( dim.y <= 768.0f ) // 1024x768 or less?
+ {
+ h = 1.01f/dim.y; // 1 pixel
+ }
+ else // more than 1024x768?
+ {
+ h = 2.0f/dim.y; // 2 pixels
+ }
+
+ p1.x = pos.x;
+ p2.x = pos.x + width;
+
+ if ( color == COLOR_LINK )
+ {
+ p1.y = pos.y;
+ p2.y = pos.y + h; // just emphasized
+ }
+ else
+ {
+#if 1
+ p1.y = pos.y;
+ p2.y = pos.y + (16.0f/256.0f)*(size/20.0f);
+//? p2.y = pos.y + h*4.0f; // just emphasized thick
+#else
+ p1.y = pos.y;
+ p2.y = pos.y + (16.0f/256.0f)*(size/20.0f)/4.0f;
+#endif
+ }
+
+ u1 = (16.0f/256.0f)*(icon%16);
+ v1 = (240.0f/256.0f);
+ u2 = (16.0f/256.0f)+u1;
+ v2 = (16.0f/256.0f)+v1;
+
+ dp = 0.5f/256.0f;
+ u1 += dp;
+ v1 += dp;
+ u2 -= dp;
+ v2 -= dp;
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+
+ if ( color == COLOR_LINK )
+ {
+ m_engine->SetState(D3DSTATETTw);
+ }
+}
+
+// Displays a character.
+
+void CText::DrawChar(int character, Math::Point pos, float size,
+ float stretch, FontType font)
+{
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Point p1, p2;
+ Math::Vector n;
+ float width, height, u1, u2, v1, v2, dp;
+ short* pt;
+
+ dp = 0.5f/256.0f;
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+
+ if ( font == FONT_BUTTON )
+ {
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+
+ p1.x = pos.x;
+ p1.y = pos.y;
+ p2.x = pos.x + (12.0f/256.0f)*(size/20.0f);
+ p2.y = pos.y + (16.0f/256.0f)*(size/20.0f);
+
+ if ( character <= 64 || character >= 128+56 )
+ {
+ u1 = 66.0f/256.0f;
+ v1 = 2.0f/256.0f;
+ u2 = 94.0f/256.0f;
+ v2 = 30.0f/256.0f;
+ }
+ else
+ {
+ u1 = 224.0f/256.0f;
+ v1 = 32.0f/256.0f;
+ u2 = 256.0f/256.0f;
+ v2 = 64.0f/256.0f;
+ }
+
+ u1 += dp;
+ v1 += dp;
+ u2 -= dp;
+ v2 -= dp;
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+
+//? p1.x += (12.0f/256.0f)*(size/20.0f)*0.1f;
+//? p1.y += (16.0f/256.0f)*(size/20.0f)*0.1f;
+//? p2.x -= (12.0f/256.0f)*(size/20.0f)*0.1f;
+//? p2.y -= (16.0f/256.0f)*(size/20.0f)*0.1f;
+
+ if ( character >= 64 && character < 64+64 )
+ {
+ character -= 64;
+ m_engine->SetTexture("button2.tga");
+ }
+ if ( character >= 128 && character < 128+64 )
+ {
+ character -= 128;
+ m_engine->SetTexture("button3.tga");
+ }
+
+ m_engine->SetState(D3DSTATETTw);
+
+ u1 = (32.0f/256.0f)*(character%8);
+ v1 = (32.0f/256.0f)*(character/8); // uv texture
+ u2 = (32.0f/256.0f)+u1;
+ v2 = (32.0f/256.0f)+v1;
+
+ u1 += dp;
+ v1 += dp;
+ u2 -= dp;
+ v2 -= dp;
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+
+
+#if _POLISH
+ m_engine->SetTexture("textp.tga");
+#else
+ m_engine->SetTexture("text.tga");
+#endif
+ return;
+ }
+
+ if ( character > 255 ) return;
+
+//? if ( character == '\t' ) character = ' '; // if tab, does not display ->
+
+#if !_NEWLOOK
+ if ( font == FONT_COLOBOT && (character == 'O' || character == 'o') )
+ {
+ stretch = 0.8f;
+ }
+#endif
+ if ( font == FONT_COURIER )
+ {
+ stretch *= 1.2f;
+ }
+
+ pt = RetTable(font)+character*4;
+ width = (float)(pt[2]-pt[0])/256.0f*stretch*0.9f;
+//? width = (float)(pt[2]-pt[0])/256.0f*stretch;
+ height = (float)(pt[3]-pt[1])/256.0f;
+
+#if _NEWLOOK
+ pos.y += height*(size/20.0f)/17.0f;
+#endif
+ p1.x = pos.x;
+ p1.y = pos.y;
+ p2.x = pos.x + width*(size/20.0f);
+ p2.y = pos.y + height*(size/20.0f);
+
+ u1 = (float)pt[0]/256.0f;
+ v1 = (float)pt[1]/256.0f;
+ u2 = (float)pt[2]/256.0f;
+ v2 = (float)pt[3]/256.0f;
+
+ if ( font == FONT_COLOBOT )
+ {
+ u1 += dp;
+ u2 += dp;
+#if _NEWLOOK
+ v2 += dp;
+#endif
+ }
+ if ( font == FONT_COURIER )
+ {
+ u1 -= dp;
+ u2 += dp*2.0f;
+ }
+
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+}
+
diff --git a/src/old/text.h b/src/old/text.h
index 6ba30a3..3b2fd90 100644
--- a/src/old/text.h
+++ b/src/old/text.h
@@ -1,111 +1,111 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// text.h
-
-#pragma once
-
-
-#include "math/point.h"
-#include "old/d3dengine.h"
-
-
-class CInstanceManager;
-
-
-
-const float SMALLFONT = 10.0f;
-const float BIGFONT = 15.0f;
-
-const float NORMSTRETCH = 0.8f;
-
-
-
-enum FontType
-{
- FONT_COLOBOT = 0,
- FONT_COURIER = 1,
- FONT_BUTTON = 2,
-};
-
-enum FontTitle
-{
- TITLE_BIG = 0x04,
- TITLE_NORM = 0x08,
- TITLE_LITTLE = 0x0c,
-};
-
-enum FontColor
-{
- COLOR_LINK = 0x10,
- COLOR_TOKEN = 0x20,
- COLOR_TYPE = 0x30,
- COLOR_CONST = 0x40,
- COLOR_REM = 0x50,
- COLOR_KEY = 0x60,
- COLOR_TABLE = 0x70,
-};
-
-const int FONT_MASK = 0x03;
-const int TITLE_MASK = 0x0c;
-const int COLOR_MASK = 0x70;
-const int IMAGE_MASK = 0x80;
-
-
-
-class CText
-{
-public:
- CText(CInstanceManager *iMan, CD3DEngine* engine);
- ~CText();
-
- void SetD3DDevice(LPDIRECT3DDEVICE7 device);
-
- void DrawText(char *string, char *format, int len, Math::Point pos, float width, int justif, float size, float stretch, int eol);
- void DrawText(char *string, char *format, Math::Point pos, float width, int justif, float size, float stretch, int eol);
- void DrawText(char *string, int len, Math::Point pos, float width, int justif, float size, float stretch, FontType font, int eol);
- void DrawText(char *string, Math::Point pos, float width, int justif, float size, float stretch, FontType font, int eol);
- void DimText(char *string, char *format, int len, Math::Point pos, int justif, float size, float stretch, Math::Point &start, Math::Point &end);
- void DimText(char *string, char *format, Math::Point pos, int justif, float size, float stretch, Math::Point &start, Math::Point &end);
- void DimText(char *string, int len, Math::Point pos, int justif, float size, float stretch, FontType font, Math::Point &start, Math::Point &end);
- void DimText(char *string, Math::Point pos, int justif, float size, float stretch, FontType font, Math::Point &start, Math::Point &end);
-
- float RetAscent(float size, FontType font);
- float RetDescent(float size, FontType font);
- float RetHeight(float size, FontType font);
-
- float RetStringWidth(char *string, char *format, int len, float size, float stretch);
- float RetStringWidth(char *string, int len, float size, float stretch, FontType font);
- float RetCharWidth(int character, float offset, float size, float stretch, FontType font);
-
- int Justif(char *string, char *format, int len, float width, float size, float stretch);
- int Justif(char *string, int len, float width, float size, float stretch, FontType font);
- int Detect(char *string, char *format, int len, float offset, float size, float stretch);
- int Detect(char *string, int len, float offset, float size, float stretch, FontType font);
-
-protected:
- void DrawString(char *string, char *format, int len, Math::Point pos, float width, float size, float stretch, int eol);
- void DrawString(char *string, int len, Math::Point pos, float width, float size, float stretch, FontType font, int eol);
- void DrawColor(Math::Point pos, float size, float width, int color);
- void DrawChar(int character, Math::Point pos, float size, float stretch, FontType font);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- LPDIRECT3DDEVICE7 m_pD3DDevice;
-
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// text.h
+
+#pragma once
+
+
+#include "math/point.h"
+#include "old/d3dengine.h"
+
+
+class CInstanceManager;
+
+
+
+const float SMALLFONT = 10.0f;
+const float BIGFONT = 15.0f;
+
+const float NORMSTRETCH = 0.8f;
+
+
+
+enum FontType
+{
+ FONT_COLOBOT = 0,
+ FONT_COURIER = 1,
+ FONT_BUTTON = 2,
+};
+
+enum FontTitle
+{
+ TITLE_BIG = 0x04,
+ TITLE_NORM = 0x08,
+ TITLE_LITTLE = 0x0c,
+};
+
+enum FontColor
+{
+ COLOR_LINK = 0x10,
+ COLOR_TOKEN = 0x20,
+ COLOR_TYPE = 0x30,
+ COLOR_CONST = 0x40,
+ COLOR_REM = 0x50,
+ COLOR_KEY = 0x60,
+ COLOR_TABLE = 0x70,
+};
+
+const int FONT_MASK = 0x03;
+const int TITLE_MASK = 0x0c;
+const int COLOR_MASK = 0x70;
+const int IMAGE_MASK = 0x80;
+
+
+
+class CText
+{
+public:
+ CText(CInstanceManager *iMan, CD3DEngine* engine);
+ ~CText();
+
+ void SetD3DDevice(LPDIRECT3DDEVICE7 device);
+
+ void DrawText(char *string, char *format, int len, Math::Point pos, float width, int justif, float size, float stretch, int eol);
+ void DrawText(char *string, char *format, Math::Point pos, float width, int justif, float size, float stretch, int eol);
+ void DrawText(char *string, int len, Math::Point pos, float width, int justif, float size, float stretch, FontType font, int eol);
+ void DrawText(char *string, Math::Point pos, float width, int justif, float size, float stretch, FontType font, int eol);
+ void DimText(char *string, char *format, int len, Math::Point pos, int justif, float size, float stretch, Math::Point &start, Math::Point &end);
+ void DimText(char *string, char *format, Math::Point pos, int justif, float size, float stretch, Math::Point &start, Math::Point &end);
+ void DimText(char *string, int len, Math::Point pos, int justif, float size, float stretch, FontType font, Math::Point &start, Math::Point &end);
+ void DimText(char *string, Math::Point pos, int justif, float size, float stretch, FontType font, Math::Point &start, Math::Point &end);
+
+ float RetAscent(float size, FontType font);
+ float RetDescent(float size, FontType font);
+ float RetHeight(float size, FontType font);
+
+ float RetStringWidth(char *string, char *format, int len, float size, float stretch);
+ float RetStringWidth(char *string, int len, float size, float stretch, FontType font);
+ float RetCharWidth(int character, float offset, float size, float stretch, FontType font);
+
+ int Justif(char *string, char *format, int len, float width, float size, float stretch);
+ int Justif(char *string, int len, float width, float size, float stretch, FontType font);
+ int Detect(char *string, char *format, int len, float offset, float size, float stretch);
+ int Detect(char *string, int len, float offset, float size, float stretch, FontType font);
+
+protected:
+ void DrawString(char *string, char *format, int len, Math::Point pos, float width, float size, float stretch, int eol);
+ void DrawString(char *string, int len, Math::Point pos, float width, float size, float stretch, FontType font, int eol);
+ void DrawColor(Math::Point pos, float size, float width, int color);
+ void DrawChar(int character, Math::Point pos, float size, float stretch, FontType font);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ LPDIRECT3DDEVICE7 m_pD3DDevice;
+
+};
+
diff --git a/src/old/water.cpp b/src/old/water.cpp
index 215bac9..dfde09e 100644
--- a/src/old/water.cpp
+++ b/src/old/water.cpp
@@ -1,844 +1,844 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// water.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/geometry.h"
-#include "math/conv.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "old/d3dutil.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "object/object.h"
-#include "old/sound.h"
-#include "old/water.h"
-
-
-
-
-// Constructor of the terrain.
-
-CWater::CWater(CInstanceManager* iMan, CD3DEngine* engine)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_WATER, this);
-
- m_engine = engine;
- m_terrain = 0;
- m_particule = 0;
- m_sound = 0;
-
- m_type[0] = WATER_NULL;
- m_type[1] = WATER_NULL;
- m_level = 0.0f;
- m_bDraw = true;
- m_bLava = false;
- m_color = 0xffffffff;
- m_subdiv = 4;
- m_filename[0] = 0;
-}
-
-// Destructor of the terrain.
-
-CWater::~CWater()
-{
-}
-
-
-bool CWater::EventProcess(const Event &event)
-{
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
-#if 0
- if ( event.param == 'S' )
- {
- if ( m_subdiv == 1 ) m_subdiv = 2;
- else if ( m_subdiv == 2 ) m_subdiv = 4;
- else if ( m_subdiv == 4 ) m_subdiv = 8;
- else if ( m_subdiv == 8 ) m_subdiv = 1;
- SetLevel(m_level);
- }
- if ( event.param == 'M' )
- {
- SetLevel(m_level+1.0f);
- }
- if ( event.param == 'D' )
- {
- SetLevel(m_level-1.0f);
- }
- if ( event.param == 'H' )
- {
- m_bDraw = !m_bDraw;
- }
- if ( event.param == 'C' )
- {
- if ( m_color == 0xffffffff ) m_color = 0xcccccccc;
- else if ( m_color == 0xcccccccc ) m_color = 0x88888888;
- else if ( m_color == 0x88888888 ) m_color = 0x44444444;
- else if ( m_color == 0x44444444 ) m_color = 0x00000000;
- else if ( m_color == 0x00000000 ) m_color = 0xffffffff;
- }
- if ( event.param == 'Q' )
- {
- int i;
- i = (m_color>>24);
- i += 0x44;
- i &= 0xff;
- i = (i<<24);
- m_color &= 0x00ffffff;
- m_color |= i;
- }
- if ( event.param == 'W' )
- {
- int i;
- i = (m_color>>16);
- i += 0x44;
- i &= 0xff;
- i = (i<<16);
- m_color &= 0xff00ffff;
- m_color |= i;
- }
- if ( event.param == 'E' )
- {
- int i;
- i = (m_color>>8);
- i += 0x44;
- i &= 0xff;
- i = (i<<8);
- m_color &= 0xffff00ff;
- m_color |= i;
- }
- if ( event.param == 'R' )
- {
- int i;
- i = m_color;
- i += 0x44;
- i &= 0xff;
- m_color &= 0xffffff00;
- m_color |= i;
- }
-#endif
- }
- return true;
-}
-
-// Makes water evolve.
-
-bool CWater::EventFrame(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
-
- m_time += event.rTime;
-
- if ( m_type[0] == WATER_NULL ) return true;
-
- if ( m_bLava )
- {
- LavaFrame(event.rTime);
- }
- return true;
-}
-
-// Makes evolve the steam jets on the lava.
-
-void CWater::LavaFrame(float rTime)
-{
- Math::Vector eye, lookat, dir, perp, pos;
- float distance, shift, level;
- int i;
-
- if ( m_particule == 0 )
- {
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- }
-
- for ( i=0 ; i<MAXWATVAPOR ; i++ )
- {
- VaporFrame(i, rTime);
- }
-
- if ( m_time-m_lastLava >= 0.1f )
- {
- eye = m_engine->RetEyePt();
- lookat = m_engine->RetLookatPt();
-
- distance = Math::Rand()*200.0f;
- shift = (Math::Rand()-0.5f)*200.0f;
-
- dir = Normalize(lookat-eye);
- pos = eye + dir*distance;
-
- perp.x = -dir.z;
- perp.y = dir.y;
- perp.z = dir.x;
- pos = pos + perp*shift;
-
- level = m_terrain->RetFloorLevel(pos, true);
- if ( level < m_level )
- {
- pos.y = m_level;
-
- level = Math::Rand();
- if ( level < 0.8f )
- {
- if ( VaporCreate(PARTIFIRE, pos, 0.02f+Math::Rand()*0.06f) )
- {
- m_lastLava = m_time;
- }
- }
- else if ( level < 0.9f )
- {
- if ( VaporCreate(PARTIFLAME, pos, 0.5f+Math::Rand()*3.0f) )
- {
- m_lastLava = m_time;
- }
- }
- else
- {
- if ( VaporCreate(PARTIVAPOR, pos, 0.2f+Math::Rand()*2.0f) )
- {
- m_lastLava = m_time;
- }
- }
- }
- }
-}
-
-// Removes all the steam jets.
-
-void CWater::VaporFlush()
-{
- int i;
-
- for ( i=0 ; i<MAXWATVAPOR ; i++ )
- {
- m_vapor[i].bUsed = false;
- }
-}
-
-// Creates a new steam.
-
-bool CWater::VaporCreate(ParticuleType type, Math::Vector pos, float delay)
-{
- int i;
-
- for ( i=0 ; i<MAXWATVAPOR ; i++ )
- {
- if ( !m_vapor[i].bUsed )
- {
- m_vapor[i].bUsed = true;
- m_vapor[i].type = type;
- m_vapor[i].pos = pos;
- m_vapor[i].delay = delay;
- m_vapor[i].time = 0.0f;
- m_vapor[i].last = 0.0f;
-
- if ( m_vapor[i].type == PARTIFIRE )
- {
- m_sound->Play(SOUND_BLUP, pos, 1.0f, 1.0f-Math::Rand()*0.5f);
- }
- if ( m_vapor[i].type == PARTIFLAME )
- {
-//? m_sound->Play(SOUND_SWIM, pos, 1.0f, 1.0f-Math::Rand()*0.5f);
- }
- if ( m_vapor[i].type == PARTIVAPOR )
- {
- m_sound->Play(SOUND_PSHHH, pos, 0.3f, 2.0f);
- }
-
- return true;
- }
- }
- return false;
-}
-
-// Makes evolve a steam jet,
-
-void CWater::VaporFrame(int i, float rTime)
-{
- Math::Vector pos, speed;
- Math::Point dim;
- int j;
-
- m_vapor[i].time += rTime;
-
- if ( m_sound == 0 )
- {
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- }
-
- if ( m_vapor[i].time <= m_vapor[i].delay )
- {
- if ( m_time-m_vapor[i].last >= m_engine->ParticuleAdapt(0.02f) )
- {
- m_vapor[i].last = m_time;
-
- if ( m_vapor[i].type == PARTIFIRE )
- {
- for ( j=0 ; j<10 ; j++ )
- {
- pos = m_vapor[i].pos;
- pos.x += (Math::Rand()-0.5f)*2.0f;
- pos.z += (Math::Rand()-0.5f)*2.0f;
- pos.y -= 1.0f;
- speed.x = (Math::Rand()-0.5f)*6.0f;
- speed.z = (Math::Rand()-0.5f)*6.0f;
- speed.y = 8.0f+Math::Rand()*5.0f;
- dim.x = Math::Rand()*1.5f+1.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 2.0f, 10.0f);
- }
- }
- else if ( m_vapor[i].type == PARTIFLAME )
- {
- pos = m_vapor[i].pos;
- pos.x += (Math::Rand()-0.5f)*8.0f;
- pos.z += (Math::Rand()-0.5f)*8.0f;
- pos.y -= 2.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = 4.0f+Math::Rand()*4.0f;
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFLAME);
- }
- else
- {
- pos = m_vapor[i].pos;
- pos.x += (Math::Rand()-0.5f)*4.0f;
- pos.z += (Math::Rand()-0.5f)*4.0f;
- pos.y -= 2.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = 8.0f+Math::Rand()*8.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIVAPOR);
- }
- }
- }
- else
- {
- m_vapor[i].bUsed = false;
- }
-}
-
-
-// Adjusts the position to normal, to imitate reflections on an expanse of water at rest.
-
-void CWater::AdjustLevel(Math::Vector &pos, Math::Vector &norm,
- Math::Point &uv1, Math::Point &uv2)
-{
-#if 0
- float t1, t2;
-
- uv1.x = (pos.x+10000.0f)/40.0f;
- uv1.y = (pos.z+10000.0f)/40.0f;
-
- t1 = m_time*1.5f + pos.x*0.1f * pos.z*0.2f;
- pos.y += sinf(t1)*m_eddy.y;
-
- t1 = m_time*0.6f + pos.x*0.1f * pos.z*0.2f;
- t2 = m_time*0.7f + pos.x*0.3f * pos.z*0.4f;
- pos.x += sinf(t1)*m_eddy.x;
- pos.z += sinf(t2)*m_eddy.z;
-
-//? uv2.x = (pos.x+10000.0f)/40.0f+0.3f;
-//? uv2.y = (pos.z+10000.0f)/40.0f+0.4f;
- uv2.x = (pos.x+10000.0f)/20.0f;
- uv2.y = (pos.z+10000.0f)/20.0f;
-
- t1 = m_time*0.7f + pos.x*5.5f + pos.z*5.6f;
- t2 = m_time*0.8f + pos.x*5.7f + pos.z*5.8f;
- norm = Math::Vector(sinf(t1)*m_glint, 1.0f, sinf(t2)*m_glint);
-#else
- float t1, t2;
-
- t1 = m_time*1.5f + pos.x*0.1f * pos.z*0.2f;
- pos.y += sinf(t1)*m_eddy.y;
-
- t1 = m_time*1.5f;
- uv1.x = (pos.x+10000.0f)/40.0f+sinf(t1)*m_eddy.x*0.02f;
- uv1.y = (pos.z+10000.0f)/40.0f-cosf(t1)*m_eddy.z*0.02f;
- uv2.x = (pos.x+10010.0f)/20.0f+cosf(-t1)*m_eddy.x*0.02f;
- uv2.y = (pos.z+10010.0f)/20.0f-sinf(-t1)*m_eddy.z*0.02f;
-
- t1 = m_time*0.50f + pos.x*2.1f + pos.z*1.1f;
- t2 = m_time*0.75f + pos.x*2.0f + pos.z*1.0f;
- norm = Math::Vector(sinf(t1)*m_glint, 1.0f, sinf(t2)*m_glint);
-#endif
-}
-
-// Draw the back surface of the water.
-// This surface prevents to see the sky (background) underwater!
-
-void CWater::DrawBack()
-{
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2 vertex[4]; // 2 triangles
- D3DMATERIAL7 material;
- Math::Matrix matrix;
- Math::Vector eye, lookat, n, p, p1, p2;
- Math::Point uv1, uv2;
- float deep, dist;
-
- if ( !m_bDraw ) return;
- if ( m_type[0] == WATER_NULL ) return;
- if ( m_lineUsed == 0 ) return;
-
- eye = m_engine->RetEyePt();
- lookat = m_engine->RetLookatPt();
-
- ZeroMemory( &material, sizeof(D3DMATERIAL7) );
- material.diffuse = m_diffuse;
- material.ambient = m_ambient;
- m_engine->SetMaterial(material);
-
- m_engine->SetTexture("", 0);
-
- device = m_engine->RetD3DDevice();
- device->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
- device->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
- device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_engine->SetState(D3DSTATENORMAL);
-
- deep = m_engine->RetDeepView(0);
- m_engine->SetDeepView(deep*2.0f, 0);
- m_engine->SetFocus(m_engine->RetFocus());
- m_engine->UpdateMatProj(); // twice the depth of view
-
- matrix.LoadIdentity();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- p.x = eye.x;
- p.z = eye.z;
- dist = Math::DistanceProjected(eye, lookat);
- p.x = (lookat.x-eye.x)*deep*1.0f/dist + eye.x;
- p.z = (lookat.z-eye.z)*deep*1.0f/dist + eye.z;
-
- p1.x = (lookat.z-eye.z)*deep*2.0f/dist + p.x;
- p1.z = -(lookat.x-eye.x)*deep*2.0f/dist + p.z;
- p2.x = -(lookat.z-eye.z)*deep*2.0f/dist + p.x;
- p2.z = (lookat.x-eye.x)*deep*2.0f/dist + p.z;
-
- p1.y = -50.0f;
- p2.y = m_level;
-
- n.x = (lookat.x-eye.x)/dist;
- n.z = (lookat.z-eye.z)/dist;
- n.y = 0.0f;
-
- uv1.x = uv1.y = 0.0f;
- uv2.x = uv2.y = 0.0f;
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p2.y, p1.z), n, uv1.x,uv2.y);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p1.y, p1.z), n, uv1.x,uv1.y);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p2.y, p2.z), n, uv2.x,uv2.y);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p1.y, p2.z), n, uv2.x,uv1.y);
-
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-
- m_engine->SetDeepView(deep, 0);
- m_engine->SetFocus(m_engine->RetFocus());
- m_engine->UpdateMatProj(); // gives the initial depth of view
-
- device->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
- device->SetRenderState(D3DRENDERSTATE_ZENABLE, true);
- device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
-}
-
-// Draws the flat surface of the water.
-
-void CWater::DrawSurf()
-{
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2* vertex; // triangles
- D3DMATERIAL7 material;
- Math::Matrix matrix;
- Math::Vector eye, lookat, n, pos, p;
- Math::Point uv1, uv2;
- bool bUnder;
- DWORD flags;
- float deep, size, sizez, radius;
- int rankview, i, j, u;
-
- if ( !m_bDraw ) return;
- if ( m_type[0] == WATER_NULL ) return;
- if ( m_lineUsed == 0 ) return;
-
- vertex = (D3DVERTEX2*)malloc(sizeof(D3DVERTEX2)*(m_brick+2)*2);
-
- eye = m_engine->RetEyePt();
- lookat = m_engine->RetLookatPt();
-
- rankview = m_engine->RetRankView();
- bUnder = ( rankview == 1);
-
- device = m_engine->RetD3DDevice();
-//? device->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
-//? device->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
-//? device->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
- device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
-
- matrix.LoadIdentity();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- ZeroMemory( &material, sizeof(D3DMATERIAL7) );
- material.diffuse = m_diffuse;
- material.ambient = m_ambient;
- m_engine->SetMaterial(material);
-
- m_engine->SetTexture(m_filename, 0);
- m_engine->SetTexture(m_filename, 1);
-
- if ( m_type[rankview] == WATER_TT )
- {
- m_engine->SetState(D3DSTATETTb|D3DSTATEDUALw|D3DSTATEWRAP, m_color);
- }
- if ( m_type[rankview] == WATER_TO )
- {
- m_engine->SetState(D3DSTATENORMAL|D3DSTATEDUALw|D3DSTATEWRAP);
- }
- if ( m_type[rankview] == WATER_CT )
- {
- m_engine->SetState(D3DSTATETTb);
- }
- if ( m_type[rankview] == WATER_CO )
- {
- m_engine->SetState(D3DSTATENORMAL);
- }
- device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
-
- size = m_size/2.0f;
- if ( bUnder ) sizez = -size;
- else sizez = size;
-
- // Draws all the lines.
- deep = m_engine->RetDeepView(0)*1.5f;
-
- for ( i=0 ; i<m_lineUsed ; i++ )
- {
- pos.y = m_level;
- pos.z = m_line[i].pz;
- pos.x = m_line[i].px1;
-
- // Visible line?
- p = pos;
- p.x += size*(m_line[i].len-1);
- radius = sqrtf(powf(size, 2.0f)+powf(size*m_line[i].len, 2.0f));
- if ( Math::Distance(p, eye) > deep+radius ) continue;
-
- D3DVECTOR pD3D = VEC_TO_D3DVEC(p);
- device->ComputeSphereVisibility(&pD3D, &radius, 1, 0, &flags);
-
- if ( flags & D3DSTATUS_CLIPINTERSECTIONALL ) continue;
-
- u = 0;
- p.x = pos.x-size;
- p.z = pos.z-sizez;
- p.y = pos.y;
- AdjustLevel(p, n, uv1, uv2);
- if ( bUnder ) n.y = -n.y;
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
-
- p.x = pos.x-size;
- p.z = pos.z+sizez;
- p.y = pos.y;
- AdjustLevel(p, n, uv1, uv2);
- if ( bUnder ) n.y = -n.y;
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
-
- for ( j=0 ; j<m_line[i].len ; j++ )
- {
- p.x = pos.x+size;
- p.z = pos.z-sizez;
- p.y = pos.y;
- AdjustLevel(p, n, uv1, uv2);
- if ( bUnder ) n.y = -n.y;
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
-
- p.x = pos.x+size;
- p.z = pos.z+sizez;
- p.y = pos.y;
- AdjustLevel(p, n, uv1, uv2);
- if ( bUnder ) n.y = -n.y;
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
-
- pos.x += size*2.0f;
- }
-
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, u, NULL);
- m_engine->AddStatisticTriangle(u-2);
- }
-
- free(vertex);
-}
-
-
-// Indicates if there is water in a given position.
-
-bool CWater::RetWater(int x, int y)
-{
- Math::Vector pos;
- float size, offset, level;
- int dx, dy;
-
- x *= m_subdiv;
- y *= m_subdiv;
-
- size = m_size/m_subdiv;
- offset = m_brick*m_size/2.0f;
-
- for ( dy=0 ; dy<=m_subdiv ; dy++ )
- {
- for ( dx=0 ; dx<=m_subdiv ; dx++ )
- {
- pos.x = (x+dx)*size - offset;
- pos.z = (y+dy)*size - offset;
- pos.y = 0.0f;
- level = m_terrain->RetFloorLevel(pos, true);
- if ( level < m_level+m_eddy.y ) return true;
- }
- }
- return false;
-}
-
-// Updates the positions, relative to the ground.
-
-bool CWater::CreateLine(int x, int y, int len)
-{
- float offset;
-
- m_line[m_lineUsed].x = x;
- m_line[m_lineUsed].y = y;
- m_line[m_lineUsed].len = len;
-
- offset = m_brick*m_size/2.0f - m_size/2.0f;
-
- m_line[m_lineUsed].px1 = m_size* m_line[m_lineUsed].x - offset;
- m_line[m_lineUsed].px2 = m_size*(m_line[m_lineUsed].x+m_line[m_lineUsed].len) - offset;
- m_line[m_lineUsed].pz = m_size* m_line[m_lineUsed].y - offset;
-
- m_lineUsed ++;
-
- return ( m_lineUsed < MAXWATERLINE );
-}
-
-// Creates all expanses of water.
-
-bool CWater::Create(WaterType type1, WaterType type2, const char *filename,
- D3DCOLORVALUE diffuse, D3DCOLORVALUE ambient,
- float level, float glint, Math::Vector eddy)
-{
- int x, y, len;
-
- m_type[0] = type1;
- m_type[1] = type2;
- m_diffuse = diffuse;
- m_ambient = ambient;
- m_level = level;
- m_glint = glint;
- m_eddy = eddy;
- m_time = 0.0f;
- m_lastLava = 0.0f;
- strcpy(m_filename, filename);
-
- VaporFlush();
-
- if ( m_filename[0] != 0 )
- {
- m_engine->LoadTexture(m_filename, 0);
- m_engine->LoadTexture(m_filename, 1);
- }
-
- if ( m_terrain == 0 )
- {
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- }
- m_brick = m_terrain->RetBrick()*m_terrain->RetMosaic();
- m_size = m_terrain->RetSize();
-
- m_brick /= m_subdiv;
- m_size *= m_subdiv;
-
- if ( m_type[0] == WATER_NULL ) return true;
-
- m_lineUsed = 0;
- for ( y=0 ; y<m_brick ; y++ )
- {
- len = 0;
- for ( x=0 ; x<m_brick ; x++ )
- {
- if ( RetWater(x,y) ) // water here?
- {
- len ++;
- if ( len >= 5 )
- {
- if ( !CreateLine(x-len+1, y, len) ) return false;
- len = 0;
- }
- }
- else // dry?
- {
- if ( len != 0 )
- {
- if ( !CreateLine(x-len, y, len) ) return false;
- len = 0;
- }
- }
- }
- if ( len != 0 )
- {
- if ( !CreateLine(x-len, y, len) ) return false;
- }
- }
- return true;
-}
-
-// Removes all the water.
-
-void CWater::Flush()
-{
- m_type[0] = WATER_NULL;
- m_type[1] = WATER_NULL;
- m_level = 0.0f;
- m_bLava = false;
-}
-
-
-// Changes the level of the water.
-
-bool CWater::SetLevel(float level)
-{
- m_level = level;
-
- return Create(m_type[0], m_type[1], m_filename, m_diffuse, m_ambient,
- m_level, m_glint, m_eddy);
-}
-
-// Returns the current level of water.
-
-float CWater::RetLevel()
-{
- return m_level;
-}
-
-// Returns the current level of water for a given object.
-
-float CWater::RetLevel(CObject* object)
-{
- ObjectType type;
-
- type = object->RetType();
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH )
- {
- return m_level-3.0f;
- }
-
- 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_MOBILEtg ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr )
- {
- return m_level-2.0f;
- }
-
- return m_level;
-}
-
-
-// Management of the mode of lava/water.
-
-void CWater::SetLava(bool bLava)
-{
- m_bLava = bLava;
-}
-
-bool CWater::RetLava()
-{
- return m_bLava;
-}
-
-
-// Adjusts the eye of the camera, not to be in the water.
-
-void CWater::AdjustEye(Math::Vector &eye)
-{
- if ( m_bLava )
- {
- if ( eye.y < m_level+2.0f )
- {
- eye.y = m_level+2.0f; // never under the lava
- }
- }
- else
- {
- if ( eye.y >= m_level-2.0f &&
- eye.y <= m_level+2.0f ) // close to the surface?
- {
- eye.y = m_level+2.0f; // bam, well above
- }
- }
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// water.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/geometry.h"
+#include "math/conv.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "old/d3dutil.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "object/object.h"
+#include "old/sound.h"
+#include "old/water.h"
+
+
+
+
+// Constructor of the terrain.
+
+CWater::CWater(CInstanceManager* iMan, CD3DEngine* engine)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_WATER, this);
+
+ m_engine = engine;
+ m_terrain = 0;
+ m_particule = 0;
+ m_sound = 0;
+
+ m_type[0] = WATER_NULL;
+ m_type[1] = WATER_NULL;
+ m_level = 0.0f;
+ m_bDraw = true;
+ m_bLava = false;
+ m_color = 0xffffffff;
+ m_subdiv = 4;
+ m_filename[0] = 0;
+}
+
+// Destructor of the terrain.
+
+CWater::~CWater()
+{
+}
+
+
+bool CWater::EventProcess(const Event &event)
+{
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if 0
+ if ( event.param == 'S' )
+ {
+ if ( m_subdiv == 1 ) m_subdiv = 2;
+ else if ( m_subdiv == 2 ) m_subdiv = 4;
+ else if ( m_subdiv == 4 ) m_subdiv = 8;
+ else if ( m_subdiv == 8 ) m_subdiv = 1;
+ SetLevel(m_level);
+ }
+ if ( event.param == 'M' )
+ {
+ SetLevel(m_level+1.0f);
+ }
+ if ( event.param == 'D' )
+ {
+ SetLevel(m_level-1.0f);
+ }
+ if ( event.param == 'H' )
+ {
+ m_bDraw = !m_bDraw;
+ }
+ if ( event.param == 'C' )
+ {
+ if ( m_color == 0xffffffff ) m_color = 0xcccccccc;
+ else if ( m_color == 0xcccccccc ) m_color = 0x88888888;
+ else if ( m_color == 0x88888888 ) m_color = 0x44444444;
+ else if ( m_color == 0x44444444 ) m_color = 0x00000000;
+ else if ( m_color == 0x00000000 ) m_color = 0xffffffff;
+ }
+ if ( event.param == 'Q' )
+ {
+ int i;
+ i = (m_color>>24);
+ i += 0x44;
+ i &= 0xff;
+ i = (i<<24);
+ m_color &= 0x00ffffff;
+ m_color |= i;
+ }
+ if ( event.param == 'W' )
+ {
+ int i;
+ i = (m_color>>16);
+ i += 0x44;
+ i &= 0xff;
+ i = (i<<16);
+ m_color &= 0xff00ffff;
+ m_color |= i;
+ }
+ if ( event.param == 'E' )
+ {
+ int i;
+ i = (m_color>>8);
+ i += 0x44;
+ i &= 0xff;
+ i = (i<<8);
+ m_color &= 0xffff00ff;
+ m_color |= i;
+ }
+ if ( event.param == 'R' )
+ {
+ int i;
+ i = m_color;
+ i += 0x44;
+ i &= 0xff;
+ m_color &= 0xffffff00;
+ m_color |= i;
+ }
+#endif
+ }
+ return true;
+}
+
+// Makes water evolve.
+
+bool CWater::EventFrame(const Event &event)
+{
+ if ( m_engine->RetPause() ) return true;
+
+ m_time += event.rTime;
+
+ if ( m_type[0] == WATER_NULL ) return true;
+
+ if ( m_bLava )
+ {
+ LavaFrame(event.rTime);
+ }
+ return true;
+}
+
+// Makes evolve the steam jets on the lava.
+
+void CWater::LavaFrame(float rTime)
+{
+ Math::Vector eye, lookat, dir, perp, pos;
+ float distance, shift, level;
+ int i;
+
+ if ( m_particule == 0 )
+ {
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ }
+
+ for ( i=0 ; i<MAXWATVAPOR ; i++ )
+ {
+ VaporFrame(i, rTime);
+ }
+
+ if ( m_time-m_lastLava >= 0.1f )
+ {
+ eye = m_engine->RetEyePt();
+ lookat = m_engine->RetLookatPt();
+
+ distance = Math::Rand()*200.0f;
+ shift = (Math::Rand()-0.5f)*200.0f;
+
+ dir = Normalize(lookat-eye);
+ pos = eye + dir*distance;
+
+ perp.x = -dir.z;
+ perp.y = dir.y;
+ perp.z = dir.x;
+ pos = pos + perp*shift;
+
+ level = m_terrain->RetFloorLevel(pos, true);
+ if ( level < m_level )
+ {
+ pos.y = m_level;
+
+ level = Math::Rand();
+ if ( level < 0.8f )
+ {
+ if ( VaporCreate(PARTIFIRE, pos, 0.02f+Math::Rand()*0.06f) )
+ {
+ m_lastLava = m_time;
+ }
+ }
+ else if ( level < 0.9f )
+ {
+ if ( VaporCreate(PARTIFLAME, pos, 0.5f+Math::Rand()*3.0f) )
+ {
+ m_lastLava = m_time;
+ }
+ }
+ else
+ {
+ if ( VaporCreate(PARTIVAPOR, pos, 0.2f+Math::Rand()*2.0f) )
+ {
+ m_lastLava = m_time;
+ }
+ }
+ }
+ }
+}
+
+// Removes all the steam jets.
+
+void CWater::VaporFlush()
+{
+ int i;
+
+ for ( i=0 ; i<MAXWATVAPOR ; i++ )
+ {
+ m_vapor[i].bUsed = false;
+ }
+}
+
+// Creates a new steam.
+
+bool CWater::VaporCreate(ParticuleType type, Math::Vector pos, float delay)
+{
+ int i;
+
+ for ( i=0 ; i<MAXWATVAPOR ; i++ )
+ {
+ if ( !m_vapor[i].bUsed )
+ {
+ m_vapor[i].bUsed = true;
+ m_vapor[i].type = type;
+ m_vapor[i].pos = pos;
+ m_vapor[i].delay = delay;
+ m_vapor[i].time = 0.0f;
+ m_vapor[i].last = 0.0f;
+
+ if ( m_vapor[i].type == PARTIFIRE )
+ {
+ m_sound->Play(SOUND_BLUP, pos, 1.0f, 1.0f-Math::Rand()*0.5f);
+ }
+ if ( m_vapor[i].type == PARTIFLAME )
+ {
+//? m_sound->Play(SOUND_SWIM, pos, 1.0f, 1.0f-Math::Rand()*0.5f);
+ }
+ if ( m_vapor[i].type == PARTIVAPOR )
+ {
+ m_sound->Play(SOUND_PSHHH, pos, 0.3f, 2.0f);
+ }
+
+ return true;
+ }
+ }
+ return false;
+}
+
+// Makes evolve a steam jet,
+
+void CWater::VaporFrame(int i, float rTime)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+ int j;
+
+ m_vapor[i].time += rTime;
+
+ if ( m_sound == 0 )
+ {
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ }
+
+ if ( m_vapor[i].time <= m_vapor[i].delay )
+ {
+ if ( m_time-m_vapor[i].last >= m_engine->ParticuleAdapt(0.02f) )
+ {
+ m_vapor[i].last = m_time;
+
+ if ( m_vapor[i].type == PARTIFIRE )
+ {
+ for ( j=0 ; j<10 ; j++ )
+ {
+ pos = m_vapor[i].pos;
+ pos.x += (Math::Rand()-0.5f)*2.0f;
+ pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos.y -= 1.0f;
+ speed.x = (Math::Rand()-0.5f)*6.0f;
+ speed.z = (Math::Rand()-0.5f)*6.0f;
+ speed.y = 8.0f+Math::Rand()*5.0f;
+ dim.x = Math::Rand()*1.5f+1.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 2.0f, 10.0f);
+ }
+ }
+ else if ( m_vapor[i].type == PARTIFLAME )
+ {
+ pos = m_vapor[i].pos;
+ pos.x += (Math::Rand()-0.5f)*8.0f;
+ pos.z += (Math::Rand()-0.5f)*8.0f;
+ pos.y -= 2.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = 4.0f+Math::Rand()*4.0f;
+ dim.x = Math::Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFLAME);
+ }
+ else
+ {
+ pos = m_vapor[i].pos;
+ pos.x += (Math::Rand()-0.5f)*4.0f;
+ pos.z += (Math::Rand()-0.5f)*4.0f;
+ pos.y -= 2.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = 8.0f+Math::Rand()*8.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIVAPOR);
+ }
+ }
+ }
+ else
+ {
+ m_vapor[i].bUsed = false;
+ }
+}
+
+
+// Adjusts the position to normal, to imitate reflections on an expanse of water at rest.
+
+void CWater::AdjustLevel(Math::Vector &pos, Math::Vector &norm,
+ Math::Point &uv1, Math::Point &uv2)
+{
+#if 0
+ float t1, t2;
+
+ uv1.x = (pos.x+10000.0f)/40.0f;
+ uv1.y = (pos.z+10000.0f)/40.0f;
+
+ t1 = m_time*1.5f + pos.x*0.1f * pos.z*0.2f;
+ pos.y += sinf(t1)*m_eddy.y;
+
+ t1 = m_time*0.6f + pos.x*0.1f * pos.z*0.2f;
+ t2 = m_time*0.7f + pos.x*0.3f * pos.z*0.4f;
+ pos.x += sinf(t1)*m_eddy.x;
+ pos.z += sinf(t2)*m_eddy.z;
+
+//? uv2.x = (pos.x+10000.0f)/40.0f+0.3f;
+//? uv2.y = (pos.z+10000.0f)/40.0f+0.4f;
+ uv2.x = (pos.x+10000.0f)/20.0f;
+ uv2.y = (pos.z+10000.0f)/20.0f;
+
+ t1 = m_time*0.7f + pos.x*5.5f + pos.z*5.6f;
+ t2 = m_time*0.8f + pos.x*5.7f + pos.z*5.8f;
+ norm = Math::Vector(sinf(t1)*m_glint, 1.0f, sinf(t2)*m_glint);
+#else
+ float t1, t2;
+
+ t1 = m_time*1.5f + pos.x*0.1f * pos.z*0.2f;
+ pos.y += sinf(t1)*m_eddy.y;
+
+ t1 = m_time*1.5f;
+ uv1.x = (pos.x+10000.0f)/40.0f+sinf(t1)*m_eddy.x*0.02f;
+ uv1.y = (pos.z+10000.0f)/40.0f-cosf(t1)*m_eddy.z*0.02f;
+ uv2.x = (pos.x+10010.0f)/20.0f+cosf(-t1)*m_eddy.x*0.02f;
+ uv2.y = (pos.z+10010.0f)/20.0f-sinf(-t1)*m_eddy.z*0.02f;
+
+ t1 = m_time*0.50f + pos.x*2.1f + pos.z*1.1f;
+ t2 = m_time*0.75f + pos.x*2.0f + pos.z*1.0f;
+ norm = Math::Vector(sinf(t1)*m_glint, 1.0f, sinf(t2)*m_glint);
+#endif
+}
+
+// Draw the back surface of the water.
+// This surface prevents to see the sky (background) underwater!
+
+void CWater::DrawBack()
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ D3DMATERIAL7 material;
+ Math::Matrix matrix;
+ Math::Vector eye, lookat, n, p, p1, p2;
+ Math::Point uv1, uv2;
+ float deep, dist;
+
+ if ( !m_bDraw ) return;
+ if ( m_type[0] == WATER_NULL ) return;
+ if ( m_lineUsed == 0 ) return;
+
+ eye = m_engine->RetEyePt();
+ lookat = m_engine->RetLookatPt();
+
+ ZeroMemory( &material, sizeof(D3DMATERIAL7) );
+ material.diffuse = m_diffuse;
+ material.ambient = m_ambient;
+ m_engine->SetMaterial(material);
+
+ m_engine->SetTexture("", 0);
+
+ device = m_engine->RetD3DDevice();
+ device->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
+ device->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
+ device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_engine->SetState(D3DSTATENORMAL);
+
+ deep = m_engine->RetDeepView(0);
+ m_engine->SetDeepView(deep*2.0f, 0);
+ m_engine->SetFocus(m_engine->RetFocus());
+ m_engine->UpdateMatProj(); // twice the depth of view
+
+ matrix.LoadIdentity();
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ p.x = eye.x;
+ p.z = eye.z;
+ dist = Math::DistanceProjected(eye, lookat);
+ p.x = (lookat.x-eye.x)*deep*1.0f/dist + eye.x;
+ p.z = (lookat.z-eye.z)*deep*1.0f/dist + eye.z;
+
+ p1.x = (lookat.z-eye.z)*deep*2.0f/dist + p.x;
+ p1.z = -(lookat.x-eye.x)*deep*2.0f/dist + p.z;
+ p2.x = -(lookat.z-eye.z)*deep*2.0f/dist + p.x;
+ p2.z = (lookat.x-eye.x)*deep*2.0f/dist + p.z;
+
+ p1.y = -50.0f;
+ p2.y = m_level;
+
+ n.x = (lookat.x-eye.x)/dist;
+ n.z = (lookat.z-eye.z)/dist;
+ n.y = 0.0f;
+
+ uv1.x = uv1.y = 0.0f;
+ uv2.x = uv2.y = 0.0f;
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p2.y, p1.z), n, uv1.x,uv2.y);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p1.y, p1.z), n, uv1.x,uv1.y);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p2.y, p2.z), n, uv2.x,uv2.y);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p1.y, p2.z), n, uv2.x,uv1.y);
+
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+
+ m_engine->SetDeepView(deep, 0);
+ m_engine->SetFocus(m_engine->RetFocus());
+ m_engine->UpdateMatProj(); // gives the initial depth of view
+
+ device->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
+ device->SetRenderState(D3DRENDERSTATE_ZENABLE, true);
+ device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+}
+
+// Draws the flat surface of the water.
+
+void CWater::DrawSurf()
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DVERTEX2* vertex; // triangles
+ D3DMATERIAL7 material;
+ Math::Matrix matrix;
+ Math::Vector eye, lookat, n, pos, p;
+ Math::Point uv1, uv2;
+ bool bUnder;
+ DWORD flags;
+ float deep, size, sizez, radius;
+ int rankview, i, j, u;
+
+ if ( !m_bDraw ) return;
+ if ( m_type[0] == WATER_NULL ) return;
+ if ( m_lineUsed == 0 ) return;
+
+ vertex = (D3DVERTEX2*)malloc(sizeof(D3DVERTEX2)*(m_brick+2)*2);
+
+ eye = m_engine->RetEyePt();
+ lookat = m_engine->RetLookatPt();
+
+ rankview = m_engine->RetRankView();
+ bUnder = ( rankview == 1);
+
+ device = m_engine->RetD3DDevice();
+//? device->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+//? device->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
+//? device->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
+ device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+
+ matrix.LoadIdentity();
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ ZeroMemory( &material, sizeof(D3DMATERIAL7) );
+ material.diffuse = m_diffuse;
+ material.ambient = m_ambient;
+ m_engine->SetMaterial(material);
+
+ m_engine->SetTexture(m_filename, 0);
+ m_engine->SetTexture(m_filename, 1);
+
+ if ( m_type[rankview] == WATER_TT )
+ {
+ m_engine->SetState(D3DSTATETTb|D3DSTATEDUALw|D3DSTATEWRAP, m_color);
+ }
+ if ( m_type[rankview] == WATER_TO )
+ {
+ m_engine->SetState(D3DSTATENORMAL|D3DSTATEDUALw|D3DSTATEWRAP);
+ }
+ if ( m_type[rankview] == WATER_CT )
+ {
+ m_engine->SetState(D3DSTATETTb);
+ }
+ if ( m_type[rankview] == WATER_CO )
+ {
+ m_engine->SetState(D3DSTATENORMAL);
+ }
+ device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
+
+ size = m_size/2.0f;
+ if ( bUnder ) sizez = -size;
+ else sizez = size;
+
+ // Draws all the lines.
+ deep = m_engine->RetDeepView(0)*1.5f;
+
+ for ( i=0 ; i<m_lineUsed ; i++ )
+ {
+ pos.y = m_level;
+ pos.z = m_line[i].pz;
+ pos.x = m_line[i].px1;
+
+ // Visible line?
+ p = pos;
+ p.x += size*(m_line[i].len-1);
+ radius = sqrtf(powf(size, 2.0f)+powf(size*m_line[i].len, 2.0f));
+ if ( Math::Distance(p, eye) > deep+radius ) continue;
+
+ D3DVECTOR pD3D = VEC_TO_D3DVEC(p);
+ device->ComputeSphereVisibility(&pD3D, &radius, 1, 0, &flags);
+
+ if ( flags & D3DSTATUS_CLIPINTERSECTIONALL ) continue;
+
+ u = 0;
+ p.x = pos.x-size;
+ p.z = pos.z-sizez;
+ p.y = pos.y;
+ AdjustLevel(p, n, uv1, uv2);
+ if ( bUnder ) n.y = -n.y;
+ vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+
+ p.x = pos.x-size;
+ p.z = pos.z+sizez;
+ p.y = pos.y;
+ AdjustLevel(p, n, uv1, uv2);
+ if ( bUnder ) n.y = -n.y;
+ vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+
+ for ( j=0 ; j<m_line[i].len ; j++ )
+ {
+ p.x = pos.x+size;
+ p.z = pos.z-sizez;
+ p.y = pos.y;
+ AdjustLevel(p, n, uv1, uv2);
+ if ( bUnder ) n.y = -n.y;
+ vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+
+ p.x = pos.x+size;
+ p.z = pos.z+sizez;
+ p.y = pos.y;
+ AdjustLevel(p, n, uv1, uv2);
+ if ( bUnder ) n.y = -n.y;
+ vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+
+ pos.x += size*2.0f;
+ }
+
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, u, NULL);
+ m_engine->AddStatisticTriangle(u-2);
+ }
+
+ free(vertex);
+}
+
+
+// Indicates if there is water in a given position.
+
+bool CWater::RetWater(int x, int y)
+{
+ Math::Vector pos;
+ float size, offset, level;
+ int dx, dy;
+
+ x *= m_subdiv;
+ y *= m_subdiv;
+
+ size = m_size/m_subdiv;
+ offset = m_brick*m_size/2.0f;
+
+ for ( dy=0 ; dy<=m_subdiv ; dy++ )
+ {
+ for ( dx=0 ; dx<=m_subdiv ; dx++ )
+ {
+ pos.x = (x+dx)*size - offset;
+ pos.z = (y+dy)*size - offset;
+ pos.y = 0.0f;
+ level = m_terrain->RetFloorLevel(pos, true);
+ if ( level < m_level+m_eddy.y ) return true;
+ }
+ }
+ return false;
+}
+
+// Updates the positions, relative to the ground.
+
+bool CWater::CreateLine(int x, int y, int len)
+{
+ float offset;
+
+ m_line[m_lineUsed].x = x;
+ m_line[m_lineUsed].y = y;
+ m_line[m_lineUsed].len = len;
+
+ offset = m_brick*m_size/2.0f - m_size/2.0f;
+
+ m_line[m_lineUsed].px1 = m_size* m_line[m_lineUsed].x - offset;
+ m_line[m_lineUsed].px2 = m_size*(m_line[m_lineUsed].x+m_line[m_lineUsed].len) - offset;
+ m_line[m_lineUsed].pz = m_size* m_line[m_lineUsed].y - offset;
+
+ m_lineUsed ++;
+
+ return ( m_lineUsed < MAXWATERLINE );
+}
+
+// Creates all expanses of water.
+
+bool CWater::Create(WaterType type1, WaterType type2, const char *filename,
+ D3DCOLORVALUE diffuse, D3DCOLORVALUE ambient,
+ float level, float glint, Math::Vector eddy)
+{
+ int x, y, len;
+
+ m_type[0] = type1;
+ m_type[1] = type2;
+ m_diffuse = diffuse;
+ m_ambient = ambient;
+ m_level = level;
+ m_glint = glint;
+ m_eddy = eddy;
+ m_time = 0.0f;
+ m_lastLava = 0.0f;
+ strcpy(m_filename, filename);
+
+ VaporFlush();
+
+ if ( m_filename[0] != 0 )
+ {
+ m_engine->LoadTexture(m_filename, 0);
+ m_engine->LoadTexture(m_filename, 1);
+ }
+
+ if ( m_terrain == 0 )
+ {
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ }
+ m_brick = m_terrain->RetBrick()*m_terrain->RetMosaic();
+ m_size = m_terrain->RetSize();
+
+ m_brick /= m_subdiv;
+ m_size *= m_subdiv;
+
+ if ( m_type[0] == WATER_NULL ) return true;
+
+ m_lineUsed = 0;
+ for ( y=0 ; y<m_brick ; y++ )
+ {
+ len = 0;
+ for ( x=0 ; x<m_brick ; x++ )
+ {
+ if ( RetWater(x,y) ) // water here?
+ {
+ len ++;
+ if ( len >= 5 )
+ {
+ if ( !CreateLine(x-len+1, y, len) ) return false;
+ len = 0;
+ }
+ }
+ else // dry?
+ {
+ if ( len != 0 )
+ {
+ if ( !CreateLine(x-len, y, len) ) return false;
+ len = 0;
+ }
+ }
+ }
+ if ( len != 0 )
+ {
+ if ( !CreateLine(x-len, y, len) ) return false;
+ }
+ }
+ return true;
+}
+
+// Removes all the water.
+
+void CWater::Flush()
+{
+ m_type[0] = WATER_NULL;
+ m_type[1] = WATER_NULL;
+ m_level = 0.0f;
+ m_bLava = false;
+}
+
+
+// Changes the level of the water.
+
+bool CWater::SetLevel(float level)
+{
+ m_level = level;
+
+ return Create(m_type[0], m_type[1], m_filename, m_diffuse, m_ambient,
+ m_level, m_glint, m_eddy);
+}
+
+// Returns the current level of water.
+
+float CWater::RetLevel()
+{
+ return m_level;
+}
+
+// Returns the current level of water for a given object.
+
+float CWater::RetLevel(CObject* object)
+{
+ ObjectType type;
+
+ type = object->RetType();
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH )
+ {
+ return m_level-3.0f;
+ }
+
+ 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_MOBILEtg ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr )
+ {
+ return m_level-2.0f;
+ }
+
+ return m_level;
+}
+
+
+// Management of the mode of lava/water.
+
+void CWater::SetLava(bool bLava)
+{
+ m_bLava = bLava;
+}
+
+bool CWater::RetLava()
+{
+ return m_bLava;
+}
+
+
+// Adjusts the eye of the camera, not to be in the water.
+
+void CWater::AdjustEye(Math::Vector &eye)
+{
+ if ( m_bLava )
+ {
+ if ( eye.y < m_level+2.0f )
+ {
+ eye.y = m_level+2.0f; // never under the lava
+ }
+ }
+ else
+ {
+ if ( eye.y >= m_level-2.0f &&
+ eye.y <= m_level+2.0f ) // close to the surface?
+ {
+ eye.y = m_level+2.0f; // bam, well above
+ }
+ }
+}
+
diff --git a/src/old/water.h b/src/old/water.h
index b2a596b..8a68dd6 100644
--- a/src/old/water.h
+++ b/src/old/water.h
@@ -1,130 +1,130 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// water.h
-
-#pragma once
-
-
-#include "common/event.h"
-#include "old/d3dengine.h"
-#include "old/particule.h"
-
-
-class CInstanceManager;
-class CTerrain;
-class CSound;
-
-
-
-const int MAXWATERLINE = 500;
-
-struct WaterLine
-{
- short x, y; // beginning
- short len; // length by x
- float px1, px2, pz;
-};
-
-
-const int MAXWATVAPOR = 10;
-
-struct WaterVapor
-{
- bool bUsed;
- ParticuleType type;
- Math::Vector pos;
- float delay;
- float time;
- float last;
-};
-
-
-enum WaterType
-{
- WATER_NULL = 0, // no water
- WATER_TT = 1, // transparent texture
- WATER_TO = 2, // opaque texture
- WATER_CT = 3, // transparent color
- WATER_CO = 4, // opaque color
-};
-
-
-class CWater
-{
-public:
- CWater(CInstanceManager* iMan, CD3DEngine* engine);
- ~CWater();
-
- void SetD3DDevice(LPDIRECT3DDEVICE7 device);
- bool EventProcess(const Event &event);
- void Flush();
- bool Create(WaterType type1, WaterType type2, const char *filename, D3DCOLORVALUE diffuse, D3DCOLORVALUE ambient, float level, float glint, Math::Vector eddy);
- void DrawBack();
- void DrawSurf();
-
- bool SetLevel(float level);
- float RetLevel();
- float RetLevel(CObject* object);
-
- void SetLava(bool bLava);
- bool RetLava();
-
- void AdjustEye(Math::Vector &eye);
-
-protected:
- bool EventFrame(const Event &event);
- void LavaFrame(float rTime);
- void AdjustLevel(Math::Vector &pos, Math::Vector &norm, Math::Point &uv1, Math::Point &uv2);
- bool RetWater(int x, int y);
- bool CreateLine(int x, int y, int len);
-
- void VaporFlush();
- bool VaporCreate(ParticuleType type, Math::Vector pos, float delay);
- void VaporFrame(int i, float rTime);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- LPDIRECT3DDEVICE7 m_pD3DDevice;
- CTerrain* m_terrain;
- CParticule* m_particule;
- CSound* m_sound;
-
- WaterType m_type[2];
- char m_filename[100];
- float m_level; // overall level
- float m_glint; // amplitude of reflections
- Math::Vector m_eddy; // amplitude of swirls
- D3DCOLORVALUE m_diffuse; // diffuse color
- D3DCOLORVALUE m_ambient; // ambient color
- float m_time;
- float m_lastLava;
- int m_subdiv;
-
- int m_brick; // number of brick*mosaics
- float m_size; // size of a item in an brick
-
- int m_lineUsed;
- WaterLine m_line[MAXWATERLINE];
-
- WaterVapor m_vapor[MAXWATVAPOR];
-
- bool m_bDraw;
- bool m_bLava;
- D3DCOLOR m_color;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// water.h
+
+#pragma once
+
+
+#include "common/event.h"
+#include "old/d3dengine.h"
+#include "old/particule.h"
+
+
+class CInstanceManager;
+class CTerrain;
+class CSound;
+
+
+
+const int MAXWATERLINE = 500;
+
+struct WaterLine
+{
+ short x, y; // beginning
+ short len; // length by x
+ float px1, px2, pz;
+};
+
+
+const int MAXWATVAPOR = 10;
+
+struct WaterVapor
+{
+ bool bUsed;
+ ParticuleType type;
+ Math::Vector pos;
+ float delay;
+ float time;
+ float last;
+};
+
+
+enum WaterType
+{
+ WATER_NULL = 0, // no water
+ WATER_TT = 1, // transparent texture
+ WATER_TO = 2, // opaque texture
+ WATER_CT = 3, // transparent color
+ WATER_CO = 4, // opaque color
+};
+
+
+class CWater
+{
+public:
+ CWater(CInstanceManager* iMan, CD3DEngine* engine);
+ ~CWater();
+
+ void SetD3DDevice(LPDIRECT3DDEVICE7 device);
+ bool EventProcess(const Event &event);
+ void Flush();
+ bool Create(WaterType type1, WaterType type2, const char *filename, D3DCOLORVALUE diffuse, D3DCOLORVALUE ambient, float level, float glint, Math::Vector eddy);
+ void DrawBack();
+ void DrawSurf();
+
+ bool SetLevel(float level);
+ float RetLevel();
+ float RetLevel(CObject* object);
+
+ void SetLava(bool bLava);
+ bool RetLava();
+
+ void AdjustEye(Math::Vector &eye);
+
+protected:
+ bool EventFrame(const Event &event);
+ void LavaFrame(float rTime);
+ void AdjustLevel(Math::Vector &pos, Math::Vector &norm, Math::Point &uv1, Math::Point &uv2);
+ bool RetWater(int x, int y);
+ bool CreateLine(int x, int y, int len);
+
+ void VaporFlush();
+ bool VaporCreate(ParticuleType type, Math::Vector pos, float delay);
+ void VaporFrame(int i, float rTime);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ LPDIRECT3DDEVICE7 m_pD3DDevice;
+ CTerrain* m_terrain;
+ CParticule* m_particule;
+ CSound* m_sound;
+
+ WaterType m_type[2];
+ char m_filename[100];
+ float m_level; // overall level
+ float m_glint; // amplitude of reflections
+ Math::Vector m_eddy; // amplitude of swirls
+ D3DCOLORVALUE m_diffuse; // diffuse color
+ D3DCOLORVALUE m_ambient; // ambient color
+ float m_time;
+ float m_lastLava;
+ int m_subdiv;
+
+ int m_brick; // number of brick*mosaics
+ float m_size; // size of a item in an brick
+
+ int m_lineUsed;
+ WaterLine m_line[MAXWATERLINE];
+
+ WaterVapor m_vapor[MAXWATVAPOR];
+
+ bool m_bDraw;
+ bool m_bLava;
+ D3DCOLOR m_color;
+};
+
diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp
index 49d7684..6e290de 100644
--- a/src/physics/physics.cpp
+++ b/src/physics/physics.cpp
@@ -1,3885 +1,3885 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// physics.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/language.h"
-#include "common/global.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "old/light.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "old/camera.h"
-#include "object/object.h"
-#include "old/pyro.h"
-#include "object/brain.h"
-#include "object/motion/motion.h"
-#include "object/motion/motionhuman.h"
-#include "old/sound.h"
-#include "object/task/task.h"
-#include "script/cmdtoken.h"
-#include "physics/physics.h"
-
-
-
-const float LANDING_SPEED = 3.0f;
-const float LANDING_ACCEL = 5.0f;
-const float LANDING_ACCELh = 1.5f;
-
-
-
-
-// Object's constructor.
-
-CPhysics::CPhysics(CInstanceManager* iMan, CObject* object)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_PHYSICS, this, 100);
-
- m_object = object;
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- m_brain = 0;
- m_motion = 0;
-
- m_type = TYPE_ROLLING;
- m_gravity = 9.81f; // default gravity
- m_time = 0.0f;
- m_timeUnderWater = 0.0f;
- m_motorSpeed = Math::Vector(0.0f, 0.0f, 0.0f);
- m_bMotor = false;
- m_bLand = true; // ground
- m_bSwim = false; // in air
- m_bCollision = false;
- m_bObstacle = false;
- m_repeatCollision = 0;
- m_linVibrationFactor = 1.0f;
- m_cirVibrationFactor = 1.0f;
- m_inclinaisonFactor = 1.0f;
- m_lastPowerParticule = 0.0f;
- m_lastSlideParticule = 0.0f;
- m_lastMotorParticule = 0.0f;
- m_lastWaterParticule = 0.0f;
- m_lastUnderParticule = 0.0f;
- m_lastPloufParticule = 0.0f;
- m_lastFlameParticule = 0.0f;
- m_bWheelParticuleBrake = false;
- m_absorbWater = 0.0f;
- m_reactorTemperature = 0.0f;
- m_reactorRange = 1.0f;
- m_timeReactorFail = 0.0f;
- m_lastEnergy = 0.0f;
- m_lastSoundWater = 0.0f;
- m_lastSoundInsect = 0.0f;
- m_restBreakParticule = 0.0f;
- m_floorHeight = 0.0f;
- m_soundChannel = -1;
- m_soundChannelSlide = -1;
- m_soundTimePshhh = 0.0f;
- m_soundTimeJostle = 0.0f;
- m_soundTimeBoum = 0.0f;
- m_bSoundSlow = true;
- m_bFreeze = false;
- m_bForceUpdate = true;
- m_bLowLevel = false;
-
- ZeroMemory(&m_linMotion, sizeof(Motion));
- ZeroMemory(&m_cirMotion, sizeof(Motion));
-}
-
-// Object's destructor.
-
-CPhysics::~CPhysics()
-{
- m_iMan->DeleteInstance(CLASS_PHYSICS, this);
-}
-
-
-// Destroys the object.
-
-void CPhysics::DeleteObject(bool bAll)
-{
- if ( m_soundChannel != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.3f, SOPER_STOP);
- m_soundChannel = -1;
- }
- if ( m_soundChannelSlide != -1 )
- {
- m_sound->FlushEnvelope(m_soundChannelSlide);
- m_sound->AddEnvelope(m_soundChannelSlide, 0.0f, 1.0f, 0.3f, SOPER_STOP);
- m_soundChannelSlide = -1;
- }
-}
-
-
-
-void CPhysics::SetBrain(CBrain* brain)
-{
- m_brain = brain;
-}
-
-void CPhysics::SetMotion(CMotion* motion)
-{
- m_motion = motion;
-}
-
-// Management of the type.
-
-void CPhysics::SetType(PhysicsType type)
-{
- m_type = type;
-}
-
-PhysicsType CPhysics::RetType()
-{
- return m_type;
-}
-
-
-
-// Saves all parameters of the object.
-
-bool CPhysics::Write(char *line)
-{
- char name[100];
-
- sprintf(name, " motor=%.2f;%.2f;%.2f", m_motorSpeed.x, m_motorSpeed.y, m_motorSpeed.z);
- strcat(line, name);
-
- if ( m_type == TYPE_FLYING )
- {
- sprintf(name, " reactorRange=%.2f", RetReactorRange());
- strcat(line, name);
-
- sprintf(name, " land=%d", RetLand());
- strcat(line, name);
- }
-
- return true;
-}
-
-// Restores all parameters of the object.
-
-bool CPhysics::Read(char *line)
-{
- m_motorSpeed = OpDir(line, "motor");
-
- if ( m_type == TYPE_FLYING )
- {
- SetReactorRange(OpFloat(line, "reactorRange", 0.0f));
- SetLand(OpInt(line, "land", 0));
- }
-
- return true;
-}
-
-
-
-// Management of the force of gravity.
-
-void CPhysics::SetGravity(float value)
-{
- m_gravity = value;
-}
-
-float CPhysics::RetGravity()
-{
- return m_gravity;
-}
-
-
-// Returns the height above the ground.
-
-float CPhysics::RetFloorHeight()
-{
- return m_floorHeight;
-}
-
-
-// Managing the state of the engine.
-
-void CPhysics::SetMotor(bool bState)
-{
- int light;
-
- m_bMotor = bState;
-
- light = m_object->RetShadowLight();
- if ( light != -1 )
- {
- m_light->SetLightIntensity(light, m_bMotor?1.0f:0.0f);
- m_light->SetLightIntensitySpeed(light, 3.0f);
- }
-}
-
-bool CPhysics::RetMotor()
-{
- return m_bMotor;
-}
-
-
-// Management of the state in flight/ground.
-
-void CPhysics::SetLand(bool bState)
-{
- m_bLand = bState;
- SetMotor(!bState); // lights if you leave the reactor in flight
-}
-
-bool CPhysics::RetLand()
-{
- return m_bLand;
-}
-
-
-// Management of the state in air/water.
-
-void CPhysics::SetSwim(bool bState)
-{
- if ( !m_bSwim && bState ) // enters the water?
- {
- m_timeUnderWater = 0.0f;
- }
- m_bSwim = bState;
-}
-
-bool CPhysics::RetSwim()
-{
- return m_bSwim;
-}
-
-
-// Indicates whether a collision occurred.
-
-void CPhysics::SetCollision(bool bCollision)
-{
- m_bCollision = bCollision;
-}
-
-bool CPhysics::RetCollision()
-{
- return m_bCollision;
-}
-
-
-// Indicates whether the influence of soil is activated or not.
-
-void CPhysics::SetFreeze(bool bFreeze)
-{
- m_bFreeze = bFreeze;
-}
-
-bool CPhysics::RetFreeze()
-{
- return m_bFreeze;
-}
-
-
-// Returns the range of the reactor.
-
-void CPhysics::SetReactorRange(float range)
-{
- m_reactorRange = range;
-}
-
-float CPhysics::RetReactorRange()
-{
- return m_reactorRange;
-}
-
-
-// Specifies the engine speed.
-// x = forward/backward
-// y = up/down
-// z = turn
-
-void CPhysics::SetMotorSpeed(Math::Vector speed)
-{
- m_motorSpeed = speed;
-}
-
-// Specifies the engine speed for forward/backward.
-// +1 = forward
-// -1 = backward
-
-void CPhysics::SetMotorSpeedX(float speed)
-{
- m_motorSpeed.x = speed;
-}
-
-// Specifies the motor speed for up/down.
-// +1 = up
-// -1 = down
-
-void CPhysics::SetMotorSpeedY(float speed)
-{
- m_motorSpeed.y = speed;
-}
-
-// Specifies the speed of the motor to turn.
-// +1 = turn right(CW)
-// -1 = turn left(CCW)
-
-void CPhysics::SetMotorSpeedZ(float speed)
-{
- m_motorSpeed.z = speed;
-}
-
-Math::Vector CPhysics::RetMotorSpeed()
-{
- return m_motorSpeed;
-}
-
-float CPhysics::RetMotorSpeedX()
-{
- return m_motorSpeed.x;
-}
-
-float CPhysics::RetMotorSpeedY()
-{
- return m_motorSpeed.y;
-}
-
-float CPhysics::RetMotorSpeedZ()
-{
- return m_motorSpeed.z;
-}
-
-
-// Management of linear and angular velocities.
-// Specifies the speed parallel to the direction of travel.
-
-void CPhysics::SetLinMotion(PhysicsMode mode, Math::Vector value)
-{
- if ( mode == MO_ADVACCEL ) m_linMotion.advanceAccel = value;
- if ( mode == MO_RECACCEL ) m_linMotion.recedeAccel = value;
- if ( mode == MO_STOACCEL ) m_linMotion.stopAccel = value;
- if ( mode == MO_TERSPEED ) m_linMotion.terrainSpeed = value;
- if ( mode == MO_TERSLIDE ) m_linMotion.terrainSlide = value;
- if ( mode == MO_MOTACCEL ) m_linMotion.motorAccel = value;
- if ( mode == MO_TERFORCE ) m_linMotion.terrainForce = value;
- if ( mode == MO_ADVSPEED ) m_linMotion.advanceSpeed = value;
- if ( mode == MO_RECSPEED ) m_linMotion.recedeSpeed = value;
- if ( mode == MO_MOTSPEED ) m_linMotion.motorSpeed = value;
- if ( mode == MO_CURSPEED ) m_linMotion.currentSpeed = value;
- if ( mode == MO_REASPEED ) m_linMotion.realSpeed = value;
-}
-
-Math::Vector CPhysics::RetLinMotion(PhysicsMode mode)
-{
- if ( mode == MO_ADVACCEL ) return m_linMotion.advanceAccel;
- if ( mode == MO_RECACCEL ) return m_linMotion.recedeAccel;
- if ( mode == MO_STOACCEL ) return m_linMotion.stopAccel;
- if ( mode == MO_TERSPEED ) return m_linMotion.terrainSpeed;
- if ( mode == MO_TERSLIDE ) return m_linMotion.terrainSlide;
- if ( mode == MO_MOTACCEL ) return m_linMotion.motorAccel;
- if ( mode == MO_TERFORCE ) return m_linMotion.terrainForce;
- if ( mode == MO_ADVSPEED ) return m_linMotion.advanceSpeed;
- if ( mode == MO_RECSPEED ) return m_linMotion.recedeSpeed;
- if ( mode == MO_MOTSPEED ) return m_linMotion.motorSpeed;
- if ( mode == MO_CURSPEED ) return m_linMotion.currentSpeed;
- if ( mode == MO_REASPEED ) return m_linMotion.realSpeed;
- return Math::Vector(0.0f, 0.0f, 0.0f);
-}
-
-void CPhysics::SetLinMotionX(PhysicsMode mode, float value)
-{
- if ( mode == MO_ADVACCEL ) m_linMotion.advanceAccel.x = value;
- if ( mode == MO_RECACCEL ) m_linMotion.recedeAccel.x = value;
- if ( mode == MO_STOACCEL ) m_linMotion.stopAccel.x = value;
- if ( mode == MO_TERSPEED ) m_linMotion.terrainSpeed.x = value;
- if ( mode == MO_TERSLIDE ) m_linMotion.terrainSlide.x = value;
- if ( mode == MO_MOTACCEL ) m_linMotion.motorAccel.x = value;
- if ( mode == MO_TERFORCE ) m_linMotion.terrainForce.x = value;
- if ( mode == MO_ADVSPEED ) m_linMotion.advanceSpeed.x = value;
- if ( mode == MO_RECSPEED ) m_linMotion.recedeSpeed.x = value;
- if ( mode == MO_MOTSPEED ) m_linMotion.motorSpeed.x = value;
- if ( mode == MO_CURSPEED ) m_linMotion.currentSpeed.x = value;
- if ( mode == MO_REASPEED ) m_linMotion.realSpeed.x = value;
-}
-
-float CPhysics::RetLinMotionX(PhysicsMode mode)
-{
- if ( mode == MO_ADVACCEL ) return m_linMotion.advanceAccel.x;
- if ( mode == MO_RECACCEL ) return m_linMotion.recedeAccel.x;
- if ( mode == MO_STOACCEL ) return m_linMotion.stopAccel.x;
- if ( mode == MO_TERSPEED ) return m_linMotion.terrainSpeed.x;
- if ( mode == MO_TERSLIDE ) return m_linMotion.terrainSlide.x;
- if ( mode == MO_MOTACCEL ) return m_linMotion.motorAccel.x;
- if ( mode == MO_TERFORCE ) return m_linMotion.terrainForce.x;
- if ( mode == MO_ADVSPEED ) return m_linMotion.advanceSpeed.x;
- if ( mode == MO_RECSPEED ) return m_linMotion.recedeSpeed.x;
- if ( mode == MO_MOTSPEED ) return m_linMotion.motorSpeed.x;
- if ( mode == MO_CURSPEED ) return m_linMotion.currentSpeed.x;
- if ( mode == MO_REASPEED ) return m_linMotion.realSpeed.x;
- return 0.0f;
-}
-
-// Specifies the speed of elevation.
-
-void CPhysics::SetLinMotionY(PhysicsMode mode, float value)
-{
- if ( mode == MO_ADVACCEL ) m_linMotion.advanceAccel.y = value;
- if ( mode == MO_RECACCEL ) m_linMotion.recedeAccel.y = value;
- if ( mode == MO_STOACCEL ) m_linMotion.stopAccel.y = value;
- if ( mode == MO_TERSPEED ) m_linMotion.terrainSpeed.y = value;
- if ( mode == MO_TERSLIDE ) m_linMotion.terrainSlide.y = value;
- if ( mode == MO_MOTACCEL ) m_linMotion.motorAccel.y = value;
- if ( mode == MO_TERFORCE ) m_linMotion.terrainForce.y = value;
- if ( mode == MO_ADVSPEED ) m_linMotion.advanceSpeed.y = value;
- if ( mode == MO_RECSPEED ) m_linMotion.recedeSpeed.y = value;
- if ( mode == MO_MOTSPEED ) m_linMotion.motorSpeed.y = value;
- if ( mode == MO_CURSPEED ) m_linMotion.currentSpeed.y = value;
- if ( mode == MO_REASPEED ) m_linMotion.realSpeed.y = value;
-}
-
-float CPhysics::RetLinMotionY(PhysicsMode mode)
-{
- if ( mode == MO_ADVACCEL ) return m_linMotion.advanceAccel.y;
- if ( mode == MO_RECACCEL ) return m_linMotion.recedeAccel.y;
- if ( mode == MO_STOACCEL ) return m_linMotion.stopAccel.y;
- if ( mode == MO_TERSPEED ) return m_linMotion.terrainSpeed.y;
- if ( mode == MO_TERSLIDE ) return m_linMotion.terrainSlide.y;
- if ( mode == MO_MOTACCEL ) return m_linMotion.motorAccel.y;
- if ( mode == MO_TERFORCE ) return m_linMotion.terrainForce.y;
- if ( mode == MO_ADVSPEED ) return m_linMotion.advanceSpeed.y;
- if ( mode == MO_RECSPEED ) return m_linMotion.recedeSpeed.y;
- if ( mode == MO_MOTSPEED ) return m_linMotion.motorSpeed.y;
- if ( mode == MO_CURSPEED ) return m_linMotion.currentSpeed.y;
- if ( mode == MO_REASPEED ) return m_linMotion.realSpeed.y;
- return 0.0f;
-}
-
-// Specifies the velocity perpendicular to the direction of travel.
-
-void CPhysics::SetLinMotionZ(PhysicsMode mode, float value)
-{
- if ( mode == MO_ADVACCEL ) m_linMotion.advanceAccel.z = value;
- if ( mode == MO_RECACCEL ) m_linMotion.recedeAccel.z = value;
- if ( mode == MO_STOACCEL ) m_linMotion.stopAccel.z = value;
- if ( mode == MO_TERSPEED ) m_linMotion.terrainSpeed.z = value;
- if ( mode == MO_TERSLIDE ) m_linMotion.terrainSlide.z = value;
- if ( mode == MO_MOTACCEL ) m_linMotion.motorAccel.z = value;
- if ( mode == MO_TERFORCE ) m_linMotion.terrainForce.z = value;
- if ( mode == MO_ADVSPEED ) m_linMotion.advanceSpeed.z = value;
- if ( mode == MO_RECSPEED ) m_linMotion.recedeSpeed.z = value;
- if ( mode == MO_MOTSPEED ) m_linMotion.motorSpeed.z = value;
- if ( mode == MO_CURSPEED ) m_linMotion.currentSpeed.z = value;
- if ( mode == MO_REASPEED ) m_linMotion.realSpeed.z = value;
-}
-
-float CPhysics::RetLinMotionZ(PhysicsMode mode)
-{
- if ( mode == MO_ADVACCEL ) return m_linMotion.advanceAccel.z;
- if ( mode == MO_RECACCEL ) return m_linMotion.recedeAccel.z;
- if ( mode == MO_STOACCEL ) return m_linMotion.stopAccel.z;
- if ( mode == MO_TERSPEED ) return m_linMotion.terrainSpeed.z;
- if ( mode == MO_TERSLIDE ) return m_linMotion.terrainSlide.z;
- if ( mode == MO_MOTACCEL ) return m_linMotion.motorAccel.z;
- if ( mode == MO_TERFORCE ) return m_linMotion.terrainForce.z;
- if ( mode == MO_ADVSPEED ) return m_linMotion.advanceSpeed.z;
- if ( mode == MO_RECSPEED ) return m_linMotion.recedeSpeed.z;
- if ( mode == MO_MOTSPEED ) return m_linMotion.motorSpeed.z;
- if ( mode == MO_CURSPEED ) return m_linMotion.currentSpeed.z;
- if ( mode == MO_REASPEED ) return m_linMotion.realSpeed.z;
- return 0.0f;
-}
-
-// Specifies the rotation around the axis of walk.
-
-void CPhysics::SetCirMotion(PhysicsMode mode, Math::Vector value)
-{
- if ( mode == MO_ADVACCEL ) m_cirMotion.advanceAccel = value;
- if ( mode == MO_RECACCEL ) m_cirMotion.recedeAccel = value;
- if ( mode == MO_STOACCEL ) m_cirMotion.stopAccel = value;
- if ( mode == MO_TERSPEED ) m_cirMotion.terrainSpeed = value;
- if ( mode == MO_TERSLIDE ) m_cirMotion.terrainSlide = value;
- if ( mode == MO_MOTACCEL ) m_cirMotion.motorAccel = value;
- if ( mode == MO_TERFORCE ) m_cirMotion.terrainForce = value;
- if ( mode == MO_ADVSPEED ) m_cirMotion.advanceSpeed = value;
- if ( mode == MO_RECSPEED ) m_cirMotion.recedeSpeed = value;
- if ( mode == MO_MOTSPEED ) m_cirMotion.motorSpeed = value;
- if ( mode == MO_CURSPEED ) m_cirMotion.currentSpeed = value;
- if ( mode == MO_REASPEED ) m_cirMotion.realSpeed = value;
-}
-
-Math::Vector CPhysics::RetCirMotion(PhysicsMode mode)
-{
- if ( mode == MO_ADVACCEL ) return m_cirMotion.advanceAccel;
- if ( mode == MO_RECACCEL ) return m_cirMotion.recedeAccel;
- if ( mode == MO_STOACCEL ) return m_cirMotion.stopAccel;
- if ( mode == MO_TERSPEED ) return m_cirMotion.terrainSpeed;
- if ( mode == MO_TERSLIDE ) return m_cirMotion.terrainSlide;
- if ( mode == MO_MOTACCEL ) return m_cirMotion.motorAccel;
- if ( mode == MO_TERFORCE ) return m_cirMotion.terrainForce;
- if ( mode == MO_ADVSPEED ) return m_cirMotion.advanceSpeed;
- if ( mode == MO_RECSPEED ) return m_cirMotion.recedeSpeed;
- if ( mode == MO_MOTSPEED ) return m_cirMotion.motorSpeed;
- if ( mode == MO_CURSPEED ) return m_cirMotion.currentSpeed;
- if ( mode == MO_REASPEED ) return m_cirMotion.realSpeed;
- return Math::Vector(0.0f, 0.0f, 0.0f);
-}
-
-void CPhysics::SetCirMotionX(PhysicsMode mode, float value)
-{
- if ( mode == MO_ADVACCEL ) m_cirMotion.advanceAccel.x = value;
- if ( mode == MO_RECACCEL ) m_cirMotion.recedeAccel.x = value;
- if ( mode == MO_STOACCEL ) m_cirMotion.stopAccel.x = value;
- if ( mode == MO_TERSPEED ) m_cirMotion.terrainSpeed.x = value;
- if ( mode == MO_TERSLIDE ) m_cirMotion.terrainSlide.x = value;
- if ( mode == MO_MOTACCEL ) m_cirMotion.motorAccel.x = value;
- if ( mode == MO_TERFORCE ) m_cirMotion.terrainForce.x = value;
- if ( mode == MO_ADVSPEED ) m_cirMotion.advanceSpeed.x = value;
- if ( mode == MO_RECSPEED ) m_cirMotion.recedeSpeed.x = value;
- if ( mode == MO_MOTSPEED ) m_cirMotion.motorSpeed.x = value;
- if ( mode == MO_CURSPEED ) m_cirMotion.currentSpeed.x = value;
- if ( mode == MO_REASPEED ) m_cirMotion.realSpeed.x = value;
-}
-
-float CPhysics::RetCirMotionX(PhysicsMode mode)
-{
- if ( mode == MO_ADVACCEL ) return m_cirMotion.advanceAccel.x;
- if ( mode == MO_RECACCEL ) return m_cirMotion.recedeAccel.x;
- if ( mode == MO_STOACCEL ) return m_cirMotion.stopAccel.x;
- if ( mode == MO_TERSPEED ) return m_cirMotion.terrainSpeed.x;
- if ( mode == MO_TERSLIDE ) return m_cirMotion.terrainSlide.x;
- if ( mode == MO_MOTACCEL ) return m_cirMotion.motorAccel.x;
- if ( mode == MO_TERFORCE ) return m_cirMotion.terrainForce.x;
- if ( mode == MO_ADVSPEED ) return m_cirMotion.advanceSpeed.x;
- if ( mode == MO_RECSPEED ) return m_cirMotion.recedeSpeed.x;
- if ( mode == MO_MOTSPEED ) return m_cirMotion.motorSpeed.x;
- if ( mode == MO_CURSPEED ) return m_cirMotion.currentSpeed.x;
- if ( mode == MO_REASPEED ) return m_cirMotion.realSpeed.x;
- return 0.0f;
-}
-
-// Specifies the rotation direction.
-
-void CPhysics::SetCirMotionY(PhysicsMode mode, float value)
-{
- if ( mode == MO_ADVACCEL ) m_cirMotion.advanceAccel.y = value;
- if ( mode == MO_RECACCEL ) m_cirMotion.recedeAccel.y = value;
- if ( mode == MO_STOACCEL ) m_cirMotion.stopAccel.y = value;
- if ( mode == MO_TERSPEED ) m_cirMotion.terrainSpeed.y = value;
- if ( mode == MO_TERSLIDE ) m_cirMotion.terrainSlide.y = value;
- if ( mode == MO_MOTACCEL ) m_cirMotion.motorAccel.y = value;
- if ( mode == MO_TERFORCE ) m_cirMotion.terrainForce.y = value;
- if ( mode == MO_ADVSPEED ) m_cirMotion.advanceSpeed.y = value;
- if ( mode == MO_RECSPEED ) m_cirMotion.recedeSpeed.y = value;
- if ( mode == MO_MOTSPEED ) m_cirMotion.motorSpeed.y = value;
- if ( mode == MO_CURSPEED ) m_cirMotion.currentSpeed.y = value;
- if ( mode == MO_REASPEED ) m_cirMotion.realSpeed.y = value;
-}
-
-float CPhysics::RetCirMotionY(PhysicsMode mode)
-{
- if ( mode == MO_ADVACCEL ) return m_cirMotion.advanceAccel.y;
- if ( mode == MO_RECACCEL ) return m_cirMotion.recedeAccel.y;
- if ( mode == MO_STOACCEL ) return m_cirMotion.stopAccel.y;
- if ( mode == MO_TERSPEED ) return m_cirMotion.terrainSpeed.y;
- if ( mode == MO_TERSLIDE ) return m_cirMotion.terrainSlide.y;
- if ( mode == MO_MOTACCEL ) return m_cirMotion.motorAccel.y;
- if ( mode == MO_TERFORCE ) return m_cirMotion.terrainForce.y;
- if ( mode == MO_ADVSPEED ) return m_cirMotion.advanceSpeed.y;
- if ( mode == MO_RECSPEED ) return m_cirMotion.recedeSpeed.y;
- if ( mode == MO_MOTSPEED ) return m_cirMotion.motorSpeed.y;
- if ( mode == MO_CURSPEED ) return m_cirMotion.currentSpeed.y;
- if ( mode == MO_REASPEED ) return m_cirMotion.realSpeed.y;
- return 0.0f;
-}
-
-// Specifies the rotation up/down.
-
-void CPhysics::SetCirMotionZ(PhysicsMode mode, float value)
-{
- if ( mode == MO_ADVACCEL ) m_cirMotion.advanceAccel.z = value;
- if ( mode == MO_RECACCEL ) m_cirMotion.recedeAccel.z = value;
- if ( mode == MO_STOACCEL ) m_cirMotion.stopAccel.z = value;
- if ( mode == MO_TERSPEED ) m_cirMotion.terrainSpeed.z = value;
- if ( mode == MO_TERSLIDE ) m_cirMotion.terrainSlide.z = value;
- if ( mode == MO_MOTACCEL ) m_cirMotion.motorAccel.z = value;
- if ( mode == MO_TERFORCE ) m_cirMotion.terrainForce.z = value;
- if ( mode == MO_ADVSPEED ) m_cirMotion.advanceSpeed.z = value;
- if ( mode == MO_RECSPEED ) m_cirMotion.recedeSpeed.z = value;
- if ( mode == MO_MOTSPEED ) m_cirMotion.motorSpeed.z = value;
- if ( mode == MO_CURSPEED ) m_cirMotion.currentSpeed.z = value;
- if ( mode == MO_REASPEED ) m_cirMotion.realSpeed.z = value;
-}
-
-float CPhysics::RetCirMotionZ(PhysicsMode mode)
-{
- if ( mode == MO_ADVACCEL ) return m_cirMotion.advanceAccel.z;
- if ( mode == MO_RECACCEL ) return m_cirMotion.recedeAccel.z;
- if ( mode == MO_STOACCEL ) return m_cirMotion.stopAccel.z;
- if ( mode == MO_TERSPEED ) return m_cirMotion.terrainSpeed.z;
- if ( mode == MO_TERSLIDE ) return m_cirMotion.terrainSlide.z;
- if ( mode == MO_MOTACCEL ) return m_cirMotion.motorAccel.z;
- if ( mode == MO_TERFORCE ) return m_cirMotion.terrainForce.z;
- if ( mode == MO_ADVSPEED ) return m_cirMotion.advanceSpeed.z;
- if ( mode == MO_RECSPEED ) return m_cirMotion.recedeSpeed.z;
- if ( mode == MO_MOTSPEED ) return m_cirMotion.motorSpeed.z;
- if ( mode == MO_CURSPEED ) return m_cirMotion.currentSpeed.z;
- if ( mode == MO_REASPEED ) return m_cirMotion.realSpeed.z;
- return 0.0f;
-}
-
-
-// Returns the linear distance braking.
-//
-// v*v
-// d = -----
-// 2a
-
-float CPhysics::RetLinStopLength(PhysicsMode sMode, PhysicsMode aMode)
-{
- float speed, accel;
-
- speed = RetLinMotionX(sMode); // MO_ADVSPEED/MO_RECSPEED
- accel = RetLinMotionX(aMode); // MO_ADVACCEL/MO_RECACCEL/MO_STOACCEL
-
- if ( m_type == TYPE_FLYING && m_bLand ) // flying on the ground?
- {
- speed /= LANDING_SPEED;
- accel *= LANDING_ACCEL;
- }
-
- return (speed*speed) / (accel*2.0f);
-}
-
-// Returns the angle of circular braking.
-
-float CPhysics::RetCirStopLength()
-{
- return m_cirMotion.advanceSpeed.y * m_cirMotion.advanceSpeed.y /
- m_cirMotion.stopAccel.y / 2.0f;
-}
-
-// Returns the length advanced into a second, on the ground, maximum speed.
-
-float CPhysics::RetLinMaxLength(float dir)
-{
- float dist;
-
- if ( dir > 0.0f ) dist = m_linMotion.advanceSpeed.x;
- else dist = m_linMotion.recedeSpeed.x;
-
- if ( m_type == TYPE_FLYING )
- {
- dist /= 5.0f;
- }
-
- return dist;
-}
-
-// Returns the time needed to travel some distance.
-
-float CPhysics::RetLinTimeLength(float dist, float dir)
-{
- float accel, decel, dps;
-
- if ( dir > 0.0f )
- {
- accel = RetLinStopLength(MO_ADVSPEED, MO_ADVACCEL);
- decel = RetLinStopLength(MO_ADVSPEED, MO_STOACCEL);
- }
- else
- {
- accel = RetLinStopLength(MO_RECSPEED, MO_RECACCEL);
- decel = RetLinStopLength(MO_RECSPEED, MO_STOACCEL);
- }
-
- dps = RetLinMaxLength(dir);
-
- return (dist+accel+decel)/dps;
-}
-
-// Returns the length for a forward travel some distance, taking into account the accelerations / decelerations.
-
-float CPhysics::RetLinLength(float dist)
-{
- float accDist, desDist;
-
- if ( dist > 0.0f )
- {
- accDist = RetLinStopLength(MO_ADVSPEED, MO_ADVACCEL);
- desDist = RetLinStopLength(MO_ADVSPEED, MO_STOACCEL);
-
- if ( dist > accDist+desDist )
- {
- return dist-desDist;
- }
-
- return dist*m_linMotion.stopAccel.x /
- (m_linMotion.advanceAccel.x+m_linMotion.stopAccel.x);
- }
- else
- {
- dist = -dist;
- accDist = RetLinStopLength(MO_RECSPEED, MO_RECACCEL);
- desDist = RetLinStopLength(MO_RECSPEED, MO_STOACCEL);
-
- if ( dist > accDist+desDist )
- {
- return dist-desDist;
- }
-
- return dist*m_linMotion.stopAccel.x /
- (m_linMotion.recedeAccel.x+m_linMotion.stopAccel.x);
- }
-}
-
-
-// Management of an event.
-// Returns false if the object is destroyed.
-
-bool CPhysics::EventProcess(const Event &event)
-{
- if ( !m_object->RetEnable() ) return true;
-
- if ( m_brain != 0 )
- {
- m_brain->EventProcess(event);
- }
-
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
- return true;
-}
-
-
-// Updates instructions for the motor speed.
-
-void CPhysics::MotorUpdate(float aTime, float rTime)
-{
- ObjectType type;
- CObject* power;
- Math::Vector pos, motorSpeed;
- float energy, speed, factor, h;
-
- type = m_object->RetType();
-
- motorSpeed = m_motorSpeed;
-
- if ( type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ||
- type == OBJECT_APOLLO2 ||
- type == OBJECT_MOBILEdr )
- {
- power = 0;
- }
- else if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH )
- {
- power = 0;
- if ( m_object->RetFret() != 0 && // carries something?
- !m_object->RetCargo() )
- {
- motorSpeed.x *= 0.7f; // forward more slowly
- motorSpeed.z *= 0.5f;
- motorSpeed.y = -1.0f; // grave
- }
- if ( m_bSwim )
- {
- if ( m_bLand ) // deep in the water?
- {
- motorSpeed.x *= 0.4f; // forward more slowly
- motorSpeed.z *= 0.5f;
- motorSpeed.y *= 0.5f;
-
- if ( m_object->RetFret() != 0 ) // carries something?
- {
- motorSpeed.x *= 0.2f;
- motorSpeed.z *= 0.9f;
- motorSpeed.y *= 0.2f;
- }
- }
- else // swimming?
- {
- motorSpeed.x *= 0.2f; // forward more slowly
- motorSpeed.z *= 0.5f;
- motorSpeed.y *= 0.2f;
- }
- }
- }
- else
- {
- power = m_object->RetPower(); // searches for the object battery uses
- if ( power == 0 || power->RetEnergy() == 0.0f ) // no battery or flat?
- {
- motorSpeed.x = 0.0f;
- motorSpeed.z = 0.0f;
- if ( m_bFreeze || m_bLand )
- {
- motorSpeed.y = 0.0f; // immobile
- }
- else
- {
- motorSpeed.y = -1.0f; // grave
- }
- SetMotor(false);
- }
- }
-
- if ( m_object->RetDead() ) // dead man?
- {
- motorSpeed.x = 0.0f;
- motorSpeed.z = 0.0f;
- if ( m_motion->RetAction() == MHS_DEADw ) // drowned?
- {
- motorSpeed.y = 0.0f; // this is MHS_DEADw going back
- }
- else
- {
- motorSpeed.y = -1.0f; // grave
- }
- SetMotor(false);
- }
-
- if ( m_type == TYPE_FLYING && !m_bLand && motorSpeed.y > 0.0f )
- {
- pos = m_object->RetPosition(0);
- h = m_terrain->RetFlyingLimit(pos, type==OBJECT_BEE);
- h += m_object->RetCharacter()->height;
- if ( pos.y > h-40.0f ) // almost at the top?
- {
- factor = 1.0f-(pos.y-(h-40.0f))/40.0f;
- if ( factor < -1.0f ) factor = -1.0f;
- if ( factor > 1.0f ) factor = 1.0f;
- motorSpeed.y *= factor; // limit the rate of rise
- }
- }
-
- if ( type != OBJECT_BEE &&
- m_object->RetRange() > 0.0f ) // limited flight range?
- {
- if ( m_bLand || m_bSwim || m_bObstacle ) // on the ground or in the water?
- {
- factor = 1.0f;
- if ( m_bObstacle ) factor = 3.0f; // in order to leave!
- if ( m_bSwim ) factor = 3.0f; // cools faster in water
- m_reactorRange += rTime*(1.0f/5.0f)*factor;
- if ( m_reactorRange > 1.0f )
- {
- m_reactorRange = 1.0f;
- if ( m_bLowLevel && m_object->RetSelect() ) // beep cool?
- {
- m_sound->Play(SOUND_INFO, m_object->RetPosition(0), 1.0f, 2.0f);
- m_bLowLevel = false;
- }
- }
- m_bObstacle = false;
- }
- else // in flight?
- {
- m_reactorRange -= rTime*(1.0f/m_object->RetRange());
- if ( m_reactorRange < 0.0f ) m_reactorRange = 0.0f;
- if ( m_reactorRange < 0.5f ) m_bLowLevel = true;
- }
-
- if ( m_reactorRange == 0.0f ) // reactor tilt?
- {
- motorSpeed.y = -1.0f; // grave
- }
- }
-
-//? MotorParticule(aTime);
-
- // Forward/backward.
- if ( motorSpeed.x > 0.0f )
- {
- m_linMotion.motorAccel.x = m_linMotion.advanceAccel.x;
- m_linMotion.motorSpeed.x = m_linMotion.advanceSpeed.x * motorSpeed.x;
- }
- if ( motorSpeed.x < 0.0f )
- {
- m_linMotion.motorAccel.x = m_linMotion.recedeAccel.x;
- m_linMotion.motorSpeed.x = m_linMotion.recedeSpeed.x * motorSpeed.x;
- }
- if ( motorSpeed.x == 0.0f )
- {
- m_linMotion.motorAccel.x = m_linMotion.stopAccel.x;
- m_linMotion.motorSpeed.x = 0.0f;
- }
-
- // Up/down.
- if ( motorSpeed.y > 0.0f )
- {
- m_linMotion.motorAccel.y = m_linMotion.advanceAccel.y;
- m_linMotion.motorSpeed.y = m_linMotion.advanceSpeed.y * motorSpeed.y;
- }
- if ( motorSpeed.y < 0.0f )
- {
- m_linMotion.motorAccel.y = m_linMotion.recedeAccel.y;
- m_linMotion.motorSpeed.y = m_linMotion.recedeSpeed.y * motorSpeed.y;
- }
- if ( motorSpeed.y == 0.0f )
- {
- m_linMotion.motorAccel.y = m_linMotion.stopAccel.y;
- m_linMotion.motorSpeed.y = 0.0f;
- }
-
- // Turn left/right.
- speed = motorSpeed.z;
-//? if ( motorSpeed.x < 0.0f ) speed = -speed; // reverse if running back
-
- if ( motorSpeed.z > 0.0f )
- {
- m_cirMotion.motorAccel.y = m_cirMotion.advanceAccel.y;
- m_cirMotion.motorSpeed.y = m_cirMotion.advanceSpeed.y * speed;
- }
- if ( motorSpeed.z < 0.0f )
- {
- m_cirMotion.motorAccel.y = m_cirMotion.recedeAccel.y;
- m_cirMotion.motorSpeed.y = m_cirMotion.recedeSpeed.y * speed;
- }
- if ( motorSpeed.z == 0.0f )
- {
- m_cirMotion.motorAccel.y = m_cirMotion.stopAccel.y;
- m_cirMotion.motorSpeed.y = 0.0f;
- }
-
- if ( m_type == TYPE_FLYING && m_bLand ) // flying on the ground?
- {
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH )
- {
- factor = LANDING_ACCELh;
- }
- else
- {
- factor = LANDING_ACCEL;
- }
- m_linMotion.motorAccel.x = m_linMotion.stopAccel.x*factor;
- m_cirMotion.motorAccel.y = m_cirMotion.stopAccel.y*factor;
-
- pos = m_object->RetPosition(0);
- h = m_terrain->RetFlyingLimit(pos, type==OBJECT_BEE);
- h += m_object->RetCharacter()->height;
- if ( motorSpeed.y > 0.0f && m_reactorRange > 0.1f && pos.y < h )
- {
- m_bLand = false; // take off
- SetMotor(true);
- pos.y += 0.05f; // small initial height (startup)
- m_object->SetPosition(0, pos);
- }
- }
-
- if ( m_type == TYPE_ROLLING )
- {
- if ( motorSpeed.x == 0.0f &&
- motorSpeed.z == 0.0f )
- {
- SetMotor(false);
- }
- else
- {
- SetMotor(true);
- }
- }
-
- if ( power != 0 ) // battery transported?
- {
- factor = 1.0f;
- if ( type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEii ) factor = 0.5f;
-
- factor /= power->RetCapacity();
-
- energy = power->RetEnergy();
- energy -= fabs(motorSpeed.x)*rTime*factor*0.005f;
- energy -= fabs(motorSpeed.z)*rTime*factor*0.005f;
-
- if ( m_type == TYPE_FLYING && motorSpeed.y > 0.0f )
- {
- energy -= motorSpeed.y*rTime*factor*0.01f;
- }
- if ( energy < 0.0f ) energy = 0.0f;
- power->SetEnergy(energy);
- }
-}
-
-
-// Updates the effects of vibration and tilt.
-
-void CPhysics::EffectUpdate(float aTime, float rTime)
-{
- Character* character;
- Math::Vector vibLin, vibCir, incl;
- float speedLin, speedCir, accel;
- ObjectType type;
- bool bOnBoard;
-
- if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return;
-
- type = m_object->RetType();
- character = m_object->RetCharacter();
-
- bOnBoard = false;
- if ( m_object->RetSelect() &&
- m_camera->RetType() == CAMERA_ONBOARD )
- {
- bOnBoard = true;
- }
-
- vibLin = m_motion->RetLinVibration();
- vibCir = m_motion->RetCirVibration();
- incl = m_motion->RetInclinaison();
-
- if ( type == OBJECT_HUMAN || // human?
- type == OBJECT_TECH )
- {
- if ( !m_bLand && !m_bSwim ) // in flight?
- {
- vibLin.y = sinf(aTime*2.00f)*0.5f+
- sinf(aTime*2.11f)*0.3f;
-
- vibCir.z = sinf(aTime*Math::PI* 2.01f)*(Math::PI/150.0f)+
- sinf(aTime*Math::PI* 2.51f)*(Math::PI/200.0f)+
- sinf(aTime*Math::PI*19.01f)*(Math::PI/400.0f);
-
- vibCir.x = sinf(aTime*Math::PI* 2.03f)*(Math::PI/150.0f)+
- sinf(aTime*Math::PI* 2.52f)*(Math::PI/200.0f)+
- sinf(aTime*Math::PI*19.53f)*(Math::PI/400.0f);
-
- speedLin = m_linMotion.realSpeed.x / m_linMotion.advanceSpeed.x;
- speedCir = m_cirMotion.realSpeed.y / m_cirMotion.advanceSpeed.y;
- incl.x = -speedLin*speedCir*0.5f; // looks if turn
-
-//? speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.5f;
- speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.2f;
- speedLin /= m_linMotion.advanceSpeed.x;
- m_linMotion.finalInclin.z = speedLin*1.4f;
- if ( incl.z < m_linMotion.finalInclin.z )
- {
- incl.z += rTime*0.4f;
- if ( incl.z > m_linMotion.finalInclin.z )
- {
- incl.z = m_linMotion.finalInclin.z;
- }
- }
- else if ( incl.z > m_linMotion.finalInclin.z )
- {
- incl.z -= rTime*0.4f;
- if ( incl.z < m_linMotion.finalInclin.z )
- {
- incl.z = m_linMotion.finalInclin.z;
- }
- }
-
- vibLin *= m_linVibrationFactor;
- vibCir *= m_cirVibrationFactor;
- incl *= m_inclinaisonFactor;
-
- m_motion->SetLinVibration(vibLin);
- m_motion->SetCirVibration(vibCir);
- m_motion->SetInclinaison(incl);
- }
- else if ( m_bSwim ) // swimming?
- {
- vibLin.y = sinf(aTime*2.00f)*0.5f+
- sinf(aTime*2.11f)*0.3f;
-
- vibCir.z = sinf(aTime*Math::PI* 2.01f)*(Math::PI/150.0f)+
- sinf(aTime*Math::PI* 2.51f)*(Math::PI/200.0f)+
-//? sinf(aTime*Math::PI*19.01f)*(Math::PI/400.0f)-Math::PI/2.0f;
- sinf(aTime*Math::PI*19.01f)*(Math::PI/400.0f);
-
- vibCir.x = sinf(aTime*Math::PI* 2.03f)*(Math::PI/150.0f)+
- sinf(aTime*Math::PI* 2.52f)*(Math::PI/200.0f)+
- sinf(aTime*Math::PI*19.53f)*(Math::PI/400.0f);
-
- speedLin = m_linMotion.realSpeed.x / m_linMotion.advanceSpeed.x;
- speedCir = m_cirMotion.realSpeed.y / m_cirMotion.advanceSpeed.y;
- incl.x = -speedLin*speedCir*5.0f; // looks if turn
-
-//? speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.5f;
- speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.2f;
- speedLin /= m_linMotion.advanceSpeed.x;
- m_linMotion.finalInclin.z = speedLin*1.4f;
- if ( incl.z < m_linMotion.finalInclin.z )
- {
- incl.z += rTime*0.4f;
- if ( incl.z > m_linMotion.finalInclin.z )
- {
- incl.z = m_linMotion.finalInclin.z;
- }
- }
- else if ( incl.z > m_linMotion.finalInclin.z )
- {
- incl.z -= rTime*0.4f;
- if ( incl.z < m_linMotion.finalInclin.z )
- {
- incl.z = m_linMotion.finalInclin.z;
- }
- }
-
- if ( m_linMotion.realSpeed.y > 0.0f ) // up?
- {
- vibCir.z += m_linMotion.realSpeed.y*0.05f;
- }
- else // down?
- {
- vibCir.z += m_linMotion.realSpeed.y*0.12f;
- }
- vibCir.z -= Math::PI*0.4f;
-
- vibLin *= m_linVibrationFactor;
- vibCir *= m_cirVibrationFactor;
- incl *= m_inclinaisonFactor;
-
- m_motion->SetLinVibration(vibLin);
- m_motion->SetCirVibration(vibCir);
- m_motion->SetInclinaison(incl);
- }
- else
- {
- m_motion->SetLinVibration(Math::Vector(0.0f, 0.0f, 0.0f));
-//? m_motion->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
-//? m_motion->SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
- }
- }
-
- if ( type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_APOLLO2 ) // wheels?
- {
- speedLin = m_linMotion.realSpeed.x / m_linMotion.advanceSpeed.x;
- speedCir = m_cirMotion.realSpeed.y / m_cirMotion.advanceSpeed.y;
- incl.x = speedLin*speedCir*0.20f; // looks if turn
- if ( type == OBJECT_APOLLO2 ) incl.x *= 0.25f;
-
- speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x;
- speedLin /= m_linMotion.advanceSpeed.x;
- if ( speedLin > 1.0f ) speedLin = 1.0f;
- m_linMotion.finalInclin.z = -speedLin*0.30f;
- accel = (0.40f-fabs(incl.z))*4.0f;
- if ( incl.z < m_linMotion.finalInclin.z )
- {
- incl.z += rTime*accel;
- if ( incl.z > m_linMotion.finalInclin.z )
- {
- incl.z = m_linMotion.finalInclin.z;
- }
- }
- else if ( incl.z > m_linMotion.finalInclin.z )
- {
- incl.z -= rTime*accel;
- if ( incl.z < m_linMotion.finalInclin.z )
- {
- incl.z = m_linMotion.finalInclin.z;
- }
- }
- if ( bOnBoard ) incl.z *= 0.1f;
- if ( type == OBJECT_APOLLO2 ) incl.z *= 0.25f;
- m_object->SetInclinaison(incl);
-
- vibLin.x = 0.0f;
- vibLin.z = 0.0f;
- vibLin.y = fabs(character->wheelFront*sinf(incl.z))*0.8f +
- fabs(character->wheelRight*sinf(incl.x))*0.5f;
- m_motion->SetLinVibration(vibLin);
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEft ) // fliyng?
- {
- if ( m_bLand ) // on the ground?
- {
- m_motion->SetLinVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- m_motion->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
- m_motion->SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
- }
- else // in flight?
- {
- vibLin.y = sinf(aTime*2.00f)*0.5f+
- sinf(aTime*2.11f)*0.3f;
-
- vibCir.z = sinf(aTime*Math::PI* 2.01f)*(Math::PI/150.0f)+
- sinf(aTime*Math::PI* 2.51f)*(Math::PI/200.0f)+
- sinf(aTime*Math::PI*19.01f)*(Math::PI/400.0f);
-
- vibCir.x = sinf(aTime*Math::PI* 2.03f)*(Math::PI/150.0f)+
- sinf(aTime*Math::PI* 2.52f)*(Math::PI/200.0f)+
- sinf(aTime*Math::PI*19.53f)*(Math::PI/400.0f);
-
- if ( bOnBoard ) vibCir *= 0.4f;
-
- speedLin = m_linMotion.realSpeed.x / m_linMotion.advanceSpeed.x;
- speedCir = m_cirMotion.realSpeed.y / m_cirMotion.advanceSpeed.y;
- incl.x = -speedLin*speedCir*0.5f; // looks if turn
-
-//? speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.5f;
- speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.2f;
- speedLin /= m_linMotion.advanceSpeed.x;
- m_linMotion.finalInclin.z = speedLin*0.8f;
- if ( incl.z < m_linMotion.finalInclin.z )
- {
- incl.z += rTime*0.4f;
- if ( incl.z > m_linMotion.finalInclin.z )
- {
- incl.z = m_linMotion.finalInclin.z;
- }
- }
- else if ( incl.z > m_linMotion.finalInclin.z )
- {
- incl.z -= rTime*0.4f;
- if ( incl.z < m_linMotion.finalInclin.z )
- {
- incl.z = m_linMotion.finalInclin.z;
- }
- }
-//? if ( bOnBoard ) incl.z *= 0.5f;
-
- vibLin *= m_linVibrationFactor;
- vibCir *= m_cirVibrationFactor;
- incl *= m_inclinaisonFactor;
-
- m_motion->SetLinVibration(vibLin);
- m_motion->SetCirVibration(vibCir);
- m_motion->SetInclinaison(incl);
- }
- }
-
- if ( type == OBJECT_BEE ) // bee?
- {
- if ( !m_bLand ) // in flight?
- {
- vibLin.y = sinf(aTime*2.00f)*0.5f+
- sinf(aTime*2.11f)*0.3f;
-
- vibCir.z = (Math::Rand()-0.5f)*0.1f+
- sinf(aTime*Math::PI* 2.01f)*(Math::PI/150.0f)+
- sinf(aTime*Math::PI* 2.51f)*(Math::PI/200.0f)+
- sinf(aTime*Math::PI*19.01f)*(Math::PI/400.0f);
-
- vibCir.x = (Math::Rand()-0.5f)*0.1f+
- sinf(aTime*Math::PI* 2.03f)*(Math::PI/150.0f)+
- sinf(aTime*Math::PI* 2.52f)*(Math::PI/200.0f)+
- sinf(aTime*Math::PI*19.53f)*(Math::PI/400.0f);
-
- speedLin = m_linMotion.realSpeed.x / m_linMotion.advanceSpeed.x;
- speedCir = m_cirMotion.realSpeed.y / m_cirMotion.advanceSpeed.y;
- incl.x = -speedLin*speedCir*1.5f; // looks if turn
-
-//? speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.5f;
- speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.2f;
- speedLin /= m_linMotion.advanceSpeed.x;
- m_linMotion.finalInclin.z = speedLin*1.4f;
- if ( incl.z < m_linMotion.finalInclin.z )
- {
- incl.z += rTime*1.6f;
- if ( incl.z > m_linMotion.finalInclin.z )
- {
- incl.z = m_linMotion.finalInclin.z;
- }
- }
- else if ( incl.z > m_linMotion.finalInclin.z )
- {
- incl.z -= rTime*1.6f;
- if ( incl.z < m_linMotion.finalInclin.z )
- {
- incl.z = m_linMotion.finalInclin.z;
- }
- }
-
- vibLin *= m_linVibrationFactor;
- vibCir *= m_cirVibrationFactor;
- incl *= m_inclinaisonFactor;
-
- m_motion->SetLinVibration(vibLin);
- m_motion->SetCirVibration(vibCir);
- m_motion->SetInclinaison(incl);
- }
- }
-}
-
-
-// Updates structure Motion.
-
-void CPhysics::UpdateMotionStruct(float rTime, Motion &motion)
-{
- float speed, motor;
-
- // Management for the coordinate x.
- speed = motion.currentSpeed.x;
- motor = motion.motorSpeed.x * m_inclinaisonFactor;
- if ( speed < motor )
- {
- speed += rTime*motion.motorAccel.x; // accelerates
- if ( speed > motor )
- {
- speed = motor; // does not exceed the speed
- }
- }
- if ( speed > motor )
- {
- speed -= rTime*motion.motorAccel.x; // decelerates
- if ( speed < motor )
- {
- speed = motor; // does not exceed the speed
- }
- }
- motion.currentSpeed.x = speed;
- motion.realSpeed.x = speed;
-
- if ( fabs(motion.terrainSpeed.x) > motion.terrainSlide.x )
- {
- if ( motion.terrainSpeed.x > 0 )
- {
- speed = motion.terrainSpeed.x - motion.terrainSlide.x;
- }
- else
- {
- speed = motion.terrainSpeed.x + motion.terrainSlide.x;
- }
- motion.realSpeed.x += speed;
- }
-
- // Management for the coordinate y.
- speed = motion.currentSpeed.y;
- motor = motion.motorSpeed.y; // unlimited speed!
- if ( speed < motor )
- {
- speed += rTime*motion.motorAccel.y; // accelerates
- if ( speed > motor )
- {
- speed = motor; // does not exceed the speed
- }
- }
- if ( speed > motor )
- {
- speed -= rTime*motion.motorAccel.y; // decelerates
- if ( speed < motor )
- {
- speed = motor; // does not exceed the speed
- }
- }
- motion.currentSpeed.y = speed;
- motion.realSpeed.y = speed;
-
- if ( fabs(motion.terrainSpeed.y) > motion.terrainSlide.y )
- {
- if ( motion.terrainSpeed.y > 0 )
- {
- speed = motion.terrainSpeed.y - motion.terrainSlide.y;
- }
- else
- {
- speed = motion.terrainSpeed.y + motion.terrainSlide.y;
- }
- motion.realSpeed.y += speed;
- }
-
- // Management for the coordinate z.
- speed = motion.currentSpeed.z;
- motor = motion.motorSpeed.z * m_inclinaisonFactor;
- if ( speed < motor )
- {
- speed += rTime*motion.motorAccel.z; // accelerates
- if ( speed > motor )
- {
- speed = motor; // does not exceed the speed
- }
- }
- if ( speed > motor )
- {
- speed -= rTime*motion.motorAccel.z; // decelerates
- if ( speed < motor )
- {
- speed = motor; // does not exceed the speed
- }
- }
- motion.currentSpeed.z = speed;
- motion.realSpeed.z = speed;
-
- if ( fabs(motion.terrainSpeed.z) > motion.terrainSlide.z )
- {
- if ( motion.terrainSpeed.z > 0 )
- {
- speed = motion.terrainSpeed.z - motion.terrainSlide.z;
- }
- else
- {
- speed = motion.terrainSpeed.z + motion.terrainSlide.z;
- }
- motion.realSpeed.z += speed;
- }
-}
-
-
-// Makes physics evolve as time elapsed.
-// Returns false if the object is destroyed.
-//
-// a: acceleration
-// v1: velocity at time t1
-// v2: velocity at time t2
-// dt: time elapsed since t1, then: dt = t2-t1
-// dd: difference in distance (advance)
-//
-// v2 = v1 + a*dt
-// dd = v2*dt
-
-bool CPhysics::EventFrame(const Event &event)
-{
- ObjectType type;
- Math::Matrix objRotate, matRotate;
- Math::Vector iPos, iAngle, tAngle, pos, newpos, angle, newangle, n;
- float h, w;
- int i;
-
- if ( m_engine->RetPause() ) return true;
-
- m_time += event.rTime;
- m_timeUnderWater += event.rTime;
- m_soundTimeJostle += event.rTime;
-
- type = m_object->RetType();
-
- FrameParticule(m_time, event.rTime);
- MotorUpdate(m_time, event.rTime);
- EffectUpdate(m_time, event.rTime);
- WaterFrame(m_time, event.rTime);
-
- iPos = pos = m_object->RetPosition(0);
- iAngle = angle = m_object->RetAngle(0);
-
- // Accelerate is the descent, brake is the ascent.
- if ( m_bFreeze || m_object->RetDead() )
- {
- m_linMotion.terrainSpeed.x = 0.0f;
- m_linMotion.terrainSpeed.z = 0.0f;
- m_linMotion.terrainSpeed.y = 0.0f;
- }
- else
- {
- tAngle = angle;
- h = m_terrain->RetBuildingFactor(pos);
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH )
- {
- if ( m_linMotion.currentSpeed.x == 0.0f )
- {
- h *= 0.5f; // immobile man -> slippage
- }
- FloorAngle(pos, tAngle); // calculates the angle with the ground
- }
-#if 1
- if ( pos.y < m_water->RetLevel(m_object) ) // underwater?
- {
- h *= 0.5f;
- }
-#endif
-//? m_linMotion.terrainSpeed.x = -tAngle.z*m_linMotion.terrainForce.x*h;
-//? m_linMotion.terrainSpeed.z = tAngle.x*m_linMotion.terrainForce.z*h;
-//? m_linMotion.terrainSpeed.x = -sinf(tAngle.z)*Math::PI*0.5f*m_linMotion.terrainForce.x*h;
-//? m_linMotion.terrainSpeed.z = sinf(tAngle.x)*Math::PI*0.5f*m_linMotion.terrainForce.z*h;
- m_linMotion.terrainSpeed.x = -tanf(tAngle.z)*0.9f*m_linMotion.terrainForce.x*h;
- m_linMotion.terrainSpeed.z = tanf(tAngle.x)*0.9f*m_linMotion.terrainForce.z*h;
- m_linMotion.terrainSpeed.y = 0.0f;
-
- // If the terrain is very steep, do not exaggerate!
- if ( m_linMotion.terrainSpeed.x > 50.0f ) m_linMotion.terrainSpeed.x = 20.0f;
- if ( m_linMotion.terrainSpeed.x < -50.0f ) m_linMotion.terrainSpeed.x = -20.0f;
- if ( m_linMotion.terrainSpeed.z > 50.0f ) m_linMotion.terrainSpeed.z = 20.0f;
- if ( m_linMotion.terrainSpeed.z < -50.0f ) m_linMotion.terrainSpeed.z = -20.0f;
- }
-
- if ( type == OBJECT_BEE && !m_bLand )
- {
- h = m_floorLevel; // ground level
- w = m_water->RetLevel(m_object);
- if ( h < w ) h = w;
- h = pos.y-h-10.0f; // maximum height (*)
- if ( h < 0.0f ) h = 0.0f;
- m_linMotion.terrainSpeed.y = -h*2.5f; // is not above
- }
-
- // (*) High enough to pass over the tower defense (OBJECT_TOWER),
- // but not too much to pass under the cover of the ship (OBJECT_BASE)!
-
- UpdateMotionStruct(event.rTime, m_linMotion);
- UpdateMotionStruct(event.rTime, m_cirMotion);
-
- newangle = angle + event.rTime*m_cirMotion.realSpeed;
- Math::LoadRotationZXYMatrix(matRotate, newangle);
- newpos = event.rTime*m_linMotion.realSpeed;
- newpos = Transform(matRotate, newpos);
- newpos += pos;
-
- m_terrain->LimitPos(newpos);
-
- if ( m_type == TYPE_FLYING && !m_bLand )
- {
- h = m_terrain->RetFlyingLimit(newpos, type==OBJECT_BEE);
- h += m_object->RetCharacter()->height;
- if ( newpos.y > h ) newpos.y = h;
- }
-
- if ( m_bForceUpdate ||
- newpos.x != pos.x ||
- newpos.y != pos.y ||
- newpos.z != pos.z ||
- newangle.x != angle.x ||
- newangle.y != angle.y ||
- newangle.z != angle.z )
- {
- FloorAdapt(m_time, event.rTime, newpos, newangle);
- }
-
- if ( m_bForceUpdate ||
- newpos.x != pos.x ||
- newpos.y != pos.y ||
- newpos.z != pos.z )
- {
- i = ObjectAdapt(newpos, newangle);
- if ( i == 2 ) // object destroyed?
- {
- return false;
- }
- if ( i == 1 ) // immobile object?
- {
- newpos = iPos; // keeps the initial position, but accepts the rotation
- }
- }
-
- if ( newangle.x != angle.x ||
- newangle.y != angle.y ||
- newangle.z != angle.z )
- {
- m_object->SetAngle(0, newangle);
- }
-
- if ( newpos.x != pos.x ||
- newpos.y != pos.y ||
- newpos.z != pos.z )
- {
- m_object->SetPosition(0, newpos);
- }
-
- MotorParticule(m_time, event.rTime);
- SoundMotor(event.rTime);
-
- m_bForceUpdate = false;
-
- return true;
-}
-
-// Starts or stops the engine sounds.
-
-void CPhysics::SoundMotor(float rTime)
-{
- CObject* power;
- ObjectType type;
- float energy;
-
- m_lastSoundInsect -= rTime;
- type = m_object->RetType();
-
- if ( type == OBJECT_MOTHER )
- {
- if ( m_lastSoundInsect <= 0.0f && m_object->RetActif() )
- {
- m_sound->Play(SOUND_INSECTm, m_object->RetPosition(0));
- if ( m_bMotor ) m_lastSoundInsect = 0.4f+Math::Rand()*2.5f;
- else m_lastSoundInsect = 1.5f+Math::Rand()*4.0f;
- }
- }
- else if ( type == OBJECT_ANT )
- {
- if ( m_object->RetBurn() ||
- m_object->RetFixed() )
- {
- if ( m_lastSoundInsect <= 0.0f )
- {
- m_sound->Play(SOUND_INSECTa, m_object->RetPosition(0), 1.0f, 1.5f+Math::Rand()*0.5f);
- m_lastSoundInsect = 0.4f+Math::Rand()*0.6f;
- }
- }
- else if ( m_object->RetActif() )
- {
- if ( m_lastSoundInsect <= 0.0f )
- {
- m_sound->Play(SOUND_INSECTa, m_object->RetPosition(0));
- if ( m_bMotor ) m_lastSoundInsect = 0.4f+Math::Rand()*2.5f;
- else m_lastSoundInsect = 1.5f+Math::Rand()*4.0f;
- }
- }
- }
- else if ( type == OBJECT_BEE )
- {
- if ( m_object->RetActif() )
- {
- if ( m_lastSoundInsect <= 0.0f )
- {
- m_sound->Play(SOUND_INSECTb, m_object->RetPosition(0));
- if ( m_bMotor ) m_lastSoundInsect = 0.4f+Math::Rand()*2.5f;
- else m_lastSoundInsect = 1.5f+Math::Rand()*4.0f;
- }
- }
- else if ( m_object->RetBurn() )
- {
- if ( m_lastSoundInsect <= 0.0f )
- {
- m_sound->Play(SOUND_INSECTb, m_object->RetPosition(0), 1.0f, 1.5f+Math::Rand()*0.5f);
- m_lastSoundInsect = 0.3f+Math::Rand()*0.5f;
- }
- }
- }
- else if ( type == OBJECT_WORM )
- {
- if ( m_object->RetActif() )
- {
- if ( m_lastSoundInsect <= 0.0f )
- {
- m_sound->Play(SOUND_INSECTw, m_object->RetPosition(0));
- if ( m_bMotor ) m_lastSoundInsect = 0.4f+Math::Rand()*2.5f;
- else m_lastSoundInsect = 1.5f+Math::Rand()*4.0f;
- }
- }
- else if ( m_object->RetBurn() )
- {
- if ( m_lastSoundInsect <= 0.0f )
- {
- m_sound->Play(SOUND_INSECTw, m_object->RetPosition(0), 1.0f, 1.5f+Math::Rand()*0.5f);
- m_lastSoundInsect = 0.2f+Math::Rand()*0.2f;
- }
- }
- }
- else if ( type == OBJECT_SPIDER )
- {
- if ( m_object->RetBurn() ||
- m_object->RetFixed() )
- {
- if ( m_lastSoundInsect <= 0.0f )
- {
- m_sound->Play(SOUND_INSECTs, m_object->RetPosition(0), 1.0f, 1.5f+Math::Rand()*0.5f);
- m_lastSoundInsect = 0.4f+Math::Rand()*0.6f;
- }
- }
- else if ( m_object->RetActif() )
- {
- if ( m_lastSoundInsect <= 0.0f )
- {
- m_sound->Play(SOUND_INSECTs, m_object->RetPosition(0));
- if ( m_bMotor ) m_lastSoundInsect = 0.4f+Math::Rand()*2.5f;
- else m_lastSoundInsect = 1.5f+Math::Rand()*4.0f;
- }
- }
- }
- else // vehicle?
- {
- if ( m_type == TYPE_ROLLING )
- {
- if ( m_bMotor && m_object->RetActif() )
- {
- SoundMotorFull(rTime, type); // full diet
- }
- else
- {
- energy = 0.0f;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- }
-
- if ( m_object->RetSelect() &&
- energy != 0.0f )
- {
- SoundMotorSlow(rTime, type); // in slow motion
- }
- else
- {
- SoundMotorStop(rTime, type); // to the stop
- }
- }
- }
-
- if ( m_type == TYPE_FLYING )
- {
- if ( m_bMotor && !m_bSwim &&
- m_object->RetActif() && !m_object->RetDead() )
- {
- SoundReactorFull(rTime, type); // full diet
- }
- else
- {
- SoundReactorStop(rTime, type); // to the stop
- }
- }
- }
-}
-
-// Detonates the object if it is underwater.
-
-void CPhysics::WaterFrame(float aTime, float rTime)
-{
- ObjectType type;
- Math::Vector pos, speed;
- Math::Point dim;
- float level;
-
- level = m_water->RetLevel();
- if ( level == 0.0f ) return; // no water?
- if ( m_object->RetTruck() != 0 ) return; // object transported?
-
- // Management of flames into the lava.
- pos = m_object->RetPosition(0);
- if ( m_water->RetLava() &&
- pos.y-m_object->RetCharacter()->height <= level )
- {
- if ( m_lastFlameParticule+m_engine->ParticuleAdapt(0.05f) <= aTime )
- {
- m_lastFlameParticule = aTime;
-
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*3.0f;
- pos.z += (Math::Rand()-0.5f)*3.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = Math::Rand()*5.0f+3.0f;
- dim.x = Math::Rand()*2.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f);
-
- pos = m_object->RetPosition(0);
- pos.y -= 2.0f;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 6.0f+Math::Rand()*6.0f+6.0f;
- dim.x = Math::Rand()*1.5f+1.0f+3.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
- }
- }
-
- pos = m_object->RetPosition(0);
- if ( pos.y >= m_water->RetLevel(m_object) ) return; // out of water?
-
- type = m_object->RetType();
- if ( type == OBJECT_TOTO ) return;
- if ( type == OBJECT_NULL ) return;
-
- if ( !m_object->RetActif() ) return;
- if ( m_object->RetResetBusy() ) return; // reset in progress?
-
- if ( m_water->RetLava() ||
- (type == OBJECT_HUMAN &&
- m_object->RetOption() != 0 ) || // human without a helmet?
- 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_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr ||
- type == OBJECT_APOLLO2 ) // vehicle not underwater?
- {
- m_object->ExploObject(EXPLO_WATER, 1.0f); // starts explosion
- }
-}
-
-// Sounds the engine at full power.
-
-void CPhysics::SoundMotorFull(float rTime, ObjectType type)
-{
- Sound sound;
- float amplitude, time, freq;
-
- if ( type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEis )
- {
- if ( m_soundChannel == -1 )
- {
- m_soundChannel = m_sound->Play(SOUND_MOTORi, m_object->RetPosition(0), 0.0f, 1.0f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 0.2f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_LOOP);
- }
- else
- {
- m_sound->Position(m_soundChannel, m_object->RetPosition(0));
- }
-
- freq = 1.0f+m_linMotion.terrainSpeed.x/50.0f;
- if ( m_linMotion.realSpeed.x == 0.0f )
- {
- freq -= fabs(m_cirMotion.realSpeed.y/3.0f);
- }
- else
- {
- freq -= fabs(m_cirMotion.realSpeed.y/4.0f);
- }
- m_sound->Frequency(m_soundChannel, freq);
-
- return;
- }
-
- if ( type == OBJECT_MOBILEsa )
- {
- sound = SOUND_MOTORs;
- amplitude = 0.6f;
- time = 0.5f;
- }
- else if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs )
- {
- sound = SOUND_MOTORr;
- amplitude = 1.0f;
- time = 0.7f;
- }
- else if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts )
- {
- sound = SOUND_MOTORt;
- amplitude = 1.0f;
- time = 0.5f;
- }
- else if ( type == OBJECT_APOLLO2 )
- {
- sound = SOUND_MANIP;
- amplitude = 1.0f;
- time = 0.5f;
- }
- else
- {
- sound = SOUND_MOTORw;
- amplitude = 0.7f;
- time = 0.3f;
- }
-
- if ( m_object->RetToy() )
- {
- sound = SOUND_MOTORd;
- amplitude = 1.0f;
- time = 0.1f;
- }
-
- freq = 0.75f+(fabs(m_motorSpeed.x)+fabs(m_motorSpeed.z))*0.25f;
- if ( freq > 1.0f ) freq = 1.0f;
- if ( m_object->RetToy() ) freq = 1.0f;
-
- if ( m_soundChannel == -1 )
- {
- m_soundChannel = m_sound->Play(sound, m_object->RetPosition(0), 0.0f, 0.5f, true);
- m_sound->AddEnvelope(m_soundChannel, amplitude, freq, time, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, amplitude, freq, 1.0f, SOPER_LOOP);
- }
- else
- {
- m_sound->Position(m_soundChannel, m_object->RetPosition(0));
-
- if ( m_bSoundSlow ) // in slow motion?
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, amplitude, freq, time, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, amplitude, freq, 1.0f, SOPER_LOOP);
- m_bSoundSlow = false;
- }
- }
-
- freq *= 1.0f + m_linMotion.terrainSpeed.x/100.0f;
- freq *= 1.0f + fabs(m_cirMotion.realSpeed.y/20.0f);
- m_sound->Frequency(m_soundChannel, freq);
-
- m_soundTimePshhh -= rTime*2.0f;
-}
-
-// Sounds the engine idling.
-
-void CPhysics::SoundMotorSlow(float rTime, ObjectType type)
-{
- Math::Matrix* mat;
- Math::Vector pos, speed;
- Math::Point dim;
- Sound sound;
- float amplitude;
- int i, max;
-
- if ( type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEis )
- {
- if ( m_soundChannel != -1 ) // engine is running?
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.3f, SOPER_STOP);
- m_soundChannel = -1;
- }
- return;
- }
-
- if ( type == OBJECT_MOBILEsa )
- {
- sound = SOUND_MOTORs;
- amplitude = 0.4f;
- }
- else if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs )
- {
- sound = SOUND_MOTORr;
- amplitude = 0.9f;
- }
- else if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts )
- {
- sound = SOUND_MOTORt;
- amplitude = 0.7f;
- }
- else if ( type == OBJECT_APOLLO2 )
- {
- if ( m_soundChannel != -1 ) // engine is running?
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.3f, SOPER_STOP);
- m_soundChannel = -1;
- }
- return;
- }
- else
- {
- sound = SOUND_MOTORw;
- amplitude = 0.3f;
- }
-
- if ( m_object->RetToy() )
- {
- sound = SOUND_MOTORd;
- amplitude = 0.0f;
- }
-
- if ( m_soundChannel == -1 )
- {
- m_soundChannel = m_sound->Play(sound, m_object->RetPosition(0), 0.0f, 0.25f, true);
- m_sound->AddEnvelope(m_soundChannel, amplitude, 0.5f, 0.2f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, amplitude, 0.5f, 1.0f, SOPER_LOOP);
- }
- else
- {
- m_sound->Position(m_soundChannel, m_object->RetPosition(0));
-
- if ( !m_bSoundSlow ) // full power?
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, amplitude, 0.5f, 0.3f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, amplitude, 0.5f, 1.0f, SOPER_LOOP);
- m_bSoundSlow = true;
- }
- }
-
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs )
- {
- m_soundTimePshhh -= rTime;
-
- if ( m_soundTimePshhh <= 0.0f )
- {
- amplitude = 0.5f-m_soundTimePshhh*0.08f;
- if ( amplitude > 1.0f ) amplitude = 1.0f;
-//? m_sound->Play(SOUND_PSHHH, m_object->RetPosition(0), amplitude);
- m_sound->Play(SOUND_PSHHH, m_object->RetPosition(0), 1.0f);
-
- m_soundTimePshhh = 4.0f+4.0f*Math::Rand();
-
- max = (int)(10.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<max ; i++ )
- {
- pos = Math::Vector(-5.0f, 2.0f, 0.0f);
- pos.x += Math::Rand()*4.0f;
- pos.z += (Math::Rand()-0.5f)*2.0f;
-
- speed = pos;
- speed.x -= Math::Rand()*4.0f;
- speed.y -= Math::Rand()*3.0f;
- speed.z += (Math::Rand()-0.5f)*6.0f;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Transform(*mat, pos);
- speed = Transform(*mat, speed)-pos;
-
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIMOTOR, 2.0f);
- }
- }
- }
-}
-
-// Sounds the engine not running.
-
-void CPhysics::SoundMotorStop(float rTime, ObjectType type)
-{
- if ( type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEis )
- {
- if ( m_soundChannel != -1 ) // engine is running?
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.3f, SOPER_STOP);
- m_soundChannel = -1;
- }
- return;
- }
-
- if ( m_soundChannel != -1 ) // engine is running?
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.3f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- m_soundTimePshhh -= rTime*2.0f;
-}
-
-// Sounds the reactor at full power.
-
-void CPhysics::SoundReactorFull(float rTime, ObjectType type)
-{
- Sound sound;
- Math::Matrix* mat;
- Math::Vector pos, speed;
- Math::Point dim;
- float freq;
- int i;
-
- if ( m_soundChannelSlide != -1 ) // slides?
- {
- m_sound->FlushEnvelope(m_soundChannelSlide);
- m_sound->AddEnvelope(m_soundChannelSlide, 0.0f, 1.0f, 0.3f, SOPER_STOP);
- m_soundChannelSlide = -1;
- }
-
- if ( m_reactorRange > 0.0f )
- {
- if ( m_soundChannel == -1 )
- {
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH )
- {
- sound = SOUND_FLYh;
- }
- else
- {
- sound = SOUND_FLY;
- }
-
- m_soundChannel = m_sound->Play(sound, m_object->RetPosition(0), 0.0f, 1.0f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 0.6f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_LOOP);
- }
- else
- {
- m_sound->Position(m_soundChannel, m_object->RetPosition(0));
- }
-
- freq = 1.0f + m_linMotion.realSpeed.y/100.0f;
- freq *= 1.0f + fabs(m_cirMotion.realSpeed.y/5.0f);
- m_sound->Frequency(m_soundChannel, freq);
- }
- else
- {
- if ( m_soundChannel != -1 ) // engine is running?
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- if ( m_timeReactorFail <= m_time )
- {
- freq = 1.0f+Math::Rand()*0.5f;
- m_sound->Play(SOUND_FLYf, m_object->RetPosition(0), 1.0f, freq);
- m_camera->StartEffect(CE_PET, m_object->RetPosition(0), 1.0f);
-
- for ( i=0 ; i<5 ; i++ )
- {
- if ( m_object->RetType() == OBJECT_HUMAN ||
- m_object->RetType() == OBJECT_TECH )
- {
- pos = Math::Vector(-1.6f, -0.5f, 0.0f);
- }
- else
- {
- pos = Math::Vector(0.0f, -1.0f, 0.0f);
- }
- pos.x += (Math::Rand()-0.5f)*2.0f;
- pos.z += (Math::Rand()-0.5f)*2.0f;
- mat = m_object->RetWorldMatrix(0);
- pos = Transform(*mat, pos);
- speed.x = (Math::Rand()-0.5f)*5.0f;
- speed.z = (Math::Rand()-0.5f)*5.0f;
- speed.y = -(4.0f+Math::Rand()*4.0f);
- dim.x = (2.0f+Math::Rand()*1.0f);
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 2.0f, 0.0f, 0.1f);
- }
-
- m_timeReactorFail = m_time+0.10f+Math::Rand()*0.30f;
- }
- else
- {
- if ( m_object->RetType() == OBJECT_HUMAN ||
- m_object->RetType() == OBJECT_TECH )
- {
- pos = Math::Vector(-1.6f, -0.5f, 0.0f);
- }
- else
- {
- pos = Math::Vector(0.0f, -1.0f, 0.0f);
- }
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- mat = m_object->RetWorldMatrix(0);
- pos = Transform(*mat, pos);
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = -(4.0f+Math::Rand()*4.0f);
- dim.x = (0.7f+Math::Rand()*0.4f);
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 2.0f, 0.0f, 0.1f);
- }
- }
-
-}
-
-// Sounds the reactor stopped.
-
-void CPhysics::SoundReactorStop(float rTime, ObjectType type)
-{
- CObject* power;
- float energy;
-
- energy = 0.0f;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- }
-
- if ( m_soundChannel != -1 ) // engine is running?
- {
- m_sound->FlushEnvelope(m_soundChannel);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
- m_soundChannel = -1;
- }
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH )
- {
- if ( m_soundChannelSlide != -1 ) // slides?
- {
- m_sound->FlushEnvelope(m_soundChannelSlide);
- m_sound->AddEnvelope(m_soundChannelSlide, 0.0f, 1.0f, 0.3f, SOPER_STOP);
- m_soundChannelSlide = -1;
- }
- }
- else
- {
- if ( energy != 0.0f &&
- (m_motorSpeed.x != 0.0f || // slides with small reactors in skates?
- m_cirMotion.realSpeed.y != 0.0f) )
- {
- if ( m_soundChannelSlide == -1 )
- {
- m_soundChannelSlide = m_sound->Play(SOUND_SLIDE, m_object->RetPosition(0), 0.0f, 1.0f, true);
- m_sound->AddEnvelope(m_soundChannelSlide, 0.5f, 1.0f, 0.3f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannelSlide, 0.5f, 1.0f, 1.0f, SOPER_LOOP);
- }
- m_sound->Position(m_soundChannelSlide, m_object->RetPosition(0));
- }
- else
- {
- if ( m_soundChannelSlide != -1 ) // slides?
- {
- m_sound->FlushEnvelope(m_soundChannelSlide);
- m_sound->AddEnvelope(m_soundChannelSlide, 0.0f, 1.0f, 0.3f, SOPER_STOP);
- m_soundChannelSlide = -1;
- }
- }
- }
-}
-
-
-// Adapts the physics of the object based on the ground.
-
-void CPhysics::FloorAdapt(float aTime, float rTime,
- Math::Vector &pos, Math::Vector &angle)
-{
- Character* character;
- ObjectType type;
- Math::Vector norm;
- Math::Matrix matRotate;
- float level, h, f, a1, volume, freq, force;
- bool bOldSwim, bSlopingTerrain;
-
- type = m_object->RetType();
- character = m_object->RetCharacter();
-
- level = m_water->RetLevel(m_object);
- bOldSwim = m_bSwim;
- SetSwim( pos.y < level );
-
- m_floorLevel = m_terrain->RetFloorLevel(pos); // height above the ground
- h = pos.y-m_floorLevel;
- h -= character->height;
- m_floorHeight = h;
-
- WaterParticule(aTime, pos, type, m_floorLevel,
- fabs(m_linMotion.realSpeed.x),
- fabs(m_cirMotion.realSpeed.y*15.0f));
-
- if ( m_type == TYPE_ROLLING )
- {
- pos.y -= h; // plate to the ground immediately
- pos.y += character->height;
- m_floorHeight = 0.0f;
- }
-
- if ( m_type == TYPE_FLYING )
- {
- bSlopingTerrain = false; // ground as possible to land
-
- if ( !m_bLand ) // in flight?
- {
- m_terrain->GetNormal(norm, pos);
- a1 = fabs(Math::RotateAngle(Math::Point(norm.x, norm.z).Length(), norm.y));
- if ( a1 < (90.0f-55.0f)*Math::PI/180.0f ) // slope exceeds 55 degrees?
- {
- bSlopingTerrain = true; // very sloped ground
-
- if ( h < 4.0f ) // collision with the ground?
- {
- force = 5.0f+fabs(m_linMotion.realSpeed.x*0.3f)+
- fabs(m_linMotion.realSpeed.y*0.3f);
- m_linMotion.currentSpeed = norm*force;
- Math::LoadRotationXZYMatrix(matRotate, -angle);
- m_linMotion.currentSpeed = Transform(matRotate, m_linMotion.currentSpeed);
-
- if ( aTime-m_soundTimeBoum > 0.5f )
- {
- volume = fabs(m_linMotion.realSpeed.x*0.02f)+
- fabs(m_linMotion.realSpeed.y*0.02f);
- freq = 0.5f+m_terrain->RetHardness(pos)*2.5f;
- m_sound->Play(SOUND_BOUM, pos, volume, freq);
-
- m_soundTimeBoum = aTime;
- }
-
-//? pos = m_object->RetPosition(0); // gives position before collision
- }
- }
- }
-
- if ( (h <= 0.0f || m_bLand) && !bSlopingTerrain ) // on the ground?
- {
- if ( !m_bLand ) // in flight?
- {
- volume = fabs(m_linMotion.realSpeed.y*0.02f);
- freq = 0.5f+m_terrain->RetHardness(pos)*2.5f;
- m_sound->Play(SOUND_BOUM, pos, volume, freq);
- }
-
- m_bLand = true; // on the ground?
- SetMotor(false);
- pos.y -= h; // plate to the ground immediately
- m_floorHeight = 0.0f;
-
- if ( h < 0.0f )
- {
- f = fabs(m_linMotion.currentSpeed.y/m_linMotion.advanceSpeed.y);
- CrashParticule(f);
- }
- m_linMotion.currentSpeed.y = 0.0f;
- m_inclinaisonFactor = 1.0f/LANDING_SPEED; // slips a little to the ground
- m_linVibrationFactor = 0.0f;
- m_cirVibrationFactor = 0.0f;
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH ) return; // always right
- }
-
- if ( h > 4.0f || bSlopingTerrain ) // meters above the ground?
- {
- if ( m_bSwim )
- {
- m_linVibrationFactor = 1.0f; // vibrates a max
- m_cirVibrationFactor = 1.0f;
- }
- else
- {
- m_linVibrationFactor = 2.0f; // vibrates a large max
- m_cirVibrationFactor = 2.0f;
- }
- m_inclinaisonFactor = 1.0f;
-
- // Gives gently the horizontal.
- if ( angle.x > 0.0f )
- {
- angle.x -= rTime*0.5f;
- if ( angle.x < 0.0f ) angle.x = 0.0f;
- }
- if ( angle.x < 0.0f )
- {
- angle.x += rTime*0.5f;
- if ( angle.x > 0.0f ) angle.x = 0.0f;
- }
- if ( angle.z > 0.0f )
- {
- angle.z -= rTime*0.5f;
- if ( angle.z < 0.0f ) angle.z = 0.0f;
- }
- if ( angle.z < 0.0f )
- {
- angle.z += rTime*0.5f;
- if ( angle.z > 0.0f ) angle.z = 0.0f;
- }
- return;
- }
- }
-
- if ( m_floorHeight == 0.0f ) // ground plate?
- {
- if ( m_object->RetTraceDown() )
- {
- WheelParticule(m_object->RetTraceColor(), m_object->RetTraceWidth()*g_unit);
- }
- else
- {
- WheelParticule(-1, 0.0f);
- }
- }
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH ||
- type == OBJECT_WORM ) return; // always right
-
- FloorAngle(pos, angle); // adjusts the angle at the ground
-
- if ( m_type == TYPE_FLYING && !m_bLand ) // flying in the air?
- {
- f = h/1.0f;
- if ( f < 0.0f ) f = 0.0f;
- if ( f > 1.0f ) f = 1.0f;
- m_linVibrationFactor = f;
- m_cirVibrationFactor = f;
- angle.z *= 1.0f-f;
- angle.x *= 1.0f-f;
-
- f = h/1.0f;
- if ( f < 0.0f ) f = 0.0f;
- if ( f > 1.0f ) f = 1.0f;
- m_inclinaisonFactor = f;
- }
-}
-
-// Calculates the angle of an object with the field.
-
-void CPhysics::FloorAngle(const Math::Vector &pos, Math::Vector &angle)
-{
- Character* character;
- Math::Vector pw, norm;
- float a1, a2;
-
- character = m_object->RetCharacter();
-
- pw.x = pos.x+character->wheelFront*cosf(angle.y+Math::PI*0.0f);
- pw.y = pos.y;
- pw.z = pos.z-character->wheelFront*sinf(angle.y+Math::PI*0.0f);
- a1 = atanf(m_terrain->RetFloorHeight(pw)/character->wheelFront);
-
- pw.x = pos.x+character->wheelBack*cosf(angle.y+Math::PI*1.0f);
- pw.y = pos.y;
- pw.z = pos.z-character->wheelBack*sinf(angle.y+Math::PI*1.0f);
- a2 = atanf(m_terrain->RetFloorHeight(pw)/character->wheelBack);
-
- angle.z = (a2-a1)/2.0f;
-
- pw.x = pos.x+character->wheelLeft*cosf(angle.y+Math::PI*0.5f)*cosf(angle.z);
- pw.y = pos.y;
- pw.z = pos.z-character->wheelLeft*sinf(angle.y+Math::PI*0.5f)*cosf(angle.z);
- a1 = atanf(m_terrain->RetFloorHeight(pw)/character->wheelLeft);
-
- pw.x = pos.x+character->wheelRight*cosf(angle.y+Math::PI*1.5f)*cosf(angle.z);
- pw.y = pos.y;
- pw.z = pos.z-character->wheelRight*sinf(angle.y+Math::PI*1.5f)*cosf(angle.z);
- a2 = atanf(m_terrain->RetFloorHeight(pw)/character->wheelRight);
-
- angle.x = (a2-a1)/2.0f;
-}
-
-
-// Adapts the physics of the object in relation to other objects.
-// Returns 0 -> mobile object
-// Returns 1 -> immobile object (because collision)
-// Returns 2 -> destroyed object
-
-int CPhysics::ObjectAdapt(const Math::Vector &pos, const Math::Vector &angle)
-{
- CObject* pObj;
- CPyro* pyro;
- CPhysics* ph;
- Math::Matrix matRotate;
- Math::Vector iPos, oPos, iiPos, oAngle, oSpeed;
- Sound sound;
- float iRad, oRad, distance, force, volume;
- int i, j, colType;
- ObjectType iType, oType;
-
- if ( m_object->RetRuin() ) return 0; // is burning or exploding?
- if ( !m_object->RetClip() ) return 0;
-
- // iiPos = sphere center is the old position.
- // iPos = sphere center has the new position.
- m_object->GetCrashSphere(0, iiPos, iRad);
- iPos = iiPos + (pos - m_object->RetPosition(0));
- iType = m_object->RetType();
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_object ) continue; // yourself?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( !pObj->RetEnable() ) continue; // inactive?
- if ( pObj->RetRuin() ) continue; // is burning or exploding?
- if ( pObj->RetDead() ) continue; // dead man?
-
- oType = pObj->RetType();
- if ( oType == OBJECT_NULL ) continue;
- if ( oType == OBJECT_TOTO ) continue;
-//? if ( iType == OBJECT_BEE && oType == OBJECT_BEE ) continue;
- if ( iType == OBJECT_WORM && oType != OBJECT_WORM ) continue;
- if ( iType != OBJECT_WORM && oType == OBJECT_WORM ) continue;
- if ( iType == OBJECT_MOTHER && oType == OBJECT_ANT ) continue;
- if ( iType == OBJECT_ANT && oType == OBJECT_MOTHER ) continue;
- if ( iType == OBJECT_MOTHER && oType == OBJECT_SPIDER ) continue;
- if ( iType == OBJECT_SPIDER && oType == OBJECT_MOTHER ) continue;
- if ( iType == OBJECT_MOTHER && oType == OBJECT_EGG ) continue;
- if ( iType == OBJECT_EGG && oType == OBJECT_MOTHER ) continue;
-
- pObj->GetJotlerSphere(oPos, oRad);
- if ( oRad > 0.0f )
- {
- JostleObject(pObj, iPos, iRad, oPos, oRad);
- }
-
- if ( iType == OBJECT_MOTHER ||
- iType == OBJECT_ANT ||
- iType == OBJECT_SPIDER ||
- iType == OBJECT_WORM ||
- iType == OBJECT_BEE ) // insect?
- {
- if ( oType == OBJECT_STONE ||
- oType == OBJECT_URANIUM ||
- oType == OBJECT_METAL ||
- oType == OBJECT_POWER ||
- oType == OBJECT_ATOMIC ||
- oType == OBJECT_BULLET ||
- oType == OBJECT_BBOX ||
- oType == OBJECT_KEYa ||
- oType == OBJECT_KEYb ||
- oType == OBJECT_KEYc ||
- oType == OBJECT_KEYd ||
- oType == OBJECT_TNT ||
- (oType >= OBJECT_PLANT0 && oType <= OBJECT_PLANT19 ) ||
- (oType >= OBJECT_MUSHROOM0 && oType <= OBJECT_MUSHROOM9) ) continue;
- }
-
-#if _TEEN
- if ( oType == OBJECT_WAYPOINT &&
- pObj->RetEnable() &&
- !m_object->RetResetBusy() ) // driving vehicle?
-#else
- if ( oType == OBJECT_WAYPOINT &&
- pObj->RetEnable() &&
- !m_object->RetResetBusy() &&
- m_object->RetTrainer() ) // driving vehicle?
-#endif
- {
- oPos = pObj->RetPosition(0);
- distance = Math::DistanceProjected(oPos, iPos);
- if ( distance < 4.0f )
- {
- m_sound->Play(SOUND_WAYPOINT, m_object->RetPosition(0));
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_WPCHECK, pObj);
- }
- }
-
- if ( oType == OBJECT_TARGET2 )
- {
- oPos = pObj->RetPosition(0);
- distance = Math::Distance(oPos, iPos);
- if ( distance < 10.0f*1.5f )
- {
- m_sound->Play(SOUND_WAYPOINT, m_object->RetPosition(0));
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_WPCHECK, pObj);
- }
- }
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRad) )
- {
- if ( iType == OBJECT_MOTHER && oRad <= 1.2f ) continue;
- if ( iType == OBJECT_ANT && oRad <= 1.2f ) continue;
- if ( iType == OBJECT_SPIDER && oRad <= 1.2f ) continue;
- if ( iType == OBJECT_BEE && oRad <= 1.2f ) continue;
- if ( iType == OBJECT_WORM && oRad <= 1.2f ) continue;
-
- distance = Math::Distance(oPos, iPos);
- if ( distance < iRad+oRad ) // collision?
- {
- distance = Math::Distance(oPos, iiPos);
- if ( distance >= iRad+oRad ) // view (*)
- {
- m_bCollision = true;
- m_bObstacle = true;
-
- sound = pObj->RetCrashSphereSound(j-1);
- if ( sound != SOUND_CLICK )
- {
- force = fabs(m_linMotion.realSpeed.x);
- force *= pObj->RetCrashSphereHardness(j-1)*2.0f;
- if ( ExploOther(iType, pObj, oType, force) ) continue;
- colType = ExploHimself(iType, oType, force);
- if ( colType == 2 ) return 2; // destroyed?
- if ( colType == 0 ) continue; // ignores?
- }
-
- force = m_linMotion.realSpeed.Length();
- force *= pObj->RetCrashSphereHardness(j-1);
- volume = fabs(force*0.05f);
- if ( volume > 1.0f ) volume = 1.0f;
- if ( sound != SOUND_CLICK )
- {
- m_sound->Play(sound, m_object->RetPosition(0), volume);
- }
- if ( iType == OBJECT_HUMAN && volume > 0.5f )
- {
- m_sound->Play(SOUND_AIE, m_object->RetPosition(0), volume);
- }
-
- if ( m_repeatCollision > 0 )
- {
- force *= 0.5f*m_repeatCollision;
- if ( force > 20.0f ) force = 20.0f;
- }
- m_repeatCollision += 2;
- if ( m_repeatCollision > 10 )
- {
- m_repeatCollision = 10;
- }
-
- m_linMotion.currentSpeed = Normalize(iPos-oPos)*force;
- Math::LoadRotationXZYMatrix(matRotate, -angle);
- m_linMotion.currentSpeed = Transform(matRotate, m_linMotion.currentSpeed);
- if ( m_type == TYPE_ROLLING )
- {
- m_linMotion.currentSpeed.y = 0.0f;
- }
-
- ph = pObj->RetPhysics();
- if ( ph != 0 )
- {
- oAngle = pObj->RetAngle(0);
- oSpeed = Normalize(oPos-iPos)*force;
- Math::LoadRotationXZYMatrix(matRotate, -oAngle);
- oSpeed = Transform(matRotate, oSpeed);
- if ( ph->RetType() == TYPE_ROLLING )
- {
- oSpeed.y = 0.0f;
- }
- ph->SetLinMotion(MO_CURSPEED, oSpeed);
- }
- return 1;
- }
- }
- }
- }
-
- if ( m_repeatCollision > 0 )
- {
- m_repeatCollision --;
- }
- return 0;
-}
-
-// (*) Collision has the initial position (iiPos) and the new position (iPos),
-// the obstacle is not known. We can therefore pass through.
-// This is necessary when barriers found "in" a vehicle, not to block it definitely!
-
-
-// Shakes an object.
-
-bool CPhysics::JostleObject(CObject* pObj, Math::Vector iPos, float iRad,
- Math::Vector oPos, float oRad)
-{
- Math::Vector speed;
- float distance, force, d, f;
-
- distance = Math::Distance(oPos, iPos);
- if ( distance >= iRad+oRad ) return false;
-
- d = (iRad+oRad)/2.0f;
- f = (distance-d)/d; // 0 = off, 1 = near
- if ( f < 0.0f ) f = 0.0f;
- if ( f > 1.0f ) f = 1.0f;
-
- speed = m_linMotion.realSpeed;
- speed.y = 0.0f;
- force = speed.Length()*f*0.05f;
- if ( force > 1.0f ) force = 1.0f;
-
- if ( m_soundTimeJostle >= 0.20f )
- {
- m_soundTimeJostle = 0.0f;
- m_sound->Play(SOUND_JOSTLE, iPos, force);
- }
-
- return pObj->JostleObject(force);
-}
-
-// Shakes forcing an object.
-
-bool CPhysics::JostleObject(CObject* pObj, float force)
-{
- Math::Vector oPos;
- float oRad;
-
- pObj->GetJotlerSphere(oPos, oRad);
- if ( oRad <= 0.0f ) return false;
-
- if ( m_soundTimeJostle >= 0.20f )
- {
- m_soundTimeJostle = 0.0f;
- m_sound->Play(SOUND_JOSTLE, pObj->RetPosition(0), force);
- }
-
- return pObj->JostleObject(force);
-}
-
-// Effects of the explosion on the object buffers.
-// Returns true if we ignore this obstacle.
-
-bool CPhysics::ExploOther(ObjectType iType,
- CObject *pObj, ObjectType oType, float force)
-{
- CPyro* pyro;
-
- if ( !pObj->RetEnable() ) return true;
-
- JostleObject(pObj, 1.0f); // shakes the object
-
- if ( force > 50.0f &&
- (oType == OBJECT_FRET ||
- oType == OBJECT_METAL ) )
- {
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_EXPLOT, pObj); // total destruction
- }
-
- if ( force > 50.0f &&
- (oType == OBJECT_POWER ||
- oType == OBJECT_ATOMIC ) )
- {
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FRAGT, pObj); // total destruction
- }
-
- if ( force > 25.0f &&
- (oType == OBJECT_STONE ||
- oType == OBJECT_URANIUM ) )
- {
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FRAGT, pObj); // total destruction
- }
-
- if ( force > 25.0f &&
- (oType == OBJECT_DERRICK ||
- oType == OBJECT_FACTORY ||
- oType == OBJECT_STATION ||
- oType == OBJECT_CONVERT ||
- oType == OBJECT_REPAIR ||
- oType == OBJECT_DESTROYER||
- oType == OBJECT_TOWER ||
- oType == OBJECT_RESEARCH ||
- oType == OBJECT_RADAR ||
- oType == OBJECT_INFO ||
- oType == OBJECT_ENERGY ||
- oType == OBJECT_LABO ||
- oType == OBJECT_NUCLEAR ||
- oType == OBJECT_PARA ||
- oType == OBJECT_SAFE ||
- oType == OBJECT_HUSTON ) ) // building?
- {
- pObj->ExploObject(EXPLO_BOUM, force/400.0f);
- }
-
- if ( force > 25.0f &&
- (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 ||
- oType == OBJECT_APOLLO2 ) ) // vehicle?
- {
- pObj->ExploObject(EXPLO_BOUM, force/200.0f);
- }
-
- if ( force > 10.0f &&
- (oType == OBJECT_MOBILEtg ||
- oType == OBJECT_TNT ) )
- {
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FRAGT, pObj); // total destruction
- }
-
- if ( force > 0.0f &&
- oType == OBJECT_BOMB )
- {
- pyro = new CPyro(m_iMan);
- pyro->Create(PT_FRAGT, pObj); // total destruction
- }
-
- return false;
-}
-
-// Effects of the explosion on the object itself.
-// Returns 0 -> mobile object
-// Returns 1 -> immobile object
-// Returns 2 -> object destroyed
-
-int CPhysics::ExploHimself(ObjectType iType, ObjectType oType, float force)
-{
- PyroType type;
- CPyro* pyro;
-
- if ( force > 10.0f &&
- (oType == OBJECT_TNT ||
- oType == OBJECT_MOBILEtg ) )
- {
- if ( iType == OBJECT_HUMAN ) type = PT_DEADG;
- else type = PT_EXPLOT;
- pyro = new CPyro(m_iMan);
- pyro->Create(type, m_object); // total destruction
- return 2;
- }
-
- if ( force > 0.0f &&
- oType == OBJECT_BOMB )
- {
- if ( iType == OBJECT_HUMAN )
- {
- type = PT_DEADG;
- }
- else if ( iType == OBJECT_ANT ||
- iType == OBJECT_SPIDER ||
- iType == OBJECT_BEE )
- {
- type = PT_EXPLOO;
- }
- else
- {
- type = PT_EXPLOT;
- }
- pyro = new CPyro(m_iMan);
- pyro->Create(type, m_object); // total destruction
- return 2;
- }
-
- if ( force > 25.0f &&
- (iType == OBJECT_HUMAN ||
- iType == OBJECT_MOBILEwa ||
- iType == OBJECT_MOBILEta ||
- iType == OBJECT_MOBILEfa ||
- iType == OBJECT_MOBILEia ||
- iType == OBJECT_MOBILEwc ||
- iType == OBJECT_MOBILEtc ||
- iType == OBJECT_MOBILEfc ||
- iType == OBJECT_MOBILEic ||
- iType == OBJECT_MOBILEwi ||
- iType == OBJECT_MOBILEti ||
- iType == OBJECT_MOBILEfi ||
- iType == OBJECT_MOBILEii ||
- iType == OBJECT_MOBILEws ||
- iType == OBJECT_MOBILEts ||
- iType == OBJECT_MOBILEfs ||
- iType == OBJECT_MOBILEis ||
- iType == OBJECT_MOBILErt ||
- iType == OBJECT_MOBILErc ||
- iType == OBJECT_MOBILErr ||
- iType == OBJECT_MOBILErs ||
- iType == OBJECT_MOBILEsa ||
- iType == OBJECT_MOBILEwt ||
- iType == OBJECT_MOBILEtt ||
- iType == OBJECT_MOBILEft ||
- iType == OBJECT_MOBILEit ||
- iType == OBJECT_MOBILEdr ||
- iType == OBJECT_APOLLO2 ) ) // vehicle?
- {
- if ( oType == OBJECT_DERRICK ||
- oType == OBJECT_FACTORY ||
- oType == OBJECT_STATION ||
- oType == OBJECT_CONVERT ||
- oType == OBJECT_REPAIR ||
- oType == OBJECT_DESTROYER||
- oType == OBJECT_TOWER ||
- oType == OBJECT_RESEARCH ||
- oType == OBJECT_RADAR ||
- oType == OBJECT_INFO ||
- oType == OBJECT_ENERGY ||
- oType == OBJECT_LABO ||
- oType == OBJECT_NUCLEAR ||
- oType == OBJECT_PARA ||
- oType == OBJECT_SAFE ||
- oType == OBJECT_HUSTON ) // building?
- {
- force /= 200.0f;
- }
- else
- if ( oType == OBJECT_MOTHER ||
- oType == OBJECT_ANT ||
- oType == OBJECT_SPIDER ||
- oType == OBJECT_BEE ||
- oType == OBJECT_WORM ) // insect?
- {
- force /= 400.0f;
- }
- else
- if ( oType == OBJECT_FRET ||
- oType == OBJECT_STONE ||
- oType == OBJECT_METAL )
- {
- force /= 500.0f;
- }
- else
- if ( oType == OBJECT_URANIUM ||
- oType == OBJECT_POWER ||
- oType == OBJECT_ATOMIC )
- {
- force /= 100.0f;
- }
- else
- {
- force /= 200.0f;
- }
-
- if ( m_object->ExploObject(EXPLO_BOUM, force) ) return 2;
- }
-
- return 1;
-}
-
-
-
-// Makes the particles evolve.
-
-void CPhysics::FrameParticule(float aTime, float rTime)
-{
- Math::Vector pos;
- CObject* power;
- float energy, intensity;
- int effectLight;
- bool bFlash;
-
- m_restBreakParticule -= rTime;
- if ( aTime-m_lastPowerParticule < m_engine->ParticuleAdapt(0.05f) ) return;
- m_lastPowerParticule = aTime;
-
- bFlash = false;
-
- energy = 0.0f;
- power = m_object->RetPower();
- if ( power != 0 )
- {
- energy = power->RetEnergy();
- }
-
- if ( energy != m_lastEnergy ) // change the energy level?
- {
- if ( energy > m_lastEnergy ) // recharge?
- {
- PowerParticule(1.0f, false);
- bFlash = true;
- }
-
- if ( energy == 0.0f || m_lastEnergy == 0.0f )
- {
- m_restBreakParticule = 2.5f; // particles for 2.5s
- }
-
- m_lastEnergy = energy;
- }
-
- if ( m_restBreakParticule > 0.0f )
- {
- PowerParticule(m_restBreakParticule/2.5f, (energy == 0));
- bFlash = true;
- }
-
- effectLight = m_object->RetEffectLight();
- if ( effectLight != -1 )
- {
- if ( bFlash )
- {
- intensity = 0.0f;
- if ( Math::Rand() < 0.5f ) intensity = 1.0f;
- m_light->SetLightIntensity(effectLight, intensity);
- m_light->SetLightIntensitySpeed(effectLight, 10000.0f);
- }
- else
- {
- m_light->SetLightIntensity(effectLight, 0.0f);
- }
- }
-}
-
-// Generates some particles after a recharge.
-
-void CPhysics::PowerParticule(float factor, bool bBreak)
-{
- Character* character;
- CObject* fret;
- Math::Matrix* mat;
- Math::Vector pos, ppos, eye, speed;
- Math::Point dim;
- bool bCarryPower;
-
- bCarryPower = false;
- fret = m_object->RetFret();
- if ( fret != 0 && fret->RetType() == OBJECT_POWER &&
- m_object->RetAngleZ(1) == ARM_STOCK_ANGLE1 )
- {
- bCarryPower = true; // carries a battery
- }
-
- mat = m_object->RetWorldMatrix(0);
- character = m_object->RetCharacter();
-
- pos = character->posPower;
- pos.x -= 0.3f;
- pos.y += 1.0f; // battery center position
- pos = Transform(*mat, pos);
-
- speed.x = (Math::Rand()-0.5f)*12.0f;
- speed.y = (Math::Rand()-0.5f)*12.0f;
- speed.z = (Math::Rand()-0.5f)*12.0f;
-
- ppos.x = pos.x;
- ppos.y = pos.y+(Math::Rand()-0.5f)*2.0f;
- ppos.z = pos.z;
-
- dim.x = 1.0f*factor;
- dim.y = 1.0f*factor;
-
- m_particule->CreateParticule(ppos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
-
- if ( bCarryPower ) // carry a battery?
- {
- pos = Math::Vector(3.0f, 5.6f, 0.0f); // position of battery holder
- pos = Transform(*mat, pos);
-
- speed.x = (Math::Rand()-0.5f)*12.0f;
- speed.y = (Math::Rand()-0.5f)*12.0f;
- speed.z = (Math::Rand()-0.5f)*12.0f;
-
- ppos.x = pos.x;
- ppos.y = pos.y;
- ppos.z = pos.z+(Math::Rand()-0.5f)*2.0f;
-
- dim.x = 1.0f*factor;
- dim.y = 1.0f*factor;
-
- m_particule->CreateParticule(ppos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
- }
-}
-
-// Generates some particles after a fall.
-// crash: 0=super soft, 1=big crash
-
-void CPhysics::CrashParticule(float crash)
-{
- Math::Vector pos, ppos, speed;
- Math::Point dim;
- float len;
- int i, max;
-
- if ( crash < 0.2f ) return;
-
- pos = m_object->RetPosition(0);
- m_camera->StartEffect(CE_CRASH, pos, crash);
-
-//? max = (int)(crash*50.0f);
- max = (int)(crash*10.0f*m_engine->RetParticuleDensity());
-
- for ( i=0 ; i<max ; i++ )
- {
- ppos.x = pos.x + (Math::Rand()-0.5f)*15.0f*crash;
- ppos.z = pos.z + (Math::Rand()-0.5f)*15.0f*crash;
- ppos.y = pos.y + Math::Rand()*4.0f;
- len = 1.0f-(Math::Distance(ppos, pos)/(15.0f+5.0f));
- if ( len <= 0.0f ) continue;
- speed.x = (ppos.x-pos.x)*0.1f;
- speed.z = (ppos.z-pos.z)*0.1f;
- speed.y = -2.0f;
- dim.x = 2.0f+crash*5.0f*len;
- dim.y = dim.x;
- m_particule->CreateParticule(ppos, speed, dim, PARTICRASH, 2.0f);
- }
-}
-
-// Generates some exhaust gas particle.
-
-void CPhysics::MotorParticule(float aTime, float rTime)
-{
- Math::Matrix* mat;
- Math::Vector pos, speed;
- Math::Point dim;
- ObjectType type;
- Math::Point c, p;
- float h, a, delay, level;
- int r, i, nb;
-
- if ( m_object->RetToy() ) return;
-
- type = m_object->RetType();
-
- if ( type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEis || // legs?
- type == OBJECT_MOBILEdr ||
- type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ||
- type == OBJECT_APOLLO2 ) return;
-
- if ( type == OBJECT_HUMAN ) delay = 3.0f;
- else delay = 8.0f;
- if ( m_bSwim && m_timeUnderWater < delay ) // bubbles when entering water?
- {
- if ( aTime-m_lastUnderParticule >= m_engine->ParticuleAdapt(0.05f) )
- {
- m_lastUnderParticule = aTime;
-
- nb = (int)(20.0f-(20.0f/delay)*m_timeUnderWater);
- for ( i=0 ; i<nb ; i++ )
- {
- pos = m_object->RetPosition(0);
- pos.x += (Math::Rand()-0.5f)*4.0f;
- pos.y += (Math::Rand()-0.5f)*4.0f;
- pos.z += (Math::Rand()-0.5f)*4.0f;
- speed.y = (Math::Rand()-0.5f)*8.0f+8.0f;
- speed.x = (Math::Rand()-0.5f)*0.2f;
- speed.z = (Math::Rand()-0.5f)*0.2f;
- dim.x = 0.06f+Math::Rand()*0.10f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBUBBLE, 3.0f, 0.0f, 0.0f);
- }
- }
- }
-
- level = m_water->RetLevel();
- pos = m_object->RetPosition(0);
- if ( type == OBJECT_HUMAN ) pos.y -= 2.0f;
- if ( pos.y < level ) // underwater?
- {
- m_absorbWater += rTime*(1.0f/2.0f); // gets wet
- if ( m_absorbWater > 1.0f ) m_absorbWater = 1.0f;
- }
- else // out of water?
- {
- m_absorbWater -= rTime*(1.0f/3.0f); // to dry
- if ( m_absorbWater < 0.0f ) m_absorbWater = 0.0f;
- }
-
- if ( pos.y >= level &&
- m_absorbWater > 0.0f &&
- !m_water->RetLava() ) // drops on leaving the water?
- {
- if ( aTime-m_lastUnderParticule >= m_engine->ParticuleAdapt(0.05f) )
- {
- m_lastUnderParticule = aTime;
-
- nb = (int)(8.0f*m_absorbWater);
- for ( i=0 ; i<nb ; i++ )
- {
- pos = m_object->RetPosition(0);
- if ( type == OBJECT_HUMAN ) pos.y -= Math::Rand()*2.0f;
- else pos.y += Math::Rand()*2.0f;
- pos.x += (Math::Rand()-0.5f)*2.0f;
- pos.z += (Math::Rand()-0.5f)*2.0f;
- speed.y = -((Math::Rand()-0.5f)*8.0f+8.0f);
- speed.x = 0.0f;
- speed.z = 0.0f;
- dim.x = 0.2f;
- dim.y = 0.2f;
- m_particule->CreateParticule(pos, speed, dim, PARTIWATER, 2.0f, 0.0f, 1.0f);
- }
- }
- }
-
- if ( type == OBJECT_HUMAN || // human?
- type == OBJECT_TECH )
- {
- if ( m_bLand &&
- aTime-m_lastSlideParticule >= m_engine->ParticuleAdapt(0.05f) )
- {
- h = Math::Max(fabs(m_linMotion.terrainSpeed.x),
- fabs(m_linMotion.terrainSpeed.z));
- if ( h > m_linMotion.terrainSlide.x+0.5f &&
- m_linMotion.motorSpeed.x == 0.0f ) // slides a stop?
- {
- m_lastSlideParticule = aTime;
-
- mat = m_object->RetWorldMatrix(0);
- pos.x = (Math::Rand()-0.5f)*1.0f;
- pos.y = -m_object->RetCharacter()->height;
- pos.z = Math::Rand()*0.4f+1.0f;
- if ( rand()%2 == 0 ) pos.z = -pos.z;
- pos = Transform(*mat, pos);
- speed = Math::Vector(0.0f, 1.0f, 0.0f);
- dim.x = Math::Rand()*(h-5.0f)/2.0f+1.0f;
- if ( dim.x > 2.5f ) dim.x = 2.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.2f);
- }
- }
- }
-
- if ( type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEts ) // caterpillars?
- {
- if ( aTime-m_lastSlideParticule >= m_engine->ParticuleAdapt(0.05f) )
- {
- h = fabs(m_linMotion.motorSpeed.x-m_linMotion.realSpeed.x);
- if ( h > 5.0f )
- {
- m_lastSlideParticule = aTime;
-
- mat = m_object->RetWorldMatrix(0);
- pos.x = (Math::Rand()-0.5f)*8.0f;
- pos.y = 0.0f;
- pos.z = Math::Rand()*2.0f+3.0f;
- if ( rand()%2 == 0 ) pos.z = -pos.z;
- pos = Transform(*mat, pos);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*(h-5.0f)/2.0f+1.0f;
- if ( dim.x > 3.0f ) dim.x = 3.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.2f);
- }
- }
- }
-
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ) // large caterpillars?
- {
- if ( aTime-m_lastSlideParticule >= m_engine->ParticuleAdapt(0.05f) )
- {
- h = fabs(m_linMotion.motorSpeed.x-m_linMotion.realSpeed.x);
- if ( h > 5.0f )
- {
- m_lastSlideParticule = aTime;
-
- mat = m_object->RetWorldMatrix(0);
- pos.x = (Math::Rand()-0.5f)*9.0f;
- pos.y = 0.0f;
- pos.z = Math::Rand()*3.0f+3.0f;
- if ( rand()%2 == 0 ) pos.z = -pos.z;
- pos = Transform(*mat, pos);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*(h-5.0f)/2.0f+1.0f;
- if ( dim.x > 3.0f ) dim.x = 3.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.2f);
- }
- }
- }
-
- if ( (type == OBJECT_HUMAN || type == OBJECT_TECH) && !m_bSwim )
- {
- if ( m_bLand ) // on the ground?
- {
- if ( m_reactorTemperature > 0.0f )
- {
- m_reactorTemperature -= rTime*(1.0f/10.0f); // cooling
- if ( m_reactorTemperature < 0.0f )
- {
- m_reactorTemperature = 0.0f;
- }
- }
-
- if ( m_reactorTemperature == 0.0f ||
- aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.05f) ) return;
- m_lastMotorParticule = aTime;
-
- pos = Math::Vector(-1.6f, -0.5f, 0.0f);
- mat = m_object->RetWorldMatrix(0);
- pos = Transform(*mat, pos);
-
- speed.x = (Math::Rand()-0.5f)*0.6f;
- speed.z = (Math::Rand()-0.5f)*0.6f;
- speed.y = -(0.5f+Math::Rand()*0.3f)*(1.0f-m_reactorTemperature);
-
- dim.x = (1.0f+Math::Rand()*0.5f)*(0.2f+m_reactorTemperature*0.8f);
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE2, 3.0f, 0.0f, 0.1f);
- }
- else // in flight?
- {
- if ( !m_bMotor || m_reactorRange == 0.0f ) return;
-
- if ( m_reactorTemperature < 1.0f ) // not too hot?
- {
- m_reactorTemperature += rTime*(1.0f/4.0f); // heating
- if ( m_reactorTemperature > 1.0f )
- {
- m_reactorTemperature = 1.0f; // but not too much
- }
- }
-
- if ( aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.02f) ) return;
- m_lastMotorParticule = aTime;
-
- pos = Math::Vector(-1.6f, -1.0f, 0.0f);
- pos.x += (Math::Rand()-0.5f)*3.0f;
- pos.y += (Math::Rand()-0.5f)*1.5f;
- pos.z += (Math::Rand()-0.5f)*3.0f;
- mat = m_object->RetWorldMatrix(0);
- pos = Transform(*mat, pos);
-
- h = m_floorHeight;
- if ( h > 10.0f ) // high enough?
- {
- speed = Math::Vector(0.0f, -10.0f, 0.0f); // against the bottom
- }
- else
- {
- speed.y = 10.0f-2.0f*h - Math::Rand()*(10.0f-h); //against the top
- speed.x = (Math::Rand()-0.5f)*(5.0f-h)*1.0f; // horizontal (xz)
- speed.z = (Math::Rand()-0.5f)*(5.0f-h)*1.0f;
- }
-
- dim.x = 0.12f;
- dim.y = 0.12f;
-
- m_particule->CreateParticule(pos, speed, dim, PARTISCRAPS, 2.0f, 10.0f);
-
-#if 1
- pos = Math::Vector(-1.6f, -0.5f, 0.0f);
- pos = Transform(*mat, pos);
-
- speed.x = (Math::Rand()-0.5f)*1.0f;
- speed.z = (Math::Rand()-0.5f)*1.0f;
- speed.y = -(4.0f+Math::Rand()*3.0f);
- speed.x += m_linMotion.realSpeed.x*0.8f;
- speed.z -= m_linMotion.realSpeed.x*m_cirMotion.realSpeed.y*0.05f;
- if ( m_linMotion.realSpeed.y > 0.0f )
- {
- speed.y += m_linMotion.realSpeed.y*0.5f;
- }
- else
- {
- speed.y += m_linMotion.realSpeed.y*1.2f;
- }
- a = m_object->RetAngleY(0);
- p.x = speed.x;
- p.y = speed.z;
- p = Math::RotatePoint(-a, p);
- speed.x = p.x;
- speed.z = p.y;
-
- dim.x = 0.4f+Math::Rand()*0.2f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIEJECT, 0.3f, 10.0f);
-#endif
- }
- }
-
- if ( (type == OBJECT_HUMAN || type == OBJECT_TECH) && m_bSwim )
- {
- m_reactorTemperature = 0.0f; // reactor cold
- }
-
- if ( m_type == TYPE_FLYING &&
- type != OBJECT_HUMAN &&
- type != OBJECT_TECH &&
- !m_bSwim )
- {
- if ( m_bLand ) // on the ground?
- {
- if ( m_motorSpeed.x == 0.0f && // glide slope due to ground?
- m_cirMotion.realSpeed.y == 0.0f )
- {
- h = Math::Max(fabs(m_linMotion.realSpeed.x),
- fabs(m_linMotion.realSpeed.z));
-
- if ( h < 3.0f ) return;
-
- if ( aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.2f) ) return;
- m_lastMotorParticule = aTime;
-
- r = rand()%3;
- if ( r == 0 ) pos = Math::Vector(-3.0f, 0.0f, -4.0f);
- if ( r == 1 ) pos = Math::Vector(-3.0f, 0.0f, 4.0f);
- if ( r == 2 ) pos = Math::Vector( 4.0f, 0.0f, 0.0f);
-
- pos.x += (Math::Rand()-0.5f)*2.0f;
- pos.z += (Math::Rand()-0.5f)*2.0f;
- mat = m_object->RetWorldMatrix(0);
- pos = Transform(*mat, pos);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = Math::Rand()*h/5.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
- }
- else // glide with small reactors in skates?
- {
- if ( m_linMotion.realSpeed.x == 0.0f &&
- m_cirMotion.realSpeed.y == 0.0f ) return;
-
- if ( aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.02f) ) return;
- m_lastMotorParticule = aTime;
-
- r = rand()%3;
- if ( r == 0 ) pos = Math::Vector(-3.0f, 0.0f, -4.0f);
- if ( r == 1 ) pos = Math::Vector(-3.0f, 0.0f, 4.0f);
- if ( r == 2 ) pos = Math::Vector( 4.0f, 0.0f, 0.0f);
-
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- mat = m_object->RetWorldMatrix(0);
- pos = Transform(*mat, pos);
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIEJECT);
- }
- }
- else // in flight?
- {
- if ( !m_bMotor || m_reactorRange == 0.0f ) return;
-
- if ( aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.02f) ) return;
- m_lastMotorParticule = aTime;
-
- pos = Math::Vector(0.0f, -1.0f, 0.0f);
- pos.x += (Math::Rand()-0.5f)*6.0f;
- pos.y += (Math::Rand()-0.5f)*3.0f;
- pos.z += (Math::Rand()-0.5f)*6.0f;
- mat = m_object->RetWorldMatrix(0);
- pos = Transform(*mat, pos);
-
- h = m_floorHeight;
- if ( h > 10.0f ) // high enough?
- {
- speed = Math::Vector(0.0f, -10.0f, 0.0f); // against the bottom
- }
- else
- {
- speed.y = 10.0f-2.0f*h - Math::Rand()*(10.0f-h); // against the top
- speed.x = (Math::Rand()-0.5f)*(10.0f-h)*2.0f; // horizontal (xz)
- speed.z = (Math::Rand()-0.5f)*(10.0f-h)*2.0f;
- }
-
- dim.x = 0.2f;
- dim.y = 0.2f;
-
- m_particule->CreateParticule(pos, speed, dim, PARTISCRAPS, 2.0f, 10.0f);
-
-#if 1
- pos = Math::Vector(0.0f, 1.0f, 0.0f);
- pos = Transform(*mat, pos);
-
- speed.x = (Math::Rand()-0.5f)*1.0f;
- speed.z = (Math::Rand()-0.5f)*1.0f;
- speed.y = -(6.0f+Math::Rand()*4.5f);
- speed.x += m_linMotion.realSpeed.x*0.8f;
- speed.z -= m_linMotion.realSpeed.x*m_cirMotion.realSpeed.y*0.05f;
- if ( m_linMotion.realSpeed.y > 0.0f )
- {
- speed.y += m_linMotion.realSpeed.y*0.5f;
- }
- else
- {
- speed.y += m_linMotion.realSpeed.y*1.2f;
- }
- a = m_object->RetAngleY(0);
- p.x = speed.x;
- p.y = speed.z;
- p = Math::RotatePoint(-a, p);
- speed.x = p.x;
- speed.z = p.y;
-
- dim.x = 0.7f+Math::Rand()*0.6f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIEJECT, 0.5f, 10.0f);
-#endif
- }
- }
-
- if ( (type == OBJECT_HUMAN || type == OBJECT_TECH) && m_bSwim )
- {
- if ( !m_object->RetDead() )
- {
- h = Math::Mod(aTime, 5.0f);
- if ( h < 3.5f && ( h < 1.5f || h > 1.6f ) ) return;
- }
- if ( aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.06f) ) return;
- m_lastMotorParticule = aTime;
-
- pos = Math::Vector(0.0f, 3.0f, 0.0f);
- mat = m_object->RetWorldMatrix(0);
- pos = Transform(*mat, pos);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- speed.y = (Math::Rand()-0.5f)*8.0f+8.0f;
- speed.x = (Math::Rand()-0.5f)*0.2f;
- speed.z = (Math::Rand()-0.5f)*0.2f;
- dim.x = 0.2f;
- dim.y = 0.2f;
- m_particule->CreateParticule(pos, speed, dim, PARTIBUBBLE, 3.0f, 0.0f, 0.0f);
-
- if ( aTime-m_lastSoundWater > 1.5f )
- {
- m_lastSoundWater = aTime;
- m_sound->Play(SOUND_BLUP, m_object->RetPosition(0), 0.5f+Math::Rand()*0.5f);
- }
- }
-
- if ( type == OBJECT_MOBILEsa && m_bSwim )
- {
- h = Math::Mod(aTime, 3.0f);
- if ( h < 1.5f && ( h < 0.5f || h > 0.9f ) ) return;
- if ( aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.06f) ) return;
- m_lastMotorParticule = aTime;
-
- pos = Math::Vector(0.0f, 3.0f, 0.0f);
- mat = m_object->RetWorldMatrix(0);
- pos = Transform(*mat, pos);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- speed.y = (Math::Rand()-0.5f)*8.0f+8.0f;
- speed.x = (Math::Rand()-0.5f)*0.2f;
- speed.z = (Math::Rand()-0.5f)*0.2f;
- dim.x = 0.2f;
- dim.y = 0.2f;
- m_particule->CreateParticule(pos, speed, dim, PARTIBUBBLE, 3.0f, 0.0f, 0.0f);
-
- if ( aTime-m_lastSoundWater > 1.5f )
- {
- m_lastSoundWater = aTime;
- m_sound->Play(SOUND_BLUP, m_object->RetPosition(0), 0.5f+Math::Rand()*0.5f);
- }
- }
-
- if ( m_type == TYPE_ROLLING )
- {
- if ( type == OBJECT_APOLLO2 ) return; // electric motors!
-
- if ( type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs )
- {
- if ( !m_bMotor ) return;
-
- if ( aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.1f) ) return;
- m_lastMotorParticule = aTime;
-
- pos = Math::Vector(-2.5f, 10.3f, -1.3f);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- mat = m_object->RetWorldMatrix(0);
- pos = Transform(*mat, pos);
-
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = 1.5f+Math::Rand()*1.0f;
-
- dim.x = Math::Rand()*0.6f+0.4f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIMOTOR, 2.0f);
- }
- else
- {
- if ( !m_bMotor ) return;
-
- if ( aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.05f) ) return;
- m_lastMotorParticule = aTime;
-
- pos = Math::Vector(-3.4f, 1.8f, 0.5f);
-
- speed = pos;
- if ( m_linMotion.currentSpeed.x < 0.0f )
- {
- speed.x += m_linMotion.currentSpeed.x*1.2f;
- }
- else if ( m_linMotion.currentSpeed.x > 0.0f )
- {
- speed.x += 0.0f;
- }
- else
- {
- speed.x -= 3.0f;
- }
- speed.y -= 0.5f+Math::Rand()*2.0f;
- speed.z += (Math::Rand()-0.5f)*3.0f;
-
- mat = m_object->RetWorldMatrix(0);
- pos = Transform(*mat, pos);
- speed = Transform(*mat, speed)-pos;
-
- dim.x = Math::Rand()*0.4f+0.3f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIMOTOR, 2.0f);
- }
- }
-}
-
-// Generates some particles after falling into the water.
-
-void CPhysics::WaterParticule(float aTime, Math::Vector pos, ObjectType type,
- float floor, float advance, float turn)
-{
- Math::Vector ppos, speed;
- Math::Point dim;
- float delay, level, min, max, force, volume, diam;
- int i, nb;
-
- level = m_water->RetLevel();
- if ( floor >= level ) return;
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH )
- {
- min = 3.0f;
- max = 3.0f;
- }
- else
- {
- min = 0.0f;
- max = 9.0f;
- }
-
- if ( pos.y+max < level || pos.y-min > level ) return;
-
- // Management of the particle "splash".
- if ( m_linMotion.realSpeed.y < -10.0f &&
- aTime-m_lastPloufParticule >= 1.0f )
- {
- m_lastPloufParticule = aTime;
-
- force = -m_linMotion.realSpeed.y/20.0f; // power according to speed drops
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH )
- {
- diam = 2.5f;
- }
- else
- {
- diam = 5.0f;
- force *= 1.3f; // a robot is heavier
- }
-
- pos = m_object->RetPosition(0);
- pos.y = m_water->RetLevel()-1.0f;
- dim.x = 2.0f*force; // height
- dim.y = diam; // diameter
- m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), dim, PARTIPLOUF0, 1.4f, 0.0f, 0.0f);
-
- force = (0.5f+force*0.5f);
- nb = (int)(force*50.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<nb ; i++ )
- {
- ppos = pos;
- ppos.x += (Math::Rand()-0.5f)*4.0f;
- ppos.z += (Math::Rand()-0.5f)*4.0f;
- ppos.y += 0.6f;
- speed.x = (Math::Rand()-0.5f)*12.0f*force;
- speed.z = (Math::Rand()-0.5f)*12.0f*force;
- speed.y = 6.0f+Math::Rand()*6.0f*force;
- dim.x = 0.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(ppos, speed, dim, PARTIDROP, 2.0f, 20.0f, 0.2f);
- }
-
- volume = fabs(m_linMotion.realSpeed.y*0.02f);
- if ( volume > 1.0f ) volume = 1.0f;
- m_sound->Play(SOUND_PLOUF, pos, volume);
- }
-
- // Management particles "cop".
- if ( m_water->RetLava() ) return;
-
- if ( advance == 0.0f && turn == 0.0f )
- {
- turn = 10.0f;
- delay = 0.50f;
- }
- else if ( advance == 0.0f )
- {
- delay = 0.24f;
- }
- else
- {
- delay = 0.06f;
- }
- m_engine->ParticuleAdapt(delay);
-
- if ( aTime-m_lastWaterParticule < delay ) return;
- m_lastWaterParticule = aTime;
-
- force = (advance+turn)*0.16f;
- if ( force < 0.001f ) return;
-
- pos = m_object->RetPosition(0);
- pos.y = level+0.1f;
- if ( advance == 0 )
- {
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- }
- else
- {
- pos.x += (Math::Rand()-0.5f)*4.0f;
- pos.z += (Math::Rand()-0.5f)*4.0f;
- }
- speed.y = 0.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- dim.x = Math::Min(Math::Rand()*force+force+1.0f, 10.0f);
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFLIC, 3.0f, 0.0f, 0.0f);
-}
-
-// Creates the trace under the robot.
-
-void CPhysics::WheelParticule(int color, float width)
-{
- Character* character;
- Math::Matrix* mat;
- Math::Vector goal1, goal2, wheel1, wheel2;
- ParticuleType parti;
- float dist1, dist2, step;
-
- character = m_object->RetCharacter();
- mat = m_object->RetWorldMatrix(0);
-
- // Draw a trace on the ground.
- if ( color >= 0 && color <= 17 )
- {
- parti = (ParticuleType)(PARTITRACE0+color);
- step = 2.0f;
- if ( color >= 16 ) step = 4.0f; // arrow?
- step /= m_engine->RetTracePrecision();
-
- goal1.x = step/2.0f;
- goal1.y = 0.0f;
- goal1.z = -width/2.0f;
- goal1 = Transform(*mat, goal1);
-
- goal2.x = step/2.0f;
- goal2.y = 0.0f;
- goal2.z = width/2.0f;
- goal2 = Transform(*mat, goal2);
-
- if ( !m_bWheelParticuleBrake )
- {
- m_wheelParticulePos[0] = goal1;
- m_wheelParticulePos[1] = goal2;
- }
-
- while ( true )
- {
- dist1 = Math::Distance(m_wheelParticulePos[0], goal1);
- if ( dist1 < step ) break;
- dist2 = Math::Distance(m_wheelParticulePos[1], goal2);
- wheel1 = Math::SegmentPoint(m_wheelParticulePos[0], goal1, step);
- wheel2 = Math::SegmentPoint(m_wheelParticulePos[1], goal2, step*dist2/dist1);
- if ( m_linMotion.realSpeed.x >= 0.0f )
- {
- m_particule->CreateWheelTrace(m_wheelParticulePos[0], m_wheelParticulePos[1], wheel1, wheel2, parti);
- }
- else
- {
- m_particule->CreateWheelTrace(m_wheelParticulePos[1], m_wheelParticulePos[0], wheel2, wheel1, parti);
- }
- m_wheelParticulePos[0] = wheel1;
- m_wheelParticulePos[1] = wheel2;
- }
-
- m_bWheelParticuleBrake = true;
- }
- else
- {
- m_bWheelParticuleBrake = false;
- }
-}
-
-
-// Creates the interface.
-
-void CPhysics::CreateInterface(bool bSelect)
-{
- if ( m_brain != 0 )
- {
- m_brain->CreateInterface(bSelect);
- }
-}
-
-
-// Returns an error related to the general state.
-
-Error CPhysics::RetError()
-{
- ObjectType type;
- CObject* power;
-
- type = m_object->RetType();
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH ||
- type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ||
- type == OBJECT_APOLLO2 ||
- type == OBJECT_MOBILEdr ) return ERR_OK;
-
- if ( m_brain != 0 && m_brain->RetActiveVirus() )
- {
- return ERR_VEH_VIRUS;
- }
-
- power = m_object->RetPower(); // searches for the object battery used
- if ( power == 0 )
- {
- return ERR_VEH_POWER;
- }
- else
- {
- if ( power->RetEnergy() == 0.0f ) return ERR_VEH_ENERGY;
- }
-
- return ERR_OK;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// physics.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/language.h"
+#include "common/global.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "old/light.h"
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "old/camera.h"
+#include "object/object.h"
+#include "old/pyro.h"
+#include "object/brain.h"
+#include "object/motion/motion.h"
+#include "object/motion/motionhuman.h"
+#include "old/sound.h"
+#include "object/task/task.h"
+#include "script/cmdtoken.h"
+#include "physics/physics.h"
+
+
+
+const float LANDING_SPEED = 3.0f;
+const float LANDING_ACCEL = 5.0f;
+const float LANDING_ACCELh = 1.5f;
+
+
+
+
+// Object's constructor.
+
+CPhysics::CPhysics(CInstanceManager* iMan, CObject* object)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_PHYSICS, this, 100);
+
+ m_object = object;
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ m_brain = 0;
+ m_motion = 0;
+
+ m_type = TYPE_ROLLING;
+ m_gravity = 9.81f; // default gravity
+ m_time = 0.0f;
+ m_timeUnderWater = 0.0f;
+ m_motorSpeed = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_bMotor = false;
+ m_bLand = true; // ground
+ m_bSwim = false; // in air
+ m_bCollision = false;
+ m_bObstacle = false;
+ m_repeatCollision = 0;
+ m_linVibrationFactor = 1.0f;
+ m_cirVibrationFactor = 1.0f;
+ m_inclinaisonFactor = 1.0f;
+ m_lastPowerParticule = 0.0f;
+ m_lastSlideParticule = 0.0f;
+ m_lastMotorParticule = 0.0f;
+ m_lastWaterParticule = 0.0f;
+ m_lastUnderParticule = 0.0f;
+ m_lastPloufParticule = 0.0f;
+ m_lastFlameParticule = 0.0f;
+ m_bWheelParticuleBrake = false;
+ m_absorbWater = 0.0f;
+ m_reactorTemperature = 0.0f;
+ m_reactorRange = 1.0f;
+ m_timeReactorFail = 0.0f;
+ m_lastEnergy = 0.0f;
+ m_lastSoundWater = 0.0f;
+ m_lastSoundInsect = 0.0f;
+ m_restBreakParticule = 0.0f;
+ m_floorHeight = 0.0f;
+ m_soundChannel = -1;
+ m_soundChannelSlide = -1;
+ m_soundTimePshhh = 0.0f;
+ m_soundTimeJostle = 0.0f;
+ m_soundTimeBoum = 0.0f;
+ m_bSoundSlow = true;
+ m_bFreeze = false;
+ m_bForceUpdate = true;
+ m_bLowLevel = false;
+
+ ZeroMemory(&m_linMotion, sizeof(Motion));
+ ZeroMemory(&m_cirMotion, sizeof(Motion));
+}
+
+// Object's destructor.
+
+CPhysics::~CPhysics()
+{
+ m_iMan->DeleteInstance(CLASS_PHYSICS, this);
+}
+
+
+// Destroys the object.
+
+void CPhysics::DeleteObject(bool bAll)
+{
+ if ( m_soundChannel != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.3f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+ if ( m_soundChannelSlide != -1 )
+ {
+ m_sound->FlushEnvelope(m_soundChannelSlide);
+ m_sound->AddEnvelope(m_soundChannelSlide, 0.0f, 1.0f, 0.3f, SOPER_STOP);
+ m_soundChannelSlide = -1;
+ }
+}
+
+
+
+void CPhysics::SetBrain(CBrain* brain)
+{
+ m_brain = brain;
+}
+
+void CPhysics::SetMotion(CMotion* motion)
+{
+ m_motion = motion;
+}
+
+// Management of the type.
+
+void CPhysics::SetType(PhysicsType type)
+{
+ m_type = type;
+}
+
+PhysicsType CPhysics::RetType()
+{
+ return m_type;
+}
+
+
+
+// Saves all parameters of the object.
+
+bool CPhysics::Write(char *line)
+{
+ char name[100];
+
+ sprintf(name, " motor=%.2f;%.2f;%.2f", m_motorSpeed.x, m_motorSpeed.y, m_motorSpeed.z);
+ strcat(line, name);
+
+ if ( m_type == TYPE_FLYING )
+ {
+ sprintf(name, " reactorRange=%.2f", RetReactorRange());
+ strcat(line, name);
+
+ sprintf(name, " land=%d", RetLand());
+ strcat(line, name);
+ }
+
+ return true;
+}
+
+// Restores all parameters of the object.
+
+bool CPhysics::Read(char *line)
+{
+ m_motorSpeed = OpDir(line, "motor");
+
+ if ( m_type == TYPE_FLYING )
+ {
+ SetReactorRange(OpFloat(line, "reactorRange", 0.0f));
+ SetLand(OpInt(line, "land", 0));
+ }
+
+ return true;
+}
+
+
+
+// Management of the force of gravity.
+
+void CPhysics::SetGravity(float value)
+{
+ m_gravity = value;
+}
+
+float CPhysics::RetGravity()
+{
+ return m_gravity;
+}
+
+
+// Returns the height above the ground.
+
+float CPhysics::RetFloorHeight()
+{
+ return m_floorHeight;
+}
+
+
+// Managing the state of the engine.
+
+void CPhysics::SetMotor(bool bState)
+{
+ int light;
+
+ m_bMotor = bState;
+
+ light = m_object->RetShadowLight();
+ if ( light != -1 )
+ {
+ m_light->SetLightIntensity(light, m_bMotor?1.0f:0.0f);
+ m_light->SetLightIntensitySpeed(light, 3.0f);
+ }
+}
+
+bool CPhysics::RetMotor()
+{
+ return m_bMotor;
+}
+
+
+// Management of the state in flight/ground.
+
+void CPhysics::SetLand(bool bState)
+{
+ m_bLand = bState;
+ SetMotor(!bState); // lights if you leave the reactor in flight
+}
+
+bool CPhysics::RetLand()
+{
+ return m_bLand;
+}
+
+
+// Management of the state in air/water.
+
+void CPhysics::SetSwim(bool bState)
+{
+ if ( !m_bSwim && bState ) // enters the water?
+ {
+ m_timeUnderWater = 0.0f;
+ }
+ m_bSwim = bState;
+}
+
+bool CPhysics::RetSwim()
+{
+ return m_bSwim;
+}
+
+
+// Indicates whether a collision occurred.
+
+void CPhysics::SetCollision(bool bCollision)
+{
+ m_bCollision = bCollision;
+}
+
+bool CPhysics::RetCollision()
+{
+ return m_bCollision;
+}
+
+
+// Indicates whether the influence of soil is activated or not.
+
+void CPhysics::SetFreeze(bool bFreeze)
+{
+ m_bFreeze = bFreeze;
+}
+
+bool CPhysics::RetFreeze()
+{
+ return m_bFreeze;
+}
+
+
+// Returns the range of the reactor.
+
+void CPhysics::SetReactorRange(float range)
+{
+ m_reactorRange = range;
+}
+
+float CPhysics::RetReactorRange()
+{
+ return m_reactorRange;
+}
+
+
+// Specifies the engine speed.
+// x = forward/backward
+// y = up/down
+// z = turn
+
+void CPhysics::SetMotorSpeed(Math::Vector speed)
+{
+ m_motorSpeed = speed;
+}
+
+// Specifies the engine speed for forward/backward.
+// +1 = forward
+// -1 = backward
+
+void CPhysics::SetMotorSpeedX(float speed)
+{
+ m_motorSpeed.x = speed;
+}
+
+// Specifies the motor speed for up/down.
+// +1 = up
+// -1 = down
+
+void CPhysics::SetMotorSpeedY(float speed)
+{
+ m_motorSpeed.y = speed;
+}
+
+// Specifies the speed of the motor to turn.
+// +1 = turn right(CW)
+// -1 = turn left(CCW)
+
+void CPhysics::SetMotorSpeedZ(float speed)
+{
+ m_motorSpeed.z = speed;
+}
+
+Math::Vector CPhysics::RetMotorSpeed()
+{
+ return m_motorSpeed;
+}
+
+float CPhysics::RetMotorSpeedX()
+{
+ return m_motorSpeed.x;
+}
+
+float CPhysics::RetMotorSpeedY()
+{
+ return m_motorSpeed.y;
+}
+
+float CPhysics::RetMotorSpeedZ()
+{
+ return m_motorSpeed.z;
+}
+
+
+// Management of linear and angular velocities.
+// Specifies the speed parallel to the direction of travel.
+
+void CPhysics::SetLinMotion(PhysicsMode mode, Math::Vector value)
+{
+ if ( mode == MO_ADVACCEL ) m_linMotion.advanceAccel = value;
+ if ( mode == MO_RECACCEL ) m_linMotion.recedeAccel = value;
+ if ( mode == MO_STOACCEL ) m_linMotion.stopAccel = value;
+ if ( mode == MO_TERSPEED ) m_linMotion.terrainSpeed = value;
+ if ( mode == MO_TERSLIDE ) m_linMotion.terrainSlide = value;
+ if ( mode == MO_MOTACCEL ) m_linMotion.motorAccel = value;
+ if ( mode == MO_TERFORCE ) m_linMotion.terrainForce = value;
+ if ( mode == MO_ADVSPEED ) m_linMotion.advanceSpeed = value;
+ if ( mode == MO_RECSPEED ) m_linMotion.recedeSpeed = value;
+ if ( mode == MO_MOTSPEED ) m_linMotion.motorSpeed = value;
+ if ( mode == MO_CURSPEED ) m_linMotion.currentSpeed = value;
+ if ( mode == MO_REASPEED ) m_linMotion.realSpeed = value;
+}
+
+Math::Vector CPhysics::RetLinMotion(PhysicsMode mode)
+{
+ if ( mode == MO_ADVACCEL ) return m_linMotion.advanceAccel;
+ if ( mode == MO_RECACCEL ) return m_linMotion.recedeAccel;
+ if ( mode == MO_STOACCEL ) return m_linMotion.stopAccel;
+ if ( mode == MO_TERSPEED ) return m_linMotion.terrainSpeed;
+ if ( mode == MO_TERSLIDE ) return m_linMotion.terrainSlide;
+ if ( mode == MO_MOTACCEL ) return m_linMotion.motorAccel;
+ if ( mode == MO_TERFORCE ) return m_linMotion.terrainForce;
+ if ( mode == MO_ADVSPEED ) return m_linMotion.advanceSpeed;
+ if ( mode == MO_RECSPEED ) return m_linMotion.recedeSpeed;
+ if ( mode == MO_MOTSPEED ) return m_linMotion.motorSpeed;
+ if ( mode == MO_CURSPEED ) return m_linMotion.currentSpeed;
+ if ( mode == MO_REASPEED ) return m_linMotion.realSpeed;
+ return Math::Vector(0.0f, 0.0f, 0.0f);
+}
+
+void CPhysics::SetLinMotionX(PhysicsMode mode, float value)
+{
+ if ( mode == MO_ADVACCEL ) m_linMotion.advanceAccel.x = value;
+ if ( mode == MO_RECACCEL ) m_linMotion.recedeAccel.x = value;
+ if ( mode == MO_STOACCEL ) m_linMotion.stopAccel.x = value;
+ if ( mode == MO_TERSPEED ) m_linMotion.terrainSpeed.x = value;
+ if ( mode == MO_TERSLIDE ) m_linMotion.terrainSlide.x = value;
+ if ( mode == MO_MOTACCEL ) m_linMotion.motorAccel.x = value;
+ if ( mode == MO_TERFORCE ) m_linMotion.terrainForce.x = value;
+ if ( mode == MO_ADVSPEED ) m_linMotion.advanceSpeed.x = value;
+ if ( mode == MO_RECSPEED ) m_linMotion.recedeSpeed.x = value;
+ if ( mode == MO_MOTSPEED ) m_linMotion.motorSpeed.x = value;
+ if ( mode == MO_CURSPEED ) m_linMotion.currentSpeed.x = value;
+ if ( mode == MO_REASPEED ) m_linMotion.realSpeed.x = value;
+}
+
+float CPhysics::RetLinMotionX(PhysicsMode mode)
+{
+ if ( mode == MO_ADVACCEL ) return m_linMotion.advanceAccel.x;
+ if ( mode == MO_RECACCEL ) return m_linMotion.recedeAccel.x;
+ if ( mode == MO_STOACCEL ) return m_linMotion.stopAccel.x;
+ if ( mode == MO_TERSPEED ) return m_linMotion.terrainSpeed.x;
+ if ( mode == MO_TERSLIDE ) return m_linMotion.terrainSlide.x;
+ if ( mode == MO_MOTACCEL ) return m_linMotion.motorAccel.x;
+ if ( mode == MO_TERFORCE ) return m_linMotion.terrainForce.x;
+ if ( mode == MO_ADVSPEED ) return m_linMotion.advanceSpeed.x;
+ if ( mode == MO_RECSPEED ) return m_linMotion.recedeSpeed.x;
+ if ( mode == MO_MOTSPEED ) return m_linMotion.motorSpeed.x;
+ if ( mode == MO_CURSPEED ) return m_linMotion.currentSpeed.x;
+ if ( mode == MO_REASPEED ) return m_linMotion.realSpeed.x;
+ return 0.0f;
+}
+
+// Specifies the speed of elevation.
+
+void CPhysics::SetLinMotionY(PhysicsMode mode, float value)
+{
+ if ( mode == MO_ADVACCEL ) m_linMotion.advanceAccel.y = value;
+ if ( mode == MO_RECACCEL ) m_linMotion.recedeAccel.y = value;
+ if ( mode == MO_STOACCEL ) m_linMotion.stopAccel.y = value;
+ if ( mode == MO_TERSPEED ) m_linMotion.terrainSpeed.y = value;
+ if ( mode == MO_TERSLIDE ) m_linMotion.terrainSlide.y = value;
+ if ( mode == MO_MOTACCEL ) m_linMotion.motorAccel.y = value;
+ if ( mode == MO_TERFORCE ) m_linMotion.terrainForce.y = value;
+ if ( mode == MO_ADVSPEED ) m_linMotion.advanceSpeed.y = value;
+ if ( mode == MO_RECSPEED ) m_linMotion.recedeSpeed.y = value;
+ if ( mode == MO_MOTSPEED ) m_linMotion.motorSpeed.y = value;
+ if ( mode == MO_CURSPEED ) m_linMotion.currentSpeed.y = value;
+ if ( mode == MO_REASPEED ) m_linMotion.realSpeed.y = value;
+}
+
+float CPhysics::RetLinMotionY(PhysicsMode mode)
+{
+ if ( mode == MO_ADVACCEL ) return m_linMotion.advanceAccel.y;
+ if ( mode == MO_RECACCEL ) return m_linMotion.recedeAccel.y;
+ if ( mode == MO_STOACCEL ) return m_linMotion.stopAccel.y;
+ if ( mode == MO_TERSPEED ) return m_linMotion.terrainSpeed.y;
+ if ( mode == MO_TERSLIDE ) return m_linMotion.terrainSlide.y;
+ if ( mode == MO_MOTACCEL ) return m_linMotion.motorAccel.y;
+ if ( mode == MO_TERFORCE ) return m_linMotion.terrainForce.y;
+ if ( mode == MO_ADVSPEED ) return m_linMotion.advanceSpeed.y;
+ if ( mode == MO_RECSPEED ) return m_linMotion.recedeSpeed.y;
+ if ( mode == MO_MOTSPEED ) return m_linMotion.motorSpeed.y;
+ if ( mode == MO_CURSPEED ) return m_linMotion.currentSpeed.y;
+ if ( mode == MO_REASPEED ) return m_linMotion.realSpeed.y;
+ return 0.0f;
+}
+
+// Specifies the velocity perpendicular to the direction of travel.
+
+void CPhysics::SetLinMotionZ(PhysicsMode mode, float value)
+{
+ if ( mode == MO_ADVACCEL ) m_linMotion.advanceAccel.z = value;
+ if ( mode == MO_RECACCEL ) m_linMotion.recedeAccel.z = value;
+ if ( mode == MO_STOACCEL ) m_linMotion.stopAccel.z = value;
+ if ( mode == MO_TERSPEED ) m_linMotion.terrainSpeed.z = value;
+ if ( mode == MO_TERSLIDE ) m_linMotion.terrainSlide.z = value;
+ if ( mode == MO_MOTACCEL ) m_linMotion.motorAccel.z = value;
+ if ( mode == MO_TERFORCE ) m_linMotion.terrainForce.z = value;
+ if ( mode == MO_ADVSPEED ) m_linMotion.advanceSpeed.z = value;
+ if ( mode == MO_RECSPEED ) m_linMotion.recedeSpeed.z = value;
+ if ( mode == MO_MOTSPEED ) m_linMotion.motorSpeed.z = value;
+ if ( mode == MO_CURSPEED ) m_linMotion.currentSpeed.z = value;
+ if ( mode == MO_REASPEED ) m_linMotion.realSpeed.z = value;
+}
+
+float CPhysics::RetLinMotionZ(PhysicsMode mode)
+{
+ if ( mode == MO_ADVACCEL ) return m_linMotion.advanceAccel.z;
+ if ( mode == MO_RECACCEL ) return m_linMotion.recedeAccel.z;
+ if ( mode == MO_STOACCEL ) return m_linMotion.stopAccel.z;
+ if ( mode == MO_TERSPEED ) return m_linMotion.terrainSpeed.z;
+ if ( mode == MO_TERSLIDE ) return m_linMotion.terrainSlide.z;
+ if ( mode == MO_MOTACCEL ) return m_linMotion.motorAccel.z;
+ if ( mode == MO_TERFORCE ) return m_linMotion.terrainForce.z;
+ if ( mode == MO_ADVSPEED ) return m_linMotion.advanceSpeed.z;
+ if ( mode == MO_RECSPEED ) return m_linMotion.recedeSpeed.z;
+ if ( mode == MO_MOTSPEED ) return m_linMotion.motorSpeed.z;
+ if ( mode == MO_CURSPEED ) return m_linMotion.currentSpeed.z;
+ if ( mode == MO_REASPEED ) return m_linMotion.realSpeed.z;
+ return 0.0f;
+}
+
+// Specifies the rotation around the axis of walk.
+
+void CPhysics::SetCirMotion(PhysicsMode mode, Math::Vector value)
+{
+ if ( mode == MO_ADVACCEL ) m_cirMotion.advanceAccel = value;
+ if ( mode == MO_RECACCEL ) m_cirMotion.recedeAccel = value;
+ if ( mode == MO_STOACCEL ) m_cirMotion.stopAccel = value;
+ if ( mode == MO_TERSPEED ) m_cirMotion.terrainSpeed = value;
+ if ( mode == MO_TERSLIDE ) m_cirMotion.terrainSlide = value;
+ if ( mode == MO_MOTACCEL ) m_cirMotion.motorAccel = value;
+ if ( mode == MO_TERFORCE ) m_cirMotion.terrainForce = value;
+ if ( mode == MO_ADVSPEED ) m_cirMotion.advanceSpeed = value;
+ if ( mode == MO_RECSPEED ) m_cirMotion.recedeSpeed = value;
+ if ( mode == MO_MOTSPEED ) m_cirMotion.motorSpeed = value;
+ if ( mode == MO_CURSPEED ) m_cirMotion.currentSpeed = value;
+ if ( mode == MO_REASPEED ) m_cirMotion.realSpeed = value;
+}
+
+Math::Vector CPhysics::RetCirMotion(PhysicsMode mode)
+{
+ if ( mode == MO_ADVACCEL ) return m_cirMotion.advanceAccel;
+ if ( mode == MO_RECACCEL ) return m_cirMotion.recedeAccel;
+ if ( mode == MO_STOACCEL ) return m_cirMotion.stopAccel;
+ if ( mode == MO_TERSPEED ) return m_cirMotion.terrainSpeed;
+ if ( mode == MO_TERSLIDE ) return m_cirMotion.terrainSlide;
+ if ( mode == MO_MOTACCEL ) return m_cirMotion.motorAccel;
+ if ( mode == MO_TERFORCE ) return m_cirMotion.terrainForce;
+ if ( mode == MO_ADVSPEED ) return m_cirMotion.advanceSpeed;
+ if ( mode == MO_RECSPEED ) return m_cirMotion.recedeSpeed;
+ if ( mode == MO_MOTSPEED ) return m_cirMotion.motorSpeed;
+ if ( mode == MO_CURSPEED ) return m_cirMotion.currentSpeed;
+ if ( mode == MO_REASPEED ) return m_cirMotion.realSpeed;
+ return Math::Vector(0.0f, 0.0f, 0.0f);
+}
+
+void CPhysics::SetCirMotionX(PhysicsMode mode, float value)
+{
+ if ( mode == MO_ADVACCEL ) m_cirMotion.advanceAccel.x = value;
+ if ( mode == MO_RECACCEL ) m_cirMotion.recedeAccel.x = value;
+ if ( mode == MO_STOACCEL ) m_cirMotion.stopAccel.x = value;
+ if ( mode == MO_TERSPEED ) m_cirMotion.terrainSpeed.x = value;
+ if ( mode == MO_TERSLIDE ) m_cirMotion.terrainSlide.x = value;
+ if ( mode == MO_MOTACCEL ) m_cirMotion.motorAccel.x = value;
+ if ( mode == MO_TERFORCE ) m_cirMotion.terrainForce.x = value;
+ if ( mode == MO_ADVSPEED ) m_cirMotion.advanceSpeed.x = value;
+ if ( mode == MO_RECSPEED ) m_cirMotion.recedeSpeed.x = value;
+ if ( mode == MO_MOTSPEED ) m_cirMotion.motorSpeed.x = value;
+ if ( mode == MO_CURSPEED ) m_cirMotion.currentSpeed.x = value;
+ if ( mode == MO_REASPEED ) m_cirMotion.realSpeed.x = value;
+}
+
+float CPhysics::RetCirMotionX(PhysicsMode mode)
+{
+ if ( mode == MO_ADVACCEL ) return m_cirMotion.advanceAccel.x;
+ if ( mode == MO_RECACCEL ) return m_cirMotion.recedeAccel.x;
+ if ( mode == MO_STOACCEL ) return m_cirMotion.stopAccel.x;
+ if ( mode == MO_TERSPEED ) return m_cirMotion.terrainSpeed.x;
+ if ( mode == MO_TERSLIDE ) return m_cirMotion.terrainSlide.x;
+ if ( mode == MO_MOTACCEL ) return m_cirMotion.motorAccel.x;
+ if ( mode == MO_TERFORCE ) return m_cirMotion.terrainForce.x;
+ if ( mode == MO_ADVSPEED ) return m_cirMotion.advanceSpeed.x;
+ if ( mode == MO_RECSPEED ) return m_cirMotion.recedeSpeed.x;
+ if ( mode == MO_MOTSPEED ) return m_cirMotion.motorSpeed.x;
+ if ( mode == MO_CURSPEED ) return m_cirMotion.currentSpeed.x;
+ if ( mode == MO_REASPEED ) return m_cirMotion.realSpeed.x;
+ return 0.0f;
+}
+
+// Specifies the rotation direction.
+
+void CPhysics::SetCirMotionY(PhysicsMode mode, float value)
+{
+ if ( mode == MO_ADVACCEL ) m_cirMotion.advanceAccel.y = value;
+ if ( mode == MO_RECACCEL ) m_cirMotion.recedeAccel.y = value;
+ if ( mode == MO_STOACCEL ) m_cirMotion.stopAccel.y = value;
+ if ( mode == MO_TERSPEED ) m_cirMotion.terrainSpeed.y = value;
+ if ( mode == MO_TERSLIDE ) m_cirMotion.terrainSlide.y = value;
+ if ( mode == MO_MOTACCEL ) m_cirMotion.motorAccel.y = value;
+ if ( mode == MO_TERFORCE ) m_cirMotion.terrainForce.y = value;
+ if ( mode == MO_ADVSPEED ) m_cirMotion.advanceSpeed.y = value;
+ if ( mode == MO_RECSPEED ) m_cirMotion.recedeSpeed.y = value;
+ if ( mode == MO_MOTSPEED ) m_cirMotion.motorSpeed.y = value;
+ if ( mode == MO_CURSPEED ) m_cirMotion.currentSpeed.y = value;
+ if ( mode == MO_REASPEED ) m_cirMotion.realSpeed.y = value;
+}
+
+float CPhysics::RetCirMotionY(PhysicsMode mode)
+{
+ if ( mode == MO_ADVACCEL ) return m_cirMotion.advanceAccel.y;
+ if ( mode == MO_RECACCEL ) return m_cirMotion.recedeAccel.y;
+ if ( mode == MO_STOACCEL ) return m_cirMotion.stopAccel.y;
+ if ( mode == MO_TERSPEED ) return m_cirMotion.terrainSpeed.y;
+ if ( mode == MO_TERSLIDE ) return m_cirMotion.terrainSlide.y;
+ if ( mode == MO_MOTACCEL ) return m_cirMotion.motorAccel.y;
+ if ( mode == MO_TERFORCE ) return m_cirMotion.terrainForce.y;
+ if ( mode == MO_ADVSPEED ) return m_cirMotion.advanceSpeed.y;
+ if ( mode == MO_RECSPEED ) return m_cirMotion.recedeSpeed.y;
+ if ( mode == MO_MOTSPEED ) return m_cirMotion.motorSpeed.y;
+ if ( mode == MO_CURSPEED ) return m_cirMotion.currentSpeed.y;
+ if ( mode == MO_REASPEED ) return m_cirMotion.realSpeed.y;
+ return 0.0f;
+}
+
+// Specifies the rotation up/down.
+
+void CPhysics::SetCirMotionZ(PhysicsMode mode, float value)
+{
+ if ( mode == MO_ADVACCEL ) m_cirMotion.advanceAccel.z = value;
+ if ( mode == MO_RECACCEL ) m_cirMotion.recedeAccel.z = value;
+ if ( mode == MO_STOACCEL ) m_cirMotion.stopAccel.z = value;
+ if ( mode == MO_TERSPEED ) m_cirMotion.terrainSpeed.z = value;
+ if ( mode == MO_TERSLIDE ) m_cirMotion.terrainSlide.z = value;
+ if ( mode == MO_MOTACCEL ) m_cirMotion.motorAccel.z = value;
+ if ( mode == MO_TERFORCE ) m_cirMotion.terrainForce.z = value;
+ if ( mode == MO_ADVSPEED ) m_cirMotion.advanceSpeed.z = value;
+ if ( mode == MO_RECSPEED ) m_cirMotion.recedeSpeed.z = value;
+ if ( mode == MO_MOTSPEED ) m_cirMotion.motorSpeed.z = value;
+ if ( mode == MO_CURSPEED ) m_cirMotion.currentSpeed.z = value;
+ if ( mode == MO_REASPEED ) m_cirMotion.realSpeed.z = value;
+}
+
+float CPhysics::RetCirMotionZ(PhysicsMode mode)
+{
+ if ( mode == MO_ADVACCEL ) return m_cirMotion.advanceAccel.z;
+ if ( mode == MO_RECACCEL ) return m_cirMotion.recedeAccel.z;
+ if ( mode == MO_STOACCEL ) return m_cirMotion.stopAccel.z;
+ if ( mode == MO_TERSPEED ) return m_cirMotion.terrainSpeed.z;
+ if ( mode == MO_TERSLIDE ) return m_cirMotion.terrainSlide.z;
+ if ( mode == MO_MOTACCEL ) return m_cirMotion.motorAccel.z;
+ if ( mode == MO_TERFORCE ) return m_cirMotion.terrainForce.z;
+ if ( mode == MO_ADVSPEED ) return m_cirMotion.advanceSpeed.z;
+ if ( mode == MO_RECSPEED ) return m_cirMotion.recedeSpeed.z;
+ if ( mode == MO_MOTSPEED ) return m_cirMotion.motorSpeed.z;
+ if ( mode == MO_CURSPEED ) return m_cirMotion.currentSpeed.z;
+ if ( mode == MO_REASPEED ) return m_cirMotion.realSpeed.z;
+ return 0.0f;
+}
+
+
+// Returns the linear distance braking.
+//
+// v*v
+// d = -----
+// 2a
+
+float CPhysics::RetLinStopLength(PhysicsMode sMode, PhysicsMode aMode)
+{
+ float speed, accel;
+
+ speed = RetLinMotionX(sMode); // MO_ADVSPEED/MO_RECSPEED
+ accel = RetLinMotionX(aMode); // MO_ADVACCEL/MO_RECACCEL/MO_STOACCEL
+
+ if ( m_type == TYPE_FLYING && m_bLand ) // flying on the ground?
+ {
+ speed /= LANDING_SPEED;
+ accel *= LANDING_ACCEL;
+ }
+
+ return (speed*speed) / (accel*2.0f);
+}
+
+// Returns the angle of circular braking.
+
+float CPhysics::RetCirStopLength()
+{
+ return m_cirMotion.advanceSpeed.y * m_cirMotion.advanceSpeed.y /
+ m_cirMotion.stopAccel.y / 2.0f;
+}
+
+// Returns the length advanced into a second, on the ground, maximum speed.
+
+float CPhysics::RetLinMaxLength(float dir)
+{
+ float dist;
+
+ if ( dir > 0.0f ) dist = m_linMotion.advanceSpeed.x;
+ else dist = m_linMotion.recedeSpeed.x;
+
+ if ( m_type == TYPE_FLYING )
+ {
+ dist /= 5.0f;
+ }
+
+ return dist;
+}
+
+// Returns the time needed to travel some distance.
+
+float CPhysics::RetLinTimeLength(float dist, float dir)
+{
+ float accel, decel, dps;
+
+ if ( dir > 0.0f )
+ {
+ accel = RetLinStopLength(MO_ADVSPEED, MO_ADVACCEL);
+ decel = RetLinStopLength(MO_ADVSPEED, MO_STOACCEL);
+ }
+ else
+ {
+ accel = RetLinStopLength(MO_RECSPEED, MO_RECACCEL);
+ decel = RetLinStopLength(MO_RECSPEED, MO_STOACCEL);
+ }
+
+ dps = RetLinMaxLength(dir);
+
+ return (dist+accel+decel)/dps;
+}
+
+// Returns the length for a forward travel some distance, taking into account the accelerations / decelerations.
+
+float CPhysics::RetLinLength(float dist)
+{
+ float accDist, desDist;
+
+ if ( dist > 0.0f )
+ {
+ accDist = RetLinStopLength(MO_ADVSPEED, MO_ADVACCEL);
+ desDist = RetLinStopLength(MO_ADVSPEED, MO_STOACCEL);
+
+ if ( dist > accDist+desDist )
+ {
+ return dist-desDist;
+ }
+
+ return dist*m_linMotion.stopAccel.x /
+ (m_linMotion.advanceAccel.x+m_linMotion.stopAccel.x);
+ }
+ else
+ {
+ dist = -dist;
+ accDist = RetLinStopLength(MO_RECSPEED, MO_RECACCEL);
+ desDist = RetLinStopLength(MO_RECSPEED, MO_STOACCEL);
+
+ if ( dist > accDist+desDist )
+ {
+ return dist-desDist;
+ }
+
+ return dist*m_linMotion.stopAccel.x /
+ (m_linMotion.recedeAccel.x+m_linMotion.stopAccel.x);
+ }
+}
+
+
+// Management of an event.
+// Returns false if the object is destroyed.
+
+bool CPhysics::EventProcess(const Event &event)
+{
+ if ( !m_object->RetEnable() ) return true;
+
+ if ( m_brain != 0 )
+ {
+ m_brain->EventProcess(event);
+ }
+
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+ return true;
+}
+
+
+// Updates instructions for the motor speed.
+
+void CPhysics::MotorUpdate(float aTime, float rTime)
+{
+ ObjectType type;
+ CObject* power;
+ Math::Vector pos, motorSpeed;
+ float energy, speed, factor, h;
+
+ type = m_object->RetType();
+
+ motorSpeed = m_motorSpeed;
+
+ if ( type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ||
+ type == OBJECT_APOLLO2 ||
+ type == OBJECT_MOBILEdr )
+ {
+ power = 0;
+ }
+ else if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH )
+ {
+ power = 0;
+ if ( m_object->RetFret() != 0 && // carries something?
+ !m_object->RetCargo() )
+ {
+ motorSpeed.x *= 0.7f; // forward more slowly
+ motorSpeed.z *= 0.5f;
+ motorSpeed.y = -1.0f; // grave
+ }
+ if ( m_bSwim )
+ {
+ if ( m_bLand ) // deep in the water?
+ {
+ motorSpeed.x *= 0.4f; // forward more slowly
+ motorSpeed.z *= 0.5f;
+ motorSpeed.y *= 0.5f;
+
+ if ( m_object->RetFret() != 0 ) // carries something?
+ {
+ motorSpeed.x *= 0.2f;
+ motorSpeed.z *= 0.9f;
+ motorSpeed.y *= 0.2f;
+ }
+ }
+ else // swimming?
+ {
+ motorSpeed.x *= 0.2f; // forward more slowly
+ motorSpeed.z *= 0.5f;
+ motorSpeed.y *= 0.2f;
+ }
+ }
+ }
+ else
+ {
+ power = m_object->RetPower(); // searches for the object battery uses
+ if ( power == 0 || power->RetEnergy() == 0.0f ) // no battery or flat?
+ {
+ motorSpeed.x = 0.0f;
+ motorSpeed.z = 0.0f;
+ if ( m_bFreeze || m_bLand )
+ {
+ motorSpeed.y = 0.0f; // immobile
+ }
+ else
+ {
+ motorSpeed.y = -1.0f; // grave
+ }
+ SetMotor(false);
+ }
+ }
+
+ if ( m_object->RetDead() ) // dead man?
+ {
+ motorSpeed.x = 0.0f;
+ motorSpeed.z = 0.0f;
+ if ( m_motion->RetAction() == MHS_DEADw ) // drowned?
+ {
+ motorSpeed.y = 0.0f; // this is MHS_DEADw going back
+ }
+ else
+ {
+ motorSpeed.y = -1.0f; // grave
+ }
+ SetMotor(false);
+ }
+
+ if ( m_type == TYPE_FLYING && !m_bLand && motorSpeed.y > 0.0f )
+ {
+ pos = m_object->RetPosition(0);
+ h = m_terrain->RetFlyingLimit(pos, type==OBJECT_BEE);
+ h += m_object->RetCharacter()->height;
+ if ( pos.y > h-40.0f ) // almost at the top?
+ {
+ factor = 1.0f-(pos.y-(h-40.0f))/40.0f;
+ if ( factor < -1.0f ) factor = -1.0f;
+ if ( factor > 1.0f ) factor = 1.0f;
+ motorSpeed.y *= factor; // limit the rate of rise
+ }
+ }
+
+ if ( type != OBJECT_BEE &&
+ m_object->RetRange() > 0.0f ) // limited flight range?
+ {
+ if ( m_bLand || m_bSwim || m_bObstacle ) // on the ground or in the water?
+ {
+ factor = 1.0f;
+ if ( m_bObstacle ) factor = 3.0f; // in order to leave!
+ if ( m_bSwim ) factor = 3.0f; // cools faster in water
+ m_reactorRange += rTime*(1.0f/5.0f)*factor;
+ if ( m_reactorRange > 1.0f )
+ {
+ m_reactorRange = 1.0f;
+ if ( m_bLowLevel && m_object->RetSelect() ) // beep cool?
+ {
+ m_sound->Play(SOUND_INFO, m_object->RetPosition(0), 1.0f, 2.0f);
+ m_bLowLevel = false;
+ }
+ }
+ m_bObstacle = false;
+ }
+ else // in flight?
+ {
+ m_reactorRange -= rTime*(1.0f/m_object->RetRange());
+ if ( m_reactorRange < 0.0f ) m_reactorRange = 0.0f;
+ if ( m_reactorRange < 0.5f ) m_bLowLevel = true;
+ }
+
+ if ( m_reactorRange == 0.0f ) // reactor tilt?
+ {
+ motorSpeed.y = -1.0f; // grave
+ }
+ }
+
+//? MotorParticule(aTime);
+
+ // Forward/backward.
+ if ( motorSpeed.x > 0.0f )
+ {
+ m_linMotion.motorAccel.x = m_linMotion.advanceAccel.x;
+ m_linMotion.motorSpeed.x = m_linMotion.advanceSpeed.x * motorSpeed.x;
+ }
+ if ( motorSpeed.x < 0.0f )
+ {
+ m_linMotion.motorAccel.x = m_linMotion.recedeAccel.x;
+ m_linMotion.motorSpeed.x = m_linMotion.recedeSpeed.x * motorSpeed.x;
+ }
+ if ( motorSpeed.x == 0.0f )
+ {
+ m_linMotion.motorAccel.x = m_linMotion.stopAccel.x;
+ m_linMotion.motorSpeed.x = 0.0f;
+ }
+
+ // Up/down.
+ if ( motorSpeed.y > 0.0f )
+ {
+ m_linMotion.motorAccel.y = m_linMotion.advanceAccel.y;
+ m_linMotion.motorSpeed.y = m_linMotion.advanceSpeed.y * motorSpeed.y;
+ }
+ if ( motorSpeed.y < 0.0f )
+ {
+ m_linMotion.motorAccel.y = m_linMotion.recedeAccel.y;
+ m_linMotion.motorSpeed.y = m_linMotion.recedeSpeed.y * motorSpeed.y;
+ }
+ if ( motorSpeed.y == 0.0f )
+ {
+ m_linMotion.motorAccel.y = m_linMotion.stopAccel.y;
+ m_linMotion.motorSpeed.y = 0.0f;
+ }
+
+ // Turn left/right.
+ speed = motorSpeed.z;
+//? if ( motorSpeed.x < 0.0f ) speed = -speed; // reverse if running back
+
+ if ( motorSpeed.z > 0.0f )
+ {
+ m_cirMotion.motorAccel.y = m_cirMotion.advanceAccel.y;
+ m_cirMotion.motorSpeed.y = m_cirMotion.advanceSpeed.y * speed;
+ }
+ if ( motorSpeed.z < 0.0f )
+ {
+ m_cirMotion.motorAccel.y = m_cirMotion.recedeAccel.y;
+ m_cirMotion.motorSpeed.y = m_cirMotion.recedeSpeed.y * speed;
+ }
+ if ( motorSpeed.z == 0.0f )
+ {
+ m_cirMotion.motorAccel.y = m_cirMotion.stopAccel.y;
+ m_cirMotion.motorSpeed.y = 0.0f;
+ }
+
+ if ( m_type == TYPE_FLYING && m_bLand ) // flying on the ground?
+ {
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH )
+ {
+ factor = LANDING_ACCELh;
+ }
+ else
+ {
+ factor = LANDING_ACCEL;
+ }
+ m_linMotion.motorAccel.x = m_linMotion.stopAccel.x*factor;
+ m_cirMotion.motorAccel.y = m_cirMotion.stopAccel.y*factor;
+
+ pos = m_object->RetPosition(0);
+ h = m_terrain->RetFlyingLimit(pos, type==OBJECT_BEE);
+ h += m_object->RetCharacter()->height;
+ if ( motorSpeed.y > 0.0f && m_reactorRange > 0.1f && pos.y < h )
+ {
+ m_bLand = false; // take off
+ SetMotor(true);
+ pos.y += 0.05f; // small initial height (startup)
+ m_object->SetPosition(0, pos);
+ }
+ }
+
+ if ( m_type == TYPE_ROLLING )
+ {
+ if ( motorSpeed.x == 0.0f &&
+ motorSpeed.z == 0.0f )
+ {
+ SetMotor(false);
+ }
+ else
+ {
+ SetMotor(true);
+ }
+ }
+
+ if ( power != 0 ) // battery transported?
+ {
+ factor = 1.0f;
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEii ) factor = 0.5f;
+
+ factor /= power->RetCapacity();
+
+ energy = power->RetEnergy();
+ energy -= fabs(motorSpeed.x)*rTime*factor*0.005f;
+ energy -= fabs(motorSpeed.z)*rTime*factor*0.005f;
+
+ if ( m_type == TYPE_FLYING && motorSpeed.y > 0.0f )
+ {
+ energy -= motorSpeed.y*rTime*factor*0.01f;
+ }
+ if ( energy < 0.0f ) energy = 0.0f;
+ power->SetEnergy(energy);
+ }
+}
+
+
+// Updates the effects of vibration and tilt.
+
+void CPhysics::EffectUpdate(float aTime, float rTime)
+{
+ Character* character;
+ Math::Vector vibLin, vibCir, incl;
+ float speedLin, speedCir, accel;
+ ObjectType type;
+ bool bOnBoard;
+
+ if ( !m_engine->IsVisiblePoint(m_object->RetPosition(0)) ) return;
+
+ type = m_object->RetType();
+ character = m_object->RetCharacter();
+
+ bOnBoard = false;
+ if ( m_object->RetSelect() &&
+ m_camera->RetType() == CAMERA_ONBOARD )
+ {
+ bOnBoard = true;
+ }
+
+ vibLin = m_motion->RetLinVibration();
+ vibCir = m_motion->RetCirVibration();
+ incl = m_motion->RetInclinaison();
+
+ if ( type == OBJECT_HUMAN || // human?
+ type == OBJECT_TECH )
+ {
+ if ( !m_bLand && !m_bSwim ) // in flight?
+ {
+ vibLin.y = sinf(aTime*2.00f)*0.5f+
+ sinf(aTime*2.11f)*0.3f;
+
+ vibCir.z = sinf(aTime*Math::PI* 2.01f)*(Math::PI/150.0f)+
+ sinf(aTime*Math::PI* 2.51f)*(Math::PI/200.0f)+
+ sinf(aTime*Math::PI*19.01f)*(Math::PI/400.0f);
+
+ vibCir.x = sinf(aTime*Math::PI* 2.03f)*(Math::PI/150.0f)+
+ sinf(aTime*Math::PI* 2.52f)*(Math::PI/200.0f)+
+ sinf(aTime*Math::PI*19.53f)*(Math::PI/400.0f);
+
+ speedLin = m_linMotion.realSpeed.x / m_linMotion.advanceSpeed.x;
+ speedCir = m_cirMotion.realSpeed.y / m_cirMotion.advanceSpeed.y;
+ incl.x = -speedLin*speedCir*0.5f; // looks if turn
+
+//? speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.5f;
+ speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.2f;
+ speedLin /= m_linMotion.advanceSpeed.x;
+ m_linMotion.finalInclin.z = speedLin*1.4f;
+ if ( incl.z < m_linMotion.finalInclin.z )
+ {
+ incl.z += rTime*0.4f;
+ if ( incl.z > m_linMotion.finalInclin.z )
+ {
+ incl.z = m_linMotion.finalInclin.z;
+ }
+ }
+ else if ( incl.z > m_linMotion.finalInclin.z )
+ {
+ incl.z -= rTime*0.4f;
+ if ( incl.z < m_linMotion.finalInclin.z )
+ {
+ incl.z = m_linMotion.finalInclin.z;
+ }
+ }
+
+ vibLin *= m_linVibrationFactor;
+ vibCir *= m_cirVibrationFactor;
+ incl *= m_inclinaisonFactor;
+
+ m_motion->SetLinVibration(vibLin);
+ m_motion->SetCirVibration(vibCir);
+ m_motion->SetInclinaison(incl);
+ }
+ else if ( m_bSwim ) // swimming?
+ {
+ vibLin.y = sinf(aTime*2.00f)*0.5f+
+ sinf(aTime*2.11f)*0.3f;
+
+ vibCir.z = sinf(aTime*Math::PI* 2.01f)*(Math::PI/150.0f)+
+ sinf(aTime*Math::PI* 2.51f)*(Math::PI/200.0f)+
+//? sinf(aTime*Math::PI*19.01f)*(Math::PI/400.0f)-Math::PI/2.0f;
+ sinf(aTime*Math::PI*19.01f)*(Math::PI/400.0f);
+
+ vibCir.x = sinf(aTime*Math::PI* 2.03f)*(Math::PI/150.0f)+
+ sinf(aTime*Math::PI* 2.52f)*(Math::PI/200.0f)+
+ sinf(aTime*Math::PI*19.53f)*(Math::PI/400.0f);
+
+ speedLin = m_linMotion.realSpeed.x / m_linMotion.advanceSpeed.x;
+ speedCir = m_cirMotion.realSpeed.y / m_cirMotion.advanceSpeed.y;
+ incl.x = -speedLin*speedCir*5.0f; // looks if turn
+
+//? speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.5f;
+ speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.2f;
+ speedLin /= m_linMotion.advanceSpeed.x;
+ m_linMotion.finalInclin.z = speedLin*1.4f;
+ if ( incl.z < m_linMotion.finalInclin.z )
+ {
+ incl.z += rTime*0.4f;
+ if ( incl.z > m_linMotion.finalInclin.z )
+ {
+ incl.z = m_linMotion.finalInclin.z;
+ }
+ }
+ else if ( incl.z > m_linMotion.finalInclin.z )
+ {
+ incl.z -= rTime*0.4f;
+ if ( incl.z < m_linMotion.finalInclin.z )
+ {
+ incl.z = m_linMotion.finalInclin.z;
+ }
+ }
+
+ if ( m_linMotion.realSpeed.y > 0.0f ) // up?
+ {
+ vibCir.z += m_linMotion.realSpeed.y*0.05f;
+ }
+ else // down?
+ {
+ vibCir.z += m_linMotion.realSpeed.y*0.12f;
+ }
+ vibCir.z -= Math::PI*0.4f;
+
+ vibLin *= m_linVibrationFactor;
+ vibCir *= m_cirVibrationFactor;
+ incl *= m_inclinaisonFactor;
+
+ m_motion->SetLinVibration(vibLin);
+ m_motion->SetCirVibration(vibCir);
+ m_motion->SetInclinaison(incl);
+ }
+ else
+ {
+ m_motion->SetLinVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+//? m_motion->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+//? m_motion->SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
+ }
+ }
+
+ if ( type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_APOLLO2 ) // wheels?
+ {
+ speedLin = m_linMotion.realSpeed.x / m_linMotion.advanceSpeed.x;
+ speedCir = m_cirMotion.realSpeed.y / m_cirMotion.advanceSpeed.y;
+ incl.x = speedLin*speedCir*0.20f; // looks if turn
+ if ( type == OBJECT_APOLLO2 ) incl.x *= 0.25f;
+
+ speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x;
+ speedLin /= m_linMotion.advanceSpeed.x;
+ if ( speedLin > 1.0f ) speedLin = 1.0f;
+ m_linMotion.finalInclin.z = -speedLin*0.30f;
+ accel = (0.40f-fabs(incl.z))*4.0f;
+ if ( incl.z < m_linMotion.finalInclin.z )
+ {
+ incl.z += rTime*accel;
+ if ( incl.z > m_linMotion.finalInclin.z )
+ {
+ incl.z = m_linMotion.finalInclin.z;
+ }
+ }
+ else if ( incl.z > m_linMotion.finalInclin.z )
+ {
+ incl.z -= rTime*accel;
+ if ( incl.z < m_linMotion.finalInclin.z )
+ {
+ incl.z = m_linMotion.finalInclin.z;
+ }
+ }
+ if ( bOnBoard ) incl.z *= 0.1f;
+ if ( type == OBJECT_APOLLO2 ) incl.z *= 0.25f;
+ m_object->SetInclinaison(incl);
+
+ vibLin.x = 0.0f;
+ vibLin.z = 0.0f;
+ vibLin.y = fabs(character->wheelFront*sinf(incl.z))*0.8f +
+ fabs(character->wheelRight*sinf(incl.x))*0.5f;
+ m_motion->SetLinVibration(vibLin);
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEft ) // fliyng?
+ {
+ if ( m_bLand ) // on the ground?
+ {
+ m_motion->SetLinVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ m_motion->SetCirVibration(Math::Vector(0.0f, 0.0f, 0.0f));
+ m_motion->SetInclinaison(Math::Vector(0.0f, 0.0f, 0.0f));
+ }
+ else // in flight?
+ {
+ vibLin.y = sinf(aTime*2.00f)*0.5f+
+ sinf(aTime*2.11f)*0.3f;
+
+ vibCir.z = sinf(aTime*Math::PI* 2.01f)*(Math::PI/150.0f)+
+ sinf(aTime*Math::PI* 2.51f)*(Math::PI/200.0f)+
+ sinf(aTime*Math::PI*19.01f)*(Math::PI/400.0f);
+
+ vibCir.x = sinf(aTime*Math::PI* 2.03f)*(Math::PI/150.0f)+
+ sinf(aTime*Math::PI* 2.52f)*(Math::PI/200.0f)+
+ sinf(aTime*Math::PI*19.53f)*(Math::PI/400.0f);
+
+ if ( bOnBoard ) vibCir *= 0.4f;
+
+ speedLin = m_linMotion.realSpeed.x / m_linMotion.advanceSpeed.x;
+ speedCir = m_cirMotion.realSpeed.y / m_cirMotion.advanceSpeed.y;
+ incl.x = -speedLin*speedCir*0.5f; // looks if turn
+
+//? speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.5f;
+ speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.2f;
+ speedLin /= m_linMotion.advanceSpeed.x;
+ m_linMotion.finalInclin.z = speedLin*0.8f;
+ if ( incl.z < m_linMotion.finalInclin.z )
+ {
+ incl.z += rTime*0.4f;
+ if ( incl.z > m_linMotion.finalInclin.z )
+ {
+ incl.z = m_linMotion.finalInclin.z;
+ }
+ }
+ else if ( incl.z > m_linMotion.finalInclin.z )
+ {
+ incl.z -= rTime*0.4f;
+ if ( incl.z < m_linMotion.finalInclin.z )
+ {
+ incl.z = m_linMotion.finalInclin.z;
+ }
+ }
+//? if ( bOnBoard ) incl.z *= 0.5f;
+
+ vibLin *= m_linVibrationFactor;
+ vibCir *= m_cirVibrationFactor;
+ incl *= m_inclinaisonFactor;
+
+ m_motion->SetLinVibration(vibLin);
+ m_motion->SetCirVibration(vibCir);
+ m_motion->SetInclinaison(incl);
+ }
+ }
+
+ if ( type == OBJECT_BEE ) // bee?
+ {
+ if ( !m_bLand ) // in flight?
+ {
+ vibLin.y = sinf(aTime*2.00f)*0.5f+
+ sinf(aTime*2.11f)*0.3f;
+
+ vibCir.z = (Math::Rand()-0.5f)*0.1f+
+ sinf(aTime*Math::PI* 2.01f)*(Math::PI/150.0f)+
+ sinf(aTime*Math::PI* 2.51f)*(Math::PI/200.0f)+
+ sinf(aTime*Math::PI*19.01f)*(Math::PI/400.0f);
+
+ vibCir.x = (Math::Rand()-0.5f)*0.1f+
+ sinf(aTime*Math::PI* 2.03f)*(Math::PI/150.0f)+
+ sinf(aTime*Math::PI* 2.52f)*(Math::PI/200.0f)+
+ sinf(aTime*Math::PI*19.53f)*(Math::PI/400.0f);
+
+ speedLin = m_linMotion.realSpeed.x / m_linMotion.advanceSpeed.x;
+ speedCir = m_cirMotion.realSpeed.y / m_cirMotion.advanceSpeed.y;
+ incl.x = -speedLin*speedCir*1.5f; // looks if turn
+
+//? speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.5f;
+ speedLin = m_linMotion.currentSpeed.x - m_linMotion.motorSpeed.x*1.2f;
+ speedLin /= m_linMotion.advanceSpeed.x;
+ m_linMotion.finalInclin.z = speedLin*1.4f;
+ if ( incl.z < m_linMotion.finalInclin.z )
+ {
+ incl.z += rTime*1.6f;
+ if ( incl.z > m_linMotion.finalInclin.z )
+ {
+ incl.z = m_linMotion.finalInclin.z;
+ }
+ }
+ else if ( incl.z > m_linMotion.finalInclin.z )
+ {
+ incl.z -= rTime*1.6f;
+ if ( incl.z < m_linMotion.finalInclin.z )
+ {
+ incl.z = m_linMotion.finalInclin.z;
+ }
+ }
+
+ vibLin *= m_linVibrationFactor;
+ vibCir *= m_cirVibrationFactor;
+ incl *= m_inclinaisonFactor;
+
+ m_motion->SetLinVibration(vibLin);
+ m_motion->SetCirVibration(vibCir);
+ m_motion->SetInclinaison(incl);
+ }
+ }
+}
+
+
+// Updates structure Motion.
+
+void CPhysics::UpdateMotionStruct(float rTime, Motion &motion)
+{
+ float speed, motor;
+
+ // Management for the coordinate x.
+ speed = motion.currentSpeed.x;
+ motor = motion.motorSpeed.x * m_inclinaisonFactor;
+ if ( speed < motor )
+ {
+ speed += rTime*motion.motorAccel.x; // accelerates
+ if ( speed > motor )
+ {
+ speed = motor; // does not exceed the speed
+ }
+ }
+ if ( speed > motor )
+ {
+ speed -= rTime*motion.motorAccel.x; // decelerates
+ if ( speed < motor )
+ {
+ speed = motor; // does not exceed the speed
+ }
+ }
+ motion.currentSpeed.x = speed;
+ motion.realSpeed.x = speed;
+
+ if ( fabs(motion.terrainSpeed.x) > motion.terrainSlide.x )
+ {
+ if ( motion.terrainSpeed.x > 0 )
+ {
+ speed = motion.terrainSpeed.x - motion.terrainSlide.x;
+ }
+ else
+ {
+ speed = motion.terrainSpeed.x + motion.terrainSlide.x;
+ }
+ motion.realSpeed.x += speed;
+ }
+
+ // Management for the coordinate y.
+ speed = motion.currentSpeed.y;
+ motor = motion.motorSpeed.y; // unlimited speed!
+ if ( speed < motor )
+ {
+ speed += rTime*motion.motorAccel.y; // accelerates
+ if ( speed > motor )
+ {
+ speed = motor; // does not exceed the speed
+ }
+ }
+ if ( speed > motor )
+ {
+ speed -= rTime*motion.motorAccel.y; // decelerates
+ if ( speed < motor )
+ {
+ speed = motor; // does not exceed the speed
+ }
+ }
+ motion.currentSpeed.y = speed;
+ motion.realSpeed.y = speed;
+
+ if ( fabs(motion.terrainSpeed.y) > motion.terrainSlide.y )
+ {
+ if ( motion.terrainSpeed.y > 0 )
+ {
+ speed = motion.terrainSpeed.y - motion.terrainSlide.y;
+ }
+ else
+ {
+ speed = motion.terrainSpeed.y + motion.terrainSlide.y;
+ }
+ motion.realSpeed.y += speed;
+ }
+
+ // Management for the coordinate z.
+ speed = motion.currentSpeed.z;
+ motor = motion.motorSpeed.z * m_inclinaisonFactor;
+ if ( speed < motor )
+ {
+ speed += rTime*motion.motorAccel.z; // accelerates
+ if ( speed > motor )
+ {
+ speed = motor; // does not exceed the speed
+ }
+ }
+ if ( speed > motor )
+ {
+ speed -= rTime*motion.motorAccel.z; // decelerates
+ if ( speed < motor )
+ {
+ speed = motor; // does not exceed the speed
+ }
+ }
+ motion.currentSpeed.z = speed;
+ motion.realSpeed.z = speed;
+
+ if ( fabs(motion.terrainSpeed.z) > motion.terrainSlide.z )
+ {
+ if ( motion.terrainSpeed.z > 0 )
+ {
+ speed = motion.terrainSpeed.z - motion.terrainSlide.z;
+ }
+ else
+ {
+ speed = motion.terrainSpeed.z + motion.terrainSlide.z;
+ }
+ motion.realSpeed.z += speed;
+ }
+}
+
+
+// Makes physics evolve as time elapsed.
+// Returns false if the object is destroyed.
+//
+// a: acceleration
+// v1: velocity at time t1
+// v2: velocity at time t2
+// dt: time elapsed since t1, then: dt = t2-t1
+// dd: difference in distance (advance)
+//
+// v2 = v1 + a*dt
+// dd = v2*dt
+
+bool CPhysics::EventFrame(const Event &event)
+{
+ ObjectType type;
+ Math::Matrix objRotate, matRotate;
+ Math::Vector iPos, iAngle, tAngle, pos, newpos, angle, newangle, n;
+ float h, w;
+ int i;
+
+ if ( m_engine->RetPause() ) return true;
+
+ m_time += event.rTime;
+ m_timeUnderWater += event.rTime;
+ m_soundTimeJostle += event.rTime;
+
+ type = m_object->RetType();
+
+ FrameParticule(m_time, event.rTime);
+ MotorUpdate(m_time, event.rTime);
+ EffectUpdate(m_time, event.rTime);
+ WaterFrame(m_time, event.rTime);
+
+ iPos = pos = m_object->RetPosition(0);
+ iAngle = angle = m_object->RetAngle(0);
+
+ // Accelerate is the descent, brake is the ascent.
+ if ( m_bFreeze || m_object->RetDead() )
+ {
+ m_linMotion.terrainSpeed.x = 0.0f;
+ m_linMotion.terrainSpeed.z = 0.0f;
+ m_linMotion.terrainSpeed.y = 0.0f;
+ }
+ else
+ {
+ tAngle = angle;
+ h = m_terrain->RetBuildingFactor(pos);
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH )
+ {
+ if ( m_linMotion.currentSpeed.x == 0.0f )
+ {
+ h *= 0.5f; // immobile man -> slippage
+ }
+ FloorAngle(pos, tAngle); // calculates the angle with the ground
+ }
+#if 1
+ if ( pos.y < m_water->RetLevel(m_object) ) // underwater?
+ {
+ h *= 0.5f;
+ }
+#endif
+//? m_linMotion.terrainSpeed.x = -tAngle.z*m_linMotion.terrainForce.x*h;
+//? m_linMotion.terrainSpeed.z = tAngle.x*m_linMotion.terrainForce.z*h;
+//? m_linMotion.terrainSpeed.x = -sinf(tAngle.z)*Math::PI*0.5f*m_linMotion.terrainForce.x*h;
+//? m_linMotion.terrainSpeed.z = sinf(tAngle.x)*Math::PI*0.5f*m_linMotion.terrainForce.z*h;
+ m_linMotion.terrainSpeed.x = -tanf(tAngle.z)*0.9f*m_linMotion.terrainForce.x*h;
+ m_linMotion.terrainSpeed.z = tanf(tAngle.x)*0.9f*m_linMotion.terrainForce.z*h;
+ m_linMotion.terrainSpeed.y = 0.0f;
+
+ // If the terrain is very steep, do not exaggerate!
+ if ( m_linMotion.terrainSpeed.x > 50.0f ) m_linMotion.terrainSpeed.x = 20.0f;
+ if ( m_linMotion.terrainSpeed.x < -50.0f ) m_linMotion.terrainSpeed.x = -20.0f;
+ if ( m_linMotion.terrainSpeed.z > 50.0f ) m_linMotion.terrainSpeed.z = 20.0f;
+ if ( m_linMotion.terrainSpeed.z < -50.0f ) m_linMotion.terrainSpeed.z = -20.0f;
+ }
+
+ if ( type == OBJECT_BEE && !m_bLand )
+ {
+ h = m_floorLevel; // ground level
+ w = m_water->RetLevel(m_object);
+ if ( h < w ) h = w;
+ h = pos.y-h-10.0f; // maximum height (*)
+ if ( h < 0.0f ) h = 0.0f;
+ m_linMotion.terrainSpeed.y = -h*2.5f; // is not above
+ }
+
+ // (*) High enough to pass over the tower defense (OBJECT_TOWER),
+ // but not too much to pass under the cover of the ship (OBJECT_BASE)!
+
+ UpdateMotionStruct(event.rTime, m_linMotion);
+ UpdateMotionStruct(event.rTime, m_cirMotion);
+
+ newangle = angle + event.rTime*m_cirMotion.realSpeed;
+ Math::LoadRotationZXYMatrix(matRotate, newangle);
+ newpos = event.rTime*m_linMotion.realSpeed;
+ newpos = Transform(matRotate, newpos);
+ newpos += pos;
+
+ m_terrain->LimitPos(newpos);
+
+ if ( m_type == TYPE_FLYING && !m_bLand )
+ {
+ h = m_terrain->RetFlyingLimit(newpos, type==OBJECT_BEE);
+ h += m_object->RetCharacter()->height;
+ if ( newpos.y > h ) newpos.y = h;
+ }
+
+ if ( m_bForceUpdate ||
+ newpos.x != pos.x ||
+ newpos.y != pos.y ||
+ newpos.z != pos.z ||
+ newangle.x != angle.x ||
+ newangle.y != angle.y ||
+ newangle.z != angle.z )
+ {
+ FloorAdapt(m_time, event.rTime, newpos, newangle);
+ }
+
+ if ( m_bForceUpdate ||
+ newpos.x != pos.x ||
+ newpos.y != pos.y ||
+ newpos.z != pos.z )
+ {
+ i = ObjectAdapt(newpos, newangle);
+ if ( i == 2 ) // object destroyed?
+ {
+ return false;
+ }
+ if ( i == 1 ) // immobile object?
+ {
+ newpos = iPos; // keeps the initial position, but accepts the rotation
+ }
+ }
+
+ if ( newangle.x != angle.x ||
+ newangle.y != angle.y ||
+ newangle.z != angle.z )
+ {
+ m_object->SetAngle(0, newangle);
+ }
+
+ if ( newpos.x != pos.x ||
+ newpos.y != pos.y ||
+ newpos.z != pos.z )
+ {
+ m_object->SetPosition(0, newpos);
+ }
+
+ MotorParticule(m_time, event.rTime);
+ SoundMotor(event.rTime);
+
+ m_bForceUpdate = false;
+
+ return true;
+}
+
+// Starts or stops the engine sounds.
+
+void CPhysics::SoundMotor(float rTime)
+{
+ CObject* power;
+ ObjectType type;
+ float energy;
+
+ m_lastSoundInsect -= rTime;
+ type = m_object->RetType();
+
+ if ( type == OBJECT_MOTHER )
+ {
+ if ( m_lastSoundInsect <= 0.0f && m_object->RetActif() )
+ {
+ m_sound->Play(SOUND_INSECTm, m_object->RetPosition(0));
+ if ( m_bMotor ) m_lastSoundInsect = 0.4f+Math::Rand()*2.5f;
+ else m_lastSoundInsect = 1.5f+Math::Rand()*4.0f;
+ }
+ }
+ else if ( type == OBJECT_ANT )
+ {
+ if ( m_object->RetBurn() ||
+ m_object->RetFixed() )
+ {
+ if ( m_lastSoundInsect <= 0.0f )
+ {
+ m_sound->Play(SOUND_INSECTa, m_object->RetPosition(0), 1.0f, 1.5f+Math::Rand()*0.5f);
+ m_lastSoundInsect = 0.4f+Math::Rand()*0.6f;
+ }
+ }
+ else if ( m_object->RetActif() )
+ {
+ if ( m_lastSoundInsect <= 0.0f )
+ {
+ m_sound->Play(SOUND_INSECTa, m_object->RetPosition(0));
+ if ( m_bMotor ) m_lastSoundInsect = 0.4f+Math::Rand()*2.5f;
+ else m_lastSoundInsect = 1.5f+Math::Rand()*4.0f;
+ }
+ }
+ }
+ else if ( type == OBJECT_BEE )
+ {
+ if ( m_object->RetActif() )
+ {
+ if ( m_lastSoundInsect <= 0.0f )
+ {
+ m_sound->Play(SOUND_INSECTb, m_object->RetPosition(0));
+ if ( m_bMotor ) m_lastSoundInsect = 0.4f+Math::Rand()*2.5f;
+ else m_lastSoundInsect = 1.5f+Math::Rand()*4.0f;
+ }
+ }
+ else if ( m_object->RetBurn() )
+ {
+ if ( m_lastSoundInsect <= 0.0f )
+ {
+ m_sound->Play(SOUND_INSECTb, m_object->RetPosition(0), 1.0f, 1.5f+Math::Rand()*0.5f);
+ m_lastSoundInsect = 0.3f+Math::Rand()*0.5f;
+ }
+ }
+ }
+ else if ( type == OBJECT_WORM )
+ {
+ if ( m_object->RetActif() )
+ {
+ if ( m_lastSoundInsect <= 0.0f )
+ {
+ m_sound->Play(SOUND_INSECTw, m_object->RetPosition(0));
+ if ( m_bMotor ) m_lastSoundInsect = 0.4f+Math::Rand()*2.5f;
+ else m_lastSoundInsect = 1.5f+Math::Rand()*4.0f;
+ }
+ }
+ else if ( m_object->RetBurn() )
+ {
+ if ( m_lastSoundInsect <= 0.0f )
+ {
+ m_sound->Play(SOUND_INSECTw, m_object->RetPosition(0), 1.0f, 1.5f+Math::Rand()*0.5f);
+ m_lastSoundInsect = 0.2f+Math::Rand()*0.2f;
+ }
+ }
+ }
+ else if ( type == OBJECT_SPIDER )
+ {
+ if ( m_object->RetBurn() ||
+ m_object->RetFixed() )
+ {
+ if ( m_lastSoundInsect <= 0.0f )
+ {
+ m_sound->Play(SOUND_INSECTs, m_object->RetPosition(0), 1.0f, 1.5f+Math::Rand()*0.5f);
+ m_lastSoundInsect = 0.4f+Math::Rand()*0.6f;
+ }
+ }
+ else if ( m_object->RetActif() )
+ {
+ if ( m_lastSoundInsect <= 0.0f )
+ {
+ m_sound->Play(SOUND_INSECTs, m_object->RetPosition(0));
+ if ( m_bMotor ) m_lastSoundInsect = 0.4f+Math::Rand()*2.5f;
+ else m_lastSoundInsect = 1.5f+Math::Rand()*4.0f;
+ }
+ }
+ }
+ else // vehicle?
+ {
+ if ( m_type == TYPE_ROLLING )
+ {
+ if ( m_bMotor && m_object->RetActif() )
+ {
+ SoundMotorFull(rTime, type); // full diet
+ }
+ else
+ {
+ energy = 0.0f;
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ }
+
+ if ( m_object->RetSelect() &&
+ energy != 0.0f )
+ {
+ SoundMotorSlow(rTime, type); // in slow motion
+ }
+ else
+ {
+ SoundMotorStop(rTime, type); // to the stop
+ }
+ }
+ }
+
+ if ( m_type == TYPE_FLYING )
+ {
+ if ( m_bMotor && !m_bSwim &&
+ m_object->RetActif() && !m_object->RetDead() )
+ {
+ SoundReactorFull(rTime, type); // full diet
+ }
+ else
+ {
+ SoundReactorStop(rTime, type); // to the stop
+ }
+ }
+ }
+}
+
+// Detonates the object if it is underwater.
+
+void CPhysics::WaterFrame(float aTime, float rTime)
+{
+ ObjectType type;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float level;
+
+ level = m_water->RetLevel();
+ if ( level == 0.0f ) return; // no water?
+ if ( m_object->RetTruck() != 0 ) return; // object transported?
+
+ // Management of flames into the lava.
+ pos = m_object->RetPosition(0);
+ if ( m_water->RetLava() &&
+ pos.y-m_object->RetCharacter()->height <= level )
+ {
+ if ( m_lastFlameParticule+m_engine->ParticuleAdapt(0.05f) <= aTime )
+ {
+ m_lastFlameParticule = aTime;
+
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*3.0f;
+ pos.z += (Math::Rand()-0.5f)*3.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = Math::Rand()*5.0f+3.0f;
+ dim.x = Math::Rand()*2.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f);
+
+ pos = m_object->RetPosition(0);
+ pos.y -= 2.0f;
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 6.0f+Math::Rand()*6.0f+6.0f;
+ dim.x = Math::Rand()*1.5f+1.0f+3.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
+ }
+ }
+
+ pos = m_object->RetPosition(0);
+ if ( pos.y >= m_water->RetLevel(m_object) ) return; // out of water?
+
+ type = m_object->RetType();
+ if ( type == OBJECT_TOTO ) return;
+ if ( type == OBJECT_NULL ) return;
+
+ if ( !m_object->RetActif() ) return;
+ if ( m_object->RetResetBusy() ) return; // reset in progress?
+
+ if ( m_water->RetLava() ||
+ (type == OBJECT_HUMAN &&
+ m_object->RetOption() != 0 ) || // human without a helmet?
+ 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_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr ||
+ type == OBJECT_APOLLO2 ) // vehicle not underwater?
+ {
+ m_object->ExploObject(EXPLO_WATER, 1.0f); // starts explosion
+ }
+}
+
+// Sounds the engine at full power.
+
+void CPhysics::SoundMotorFull(float rTime, ObjectType type)
+{
+ Sound sound;
+ float amplitude, time, freq;
+
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEis )
+ {
+ if ( m_soundChannel == -1 )
+ {
+ m_soundChannel = m_sound->Play(SOUND_MOTORi, m_object->RetPosition(0), 0.0f, 1.0f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 0.2f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_LOOP);
+ }
+ else
+ {
+ m_sound->Position(m_soundChannel, m_object->RetPosition(0));
+ }
+
+ freq = 1.0f+m_linMotion.terrainSpeed.x/50.0f;
+ if ( m_linMotion.realSpeed.x == 0.0f )
+ {
+ freq -= fabs(m_cirMotion.realSpeed.y/3.0f);
+ }
+ else
+ {
+ freq -= fabs(m_cirMotion.realSpeed.y/4.0f);
+ }
+ m_sound->Frequency(m_soundChannel, freq);
+
+ return;
+ }
+
+ if ( type == OBJECT_MOBILEsa )
+ {
+ sound = SOUND_MOTORs;
+ amplitude = 0.6f;
+ time = 0.5f;
+ }
+ else if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ sound = SOUND_MOTORr;
+ amplitude = 1.0f;
+ time = 0.7f;
+ }
+ else if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts )
+ {
+ sound = SOUND_MOTORt;
+ amplitude = 1.0f;
+ time = 0.5f;
+ }
+ else if ( type == OBJECT_APOLLO2 )
+ {
+ sound = SOUND_MANIP;
+ amplitude = 1.0f;
+ time = 0.5f;
+ }
+ else
+ {
+ sound = SOUND_MOTORw;
+ amplitude = 0.7f;
+ time = 0.3f;
+ }
+
+ if ( m_object->RetToy() )
+ {
+ sound = SOUND_MOTORd;
+ amplitude = 1.0f;
+ time = 0.1f;
+ }
+
+ freq = 0.75f+(fabs(m_motorSpeed.x)+fabs(m_motorSpeed.z))*0.25f;
+ if ( freq > 1.0f ) freq = 1.0f;
+ if ( m_object->RetToy() ) freq = 1.0f;
+
+ if ( m_soundChannel == -1 )
+ {
+ m_soundChannel = m_sound->Play(sound, m_object->RetPosition(0), 0.0f, 0.5f, true);
+ m_sound->AddEnvelope(m_soundChannel, amplitude, freq, time, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, amplitude, freq, 1.0f, SOPER_LOOP);
+ }
+ else
+ {
+ m_sound->Position(m_soundChannel, m_object->RetPosition(0));
+
+ if ( m_bSoundSlow ) // in slow motion?
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, amplitude, freq, time, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, amplitude, freq, 1.0f, SOPER_LOOP);
+ m_bSoundSlow = false;
+ }
+ }
+
+ freq *= 1.0f + m_linMotion.terrainSpeed.x/100.0f;
+ freq *= 1.0f + fabs(m_cirMotion.realSpeed.y/20.0f);
+ m_sound->Frequency(m_soundChannel, freq);
+
+ m_soundTimePshhh -= rTime*2.0f;
+}
+
+// Sounds the engine idling.
+
+void CPhysics::SoundMotorSlow(float rTime, ObjectType type)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ Sound sound;
+ float amplitude;
+ int i, max;
+
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEis )
+ {
+ if ( m_soundChannel != -1 ) // engine is running?
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.3f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+ return;
+ }
+
+ if ( type == OBJECT_MOBILEsa )
+ {
+ sound = SOUND_MOTORs;
+ amplitude = 0.4f;
+ }
+ else if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ sound = SOUND_MOTORr;
+ amplitude = 0.9f;
+ }
+ else if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts )
+ {
+ sound = SOUND_MOTORt;
+ amplitude = 0.7f;
+ }
+ else if ( type == OBJECT_APOLLO2 )
+ {
+ if ( m_soundChannel != -1 ) // engine is running?
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.3f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+ return;
+ }
+ else
+ {
+ sound = SOUND_MOTORw;
+ amplitude = 0.3f;
+ }
+
+ if ( m_object->RetToy() )
+ {
+ sound = SOUND_MOTORd;
+ amplitude = 0.0f;
+ }
+
+ if ( m_soundChannel == -1 )
+ {
+ m_soundChannel = m_sound->Play(sound, m_object->RetPosition(0), 0.0f, 0.25f, true);
+ m_sound->AddEnvelope(m_soundChannel, amplitude, 0.5f, 0.2f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, amplitude, 0.5f, 1.0f, SOPER_LOOP);
+ }
+ else
+ {
+ m_sound->Position(m_soundChannel, m_object->RetPosition(0));
+
+ if ( !m_bSoundSlow ) // full power?
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, amplitude, 0.5f, 0.3f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, amplitude, 0.5f, 1.0f, SOPER_LOOP);
+ m_bSoundSlow = true;
+ }
+ }
+
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ m_soundTimePshhh -= rTime;
+
+ if ( m_soundTimePshhh <= 0.0f )
+ {
+ amplitude = 0.5f-m_soundTimePshhh*0.08f;
+ if ( amplitude > 1.0f ) amplitude = 1.0f;
+//? m_sound->Play(SOUND_PSHHH, m_object->RetPosition(0), amplitude);
+ m_sound->Play(SOUND_PSHHH, m_object->RetPosition(0), 1.0f);
+
+ m_soundTimePshhh = 4.0f+4.0f*Math::Rand();
+
+ max = (int)(10.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<max ; i++ )
+ {
+ pos = Math::Vector(-5.0f, 2.0f, 0.0f);
+ pos.x += Math::Rand()*4.0f;
+ pos.z += (Math::Rand()-0.5f)*2.0f;
+
+ speed = pos;
+ speed.x -= Math::Rand()*4.0f;
+ speed.y -= Math::Rand()*3.0f;
+ speed.z += (Math::Rand()-0.5f)*6.0f;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+ speed = Transform(*mat, speed)-pos;
+
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTIMOTOR, 2.0f);
+ }
+ }
+ }
+}
+
+// Sounds the engine not running.
+
+void CPhysics::SoundMotorStop(float rTime, ObjectType type)
+{
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEis )
+ {
+ if ( m_soundChannel != -1 ) // engine is running?
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 0.3f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+ return;
+ }
+
+ if ( m_soundChannel != -1 ) // engine is running?
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 0.5f, 0.3f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ m_soundTimePshhh -= rTime*2.0f;
+}
+
+// Sounds the reactor at full power.
+
+void CPhysics::SoundReactorFull(float rTime, ObjectType type)
+{
+ Sound sound;
+ Math::Matrix* mat;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float freq;
+ int i;
+
+ if ( m_soundChannelSlide != -1 ) // slides?
+ {
+ m_sound->FlushEnvelope(m_soundChannelSlide);
+ m_sound->AddEnvelope(m_soundChannelSlide, 0.0f, 1.0f, 0.3f, SOPER_STOP);
+ m_soundChannelSlide = -1;
+ }
+
+ if ( m_reactorRange > 0.0f )
+ {
+ if ( m_soundChannel == -1 )
+ {
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH )
+ {
+ sound = SOUND_FLYh;
+ }
+ else
+ {
+ sound = SOUND_FLY;
+ }
+
+ m_soundChannel = m_sound->Play(sound, m_object->RetPosition(0), 0.0f, 1.0f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 0.6f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 1.0f, SOPER_LOOP);
+ }
+ else
+ {
+ m_sound->Position(m_soundChannel, m_object->RetPosition(0));
+ }
+
+ freq = 1.0f + m_linMotion.realSpeed.y/100.0f;
+ freq *= 1.0f + fabs(m_cirMotion.realSpeed.y/5.0f);
+ m_sound->Frequency(m_soundChannel, freq);
+ }
+ else
+ {
+ if ( m_soundChannel != -1 ) // engine is running?
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ if ( m_timeReactorFail <= m_time )
+ {
+ freq = 1.0f+Math::Rand()*0.5f;
+ m_sound->Play(SOUND_FLYf, m_object->RetPosition(0), 1.0f, freq);
+ m_camera->StartEffect(CE_PET, m_object->RetPosition(0), 1.0f);
+
+ for ( i=0 ; i<5 ; i++ )
+ {
+ if ( m_object->RetType() == OBJECT_HUMAN ||
+ m_object->RetType() == OBJECT_TECH )
+ {
+ pos = Math::Vector(-1.6f, -0.5f, 0.0f);
+ }
+ else
+ {
+ pos = Math::Vector(0.0f, -1.0f, 0.0f);
+ }
+ pos.x += (Math::Rand()-0.5f)*2.0f;
+ pos.z += (Math::Rand()-0.5f)*2.0f;
+ mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+ speed.x = (Math::Rand()-0.5f)*5.0f;
+ speed.z = (Math::Rand()-0.5f)*5.0f;
+ speed.y = -(4.0f+Math::Rand()*4.0f);
+ dim.x = (2.0f+Math::Rand()*1.0f);
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 2.0f, 0.0f, 0.1f);
+ }
+
+ m_timeReactorFail = m_time+0.10f+Math::Rand()*0.30f;
+ }
+ else
+ {
+ if ( m_object->RetType() == OBJECT_HUMAN ||
+ m_object->RetType() == OBJECT_TECH )
+ {
+ pos = Math::Vector(-1.6f, -0.5f, 0.0f);
+ }
+ else
+ {
+ pos = Math::Vector(0.0f, -1.0f, 0.0f);
+ }
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = -(4.0f+Math::Rand()*4.0f);
+ dim.x = (0.7f+Math::Rand()*0.4f);
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 2.0f, 0.0f, 0.1f);
+ }
+ }
+
+}
+
+// Sounds the reactor stopped.
+
+void CPhysics::SoundReactorStop(float rTime, ObjectType type)
+{
+ CObject* power;
+ float energy;
+
+ energy = 0.0f;
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ }
+
+ if ( m_soundChannel != -1 ) // engine is running?
+ {
+ m_sound->FlushEnvelope(m_soundChannel);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP);
+ m_soundChannel = -1;
+ }
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH )
+ {
+ if ( m_soundChannelSlide != -1 ) // slides?
+ {
+ m_sound->FlushEnvelope(m_soundChannelSlide);
+ m_sound->AddEnvelope(m_soundChannelSlide, 0.0f, 1.0f, 0.3f, SOPER_STOP);
+ m_soundChannelSlide = -1;
+ }
+ }
+ else
+ {
+ if ( energy != 0.0f &&
+ (m_motorSpeed.x != 0.0f || // slides with small reactors in skates?
+ m_cirMotion.realSpeed.y != 0.0f) )
+ {
+ if ( m_soundChannelSlide == -1 )
+ {
+ m_soundChannelSlide = m_sound->Play(SOUND_SLIDE, m_object->RetPosition(0), 0.0f, 1.0f, true);
+ m_sound->AddEnvelope(m_soundChannelSlide, 0.5f, 1.0f, 0.3f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannelSlide, 0.5f, 1.0f, 1.0f, SOPER_LOOP);
+ }
+ m_sound->Position(m_soundChannelSlide, m_object->RetPosition(0));
+ }
+ else
+ {
+ if ( m_soundChannelSlide != -1 ) // slides?
+ {
+ m_sound->FlushEnvelope(m_soundChannelSlide);
+ m_sound->AddEnvelope(m_soundChannelSlide, 0.0f, 1.0f, 0.3f, SOPER_STOP);
+ m_soundChannelSlide = -1;
+ }
+ }
+ }
+}
+
+
+// Adapts the physics of the object based on the ground.
+
+void CPhysics::FloorAdapt(float aTime, float rTime,
+ Math::Vector &pos, Math::Vector &angle)
+{
+ Character* character;
+ ObjectType type;
+ Math::Vector norm;
+ Math::Matrix matRotate;
+ float level, h, f, a1, volume, freq, force;
+ bool bOldSwim, bSlopingTerrain;
+
+ type = m_object->RetType();
+ character = m_object->RetCharacter();
+
+ level = m_water->RetLevel(m_object);
+ bOldSwim = m_bSwim;
+ SetSwim( pos.y < level );
+
+ m_floorLevel = m_terrain->RetFloorLevel(pos); // height above the ground
+ h = pos.y-m_floorLevel;
+ h -= character->height;
+ m_floorHeight = h;
+
+ WaterParticule(aTime, pos, type, m_floorLevel,
+ fabs(m_linMotion.realSpeed.x),
+ fabs(m_cirMotion.realSpeed.y*15.0f));
+
+ if ( m_type == TYPE_ROLLING )
+ {
+ pos.y -= h; // plate to the ground immediately
+ pos.y += character->height;
+ m_floorHeight = 0.0f;
+ }
+
+ if ( m_type == TYPE_FLYING )
+ {
+ bSlopingTerrain = false; // ground as possible to land
+
+ if ( !m_bLand ) // in flight?
+ {
+ m_terrain->GetNormal(norm, pos);
+ a1 = fabs(Math::RotateAngle(Math::Point(norm.x, norm.z).Length(), norm.y));
+ if ( a1 < (90.0f-55.0f)*Math::PI/180.0f ) // slope exceeds 55 degrees?
+ {
+ bSlopingTerrain = true; // very sloped ground
+
+ if ( h < 4.0f ) // collision with the ground?
+ {
+ force = 5.0f+fabs(m_linMotion.realSpeed.x*0.3f)+
+ fabs(m_linMotion.realSpeed.y*0.3f);
+ m_linMotion.currentSpeed = norm*force;
+ Math::LoadRotationXZYMatrix(matRotate, -angle);
+ m_linMotion.currentSpeed = Transform(matRotate, m_linMotion.currentSpeed);
+
+ if ( aTime-m_soundTimeBoum > 0.5f )
+ {
+ volume = fabs(m_linMotion.realSpeed.x*0.02f)+
+ fabs(m_linMotion.realSpeed.y*0.02f);
+ freq = 0.5f+m_terrain->RetHardness(pos)*2.5f;
+ m_sound->Play(SOUND_BOUM, pos, volume, freq);
+
+ m_soundTimeBoum = aTime;
+ }
+
+//? pos = m_object->RetPosition(0); // gives position before collision
+ }
+ }
+ }
+
+ if ( (h <= 0.0f || m_bLand) && !bSlopingTerrain ) // on the ground?
+ {
+ if ( !m_bLand ) // in flight?
+ {
+ volume = fabs(m_linMotion.realSpeed.y*0.02f);
+ freq = 0.5f+m_terrain->RetHardness(pos)*2.5f;
+ m_sound->Play(SOUND_BOUM, pos, volume, freq);
+ }
+
+ m_bLand = true; // on the ground?
+ SetMotor(false);
+ pos.y -= h; // plate to the ground immediately
+ m_floorHeight = 0.0f;
+
+ if ( h < 0.0f )
+ {
+ f = fabs(m_linMotion.currentSpeed.y/m_linMotion.advanceSpeed.y);
+ CrashParticule(f);
+ }
+ m_linMotion.currentSpeed.y = 0.0f;
+ m_inclinaisonFactor = 1.0f/LANDING_SPEED; // slips a little to the ground
+ m_linVibrationFactor = 0.0f;
+ m_cirVibrationFactor = 0.0f;
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH ) return; // always right
+ }
+
+ if ( h > 4.0f || bSlopingTerrain ) // meters above the ground?
+ {
+ if ( m_bSwim )
+ {
+ m_linVibrationFactor = 1.0f; // vibrates a max
+ m_cirVibrationFactor = 1.0f;
+ }
+ else
+ {
+ m_linVibrationFactor = 2.0f; // vibrates a large max
+ m_cirVibrationFactor = 2.0f;
+ }
+ m_inclinaisonFactor = 1.0f;
+
+ // Gives gently the horizontal.
+ if ( angle.x > 0.0f )
+ {
+ angle.x -= rTime*0.5f;
+ if ( angle.x < 0.0f ) angle.x = 0.0f;
+ }
+ if ( angle.x < 0.0f )
+ {
+ angle.x += rTime*0.5f;
+ if ( angle.x > 0.0f ) angle.x = 0.0f;
+ }
+ if ( angle.z > 0.0f )
+ {
+ angle.z -= rTime*0.5f;
+ if ( angle.z < 0.0f ) angle.z = 0.0f;
+ }
+ if ( angle.z < 0.0f )
+ {
+ angle.z += rTime*0.5f;
+ if ( angle.z > 0.0f ) angle.z = 0.0f;
+ }
+ return;
+ }
+ }
+
+ if ( m_floorHeight == 0.0f ) // ground plate?
+ {
+ if ( m_object->RetTraceDown() )
+ {
+ WheelParticule(m_object->RetTraceColor(), m_object->RetTraceWidth()*g_unit);
+ }
+ else
+ {
+ WheelParticule(-1, 0.0f);
+ }
+ }
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH ||
+ type == OBJECT_WORM ) return; // always right
+
+ FloorAngle(pos, angle); // adjusts the angle at the ground
+
+ if ( m_type == TYPE_FLYING && !m_bLand ) // flying in the air?
+ {
+ f = h/1.0f;
+ if ( f < 0.0f ) f = 0.0f;
+ if ( f > 1.0f ) f = 1.0f;
+ m_linVibrationFactor = f;
+ m_cirVibrationFactor = f;
+ angle.z *= 1.0f-f;
+ angle.x *= 1.0f-f;
+
+ f = h/1.0f;
+ if ( f < 0.0f ) f = 0.0f;
+ if ( f > 1.0f ) f = 1.0f;
+ m_inclinaisonFactor = f;
+ }
+}
+
+// Calculates the angle of an object with the field.
+
+void CPhysics::FloorAngle(const Math::Vector &pos, Math::Vector &angle)
+{
+ Character* character;
+ Math::Vector pw, norm;
+ float a1, a2;
+
+ character = m_object->RetCharacter();
+
+ pw.x = pos.x+character->wheelFront*cosf(angle.y+Math::PI*0.0f);
+ pw.y = pos.y;
+ pw.z = pos.z-character->wheelFront*sinf(angle.y+Math::PI*0.0f);
+ a1 = atanf(m_terrain->RetFloorHeight(pw)/character->wheelFront);
+
+ pw.x = pos.x+character->wheelBack*cosf(angle.y+Math::PI*1.0f);
+ pw.y = pos.y;
+ pw.z = pos.z-character->wheelBack*sinf(angle.y+Math::PI*1.0f);
+ a2 = atanf(m_terrain->RetFloorHeight(pw)/character->wheelBack);
+
+ angle.z = (a2-a1)/2.0f;
+
+ pw.x = pos.x+character->wheelLeft*cosf(angle.y+Math::PI*0.5f)*cosf(angle.z);
+ pw.y = pos.y;
+ pw.z = pos.z-character->wheelLeft*sinf(angle.y+Math::PI*0.5f)*cosf(angle.z);
+ a1 = atanf(m_terrain->RetFloorHeight(pw)/character->wheelLeft);
+
+ pw.x = pos.x+character->wheelRight*cosf(angle.y+Math::PI*1.5f)*cosf(angle.z);
+ pw.y = pos.y;
+ pw.z = pos.z-character->wheelRight*sinf(angle.y+Math::PI*1.5f)*cosf(angle.z);
+ a2 = atanf(m_terrain->RetFloorHeight(pw)/character->wheelRight);
+
+ angle.x = (a2-a1)/2.0f;
+}
+
+
+// Adapts the physics of the object in relation to other objects.
+// Returns 0 -> mobile object
+// Returns 1 -> immobile object (because collision)
+// Returns 2 -> destroyed object
+
+int CPhysics::ObjectAdapt(const Math::Vector &pos, const Math::Vector &angle)
+{
+ CObject* pObj;
+ CPyro* pyro;
+ CPhysics* ph;
+ Math::Matrix matRotate;
+ Math::Vector iPos, oPos, iiPos, oAngle, oSpeed;
+ Sound sound;
+ float iRad, oRad, distance, force, volume;
+ int i, j, colType;
+ ObjectType iType, oType;
+
+ if ( m_object->RetRuin() ) return 0; // is burning or exploding?
+ if ( !m_object->RetClip() ) return 0;
+
+ // iiPos = sphere center is the old position.
+ // iPos = sphere center has the new position.
+ m_object->GetCrashSphere(0, iiPos, iRad);
+ iPos = iiPos + (pos - m_object->RetPosition(0));
+ iType = m_object->RetType();
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_object ) continue; // yourself?
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( !pObj->RetEnable() ) continue; // inactive?
+ if ( pObj->RetRuin() ) continue; // is burning or exploding?
+ if ( pObj->RetDead() ) continue; // dead man?
+
+ oType = pObj->RetType();
+ if ( oType == OBJECT_NULL ) continue;
+ if ( oType == OBJECT_TOTO ) continue;
+//? if ( iType == OBJECT_BEE && oType == OBJECT_BEE ) continue;
+ if ( iType == OBJECT_WORM && oType != OBJECT_WORM ) continue;
+ if ( iType != OBJECT_WORM && oType == OBJECT_WORM ) continue;
+ if ( iType == OBJECT_MOTHER && oType == OBJECT_ANT ) continue;
+ if ( iType == OBJECT_ANT && oType == OBJECT_MOTHER ) continue;
+ if ( iType == OBJECT_MOTHER && oType == OBJECT_SPIDER ) continue;
+ if ( iType == OBJECT_SPIDER && oType == OBJECT_MOTHER ) continue;
+ if ( iType == OBJECT_MOTHER && oType == OBJECT_EGG ) continue;
+ if ( iType == OBJECT_EGG && oType == OBJECT_MOTHER ) continue;
+
+ pObj->GetJotlerSphere(oPos, oRad);
+ if ( oRad > 0.0f )
+ {
+ JostleObject(pObj, iPos, iRad, oPos, oRad);
+ }
+
+ if ( iType == OBJECT_MOTHER ||
+ iType == OBJECT_ANT ||
+ iType == OBJECT_SPIDER ||
+ iType == OBJECT_WORM ||
+ iType == OBJECT_BEE ) // insect?
+ {
+ if ( oType == OBJECT_STONE ||
+ oType == OBJECT_URANIUM ||
+ oType == OBJECT_METAL ||
+ oType == OBJECT_POWER ||
+ oType == OBJECT_ATOMIC ||
+ oType == OBJECT_BULLET ||
+ oType == OBJECT_BBOX ||
+ oType == OBJECT_KEYa ||
+ oType == OBJECT_KEYb ||
+ oType == OBJECT_KEYc ||
+ oType == OBJECT_KEYd ||
+ oType == OBJECT_TNT ||
+ (oType >= OBJECT_PLANT0 && oType <= OBJECT_PLANT19 ) ||
+ (oType >= OBJECT_MUSHROOM0 && oType <= OBJECT_MUSHROOM9) ) continue;
+ }
+
+#if _TEEN
+ if ( oType == OBJECT_WAYPOINT &&
+ pObj->RetEnable() &&
+ !m_object->RetResetBusy() ) // driving vehicle?
+#else
+ if ( oType == OBJECT_WAYPOINT &&
+ pObj->RetEnable() &&
+ !m_object->RetResetBusy() &&
+ m_object->RetTrainer() ) // driving vehicle?
+#endif
+ {
+ oPos = pObj->RetPosition(0);
+ distance = Math::DistanceProjected(oPos, iPos);
+ if ( distance < 4.0f )
+ {
+ m_sound->Play(SOUND_WAYPOINT, m_object->RetPosition(0));
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_WPCHECK, pObj);
+ }
+ }
+
+ if ( oType == OBJECT_TARGET2 )
+ {
+ oPos = pObj->RetPosition(0);
+ distance = Math::Distance(oPos, iPos);
+ if ( distance < 10.0f*1.5f )
+ {
+ m_sound->Play(SOUND_WAYPOINT, m_object->RetPosition(0));
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_WPCHECK, pObj);
+ }
+ }
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRad) )
+ {
+ if ( iType == OBJECT_MOTHER && oRad <= 1.2f ) continue;
+ if ( iType == OBJECT_ANT && oRad <= 1.2f ) continue;
+ if ( iType == OBJECT_SPIDER && oRad <= 1.2f ) continue;
+ if ( iType == OBJECT_BEE && oRad <= 1.2f ) continue;
+ if ( iType == OBJECT_WORM && oRad <= 1.2f ) continue;
+
+ distance = Math::Distance(oPos, iPos);
+ if ( distance < iRad+oRad ) // collision?
+ {
+ distance = Math::Distance(oPos, iiPos);
+ if ( distance >= iRad+oRad ) // view (*)
+ {
+ m_bCollision = true;
+ m_bObstacle = true;
+
+ sound = pObj->RetCrashSphereSound(j-1);
+ if ( sound != SOUND_CLICK )
+ {
+ force = fabs(m_linMotion.realSpeed.x);
+ force *= pObj->RetCrashSphereHardness(j-1)*2.0f;
+ if ( ExploOther(iType, pObj, oType, force) ) continue;
+ colType = ExploHimself(iType, oType, force);
+ if ( colType == 2 ) return 2; // destroyed?
+ if ( colType == 0 ) continue; // ignores?
+ }
+
+ force = m_linMotion.realSpeed.Length();
+ force *= pObj->RetCrashSphereHardness(j-1);
+ volume = fabs(force*0.05f);
+ if ( volume > 1.0f ) volume = 1.0f;
+ if ( sound != SOUND_CLICK )
+ {
+ m_sound->Play(sound, m_object->RetPosition(0), volume);
+ }
+ if ( iType == OBJECT_HUMAN && volume > 0.5f )
+ {
+ m_sound->Play(SOUND_AIE, m_object->RetPosition(0), volume);
+ }
+
+ if ( m_repeatCollision > 0 )
+ {
+ force *= 0.5f*m_repeatCollision;
+ if ( force > 20.0f ) force = 20.0f;
+ }
+ m_repeatCollision += 2;
+ if ( m_repeatCollision > 10 )
+ {
+ m_repeatCollision = 10;
+ }
+
+ m_linMotion.currentSpeed = Normalize(iPos-oPos)*force;
+ Math::LoadRotationXZYMatrix(matRotate, -angle);
+ m_linMotion.currentSpeed = Transform(matRotate, m_linMotion.currentSpeed);
+ if ( m_type == TYPE_ROLLING )
+ {
+ m_linMotion.currentSpeed.y = 0.0f;
+ }
+
+ ph = pObj->RetPhysics();
+ if ( ph != 0 )
+ {
+ oAngle = pObj->RetAngle(0);
+ oSpeed = Normalize(oPos-iPos)*force;
+ Math::LoadRotationXZYMatrix(matRotate, -oAngle);
+ oSpeed = Transform(matRotate, oSpeed);
+ if ( ph->RetType() == TYPE_ROLLING )
+ {
+ oSpeed.y = 0.0f;
+ }
+ ph->SetLinMotion(MO_CURSPEED, oSpeed);
+ }
+ return 1;
+ }
+ }
+ }
+ }
+
+ if ( m_repeatCollision > 0 )
+ {
+ m_repeatCollision --;
+ }
+ return 0;
+}
+
+// (*) Collision has the initial position (iiPos) and the new position (iPos),
+// the obstacle is not known. We can therefore pass through.
+// This is necessary when barriers found "in" a vehicle, not to block it definitely!
+
+
+// Shakes an object.
+
+bool CPhysics::JostleObject(CObject* pObj, Math::Vector iPos, float iRad,
+ Math::Vector oPos, float oRad)
+{
+ Math::Vector speed;
+ float distance, force, d, f;
+
+ distance = Math::Distance(oPos, iPos);
+ if ( distance >= iRad+oRad ) return false;
+
+ d = (iRad+oRad)/2.0f;
+ f = (distance-d)/d; // 0 = off, 1 = near
+ if ( f < 0.0f ) f = 0.0f;
+ if ( f > 1.0f ) f = 1.0f;
+
+ speed = m_linMotion.realSpeed;
+ speed.y = 0.0f;
+ force = speed.Length()*f*0.05f;
+ if ( force > 1.0f ) force = 1.0f;
+
+ if ( m_soundTimeJostle >= 0.20f )
+ {
+ m_soundTimeJostle = 0.0f;
+ m_sound->Play(SOUND_JOSTLE, iPos, force);
+ }
+
+ return pObj->JostleObject(force);
+}
+
+// Shakes forcing an object.
+
+bool CPhysics::JostleObject(CObject* pObj, float force)
+{
+ Math::Vector oPos;
+ float oRad;
+
+ pObj->GetJotlerSphere(oPos, oRad);
+ if ( oRad <= 0.0f ) return false;
+
+ if ( m_soundTimeJostle >= 0.20f )
+ {
+ m_soundTimeJostle = 0.0f;
+ m_sound->Play(SOUND_JOSTLE, pObj->RetPosition(0), force);
+ }
+
+ return pObj->JostleObject(force);
+}
+
+// Effects of the explosion on the object buffers.
+// Returns true if we ignore this obstacle.
+
+bool CPhysics::ExploOther(ObjectType iType,
+ CObject *pObj, ObjectType oType, float force)
+{
+ CPyro* pyro;
+
+ if ( !pObj->RetEnable() ) return true;
+
+ JostleObject(pObj, 1.0f); // shakes the object
+
+ if ( force > 50.0f &&
+ (oType == OBJECT_FRET ||
+ oType == OBJECT_METAL ) )
+ {
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_EXPLOT, pObj); // total destruction
+ }
+
+ if ( force > 50.0f &&
+ (oType == OBJECT_POWER ||
+ oType == OBJECT_ATOMIC ) )
+ {
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FRAGT, pObj); // total destruction
+ }
+
+ if ( force > 25.0f &&
+ (oType == OBJECT_STONE ||
+ oType == OBJECT_URANIUM ) )
+ {
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FRAGT, pObj); // total destruction
+ }
+
+ if ( force > 25.0f &&
+ (oType == OBJECT_DERRICK ||
+ oType == OBJECT_FACTORY ||
+ oType == OBJECT_STATION ||
+ oType == OBJECT_CONVERT ||
+ oType == OBJECT_REPAIR ||
+ oType == OBJECT_DESTROYER||
+ oType == OBJECT_TOWER ||
+ oType == OBJECT_RESEARCH ||
+ oType == OBJECT_RADAR ||
+ oType == OBJECT_INFO ||
+ oType == OBJECT_ENERGY ||
+ oType == OBJECT_LABO ||
+ oType == OBJECT_NUCLEAR ||
+ oType == OBJECT_PARA ||
+ oType == OBJECT_SAFE ||
+ oType == OBJECT_HUSTON ) ) // building?
+ {
+ pObj->ExploObject(EXPLO_BOUM, force/400.0f);
+ }
+
+ if ( force > 25.0f &&
+ (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 ||
+ oType == OBJECT_APOLLO2 ) ) // vehicle?
+ {
+ pObj->ExploObject(EXPLO_BOUM, force/200.0f);
+ }
+
+ if ( force > 10.0f &&
+ (oType == OBJECT_MOBILEtg ||
+ oType == OBJECT_TNT ) )
+ {
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FRAGT, pObj); // total destruction
+ }
+
+ if ( force > 0.0f &&
+ oType == OBJECT_BOMB )
+ {
+ pyro = new CPyro(m_iMan);
+ pyro->Create(PT_FRAGT, pObj); // total destruction
+ }
+
+ return false;
+}
+
+// Effects of the explosion on the object itself.
+// Returns 0 -> mobile object
+// Returns 1 -> immobile object
+// Returns 2 -> object destroyed
+
+int CPhysics::ExploHimself(ObjectType iType, ObjectType oType, float force)
+{
+ PyroType type;
+ CPyro* pyro;
+
+ if ( force > 10.0f &&
+ (oType == OBJECT_TNT ||
+ oType == OBJECT_MOBILEtg ) )
+ {
+ if ( iType == OBJECT_HUMAN ) type = PT_DEADG;
+ else type = PT_EXPLOT;
+ pyro = new CPyro(m_iMan);
+ pyro->Create(type, m_object); // total destruction
+ return 2;
+ }
+
+ if ( force > 0.0f &&
+ oType == OBJECT_BOMB )
+ {
+ if ( iType == OBJECT_HUMAN )
+ {
+ type = PT_DEADG;
+ }
+ else if ( iType == OBJECT_ANT ||
+ iType == OBJECT_SPIDER ||
+ iType == OBJECT_BEE )
+ {
+ type = PT_EXPLOO;
+ }
+ else
+ {
+ type = PT_EXPLOT;
+ }
+ pyro = new CPyro(m_iMan);
+ pyro->Create(type, m_object); // total destruction
+ return 2;
+ }
+
+ if ( force > 25.0f &&
+ (iType == OBJECT_HUMAN ||
+ iType == OBJECT_MOBILEwa ||
+ iType == OBJECT_MOBILEta ||
+ iType == OBJECT_MOBILEfa ||
+ iType == OBJECT_MOBILEia ||
+ iType == OBJECT_MOBILEwc ||
+ iType == OBJECT_MOBILEtc ||
+ iType == OBJECT_MOBILEfc ||
+ iType == OBJECT_MOBILEic ||
+ iType == OBJECT_MOBILEwi ||
+ iType == OBJECT_MOBILEti ||
+ iType == OBJECT_MOBILEfi ||
+ iType == OBJECT_MOBILEii ||
+ iType == OBJECT_MOBILEws ||
+ iType == OBJECT_MOBILEts ||
+ iType == OBJECT_MOBILEfs ||
+ iType == OBJECT_MOBILEis ||
+ iType == OBJECT_MOBILErt ||
+ iType == OBJECT_MOBILErc ||
+ iType == OBJECT_MOBILErr ||
+ iType == OBJECT_MOBILErs ||
+ iType == OBJECT_MOBILEsa ||
+ iType == OBJECT_MOBILEwt ||
+ iType == OBJECT_MOBILEtt ||
+ iType == OBJECT_MOBILEft ||
+ iType == OBJECT_MOBILEit ||
+ iType == OBJECT_MOBILEdr ||
+ iType == OBJECT_APOLLO2 ) ) // vehicle?
+ {
+ if ( oType == OBJECT_DERRICK ||
+ oType == OBJECT_FACTORY ||
+ oType == OBJECT_STATION ||
+ oType == OBJECT_CONVERT ||
+ oType == OBJECT_REPAIR ||
+ oType == OBJECT_DESTROYER||
+ oType == OBJECT_TOWER ||
+ oType == OBJECT_RESEARCH ||
+ oType == OBJECT_RADAR ||
+ oType == OBJECT_INFO ||
+ oType == OBJECT_ENERGY ||
+ oType == OBJECT_LABO ||
+ oType == OBJECT_NUCLEAR ||
+ oType == OBJECT_PARA ||
+ oType == OBJECT_SAFE ||
+ oType == OBJECT_HUSTON ) // building?
+ {
+ force /= 200.0f;
+ }
+ else
+ if ( oType == OBJECT_MOTHER ||
+ oType == OBJECT_ANT ||
+ oType == OBJECT_SPIDER ||
+ oType == OBJECT_BEE ||
+ oType == OBJECT_WORM ) // insect?
+ {
+ force /= 400.0f;
+ }
+ else
+ if ( oType == OBJECT_FRET ||
+ oType == OBJECT_STONE ||
+ oType == OBJECT_METAL )
+ {
+ force /= 500.0f;
+ }
+ else
+ if ( oType == OBJECT_URANIUM ||
+ oType == OBJECT_POWER ||
+ oType == OBJECT_ATOMIC )
+ {
+ force /= 100.0f;
+ }
+ else
+ {
+ force /= 200.0f;
+ }
+
+ if ( m_object->ExploObject(EXPLO_BOUM, force) ) return 2;
+ }
+
+ return 1;
+}
+
+
+
+// Makes the particles evolve.
+
+void CPhysics::FrameParticule(float aTime, float rTime)
+{
+ Math::Vector pos;
+ CObject* power;
+ float energy, intensity;
+ int effectLight;
+ bool bFlash;
+
+ m_restBreakParticule -= rTime;
+ if ( aTime-m_lastPowerParticule < m_engine->ParticuleAdapt(0.05f) ) return;
+ m_lastPowerParticule = aTime;
+
+ bFlash = false;
+
+ energy = 0.0f;
+ power = m_object->RetPower();
+ if ( power != 0 )
+ {
+ energy = power->RetEnergy();
+ }
+
+ if ( energy != m_lastEnergy ) // change the energy level?
+ {
+ if ( energy > m_lastEnergy ) // recharge?
+ {
+ PowerParticule(1.0f, false);
+ bFlash = true;
+ }
+
+ if ( energy == 0.0f || m_lastEnergy == 0.0f )
+ {
+ m_restBreakParticule = 2.5f; // particles for 2.5s
+ }
+
+ m_lastEnergy = energy;
+ }
+
+ if ( m_restBreakParticule > 0.0f )
+ {
+ PowerParticule(m_restBreakParticule/2.5f, (energy == 0));
+ bFlash = true;
+ }
+
+ effectLight = m_object->RetEffectLight();
+ if ( effectLight != -1 )
+ {
+ if ( bFlash )
+ {
+ intensity = 0.0f;
+ if ( Math::Rand() < 0.5f ) intensity = 1.0f;
+ m_light->SetLightIntensity(effectLight, intensity);
+ m_light->SetLightIntensitySpeed(effectLight, 10000.0f);
+ }
+ else
+ {
+ m_light->SetLightIntensity(effectLight, 0.0f);
+ }
+ }
+}
+
+// Generates some particles after a recharge.
+
+void CPhysics::PowerParticule(float factor, bool bBreak)
+{
+ Character* character;
+ CObject* fret;
+ Math::Matrix* mat;
+ Math::Vector pos, ppos, eye, speed;
+ Math::Point dim;
+ bool bCarryPower;
+
+ bCarryPower = false;
+ fret = m_object->RetFret();
+ if ( fret != 0 && fret->RetType() == OBJECT_POWER &&
+ m_object->RetAngleZ(1) == ARM_STOCK_ANGLE1 )
+ {
+ bCarryPower = true; // carries a battery
+ }
+
+ mat = m_object->RetWorldMatrix(0);
+ character = m_object->RetCharacter();
+
+ pos = character->posPower;
+ pos.x -= 0.3f;
+ pos.y += 1.0f; // battery center position
+ pos = Transform(*mat, pos);
+
+ speed.x = (Math::Rand()-0.5f)*12.0f;
+ speed.y = (Math::Rand()-0.5f)*12.0f;
+ speed.z = (Math::Rand()-0.5f)*12.0f;
+
+ ppos.x = pos.x;
+ ppos.y = pos.y+(Math::Rand()-0.5f)*2.0f;
+ ppos.z = pos.z;
+
+ dim.x = 1.0f*factor;
+ dim.y = 1.0f*factor;
+
+ m_particule->CreateParticule(ppos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
+
+ if ( bCarryPower ) // carry a battery?
+ {
+ pos = Math::Vector(3.0f, 5.6f, 0.0f); // position of battery holder
+ pos = Transform(*mat, pos);
+
+ speed.x = (Math::Rand()-0.5f)*12.0f;
+ speed.y = (Math::Rand()-0.5f)*12.0f;
+ speed.z = (Math::Rand()-0.5f)*12.0f;
+
+ ppos.x = pos.x;
+ ppos.y = pos.y;
+ ppos.z = pos.z+(Math::Rand()-0.5f)*2.0f;
+
+ dim.x = 1.0f*factor;
+ dim.y = 1.0f*factor;
+
+ m_particule->CreateParticule(ppos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
+ }
+}
+
+// Generates some particles after a fall.
+// crash: 0=super soft, 1=big crash
+
+void CPhysics::CrashParticule(float crash)
+{
+ Math::Vector pos, ppos, speed;
+ Math::Point dim;
+ float len;
+ int i, max;
+
+ if ( crash < 0.2f ) return;
+
+ pos = m_object->RetPosition(0);
+ m_camera->StartEffect(CE_CRASH, pos, crash);
+
+//? max = (int)(crash*50.0f);
+ max = (int)(crash*10.0f*m_engine->RetParticuleDensity());
+
+ for ( i=0 ; i<max ; i++ )
+ {
+ ppos.x = pos.x + (Math::Rand()-0.5f)*15.0f*crash;
+ ppos.z = pos.z + (Math::Rand()-0.5f)*15.0f*crash;
+ ppos.y = pos.y + Math::Rand()*4.0f;
+ len = 1.0f-(Math::Distance(ppos, pos)/(15.0f+5.0f));
+ if ( len <= 0.0f ) continue;
+ speed.x = (ppos.x-pos.x)*0.1f;
+ speed.z = (ppos.z-pos.z)*0.1f;
+ speed.y = -2.0f;
+ dim.x = 2.0f+crash*5.0f*len;
+ dim.y = dim.x;
+ m_particule->CreateParticule(ppos, speed, dim, PARTICRASH, 2.0f);
+ }
+}
+
+// Generates some exhaust gas particle.
+
+void CPhysics::MotorParticule(float aTime, float rTime)
+{
+ Math::Matrix* mat;
+ Math::Vector pos, speed;
+ Math::Point dim;
+ ObjectType type;
+ Math::Point c, p;
+ float h, a, delay, level;
+ int r, i, nb;
+
+ if ( m_object->RetToy() ) return;
+
+ type = m_object->RetType();
+
+ if ( type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEis || // legs?
+ type == OBJECT_MOBILEdr ||
+ type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ||
+ type == OBJECT_APOLLO2 ) return;
+
+ if ( type == OBJECT_HUMAN ) delay = 3.0f;
+ else delay = 8.0f;
+ if ( m_bSwim && m_timeUnderWater < delay ) // bubbles when entering water?
+ {
+ if ( aTime-m_lastUnderParticule >= m_engine->ParticuleAdapt(0.05f) )
+ {
+ m_lastUnderParticule = aTime;
+
+ nb = (int)(20.0f-(20.0f/delay)*m_timeUnderWater);
+ for ( i=0 ; i<nb ; i++ )
+ {
+ pos = m_object->RetPosition(0);
+ pos.x += (Math::Rand()-0.5f)*4.0f;
+ pos.y += (Math::Rand()-0.5f)*4.0f;
+ pos.z += (Math::Rand()-0.5f)*4.0f;
+ speed.y = (Math::Rand()-0.5f)*8.0f+8.0f;
+ speed.x = (Math::Rand()-0.5f)*0.2f;
+ speed.z = (Math::Rand()-0.5f)*0.2f;
+ dim.x = 0.06f+Math::Rand()*0.10f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBUBBLE, 3.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+
+ level = m_water->RetLevel();
+ pos = m_object->RetPosition(0);
+ if ( type == OBJECT_HUMAN ) pos.y -= 2.0f;
+ if ( pos.y < level ) // underwater?
+ {
+ m_absorbWater += rTime*(1.0f/2.0f); // gets wet
+ if ( m_absorbWater > 1.0f ) m_absorbWater = 1.0f;
+ }
+ else // out of water?
+ {
+ m_absorbWater -= rTime*(1.0f/3.0f); // to dry
+ if ( m_absorbWater < 0.0f ) m_absorbWater = 0.0f;
+ }
+
+ if ( pos.y >= level &&
+ m_absorbWater > 0.0f &&
+ !m_water->RetLava() ) // drops on leaving the water?
+ {
+ if ( aTime-m_lastUnderParticule >= m_engine->ParticuleAdapt(0.05f) )
+ {
+ m_lastUnderParticule = aTime;
+
+ nb = (int)(8.0f*m_absorbWater);
+ for ( i=0 ; i<nb ; i++ )
+ {
+ pos = m_object->RetPosition(0);
+ if ( type == OBJECT_HUMAN ) pos.y -= Math::Rand()*2.0f;
+ else pos.y += Math::Rand()*2.0f;
+ pos.x += (Math::Rand()-0.5f)*2.0f;
+ pos.z += (Math::Rand()-0.5f)*2.0f;
+ speed.y = -((Math::Rand()-0.5f)*8.0f+8.0f);
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ dim.x = 0.2f;
+ dim.y = 0.2f;
+ m_particule->CreateParticule(pos, speed, dim, PARTIWATER, 2.0f, 0.0f, 1.0f);
+ }
+ }
+ }
+
+ if ( type == OBJECT_HUMAN || // human?
+ type == OBJECT_TECH )
+ {
+ if ( m_bLand &&
+ aTime-m_lastSlideParticule >= m_engine->ParticuleAdapt(0.05f) )
+ {
+ h = Math::Max(fabs(m_linMotion.terrainSpeed.x),
+ fabs(m_linMotion.terrainSpeed.z));
+ if ( h > m_linMotion.terrainSlide.x+0.5f &&
+ m_linMotion.motorSpeed.x == 0.0f ) // slides a stop?
+ {
+ m_lastSlideParticule = aTime;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos.x = (Math::Rand()-0.5f)*1.0f;
+ pos.y = -m_object->RetCharacter()->height;
+ pos.z = Math::Rand()*0.4f+1.0f;
+ if ( rand()%2 == 0 ) pos.z = -pos.z;
+ pos = Transform(*mat, pos);
+ speed = Math::Vector(0.0f, 1.0f, 0.0f);
+ dim.x = Math::Rand()*(h-5.0f)/2.0f+1.0f;
+ if ( dim.x > 2.5f ) dim.x = 2.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.2f);
+ }
+ }
+ }
+
+ if ( type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEts ) // caterpillars?
+ {
+ if ( aTime-m_lastSlideParticule >= m_engine->ParticuleAdapt(0.05f) )
+ {
+ h = fabs(m_linMotion.motorSpeed.x-m_linMotion.realSpeed.x);
+ if ( h > 5.0f )
+ {
+ m_lastSlideParticule = aTime;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos.x = (Math::Rand()-0.5f)*8.0f;
+ pos.y = 0.0f;
+ pos.z = Math::Rand()*2.0f+3.0f;
+ if ( rand()%2 == 0 ) pos.z = -pos.z;
+ pos = Transform(*mat, pos);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*(h-5.0f)/2.0f+1.0f;
+ if ( dim.x > 3.0f ) dim.x = 3.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.2f);
+ }
+ }
+ }
+
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ) // large caterpillars?
+ {
+ if ( aTime-m_lastSlideParticule >= m_engine->ParticuleAdapt(0.05f) )
+ {
+ h = fabs(m_linMotion.motorSpeed.x-m_linMotion.realSpeed.x);
+ if ( h > 5.0f )
+ {
+ m_lastSlideParticule = aTime;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos.x = (Math::Rand()-0.5f)*9.0f;
+ pos.y = 0.0f;
+ pos.z = Math::Rand()*3.0f+3.0f;
+ if ( rand()%2 == 0 ) pos.z = -pos.z;
+ pos = Transform(*mat, pos);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*(h-5.0f)/2.0f+1.0f;
+ if ( dim.x > 3.0f ) dim.x = 3.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f, 0.0f, 0.2f);
+ }
+ }
+ }
+
+ if ( (type == OBJECT_HUMAN || type == OBJECT_TECH) && !m_bSwim )
+ {
+ if ( m_bLand ) // on the ground?
+ {
+ if ( m_reactorTemperature > 0.0f )
+ {
+ m_reactorTemperature -= rTime*(1.0f/10.0f); // cooling
+ if ( m_reactorTemperature < 0.0f )
+ {
+ m_reactorTemperature = 0.0f;
+ }
+ }
+
+ if ( m_reactorTemperature == 0.0f ||
+ aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.05f) ) return;
+ m_lastMotorParticule = aTime;
+
+ pos = Math::Vector(-1.6f, -0.5f, 0.0f);
+ mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+
+ speed.x = (Math::Rand()-0.5f)*0.6f;
+ speed.z = (Math::Rand()-0.5f)*0.6f;
+ speed.y = -(0.5f+Math::Rand()*0.3f)*(1.0f-m_reactorTemperature);
+
+ dim.x = (1.0f+Math::Rand()*0.5f)*(0.2f+m_reactorTemperature*0.8f);
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE2, 3.0f, 0.0f, 0.1f);
+ }
+ else // in flight?
+ {
+ if ( !m_bMotor || m_reactorRange == 0.0f ) return;
+
+ if ( m_reactorTemperature < 1.0f ) // not too hot?
+ {
+ m_reactorTemperature += rTime*(1.0f/4.0f); // heating
+ if ( m_reactorTemperature > 1.0f )
+ {
+ m_reactorTemperature = 1.0f; // but not too much
+ }
+ }
+
+ if ( aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.02f) ) return;
+ m_lastMotorParticule = aTime;
+
+ pos = Math::Vector(-1.6f, -1.0f, 0.0f);
+ pos.x += (Math::Rand()-0.5f)*3.0f;
+ pos.y += (Math::Rand()-0.5f)*1.5f;
+ pos.z += (Math::Rand()-0.5f)*3.0f;
+ mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+
+ h = m_floorHeight;
+ if ( h > 10.0f ) // high enough?
+ {
+ speed = Math::Vector(0.0f, -10.0f, 0.0f); // against the bottom
+ }
+ else
+ {
+ speed.y = 10.0f-2.0f*h - Math::Rand()*(10.0f-h); //against the top
+ speed.x = (Math::Rand()-0.5f)*(5.0f-h)*1.0f; // horizontal (xz)
+ speed.z = (Math::Rand()-0.5f)*(5.0f-h)*1.0f;
+ }
+
+ dim.x = 0.12f;
+ dim.y = 0.12f;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTISCRAPS, 2.0f, 10.0f);
+
+#if 1
+ pos = Math::Vector(-1.6f, -0.5f, 0.0f);
+ pos = Transform(*mat, pos);
+
+ speed.x = (Math::Rand()-0.5f)*1.0f;
+ speed.z = (Math::Rand()-0.5f)*1.0f;
+ speed.y = -(4.0f+Math::Rand()*3.0f);
+ speed.x += m_linMotion.realSpeed.x*0.8f;
+ speed.z -= m_linMotion.realSpeed.x*m_cirMotion.realSpeed.y*0.05f;
+ if ( m_linMotion.realSpeed.y > 0.0f )
+ {
+ speed.y += m_linMotion.realSpeed.y*0.5f;
+ }
+ else
+ {
+ speed.y += m_linMotion.realSpeed.y*1.2f;
+ }
+ a = m_object->RetAngleY(0);
+ p.x = speed.x;
+ p.y = speed.z;
+ p = Math::RotatePoint(-a, p);
+ speed.x = p.x;
+ speed.z = p.y;
+
+ dim.x = 0.4f+Math::Rand()*0.2f;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTIEJECT, 0.3f, 10.0f);
+#endif
+ }
+ }
+
+ if ( (type == OBJECT_HUMAN || type == OBJECT_TECH) && m_bSwim )
+ {
+ m_reactorTemperature = 0.0f; // reactor cold
+ }
+
+ if ( m_type == TYPE_FLYING &&
+ type != OBJECT_HUMAN &&
+ type != OBJECT_TECH &&
+ !m_bSwim )
+ {
+ if ( m_bLand ) // on the ground?
+ {
+ if ( m_motorSpeed.x == 0.0f && // glide slope due to ground?
+ m_cirMotion.realSpeed.y == 0.0f )
+ {
+ h = Math::Max(fabs(m_linMotion.realSpeed.x),
+ fabs(m_linMotion.realSpeed.z));
+
+ if ( h < 3.0f ) return;
+
+ if ( aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.2f) ) return;
+ m_lastMotorParticule = aTime;
+
+ r = rand()%3;
+ if ( r == 0 ) pos = Math::Vector(-3.0f, 0.0f, -4.0f);
+ if ( r == 1 ) pos = Math::Vector(-3.0f, 0.0f, 4.0f);
+ if ( r == 2 ) pos = Math::Vector( 4.0f, 0.0f, 0.0f);
+
+ pos.x += (Math::Rand()-0.5f)*2.0f;
+ pos.z += (Math::Rand()-0.5f)*2.0f;
+ mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = Math::Rand()*h/5.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 2.0f);
+ }
+ else // glide with small reactors in skates?
+ {
+ if ( m_linMotion.realSpeed.x == 0.0f &&
+ m_cirMotion.realSpeed.y == 0.0f ) return;
+
+ if ( aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.02f) ) return;
+ m_lastMotorParticule = aTime;
+
+ r = rand()%3;
+ if ( r == 0 ) pos = Math::Vector(-3.0f, 0.0f, -4.0f);
+ if ( r == 1 ) pos = Math::Vector(-3.0f, 0.0f, 4.0f);
+ if ( r == 2 ) pos = Math::Vector( 4.0f, 0.0f, 0.0f);
+
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIEJECT);
+ }
+ }
+ else // in flight?
+ {
+ if ( !m_bMotor || m_reactorRange == 0.0f ) return;
+
+ if ( aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.02f) ) return;
+ m_lastMotorParticule = aTime;
+
+ pos = Math::Vector(0.0f, -1.0f, 0.0f);
+ pos.x += (Math::Rand()-0.5f)*6.0f;
+ pos.y += (Math::Rand()-0.5f)*3.0f;
+ pos.z += (Math::Rand()-0.5f)*6.0f;
+ mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+
+ h = m_floorHeight;
+ if ( h > 10.0f ) // high enough?
+ {
+ speed = Math::Vector(0.0f, -10.0f, 0.0f); // against the bottom
+ }
+ else
+ {
+ speed.y = 10.0f-2.0f*h - Math::Rand()*(10.0f-h); // against the top
+ speed.x = (Math::Rand()-0.5f)*(10.0f-h)*2.0f; // horizontal (xz)
+ speed.z = (Math::Rand()-0.5f)*(10.0f-h)*2.0f;
+ }
+
+ dim.x = 0.2f;
+ dim.y = 0.2f;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTISCRAPS, 2.0f, 10.0f);
+
+#if 1
+ pos = Math::Vector(0.0f, 1.0f, 0.0f);
+ pos = Transform(*mat, pos);
+
+ speed.x = (Math::Rand()-0.5f)*1.0f;
+ speed.z = (Math::Rand()-0.5f)*1.0f;
+ speed.y = -(6.0f+Math::Rand()*4.5f);
+ speed.x += m_linMotion.realSpeed.x*0.8f;
+ speed.z -= m_linMotion.realSpeed.x*m_cirMotion.realSpeed.y*0.05f;
+ if ( m_linMotion.realSpeed.y > 0.0f )
+ {
+ speed.y += m_linMotion.realSpeed.y*0.5f;
+ }
+ else
+ {
+ speed.y += m_linMotion.realSpeed.y*1.2f;
+ }
+ a = m_object->RetAngleY(0);
+ p.x = speed.x;
+ p.y = speed.z;
+ p = Math::RotatePoint(-a, p);
+ speed.x = p.x;
+ speed.z = p.y;
+
+ dim.x = 0.7f+Math::Rand()*0.6f;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTIEJECT, 0.5f, 10.0f);
+#endif
+ }
+ }
+
+ if ( (type == OBJECT_HUMAN || type == OBJECT_TECH) && m_bSwim )
+ {
+ if ( !m_object->RetDead() )
+ {
+ h = Math::Mod(aTime, 5.0f);
+ if ( h < 3.5f && ( h < 1.5f || h > 1.6f ) ) return;
+ }
+ if ( aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.06f) ) return;
+ m_lastMotorParticule = aTime;
+
+ pos = Math::Vector(0.0f, 3.0f, 0.0f);
+ mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ speed.y = (Math::Rand()-0.5f)*8.0f+8.0f;
+ speed.x = (Math::Rand()-0.5f)*0.2f;
+ speed.z = (Math::Rand()-0.5f)*0.2f;
+ dim.x = 0.2f;
+ dim.y = 0.2f;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBUBBLE, 3.0f, 0.0f, 0.0f);
+
+ if ( aTime-m_lastSoundWater > 1.5f )
+ {
+ m_lastSoundWater = aTime;
+ m_sound->Play(SOUND_BLUP, m_object->RetPosition(0), 0.5f+Math::Rand()*0.5f);
+ }
+ }
+
+ if ( type == OBJECT_MOBILEsa && m_bSwim )
+ {
+ h = Math::Mod(aTime, 3.0f);
+ if ( h < 1.5f && ( h < 0.5f || h > 0.9f ) ) return;
+ if ( aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.06f) ) return;
+ m_lastMotorParticule = aTime;
+
+ pos = Math::Vector(0.0f, 3.0f, 0.0f);
+ mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ speed.y = (Math::Rand()-0.5f)*8.0f+8.0f;
+ speed.x = (Math::Rand()-0.5f)*0.2f;
+ speed.z = (Math::Rand()-0.5f)*0.2f;
+ dim.x = 0.2f;
+ dim.y = 0.2f;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBUBBLE, 3.0f, 0.0f, 0.0f);
+
+ if ( aTime-m_lastSoundWater > 1.5f )
+ {
+ m_lastSoundWater = aTime;
+ m_sound->Play(SOUND_BLUP, m_object->RetPosition(0), 0.5f+Math::Rand()*0.5f);
+ }
+ }
+
+ if ( m_type == TYPE_ROLLING )
+ {
+ if ( type == OBJECT_APOLLO2 ) return; // electric motors!
+
+ if ( type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs )
+ {
+ if ( !m_bMotor ) return;
+
+ if ( aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.1f) ) return;
+ m_lastMotorParticule = aTime;
+
+ pos = Math::Vector(-2.5f, 10.3f, -1.3f);
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = 1.5f+Math::Rand()*1.0f;
+
+ dim.x = Math::Rand()*0.6f+0.4f;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTIMOTOR, 2.0f);
+ }
+ else
+ {
+ if ( !m_bMotor ) return;
+
+ if ( aTime-m_lastMotorParticule < m_engine->ParticuleAdapt(0.05f) ) return;
+ m_lastMotorParticule = aTime;
+
+ pos = Math::Vector(-3.4f, 1.8f, 0.5f);
+
+ speed = pos;
+ if ( m_linMotion.currentSpeed.x < 0.0f )
+ {
+ speed.x += m_linMotion.currentSpeed.x*1.2f;
+ }
+ else if ( m_linMotion.currentSpeed.x > 0.0f )
+ {
+ speed.x += 0.0f;
+ }
+ else
+ {
+ speed.x -= 3.0f;
+ }
+ speed.y -= 0.5f+Math::Rand()*2.0f;
+ speed.z += (Math::Rand()-0.5f)*3.0f;
+
+ mat = m_object->RetWorldMatrix(0);
+ pos = Transform(*mat, pos);
+ speed = Transform(*mat, speed)-pos;
+
+ dim.x = Math::Rand()*0.4f+0.3f;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTIMOTOR, 2.0f);
+ }
+ }
+}
+
+// Generates some particles after falling into the water.
+
+void CPhysics::WaterParticule(float aTime, Math::Vector pos, ObjectType type,
+ float floor, float advance, float turn)
+{
+ Math::Vector ppos, speed;
+ Math::Point dim;
+ float delay, level, min, max, force, volume, diam;
+ int i, nb;
+
+ level = m_water->RetLevel();
+ if ( floor >= level ) return;
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH )
+ {
+ min = 3.0f;
+ max = 3.0f;
+ }
+ else
+ {
+ min = 0.0f;
+ max = 9.0f;
+ }
+
+ if ( pos.y+max < level || pos.y-min > level ) return;
+
+ // Management of the particle "splash".
+ if ( m_linMotion.realSpeed.y < -10.0f &&
+ aTime-m_lastPloufParticule >= 1.0f )
+ {
+ m_lastPloufParticule = aTime;
+
+ force = -m_linMotion.realSpeed.y/20.0f; // power according to speed drops
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH )
+ {
+ diam = 2.5f;
+ }
+ else
+ {
+ diam = 5.0f;
+ force *= 1.3f; // a robot is heavier
+ }
+
+ pos = m_object->RetPosition(0);
+ pos.y = m_water->RetLevel()-1.0f;
+ dim.x = 2.0f*force; // height
+ dim.y = diam; // diameter
+ m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), dim, PARTIPLOUF0, 1.4f, 0.0f, 0.0f);
+
+ force = (0.5f+force*0.5f);
+ nb = (int)(force*50.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<nb ; i++ )
+ {
+ ppos = pos;
+ ppos.x += (Math::Rand()-0.5f)*4.0f;
+ ppos.z += (Math::Rand()-0.5f)*4.0f;
+ ppos.y += 0.6f;
+ speed.x = (Math::Rand()-0.5f)*12.0f*force;
+ speed.z = (Math::Rand()-0.5f)*12.0f*force;
+ speed.y = 6.0f+Math::Rand()*6.0f*force;
+ dim.x = 0.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(ppos, speed, dim, PARTIDROP, 2.0f, 20.0f, 0.2f);
+ }
+
+ volume = fabs(m_linMotion.realSpeed.y*0.02f);
+ if ( volume > 1.0f ) volume = 1.0f;
+ m_sound->Play(SOUND_PLOUF, pos, volume);
+ }
+
+ // Management particles "cop".
+ if ( m_water->RetLava() ) return;
+
+ if ( advance == 0.0f && turn == 0.0f )
+ {
+ turn = 10.0f;
+ delay = 0.50f;
+ }
+ else if ( advance == 0.0f )
+ {
+ delay = 0.24f;
+ }
+ else
+ {
+ delay = 0.06f;
+ }
+ m_engine->ParticuleAdapt(delay);
+
+ if ( aTime-m_lastWaterParticule < delay ) return;
+ m_lastWaterParticule = aTime;
+
+ force = (advance+turn)*0.16f;
+ if ( force < 0.001f ) return;
+
+ pos = m_object->RetPosition(0);
+ pos.y = level+0.1f;
+ if ( advance == 0 )
+ {
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ }
+ else
+ {
+ pos.x += (Math::Rand()-0.5f)*4.0f;
+ pos.z += (Math::Rand()-0.5f)*4.0f;
+ }
+ speed.y = 0.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ dim.x = Math::Min(Math::Rand()*force+force+1.0f, 10.0f);
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFLIC, 3.0f, 0.0f, 0.0f);
+}
+
+// Creates the trace under the robot.
+
+void CPhysics::WheelParticule(int color, float width)
+{
+ Character* character;
+ Math::Matrix* mat;
+ Math::Vector goal1, goal2, wheel1, wheel2;
+ ParticuleType parti;
+ float dist1, dist2, step;
+
+ character = m_object->RetCharacter();
+ mat = m_object->RetWorldMatrix(0);
+
+ // Draw a trace on the ground.
+ if ( color >= 0 && color <= 17 )
+ {
+ parti = (ParticuleType)(PARTITRACE0+color);
+ step = 2.0f;
+ if ( color >= 16 ) step = 4.0f; // arrow?
+ step /= m_engine->RetTracePrecision();
+
+ goal1.x = step/2.0f;
+ goal1.y = 0.0f;
+ goal1.z = -width/2.0f;
+ goal1 = Transform(*mat, goal1);
+
+ goal2.x = step/2.0f;
+ goal2.y = 0.0f;
+ goal2.z = width/2.0f;
+ goal2 = Transform(*mat, goal2);
+
+ if ( !m_bWheelParticuleBrake )
+ {
+ m_wheelParticulePos[0] = goal1;
+ m_wheelParticulePos[1] = goal2;
+ }
+
+ while ( true )
+ {
+ dist1 = Math::Distance(m_wheelParticulePos[0], goal1);
+ if ( dist1 < step ) break;
+ dist2 = Math::Distance(m_wheelParticulePos[1], goal2);
+ wheel1 = Math::SegmentPoint(m_wheelParticulePos[0], goal1, step);
+ wheel2 = Math::SegmentPoint(m_wheelParticulePos[1], goal2, step*dist2/dist1);
+ if ( m_linMotion.realSpeed.x >= 0.0f )
+ {
+ m_particule->CreateWheelTrace(m_wheelParticulePos[0], m_wheelParticulePos[1], wheel1, wheel2, parti);
+ }
+ else
+ {
+ m_particule->CreateWheelTrace(m_wheelParticulePos[1], m_wheelParticulePos[0], wheel2, wheel1, parti);
+ }
+ m_wheelParticulePos[0] = wheel1;
+ m_wheelParticulePos[1] = wheel2;
+ }
+
+ m_bWheelParticuleBrake = true;
+ }
+ else
+ {
+ m_bWheelParticuleBrake = false;
+ }
+}
+
+
+// Creates the interface.
+
+void CPhysics::CreateInterface(bool bSelect)
+{
+ if ( m_brain != 0 )
+ {
+ m_brain->CreateInterface(bSelect);
+ }
+}
+
+
+// Returns an error related to the general state.
+
+Error CPhysics::RetError()
+{
+ ObjectType type;
+ CObject* power;
+
+ type = m_object->RetType();
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH ||
+ type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ||
+ type == OBJECT_APOLLO2 ||
+ type == OBJECT_MOBILEdr ) return ERR_OK;
+
+ if ( m_brain != 0 && m_brain->RetActiveVirus() )
+ {
+ return ERR_VEH_VIRUS;
+ }
+
+ power = m_object->RetPower(); // searches for the object battery used
+ if ( power == 0 )
+ {
+ return ERR_VEH_POWER;
+ }
+ else
+ {
+ if ( power->RetEnergy() == 0.0f ) return ERR_VEH_ENERGY;
+ }
+
+ return ERR_OK;
+}
+
diff --git a/src/physics/physics.h b/src/physics/physics.h
index 53aff8a..6865b6a 100644
--- a/src/physics/physics.h
+++ b/src/physics/physics.h
@@ -1,246 +1,246 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// physics.h
-
-#pragma once
-
-
-#include "old/d3dengine.h"
-#include "common/misc.h"
-#include "object/object.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CLight;
-class CParticule;
-class CTerrain;
-class CWater;
-class CCamera;
-class CObject;
-class CBrain;
-class CMotion;
-class CSound;
-
-
-enum PhysicsType
-{
- TYPE_ROLLING = 1,
- TYPE_FLYING = 2,
-};
-
-enum PhysicsMode
-{
- MO_ADVACCEL = 0,
- MO_RECACCEL = 1,
- MO_STOACCEL = 2,
- MO_MOTACCEL = 3,
- MO_ADVSPEED = 4,
- MO_RECSPEED = 5,
- MO_MOTSPEED = 6,
- MO_CURSPEED = 7,
- MO_TERFORCE = 8,
- MO_TERSPEED = 9,
- MO_TERSLIDE = 10,
- MO_REASPEED = 11,
-};
-
-
-struct Motion
-{
- Math::Vector advanceAccel; // acceleration starting (+)
- Math::Vector recedeAccel; // acceleration starting (+)
- Math::Vector stopAccel; // acceleration stoping (+)
- Math::Vector motorAccel; // current acceleration (+/-)
-
- Math::Vector advanceSpeed; // forward speed (+)
- Math::Vector recedeSpeed; // reversing speed (+)
- Math::Vector motorSpeed; // desired speed (+/-)
- Math::Vector currentSpeed; // current speed (+/-)
-
- Math::Vector terrainForce; // power of resistance of the ground (+)
- Math::Vector terrainSpeed; // speed of the ground (+/-)
- Math::Vector terrainSlide; // limit sliding speed (+)
-
- Math::Vector realSpeed; // real speed(+/-)
-
- Math::Vector finalInclin; // final inclination
-};
-
-
-
-
-class CPhysics
-{
-public:
- CPhysics(CInstanceManager* iMan, CObject* object);
- ~CPhysics();
-
- void DeleteObject(bool bAll=false);
-
- bool EventProcess(const Event &event);
-
- void SetBrain(CBrain* brain);
- void SetMotion(CMotion* motion);
-
- void SetType(PhysicsType type);
- PhysicsType RetType();
-
- bool Write(char *line);
- bool Read(char *line);
-
- void SetGravity(float value);
- float RetGravity();
-
- float RetFloorHeight();
-
- void SetLinMotion(PhysicsMode mode, Math::Vector value);
- Math::Vector RetLinMotion(PhysicsMode mode);
- void SetLinMotionX(PhysicsMode mode, float value);
- void SetLinMotionY(PhysicsMode mode, float value);
- void SetLinMotionZ(PhysicsMode mode, float value);
- float RetLinMotionX(PhysicsMode mode);
- float RetLinMotionY(PhysicsMode mode);
- float RetLinMotionZ(PhysicsMode mode);
-
- void SetCirMotion(PhysicsMode mode, Math::Vector value);
- Math::Vector RetCirMotion(PhysicsMode mode);
- void SetCirMotionX(PhysicsMode mode, float value);
- void SetCirMotionY(PhysicsMode mode, float value);
- void SetCirMotionZ(PhysicsMode mode, float value);
- float RetCirMotionX(PhysicsMode mode);
- float RetCirMotionY(PhysicsMode mode);
- float RetCirMotionZ(PhysicsMode mode);
-
- float RetLinStopLength(PhysicsMode sMode=MO_ADVSPEED, PhysicsMode aMode=MO_STOACCEL);
- float RetCirStopLength();
- float RetLinMaxLength(float dir);
- float RetLinTimeLength(float dist, float dir=1.0f);
- float RetLinLength(float dist);
-
- void SetMotor(bool bState);
- bool RetMotor();
- void SetLand(bool bState);
- bool RetLand();
- void SetSwim(bool bState);
- bool RetSwim();
- void SetCollision(bool bCollision);
- bool RetCollision();
- void SetFreeze(bool bFreeze);
- bool RetFreeze();
- void SetReactorRange(float range);
- float RetReactorRange();
-
- void SetMotorSpeed(Math::Vector speed);
- void SetMotorSpeedX(float speed);
- void SetMotorSpeedY(float speed);
- void SetMotorSpeedZ(float speed);
- Math::Vector RetMotorSpeed();
- float RetMotorSpeedX();
- float RetMotorSpeedY();
- float RetMotorSpeedZ();
-
- void CreateInterface(bool bSelect);
- Error RetError();
-
-protected:
- bool EventFrame(const Event &event);
- void WaterFrame(float aTime, float rTime);
- void SoundMotor(float rTime);
- void SoundMotorFull(float rTime, ObjectType type);
- void SoundMotorSlow(float rTime, ObjectType type);
- void SoundMotorStop(float rTime, ObjectType type);
- void SoundReactorFull(float rTime, ObjectType type);
- void SoundReactorStop(float rTime, ObjectType type);
- void FrameParticule(float aTime, float rTime);
- void MotorUpdate(float aTime, float rTime);
- void EffectUpdate(float aTime, float rTime);
- void UpdateMotionStruct(float rTime, Motion &motion);
- void FloorAdapt(float aTime, float rTime, Math::Vector &pos, Math::Vector &angle);
- void FloorAngle(const Math::Vector &pos, Math::Vector &angle);
- int ObjectAdapt(const Math::Vector &pos, const Math::Vector &angle);
- bool JostleObject(CObject* pObj, Math::Vector iPos, float iRad, Math::Vector oPos, float oRad);
- bool JostleObject(CObject* pObj, float force);
- bool ExploOther(ObjectType iType, CObject *pObj, ObjectType oType, float force);
- int ExploHimself(ObjectType iType, ObjectType oType, float force);
-
- void PowerParticule(float factor, bool bBreak);
- void CrashParticule(float crash);
- void MotorParticule(float aTime, float rTime);
- void WaterParticule(float aTime, Math::Vector pos, ObjectType type, float floor, float advance, float turn);
- void WheelParticule(int color, float width);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CLight* m_light;
- CParticule* m_particule;
- CTerrain* m_terrain;
- CWater* m_water;
- CCamera* m_camera;
- CObject* m_object;
- CBrain* m_brain;
- CMotion* m_motion;
- CSound* m_sound;
-
- PhysicsType m_type; // TYPE_*
- float m_gravity; // force of gravity
- float m_time; // absolute time
- Math::Vector m_motorSpeed; // motor speed (-1..1)
- Motion m_linMotion; // linear motion
- Motion m_cirMotion; // circular motion
- bool m_bMotor;
- bool m_bLand;
- bool m_bSwim;
- bool m_bCollision;
- bool m_bObstacle;
- bool m_bFreeze;
- int m_repeatCollision;
- float m_linVibrationFactor;
- float m_cirVibrationFactor;
- float m_inclinaisonFactor;
- float m_lastPowerParticule;
- float m_lastSlideParticule;
- float m_lastMotorParticule;
- float m_lastWaterParticule;
- float m_lastUnderParticule;
- float m_lastPloufParticule;
- float m_lastFlameParticule;
- bool m_bWheelParticuleBrake;
- Math::Vector m_wheelParticulePos[2];
- float m_absorbWater;
- float m_reactorTemperature;
- float m_reactorRange;
- float m_timeReactorFail;
- float m_timeUnderWater;
- float m_lastEnergy;
- float m_lastSoundWater;
- float m_lastSoundInsect;
- float m_restBreakParticule;
- float m_floorLevel; // ground level
- float m_floorHeight; // height above the ground
- int m_soundChannel;
- int m_soundChannelSlide;
- float m_soundTimePshhh;
- float m_soundTimeJostle;
- float m_soundTimeBoum;
- bool m_bSoundSlow;
- bool m_bForceUpdate;
- bool m_bLowLevel;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// physics.h
+
+#pragma once
+
+
+#include "old/d3dengine.h"
+#include "common/misc.h"
+#include "object/object.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CLight;
+class CParticule;
+class CTerrain;
+class CWater;
+class CCamera;
+class CObject;
+class CBrain;
+class CMotion;
+class CSound;
+
+
+enum PhysicsType
+{
+ TYPE_ROLLING = 1,
+ TYPE_FLYING = 2,
+};
+
+enum PhysicsMode
+{
+ MO_ADVACCEL = 0,
+ MO_RECACCEL = 1,
+ MO_STOACCEL = 2,
+ MO_MOTACCEL = 3,
+ MO_ADVSPEED = 4,
+ MO_RECSPEED = 5,
+ MO_MOTSPEED = 6,
+ MO_CURSPEED = 7,
+ MO_TERFORCE = 8,
+ MO_TERSPEED = 9,
+ MO_TERSLIDE = 10,
+ MO_REASPEED = 11,
+};
+
+
+struct Motion
+{
+ Math::Vector advanceAccel; // acceleration starting (+)
+ Math::Vector recedeAccel; // acceleration starting (+)
+ Math::Vector stopAccel; // acceleration stoping (+)
+ Math::Vector motorAccel; // current acceleration (+/-)
+
+ Math::Vector advanceSpeed; // forward speed (+)
+ Math::Vector recedeSpeed; // reversing speed (+)
+ Math::Vector motorSpeed; // desired speed (+/-)
+ Math::Vector currentSpeed; // current speed (+/-)
+
+ Math::Vector terrainForce; // power of resistance of the ground (+)
+ Math::Vector terrainSpeed; // speed of the ground (+/-)
+ Math::Vector terrainSlide; // limit sliding speed (+)
+
+ Math::Vector realSpeed; // real speed(+/-)
+
+ Math::Vector finalInclin; // final inclination
+};
+
+
+
+
+class CPhysics
+{
+public:
+ CPhysics(CInstanceManager* iMan, CObject* object);
+ ~CPhysics();
+
+ void DeleteObject(bool bAll=false);
+
+ bool EventProcess(const Event &event);
+
+ void SetBrain(CBrain* brain);
+ void SetMotion(CMotion* motion);
+
+ void SetType(PhysicsType type);
+ PhysicsType RetType();
+
+ bool Write(char *line);
+ bool Read(char *line);
+
+ void SetGravity(float value);
+ float RetGravity();
+
+ float RetFloorHeight();
+
+ void SetLinMotion(PhysicsMode mode, Math::Vector value);
+ Math::Vector RetLinMotion(PhysicsMode mode);
+ void SetLinMotionX(PhysicsMode mode, float value);
+ void SetLinMotionY(PhysicsMode mode, float value);
+ void SetLinMotionZ(PhysicsMode mode, float value);
+ float RetLinMotionX(PhysicsMode mode);
+ float RetLinMotionY(PhysicsMode mode);
+ float RetLinMotionZ(PhysicsMode mode);
+
+ void SetCirMotion(PhysicsMode mode, Math::Vector value);
+ Math::Vector RetCirMotion(PhysicsMode mode);
+ void SetCirMotionX(PhysicsMode mode, float value);
+ void SetCirMotionY(PhysicsMode mode, float value);
+ void SetCirMotionZ(PhysicsMode mode, float value);
+ float RetCirMotionX(PhysicsMode mode);
+ float RetCirMotionY(PhysicsMode mode);
+ float RetCirMotionZ(PhysicsMode mode);
+
+ float RetLinStopLength(PhysicsMode sMode=MO_ADVSPEED, PhysicsMode aMode=MO_STOACCEL);
+ float RetCirStopLength();
+ float RetLinMaxLength(float dir);
+ float RetLinTimeLength(float dist, float dir=1.0f);
+ float RetLinLength(float dist);
+
+ void SetMotor(bool bState);
+ bool RetMotor();
+ void SetLand(bool bState);
+ bool RetLand();
+ void SetSwim(bool bState);
+ bool RetSwim();
+ void SetCollision(bool bCollision);
+ bool RetCollision();
+ void SetFreeze(bool bFreeze);
+ bool RetFreeze();
+ void SetReactorRange(float range);
+ float RetReactorRange();
+
+ void SetMotorSpeed(Math::Vector speed);
+ void SetMotorSpeedX(float speed);
+ void SetMotorSpeedY(float speed);
+ void SetMotorSpeedZ(float speed);
+ Math::Vector RetMotorSpeed();
+ float RetMotorSpeedX();
+ float RetMotorSpeedY();
+ float RetMotorSpeedZ();
+
+ void CreateInterface(bool bSelect);
+ Error RetError();
+
+protected:
+ bool EventFrame(const Event &event);
+ void WaterFrame(float aTime, float rTime);
+ void SoundMotor(float rTime);
+ void SoundMotorFull(float rTime, ObjectType type);
+ void SoundMotorSlow(float rTime, ObjectType type);
+ void SoundMotorStop(float rTime, ObjectType type);
+ void SoundReactorFull(float rTime, ObjectType type);
+ void SoundReactorStop(float rTime, ObjectType type);
+ void FrameParticule(float aTime, float rTime);
+ void MotorUpdate(float aTime, float rTime);
+ void EffectUpdate(float aTime, float rTime);
+ void UpdateMotionStruct(float rTime, Motion &motion);
+ void FloorAdapt(float aTime, float rTime, Math::Vector &pos, Math::Vector &angle);
+ void FloorAngle(const Math::Vector &pos, Math::Vector &angle);
+ int ObjectAdapt(const Math::Vector &pos, const Math::Vector &angle);
+ bool JostleObject(CObject* pObj, Math::Vector iPos, float iRad, Math::Vector oPos, float oRad);
+ bool JostleObject(CObject* pObj, float force);
+ bool ExploOther(ObjectType iType, CObject *pObj, ObjectType oType, float force);
+ int ExploHimself(ObjectType iType, ObjectType oType, float force);
+
+ void PowerParticule(float factor, bool bBreak);
+ void CrashParticule(float crash);
+ void MotorParticule(float aTime, float rTime);
+ void WaterParticule(float aTime, Math::Vector pos, ObjectType type, float floor, float advance, float turn);
+ void WheelParticule(int color, float width);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CLight* m_light;
+ CParticule* m_particule;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CCamera* m_camera;
+ CObject* m_object;
+ CBrain* m_brain;
+ CMotion* m_motion;
+ CSound* m_sound;
+
+ PhysicsType m_type; // TYPE_*
+ float m_gravity; // force of gravity
+ float m_time; // absolute time
+ Math::Vector m_motorSpeed; // motor speed (-1..1)
+ Motion m_linMotion; // linear motion
+ Motion m_cirMotion; // circular motion
+ bool m_bMotor;
+ bool m_bLand;
+ bool m_bSwim;
+ bool m_bCollision;
+ bool m_bObstacle;
+ bool m_bFreeze;
+ int m_repeatCollision;
+ float m_linVibrationFactor;
+ float m_cirVibrationFactor;
+ float m_inclinaisonFactor;
+ float m_lastPowerParticule;
+ float m_lastSlideParticule;
+ float m_lastMotorParticule;
+ float m_lastWaterParticule;
+ float m_lastUnderParticule;
+ float m_lastPloufParticule;
+ float m_lastFlameParticule;
+ bool m_bWheelParticuleBrake;
+ Math::Vector m_wheelParticulePos[2];
+ float m_absorbWater;
+ float m_reactorTemperature;
+ float m_reactorRange;
+ float m_timeReactorFail;
+ float m_timeUnderWater;
+ float m_lastEnergy;
+ float m_lastSoundWater;
+ float m_lastSoundInsect;
+ float m_restBreakParticule;
+ float m_floorLevel; // ground level
+ float m_floorHeight; // height above the ground
+ int m_soundChannel;
+ int m_soundChannelSlide;
+ float m_soundTimePshhh;
+ float m_soundTimeJostle;
+ float m_soundTimeBoum;
+ bool m_bSoundSlow;
+ bool m_bForceUpdate;
+ bool m_bLowLevel;
+};
+
+
diff --git a/src/script/ClassFILE.cpp b/src/script/ClassFILE.cpp
index 2c97fab..c25d436 100644
--- a/src/script/ClassFILE.cpp
+++ b/src/script/ClassFILE.cpp
@@ -1,425 +1,425 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-
-// Static variables
-
-static CBotClass* m_pClassFILE;
-static CBotProgram* m_pFuncFile;
-static int m_CompteurFileOpen = 0;
-static char* m_filesDir;
-
-
-
-// Prepares a file name.
-
-void PrepareFilename(CBotString &filename)
-{
- int pos;
-
- pos = filename.ReverseFind('\\');
- if ( pos > 0 )
- {
- filename = filename.Mid(pos+1); // Remove files with
- }
-
- pos = filename.ReverseFind('/');
- if ( pos > 0 )
- {
- filename = filename.Mid(pos+1); // also with /
- }
-
- pos = filename.ReverseFind(':');
- if ( pos > 0 )
- {
- filename = filename.Mid(pos+1); // also removes the drive letter C:
- }
-
- filename = CBotString(m_filesDir) + CBotString("\\") + filename;
-}
-
-
-// constructor of the class
-// get the filename as a parameter
-
-// execution
-bool rfconstruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
-{
- CBotString mode;
-
- // accepts no parameters
- if ( pVar == NULL ) return true;
-
- // must be a character string
- if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return false; }
-
- CBotString filename = pVar->GivValString();
- PrepareFilename(filename);
-
- // there may be a second parameter
- pVar = pVar->GivNext();
- if ( pVar != NULL )
- {
- // recover mode
- mode = pVar->GivValString();
- if ( mode != "r" && mode != "w" ) { Exception = CBotErrBadParam; return false; }
-
- // no third parameter
- if ( pVar->GivNext() != NULL ) { Exception = CBotErrOverParam; return false; }
- }
-
- // saves the file name
- pVar = pThis->GivItem("filename");
- pVar->SetValString(filename);
-
- if ( ! mode.IsEmpty() )
- {
- // opens the requested file
- FILE* pFile = fopen( filename, mode );
- if ( pFile == NULL ) { Exception = CBotErrFileOpen; return false; }
-
- m_CompteurFileOpen ++;
-
- // save the channel file
- pVar = pThis->GivItem("handle");
- pVar->SetValInt((long)pFile);
- }
-
- return true;
-}
-
-// compilation
-CBotTypResult cfconstruct (CBotVar* pThis, CBotVar* &pVar)
-{
- // accepts no parameters
- if ( pVar == NULL ) return CBotTypResult( 0 );
-
- // must be a character string
- if ( pVar->GivType() != CBotTypString )
- return CBotTypResult( CBotErrBadString );
-
- // there may be a second parameter
- pVar = pVar->GivNext();
- if ( pVar != NULL )
- {
- // which must be a string
- if ( pVar->GivType() != CBotTypString )
- return CBotTypResult( CBotErrBadString );
- // no third parameter
- if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
- }
-
- // the result is void (constructor)
- return CBotTypResult( 0 );
-}
-
-
-// destructor of the class
-
-// execution
-bool rfdestruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
-{
- // retrieve the item "handle"
- pVar = pThis->GivItem("handle");
-
- // don't open? no problem :)
- if ( pVar->GivInit() != IS_DEF) return true;
-
- FILE* pFile= (FILE*)pVar->GivValInt();
- fclose(pFile);
- m_CompteurFileOpen --;
-
- pVar->SetInit(IS_NAN);
-
- return true;
-}
-
-
-// process FILE :: open
-// get the r/w mode as a parameter
-
-// execution
-bool rfopen (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
-{
- // there must be a parameter
- if ( pVar == NULL ) { Exception = CBotErrLowParam; return false; }
-
- // which must be a character string
- if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return false; }
-
- // There may be a second parameter
- if ( pVar->GivNext() != NULL )
- {
- // if the first parameter is the file name
- CBotString filename = pVar->GivValString();
- PrepareFilename(filename);
-
- // saves the file name
- CBotVar* pVar2 = pThis->GivItem("filename");
- pVar2->SetValString(filename);
-
- // next parameter is the mode
- pVar = pVar -> GivNext();
- }
-
- CBotString mode = pVar->GivValString();
- if ( mode != "r" && mode != "w" ) { Exception = CBotErrBadParam; return false; }
-
- // no third parameter
- if ( pVar->GivNext() != NULL ) { Exception = CBotErrOverParam; return false; }
-
- // retrieve the item "handle"
- pVar = pThis->GivItem("handle");
-
- // which must not be initialized
- if ( pVar->GivInit() == IS_DEF) { Exception = CBotErrFileOpen; return false; }
-
- // file contains the name
- pVar = pThis->GivItem("filename");
- CBotString filename = pVar->GivValString();
-
- PrepareFilename(filename); // if the name was h.filename attribute = "...";
-
- // opens the requested file
- FILE* pFile = fopen( filename, mode );
- if ( pFile == NULL )
- {
- pResult->SetValInt(false);
- return true;
- }
-
- m_CompteurFileOpen ++;
-
- // Registered the channel file
- pVar = pThis->GivItem("handle");
- pVar->SetValInt((long)pFile);
-
- pResult->SetValInt(true);
- return true;
-}
-
-// compilation
-CBotTypResult cfopen (CBotVar* pThis, CBotVar* &pVar)
-{
- // there must be a parameter
- if ( pVar == NULL ) return CBotTypResult( CBotErrLowParam );
-
- // which must be a string
- if ( pVar->GivType() != CBotTypString )
- return CBotTypResult( CBotErrBadString );
-
- // there may be a second parameter
- pVar = pVar->GivNext();
- if ( pVar != NULL )
- {
- // which must be a string
- if ( pVar->GivType() != CBotTypString )
- return CBotTypResult( CBotErrBadString );
-
- // no third parameter
- if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
- }
-
- // the result is bool
- return CBotTypResult(CBotTypBoolean);
-}
-
-
-// process FILE :: close
-
-// execeution
-bool rfclose (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
-{
- // it shouldn't be any parameters
- if ( pVar != NULL ) return CBotErrOverParam;
-
- // retrieve the item "handle"
- pVar = pThis->GivItem("handle");
-
- if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return false; }
-
- FILE* pFile= (FILE*)pVar->GivValInt();
- fclose(pFile);
- m_CompteurFileOpen --;
-
- pVar->SetInit(IS_NAN);
-
- return true;
-}
-
-// compilation
-CBotTypResult cfclose (CBotVar* pThis, CBotVar* &pVar)
-{
- // it shouldn't be any parameters
- if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
-
- // function returns a result "void"
- return CBotTypResult( 0 );
-}
-
-// process FILE :: writeln
-
-// execution
-bool rfwrite (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
-{
- // there must be a parameter
- if ( pVar == NULL ) { Exception = CBotErrLowParam; return false; }
-
- // which must be a character string
- if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return false; }
-
- CBotString param = pVar->GivValString();
-
- // retrieve the item "handle"
- pVar = pThis->GivItem("handle");
-
- if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return false; }
-
- FILE* pFile= (FILE*)pVar->GivValInt();
-
- int res = fputs(param+CBotString("\n"), pFile);
-
- // if an error occurs generate an exception
- if ( res < 0 ) { Exception = CBotErrWrite; return false; }
-
- return true;
-}
-
-// compilation
-CBotTypResult cfwrite (CBotVar* pThis, CBotVar* &pVar)
-{
- // there must be a parameter
- if ( pVar == NULL ) return CBotTypResult( CBotErrLowParam );
-
- // which must be a character string
- if ( pVar->GivType() != CBotTypString ) return CBotTypResult( CBotErrBadString );
-
- // no other parameter
- if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
-
- // the function returns a void result
- return CBotTypResult( 0 );
-}
-
-// process FILE :: readln
-
-// execution
-bool rfread (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
-{
- // it shouldn't be any parameters
- if ( pVar != NULL ) { Exception = CBotErrOverParam; return false; }
-
- // retrieve the item "handle"
- pVar = pThis->GivItem("handle");
-
- if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return false; }
-
- FILE* pFile= (FILE*)pVar->GivValInt();
-
- char chaine[2000];
- int i;
- for ( i = 0 ; i < 2000 ; i++ ) chaine[i] = 0;
-
- fgets(chaine, 1999, pFile);
-
- for ( i = 0 ; i < 2000 ; i++ ) if (chaine[i] == '\n') chaine[i] = 0;
-
- // if an error occurs generate an exception
- if ( ferror(pFile) ) { Exception = CBotErrRead; return false; }
-
- pResult->SetValString( chaine );
-
- return true;
-}
-
-// compilation
-CBotTypResult cfread (CBotVar* pThis, CBotVar* &pVar)
-{
- // it should not be any parameter
- if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
-
- // function returns a result "string"
- return CBotTypResult( CBotTypString );
-}
-// process FILE :: readln
-
-
-// execution
-bool rfeof (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
-{
- // it should not be any parameter
- if ( pVar != NULL ) { Exception = CBotErrOverParam; return false; }
-
- // retrieve the item "handle"
- pVar = pThis->GivItem("handle");
-
- if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return false; }
-
- FILE* pFile= (FILE*)pVar->GivValInt();
-
- pResult->SetValInt( feof( pFile ) );
-
- return true;
-}
-
-// compilation
-CBotTypResult cfeof (CBotVar* pThis, CBotVar* &pVar)
-{
- // it shouldn't be any parameter
- if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
-
- // the function returns a boolean result
- return CBotTypResult( CBotTypBoolean );
-}
-
-
-
-
-
-void InitClassFILE()
-{
-// create a class for file management
-// the use is as follows:
-// file canal( "NomFichier.txt" )
-// canal.open( "r" ); // open for read
-// s = canal.readln( ); // reads a line
-// canal.close(); // close the file
-
- // create the class FILE
- m_pClassFILE = new CBotClass("file", NULL);
- // adds the component ".filename"
- m_pClassFILE->AddItem("filename", CBotTypString);
- // adds the component ".handle"
- m_pClassFILE->AddItem("handle", CBotTypInt, PR_PRIVATE);
-
- // define a constructor and a destructor
- m_pClassFILE->AddFunction("file", rfconstruct, cfconstruct );
- m_pClassFILE->AddFunction("~file", rfdestruct, NULL );
-
- // end of the methods associated
- m_pClassFILE->AddFunction("open", rfopen, cfopen );
- m_pClassFILE->AddFunction("close", rfclose, cfclose );
- m_pClassFILE->AddFunction("writeln", rfwrite, cfwrite );
- m_pClassFILE->AddFunction("readln", rfread, cfread );
- m_pClassFILE->AddFunction("eof", rfeof, cfeof );
-
- m_pFuncFile = new CBotProgram( );
- CBotStringArray ListFonctions;
- m_pFuncFile->Compile( "public file openfile(string name, string mode) {return new file(name, mode);}", ListFonctions);
- m_pFuncFile->SetIdent(-2); // restoreState in special identifier for this function
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+
+// Static variables
+
+static CBotClass* m_pClassFILE;
+static CBotProgram* m_pFuncFile;
+static int m_CompteurFileOpen = 0;
+static char* m_filesDir;
+
+
+
+// Prepares a file name.
+
+void PrepareFilename(CBotString &filename)
+{
+ int pos;
+
+ pos = filename.ReverseFind('\\');
+ if ( pos > 0 )
+ {
+ filename = filename.Mid(pos+1); // Remove files with
+ }
+
+ pos = filename.ReverseFind('/');
+ if ( pos > 0 )
+ {
+ filename = filename.Mid(pos+1); // also with /
+ }
+
+ pos = filename.ReverseFind(':');
+ if ( pos > 0 )
+ {
+ filename = filename.Mid(pos+1); // also removes the drive letter C:
+ }
+
+ filename = CBotString(m_filesDir) + CBotString("\\") + filename;
+}
+
+
+// constructor of the class
+// get the filename as a parameter
+
+// execution
+bool rfconstruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ CBotString mode;
+
+ // accepts no parameters
+ if ( pVar == NULL ) return true;
+
+ // must be a character string
+ if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return false; }
+
+ CBotString filename = pVar->GivValString();
+ PrepareFilename(filename);
+
+ // there may be a second parameter
+ pVar = pVar->GivNext();
+ if ( pVar != NULL )
+ {
+ // recover mode
+ mode = pVar->GivValString();
+ if ( mode != "r" && mode != "w" ) { Exception = CBotErrBadParam; return false; }
+
+ // no third parameter
+ if ( pVar->GivNext() != NULL ) { Exception = CBotErrOverParam; return false; }
+ }
+
+ // saves the file name
+ pVar = pThis->GivItem("filename");
+ pVar->SetValString(filename);
+
+ if ( ! mode.IsEmpty() )
+ {
+ // opens the requested file
+ FILE* pFile = fopen( filename, mode );
+ if ( pFile == NULL ) { Exception = CBotErrFileOpen; return false; }
+
+ m_CompteurFileOpen ++;
+
+ // save the channel file
+ pVar = pThis->GivItem("handle");
+ pVar->SetValInt((long)pFile);
+ }
+
+ return true;
+}
+
+// compilation
+CBotTypResult cfconstruct (CBotVar* pThis, CBotVar* &pVar)
+{
+ // accepts no parameters
+ if ( pVar == NULL ) return CBotTypResult( 0 );
+
+ // must be a character string
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( CBotErrBadString );
+
+ // there may be a second parameter
+ pVar = pVar->GivNext();
+ if ( pVar != NULL )
+ {
+ // which must be a string
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( CBotErrBadString );
+ // no third parameter
+ if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
+ }
+
+ // the result is void (constructor)
+ return CBotTypResult( 0 );
+}
+
+
+// destructor of the class
+
+// execution
+bool rfdestruct (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // retrieve the item "handle"
+ pVar = pThis->GivItem("handle");
+
+ // don't open? no problem :)
+ if ( pVar->GivInit() != IS_DEF) return true;
+
+ FILE* pFile= (FILE*)pVar->GivValInt();
+ fclose(pFile);
+ m_CompteurFileOpen --;
+
+ pVar->SetInit(IS_NAN);
+
+ return true;
+}
+
+
+// process FILE :: open
+// get the r/w mode as a parameter
+
+// execution
+bool rfopen (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // there must be a parameter
+ if ( pVar == NULL ) { Exception = CBotErrLowParam; return false; }
+
+ // which must be a character string
+ if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return false; }
+
+ // There may be a second parameter
+ if ( pVar->GivNext() != NULL )
+ {
+ // if the first parameter is the file name
+ CBotString filename = pVar->GivValString();
+ PrepareFilename(filename);
+
+ // saves the file name
+ CBotVar* pVar2 = pThis->GivItem("filename");
+ pVar2->SetValString(filename);
+
+ // next parameter is the mode
+ pVar = pVar -> GivNext();
+ }
+
+ CBotString mode = pVar->GivValString();
+ if ( mode != "r" && mode != "w" ) { Exception = CBotErrBadParam; return false; }
+
+ // no third parameter
+ if ( pVar->GivNext() != NULL ) { Exception = CBotErrOverParam; return false; }
+
+ // retrieve the item "handle"
+ pVar = pThis->GivItem("handle");
+
+ // which must not be initialized
+ if ( pVar->GivInit() == IS_DEF) { Exception = CBotErrFileOpen; return false; }
+
+ // file contains the name
+ pVar = pThis->GivItem("filename");
+ CBotString filename = pVar->GivValString();
+
+ PrepareFilename(filename); // if the name was h.filename attribute = "...";
+
+ // opens the requested file
+ FILE* pFile = fopen( filename, mode );
+ if ( pFile == NULL )
+ {
+ pResult->SetValInt(false);
+ return true;
+ }
+
+ m_CompteurFileOpen ++;
+
+ // Registered the channel file
+ pVar = pThis->GivItem("handle");
+ pVar->SetValInt((long)pFile);
+
+ pResult->SetValInt(true);
+ return true;
+}
+
+// compilation
+CBotTypResult cfopen (CBotVar* pThis, CBotVar* &pVar)
+{
+ // there must be a parameter
+ if ( pVar == NULL ) return CBotTypResult( CBotErrLowParam );
+
+ // which must be a string
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( CBotErrBadString );
+
+ // there may be a second parameter
+ pVar = pVar->GivNext();
+ if ( pVar != NULL )
+ {
+ // which must be a string
+ if ( pVar->GivType() != CBotTypString )
+ return CBotTypResult( CBotErrBadString );
+
+ // no third parameter
+ if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
+ }
+
+ // the result is bool
+ return CBotTypResult(CBotTypBoolean);
+}
+
+
+// process FILE :: close
+
+// execeution
+bool rfclose (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // it shouldn't be any parameters
+ if ( pVar != NULL ) return CBotErrOverParam;
+
+ // retrieve the item "handle"
+ pVar = pThis->GivItem("handle");
+
+ if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return false; }
+
+ FILE* pFile= (FILE*)pVar->GivValInt();
+ fclose(pFile);
+ m_CompteurFileOpen --;
+
+ pVar->SetInit(IS_NAN);
+
+ return true;
+}
+
+// compilation
+CBotTypResult cfclose (CBotVar* pThis, CBotVar* &pVar)
+{
+ // it shouldn't be any parameters
+ if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
+
+ // function returns a result "void"
+ return CBotTypResult( 0 );
+}
+
+// process FILE :: writeln
+
+// execution
+bool rfwrite (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // there must be a parameter
+ if ( pVar == NULL ) { Exception = CBotErrLowParam; return false; }
+
+ // which must be a character string
+ if ( pVar->GivType() != CBotTypString ) { Exception = CBotErrBadString; return false; }
+
+ CBotString param = pVar->GivValString();
+
+ // retrieve the item "handle"
+ pVar = pThis->GivItem("handle");
+
+ if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return false; }
+
+ FILE* pFile= (FILE*)pVar->GivValInt();
+
+ int res = fputs(param+CBotString("\n"), pFile);
+
+ // if an error occurs generate an exception
+ if ( res < 0 ) { Exception = CBotErrWrite; return false; }
+
+ return true;
+}
+
+// compilation
+CBotTypResult cfwrite (CBotVar* pThis, CBotVar* &pVar)
+{
+ // there must be a parameter
+ if ( pVar == NULL ) return CBotTypResult( CBotErrLowParam );
+
+ // which must be a character string
+ if ( pVar->GivType() != CBotTypString ) return CBotTypResult( CBotErrBadString );
+
+ // no other parameter
+ if ( pVar->GivNext() != NULL ) return CBotTypResult( CBotErrOverParam );
+
+ // the function returns a void result
+ return CBotTypResult( 0 );
+}
+
+// process FILE :: readln
+
+// execution
+bool rfread (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // it shouldn't be any parameters
+ if ( pVar != NULL ) { Exception = CBotErrOverParam; return false; }
+
+ // retrieve the item "handle"
+ pVar = pThis->GivItem("handle");
+
+ if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return false; }
+
+ FILE* pFile= (FILE*)pVar->GivValInt();
+
+ char chaine[2000];
+ int i;
+ for ( i = 0 ; i < 2000 ; i++ ) chaine[i] = 0;
+
+ fgets(chaine, 1999, pFile);
+
+ for ( i = 0 ; i < 2000 ; i++ ) if (chaine[i] == '\n') chaine[i] = 0;
+
+ // if an error occurs generate an exception
+ if ( ferror(pFile) ) { Exception = CBotErrRead; return false; }
+
+ pResult->SetValString( chaine );
+
+ return true;
+}
+
+// compilation
+CBotTypResult cfread (CBotVar* pThis, CBotVar* &pVar)
+{
+ // it should not be any parameter
+ if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
+
+ // function returns a result "string"
+ return CBotTypResult( CBotTypString );
+}
+// process FILE :: readln
+
+
+// execution
+bool rfeof (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception)
+{
+ // it should not be any parameter
+ if ( pVar != NULL ) { Exception = CBotErrOverParam; return false; }
+
+ // retrieve the item "handle"
+ pVar = pThis->GivItem("handle");
+
+ if ( pVar->GivInit() != IS_DEF) { Exception = CBotErrNotOpen; return false; }
+
+ FILE* pFile= (FILE*)pVar->GivValInt();
+
+ pResult->SetValInt( feof( pFile ) );
+
+ return true;
+}
+
+// compilation
+CBotTypResult cfeof (CBotVar* pThis, CBotVar* &pVar)
+{
+ // it shouldn't be any parameter
+ if ( pVar != NULL ) return CBotTypResult( CBotErrOverParam );
+
+ // the function returns a boolean result
+ return CBotTypResult( CBotTypBoolean );
+}
+
+
+
+
+
+void InitClassFILE()
+{
+// create a class for file management
+// the use is as follows:
+// file canal( "NomFichier.txt" )
+// canal.open( "r" ); // open for read
+// s = canal.readln( ); // reads a line
+// canal.close(); // close the file
+
+ // create the class FILE
+ m_pClassFILE = new CBotClass("file", NULL);
+ // adds the component ".filename"
+ m_pClassFILE->AddItem("filename", CBotTypString);
+ // adds the component ".handle"
+ m_pClassFILE->AddItem("handle", CBotTypInt, PR_PRIVATE);
+
+ // define a constructor and a destructor
+ m_pClassFILE->AddFunction("file", rfconstruct, cfconstruct );
+ m_pClassFILE->AddFunction("~file", rfdestruct, NULL );
+
+ // end of the methods associated
+ m_pClassFILE->AddFunction("open", rfopen, cfopen );
+ m_pClassFILE->AddFunction("close", rfclose, cfclose );
+ m_pClassFILE->AddFunction("writeln", rfwrite, cfwrite );
+ m_pClassFILE->AddFunction("readln", rfread, cfread );
+ m_pClassFILE->AddFunction("eof", rfeof, cfeof );
+
+ m_pFuncFile = new CBotProgram( );
+ CBotStringArray ListFonctions;
+ m_pFuncFile->Compile( "public file openfile(string name, string mode) {return new file(name, mode);}", ListFonctions);
+ m_pFuncFile->SetIdent(-2); // restoreState in special identifier for this function
+}
+
diff --git a/src/script/cbottoken.cpp b/src/script/cbottoken.cpp
index 568c870..223da4d 100644
--- a/src/script/cbottoken.cpp
+++ b/src/script/cbottoken.cpp
@@ -1,519 +1,519 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/language.h"
-#include "common/global.h"
-#include "common/event.h"
-#include "object/object.h"
-#include "script/cbottoken.h"
-
-
-
-
-// Seeking the name of an object.
-
-char* RetObjectName(ObjectType type)
-{
- if ( type == OBJECT_PORTICO ) return "Portico";
- if ( type == OBJECT_BASE ) return "SpaceShip";
- if ( type == OBJECT_DERRICK ) return "Derrick";
- if ( type == OBJECT_FACTORY ) return "BotFactory";
- if ( type == OBJECT_STATION ) return "PowerStation";
- if ( type == OBJECT_CONVERT ) return "Converter";
- if ( type == OBJECT_REPAIR ) return "RepairCenter";
- if ( type == OBJECT_DESTROYER ) return "Destroyer";
- if ( type == OBJECT_TOWER ) return "DefenseTower";
- if ( type == OBJECT_NEST ) return "AlienNest";
- if ( type == OBJECT_RESEARCH ) return "ResearchCenter";
- if ( type == OBJECT_RADAR ) return "RadarStation";
- if ( type == OBJECT_INFO ) return "ExchangePost";
- if ( type == OBJECT_ENERGY ) return "PowerPlant";
- if ( type == OBJECT_LABO ) return "AutoLab";
- if ( type == OBJECT_NUCLEAR ) return "NuclearPlant";
- if ( type == OBJECT_PARA ) return "PowerCaptor";
- if ( type == OBJECT_SAFE ) return "Vault";
- if ( type == OBJECT_HUSTON ) return "Houston";
- if ( type == OBJECT_TARGET1 ) return "Target1";
- if ( type == OBJECT_TARGET2 ) return "Target2";
- if ( type == OBJECT_START ) return "StartArea";
- if ( type == OBJECT_END ) return "GoalArea";
- if ( type == OBJECT_TEEN34 ) return "Stone";
- if ( type == OBJECT_STONE ) return "TitaniumOre";
- if ( type == OBJECT_URANIUM ) return "UraniumOre";
- if ( type == OBJECT_METAL ) return "Titanium";
- if ( type == OBJECT_POWER ) return "PowerCell";
- if ( type == OBJECT_ATOMIC ) return "NuclearCell";
- if ( type == OBJECT_BULLET ) return "OrgaMatter";
- if ( type == OBJECT_BBOX ) return "BlackBox";
- if ( type == OBJECT_KEYa ) return "KeyA";
- if ( type == OBJECT_KEYb ) return "KeyB";
- if ( type == OBJECT_KEYc ) return "KeyC";
- if ( type == OBJECT_KEYd ) return "KeyD";
- if ( type == OBJECT_TNT ) return "TNT";
- if ( type == OBJECT_SCRAP1 ) return "Scrap";
- if ( type == OBJECT_BOMB ) return "Mine";
- if ( type == OBJECT_BARRIER1 ) return "Barrier";
- if ( type == OBJECT_WAYPOINT ) return "WayPoint";
- if ( type == OBJECT_FLAGb ) return "BlueFlag";
- if ( type == OBJECT_FLAGr ) return "RedFlag";
- if ( type == OBJECT_FLAGg ) return "GreenFlag";
- if ( type == OBJECT_FLAGy ) return "YellowFlag";
- if ( type == OBJECT_FLAGv ) return "VioletFlag";
- if ( type == OBJECT_MARKPOWER ) return "PowerSpot";
- if ( type == OBJECT_MARKSTONE ) return "TitaniumSpot";
- if ( type == OBJECT_MARKURANIUM ) return "UraniumSpot";
- if ( type == OBJECT_MARKKEYa ) return "KeyASpot";
- if ( type == OBJECT_MARKKEYb ) return "KeyBSpot";
- if ( type == OBJECT_MARKKEYc ) return "KeyCSpot";
- if ( type == OBJECT_MARKKEYd ) return "KeyDSpot";
- if ( type == OBJECT_MOBILEwt ) return "PracticeBot";
- if ( type == OBJECT_MOBILEwa ) return "WheeledGrabber";
- if ( type == OBJECT_MOBILEta ) return "TrackedGrabber";
- if ( type == OBJECT_MOBILEfa ) return "WingedGrabber";
- if ( type == OBJECT_MOBILEia ) return "LeggedGrabber";
- if ( type == OBJECT_MOBILEwc ) return "WheeledShooter";
- if ( type == OBJECT_MOBILEtc ) return "TrackedShooter";
- if ( type == OBJECT_MOBILEfc ) return "WingedShooter";
- if ( type == OBJECT_MOBILEic ) return "LeggedShooter";
- if ( type == OBJECT_MOBILEwi ) return "WheeledOrgaShooter";
- if ( type == OBJECT_MOBILEti ) return "TrackedOrgaShooter";
- if ( type == OBJECT_MOBILEfi ) return "WingedOrgaShooter";
- if ( type == OBJECT_MOBILEii ) return "LeggedOrgaShooter";
- if ( type == OBJECT_MOBILEws ) return "WheeledSniffer";
- if ( type == OBJECT_MOBILEts ) return "TrackedSniffer";
- if ( type == OBJECT_MOBILEfs ) return "WingedSniffer";
- if ( type == OBJECT_MOBILEis ) return "LeggedSniffer";
- if ( type == OBJECT_MOBILErt ) return "Thumper";
- if ( type == OBJECT_MOBILErc ) return "PhazerShooter";
- if ( type == OBJECT_MOBILErr ) return "Recycler";
- if ( type == OBJECT_MOBILErs ) return "Shielder";
- if ( type == OBJECT_MOBILEsa ) return "Subber";
- if ( type == OBJECT_MOBILEtg ) return "TargetBot";
- if ( type == OBJECT_MOBILEdr ) return "Scribbler";
- if ( type == OBJECT_HUMAN ) return "Me";
- if ( type == OBJECT_TECH ) return "Tech";
- if ( type == OBJECT_MOTHER ) return "AlienQueen";
- if ( type == OBJECT_EGG ) return "AlienEgg";
- if ( type == OBJECT_ANT ) return "AlienAnt";
- if ( type == OBJECT_SPIDER ) return "AlienSpider";
- if ( type == OBJECT_BEE ) return "AlienWasp";
- if ( type == OBJECT_WORM ) return "AlienWorm";
- if ( type == OBJECT_RUINmobilew1) return "Wreck";
- return "";
-}
-
-// Seeking the name of a secondary object.
-// (because Otto thinks that Germans do not like nuclear power)
-
-char* RetObjectAlias(ObjectType type)
-{
- if ( type == OBJECT_NUCLEAR ) return "FuelCellPlant";
- if ( type == OBJECT_URANIUM ) return "PlatinumOre";
- if ( type == OBJECT_ATOMIC ) return "FuelCell";
- if ( type == OBJECT_MARKURANIUM ) return "PlatinumSpot";
- if ( type == OBJECT_ENERGY ) return "Disintegrator"; // for K-CeeBot
- return "";
-}
-
-
-// Returns the help file to use for the object.
-
-char* RetHelpFilename(ObjectType type)
-{
- if ( type == OBJECT_BASE ) return "help\\object\\base.txt";
- if ( type == OBJECT_DERRICK ) return "help\\object\\derrick.txt";
- if ( type == OBJECT_FACTORY ) return "help\\object\\factory.txt";
- if ( type == OBJECT_STATION ) return "help\\object\\station.txt";
- if ( type == OBJECT_CONVERT ) return "help\\object\\convert.txt";
- if ( type == OBJECT_REPAIR ) return "help\\object\\repair.txt";
- if ( type == OBJECT_DESTROYER ) return "help\\object\\destroy.txt";
- if ( type == OBJECT_TOWER ) return "help\\object\\tower.txt";
- if ( type == OBJECT_NEST ) return "help\\object\\nest.txt";
- if ( type == OBJECT_RESEARCH ) return "help\\object\\research.txt";
- if ( type == OBJECT_RADAR ) return "help\\object\\radar.txt";
- if ( type == OBJECT_INFO ) return "help\\object\\exchange.txt";
- if ( type == OBJECT_ENERGY ) return "help\\object\\energy.txt";
- if ( type == OBJECT_LABO ) return "help\\object\\labo.txt";
- if ( type == OBJECT_NUCLEAR ) return "help\\object\\nuclear.txt";
- if ( type == OBJECT_PARA ) return "help\\object\\captor.txt";
- if ( type == OBJECT_SAFE ) return "help\\object\\safe.txt";
- if ( type == OBJECT_HUSTON ) return "help\\object\\huston.txt";
- if ( type == OBJECT_START ) return "help\\object\\start.txt";
- if ( type == OBJECT_END ) return "help\\object\\goal.txt";
- if ( type == OBJECT_STONE ) return "help\\object\\titanore.txt";
- if ( type == OBJECT_URANIUM ) return "help\\object\\uranore.txt";
- if ( type == OBJECT_METAL ) return "help\\object\\titan.txt";
- if ( type == OBJECT_POWER ) return "help\\object\\power.txt";
- if ( type == OBJECT_ATOMIC ) return "help\\object\\atomic.txt";
- if ( type == OBJECT_BULLET ) return "help\\object\\bullet.txt";
- if ( type == OBJECT_BBOX ) return "help\\object\\bbox.txt";
- if ( type == OBJECT_KEYa ) return "help\\object\\key.txt";
- if ( type == OBJECT_KEYb ) return "help\\object\\key.txt";
- if ( type == OBJECT_KEYc ) return "help\\object\\key.txt";
- if ( type == OBJECT_KEYd ) return "help\\object\\key.txt";
- if ( type == OBJECT_TNT ) return "help\\object\\tnt.txt";
- if ( type == OBJECT_SCRAP1 ) return "help\\object\\scrap.txt";
- if ( type == OBJECT_BOMB ) return "help\\object\\mine.txt";
- if ( type == OBJECT_BARRIER1 ) return "help\\object\\barrier.txt";
- if ( type == OBJECT_WAYPOINT ) return "help\\object\\waypoint.txt";
- if ( type == OBJECT_FLAGb ) return "help\\object\\flag.txt";
- if ( type == OBJECT_FLAGr ) return "help\\object\\flag.txt";
- if ( type == OBJECT_FLAGg ) return "help\\object\\flag.txt";
- if ( type == OBJECT_FLAGy ) return "help\\object\\flag.txt";
- if ( type == OBJECT_FLAGv ) return "help\\object\\flag.txt";
- if ( type == OBJECT_MARKPOWER ) return "help\\object\\enerspot.txt";
- if ( type == OBJECT_MARKSTONE ) return "help\\object\\stonspot.txt";
- if ( type == OBJECT_MARKURANIUM ) return "help\\object\\uranspot.txt";
- if ( type == OBJECT_MOBILEwa ) return "help\\object\\botgr.txt";
- if ( type == OBJECT_MOBILEta ) return "help\\object\\botgc.txt";
- if ( type == OBJECT_MOBILEfa ) return "help\\object\\botgj.txt";
- if ( type == OBJECT_MOBILEia ) return "help\\object\\botgs.txt";
- if ( type == OBJECT_MOBILEws ) return "help\\object\\botsr.txt";
- if ( type == OBJECT_MOBILEts ) return "help\\object\\botsc.txt";
- if ( type == OBJECT_MOBILEfs ) return "help\\object\\botsj.txt";
- if ( type == OBJECT_MOBILEis ) return "help\\object\\botss.txt";
- if ( type == OBJECT_MOBILEwi ) return "help\\object\\botor.txt";
- if ( type == OBJECT_MOBILEti ) return "help\\object\\botoc.txt";
- if ( type == OBJECT_MOBILEfi ) return "help\\object\\botoj.txt";
- if ( type == OBJECT_MOBILEii ) return "help\\object\\botos.txt";
- if ( type == OBJECT_MOBILEwc ) return "help\\object\\botfr.txt";
- if ( type == OBJECT_MOBILEtc ) return "help\\object\\botfc.txt";
- if ( type == OBJECT_MOBILEfc ) return "help\\object\\botfj.txt";
- if ( type == OBJECT_MOBILEic ) return "help\\object\\botfs.txt";
- if ( type == OBJECT_MOBILErt ) return "help\\object\\bottump.txt";
- if ( type == OBJECT_MOBILErc ) return "help\\object\\botphaz.txt";
- if ( type == OBJECT_MOBILErr ) return "help\\object\\botrecy.txt";
- if ( type == OBJECT_MOBILErs ) return "help\\object\\botshld.txt";
- if ( type == OBJECT_MOBILEsa ) return "help\\object\\botsub.txt";
- if ( type == OBJECT_MOBILEwt ) return "help\\object\\bottr.txt";
- if ( type == OBJECT_MOBILEtg ) return "help\\object\\bottarg.txt";
- if ( type == OBJECT_MOBILEdr ) return "help\\object\\botdraw.txt";
- if ( type == OBJECT_APOLLO2 ) return "help\\object\\lrv.txt";
- if ( type == OBJECT_HUMAN ) return "help\\object\\human.txt";
- if ( type == OBJECT_MOTHER ) return "help\\object\\mother.txt";
- if ( type == OBJECT_EGG ) return "help\\object\\egg.txt";
- if ( type == OBJECT_ANT ) return "help\\object\\ant.txt";
- if ( type == OBJECT_SPIDER ) return "help\\object\\spider.txt";
- if ( type == OBJECT_BEE ) return "help\\object\\wasp.txt";
- if ( type == OBJECT_WORM ) return "help\\object\\worm.txt";
- if ( type == OBJECT_RUINmobilew1) return "help\\object\\wreck.txt";
- return "";
-}
-
-
-// Returns the help file to use for instruction.
-
-char* RetHelpFilename(const char *token)
-{
- if ( strcmp(token, "if" ) == 0 ) return "help\\cbot\\if.txt";
- if ( strcmp(token, "else" ) == 0 ) return "help\\cbot\\if.txt";
- if ( strcmp(token, "repeat" ) == 0 ) return "help\\cbot\\repeat.txt";
- if ( strcmp(token, "for" ) == 0 ) return "help\\cbot\\for.txt";
- if ( strcmp(token, "while" ) == 0 ) return "help\\cbot\\while.txt";
- if ( strcmp(token, "do" ) == 0 ) return "help\\cbot\\do.txt";
- if ( strcmp(token, "break" ) == 0 ) return "help\\cbot\\break.txt";
- if ( strcmp(token, "continue" ) == 0 ) return "help\\cbot\\continue.txt";
- if ( strcmp(token, "return" ) == 0 ) return "help\\cbot\\return.txt";
- if ( strcmp(token, "sizeof" ) == 0 ) return "help\\cbot\\sizeof.txt";
- if ( strcmp(token, "int" ) == 0 ) return "help\\cbot\\int.txt";
- if ( strcmp(token, "float" ) == 0 ) return "help\\cbot\\float.txt";
- if ( strcmp(token, "bool" ) == 0 ) return "help\\cbot\\bool.txt";
- if ( strcmp(token, "string" ) == 0 ) return "help\\cbot\\string.txt";
- if ( strcmp(token, "point" ) == 0 ) return "help\\cbot\\point.txt";
- if ( strcmp(token, "object" ) == 0 ) return "help\\cbot\\object.txt";
- if ( strcmp(token, "file" ) == 0 ) return "help\\cbot\\file.txt";
- if ( strcmp(token, "void" ) == 0 ) return "help\\cbot\\void.txt";
- if ( strcmp(token, "null" ) == 0 ) return "help\\cbot\\null.txt";
- if ( strcmp(token, "nan" ) == 0 ) return "help\\cbot\\nan.txt";
- if ( strcmp(token, "true" ) == 0 ) return "help\\cbot\\true.txt";
- if ( strcmp(token, "false" ) == 0 ) return "help\\cbot\\false.txt";
- if ( strcmp(token, "sin" ) == 0 ) return "help\\cbot\\expr.txt";
- if ( strcmp(token, "cos" ) == 0 ) return "help\\cbot\\expr.txt";
- if ( strcmp(token, "tan" ) == 0 ) return "help\\cbot\\expr.txt";
- if ( strcmp(token, "asin" ) == 0 ) return "help\\cbot\\expr.txt";
- if ( strcmp(token, "acos" ) == 0 ) return "help\\cbot\\expr.txt";
- if ( strcmp(token, "atan" ) == 0 ) return "help\\cbot\\expr.txt";
- if ( strcmp(token, "sqrt" ) == 0 ) return "help\\cbot\\expr.txt";
- if ( strcmp(token, "pow" ) == 0 ) return "help\\cbot\\expr.txt";
- if ( strcmp(token, "rand" ) == 0 ) return "help\\cbot\\expr.txt";
- if ( strcmp(token, "abs" ) == 0 ) return "help\\cbot\\expr.txt";
- if ( strcmp(token, "retobject" ) == 0 ) return "help\\cbot\\retobj.txt";
- if ( strcmp(token, "search" ) == 0 ) return "help\\cbot\\search.txt";
- if ( strcmp(token, "radar" ) == 0 ) return "help\\cbot\\radar.txt";
- if ( strcmp(token, "direction" ) == 0 ) return "help\\cbot\\direct.txt";
- if ( strcmp(token, "distance" ) == 0 ) return "help\\cbot\\dist.txt";
- if ( strcmp(token, "distance2d" ) == 0 ) return "help\\cbot\\dist2d.txt";
- if ( strcmp(token, "space" ) == 0 ) return "help\\cbot\\space.txt";
- if ( strcmp(token, "flatground" ) == 0 ) return "help\\cbot\\flatgrnd.txt";
- if ( strcmp(token, "wait" ) == 0 ) return "help\\cbot\\wait.txt";
- if ( strcmp(token, "move" ) == 0 ) return "help\\cbot\\move.txt";
- if ( strcmp(token, "turn" ) == 0 ) return "help\\cbot\\turn.txt";
- if ( strcmp(token, "goto" ) == 0 ) return "help\\cbot\\goto.txt";
- if ( strcmp(token, "find" ) == 0 ) return "help\\cbot\\find.txt";
- if ( strcmp(token, "grab" ) == 0 ) return "help\\cbot\\grab.txt";
- if ( strcmp(token, "drop" ) == 0 ) return "help\\cbot\\drop.txt";
- if ( strcmp(token, "sniff" ) == 0 ) return "help\\cbot\\sniff.txt";
- if ( strcmp(token, "receive" ) == 0 ) return "help\\cbot\\receive.txt";
- if ( strcmp(token, "send" ) == 0 ) return "help\\cbot\\send.txt";
- if ( strcmp(token, "deleteinfo" ) == 0 ) return "help\\cbot\\delinfo.txt";
- if ( strcmp(token, "testinfo" ) == 0 ) return "help\\cbot\\testinfo.txt";
- if ( strcmp(token, "thump" ) == 0 ) return "help\\cbot\\thump.txt";
- if ( strcmp(token, "recycle" ) == 0 ) return "help\\cbot\\recycle.txt";
- if ( strcmp(token, "shield" ) == 0 ) return "help\\cbot\\shield.txt";
- if ( strcmp(token, "fire" ) == 0 ) return "help\\cbot\\fire.txt";
- if ( strcmp(token, "antfire" ) == 0 ) return "help\\cbot\\antfire.txt";
- if ( strcmp(token, "aim" ) == 0 ) return "help\\cbot\\aim.txt";
- if ( strcmp(token, "motor" ) == 0 ) return "help\\cbot\\motor.txt";
- if ( strcmp(token, "jet" ) == 0 ) return "help\\cbot\\jet.txt";
- if ( strcmp(token, "topo" ) == 0 ) return "help\\cbot\\topo.txt";
- if ( strcmp(token, "message" ) == 0 ) return "help\\cbot\\message.txt";
- if ( strcmp(token, "abstime" ) == 0 ) return "help\\cbot\\abstime.txt";
- if ( strcmp(token, "BlackArrow" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "RedArrow" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "White" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "Black" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "Gray" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "LightGray" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "Red" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "Pink" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "Purple" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "Orange" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "Yellow" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "Beige" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "Brown" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "Skin" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "Green" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "LightGreen" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "Blue" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "LightBlue" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "InFront" ) == 0 ) return "help\\cbot\\grab.txt";
- if ( strcmp(token, "Behind" ) == 0 ) return "help\\cbot\\grab.txt";
- if ( strcmp(token, "EnergyCell" ) == 0 ) return "help\\cbot\\grab.txt";
- if ( strcmp(token, "DisplayError" ) == 0 ) return "help\\cbot\\message.txt";
- if ( strcmp(token, "DisplayWarning") == 0 ) return "help\\cbot\\message.txt";
- if ( strcmp(token, "DisplayInfo" ) == 0 ) return "help\\cbot\\message.txt";
- if ( strcmp(token, "DisplayMessage") == 0 ) return "help\\cbot\\message.txt";
- if ( strcmp(token, "strlen" ) == 0 ) return "help\\cbot\\string.txt";
- if ( strcmp(token, "strleft" ) == 0 ) return "help\\cbot\\string.txt";
- if ( strcmp(token, "strright" ) == 0 ) return "help\\cbot\\string.txt";
- if ( strcmp(token, "strmid" ) == 0 ) return "help\\cbot\\string.txt";
- if ( strcmp(token, "strval" ) == 0 ) return "help\\cbot\\string.txt";
- if ( strcmp(token, "strfind" ) == 0 ) return "help\\cbot\\string.txt";
- if ( strcmp(token, "strlower" ) == 0 ) return "help\\cbot\\string.txt";
- if ( strcmp(token, "strupper" ) == 0 ) return "help\\cbot\\string.txt";
- if ( strcmp(token, "open" ) == 0 ) return "help\\cbot\\open.txt";
- if ( strcmp(token, "close" ) == 0 ) return "help\\cbot\\close.txt";
- if ( strcmp(token, "writeln" ) == 0 ) return "help\\cbot\\writeln.txt";
- if ( strcmp(token, "readln " ) == 0 ) return "help\\cbot\\readln.txt";
- if ( strcmp(token, "eof" ) == 0 ) return "help\\cbot\\eof.txt";
- if ( strcmp(token, "deletefile" ) == 0 ) return "help\\cbot\\deletef.txt";
- if ( strcmp(token, "openfile" ) == 0 ) return "help\\cbot\\openfile.txt";
- if ( strcmp(token, "pendown" ) == 0 ) return "help\\cbot\\pendown.txt";
- if ( strcmp(token, "penup" ) == 0 ) return "help\\cbot\\penup.txt";
- if ( strcmp(token, "pencolor" ) == 0 ) return "help\\cbot\\pencolor.txt";
- if ( strcmp(token, "penwidth" ) == 0 ) return "help\\cbot\\penwidth.txt";
- if ( strcmp(token, "extern" ) == 0 ) return "help\\cbot\\extern.txt";
- if ( strcmp(token, "class" ) == 0 ) return "help\\cbot\\class.txt";
- if ( strcmp(token, "static" ) == 0 ) return "help\\cbot\\static.txt";
- if ( strcmp(token, "public" ) == 0 ) return "help\\cbot\\public.txt";
- if ( strcmp(token, "private" ) == 0 ) return "help\\cbot\\private.txt";
- if ( strcmp(token, "synchronized" ) == 0 ) return "help\\cbot\\synchro.txt";
- if ( strcmp(token, "new" ) == 0 ) return "help\\cbot\\new.txt";
- if ( strcmp(token, "this" ) == 0 ) return "help\\cbot\\this.txt";
- return "";
-}
-
-
-// Test if a keyword is a type of variable.
-
-bool IsType(const char *token)
-{
- if ( strcmp(token, "void" ) == 0 ) return true;
- if ( strcmp(token, "int" ) == 0 ) return true;
- if ( strcmp(token, "float" ) == 0 ) return true;
- if ( strcmp(token, "bool" ) == 0 ) return true;
- if ( strcmp(token, "string" ) == 0 ) return true;
- if ( strcmp(token, "point" ) == 0 ) return true;
- if ( strcmp(token, "object" ) == 0 ) return true;
- if ( strcmp(token, "file" ) == 0 ) return true;
- if ( strcmp(token, "this" ) == 0 ) return true;
- return false;
-}
-
-// Test if a keyword is a function.
-
-bool IsFunction(const char *token)
-{
- if ( strcmp(token, "sin" ) == 0 ) return true;
- if ( strcmp(token, "cos" ) == 0 ) return true;
- if ( strcmp(token, "tan" ) == 0 ) return true;
- if ( strcmp(token, "asin" ) == 0 ) return true;
- if ( strcmp(token, "acos" ) == 0 ) return true;
- if ( strcmp(token, "atan" ) == 0 ) return true;
- if ( strcmp(token, "sqrt" ) == 0 ) return true;
- if ( strcmp(token, "pow" ) == 0 ) return true;
- if ( strcmp(token, "rand" ) == 0 ) return true;
- if ( strcmp(token, "abs" ) == 0 ) return true;
- if ( strcmp(token, "retobject" ) == 0 ) return true;
- if ( strcmp(token, "search" ) == 0 ) return true;
- if ( strcmp(token, "radar" ) == 0 ) return true;
- if ( strcmp(token, "detect" ) == 0 ) return true;
- if ( strcmp(token, "direction" ) == 0 ) return true;
- if ( strcmp(token, "distance" ) == 0 ) return true;
- if ( strcmp(token, "distance2d" ) == 0 ) return true;
- if ( strcmp(token, "space" ) == 0 ) return true;
- if ( strcmp(token, "flatground" ) == 0 ) return true;
- if ( strcmp(token, "wait" ) == 0 ) return true;
- if ( strcmp(token, "move" ) == 0 ) return true;
- if ( strcmp(token, "turn" ) == 0 ) return true;
- if ( strcmp(token, "goto" ) == 0 ) return true;
- if ( strcmp(token, "find" ) == 0 ) return true;
- if ( strcmp(token, "grab" ) == 0 ) return true;
- if ( strcmp(token, "drop" ) == 0 ) return true;
- if ( strcmp(token, "sniff" ) == 0 ) return true;
- if ( strcmp(token, "receive" ) == 0 ) return true;
- if ( strcmp(token, "send" ) == 0 ) return true;
- if ( strcmp(token, "deleteinfo" ) == 0 ) return true;
- if ( strcmp(token, "testinfo" ) == 0 ) return true;
- if ( strcmp(token, "thump" ) == 0 ) return true;
- if ( strcmp(token, "recycle" ) == 0 ) return true;
- if ( strcmp(token, "shield" ) == 0 ) return true;
- if ( strcmp(token, "fire" ) == 0 ) return true;
- if ( strcmp(token, "antfire" ) == 0 ) return true;
- if ( strcmp(token, "aim" ) == 0 ) return true;
- if ( strcmp(token, "motor" ) == 0 ) return true;
- if ( strcmp(token, "jet" ) == 0 ) return true;
- if ( strcmp(token, "topo" ) == 0 ) return true;
- if ( strcmp(token, "message" ) == 0 ) return true;
- if ( strcmp(token, "abstime" ) == 0 ) return true;
- if ( strcmp(token, "ismovie" ) == 0 ) return true;
- if ( strcmp(token, "errmode" ) == 0 ) return true;
- if ( strcmp(token, "ipf" ) == 0 ) return true;
- if ( strcmp(token, "strlen" ) == 0 ) return true;
- if ( strcmp(token, "strleft" ) == 0 ) return true;
- if ( strcmp(token, "strright" ) == 0 ) return true;
- if ( strcmp(token, "strmid" ) == 0 ) return true;
- if ( strcmp(token, "strval" ) == 0 ) return true;
- if ( strcmp(token, "strfind" ) == 0 ) return true;
- if ( strcmp(token, "strlower" ) == 0 ) return true;
- if ( strcmp(token, "strupper" ) == 0 ) return true;
- if ( strcmp(token, "open" ) == 0 ) return true;
- if ( strcmp(token, "close" ) == 0 ) return true;
- if ( strcmp(token, "writeln" ) == 0 ) return true;
- if ( strcmp(token, "readln" ) == 0 ) return true;
- if ( strcmp(token, "eof" ) == 0 ) return true;
- if ( strcmp(token, "deletefile" ) == 0 ) return true;
- if ( strcmp(token, "openfile" ) == 0 ) return true;
- if ( strcmp(token, "pendown" ) == 0 ) return true;
- if ( strcmp(token, "penup" ) == 0 ) return true;
- if ( strcmp(token, "pencolor" ) == 0 ) return true;
- if ( strcmp(token, "penwidth" ) == 0 ) return true;
- if ( strcmp(token, "sizeof" ) == 0 ) return true;
- return false;
-}
-
-
-// Returns using a compact instruction.
-
-char* RetHelpText(const char *token)
-{
- if ( strcmp(token, "if" ) == 0 ) return "if ( condition ) { bloc }";
- if ( strcmp(token, "else" ) == 0 ) return "else { bloc }";
- if ( strcmp(token, "repeat" ) == 0 ) return "repeat ( number )";
- if ( strcmp(token, "for" ) == 0 ) return "for ( before ; condition ; end )";
- if ( strcmp(token, "while" ) == 0 ) return "while ( condition ) { bloc }";
- if ( strcmp(token, "do" ) == 0 ) return "do { bloc } while ( condition );";
- if ( strcmp(token, "break" ) == 0 ) return "break;";
- if ( strcmp(token, "continue" ) == 0 ) return "continue;";
- if ( strcmp(token, "return" ) == 0 ) return "return;";
- if ( strcmp(token, "sizeof" ) == 0 ) return "sizeof( array );";
- if ( strcmp(token, "int" ) == 0 ) return "int";
- if ( strcmp(token, "sin" ) == 0 ) return "sin ( angle );";
- if ( strcmp(token, "cos" ) == 0 ) return "cos ( angle );";
- if ( strcmp(token, "tan" ) == 0 ) return "tan ( angle );";
- if ( strcmp(token, "asin" ) == 0 ) return "asin ( value );";
- if ( strcmp(token, "acos" ) == 0 ) return "acos ( value );";
- if ( strcmp(token, "atan" ) == 0 ) return "atan ( value );";
- if ( strcmp(token, "sqrt" ) == 0 ) return "sqrt ( value );";
- if ( strcmp(token, "pow" ) == 0 ) return "pow ( x, y );";
- if ( strcmp(token, "rand" ) == 0 ) return "rand ( );";
- if ( strcmp(token, "abs" ) == 0 ) return "abs ( value );";
- if ( strcmp(token, "retobject" ) == 0 ) return "retobjet ( );";
- if ( strcmp(token, "search" ) == 0 ) return "search ( );";
- if ( strcmp(token, "radar" ) == 0 ) return "radar ( cat, angle, focus, min, max, sens );";
- if ( strcmp(token, "detect" ) == 0 ) return "detect ( cat );";
- if ( strcmp(token, "direction" ) == 0 ) return "direction ( position );";
- if ( strcmp(token, "distance2d") == 0 ) return "distance2d ( p1, p2 );";
- if ( strcmp(token, "distance" ) == 0 ) return "distance ( p1, p2 );";
- if ( strcmp(token, "space" ) == 0 ) return "space ( center, rmin, rmax, dist );";
- if ( strcmp(token, "flatground") == 0 ) return "flatground ( center, rmax );";
- if ( strcmp(token, "wait" ) == 0 ) return "wait ( time );";
- if ( strcmp(token, "move" ) == 0 ) return "move ( distance );";
- if ( strcmp(token, "turn" ) == 0 ) return "turn ( angle );";
- if ( strcmp(token, "goto" ) == 0 ) return "goto ( position, altitude );";
- if ( strcmp(token, "find" ) == 0 ) return "find ( cat );";
- if ( strcmp(token, "grab" ) == 0 ) return "grab ( order );";
- if ( strcmp(token, "drop" ) == 0 ) return "drop ( order );";
- if ( strcmp(token, "sniff" ) == 0 ) return "sniff ( );";
- if ( strcmp(token, "receive" ) == 0 ) return "receive ( name, power );";
- if ( strcmp(token, "send" ) == 0 ) return "send ( name, value, power );";
- if ( strcmp(token, "deleteinfo") == 0 ) return "deleteinfo ( name, power );";
- if ( strcmp(token, "testinfo" ) == 0 ) return "testinfo ( name, power );";
- if ( strcmp(token, "thump" ) == 0 ) return "thump ( );";
- if ( strcmp(token, "recycle" ) == 0 ) return "recycle ( );";
- if ( strcmp(token, "shield" ) == 0 ) return "shield ( oper, radius );";
- if ( strcmp(token, "fire" ) == 0 ) return "fire ( time );";
- if ( strcmp(token, "antfire" ) == 0 ) return "antfire ( );";
- if ( strcmp(token, "aim" ) == 0 ) return "aim ( angle );";
- if ( strcmp(token, "motor" ) == 0 ) return "motor ( left, right );";
- if ( strcmp(token, "jet" ) == 0 ) return "jet ( power );";
- if ( strcmp(token, "topo" ) == 0 ) return "topo ( position );";
- if ( strcmp(token, "message" ) == 0 ) return "message ( string, type );";
- if ( strcmp(token, "abstime" ) == 0 ) return "abstime ( );";
- if ( strcmp(token, "ismovie" ) == 0 ) return "ismovie ( );";
- if ( strcmp(token, "errmode" ) == 0 ) return "errmode ( mdoe );";
- if ( strcmp(token, "ipf" ) == 0 ) return "ipf ( number );";
- if ( strcmp(token, "strlen" ) == 0 ) return "strlen ( string );";
- if ( strcmp(token, "strleft" ) == 0 ) return "strleft ( string, len );";
- if ( strcmp(token, "strright" ) == 0 ) return "strright ( string, len );";
- if ( strcmp(token, "strmid" ) == 0 ) return "strmid ( string, pos, len );";
- if ( strcmp(token, "strval" ) == 0 ) return "strval ( string );";
- if ( strcmp(token, "strfind" ) == 0 ) return "strfind ( string, substring );";
- if ( strcmp(token, "strlower" ) == 0 ) return "strlower ( string );";
- if ( strcmp(token, "strupper" ) == 0 ) return "strupper ( string );";
- if ( strcmp(token, "open" ) == 0 ) return "open ( filename, mode );";
- if ( strcmp(token, "close" ) == 0 ) return "close ( );";
- if ( strcmp(token, "writeln" ) == 0 ) return "writeln ( string );";
- if ( strcmp(token, "readln" ) == 0 ) return "readln ( );";
- if ( strcmp(token, "eof" ) == 0 ) return "eof ( );";
- if ( strcmp(token, "deletefile") == 0 ) return "deletefile ( filename );";
- if ( strcmp(token, "openfile" ) == 0 ) return "openfile ( filename, mode );";
- if ( strcmp(token, "pendown" ) == 0 ) return "pendown ( color, width );";
- if ( strcmp(token, "penup" ) == 0 ) return "penup ( );";
- if ( strcmp(token, "pencolor" ) == 0 ) return "pencolor ( color );";
- if ( strcmp(token, "penwidth" ) == 0 ) return "penwidth ( width );";
- return "";
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/language.h"
+#include "common/global.h"
+#include "common/event.h"
+#include "object/object.h"
+#include "script/cbottoken.h"
+
+
+
+
+// Seeking the name of an object.
+
+char* RetObjectName(ObjectType type)
+{
+ if ( type == OBJECT_PORTICO ) return "Portico";
+ if ( type == OBJECT_BASE ) return "SpaceShip";
+ if ( type == OBJECT_DERRICK ) return "Derrick";
+ if ( type == OBJECT_FACTORY ) return "BotFactory";
+ if ( type == OBJECT_STATION ) return "PowerStation";
+ if ( type == OBJECT_CONVERT ) return "Converter";
+ if ( type == OBJECT_REPAIR ) return "RepairCenter";
+ if ( type == OBJECT_DESTROYER ) return "Destroyer";
+ if ( type == OBJECT_TOWER ) return "DefenseTower";
+ if ( type == OBJECT_NEST ) return "AlienNest";
+ if ( type == OBJECT_RESEARCH ) return "ResearchCenter";
+ if ( type == OBJECT_RADAR ) return "RadarStation";
+ if ( type == OBJECT_INFO ) return "ExchangePost";
+ if ( type == OBJECT_ENERGY ) return "PowerPlant";
+ if ( type == OBJECT_LABO ) return "AutoLab";
+ if ( type == OBJECT_NUCLEAR ) return "NuclearPlant";
+ if ( type == OBJECT_PARA ) return "PowerCaptor";
+ if ( type == OBJECT_SAFE ) return "Vault";
+ if ( type == OBJECT_HUSTON ) return "Houston";
+ if ( type == OBJECT_TARGET1 ) return "Target1";
+ if ( type == OBJECT_TARGET2 ) return "Target2";
+ if ( type == OBJECT_START ) return "StartArea";
+ if ( type == OBJECT_END ) return "GoalArea";
+ if ( type == OBJECT_TEEN34 ) return "Stone";
+ if ( type == OBJECT_STONE ) return "TitaniumOre";
+ if ( type == OBJECT_URANIUM ) return "UraniumOre";
+ if ( type == OBJECT_METAL ) return "Titanium";
+ if ( type == OBJECT_POWER ) return "PowerCell";
+ if ( type == OBJECT_ATOMIC ) return "NuclearCell";
+ if ( type == OBJECT_BULLET ) return "OrgaMatter";
+ if ( type == OBJECT_BBOX ) return "BlackBox";
+ if ( type == OBJECT_KEYa ) return "KeyA";
+ if ( type == OBJECT_KEYb ) return "KeyB";
+ if ( type == OBJECT_KEYc ) return "KeyC";
+ if ( type == OBJECT_KEYd ) return "KeyD";
+ if ( type == OBJECT_TNT ) return "TNT";
+ if ( type == OBJECT_SCRAP1 ) return "Scrap";
+ if ( type == OBJECT_BOMB ) return "Mine";
+ if ( type == OBJECT_BARRIER1 ) return "Barrier";
+ if ( type == OBJECT_WAYPOINT ) return "WayPoint";
+ if ( type == OBJECT_FLAGb ) return "BlueFlag";
+ if ( type == OBJECT_FLAGr ) return "RedFlag";
+ if ( type == OBJECT_FLAGg ) return "GreenFlag";
+ if ( type == OBJECT_FLAGy ) return "YellowFlag";
+ if ( type == OBJECT_FLAGv ) return "VioletFlag";
+ if ( type == OBJECT_MARKPOWER ) return "PowerSpot";
+ if ( type == OBJECT_MARKSTONE ) return "TitaniumSpot";
+ if ( type == OBJECT_MARKURANIUM ) return "UraniumSpot";
+ if ( type == OBJECT_MARKKEYa ) return "KeyASpot";
+ if ( type == OBJECT_MARKKEYb ) return "KeyBSpot";
+ if ( type == OBJECT_MARKKEYc ) return "KeyCSpot";
+ if ( type == OBJECT_MARKKEYd ) return "KeyDSpot";
+ if ( type == OBJECT_MOBILEwt ) return "PracticeBot";
+ if ( type == OBJECT_MOBILEwa ) return "WheeledGrabber";
+ if ( type == OBJECT_MOBILEta ) return "TrackedGrabber";
+ if ( type == OBJECT_MOBILEfa ) return "WingedGrabber";
+ if ( type == OBJECT_MOBILEia ) return "LeggedGrabber";
+ if ( type == OBJECT_MOBILEwc ) return "WheeledShooter";
+ if ( type == OBJECT_MOBILEtc ) return "TrackedShooter";
+ if ( type == OBJECT_MOBILEfc ) return "WingedShooter";
+ if ( type == OBJECT_MOBILEic ) return "LeggedShooter";
+ if ( type == OBJECT_MOBILEwi ) return "WheeledOrgaShooter";
+ if ( type == OBJECT_MOBILEti ) return "TrackedOrgaShooter";
+ if ( type == OBJECT_MOBILEfi ) return "WingedOrgaShooter";
+ if ( type == OBJECT_MOBILEii ) return "LeggedOrgaShooter";
+ if ( type == OBJECT_MOBILEws ) return "WheeledSniffer";
+ if ( type == OBJECT_MOBILEts ) return "TrackedSniffer";
+ if ( type == OBJECT_MOBILEfs ) return "WingedSniffer";
+ if ( type == OBJECT_MOBILEis ) return "LeggedSniffer";
+ if ( type == OBJECT_MOBILErt ) return "Thumper";
+ if ( type == OBJECT_MOBILErc ) return "PhazerShooter";
+ if ( type == OBJECT_MOBILErr ) return "Recycler";
+ if ( type == OBJECT_MOBILErs ) return "Shielder";
+ if ( type == OBJECT_MOBILEsa ) return "Subber";
+ if ( type == OBJECT_MOBILEtg ) return "TargetBot";
+ if ( type == OBJECT_MOBILEdr ) return "Scribbler";
+ if ( type == OBJECT_HUMAN ) return "Me";
+ if ( type == OBJECT_TECH ) return "Tech";
+ if ( type == OBJECT_MOTHER ) return "AlienQueen";
+ if ( type == OBJECT_EGG ) return "AlienEgg";
+ if ( type == OBJECT_ANT ) return "AlienAnt";
+ if ( type == OBJECT_SPIDER ) return "AlienSpider";
+ if ( type == OBJECT_BEE ) return "AlienWasp";
+ if ( type == OBJECT_WORM ) return "AlienWorm";
+ if ( type == OBJECT_RUINmobilew1) return "Wreck";
+ return "";
+}
+
+// Seeking the name of a secondary object.
+// (because Otto thinks that Germans do not like nuclear power)
+
+char* RetObjectAlias(ObjectType type)
+{
+ if ( type == OBJECT_NUCLEAR ) return "FuelCellPlant";
+ if ( type == OBJECT_URANIUM ) return "PlatinumOre";
+ if ( type == OBJECT_ATOMIC ) return "FuelCell";
+ if ( type == OBJECT_MARKURANIUM ) return "PlatinumSpot";
+ if ( type == OBJECT_ENERGY ) return "Disintegrator"; // for K-CeeBot
+ return "";
+}
+
+
+// Returns the help file to use for the object.
+
+char* RetHelpFilename(ObjectType type)
+{
+ if ( type == OBJECT_BASE ) return "help\\object\\base.txt";
+ if ( type == OBJECT_DERRICK ) return "help\\object\\derrick.txt";
+ if ( type == OBJECT_FACTORY ) return "help\\object\\factory.txt";
+ if ( type == OBJECT_STATION ) return "help\\object\\station.txt";
+ if ( type == OBJECT_CONVERT ) return "help\\object\\convert.txt";
+ if ( type == OBJECT_REPAIR ) return "help\\object\\repair.txt";
+ if ( type == OBJECT_DESTROYER ) return "help\\object\\destroy.txt";
+ if ( type == OBJECT_TOWER ) return "help\\object\\tower.txt";
+ if ( type == OBJECT_NEST ) return "help\\object\\nest.txt";
+ if ( type == OBJECT_RESEARCH ) return "help\\object\\research.txt";
+ if ( type == OBJECT_RADAR ) return "help\\object\\radar.txt";
+ if ( type == OBJECT_INFO ) return "help\\object\\exchange.txt";
+ if ( type == OBJECT_ENERGY ) return "help\\object\\energy.txt";
+ if ( type == OBJECT_LABO ) return "help\\object\\labo.txt";
+ if ( type == OBJECT_NUCLEAR ) return "help\\object\\nuclear.txt";
+ if ( type == OBJECT_PARA ) return "help\\object\\captor.txt";
+ if ( type == OBJECT_SAFE ) return "help\\object\\safe.txt";
+ if ( type == OBJECT_HUSTON ) return "help\\object\\huston.txt";
+ if ( type == OBJECT_START ) return "help\\object\\start.txt";
+ if ( type == OBJECT_END ) return "help\\object\\goal.txt";
+ if ( type == OBJECT_STONE ) return "help\\object\\titanore.txt";
+ if ( type == OBJECT_URANIUM ) return "help\\object\\uranore.txt";
+ if ( type == OBJECT_METAL ) return "help\\object\\titan.txt";
+ if ( type == OBJECT_POWER ) return "help\\object\\power.txt";
+ if ( type == OBJECT_ATOMIC ) return "help\\object\\atomic.txt";
+ if ( type == OBJECT_BULLET ) return "help\\object\\bullet.txt";
+ if ( type == OBJECT_BBOX ) return "help\\object\\bbox.txt";
+ if ( type == OBJECT_KEYa ) return "help\\object\\key.txt";
+ if ( type == OBJECT_KEYb ) return "help\\object\\key.txt";
+ if ( type == OBJECT_KEYc ) return "help\\object\\key.txt";
+ if ( type == OBJECT_KEYd ) return "help\\object\\key.txt";
+ if ( type == OBJECT_TNT ) return "help\\object\\tnt.txt";
+ if ( type == OBJECT_SCRAP1 ) return "help\\object\\scrap.txt";
+ if ( type == OBJECT_BOMB ) return "help\\object\\mine.txt";
+ if ( type == OBJECT_BARRIER1 ) return "help\\object\\barrier.txt";
+ if ( type == OBJECT_WAYPOINT ) return "help\\object\\waypoint.txt";
+ if ( type == OBJECT_FLAGb ) return "help\\object\\flag.txt";
+ if ( type == OBJECT_FLAGr ) return "help\\object\\flag.txt";
+ if ( type == OBJECT_FLAGg ) return "help\\object\\flag.txt";
+ if ( type == OBJECT_FLAGy ) return "help\\object\\flag.txt";
+ if ( type == OBJECT_FLAGv ) return "help\\object\\flag.txt";
+ if ( type == OBJECT_MARKPOWER ) return "help\\object\\enerspot.txt";
+ if ( type == OBJECT_MARKSTONE ) return "help\\object\\stonspot.txt";
+ if ( type == OBJECT_MARKURANIUM ) return "help\\object\\uranspot.txt";
+ if ( type == OBJECT_MOBILEwa ) return "help\\object\\botgr.txt";
+ if ( type == OBJECT_MOBILEta ) return "help\\object\\botgc.txt";
+ if ( type == OBJECT_MOBILEfa ) return "help\\object\\botgj.txt";
+ if ( type == OBJECT_MOBILEia ) return "help\\object\\botgs.txt";
+ if ( type == OBJECT_MOBILEws ) return "help\\object\\botsr.txt";
+ if ( type == OBJECT_MOBILEts ) return "help\\object\\botsc.txt";
+ if ( type == OBJECT_MOBILEfs ) return "help\\object\\botsj.txt";
+ if ( type == OBJECT_MOBILEis ) return "help\\object\\botss.txt";
+ if ( type == OBJECT_MOBILEwi ) return "help\\object\\botor.txt";
+ if ( type == OBJECT_MOBILEti ) return "help\\object\\botoc.txt";
+ if ( type == OBJECT_MOBILEfi ) return "help\\object\\botoj.txt";
+ if ( type == OBJECT_MOBILEii ) return "help\\object\\botos.txt";
+ if ( type == OBJECT_MOBILEwc ) return "help\\object\\botfr.txt";
+ if ( type == OBJECT_MOBILEtc ) return "help\\object\\botfc.txt";
+ if ( type == OBJECT_MOBILEfc ) return "help\\object\\botfj.txt";
+ if ( type == OBJECT_MOBILEic ) return "help\\object\\botfs.txt";
+ if ( type == OBJECT_MOBILErt ) return "help\\object\\bottump.txt";
+ if ( type == OBJECT_MOBILErc ) return "help\\object\\botphaz.txt";
+ if ( type == OBJECT_MOBILErr ) return "help\\object\\botrecy.txt";
+ if ( type == OBJECT_MOBILErs ) return "help\\object\\botshld.txt";
+ if ( type == OBJECT_MOBILEsa ) return "help\\object\\botsub.txt";
+ if ( type == OBJECT_MOBILEwt ) return "help\\object\\bottr.txt";
+ if ( type == OBJECT_MOBILEtg ) return "help\\object\\bottarg.txt";
+ if ( type == OBJECT_MOBILEdr ) return "help\\object\\botdraw.txt";
+ if ( type == OBJECT_APOLLO2 ) return "help\\object\\lrv.txt";
+ if ( type == OBJECT_HUMAN ) return "help\\object\\human.txt";
+ if ( type == OBJECT_MOTHER ) return "help\\object\\mother.txt";
+ if ( type == OBJECT_EGG ) return "help\\object\\egg.txt";
+ if ( type == OBJECT_ANT ) return "help\\object\\ant.txt";
+ if ( type == OBJECT_SPIDER ) return "help\\object\\spider.txt";
+ if ( type == OBJECT_BEE ) return "help\\object\\wasp.txt";
+ if ( type == OBJECT_WORM ) return "help\\object\\worm.txt";
+ if ( type == OBJECT_RUINmobilew1) return "help\\object\\wreck.txt";
+ return "";
+}
+
+
+// Returns the help file to use for instruction.
+
+char* RetHelpFilename(const char *token)
+{
+ if ( strcmp(token, "if" ) == 0 ) return "help\\cbot\\if.txt";
+ if ( strcmp(token, "else" ) == 0 ) return "help\\cbot\\if.txt";
+ if ( strcmp(token, "repeat" ) == 0 ) return "help\\cbot\\repeat.txt";
+ if ( strcmp(token, "for" ) == 0 ) return "help\\cbot\\for.txt";
+ if ( strcmp(token, "while" ) == 0 ) return "help\\cbot\\while.txt";
+ if ( strcmp(token, "do" ) == 0 ) return "help\\cbot\\do.txt";
+ if ( strcmp(token, "break" ) == 0 ) return "help\\cbot\\break.txt";
+ if ( strcmp(token, "continue" ) == 0 ) return "help\\cbot\\continue.txt";
+ if ( strcmp(token, "return" ) == 0 ) return "help\\cbot\\return.txt";
+ if ( strcmp(token, "sizeof" ) == 0 ) return "help\\cbot\\sizeof.txt";
+ if ( strcmp(token, "int" ) == 0 ) return "help\\cbot\\int.txt";
+ if ( strcmp(token, "float" ) == 0 ) return "help\\cbot\\float.txt";
+ if ( strcmp(token, "bool" ) == 0 ) return "help\\cbot\\bool.txt";
+ if ( strcmp(token, "string" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "point" ) == 0 ) return "help\\cbot\\point.txt";
+ if ( strcmp(token, "object" ) == 0 ) return "help\\cbot\\object.txt";
+ if ( strcmp(token, "file" ) == 0 ) return "help\\cbot\\file.txt";
+ if ( strcmp(token, "void" ) == 0 ) return "help\\cbot\\void.txt";
+ if ( strcmp(token, "null" ) == 0 ) return "help\\cbot\\null.txt";
+ if ( strcmp(token, "nan" ) == 0 ) return "help\\cbot\\nan.txt";
+ if ( strcmp(token, "true" ) == 0 ) return "help\\cbot\\true.txt";
+ if ( strcmp(token, "false" ) == 0 ) return "help\\cbot\\false.txt";
+ if ( strcmp(token, "sin" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "cos" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "tan" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "asin" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "acos" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "atan" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "sqrt" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "pow" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "rand" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "abs" ) == 0 ) return "help\\cbot\\expr.txt";
+ if ( strcmp(token, "retobject" ) == 0 ) return "help\\cbot\\retobj.txt";
+ if ( strcmp(token, "search" ) == 0 ) return "help\\cbot\\search.txt";
+ if ( strcmp(token, "radar" ) == 0 ) return "help\\cbot\\radar.txt";
+ if ( strcmp(token, "direction" ) == 0 ) return "help\\cbot\\direct.txt";
+ if ( strcmp(token, "distance" ) == 0 ) return "help\\cbot\\dist.txt";
+ if ( strcmp(token, "distance2d" ) == 0 ) return "help\\cbot\\dist2d.txt";
+ if ( strcmp(token, "space" ) == 0 ) return "help\\cbot\\space.txt";
+ if ( strcmp(token, "flatground" ) == 0 ) return "help\\cbot\\flatgrnd.txt";
+ if ( strcmp(token, "wait" ) == 0 ) return "help\\cbot\\wait.txt";
+ if ( strcmp(token, "move" ) == 0 ) return "help\\cbot\\move.txt";
+ if ( strcmp(token, "turn" ) == 0 ) return "help\\cbot\\turn.txt";
+ if ( strcmp(token, "goto" ) == 0 ) return "help\\cbot\\goto.txt";
+ if ( strcmp(token, "find" ) == 0 ) return "help\\cbot\\find.txt";
+ if ( strcmp(token, "grab" ) == 0 ) return "help\\cbot\\grab.txt";
+ if ( strcmp(token, "drop" ) == 0 ) return "help\\cbot\\drop.txt";
+ if ( strcmp(token, "sniff" ) == 0 ) return "help\\cbot\\sniff.txt";
+ if ( strcmp(token, "receive" ) == 0 ) return "help\\cbot\\receive.txt";
+ if ( strcmp(token, "send" ) == 0 ) return "help\\cbot\\send.txt";
+ if ( strcmp(token, "deleteinfo" ) == 0 ) return "help\\cbot\\delinfo.txt";
+ if ( strcmp(token, "testinfo" ) == 0 ) return "help\\cbot\\testinfo.txt";
+ if ( strcmp(token, "thump" ) == 0 ) return "help\\cbot\\thump.txt";
+ if ( strcmp(token, "recycle" ) == 0 ) return "help\\cbot\\recycle.txt";
+ if ( strcmp(token, "shield" ) == 0 ) return "help\\cbot\\shield.txt";
+ if ( strcmp(token, "fire" ) == 0 ) return "help\\cbot\\fire.txt";
+ if ( strcmp(token, "antfire" ) == 0 ) return "help\\cbot\\antfire.txt";
+ if ( strcmp(token, "aim" ) == 0 ) return "help\\cbot\\aim.txt";
+ if ( strcmp(token, "motor" ) == 0 ) return "help\\cbot\\motor.txt";
+ if ( strcmp(token, "jet" ) == 0 ) return "help\\cbot\\jet.txt";
+ if ( strcmp(token, "topo" ) == 0 ) return "help\\cbot\\topo.txt";
+ if ( strcmp(token, "message" ) == 0 ) return "help\\cbot\\message.txt";
+ if ( strcmp(token, "abstime" ) == 0 ) return "help\\cbot\\abstime.txt";
+ if ( strcmp(token, "BlackArrow" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "RedArrow" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "White" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Black" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Gray" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "LightGray" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Red" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Pink" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Purple" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Orange" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Yellow" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Beige" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Brown" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Skin" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Green" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "LightGreen" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "Blue" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "LightBlue" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "InFront" ) == 0 ) return "help\\cbot\\grab.txt";
+ if ( strcmp(token, "Behind" ) == 0 ) return "help\\cbot\\grab.txt";
+ if ( strcmp(token, "EnergyCell" ) == 0 ) return "help\\cbot\\grab.txt";
+ if ( strcmp(token, "DisplayError" ) == 0 ) return "help\\cbot\\message.txt";
+ if ( strcmp(token, "DisplayWarning") == 0 ) return "help\\cbot\\message.txt";
+ if ( strcmp(token, "DisplayInfo" ) == 0 ) return "help\\cbot\\message.txt";
+ if ( strcmp(token, "DisplayMessage") == 0 ) return "help\\cbot\\message.txt";
+ if ( strcmp(token, "strlen" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "strleft" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "strright" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "strmid" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "strval" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "strfind" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "strlower" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "strupper" ) == 0 ) return "help\\cbot\\string.txt";
+ if ( strcmp(token, "open" ) == 0 ) return "help\\cbot\\open.txt";
+ if ( strcmp(token, "close" ) == 0 ) return "help\\cbot\\close.txt";
+ if ( strcmp(token, "writeln" ) == 0 ) return "help\\cbot\\writeln.txt";
+ if ( strcmp(token, "readln " ) == 0 ) return "help\\cbot\\readln.txt";
+ if ( strcmp(token, "eof" ) == 0 ) return "help\\cbot\\eof.txt";
+ if ( strcmp(token, "deletefile" ) == 0 ) return "help\\cbot\\deletef.txt";
+ if ( strcmp(token, "openfile" ) == 0 ) return "help\\cbot\\openfile.txt";
+ if ( strcmp(token, "pendown" ) == 0 ) return "help\\cbot\\pendown.txt";
+ if ( strcmp(token, "penup" ) == 0 ) return "help\\cbot\\penup.txt";
+ if ( strcmp(token, "pencolor" ) == 0 ) return "help\\cbot\\pencolor.txt";
+ if ( strcmp(token, "penwidth" ) == 0 ) return "help\\cbot\\penwidth.txt";
+ if ( strcmp(token, "extern" ) == 0 ) return "help\\cbot\\extern.txt";
+ if ( strcmp(token, "class" ) == 0 ) return "help\\cbot\\class.txt";
+ if ( strcmp(token, "static" ) == 0 ) return "help\\cbot\\static.txt";
+ if ( strcmp(token, "public" ) == 0 ) return "help\\cbot\\public.txt";
+ if ( strcmp(token, "private" ) == 0 ) return "help\\cbot\\private.txt";
+ if ( strcmp(token, "synchronized" ) == 0 ) return "help\\cbot\\synchro.txt";
+ if ( strcmp(token, "new" ) == 0 ) return "help\\cbot\\new.txt";
+ if ( strcmp(token, "this" ) == 0 ) return "help\\cbot\\this.txt";
+ return "";
+}
+
+
+// Test if a keyword is a type of variable.
+
+bool IsType(const char *token)
+{
+ if ( strcmp(token, "void" ) == 0 ) return true;
+ if ( strcmp(token, "int" ) == 0 ) return true;
+ if ( strcmp(token, "float" ) == 0 ) return true;
+ if ( strcmp(token, "bool" ) == 0 ) return true;
+ if ( strcmp(token, "string" ) == 0 ) return true;
+ if ( strcmp(token, "point" ) == 0 ) return true;
+ if ( strcmp(token, "object" ) == 0 ) return true;
+ if ( strcmp(token, "file" ) == 0 ) return true;
+ if ( strcmp(token, "this" ) == 0 ) return true;
+ return false;
+}
+
+// Test if a keyword is a function.
+
+bool IsFunction(const char *token)
+{
+ if ( strcmp(token, "sin" ) == 0 ) return true;
+ if ( strcmp(token, "cos" ) == 0 ) return true;
+ if ( strcmp(token, "tan" ) == 0 ) return true;
+ if ( strcmp(token, "asin" ) == 0 ) return true;
+ if ( strcmp(token, "acos" ) == 0 ) return true;
+ if ( strcmp(token, "atan" ) == 0 ) return true;
+ if ( strcmp(token, "sqrt" ) == 0 ) return true;
+ if ( strcmp(token, "pow" ) == 0 ) return true;
+ if ( strcmp(token, "rand" ) == 0 ) return true;
+ if ( strcmp(token, "abs" ) == 0 ) return true;
+ if ( strcmp(token, "retobject" ) == 0 ) return true;
+ if ( strcmp(token, "search" ) == 0 ) return true;
+ if ( strcmp(token, "radar" ) == 0 ) return true;
+ if ( strcmp(token, "detect" ) == 0 ) return true;
+ if ( strcmp(token, "direction" ) == 0 ) return true;
+ if ( strcmp(token, "distance" ) == 0 ) return true;
+ if ( strcmp(token, "distance2d" ) == 0 ) return true;
+ if ( strcmp(token, "space" ) == 0 ) return true;
+ if ( strcmp(token, "flatground" ) == 0 ) return true;
+ if ( strcmp(token, "wait" ) == 0 ) return true;
+ if ( strcmp(token, "move" ) == 0 ) return true;
+ if ( strcmp(token, "turn" ) == 0 ) return true;
+ if ( strcmp(token, "goto" ) == 0 ) return true;
+ if ( strcmp(token, "find" ) == 0 ) return true;
+ if ( strcmp(token, "grab" ) == 0 ) return true;
+ if ( strcmp(token, "drop" ) == 0 ) return true;
+ if ( strcmp(token, "sniff" ) == 0 ) return true;
+ if ( strcmp(token, "receive" ) == 0 ) return true;
+ if ( strcmp(token, "send" ) == 0 ) return true;
+ if ( strcmp(token, "deleteinfo" ) == 0 ) return true;
+ if ( strcmp(token, "testinfo" ) == 0 ) return true;
+ if ( strcmp(token, "thump" ) == 0 ) return true;
+ if ( strcmp(token, "recycle" ) == 0 ) return true;
+ if ( strcmp(token, "shield" ) == 0 ) return true;
+ if ( strcmp(token, "fire" ) == 0 ) return true;
+ if ( strcmp(token, "antfire" ) == 0 ) return true;
+ if ( strcmp(token, "aim" ) == 0 ) return true;
+ if ( strcmp(token, "motor" ) == 0 ) return true;
+ if ( strcmp(token, "jet" ) == 0 ) return true;
+ if ( strcmp(token, "topo" ) == 0 ) return true;
+ if ( strcmp(token, "message" ) == 0 ) return true;
+ if ( strcmp(token, "abstime" ) == 0 ) return true;
+ if ( strcmp(token, "ismovie" ) == 0 ) return true;
+ if ( strcmp(token, "errmode" ) == 0 ) return true;
+ if ( strcmp(token, "ipf" ) == 0 ) return true;
+ if ( strcmp(token, "strlen" ) == 0 ) return true;
+ if ( strcmp(token, "strleft" ) == 0 ) return true;
+ if ( strcmp(token, "strright" ) == 0 ) return true;
+ if ( strcmp(token, "strmid" ) == 0 ) return true;
+ if ( strcmp(token, "strval" ) == 0 ) return true;
+ if ( strcmp(token, "strfind" ) == 0 ) return true;
+ if ( strcmp(token, "strlower" ) == 0 ) return true;
+ if ( strcmp(token, "strupper" ) == 0 ) return true;
+ if ( strcmp(token, "open" ) == 0 ) return true;
+ if ( strcmp(token, "close" ) == 0 ) return true;
+ if ( strcmp(token, "writeln" ) == 0 ) return true;
+ if ( strcmp(token, "readln" ) == 0 ) return true;
+ if ( strcmp(token, "eof" ) == 0 ) return true;
+ if ( strcmp(token, "deletefile" ) == 0 ) return true;
+ if ( strcmp(token, "openfile" ) == 0 ) return true;
+ if ( strcmp(token, "pendown" ) == 0 ) return true;
+ if ( strcmp(token, "penup" ) == 0 ) return true;
+ if ( strcmp(token, "pencolor" ) == 0 ) return true;
+ if ( strcmp(token, "penwidth" ) == 0 ) return true;
+ if ( strcmp(token, "sizeof" ) == 0 ) return true;
+ return false;
+}
+
+
+// Returns using a compact instruction.
+
+char* RetHelpText(const char *token)
+{
+ if ( strcmp(token, "if" ) == 0 ) return "if ( condition ) { bloc }";
+ if ( strcmp(token, "else" ) == 0 ) return "else { bloc }";
+ if ( strcmp(token, "repeat" ) == 0 ) return "repeat ( number )";
+ if ( strcmp(token, "for" ) == 0 ) return "for ( before ; condition ; end )";
+ if ( strcmp(token, "while" ) == 0 ) return "while ( condition ) { bloc }";
+ if ( strcmp(token, "do" ) == 0 ) return "do { bloc } while ( condition );";
+ if ( strcmp(token, "break" ) == 0 ) return "break;";
+ if ( strcmp(token, "continue" ) == 0 ) return "continue;";
+ if ( strcmp(token, "return" ) == 0 ) return "return;";
+ if ( strcmp(token, "sizeof" ) == 0 ) return "sizeof( array );";
+ if ( strcmp(token, "int" ) == 0 ) return "int";
+ if ( strcmp(token, "sin" ) == 0 ) return "sin ( angle );";
+ if ( strcmp(token, "cos" ) == 0 ) return "cos ( angle );";
+ if ( strcmp(token, "tan" ) == 0 ) return "tan ( angle );";
+ if ( strcmp(token, "asin" ) == 0 ) return "asin ( value );";
+ if ( strcmp(token, "acos" ) == 0 ) return "acos ( value );";
+ if ( strcmp(token, "atan" ) == 0 ) return "atan ( value );";
+ if ( strcmp(token, "sqrt" ) == 0 ) return "sqrt ( value );";
+ if ( strcmp(token, "pow" ) == 0 ) return "pow ( x, y );";
+ if ( strcmp(token, "rand" ) == 0 ) return "rand ( );";
+ if ( strcmp(token, "abs" ) == 0 ) return "abs ( value );";
+ if ( strcmp(token, "retobject" ) == 0 ) return "retobjet ( );";
+ if ( strcmp(token, "search" ) == 0 ) return "search ( );";
+ if ( strcmp(token, "radar" ) == 0 ) return "radar ( cat, angle, focus, min, max, sens );";
+ if ( strcmp(token, "detect" ) == 0 ) return "detect ( cat );";
+ if ( strcmp(token, "direction" ) == 0 ) return "direction ( position );";
+ if ( strcmp(token, "distance2d") == 0 ) return "distance2d ( p1, p2 );";
+ if ( strcmp(token, "distance" ) == 0 ) return "distance ( p1, p2 );";
+ if ( strcmp(token, "space" ) == 0 ) return "space ( center, rmin, rmax, dist );";
+ if ( strcmp(token, "flatground") == 0 ) return "flatground ( center, rmax );";
+ if ( strcmp(token, "wait" ) == 0 ) return "wait ( time );";
+ if ( strcmp(token, "move" ) == 0 ) return "move ( distance );";
+ if ( strcmp(token, "turn" ) == 0 ) return "turn ( angle );";
+ if ( strcmp(token, "goto" ) == 0 ) return "goto ( position, altitude );";
+ if ( strcmp(token, "find" ) == 0 ) return "find ( cat );";
+ if ( strcmp(token, "grab" ) == 0 ) return "grab ( order );";
+ if ( strcmp(token, "drop" ) == 0 ) return "drop ( order );";
+ if ( strcmp(token, "sniff" ) == 0 ) return "sniff ( );";
+ if ( strcmp(token, "receive" ) == 0 ) return "receive ( name, power );";
+ if ( strcmp(token, "send" ) == 0 ) return "send ( name, value, power );";
+ if ( strcmp(token, "deleteinfo") == 0 ) return "deleteinfo ( name, power );";
+ if ( strcmp(token, "testinfo" ) == 0 ) return "testinfo ( name, power );";
+ if ( strcmp(token, "thump" ) == 0 ) return "thump ( );";
+ if ( strcmp(token, "recycle" ) == 0 ) return "recycle ( );";
+ if ( strcmp(token, "shield" ) == 0 ) return "shield ( oper, radius );";
+ if ( strcmp(token, "fire" ) == 0 ) return "fire ( time );";
+ if ( strcmp(token, "antfire" ) == 0 ) return "antfire ( );";
+ if ( strcmp(token, "aim" ) == 0 ) return "aim ( angle );";
+ if ( strcmp(token, "motor" ) == 0 ) return "motor ( left, right );";
+ if ( strcmp(token, "jet" ) == 0 ) return "jet ( power );";
+ if ( strcmp(token, "topo" ) == 0 ) return "topo ( position );";
+ if ( strcmp(token, "message" ) == 0 ) return "message ( string, type );";
+ if ( strcmp(token, "abstime" ) == 0 ) return "abstime ( );";
+ if ( strcmp(token, "ismovie" ) == 0 ) return "ismovie ( );";
+ if ( strcmp(token, "errmode" ) == 0 ) return "errmode ( mdoe );";
+ if ( strcmp(token, "ipf" ) == 0 ) return "ipf ( number );";
+ if ( strcmp(token, "strlen" ) == 0 ) return "strlen ( string );";
+ if ( strcmp(token, "strleft" ) == 0 ) return "strleft ( string, len );";
+ if ( strcmp(token, "strright" ) == 0 ) return "strright ( string, len );";
+ if ( strcmp(token, "strmid" ) == 0 ) return "strmid ( string, pos, len );";
+ if ( strcmp(token, "strval" ) == 0 ) return "strval ( string );";
+ if ( strcmp(token, "strfind" ) == 0 ) return "strfind ( string, substring );";
+ if ( strcmp(token, "strlower" ) == 0 ) return "strlower ( string );";
+ if ( strcmp(token, "strupper" ) == 0 ) return "strupper ( string );";
+ if ( strcmp(token, "open" ) == 0 ) return "open ( filename, mode );";
+ if ( strcmp(token, "close" ) == 0 ) return "close ( );";
+ if ( strcmp(token, "writeln" ) == 0 ) return "writeln ( string );";
+ if ( strcmp(token, "readln" ) == 0 ) return "readln ( );";
+ if ( strcmp(token, "eof" ) == 0 ) return "eof ( );";
+ if ( strcmp(token, "deletefile") == 0 ) return "deletefile ( filename );";
+ if ( strcmp(token, "openfile" ) == 0 ) return "openfile ( filename, mode );";
+ if ( strcmp(token, "pendown" ) == 0 ) return "pendown ( color, width );";
+ if ( strcmp(token, "penup" ) == 0 ) return "penup ( );";
+ if ( strcmp(token, "pencolor" ) == 0 ) return "pencolor ( color );";
+ if ( strcmp(token, "penwidth" ) == 0 ) return "penwidth ( width );";
+ return "";
+}
+
+
diff --git a/src/script/cbottoken.h b/src/script/cbottoken.h
index ff06fa7..c1a6a65 100644
--- a/src/script/cbottoken.h
+++ b/src/script/cbottoken.h
@@ -1,36 +1,36 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// cbottoken.h
-
-#pragma once
-
-
-#include "object/object.h"
-
-
-
-// Procedures.
-
-extern char* RetObjectName(ObjectType type);
-extern char* RetObjectAlias(ObjectType type);
-extern char* RetHelpFilename(ObjectType type);
-extern char* RetHelpFilename(const char *token);
-extern bool IsType(const char *token);
-extern bool IsFunction(const char *token);
-extern char* RetHelpText(const char *token);
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// cbottoken.h
+
+#pragma once
+
+
+#include "object/object.h"
+
+
+
+// Procedures.
+
+extern char* RetObjectName(ObjectType type);
+extern char* RetObjectAlias(ObjectType type);
+extern char* RetHelpFilename(ObjectType type);
+extern char* RetHelpFilename(const char *token);
+extern bool IsType(const char *token);
+extern bool IsFunction(const char *token);
+extern char* RetHelpText(const char *token);
+
+
diff --git a/src/script/cmdtoken.cpp b/src/script/cmdtoken.cpp
index 9559e42..256b580 100644
--- a/src/script/cmdtoken.cpp
+++ b/src/script/cmdtoken.cpp
@@ -1,976 +1,976 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/language.h"
-#include "common/global.h"
-#include "common/event.h"
-#include "old/water.h"
-#include "old/pyro.h"
-#include "old/camera.h"
-#include "object/object.h"
-#include "script/cmdtoken.h"
-
-
-
-
-
-// Skips spaces.
-
-char* SkipSpace(char *line)
-{
- while ( *line == ' ' )
- {
- line ++;
- }
- return line;
-}
-
-// Checks if a line contains a command.
-
-bool Cmd(char *line, char *token)
-{
- char* p;
-
- line = SkipSpace(line);
- p = strstr(line, token);
- return ( p == line ); // command at the beginning?
-}
-
-// Seeking an operator.
-
-char* SearchOp(char *line, char *op)
-{
- char opeq[50];
- char* p;
-
- strcpy(opeq, " ");
- strcat(opeq, op);
- strcat(opeq, "=");
-
- p = strstr(line, opeq);
- if ( p == 0 ) // not found?
- {
- return line+strlen(line); // point zero terminator
- }
- return p+strlen(opeq); // after the point "="
-}
-
-// Seeks the argument.
-
-char* SearchArg(char *line, int rank)
-{
- int i;
- char c;
-
- for ( i=0 ; i<rank ; i++ )
- {
- while ( true )
- {
- c = *line++;
- if ( c == ';' ) break;
- if ( c == '=' ||
- c == 0 ) return line+strlen(line);
- }
- }
-
- line = SkipSpace(line);
- return line;
-}
-
-// Reads an integer, eventually hexadecimal.
-
-int GetInt(char *line, int rank, int def)
-{
- char* p;
- int n = 0;
-
- p = SearchArg(line, rank);
- if ( *p == 0 ) return def;
-
- if ( p[0] == '0' &&
- p[1] == 'x' ) // begins with "0x" (hexadecimal)?
- {
- p += 2;
- while ( true )
- {
- if ( *p >= '0' && *p <= '9' )
- {
- n *= 16;
- n += (*p++)-'0';
- continue;
- }
- if ( *p >= 'a' && *p <= 'f' )
- {
- n *= 16;
- n += (*p++)-'a'+10;
- continue;
- }
- break;
- }
- }
- else // integer?
- {
- sscanf(p, "%d", &n);
- }
- return n;
-}
-
-// Reads a float number.
-
-float GetFloat(char *line, int rank, float def)
-{
- char* p;
- float n = 0.0f;
-
- p = SearchArg(line, rank);
- if ( *p == 0 ) return def;
-
- sscanf(p, "%f", &n);
- return n;
-}
-
-// Reads a string.
-
-void GetString(char *line, int rank, char *buffer)
-{
- char* p;
-
- p = SearchArg(line, rank);
- *buffer = 0;
- if ( *p++ != '"' ) return;
-
- while ( p[0] != 0 )
- {
- if ( p[0] == '"' &&
- p[1] == '"' )
- {
- *buffer++ = *p++;
- p++;
- continue;
- }
- if ( p[0] == '"' ) break;
-
- *buffer++ = *p++;
- }
- *buffer = 0;
-}
-
-// Returns the type of an object.
-
-ObjectType GetTypeObject(char *line, int rank, ObjectType def)
-{
- char* p;
-
- p = SearchArg(line, rank);
- if ( *p == 0 ) return def;
-
- if ( Cmd(p, "All" ) ) return OBJECT_NULL;
- if ( Cmd(p, "Portico" ) ) return OBJECT_PORTICO;
- if ( Cmd(p, "SpaceShip" ) ) return OBJECT_BASE;
- if ( Cmd(p, "PracticeBot" ) ) return OBJECT_MOBILEwt;
- if ( Cmd(p, "WingedGrabber" ) ) return OBJECT_MOBILEfa;
- if ( Cmd(p, "TrackedGrabber" ) ) return OBJECT_MOBILEta;
- if ( Cmd(p, "WheeledGrabber" ) ) return OBJECT_MOBILEwa;
- if ( Cmd(p, "LeggedGrabber" ) ) return OBJECT_MOBILEia;
- if ( Cmd(p, "WingedShooter" ) ) return OBJECT_MOBILEfc;
- if ( Cmd(p, "TrackedShooter" ) ) return OBJECT_MOBILEtc;
- if ( Cmd(p, "WheeledShooter" ) ) return OBJECT_MOBILEwc;
- if ( Cmd(p, "LeggedShooter" ) ) return OBJECT_MOBILEic;
- if ( Cmd(p, "WingedOrgaShooter" ) ) return OBJECT_MOBILEfi;
- if ( Cmd(p, "TrackedOrgaShooter") ) return OBJECT_MOBILEti;
- if ( Cmd(p, "WheeledOrgaShooter") ) return OBJECT_MOBILEwi;
- if ( Cmd(p, "LeggedOrgaShooter" ) ) return OBJECT_MOBILEii;
- if ( Cmd(p, "WingedSniffer" ) ) return OBJECT_MOBILEfs;
- if ( Cmd(p, "TrackedSniffer" ) ) return OBJECT_MOBILEts;
- if ( Cmd(p, "WheeledSniffer" ) ) return OBJECT_MOBILEws;
- if ( Cmd(p, "LeggedSniffer" ) ) return OBJECT_MOBILEis;
- if ( Cmd(p, "Thumper" ) ) return OBJECT_MOBILErt;
- if ( Cmd(p, "PhazerShooter" ) ) return OBJECT_MOBILErc;
- if ( Cmd(p, "Recycler" ) ) return OBJECT_MOBILErr;
- if ( Cmd(p, "Shielder" ) ) return OBJECT_MOBILErs;
- if ( Cmd(p, "Subber" ) ) return OBJECT_MOBILEsa;
- if ( Cmd(p, "TargetBot" ) ) return OBJECT_MOBILEtg;
- if ( Cmd(p, "Scribbler" ) ) return OBJECT_MOBILEdr;
- if ( Cmd(p, "PowerSpot" ) ) return OBJECT_MARKPOWER;
- if ( Cmd(p, "TitaniumSpot" ) ) return OBJECT_MARKSTONE;
- if ( Cmd(p, "UraniumSpot" ) ) return OBJECT_MARKURANIUM;
- if ( Cmd(p, "PlatinumSpot" ) ) return OBJECT_MARKURANIUM;
- if ( Cmd(p, "KeyASpot" ) ) return OBJECT_MARKKEYa;
- if ( Cmd(p, "KeyBSpot" ) ) return OBJECT_MARKKEYb;
- if ( Cmd(p, "KeyCSpot" ) ) return OBJECT_MARKKEYc;
- if ( Cmd(p, "KeyDSpot" ) ) return OBJECT_MARKKEYd;
- if ( Cmd(p, "WayPoint" ) ) return OBJECT_WAYPOINT;
- if ( Cmd(p, "BlueFlag" ) ) return OBJECT_FLAGb;
- if ( Cmd(p, "RedFlag" ) ) return OBJECT_FLAGr;
- if ( Cmd(p, "GreenFlag" ) ) return OBJECT_FLAGg;
- if ( Cmd(p, "YellowFlag" ) ) return OBJECT_FLAGy;
- if ( Cmd(p, "VioletFlag" ) ) return OBJECT_FLAGv;
- if ( Cmd(p, "PowerCell" ) ) return OBJECT_POWER;
- if ( Cmd(p, "FuelCellPlant" ) ) return OBJECT_NUCLEAR;
- if ( Cmd(p, "FuelCell" ) ) return OBJECT_ATOMIC;
- if ( Cmd(p, "NuclearCell" ) ) return OBJECT_ATOMIC;
- if ( Cmd(p, "TitaniumOre" ) ) return OBJECT_STONE;
- if ( Cmd(p, "UraniumOre" ) ) return OBJECT_URANIUM;
- if ( Cmd(p, "PlatinumOre" ) ) return OBJECT_URANIUM;
- if ( Cmd(p, "Titanium" ) ) return OBJECT_METAL;
- if ( Cmd(p, "OrgaMatter" ) ) return OBJECT_BULLET;
- if ( Cmd(p, "BlackBox" ) ) return OBJECT_BBOX;
- if ( Cmd(p, "KeyA" ) ) return OBJECT_KEYa;
- if ( Cmd(p, "KeyB" ) ) return OBJECT_KEYb;
- if ( Cmd(p, "KeyC" ) ) return OBJECT_KEYc;
- if ( Cmd(p, "KeyD" ) ) return OBJECT_KEYd;
- if ( Cmd(p, "TNT" ) ) return OBJECT_TNT;
- if ( Cmd(p, "Scrap1" ) ) return OBJECT_SCRAP1;
- if ( Cmd(p, "Scrap2" ) ) return OBJECT_SCRAP2;
- if ( Cmd(p, "Scrap3" ) ) return OBJECT_SCRAP3;
- if ( Cmd(p, "Scrap4" ) ) return OBJECT_SCRAP4;
- if ( Cmd(p, "Scrap5" ) ) return OBJECT_SCRAP5;
- if ( Cmd(p, "Mine" ) ) return OBJECT_BOMB;
- if ( Cmd(p, "Firework" ) ) return OBJECT_WINFIRE;
- if ( Cmd(p, "Bag" ) ) return OBJECT_BAG;
- if ( Cmd(p, "Greenery10" ) ) return OBJECT_PLANT10;
- if ( Cmd(p, "Greenery11" ) ) return OBJECT_PLANT11;
- if ( Cmd(p, "Greenery12" ) ) return OBJECT_PLANT12;
- if ( Cmd(p, "Greenery13" ) ) return OBJECT_PLANT13;
- if ( Cmd(p, "Greenery14" ) ) return OBJECT_PLANT14;
- if ( Cmd(p, "Greenery15" ) ) return OBJECT_PLANT15;
- if ( Cmd(p, "Greenery16" ) ) return OBJECT_PLANT16;
- if ( Cmd(p, "Greenery17" ) ) return OBJECT_PLANT17;
- if ( Cmd(p, "Greenery18" ) ) return OBJECT_PLANT18;
- if ( Cmd(p, "Greenery19" ) ) return OBJECT_PLANT19;
- if ( Cmd(p, "Greenery0" ) ) return OBJECT_PLANT0;
- if ( Cmd(p, "Greenery1" ) ) return OBJECT_PLANT1;
- if ( Cmd(p, "Greenery2" ) ) return OBJECT_PLANT2;
- if ( Cmd(p, "Greenery3" ) ) return OBJECT_PLANT3;
- if ( Cmd(p, "Greenery4" ) ) return OBJECT_PLANT4;
- if ( Cmd(p, "Greenery5" ) ) return OBJECT_PLANT5;
- if ( Cmd(p, "Greenery6" ) ) return OBJECT_PLANT6;
- if ( Cmd(p, "Greenery7" ) ) return OBJECT_PLANT7;
- if ( Cmd(p, "Greenery8" ) ) return OBJECT_PLANT8;
- if ( Cmd(p, "Greenery9" ) ) return OBJECT_PLANT9;
- if ( Cmd(p, "Tree0" ) ) return OBJECT_TREE0;
- if ( Cmd(p, "Tree1" ) ) return OBJECT_TREE1;
- if ( Cmd(p, "Tree2" ) ) return OBJECT_TREE2;
- if ( Cmd(p, "Tree3" ) ) return OBJECT_TREE3;
- if ( Cmd(p, "Tree4" ) ) return OBJECT_TREE4;
- if ( Cmd(p, "Tree5" ) ) return OBJECT_TREE5;
- if ( Cmd(p, "Tree6" ) ) return OBJECT_TREE6;
- if ( Cmd(p, "Tree7" ) ) return OBJECT_TREE7;
- if ( Cmd(p, "Tree8" ) ) return OBJECT_TREE8;
- if ( Cmd(p, "Tree9" ) ) return OBJECT_TREE9;
- if ( Cmd(p, "Mushroom0" ) ) return OBJECT_MUSHROOM0;
- if ( Cmd(p, "Mushroom1" ) ) return OBJECT_MUSHROOM1;
- if ( Cmd(p, "Mushroom2" ) ) return OBJECT_MUSHROOM2;
- if ( Cmd(p, "Mushroom3" ) ) return OBJECT_MUSHROOM3;
- if ( Cmd(p, "Mushroom4" ) ) return OBJECT_MUSHROOM4;
- if ( Cmd(p, "Mushroom5" ) ) return OBJECT_MUSHROOM5;
- if ( Cmd(p, "Mushroom6" ) ) return OBJECT_MUSHROOM6;
- if ( Cmd(p, "Mushroom7" ) ) return OBJECT_MUSHROOM7;
- if ( Cmd(p, "Mushroom8" ) ) return OBJECT_MUSHROOM8;
- if ( Cmd(p, "Mushroom9" ) ) return OBJECT_MUSHROOM9;
- if ( Cmd(p, "Home" ) ) return OBJECT_HOME1;
- if ( Cmd(p, "Derrick" ) ) return OBJECT_DERRICK;
- if ( Cmd(p, "BotFactory" ) ) return OBJECT_FACTORY;
- if ( Cmd(p, "PowerStation" ) ) return OBJECT_STATION;
- if ( Cmd(p, "Converter" ) ) return OBJECT_CONVERT;
- if ( Cmd(p, "RepairCenter" ) ) return OBJECT_REPAIR;
- if ( Cmd(p, "Destroyer" ) ) return OBJECT_DESTROYER;
- if ( Cmd(p, "DefenseTower" ) ) return OBJECT_TOWER;
- if ( Cmd(p, "AlienNest" ) ) return OBJECT_NEST;
- if ( Cmd(p, "ResearchCenter" ) ) return OBJECT_RESEARCH;
- if ( Cmd(p, "RadarStation" ) ) return OBJECT_RADAR;
- if ( Cmd(p, "ExchangePost" ) ) return OBJECT_INFO;
- if ( Cmd(p, "PowerPlant" ) ) return OBJECT_ENERGY;
- if ( Cmd(p, "AutoLab" ) ) return OBJECT_LABO;
- if ( Cmd(p, "NuclearPlant" ) ) return OBJECT_NUCLEAR;
- if ( Cmd(p, "PowerCaptor" ) ) return OBJECT_PARA;
- if ( Cmd(p, "Vault" ) ) return OBJECT_SAFE;
- if ( Cmd(p, "Houston" ) ) return OBJECT_HUSTON;
- if ( Cmd(p, "Target1" ) ) return OBJECT_TARGET1;
- if ( Cmd(p, "Target2" ) ) return OBJECT_TARGET2;
- if ( Cmd(p, "StartArea" ) ) return OBJECT_START;
- if ( Cmd(p, "GoalArea" ) ) return OBJECT_END;
- if ( Cmd(p, "AlienQueen" ) ) return OBJECT_MOTHER;
- if ( Cmd(p, "AlienEgg" ) ) return OBJECT_EGG;
- if ( Cmd(p, "AlienAnt" ) ) return OBJECT_ANT;
- if ( Cmd(p, "AlienSpider" ) ) return OBJECT_SPIDER;
- if ( Cmd(p, "AlienWasp" ) ) return OBJECT_BEE;
- if ( Cmd(p, "AlienWorm" ) ) return OBJECT_WORM;
- if ( Cmd(p, "WreckBotw1" ) ) return OBJECT_RUINmobilew1;
- if ( Cmd(p, "WreckBotw2" ) ) return OBJECT_RUINmobilew2;
- if ( Cmd(p, "WreckBott1" ) ) return OBJECT_RUINmobilet1;
- if ( Cmd(p, "WreckBott2" ) ) return OBJECT_RUINmobilet2;
- if ( Cmd(p, "WreckBotr1" ) ) return OBJECT_RUINmobiler1;
- if ( Cmd(p, "WreckBotr2" ) ) return OBJECT_RUINmobiler2;
- if ( Cmd(p, "RuinBotFactory" ) ) return OBJECT_RUINfactory;
- if ( Cmd(p, "RuinDoor" ) ) return OBJECT_RUINdoor;
- if ( Cmd(p, "RuinSupport" ) ) return OBJECT_RUINsupport;
- if ( Cmd(p, "RuinRadar" ) ) return OBJECT_RUINradar;
- if ( Cmd(p, "RuinConvert" ) ) return OBJECT_RUINconvert;
- if ( Cmd(p, "RuinBaseCamp" ) ) return OBJECT_RUINbase;
- if ( Cmd(p, "RuinHeadCamp" ) ) return OBJECT_RUINhead;
- if ( Cmd(p, "Barrier0" ) ) return OBJECT_BARRIER0;
- if ( Cmd(p, "Barrier1" ) ) return OBJECT_BARRIER1;
- if ( Cmd(p, "Barrier2" ) ) return OBJECT_BARRIER2;
- if ( Cmd(p, "Barrier3" ) ) return OBJECT_BARRIER3;
- if ( Cmd(p, "Barrier4" ) ) return OBJECT_BARRIER4;
- if ( Cmd(p, "Teen40" ) ) return OBJECT_TEEN40;
- if ( Cmd(p, "Teen41" ) ) return OBJECT_TEEN41;
- if ( Cmd(p, "Teen42" ) ) return OBJECT_TEEN42;
- if ( Cmd(p, "Teen43" ) ) return OBJECT_TEEN43;
- if ( Cmd(p, "Teen44" ) ) return OBJECT_TEEN44;
- if ( Cmd(p, "Teen45" ) ) return OBJECT_TEEN45;
- if ( Cmd(p, "Teen46" ) ) return OBJECT_TEEN46;
- if ( Cmd(p, "Teen47" ) ) return OBJECT_TEEN47;
- if ( Cmd(p, "Teen48" ) ) return OBJECT_TEEN48;
- if ( Cmd(p, "Teen49" ) ) return OBJECT_TEEN49;
- if ( Cmd(p, "Teen30" ) ) return OBJECT_TEEN30;
- if ( Cmd(p, "Teen31" ) ) return OBJECT_TEEN31;
- if ( Cmd(p, "Teen32" ) ) return OBJECT_TEEN32;
- if ( Cmd(p, "Teen33" ) ) return OBJECT_TEEN33;
- if ( Cmd(p, "Stone" ) ) return OBJECT_TEEN34;
- if ( Cmd(p, "Teen35" ) ) return OBJECT_TEEN35;
- if ( Cmd(p, "Teen36" ) ) return OBJECT_TEEN36;
- if ( Cmd(p, "Teen37" ) ) return OBJECT_TEEN37;
- if ( Cmd(p, "Teen38" ) ) return OBJECT_TEEN38;
- if ( Cmd(p, "Teen39" ) ) return OBJECT_TEEN39;
- if ( Cmd(p, "Teen20" ) ) return OBJECT_TEEN20;
- if ( Cmd(p, "Teen21" ) ) return OBJECT_TEEN21;
- if ( Cmd(p, "Teen22" ) ) return OBJECT_TEEN22;
- if ( Cmd(p, "Teen23" ) ) return OBJECT_TEEN23;
- if ( Cmd(p, "Teen24" ) ) return OBJECT_TEEN24;
- if ( Cmd(p, "Teen25" ) ) return OBJECT_TEEN25;
- if ( Cmd(p, "Teen26" ) ) return OBJECT_TEEN26;
- if ( Cmd(p, "Teen27" ) ) return OBJECT_TEEN27;
- if ( Cmd(p, "Teen28" ) ) return OBJECT_TEEN28;
- if ( Cmd(p, "Teen29" ) ) return OBJECT_TEEN29;
- if ( Cmd(p, "Teen10" ) ) return OBJECT_TEEN10;
- if ( Cmd(p, "Teen11" ) ) return OBJECT_TEEN11;
- if ( Cmd(p, "Teen12" ) ) return OBJECT_TEEN12;
- if ( Cmd(p, "Teen13" ) ) return OBJECT_TEEN13;
- if ( Cmd(p, "Teen14" ) ) return OBJECT_TEEN14;
- if ( Cmd(p, "Teen15" ) ) return OBJECT_TEEN15;
- if ( Cmd(p, "Teen16" ) ) return OBJECT_TEEN16;
- if ( Cmd(p, "Teen17" ) ) return OBJECT_TEEN17;
- if ( Cmd(p, "Teen18" ) ) return OBJECT_TEEN18;
- if ( Cmd(p, "Teen19" ) ) return OBJECT_TEEN19;
- if ( Cmd(p, "Teen0" ) ) return OBJECT_TEEN0;
- if ( Cmd(p, "Teen1" ) ) return OBJECT_TEEN1;
- if ( Cmd(p, "Teen2" ) ) return OBJECT_TEEN2;
- if ( Cmd(p, "Teen3" ) ) return OBJECT_TEEN3;
- if ( Cmd(p, "Teen4" ) ) return OBJECT_TEEN4;
- if ( Cmd(p, "Teen5" ) ) return OBJECT_TEEN5;
- if ( Cmd(p, "Teen6" ) ) return OBJECT_TEEN6;
- if ( Cmd(p, "Teen7" ) ) return OBJECT_TEEN7;
- if ( Cmd(p, "Teen8" ) ) return OBJECT_TEEN8;
- if ( Cmd(p, "Teen9" ) ) return OBJECT_TEEN9;
- if ( Cmd(p, "Quartz0" ) ) return OBJECT_QUARTZ0;
- if ( Cmd(p, "Quartz1" ) ) return OBJECT_QUARTZ1;
- if ( Cmd(p, "Quartz2" ) ) return OBJECT_QUARTZ2;
- if ( Cmd(p, "Quartz3" ) ) return OBJECT_QUARTZ3;
- if ( Cmd(p, "Quartz4" ) ) return OBJECT_QUARTZ4;
- if ( Cmd(p, "Quartz5" ) ) return OBJECT_QUARTZ5;
- if ( Cmd(p, "Quartz6" ) ) return OBJECT_QUARTZ6;
- if ( Cmd(p, "Quartz7" ) ) return OBJECT_QUARTZ7;
- if ( Cmd(p, "Quartz8" ) ) return OBJECT_QUARTZ8;
- if ( Cmd(p, "Quartz9" ) ) return OBJECT_QUARTZ9;
- if ( Cmd(p, "MegaStalk0" ) ) return OBJECT_ROOT0;
- if ( Cmd(p, "MegaStalk1" ) ) return OBJECT_ROOT1;
- if ( Cmd(p, "MegaStalk2" ) ) return OBJECT_ROOT2;
- if ( Cmd(p, "MegaStalk3" ) ) return OBJECT_ROOT3;
- if ( Cmd(p, "MegaStalk4" ) ) return OBJECT_ROOT4;
- if ( Cmd(p, "MegaStalk5" ) ) return OBJECT_ROOT5;
- if ( Cmd(p, "MegaStalk6" ) ) return OBJECT_ROOT6;
- if ( Cmd(p, "MegaStalk7" ) ) return OBJECT_ROOT7;
- if ( Cmd(p, "MegaStalk8" ) ) return OBJECT_ROOT8;
- if ( Cmd(p, "MegaStalk9" ) ) return OBJECT_ROOT9;
- if ( Cmd(p, "ApolloLEM" ) ) return OBJECT_APOLLO1;
- if ( Cmd(p, "ApolloJeep" ) ) return OBJECT_APOLLO2;
- if ( Cmd(p, "ApolloFlag" ) ) return OBJECT_APOLLO3;
- if ( Cmd(p, "ApolloModule" ) ) return OBJECT_APOLLO4;
- if ( Cmd(p, "ApolloAntenna" ) ) return OBJECT_APOLLO5;
- if ( Cmd(p, "Me" ) ) return OBJECT_HUMAN;
- if ( Cmd(p, "Tech" ) ) return OBJECT_TECH;
-
- return def;
-}
-
-// Returns the name of an object type.
-
-char* GetTypeObject(ObjectType type)
-{
- if ( type == OBJECT_PORTICO ) return "Portico";
- if ( type == OBJECT_BASE ) return "SpaceShip";
- if ( type == OBJECT_MOBILEwt ) return "PracticeBot";
- if ( type == OBJECT_MOBILEfa ) return "WingedGrabber";
- if ( type == OBJECT_MOBILEta ) return "TrackedGrabber";
- if ( type == OBJECT_MOBILEwa ) return "WheeledGrabber";
- if ( type == OBJECT_MOBILEia ) return "LeggedGrabber";
- if ( type == OBJECT_MOBILEfc ) return "WingedShooter";
- if ( type == OBJECT_MOBILEtc ) return "TrackedShooter";
- if ( type == OBJECT_MOBILEwc ) return "WheeledShooter";
- if ( type == OBJECT_MOBILEic ) return "LeggedShooter";
- if ( type == OBJECT_MOBILEfi ) return "WingedOrgaShooter";
- if ( type == OBJECT_MOBILEti ) return "TrackedOrgaShooter";
- if ( type == OBJECT_MOBILEwi ) return "WheeledOrgaShooter";
- if ( type == OBJECT_MOBILEii ) return "LeggedOrgaShooter";
- if ( type == OBJECT_MOBILEfs ) return "WingedSniffer";
- if ( type == OBJECT_MOBILEts ) return "TrackedSniffer";
- if ( type == OBJECT_MOBILEws ) return "WheeledSniffer";
- if ( type == OBJECT_MOBILEis ) return "LeggedSniffer";
- if ( type == OBJECT_MOBILErt ) return "Thumper";
- if ( type == OBJECT_MOBILErc ) return "PhazerShooter";
- if ( type == OBJECT_MOBILErr ) return "Recycler";
- if ( type == OBJECT_MOBILErs ) return "Shielder";
- if ( type == OBJECT_MOBILEsa ) return "Subber";
- if ( type == OBJECT_MOBILEtg ) return "TargetBot";
- if ( type == OBJECT_MOBILEdr ) return "Scribbler";
- if ( type == OBJECT_MARKPOWER ) return "PowerSpot";
- if ( type == OBJECT_MARKSTONE ) return "TitaniumSpot";
-#if _GERMAN | _WG
- if ( type == OBJECT_MARKURANIUM ) return "PlatinumSpot";
-#else
- if ( type == OBJECT_MARKURANIUM ) return "UraniumSpot";
-#endif
- if ( type == OBJECT_MARKKEYa ) return "KeyASpot";
- if ( type == OBJECT_MARKKEYb ) return "KeyBSpot";
- if ( type == OBJECT_MARKKEYc ) return "KeyCSpot";
- if ( type == OBJECT_MARKKEYd ) return "KeyDSpot";
- if ( type == OBJECT_WAYPOINT ) return "WayPoint";
- if ( type == OBJECT_FLAGb ) return "BlueFlag";
- if ( type == OBJECT_FLAGr ) return "RedFlag";
- if ( type == OBJECT_FLAGg ) return "GreenFlag";
- if ( type == OBJECT_FLAGy ) return "YellowFlag";
- if ( type == OBJECT_FLAGv ) return "VioletFlag";
- if ( type == OBJECT_POWER ) return "PowerCell";
-#if _GERMAN | _WG
- if ( type == OBJECT_ATOMIC ) return "FuelCell";
-#else
- if ( type == OBJECT_ATOMIC ) return "NuclearCell";
-#endif
- if ( type == OBJECT_STONE ) return "TitaniumOre";
-#if _GERMAN | _WG
- if ( type == OBJECT_URANIUM ) return "PlatinumOre";
-#else
- if ( type == OBJECT_URANIUM ) return "UraniumOre";
-#endif
- if ( type == OBJECT_METAL ) return "Titanium";
- if ( type == OBJECT_BULLET ) return "OrgaMatter";
- if ( type == OBJECT_BBOX ) return "BlackBox";
- if ( type == OBJECT_KEYa ) return "KeyA";
- if ( type == OBJECT_KEYb ) return "KeyB";
- if ( type == OBJECT_KEYc ) return "KeyC";
- if ( type == OBJECT_KEYd ) return "KeyD";
- if ( type == OBJECT_TNT ) return "TNT";
- if ( type == OBJECT_SCRAP1 ) return "Scrap1";
- if ( type == OBJECT_SCRAP2 ) return "Scrap2";
- if ( type == OBJECT_SCRAP3 ) return "Scrap3";
- if ( type == OBJECT_SCRAP4 ) return "Scrap4";
- if ( type == OBJECT_SCRAP5 ) return "Scrap5";
- if ( type == OBJECT_BOMB ) return "Mine";
- if ( type == OBJECT_WINFIRE ) return "Firework";
- if ( type == OBJECT_BAG ) return "Bag";
- if ( type == OBJECT_PLANT0 ) return "Greenery0";
- if ( type == OBJECT_PLANT1 ) return "Greenery1";
- if ( type == OBJECT_PLANT2 ) return "Greenery2";
- if ( type == OBJECT_PLANT3 ) return "Greenery3";
- if ( type == OBJECT_PLANT4 ) return "Greenery4";
- if ( type == OBJECT_PLANT5 ) return "Greenery5";
- if ( type == OBJECT_PLANT6 ) return "Greenery6";
- if ( type == OBJECT_PLANT7 ) return "Greenery7";
- if ( type == OBJECT_PLANT8 ) return "Greenery8";
- if ( type == OBJECT_PLANT9 ) return "Greenery9";
- if ( type == OBJECT_PLANT10 ) return "Greenery10";
- if ( type == OBJECT_PLANT11 ) return "Greenery11";
- if ( type == OBJECT_PLANT12 ) return "Greenery12";
- if ( type == OBJECT_PLANT13 ) return "Greenery13";
- if ( type == OBJECT_PLANT14 ) return "Greenery14";
- if ( type == OBJECT_PLANT15 ) return "Greenery15";
- if ( type == OBJECT_PLANT16 ) return "Greenery16";
- if ( type == OBJECT_PLANT17 ) return "Greenery17";
- if ( type == OBJECT_PLANT18 ) return "Greenery18";
- if ( type == OBJECT_PLANT19 ) return "Greenery19";
- if ( type == OBJECT_TREE0 ) return "Tree0";
- if ( type == OBJECT_TREE1 ) return "Tree1";
- if ( type == OBJECT_TREE2 ) return "Tree2";
- if ( type == OBJECT_TREE3 ) return "Tree3";
- if ( type == OBJECT_TREE4 ) return "Tree4";
- if ( type == OBJECT_TREE5 ) return "Tree5";
- if ( type == OBJECT_TREE6 ) return "Tree6";
- if ( type == OBJECT_TREE7 ) return "Tree7";
- if ( type == OBJECT_TREE8 ) return "Tree8";
- if ( type == OBJECT_TREE9 ) return "Tree9";
- if ( type == OBJECT_MUSHROOM0 ) return "Mushroom0";
- if ( type == OBJECT_MUSHROOM1 ) return "Mushroom1";
- if ( type == OBJECT_MUSHROOM2 ) return "Mushroom2";
- if ( type == OBJECT_MUSHROOM3 ) return "Mushroom3";
- if ( type == OBJECT_MUSHROOM4 ) return "Mushroom4";
- if ( type == OBJECT_MUSHROOM5 ) return "Mushroom5";
- if ( type == OBJECT_MUSHROOM6 ) return "Mushroom6";
- if ( type == OBJECT_MUSHROOM7 ) return "Mushroom7";
- if ( type == OBJECT_MUSHROOM8 ) return "Mushroom8";
- if ( type == OBJECT_MUSHROOM9 ) return "Mushroom9";
- if ( type == OBJECT_HOME1 ) return "Home";
- if ( type == OBJECT_DERRICK ) return "Derrick";
- if ( type == OBJECT_FACTORY ) return "BotFactory";
- if ( type == OBJECT_STATION ) return "PowerStation";
- if ( type == OBJECT_CONVERT ) return "Converter";
- if ( type == OBJECT_REPAIR ) return "RepairCenter";
- if ( type == OBJECT_DESTROYER ) return "Destroyer";
- if ( type == OBJECT_TOWER ) return "DefenseTower";
- if ( type == OBJECT_NEST ) return "AlienNest";
- if ( type == OBJECT_RESEARCH ) return "ResearchCenter";
- if ( type == OBJECT_RADAR ) return "RadarStation";
- if ( type == OBJECT_INFO ) return "ExchangePost";
- if ( type == OBJECT_ENERGY ) return "PowerPlant";
- if ( type == OBJECT_LABO ) return "AutoLab";
-#if _GERMAN | _WG
- if ( type == OBJECT_NUCLEAR ) return "FuelCellPlant";
-#else
- if ( type == OBJECT_NUCLEAR ) return "NuclearPlant";
-#endif
- if ( type == OBJECT_PARA ) return "PowerCaptor";
- if ( type == OBJECT_SAFE ) return "Vault";
- if ( type == OBJECT_HUSTON ) return "Houston";
- if ( type == OBJECT_TARGET1 ) return "Target1";
- if ( type == OBJECT_TARGET2 ) return "Target2";
- if ( type == OBJECT_START ) return "StartArea";
- if ( type == OBJECT_END ) return "GoalArea";
- if ( type == OBJECT_MOTHER ) return "AlienQueen";
- if ( type == OBJECT_EGG ) return "AlienEgg";
- if ( type == OBJECT_ANT ) return "AlienAnt";
- if ( type == OBJECT_SPIDER ) return "AlienSpider";
- if ( type == OBJECT_BEE ) return "AlienWasp";
- if ( type == OBJECT_WORM ) return "AlienWorm";
- if ( type == OBJECT_RUINmobilew1 ) return "WreckBotw1";
- if ( type == OBJECT_RUINmobilew2 ) return "WreckBotw2";
- if ( type == OBJECT_RUINmobilet1 ) return "WreckBott1";
- if ( type == OBJECT_RUINmobilet2 ) return "WreckBott2";
- if ( type == OBJECT_RUINmobiler1 ) return "WreckBotr1";
- if ( type == OBJECT_RUINmobiler2 ) return "WreckBotr2";
- if ( type == OBJECT_RUINfactory ) return "RuinBotFactory";
- if ( type == OBJECT_RUINdoor ) return "RuinDoor";
- if ( type == OBJECT_RUINsupport ) return "RuinSupport";
- if ( type == OBJECT_RUINradar ) return "RuinRadar";
- if ( type == OBJECT_RUINconvert ) return "RuinConvert";
- if ( type == OBJECT_RUINbase ) return "RuinBaseCamp";
- if ( type == OBJECT_RUINhead ) return "RuinHeadCamp";
- if ( type == OBJECT_BARRIER0 ) return "Barrier0";
- if ( type == OBJECT_BARRIER1 ) return "Barrier1";
- if ( type == OBJECT_BARRIER2 ) return "Barrier2";
- if ( type == OBJECT_BARRIER3 ) return "Barrier3";
- if ( type == OBJECT_BARRIER4 ) return "Barrier4";
- if ( type == OBJECT_TEEN0 ) return "Teen0";
- if ( type == OBJECT_TEEN1 ) return "Teen1";
- if ( type == OBJECT_TEEN2 ) return "Teen2";
- if ( type == OBJECT_TEEN3 ) return "Teen3";
- if ( type == OBJECT_TEEN4 ) return "Teen4";
- if ( type == OBJECT_TEEN5 ) return "Teen5";
- if ( type == OBJECT_TEEN6 ) return "Teen6";
- if ( type == OBJECT_TEEN7 ) return "Teen7";
- if ( type == OBJECT_TEEN8 ) return "Teen8";
- if ( type == OBJECT_TEEN9 ) return "Teen9";
- if ( type == OBJECT_TEEN10 ) return "Teen10";
- if ( type == OBJECT_TEEN11 ) return "Teen11";
- if ( type == OBJECT_TEEN12 ) return "Teen12";
- if ( type == OBJECT_TEEN13 ) return "Teen13";
- if ( type == OBJECT_TEEN14 ) return "Teen14";
- if ( type == OBJECT_TEEN15 ) return "Teen15";
- if ( type == OBJECT_TEEN16 ) return "Teen16";
- if ( type == OBJECT_TEEN17 ) return "Teen17";
- if ( type == OBJECT_TEEN18 ) return "Teen18";
- if ( type == OBJECT_TEEN19 ) return "Teen19";
- if ( type == OBJECT_TEEN20 ) return "Teen20";
- if ( type == OBJECT_TEEN21 ) return "Teen21";
- if ( type == OBJECT_TEEN22 ) return "Teen22";
- if ( type == OBJECT_TEEN23 ) return "Teen23";
- if ( type == OBJECT_TEEN24 ) return "Teen24";
- if ( type == OBJECT_TEEN25 ) return "Teen25";
- if ( type == OBJECT_TEEN26 ) return "Teen26";
- if ( type == OBJECT_TEEN27 ) return "Teen27";
- if ( type == OBJECT_TEEN28 ) return "Teen28";
- if ( type == OBJECT_TEEN29 ) return "Teen29";
- if ( type == OBJECT_TEEN30 ) return "Teen30";
- if ( type == OBJECT_TEEN31 ) return "Teen31";
- if ( type == OBJECT_TEEN32 ) return "Teen32";
- if ( type == OBJECT_TEEN33 ) return "Teen33";
- if ( type == OBJECT_TEEN34 ) return "Stone";
- if ( type == OBJECT_TEEN35 ) return "Teen35";
- if ( type == OBJECT_TEEN36 ) return "Teen36";
- if ( type == OBJECT_TEEN37 ) return "Teen37";
- if ( type == OBJECT_TEEN38 ) return "Teen38";
- if ( type == OBJECT_TEEN39 ) return "Teen39";
- if ( type == OBJECT_TEEN40 ) return "Teen40";
- if ( type == OBJECT_TEEN41 ) return "Teen41";
- if ( type == OBJECT_TEEN42 ) return "Teen42";
- if ( type == OBJECT_TEEN43 ) return "Teen43";
- if ( type == OBJECT_TEEN44 ) return "Teen44";
- if ( type == OBJECT_TEEN45 ) return "Teen45";
- if ( type == OBJECT_TEEN46 ) return "Teen46";
- if ( type == OBJECT_TEEN47 ) return "Teen47";
- if ( type == OBJECT_TEEN48 ) return "Teen48";
- if ( type == OBJECT_TEEN49 ) return "Teen49";
- if ( type == OBJECT_QUARTZ0 ) return "Quartz0";
- if ( type == OBJECT_QUARTZ1 ) return "Quartz1";
- if ( type == OBJECT_QUARTZ2 ) return "Quartz2";
- if ( type == OBJECT_QUARTZ3 ) return "Quartz3";
- if ( type == OBJECT_QUARTZ4 ) return "Quartz4";
- if ( type == OBJECT_QUARTZ5 ) return "Quartz5";
- if ( type == OBJECT_QUARTZ6 ) return "Quartz6";
- if ( type == OBJECT_QUARTZ7 ) return "Quartz7";
- if ( type == OBJECT_QUARTZ8 ) return "Quartz8";
- if ( type == OBJECT_QUARTZ9 ) return "Quartz9";
- if ( type == OBJECT_ROOT0 ) return "MegaStalk0";
- if ( type == OBJECT_ROOT1 ) return "MegaStalk1";
- if ( type == OBJECT_ROOT2 ) return "MegaStalk2";
- if ( type == OBJECT_ROOT3 ) return "MegaStalk3";
- if ( type == OBJECT_ROOT4 ) return "MegaStalk4";
- if ( type == OBJECT_ROOT5 ) return "MegaStalk5";
- if ( type == OBJECT_ROOT6 ) return "MegaStalk6";
- if ( type == OBJECT_ROOT7 ) return "MegaStalk7";
- if ( type == OBJECT_ROOT8 ) return "MegaStalk8";
- if ( type == OBJECT_ROOT9 ) return "MegaStalk9";
- if ( type == OBJECT_APOLLO1 ) return "ApolloLEM";
- if ( type == OBJECT_APOLLO2 ) return "ApolloJeep";
- if ( type == OBJECT_APOLLO3 ) return "ApolloFlag";
- if ( type == OBJECT_APOLLO4 ) return "ApolloModule";
- if ( type == OBJECT_APOLLO5 ) return "ApolloAntenna";
- if ( type == OBJECT_HUMAN ) return "Me";
- if ( type == OBJECT_TECH ) return "Tech";
- return "";
-}
-
-// Returns the type of water.
-
-WaterType GetTypeWater(char *line, int rank, WaterType def)
-{
- char* p;
-
- p = SearchArg(line, rank);
- if ( *p == 0 ) return def;
-
- if ( Cmd(p, "NULL" ) ) return WATER_NULL;
- if ( Cmd(p, "TT" ) ) return WATER_TT;
- if ( Cmd(p, "TO" ) ) return WATER_TO;
- if ( Cmd(p, "CT" ) ) return WATER_CT;
- if ( Cmd(p, "CO" ) ) return WATER_CO;
-
- return def;
-}
-
-// Returns the type of terrain.
-
-D3DTypeObj GetTypeTerrain(char *line, int rank, D3DTypeObj def)
-{
- char* p;
-
- p = SearchArg(line, rank);
- if ( *p == 0 ) return def;
-
- if ( Cmd(p, "Terrain" ) ) return TYPETERRAIN;
- if ( Cmd(p, "Object" ) ) return TYPEFIX;
- if ( Cmd(p, "Quartz" ) ) return TYPEQUARTZ;
- if ( Cmd(p, "Metal" ) ) return TYPEMETAL;
-
- return def;
-}
-
-// Returns the type of a building.
-
-int GetBuild(char *line, int rank)
-{
- char* p;
-
- p = SearchArg(line, rank);
- if ( *p == 0 ) return 0;
-
- if ( Cmd(p, "BotFactory" ) ) return BUILD_FACTORY;
- if ( Cmd(p, "Derrick" ) ) return BUILD_DERRICK;
- if ( Cmd(p, "Converter" ) ) return BUILD_CONVERT;
- if ( Cmd(p, "RadarStation" ) ) return BUILD_RADAR;
- if ( Cmd(p, "PowerPlant" ) ) return BUILD_ENERGY;
- if ( Cmd(p, "NuclearPlant" ) ) return BUILD_NUCLEAR;
- if ( Cmd(p, "FuelCellPlant" ) ) return BUILD_NUCLEAR;
- if ( Cmd(p, "PowerStation" ) ) return BUILD_STATION;
- if ( Cmd(p, "RepairCenter" ) ) return BUILD_REPAIR;
- if ( Cmd(p, "DefenseTower" ) ) return BUILD_TOWER;
- if ( Cmd(p, "ResearchCenter") ) return BUILD_RESEARCH;
- if ( Cmd(p, "AutoLab" ) ) return BUILD_LABO;
- if ( Cmd(p, "PowerCaptor" ) ) return BUILD_PARA;
- if ( Cmd(p, "ExchangePost" ) ) return BUILD_INFO;
- if ( Cmd(p, "FlatGround" ) ) return BUILD_GFLAT;
- if ( Cmd(p, "Flag" ) ) return BUILD_FLAG;
-
- return 0;
-}
-
-// Returns the type of search.
-
-int GetResearch(char *line, int rank)
-{
- char* p;
-
- p = SearchArg(line, rank);
- if ( *p == 0 ) return 0;
-
- if ( Cmd(p, "TRACKER" ) ) return RESEARCH_TANK;
- if ( Cmd(p, "WINGER" ) ) return RESEARCH_FLY;
- if ( Cmd(p, "THUMPER" ) ) return RESEARCH_THUMP;
- if ( Cmd(p, "SHOOTER" ) ) return RESEARCH_CANON;
- if ( Cmd(p, "TOWER" ) ) return RESEARCH_TOWER;
- if ( Cmd(p, "PHAZER" ) ) return RESEARCH_PHAZER;
- if ( Cmd(p, "SHIELDER") ) return RESEARCH_SHIELD;
- if ( Cmd(p, "ATOMIC" ) ) return RESEARCH_ATOMIC;
- if ( Cmd(p, "iPAW" ) ) return RESEARCH_iPAW;
- if ( Cmd(p, "iGUN" ) ) return RESEARCH_iGUN;
- if ( Cmd(p, "RECYCLER") ) return RESEARCH_RECYCLER;
- if ( Cmd(p, "SUBBER" ) ) return RESEARCH_SUBM;
- if ( Cmd(p, "SNIFFER" ) ) return RESEARCH_SNIFFER;
-
- return 0;
-}
-
-// Returns the type of pyrotechnic effect.
-
-PyroType GetPyro(char *line, int rank)
-{
- char* p;
-
- p = SearchArg(line, rank);
- if ( *p == 0 ) return PT_NULL;
-
- if ( Cmd(p, "FRAGt" ) ) return PT_FRAGT;
- if ( Cmd(p, "FRAGo" ) ) return PT_FRAGO;
- if ( Cmd(p, "FRAGw" ) ) return PT_FRAGW;
- if ( Cmd(p, "EXPLOt" ) ) return PT_EXPLOT;
- if ( Cmd(p, "EXPLOo" ) ) return PT_EXPLOO;
- if ( Cmd(p, "EXPLOw" ) ) return PT_EXPLOW;
- if ( Cmd(p, "SHOTt" ) ) return PT_SHOTT;
- if ( Cmd(p, "SHOTh" ) ) return PT_SHOTH;
- if ( Cmd(p, "SHOTm" ) ) return PT_SHOTM;
- if ( Cmd(p, "SHOTw" ) ) return PT_SHOTW;
- if ( Cmd(p, "EGG" ) ) return PT_EGG;
- if ( Cmd(p, "BURNt" ) ) return PT_BURNT;
- if ( Cmd(p, "BURNo" ) ) return PT_BURNO;
- if ( Cmd(p, "SPIDER" ) ) return PT_SPIDER;
- if ( Cmd(p, "FALL" ) ) return PT_FALL;
- if ( Cmd(p, "RESET" ) ) return PT_RESET;
- if ( Cmd(p, "WIN" ) ) return PT_WIN;
- if ( Cmd(p, "LOST" ) ) return PT_LOST;
-
- return PT_NULL;
-}
-
-// Returns the type of camera.
-
-CameraType GetCamera(char *line, int rank)
-{
- char* p;
-
- p = SearchArg(line, rank);
- if ( *p == 0 ) return CAMERA_NULL;
-
- if ( Cmd(p, "BACK" ) ) return CAMERA_BACK;
- if ( Cmd(p, "PLANE" ) ) return CAMERA_PLANE;
- if ( Cmd(p, "ONBOARD" ) ) return CAMERA_ONBOARD;
- if ( Cmd(p, "FIX" ) ) return CAMERA_FIX;
-
- return CAMERA_NULL;
-}
-
-// Returns the name of a camera.
-
-char* GetCamera(CameraType type)
-{
- if ( type == CAMERA_ONBOARD ) return "ONBOARD";
- if ( type == CAMERA_FIX ) return "FIX";
- return "BACK";
-}
-
-// Returns an integer.
-
-int OpInt(char *line, char *op, int def)
-{
- line = SearchOp(line, op);
- if ( *line == 0 ) return def;
- return GetInt(line, 0, def);
-}
-
-// Returns a float number.
-
-float OpFloat(char *line, char *op, float def)
-{
- line = SearchOp(line, op);
- if ( *line == 0 ) return def;
- return GetFloat(line, 0, def);
-}
-
-// Returns a string.
-
-void OpString(char *line, char *op, char *buffer)
-{
- line = SearchOp(line, op);
- if ( *line == 0 )
- {
- buffer[0] = 0;
- }
- else
- {
- GetString(line, 0, buffer);
- }
-}
-
-// Returns the type of an object.
-
-ObjectType OpTypeObject(char *line, char *op, ObjectType def)
-{
- line = SearchOp(line, op);
- if ( *line == 0 ) return def;
- return GetTypeObject(line, 0, def);
-}
-
-// Returns the type of a water.
-
-WaterType OpTypeWater(char *line, char *op, WaterType def)
-{
- line = SearchOp(line, op);
- if ( *line == 0 ) return def;
- return GetTypeWater(line, 0, def);
-}
-
-// Returns the type of a terrain.
-
-D3DTypeObj OpTypeTerrain(char *line, char *op, D3DTypeObj def)
-{
- line = SearchOp(line, op);
- if ( *line == 0 ) return def;
- return GetTypeTerrain(line, 0, def);
-}
-
-// Returns the type of research.
-
-int OpResearch(char *line, char *op)
-{
- line = SearchOp(line, op);
- if ( *line == 0 ) return 0;
- return GetResearch(line, 0);
-}
-
-// Returns the type of pyrotechnic effect.
-
-PyroType OpPyro(char *line, char *op)
-{
- line = SearchOp(line, op);
- if ( *line == 0 ) return PT_NULL;
- return GetPyro(line, 0);
-}
-
-// Returns the type of camera.
-
-CameraType OpCamera(char *line, char *op)
-{
- line = SearchOp(line, op);
- if ( *line == 0 ) return CAMERA_NULL;
- return GetCamera(line, 0);
-}
-
-// Returns the type of a building.
-
-int OpBuild(char *line, char *op)
-{
- line = SearchOp(line, op);
- if ( *line == 0 ) return 0;
- return GetBuild(line, 0);
-}
-
-// Returns a position in the XZ plane (top view).
-
-Math::Vector OpPos(char *line, char *op)
-{
- Math::Vector pos;
-
- line = SearchOp(line, op);
- if ( *line == 0 )
- {
- pos = Math::Vector(0.0f, 0.0f, 0.0f);
- return pos;
- }
- pos.x = GetFloat(line, 0, 0.0f);
- pos.y = 0.0f;
- pos.z = GetFloat(line, 1, 0.0f);
- return pos;
-}
-
-// Returns a direction.
-
-Math::Vector OpDir(char *line, char *op)
-{
- Math::Vector dir;
-
- line = SearchOp(line, op);
- if ( *line == 0 )
- {
- dir = Math::Vector(0.0f, 0.0f, 0.0f);
- return dir;
- }
- dir.x = GetFloat(line, 0, 0.0f);
- dir.y = GetFloat(line, 1, 0.0f);
- dir.z = GetFloat(line, 2, 0.0f);
- return dir;
-}
-
-// Reads a color (0 .. 255).
-
-D3DCOLOR OpColor(char *line, char *op, D3DCOLOR def)
-{
- D3DCOLOR color;
-
- line = SearchOp(line, op);
- if ( *line == 0 ) return def;
-
- color = 0;
- color |= (GetInt(line, 0, 0)&0xff)<<16; // r
- color |= (GetInt(line, 1, 0)&0xff)<<8; // g
- color |= (GetInt(line, 2, 0)&0xff)<<0; // b
- color |= (GetInt(line, 3, 0)&0xff)<<24; // a
- return color;
-}
-
-// Reads a color (-1 .. 1).
-
-D3DCOLORVALUE OpColorValue(char *line, char *op, D3DCOLORVALUE def)
-{
- D3DCOLORVALUE color;
-
- line = SearchOp(line, op);
- if ( *line == 0 ) return def;
-
- color.r = GetFloat(line, 0, 0.0f);
- color.g = GetFloat(line, 1, 0.0f);
- color.b = GetFloat(line, 2, 0.0f);
- color.a = GetFloat(line, 3, 0.0f);
- return color;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/language.h"
+#include "common/global.h"
+#include "common/event.h"
+#include "old/water.h"
+#include "old/pyro.h"
+#include "old/camera.h"
+#include "object/object.h"
+#include "script/cmdtoken.h"
+
+
+
+
+
+// Skips spaces.
+
+char* SkipSpace(char *line)
+{
+ while ( *line == ' ' )
+ {
+ line ++;
+ }
+ return line;
+}
+
+// Checks if a line contains a command.
+
+bool Cmd(char *line, char *token)
+{
+ char* p;
+
+ line = SkipSpace(line);
+ p = strstr(line, token);
+ return ( p == line ); // command at the beginning?
+}
+
+// Seeking an operator.
+
+char* SearchOp(char *line, char *op)
+{
+ char opeq[50];
+ char* p;
+
+ strcpy(opeq, " ");
+ strcat(opeq, op);
+ strcat(opeq, "=");
+
+ p = strstr(line, opeq);
+ if ( p == 0 ) // not found?
+ {
+ return line+strlen(line); // point zero terminator
+ }
+ return p+strlen(opeq); // after the point "="
+}
+
+// Seeks the argument.
+
+char* SearchArg(char *line, int rank)
+{
+ int i;
+ char c;
+
+ for ( i=0 ; i<rank ; i++ )
+ {
+ while ( true )
+ {
+ c = *line++;
+ if ( c == ';' ) break;
+ if ( c == '=' ||
+ c == 0 ) return line+strlen(line);
+ }
+ }
+
+ line = SkipSpace(line);
+ return line;
+}
+
+// Reads an integer, eventually hexadecimal.
+
+int GetInt(char *line, int rank, int def)
+{
+ char* p;
+ int n = 0;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return def;
+
+ if ( p[0] == '0' &&
+ p[1] == 'x' ) // begins with "0x" (hexadecimal)?
+ {
+ p += 2;
+ while ( true )
+ {
+ if ( *p >= '0' && *p <= '9' )
+ {
+ n *= 16;
+ n += (*p++)-'0';
+ continue;
+ }
+ if ( *p >= 'a' && *p <= 'f' )
+ {
+ n *= 16;
+ n += (*p++)-'a'+10;
+ continue;
+ }
+ break;
+ }
+ }
+ else // integer?
+ {
+ sscanf(p, "%d", &n);
+ }
+ return n;
+}
+
+// Reads a float number.
+
+float GetFloat(char *line, int rank, float def)
+{
+ char* p;
+ float n = 0.0f;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return def;
+
+ sscanf(p, "%f", &n);
+ return n;
+}
+
+// Reads a string.
+
+void GetString(char *line, int rank, char *buffer)
+{
+ char* p;
+
+ p = SearchArg(line, rank);
+ *buffer = 0;
+ if ( *p++ != '"' ) return;
+
+ while ( p[0] != 0 )
+ {
+ if ( p[0] == '"' &&
+ p[1] == '"' )
+ {
+ *buffer++ = *p++;
+ p++;
+ continue;
+ }
+ if ( p[0] == '"' ) break;
+
+ *buffer++ = *p++;
+ }
+ *buffer = 0;
+}
+
+// Returns the type of an object.
+
+ObjectType GetTypeObject(char *line, int rank, ObjectType def)
+{
+ char* p;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return def;
+
+ if ( Cmd(p, "All" ) ) return OBJECT_NULL;
+ if ( Cmd(p, "Portico" ) ) return OBJECT_PORTICO;
+ if ( Cmd(p, "SpaceShip" ) ) return OBJECT_BASE;
+ if ( Cmd(p, "PracticeBot" ) ) return OBJECT_MOBILEwt;
+ if ( Cmd(p, "WingedGrabber" ) ) return OBJECT_MOBILEfa;
+ if ( Cmd(p, "TrackedGrabber" ) ) return OBJECT_MOBILEta;
+ if ( Cmd(p, "WheeledGrabber" ) ) return OBJECT_MOBILEwa;
+ if ( Cmd(p, "LeggedGrabber" ) ) return OBJECT_MOBILEia;
+ if ( Cmd(p, "WingedShooter" ) ) return OBJECT_MOBILEfc;
+ if ( Cmd(p, "TrackedShooter" ) ) return OBJECT_MOBILEtc;
+ if ( Cmd(p, "WheeledShooter" ) ) return OBJECT_MOBILEwc;
+ if ( Cmd(p, "LeggedShooter" ) ) return OBJECT_MOBILEic;
+ if ( Cmd(p, "WingedOrgaShooter" ) ) return OBJECT_MOBILEfi;
+ if ( Cmd(p, "TrackedOrgaShooter") ) return OBJECT_MOBILEti;
+ if ( Cmd(p, "WheeledOrgaShooter") ) return OBJECT_MOBILEwi;
+ if ( Cmd(p, "LeggedOrgaShooter" ) ) return OBJECT_MOBILEii;
+ if ( Cmd(p, "WingedSniffer" ) ) return OBJECT_MOBILEfs;
+ if ( Cmd(p, "TrackedSniffer" ) ) return OBJECT_MOBILEts;
+ if ( Cmd(p, "WheeledSniffer" ) ) return OBJECT_MOBILEws;
+ if ( Cmd(p, "LeggedSniffer" ) ) return OBJECT_MOBILEis;
+ if ( Cmd(p, "Thumper" ) ) return OBJECT_MOBILErt;
+ if ( Cmd(p, "PhazerShooter" ) ) return OBJECT_MOBILErc;
+ if ( Cmd(p, "Recycler" ) ) return OBJECT_MOBILErr;
+ if ( Cmd(p, "Shielder" ) ) return OBJECT_MOBILErs;
+ if ( Cmd(p, "Subber" ) ) return OBJECT_MOBILEsa;
+ if ( Cmd(p, "TargetBot" ) ) return OBJECT_MOBILEtg;
+ if ( Cmd(p, "Scribbler" ) ) return OBJECT_MOBILEdr;
+ if ( Cmd(p, "PowerSpot" ) ) return OBJECT_MARKPOWER;
+ if ( Cmd(p, "TitaniumSpot" ) ) return OBJECT_MARKSTONE;
+ if ( Cmd(p, "UraniumSpot" ) ) return OBJECT_MARKURANIUM;
+ if ( Cmd(p, "PlatinumSpot" ) ) return OBJECT_MARKURANIUM;
+ if ( Cmd(p, "KeyASpot" ) ) return OBJECT_MARKKEYa;
+ if ( Cmd(p, "KeyBSpot" ) ) return OBJECT_MARKKEYb;
+ if ( Cmd(p, "KeyCSpot" ) ) return OBJECT_MARKKEYc;
+ if ( Cmd(p, "KeyDSpot" ) ) return OBJECT_MARKKEYd;
+ if ( Cmd(p, "WayPoint" ) ) return OBJECT_WAYPOINT;
+ if ( Cmd(p, "BlueFlag" ) ) return OBJECT_FLAGb;
+ if ( Cmd(p, "RedFlag" ) ) return OBJECT_FLAGr;
+ if ( Cmd(p, "GreenFlag" ) ) return OBJECT_FLAGg;
+ if ( Cmd(p, "YellowFlag" ) ) return OBJECT_FLAGy;
+ if ( Cmd(p, "VioletFlag" ) ) return OBJECT_FLAGv;
+ if ( Cmd(p, "PowerCell" ) ) return OBJECT_POWER;
+ if ( Cmd(p, "FuelCellPlant" ) ) return OBJECT_NUCLEAR;
+ if ( Cmd(p, "FuelCell" ) ) return OBJECT_ATOMIC;
+ if ( Cmd(p, "NuclearCell" ) ) return OBJECT_ATOMIC;
+ if ( Cmd(p, "TitaniumOre" ) ) return OBJECT_STONE;
+ if ( Cmd(p, "UraniumOre" ) ) return OBJECT_URANIUM;
+ if ( Cmd(p, "PlatinumOre" ) ) return OBJECT_URANIUM;
+ if ( Cmd(p, "Titanium" ) ) return OBJECT_METAL;
+ if ( Cmd(p, "OrgaMatter" ) ) return OBJECT_BULLET;
+ if ( Cmd(p, "BlackBox" ) ) return OBJECT_BBOX;
+ if ( Cmd(p, "KeyA" ) ) return OBJECT_KEYa;
+ if ( Cmd(p, "KeyB" ) ) return OBJECT_KEYb;
+ if ( Cmd(p, "KeyC" ) ) return OBJECT_KEYc;
+ if ( Cmd(p, "KeyD" ) ) return OBJECT_KEYd;
+ if ( Cmd(p, "TNT" ) ) return OBJECT_TNT;
+ if ( Cmd(p, "Scrap1" ) ) return OBJECT_SCRAP1;
+ if ( Cmd(p, "Scrap2" ) ) return OBJECT_SCRAP2;
+ if ( Cmd(p, "Scrap3" ) ) return OBJECT_SCRAP3;
+ if ( Cmd(p, "Scrap4" ) ) return OBJECT_SCRAP4;
+ if ( Cmd(p, "Scrap5" ) ) return OBJECT_SCRAP5;
+ if ( Cmd(p, "Mine" ) ) return OBJECT_BOMB;
+ if ( Cmd(p, "Firework" ) ) return OBJECT_WINFIRE;
+ if ( Cmd(p, "Bag" ) ) return OBJECT_BAG;
+ if ( Cmd(p, "Greenery10" ) ) return OBJECT_PLANT10;
+ if ( Cmd(p, "Greenery11" ) ) return OBJECT_PLANT11;
+ if ( Cmd(p, "Greenery12" ) ) return OBJECT_PLANT12;
+ if ( Cmd(p, "Greenery13" ) ) return OBJECT_PLANT13;
+ if ( Cmd(p, "Greenery14" ) ) return OBJECT_PLANT14;
+ if ( Cmd(p, "Greenery15" ) ) return OBJECT_PLANT15;
+ if ( Cmd(p, "Greenery16" ) ) return OBJECT_PLANT16;
+ if ( Cmd(p, "Greenery17" ) ) return OBJECT_PLANT17;
+ if ( Cmd(p, "Greenery18" ) ) return OBJECT_PLANT18;
+ if ( Cmd(p, "Greenery19" ) ) return OBJECT_PLANT19;
+ if ( Cmd(p, "Greenery0" ) ) return OBJECT_PLANT0;
+ if ( Cmd(p, "Greenery1" ) ) return OBJECT_PLANT1;
+ if ( Cmd(p, "Greenery2" ) ) return OBJECT_PLANT2;
+ if ( Cmd(p, "Greenery3" ) ) return OBJECT_PLANT3;
+ if ( Cmd(p, "Greenery4" ) ) return OBJECT_PLANT4;
+ if ( Cmd(p, "Greenery5" ) ) return OBJECT_PLANT5;
+ if ( Cmd(p, "Greenery6" ) ) return OBJECT_PLANT6;
+ if ( Cmd(p, "Greenery7" ) ) return OBJECT_PLANT7;
+ if ( Cmd(p, "Greenery8" ) ) return OBJECT_PLANT8;
+ if ( Cmd(p, "Greenery9" ) ) return OBJECT_PLANT9;
+ if ( Cmd(p, "Tree0" ) ) return OBJECT_TREE0;
+ if ( Cmd(p, "Tree1" ) ) return OBJECT_TREE1;
+ if ( Cmd(p, "Tree2" ) ) return OBJECT_TREE2;
+ if ( Cmd(p, "Tree3" ) ) return OBJECT_TREE3;
+ if ( Cmd(p, "Tree4" ) ) return OBJECT_TREE4;
+ if ( Cmd(p, "Tree5" ) ) return OBJECT_TREE5;
+ if ( Cmd(p, "Tree6" ) ) return OBJECT_TREE6;
+ if ( Cmd(p, "Tree7" ) ) return OBJECT_TREE7;
+ if ( Cmd(p, "Tree8" ) ) return OBJECT_TREE8;
+ if ( Cmd(p, "Tree9" ) ) return OBJECT_TREE9;
+ if ( Cmd(p, "Mushroom0" ) ) return OBJECT_MUSHROOM0;
+ if ( Cmd(p, "Mushroom1" ) ) return OBJECT_MUSHROOM1;
+ if ( Cmd(p, "Mushroom2" ) ) return OBJECT_MUSHROOM2;
+ if ( Cmd(p, "Mushroom3" ) ) return OBJECT_MUSHROOM3;
+ if ( Cmd(p, "Mushroom4" ) ) return OBJECT_MUSHROOM4;
+ if ( Cmd(p, "Mushroom5" ) ) return OBJECT_MUSHROOM5;
+ if ( Cmd(p, "Mushroom6" ) ) return OBJECT_MUSHROOM6;
+ if ( Cmd(p, "Mushroom7" ) ) return OBJECT_MUSHROOM7;
+ if ( Cmd(p, "Mushroom8" ) ) return OBJECT_MUSHROOM8;
+ if ( Cmd(p, "Mushroom9" ) ) return OBJECT_MUSHROOM9;
+ if ( Cmd(p, "Home" ) ) return OBJECT_HOME1;
+ if ( Cmd(p, "Derrick" ) ) return OBJECT_DERRICK;
+ if ( Cmd(p, "BotFactory" ) ) return OBJECT_FACTORY;
+ if ( Cmd(p, "PowerStation" ) ) return OBJECT_STATION;
+ if ( Cmd(p, "Converter" ) ) return OBJECT_CONVERT;
+ if ( Cmd(p, "RepairCenter" ) ) return OBJECT_REPAIR;
+ if ( Cmd(p, "Destroyer" ) ) return OBJECT_DESTROYER;
+ if ( Cmd(p, "DefenseTower" ) ) return OBJECT_TOWER;
+ if ( Cmd(p, "AlienNest" ) ) return OBJECT_NEST;
+ if ( Cmd(p, "ResearchCenter" ) ) return OBJECT_RESEARCH;
+ if ( Cmd(p, "RadarStation" ) ) return OBJECT_RADAR;
+ if ( Cmd(p, "ExchangePost" ) ) return OBJECT_INFO;
+ if ( Cmd(p, "PowerPlant" ) ) return OBJECT_ENERGY;
+ if ( Cmd(p, "AutoLab" ) ) return OBJECT_LABO;
+ if ( Cmd(p, "NuclearPlant" ) ) return OBJECT_NUCLEAR;
+ if ( Cmd(p, "PowerCaptor" ) ) return OBJECT_PARA;
+ if ( Cmd(p, "Vault" ) ) return OBJECT_SAFE;
+ if ( Cmd(p, "Houston" ) ) return OBJECT_HUSTON;
+ if ( Cmd(p, "Target1" ) ) return OBJECT_TARGET1;
+ if ( Cmd(p, "Target2" ) ) return OBJECT_TARGET2;
+ if ( Cmd(p, "StartArea" ) ) return OBJECT_START;
+ if ( Cmd(p, "GoalArea" ) ) return OBJECT_END;
+ if ( Cmd(p, "AlienQueen" ) ) return OBJECT_MOTHER;
+ if ( Cmd(p, "AlienEgg" ) ) return OBJECT_EGG;
+ if ( Cmd(p, "AlienAnt" ) ) return OBJECT_ANT;
+ if ( Cmd(p, "AlienSpider" ) ) return OBJECT_SPIDER;
+ if ( Cmd(p, "AlienWasp" ) ) return OBJECT_BEE;
+ if ( Cmd(p, "AlienWorm" ) ) return OBJECT_WORM;
+ if ( Cmd(p, "WreckBotw1" ) ) return OBJECT_RUINmobilew1;
+ if ( Cmd(p, "WreckBotw2" ) ) return OBJECT_RUINmobilew2;
+ if ( Cmd(p, "WreckBott1" ) ) return OBJECT_RUINmobilet1;
+ if ( Cmd(p, "WreckBott2" ) ) return OBJECT_RUINmobilet2;
+ if ( Cmd(p, "WreckBotr1" ) ) return OBJECT_RUINmobiler1;
+ if ( Cmd(p, "WreckBotr2" ) ) return OBJECT_RUINmobiler2;
+ if ( Cmd(p, "RuinBotFactory" ) ) return OBJECT_RUINfactory;
+ if ( Cmd(p, "RuinDoor" ) ) return OBJECT_RUINdoor;
+ if ( Cmd(p, "RuinSupport" ) ) return OBJECT_RUINsupport;
+ if ( Cmd(p, "RuinRadar" ) ) return OBJECT_RUINradar;
+ if ( Cmd(p, "RuinConvert" ) ) return OBJECT_RUINconvert;
+ if ( Cmd(p, "RuinBaseCamp" ) ) return OBJECT_RUINbase;
+ if ( Cmd(p, "RuinHeadCamp" ) ) return OBJECT_RUINhead;
+ if ( Cmd(p, "Barrier0" ) ) return OBJECT_BARRIER0;
+ if ( Cmd(p, "Barrier1" ) ) return OBJECT_BARRIER1;
+ if ( Cmd(p, "Barrier2" ) ) return OBJECT_BARRIER2;
+ if ( Cmd(p, "Barrier3" ) ) return OBJECT_BARRIER3;
+ if ( Cmd(p, "Barrier4" ) ) return OBJECT_BARRIER4;
+ if ( Cmd(p, "Teen40" ) ) return OBJECT_TEEN40;
+ if ( Cmd(p, "Teen41" ) ) return OBJECT_TEEN41;
+ if ( Cmd(p, "Teen42" ) ) return OBJECT_TEEN42;
+ if ( Cmd(p, "Teen43" ) ) return OBJECT_TEEN43;
+ if ( Cmd(p, "Teen44" ) ) return OBJECT_TEEN44;
+ if ( Cmd(p, "Teen45" ) ) return OBJECT_TEEN45;
+ if ( Cmd(p, "Teen46" ) ) return OBJECT_TEEN46;
+ if ( Cmd(p, "Teen47" ) ) return OBJECT_TEEN47;
+ if ( Cmd(p, "Teen48" ) ) return OBJECT_TEEN48;
+ if ( Cmd(p, "Teen49" ) ) return OBJECT_TEEN49;
+ if ( Cmd(p, "Teen30" ) ) return OBJECT_TEEN30;
+ if ( Cmd(p, "Teen31" ) ) return OBJECT_TEEN31;
+ if ( Cmd(p, "Teen32" ) ) return OBJECT_TEEN32;
+ if ( Cmd(p, "Teen33" ) ) return OBJECT_TEEN33;
+ if ( Cmd(p, "Stone" ) ) return OBJECT_TEEN34;
+ if ( Cmd(p, "Teen35" ) ) return OBJECT_TEEN35;
+ if ( Cmd(p, "Teen36" ) ) return OBJECT_TEEN36;
+ if ( Cmd(p, "Teen37" ) ) return OBJECT_TEEN37;
+ if ( Cmd(p, "Teen38" ) ) return OBJECT_TEEN38;
+ if ( Cmd(p, "Teen39" ) ) return OBJECT_TEEN39;
+ if ( Cmd(p, "Teen20" ) ) return OBJECT_TEEN20;
+ if ( Cmd(p, "Teen21" ) ) return OBJECT_TEEN21;
+ if ( Cmd(p, "Teen22" ) ) return OBJECT_TEEN22;
+ if ( Cmd(p, "Teen23" ) ) return OBJECT_TEEN23;
+ if ( Cmd(p, "Teen24" ) ) return OBJECT_TEEN24;
+ if ( Cmd(p, "Teen25" ) ) return OBJECT_TEEN25;
+ if ( Cmd(p, "Teen26" ) ) return OBJECT_TEEN26;
+ if ( Cmd(p, "Teen27" ) ) return OBJECT_TEEN27;
+ if ( Cmd(p, "Teen28" ) ) return OBJECT_TEEN28;
+ if ( Cmd(p, "Teen29" ) ) return OBJECT_TEEN29;
+ if ( Cmd(p, "Teen10" ) ) return OBJECT_TEEN10;
+ if ( Cmd(p, "Teen11" ) ) return OBJECT_TEEN11;
+ if ( Cmd(p, "Teen12" ) ) return OBJECT_TEEN12;
+ if ( Cmd(p, "Teen13" ) ) return OBJECT_TEEN13;
+ if ( Cmd(p, "Teen14" ) ) return OBJECT_TEEN14;
+ if ( Cmd(p, "Teen15" ) ) return OBJECT_TEEN15;
+ if ( Cmd(p, "Teen16" ) ) return OBJECT_TEEN16;
+ if ( Cmd(p, "Teen17" ) ) return OBJECT_TEEN17;
+ if ( Cmd(p, "Teen18" ) ) return OBJECT_TEEN18;
+ if ( Cmd(p, "Teen19" ) ) return OBJECT_TEEN19;
+ if ( Cmd(p, "Teen0" ) ) return OBJECT_TEEN0;
+ if ( Cmd(p, "Teen1" ) ) return OBJECT_TEEN1;
+ if ( Cmd(p, "Teen2" ) ) return OBJECT_TEEN2;
+ if ( Cmd(p, "Teen3" ) ) return OBJECT_TEEN3;
+ if ( Cmd(p, "Teen4" ) ) return OBJECT_TEEN4;
+ if ( Cmd(p, "Teen5" ) ) return OBJECT_TEEN5;
+ if ( Cmd(p, "Teen6" ) ) return OBJECT_TEEN6;
+ if ( Cmd(p, "Teen7" ) ) return OBJECT_TEEN7;
+ if ( Cmd(p, "Teen8" ) ) return OBJECT_TEEN8;
+ if ( Cmd(p, "Teen9" ) ) return OBJECT_TEEN9;
+ if ( Cmd(p, "Quartz0" ) ) return OBJECT_QUARTZ0;
+ if ( Cmd(p, "Quartz1" ) ) return OBJECT_QUARTZ1;
+ if ( Cmd(p, "Quartz2" ) ) return OBJECT_QUARTZ2;
+ if ( Cmd(p, "Quartz3" ) ) return OBJECT_QUARTZ3;
+ if ( Cmd(p, "Quartz4" ) ) return OBJECT_QUARTZ4;
+ if ( Cmd(p, "Quartz5" ) ) return OBJECT_QUARTZ5;
+ if ( Cmd(p, "Quartz6" ) ) return OBJECT_QUARTZ6;
+ if ( Cmd(p, "Quartz7" ) ) return OBJECT_QUARTZ7;
+ if ( Cmd(p, "Quartz8" ) ) return OBJECT_QUARTZ8;
+ if ( Cmd(p, "Quartz9" ) ) return OBJECT_QUARTZ9;
+ if ( Cmd(p, "MegaStalk0" ) ) return OBJECT_ROOT0;
+ if ( Cmd(p, "MegaStalk1" ) ) return OBJECT_ROOT1;
+ if ( Cmd(p, "MegaStalk2" ) ) return OBJECT_ROOT2;
+ if ( Cmd(p, "MegaStalk3" ) ) return OBJECT_ROOT3;
+ if ( Cmd(p, "MegaStalk4" ) ) return OBJECT_ROOT4;
+ if ( Cmd(p, "MegaStalk5" ) ) return OBJECT_ROOT5;
+ if ( Cmd(p, "MegaStalk6" ) ) return OBJECT_ROOT6;
+ if ( Cmd(p, "MegaStalk7" ) ) return OBJECT_ROOT7;
+ if ( Cmd(p, "MegaStalk8" ) ) return OBJECT_ROOT8;
+ if ( Cmd(p, "MegaStalk9" ) ) return OBJECT_ROOT9;
+ if ( Cmd(p, "ApolloLEM" ) ) return OBJECT_APOLLO1;
+ if ( Cmd(p, "ApolloJeep" ) ) return OBJECT_APOLLO2;
+ if ( Cmd(p, "ApolloFlag" ) ) return OBJECT_APOLLO3;
+ if ( Cmd(p, "ApolloModule" ) ) return OBJECT_APOLLO4;
+ if ( Cmd(p, "ApolloAntenna" ) ) return OBJECT_APOLLO5;
+ if ( Cmd(p, "Me" ) ) return OBJECT_HUMAN;
+ if ( Cmd(p, "Tech" ) ) return OBJECT_TECH;
+
+ return def;
+}
+
+// Returns the name of an object type.
+
+char* GetTypeObject(ObjectType type)
+{
+ if ( type == OBJECT_PORTICO ) return "Portico";
+ if ( type == OBJECT_BASE ) return "SpaceShip";
+ if ( type == OBJECT_MOBILEwt ) return "PracticeBot";
+ if ( type == OBJECT_MOBILEfa ) return "WingedGrabber";
+ if ( type == OBJECT_MOBILEta ) return "TrackedGrabber";
+ if ( type == OBJECT_MOBILEwa ) return "WheeledGrabber";
+ if ( type == OBJECT_MOBILEia ) return "LeggedGrabber";
+ if ( type == OBJECT_MOBILEfc ) return "WingedShooter";
+ if ( type == OBJECT_MOBILEtc ) return "TrackedShooter";
+ if ( type == OBJECT_MOBILEwc ) return "WheeledShooter";
+ if ( type == OBJECT_MOBILEic ) return "LeggedShooter";
+ if ( type == OBJECT_MOBILEfi ) return "WingedOrgaShooter";
+ if ( type == OBJECT_MOBILEti ) return "TrackedOrgaShooter";
+ if ( type == OBJECT_MOBILEwi ) return "WheeledOrgaShooter";
+ if ( type == OBJECT_MOBILEii ) return "LeggedOrgaShooter";
+ if ( type == OBJECT_MOBILEfs ) return "WingedSniffer";
+ if ( type == OBJECT_MOBILEts ) return "TrackedSniffer";
+ if ( type == OBJECT_MOBILEws ) return "WheeledSniffer";
+ if ( type == OBJECT_MOBILEis ) return "LeggedSniffer";
+ if ( type == OBJECT_MOBILErt ) return "Thumper";
+ if ( type == OBJECT_MOBILErc ) return "PhazerShooter";
+ if ( type == OBJECT_MOBILErr ) return "Recycler";
+ if ( type == OBJECT_MOBILErs ) return "Shielder";
+ if ( type == OBJECT_MOBILEsa ) return "Subber";
+ if ( type == OBJECT_MOBILEtg ) return "TargetBot";
+ if ( type == OBJECT_MOBILEdr ) return "Scribbler";
+ if ( type == OBJECT_MARKPOWER ) return "PowerSpot";
+ if ( type == OBJECT_MARKSTONE ) return "TitaniumSpot";
+#if _GERMAN | _WG
+ if ( type == OBJECT_MARKURANIUM ) return "PlatinumSpot";
+#else
+ if ( type == OBJECT_MARKURANIUM ) return "UraniumSpot";
+#endif
+ if ( type == OBJECT_MARKKEYa ) return "KeyASpot";
+ if ( type == OBJECT_MARKKEYb ) return "KeyBSpot";
+ if ( type == OBJECT_MARKKEYc ) return "KeyCSpot";
+ if ( type == OBJECT_MARKKEYd ) return "KeyDSpot";
+ if ( type == OBJECT_WAYPOINT ) return "WayPoint";
+ if ( type == OBJECT_FLAGb ) return "BlueFlag";
+ if ( type == OBJECT_FLAGr ) return "RedFlag";
+ if ( type == OBJECT_FLAGg ) return "GreenFlag";
+ if ( type == OBJECT_FLAGy ) return "YellowFlag";
+ if ( type == OBJECT_FLAGv ) return "VioletFlag";
+ if ( type == OBJECT_POWER ) return "PowerCell";
+#if _GERMAN | _WG
+ if ( type == OBJECT_ATOMIC ) return "FuelCell";
+#else
+ if ( type == OBJECT_ATOMIC ) return "NuclearCell";
+#endif
+ if ( type == OBJECT_STONE ) return "TitaniumOre";
+#if _GERMAN | _WG
+ if ( type == OBJECT_URANIUM ) return "PlatinumOre";
+#else
+ if ( type == OBJECT_URANIUM ) return "UraniumOre";
+#endif
+ if ( type == OBJECT_METAL ) return "Titanium";
+ if ( type == OBJECT_BULLET ) return "OrgaMatter";
+ if ( type == OBJECT_BBOX ) return "BlackBox";
+ if ( type == OBJECT_KEYa ) return "KeyA";
+ if ( type == OBJECT_KEYb ) return "KeyB";
+ if ( type == OBJECT_KEYc ) return "KeyC";
+ if ( type == OBJECT_KEYd ) return "KeyD";
+ if ( type == OBJECT_TNT ) return "TNT";
+ if ( type == OBJECT_SCRAP1 ) return "Scrap1";
+ if ( type == OBJECT_SCRAP2 ) return "Scrap2";
+ if ( type == OBJECT_SCRAP3 ) return "Scrap3";
+ if ( type == OBJECT_SCRAP4 ) return "Scrap4";
+ if ( type == OBJECT_SCRAP5 ) return "Scrap5";
+ if ( type == OBJECT_BOMB ) return "Mine";
+ if ( type == OBJECT_WINFIRE ) return "Firework";
+ if ( type == OBJECT_BAG ) return "Bag";
+ if ( type == OBJECT_PLANT0 ) return "Greenery0";
+ if ( type == OBJECT_PLANT1 ) return "Greenery1";
+ if ( type == OBJECT_PLANT2 ) return "Greenery2";
+ if ( type == OBJECT_PLANT3 ) return "Greenery3";
+ if ( type == OBJECT_PLANT4 ) return "Greenery4";
+ if ( type == OBJECT_PLANT5 ) return "Greenery5";
+ if ( type == OBJECT_PLANT6 ) return "Greenery6";
+ if ( type == OBJECT_PLANT7 ) return "Greenery7";
+ if ( type == OBJECT_PLANT8 ) return "Greenery8";
+ if ( type == OBJECT_PLANT9 ) return "Greenery9";
+ if ( type == OBJECT_PLANT10 ) return "Greenery10";
+ if ( type == OBJECT_PLANT11 ) return "Greenery11";
+ if ( type == OBJECT_PLANT12 ) return "Greenery12";
+ if ( type == OBJECT_PLANT13 ) return "Greenery13";
+ if ( type == OBJECT_PLANT14 ) return "Greenery14";
+ if ( type == OBJECT_PLANT15 ) return "Greenery15";
+ if ( type == OBJECT_PLANT16 ) return "Greenery16";
+ if ( type == OBJECT_PLANT17 ) return "Greenery17";
+ if ( type == OBJECT_PLANT18 ) return "Greenery18";
+ if ( type == OBJECT_PLANT19 ) return "Greenery19";
+ if ( type == OBJECT_TREE0 ) return "Tree0";
+ if ( type == OBJECT_TREE1 ) return "Tree1";
+ if ( type == OBJECT_TREE2 ) return "Tree2";
+ if ( type == OBJECT_TREE3 ) return "Tree3";
+ if ( type == OBJECT_TREE4 ) return "Tree4";
+ if ( type == OBJECT_TREE5 ) return "Tree5";
+ if ( type == OBJECT_TREE6 ) return "Tree6";
+ if ( type == OBJECT_TREE7 ) return "Tree7";
+ if ( type == OBJECT_TREE8 ) return "Tree8";
+ if ( type == OBJECT_TREE9 ) return "Tree9";
+ if ( type == OBJECT_MUSHROOM0 ) return "Mushroom0";
+ if ( type == OBJECT_MUSHROOM1 ) return "Mushroom1";
+ if ( type == OBJECT_MUSHROOM2 ) return "Mushroom2";
+ if ( type == OBJECT_MUSHROOM3 ) return "Mushroom3";
+ if ( type == OBJECT_MUSHROOM4 ) return "Mushroom4";
+ if ( type == OBJECT_MUSHROOM5 ) return "Mushroom5";
+ if ( type == OBJECT_MUSHROOM6 ) return "Mushroom6";
+ if ( type == OBJECT_MUSHROOM7 ) return "Mushroom7";
+ if ( type == OBJECT_MUSHROOM8 ) return "Mushroom8";
+ if ( type == OBJECT_MUSHROOM9 ) return "Mushroom9";
+ if ( type == OBJECT_HOME1 ) return "Home";
+ if ( type == OBJECT_DERRICK ) return "Derrick";
+ if ( type == OBJECT_FACTORY ) return "BotFactory";
+ if ( type == OBJECT_STATION ) return "PowerStation";
+ if ( type == OBJECT_CONVERT ) return "Converter";
+ if ( type == OBJECT_REPAIR ) return "RepairCenter";
+ if ( type == OBJECT_DESTROYER ) return "Destroyer";
+ if ( type == OBJECT_TOWER ) return "DefenseTower";
+ if ( type == OBJECT_NEST ) return "AlienNest";
+ if ( type == OBJECT_RESEARCH ) return "ResearchCenter";
+ if ( type == OBJECT_RADAR ) return "RadarStation";
+ if ( type == OBJECT_INFO ) return "ExchangePost";
+ if ( type == OBJECT_ENERGY ) return "PowerPlant";
+ if ( type == OBJECT_LABO ) return "AutoLab";
+#if _GERMAN | _WG
+ if ( type == OBJECT_NUCLEAR ) return "FuelCellPlant";
+#else
+ if ( type == OBJECT_NUCLEAR ) return "NuclearPlant";
+#endif
+ if ( type == OBJECT_PARA ) return "PowerCaptor";
+ if ( type == OBJECT_SAFE ) return "Vault";
+ if ( type == OBJECT_HUSTON ) return "Houston";
+ if ( type == OBJECT_TARGET1 ) return "Target1";
+ if ( type == OBJECT_TARGET2 ) return "Target2";
+ if ( type == OBJECT_START ) return "StartArea";
+ if ( type == OBJECT_END ) return "GoalArea";
+ if ( type == OBJECT_MOTHER ) return "AlienQueen";
+ if ( type == OBJECT_EGG ) return "AlienEgg";
+ if ( type == OBJECT_ANT ) return "AlienAnt";
+ if ( type == OBJECT_SPIDER ) return "AlienSpider";
+ if ( type == OBJECT_BEE ) return "AlienWasp";
+ if ( type == OBJECT_WORM ) return "AlienWorm";
+ if ( type == OBJECT_RUINmobilew1 ) return "WreckBotw1";
+ if ( type == OBJECT_RUINmobilew2 ) return "WreckBotw2";
+ if ( type == OBJECT_RUINmobilet1 ) return "WreckBott1";
+ if ( type == OBJECT_RUINmobilet2 ) return "WreckBott2";
+ if ( type == OBJECT_RUINmobiler1 ) return "WreckBotr1";
+ if ( type == OBJECT_RUINmobiler2 ) return "WreckBotr2";
+ if ( type == OBJECT_RUINfactory ) return "RuinBotFactory";
+ if ( type == OBJECT_RUINdoor ) return "RuinDoor";
+ if ( type == OBJECT_RUINsupport ) return "RuinSupport";
+ if ( type == OBJECT_RUINradar ) return "RuinRadar";
+ if ( type == OBJECT_RUINconvert ) return "RuinConvert";
+ if ( type == OBJECT_RUINbase ) return "RuinBaseCamp";
+ if ( type == OBJECT_RUINhead ) return "RuinHeadCamp";
+ if ( type == OBJECT_BARRIER0 ) return "Barrier0";
+ if ( type == OBJECT_BARRIER1 ) return "Barrier1";
+ if ( type == OBJECT_BARRIER2 ) return "Barrier2";
+ if ( type == OBJECT_BARRIER3 ) return "Barrier3";
+ if ( type == OBJECT_BARRIER4 ) return "Barrier4";
+ if ( type == OBJECT_TEEN0 ) return "Teen0";
+ if ( type == OBJECT_TEEN1 ) return "Teen1";
+ if ( type == OBJECT_TEEN2 ) return "Teen2";
+ if ( type == OBJECT_TEEN3 ) return "Teen3";
+ if ( type == OBJECT_TEEN4 ) return "Teen4";
+ if ( type == OBJECT_TEEN5 ) return "Teen5";
+ if ( type == OBJECT_TEEN6 ) return "Teen6";
+ if ( type == OBJECT_TEEN7 ) return "Teen7";
+ if ( type == OBJECT_TEEN8 ) return "Teen8";
+ if ( type == OBJECT_TEEN9 ) return "Teen9";
+ if ( type == OBJECT_TEEN10 ) return "Teen10";
+ if ( type == OBJECT_TEEN11 ) return "Teen11";
+ if ( type == OBJECT_TEEN12 ) return "Teen12";
+ if ( type == OBJECT_TEEN13 ) return "Teen13";
+ if ( type == OBJECT_TEEN14 ) return "Teen14";
+ if ( type == OBJECT_TEEN15 ) return "Teen15";
+ if ( type == OBJECT_TEEN16 ) return "Teen16";
+ if ( type == OBJECT_TEEN17 ) return "Teen17";
+ if ( type == OBJECT_TEEN18 ) return "Teen18";
+ if ( type == OBJECT_TEEN19 ) return "Teen19";
+ if ( type == OBJECT_TEEN20 ) return "Teen20";
+ if ( type == OBJECT_TEEN21 ) return "Teen21";
+ if ( type == OBJECT_TEEN22 ) return "Teen22";
+ if ( type == OBJECT_TEEN23 ) return "Teen23";
+ if ( type == OBJECT_TEEN24 ) return "Teen24";
+ if ( type == OBJECT_TEEN25 ) return "Teen25";
+ if ( type == OBJECT_TEEN26 ) return "Teen26";
+ if ( type == OBJECT_TEEN27 ) return "Teen27";
+ if ( type == OBJECT_TEEN28 ) return "Teen28";
+ if ( type == OBJECT_TEEN29 ) return "Teen29";
+ if ( type == OBJECT_TEEN30 ) return "Teen30";
+ if ( type == OBJECT_TEEN31 ) return "Teen31";
+ if ( type == OBJECT_TEEN32 ) return "Teen32";
+ if ( type == OBJECT_TEEN33 ) return "Teen33";
+ if ( type == OBJECT_TEEN34 ) return "Stone";
+ if ( type == OBJECT_TEEN35 ) return "Teen35";
+ if ( type == OBJECT_TEEN36 ) return "Teen36";
+ if ( type == OBJECT_TEEN37 ) return "Teen37";
+ if ( type == OBJECT_TEEN38 ) return "Teen38";
+ if ( type == OBJECT_TEEN39 ) return "Teen39";
+ if ( type == OBJECT_TEEN40 ) return "Teen40";
+ if ( type == OBJECT_TEEN41 ) return "Teen41";
+ if ( type == OBJECT_TEEN42 ) return "Teen42";
+ if ( type == OBJECT_TEEN43 ) return "Teen43";
+ if ( type == OBJECT_TEEN44 ) return "Teen44";
+ if ( type == OBJECT_TEEN45 ) return "Teen45";
+ if ( type == OBJECT_TEEN46 ) return "Teen46";
+ if ( type == OBJECT_TEEN47 ) return "Teen47";
+ if ( type == OBJECT_TEEN48 ) return "Teen48";
+ if ( type == OBJECT_TEEN49 ) return "Teen49";
+ if ( type == OBJECT_QUARTZ0 ) return "Quartz0";
+ if ( type == OBJECT_QUARTZ1 ) return "Quartz1";
+ if ( type == OBJECT_QUARTZ2 ) return "Quartz2";
+ if ( type == OBJECT_QUARTZ3 ) return "Quartz3";
+ if ( type == OBJECT_QUARTZ4 ) return "Quartz4";
+ if ( type == OBJECT_QUARTZ5 ) return "Quartz5";
+ if ( type == OBJECT_QUARTZ6 ) return "Quartz6";
+ if ( type == OBJECT_QUARTZ7 ) return "Quartz7";
+ if ( type == OBJECT_QUARTZ8 ) return "Quartz8";
+ if ( type == OBJECT_QUARTZ9 ) return "Quartz9";
+ if ( type == OBJECT_ROOT0 ) return "MegaStalk0";
+ if ( type == OBJECT_ROOT1 ) return "MegaStalk1";
+ if ( type == OBJECT_ROOT2 ) return "MegaStalk2";
+ if ( type == OBJECT_ROOT3 ) return "MegaStalk3";
+ if ( type == OBJECT_ROOT4 ) return "MegaStalk4";
+ if ( type == OBJECT_ROOT5 ) return "MegaStalk5";
+ if ( type == OBJECT_ROOT6 ) return "MegaStalk6";
+ if ( type == OBJECT_ROOT7 ) return "MegaStalk7";
+ if ( type == OBJECT_ROOT8 ) return "MegaStalk8";
+ if ( type == OBJECT_ROOT9 ) return "MegaStalk9";
+ if ( type == OBJECT_APOLLO1 ) return "ApolloLEM";
+ if ( type == OBJECT_APOLLO2 ) return "ApolloJeep";
+ if ( type == OBJECT_APOLLO3 ) return "ApolloFlag";
+ if ( type == OBJECT_APOLLO4 ) return "ApolloModule";
+ if ( type == OBJECT_APOLLO5 ) return "ApolloAntenna";
+ if ( type == OBJECT_HUMAN ) return "Me";
+ if ( type == OBJECT_TECH ) return "Tech";
+ return "";
+}
+
+// Returns the type of water.
+
+WaterType GetTypeWater(char *line, int rank, WaterType def)
+{
+ char* p;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return def;
+
+ if ( Cmd(p, "NULL" ) ) return WATER_NULL;
+ if ( Cmd(p, "TT" ) ) return WATER_TT;
+ if ( Cmd(p, "TO" ) ) return WATER_TO;
+ if ( Cmd(p, "CT" ) ) return WATER_CT;
+ if ( Cmd(p, "CO" ) ) return WATER_CO;
+
+ return def;
+}
+
+// Returns the type of terrain.
+
+D3DTypeObj GetTypeTerrain(char *line, int rank, D3DTypeObj def)
+{
+ char* p;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return def;
+
+ if ( Cmd(p, "Terrain" ) ) return TYPETERRAIN;
+ if ( Cmd(p, "Object" ) ) return TYPEFIX;
+ if ( Cmd(p, "Quartz" ) ) return TYPEQUARTZ;
+ if ( Cmd(p, "Metal" ) ) return TYPEMETAL;
+
+ return def;
+}
+
+// Returns the type of a building.
+
+int GetBuild(char *line, int rank)
+{
+ char* p;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return 0;
+
+ if ( Cmd(p, "BotFactory" ) ) return BUILD_FACTORY;
+ if ( Cmd(p, "Derrick" ) ) return BUILD_DERRICK;
+ if ( Cmd(p, "Converter" ) ) return BUILD_CONVERT;
+ if ( Cmd(p, "RadarStation" ) ) return BUILD_RADAR;
+ if ( Cmd(p, "PowerPlant" ) ) return BUILD_ENERGY;
+ if ( Cmd(p, "NuclearPlant" ) ) return BUILD_NUCLEAR;
+ if ( Cmd(p, "FuelCellPlant" ) ) return BUILD_NUCLEAR;
+ if ( Cmd(p, "PowerStation" ) ) return BUILD_STATION;
+ if ( Cmd(p, "RepairCenter" ) ) return BUILD_REPAIR;
+ if ( Cmd(p, "DefenseTower" ) ) return BUILD_TOWER;
+ if ( Cmd(p, "ResearchCenter") ) return BUILD_RESEARCH;
+ if ( Cmd(p, "AutoLab" ) ) return BUILD_LABO;
+ if ( Cmd(p, "PowerCaptor" ) ) return BUILD_PARA;
+ if ( Cmd(p, "ExchangePost" ) ) return BUILD_INFO;
+ if ( Cmd(p, "FlatGround" ) ) return BUILD_GFLAT;
+ if ( Cmd(p, "Flag" ) ) return BUILD_FLAG;
+
+ return 0;
+}
+
+// Returns the type of search.
+
+int GetResearch(char *line, int rank)
+{
+ char* p;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return 0;
+
+ if ( Cmd(p, "TRACKER" ) ) return RESEARCH_TANK;
+ if ( Cmd(p, "WINGER" ) ) return RESEARCH_FLY;
+ if ( Cmd(p, "THUMPER" ) ) return RESEARCH_THUMP;
+ if ( Cmd(p, "SHOOTER" ) ) return RESEARCH_CANON;
+ if ( Cmd(p, "TOWER" ) ) return RESEARCH_TOWER;
+ if ( Cmd(p, "PHAZER" ) ) return RESEARCH_PHAZER;
+ if ( Cmd(p, "SHIELDER") ) return RESEARCH_SHIELD;
+ if ( Cmd(p, "ATOMIC" ) ) return RESEARCH_ATOMIC;
+ if ( Cmd(p, "iPAW" ) ) return RESEARCH_iPAW;
+ if ( Cmd(p, "iGUN" ) ) return RESEARCH_iGUN;
+ if ( Cmd(p, "RECYCLER") ) return RESEARCH_RECYCLER;
+ if ( Cmd(p, "SUBBER" ) ) return RESEARCH_SUBM;
+ if ( Cmd(p, "SNIFFER" ) ) return RESEARCH_SNIFFER;
+
+ return 0;
+}
+
+// Returns the type of pyrotechnic effect.
+
+PyroType GetPyro(char *line, int rank)
+{
+ char* p;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return PT_NULL;
+
+ if ( Cmd(p, "FRAGt" ) ) return PT_FRAGT;
+ if ( Cmd(p, "FRAGo" ) ) return PT_FRAGO;
+ if ( Cmd(p, "FRAGw" ) ) return PT_FRAGW;
+ if ( Cmd(p, "EXPLOt" ) ) return PT_EXPLOT;
+ if ( Cmd(p, "EXPLOo" ) ) return PT_EXPLOO;
+ if ( Cmd(p, "EXPLOw" ) ) return PT_EXPLOW;
+ if ( Cmd(p, "SHOTt" ) ) return PT_SHOTT;
+ if ( Cmd(p, "SHOTh" ) ) return PT_SHOTH;
+ if ( Cmd(p, "SHOTm" ) ) return PT_SHOTM;
+ if ( Cmd(p, "SHOTw" ) ) return PT_SHOTW;
+ if ( Cmd(p, "EGG" ) ) return PT_EGG;
+ if ( Cmd(p, "BURNt" ) ) return PT_BURNT;
+ if ( Cmd(p, "BURNo" ) ) return PT_BURNO;
+ if ( Cmd(p, "SPIDER" ) ) return PT_SPIDER;
+ if ( Cmd(p, "FALL" ) ) return PT_FALL;
+ if ( Cmd(p, "RESET" ) ) return PT_RESET;
+ if ( Cmd(p, "WIN" ) ) return PT_WIN;
+ if ( Cmd(p, "LOST" ) ) return PT_LOST;
+
+ return PT_NULL;
+}
+
+// Returns the type of camera.
+
+CameraType GetCamera(char *line, int rank)
+{
+ char* p;
+
+ p = SearchArg(line, rank);
+ if ( *p == 0 ) return CAMERA_NULL;
+
+ if ( Cmd(p, "BACK" ) ) return CAMERA_BACK;
+ if ( Cmd(p, "PLANE" ) ) return CAMERA_PLANE;
+ if ( Cmd(p, "ONBOARD" ) ) return CAMERA_ONBOARD;
+ if ( Cmd(p, "FIX" ) ) return CAMERA_FIX;
+
+ return CAMERA_NULL;
+}
+
+// Returns the name of a camera.
+
+char* GetCamera(CameraType type)
+{
+ if ( type == CAMERA_ONBOARD ) return "ONBOARD";
+ if ( type == CAMERA_FIX ) return "FIX";
+ return "BACK";
+}
+
+// Returns an integer.
+
+int OpInt(char *line, char *op, int def)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return def;
+ return GetInt(line, 0, def);
+}
+
+// Returns a float number.
+
+float OpFloat(char *line, char *op, float def)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return def;
+ return GetFloat(line, 0, def);
+}
+
+// Returns a string.
+
+void OpString(char *line, char *op, char *buffer)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 )
+ {
+ buffer[0] = 0;
+ }
+ else
+ {
+ GetString(line, 0, buffer);
+ }
+}
+
+// Returns the type of an object.
+
+ObjectType OpTypeObject(char *line, char *op, ObjectType def)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return def;
+ return GetTypeObject(line, 0, def);
+}
+
+// Returns the type of a water.
+
+WaterType OpTypeWater(char *line, char *op, WaterType def)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return def;
+ return GetTypeWater(line, 0, def);
+}
+
+// Returns the type of a terrain.
+
+D3DTypeObj OpTypeTerrain(char *line, char *op, D3DTypeObj def)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return def;
+ return GetTypeTerrain(line, 0, def);
+}
+
+// Returns the type of research.
+
+int OpResearch(char *line, char *op)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return 0;
+ return GetResearch(line, 0);
+}
+
+// Returns the type of pyrotechnic effect.
+
+PyroType OpPyro(char *line, char *op)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return PT_NULL;
+ return GetPyro(line, 0);
+}
+
+// Returns the type of camera.
+
+CameraType OpCamera(char *line, char *op)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return CAMERA_NULL;
+ return GetCamera(line, 0);
+}
+
+// Returns the type of a building.
+
+int OpBuild(char *line, char *op)
+{
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return 0;
+ return GetBuild(line, 0);
+}
+
+// Returns a position in the XZ plane (top view).
+
+Math::Vector OpPos(char *line, char *op)
+{
+ Math::Vector pos;
+
+ line = SearchOp(line, op);
+ if ( *line == 0 )
+ {
+ pos = Math::Vector(0.0f, 0.0f, 0.0f);
+ return pos;
+ }
+ pos.x = GetFloat(line, 0, 0.0f);
+ pos.y = 0.0f;
+ pos.z = GetFloat(line, 1, 0.0f);
+ return pos;
+}
+
+// Returns a direction.
+
+Math::Vector OpDir(char *line, char *op)
+{
+ Math::Vector dir;
+
+ line = SearchOp(line, op);
+ if ( *line == 0 )
+ {
+ dir = Math::Vector(0.0f, 0.0f, 0.0f);
+ return dir;
+ }
+ dir.x = GetFloat(line, 0, 0.0f);
+ dir.y = GetFloat(line, 1, 0.0f);
+ dir.z = GetFloat(line, 2, 0.0f);
+ return dir;
+}
+
+// Reads a color (0 .. 255).
+
+D3DCOLOR OpColor(char *line, char *op, D3DCOLOR def)
+{
+ D3DCOLOR color;
+
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return def;
+
+ color = 0;
+ color |= (GetInt(line, 0, 0)&0xff)<<16; // r
+ color |= (GetInt(line, 1, 0)&0xff)<<8; // g
+ color |= (GetInt(line, 2, 0)&0xff)<<0; // b
+ color |= (GetInt(line, 3, 0)&0xff)<<24; // a
+ return color;
+}
+
+// Reads a color (-1 .. 1).
+
+D3DCOLORVALUE OpColorValue(char *line, char *op, D3DCOLORVALUE def)
+{
+ D3DCOLORVALUE color;
+
+ line = SearchOp(line, op);
+ if ( *line == 0 ) return def;
+
+ color.r = GetFloat(line, 0, 0.0f);
+ color.g = GetFloat(line, 1, 0.0f);
+ color.b = GetFloat(line, 2, 0.0f);
+ color.a = GetFloat(line, 3, 0.0f);
+ return color;
+}
+
+
diff --git a/src/script/cmdtoken.h b/src/script/cmdtoken.h
index fa00921..05ff758 100644
--- a/src/script/cmdtoken.h
+++ b/src/script/cmdtoken.h
@@ -1,64 +1,64 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// cmdtoken.h
-
-#pragma once
-
-
-#include "old/d3denum.h"
-#include "old/d3dengine.h"
-#include "object/object.h"
-#include "old/water.h"
-#include "old/pyro.h"
-#include "old/camera.h"
-
-
-
-// Procedures.
-
-extern bool Cmd(char *line, char *token);
-extern char* SearchOp(char *line, char *op);
-
-extern int GetInt(char *line, int rank, int def);
-extern float GetFloat(char *line, int rank, float def);
-extern void GetString(char *line, int rank, char *buffer);
-extern ObjectType GetTypeObject(char *line, int rank, ObjectType def);
-extern char* GetTypeObject(ObjectType type);
-extern WaterType GetTypeWater(char *line, int rank, WaterType def);
-extern D3DTypeObj GetTypeTerrain(char *line, int rank, D3DTypeObj def);
-extern int GetBuild(char *line, int rank);
-extern int GetResearch(char *line, int rank);
-extern PyroType GetPyro(char *line, int rank);
-extern CameraType GetCamera(char *line, int rank);
-extern char* GetCamera(CameraType type);
-
-extern int OpInt(char *line, char *op, int def);
-extern float OpFloat(char *line, char *op, float def);
-extern void OpString(char *line, char *op, char *buffer);
-extern ObjectType OpTypeObject(char *line, char *op, ObjectType def);
-extern WaterType OpTypeWater(char *line, char *op, WaterType def);
-extern D3DTypeObj OpTypeTerrain(char *line, char *op, D3DTypeObj def);
-extern int OpResearch(char *line, char *op);
-extern PyroType OpPyro(char *line, char *op);
-extern CameraType OpCamera(char *line, char *op);
-extern int OpBuild(char *line, char *op);
-extern Math::Vector OpPos(char *line, char *op);
-extern Math::Vector OpDir(char *line, char *op);
-extern D3DCOLOR OpColor(char *line, char *op, D3DCOLOR def);
-extern D3DCOLORVALUE OpColorValue(char *line, char *op, D3DCOLORVALUE def);
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// cmdtoken.h
+
+#pragma once
+
+
+#include "old/d3denum.h"
+#include "old/d3dengine.h"
+#include "object/object.h"
+#include "old/water.h"
+#include "old/pyro.h"
+#include "old/camera.h"
+
+
+
+// Procedures.
+
+extern bool Cmd(char *line, char *token);
+extern char* SearchOp(char *line, char *op);
+
+extern int GetInt(char *line, int rank, int def);
+extern float GetFloat(char *line, int rank, float def);
+extern void GetString(char *line, int rank, char *buffer);
+extern ObjectType GetTypeObject(char *line, int rank, ObjectType def);
+extern char* GetTypeObject(ObjectType type);
+extern WaterType GetTypeWater(char *line, int rank, WaterType def);
+extern D3DTypeObj GetTypeTerrain(char *line, int rank, D3DTypeObj def);
+extern int GetBuild(char *line, int rank);
+extern int GetResearch(char *line, int rank);
+extern PyroType GetPyro(char *line, int rank);
+extern CameraType GetCamera(char *line, int rank);
+extern char* GetCamera(CameraType type);
+
+extern int OpInt(char *line, char *op, int def);
+extern float OpFloat(char *line, char *op, float def);
+extern void OpString(char *line, char *op, char *buffer);
+extern ObjectType OpTypeObject(char *line, char *op, ObjectType def);
+extern WaterType OpTypeWater(char *line, char *op, WaterType def);
+extern D3DTypeObj OpTypeTerrain(char *line, char *op, D3DTypeObj def);
+extern int OpResearch(char *line, char *op);
+extern PyroType OpPyro(char *line, char *op);
+extern CameraType OpCamera(char *line, char *op);
+extern int OpBuild(char *line, char *op);
+extern Math::Vector OpPos(char *line, char *op);
+extern Math::Vector OpDir(char *line, char *op);
+extern D3DCOLOR OpColor(char *line, char *op, D3DCOLOR def);
+extern D3DCOLORVALUE OpColorValue(char *line, char *op, D3DCOLORVALUE def);
+
+
diff --git a/src/script/dd.cpp b/src/script/dd.cpp
index 4c7095e..4110813 100644
--- a/src/script/dd.cpp
+++ b/src/script/dd.cpp
@@ -1,175 +1,175 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// Compilation of a procedure with a "dot".
-
-int cPoint(CBotVar* &var, CBotString& retClass, void* user)
-{
- if ( var == 0 ) return CBotErrLowParam;
-
- if ( var->GivType() <= CBotTypDouble )
- {
- var = var->GivNext();
- if ( var == 0 ) return CBotErrLowParam;
- if ( var->GivType() > CBotTypDouble ) return CBotErrBadNum;
- var = var->GivNext();
- if ( var == 0 ) return CBotErrLowParam;
- if ( var->GivType() > CBotTypDouble ) return CBotErrBadNum;
- var = var->GivNext();
- return 0;
- }
-
- if ( var->GivType() == CBotTypClass )
- {
- if ( !var->IsElemOfClass("point") ) return CBotErrBadParam;
- var = var->GivNext();
- return 0;
- }
-
- return CBotErrBadParam;
-}
-
-// Gives a parameter of type "point".
-
-bool GetPoint(CBotVar* &var, int& exception, Math::Vector& pos)
-{
- CBotVar *pX, *pY, *pZ;
-
- if ( var->GivType() <= CBotTypDouble )
- {
- pos.x = var->GivValFloat()*UNIT;
- var = var->GivNext();
-
- pos.z = var->GivValFloat()*UNIT;
- var = var->GivNext();
-
- pos.y = var->GivValFloat()*UNIT;
- var = var->GivNext();
- }
- else
- {
- pX = var->GivItem("x");
- if ( pX == NULL )
- {
- exception = CBotErrUndefItem; return true;
- }
- pos.x = pX->GivValFloat()*UNIT;
-
- pY = var->GivItem("y");
- if ( pY == NULL )
- {
- exception = CBotErrUndefItem; return true;
- }
- pos.z = pY->GivValFloat()*UNIT; // attention y -> z !
-
- pZ = var->GivItem("z");
- if ( pZ == NULL )
- {
- exception = CBotErrUndefItem; return true;
- }
- pos.y = pZ->GivValFloat()*UNIT; // attention z -> y !
-
- var = var->GivNext();
- }
- return true;
-}
-
-
-
-// Compilation of the instruction "space(center, rMin, rMax, dist)".
-
-int cSpace(CBotVar* &var, CBotString& retClass, void* user)
-{
- int ret;
-
- retClass = "point";
-
- if ( var == 0 ) return CBotTypIntrinsic;
- ret = cPoint(var, retClass, user);
- if ( ret != 0 ) return ret;
-
- if ( var == 0 ) return CBotTypIntrinsic;
- if ( var->GivType() > CBotTypDouble ) return CBotErrBadNum;
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypIntrinsic;
- if ( var->GivType() > CBotTypDouble ) return CBotErrBadNum;
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypIntrinsic;
- if ( var->GivType() > CBotTypDouble ) return CBotErrBadNum;
- var = var->GivNext();
-
- if ( var != 0 ) return CBotErrOverParam;
- return CBotTypIntrinsic;
-}
-
-// Instruction "space(center, rMin, rMax, dist)".
-
-bool rSpace(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pThis = (CObject*)user;
- CBotVar* pSub;
- Math::Vector center;
- float rMin, rMax, dist;
-
- rMin = 5.0f*UNIT;
- rMax = 50.0f*UNIT;
- dist = 4.0f*UNIT;
-
- if ( var == 0 )
- {
- center = pThis->RetPosition(0);
- }
- else
- {
- if ( !GetPoint(var, exception, center) ) return true;
-
- if ( var != 0 )
- {
- rMin = var->GivValFloat()*UNIT;
- var = var->GivNext();
-
- if ( var != 0 )
- {
- rMax = var->GivValFloat()*UNIT;
- var = var->GivNext();
-
- if ( var != 0 )
- {
- dist = var->GivValFloat()*UNIT;
- var = var->GivNext();
- }
- }
- }
- }
- script->m_main->FreeSpace(center, rMin, rMax, dist, pThis);
-
- if ( result != 0 )
- {
- pSub = result->GivItemList();
- if ( pSub != 0 )
- {
- pSub->SetValFloat(center.x/UNIT);
- pSub = pSub->GivNext(); // "y"
- pSub->SetValFloat(center.z/UNIT);
- pSub = pSub->GivNext(); // "z"
- pSub->SetValFloat(center.y/UNIT);
- }
- }
- return true;
-}
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// Compilation of a procedure with a "dot".
+
+int cPoint(CBotVar* &var, CBotString& retClass, void* user)
+{
+ if ( var == 0 ) return CBotErrLowParam;
+
+ if ( var->GivType() <= CBotTypDouble )
+ {
+ var = var->GivNext();
+ if ( var == 0 ) return CBotErrLowParam;
+ if ( var->GivType() > CBotTypDouble ) return CBotErrBadNum;
+ var = var->GivNext();
+ if ( var == 0 ) return CBotErrLowParam;
+ if ( var->GivType() > CBotTypDouble ) return CBotErrBadNum;
+ var = var->GivNext();
+ return 0;
+ }
+
+ if ( var->GivType() == CBotTypClass )
+ {
+ if ( !var->IsElemOfClass("point") ) return CBotErrBadParam;
+ var = var->GivNext();
+ return 0;
+ }
+
+ return CBotErrBadParam;
+}
+
+// Gives a parameter of type "point".
+
+bool GetPoint(CBotVar* &var, int& exception, Math::Vector& pos)
+{
+ CBotVar *pX, *pY, *pZ;
+
+ if ( var->GivType() <= CBotTypDouble )
+ {
+ pos.x = var->GivValFloat()*UNIT;
+ var = var->GivNext();
+
+ pos.z = var->GivValFloat()*UNIT;
+ var = var->GivNext();
+
+ pos.y = var->GivValFloat()*UNIT;
+ var = var->GivNext();
+ }
+ else
+ {
+ pX = var->GivItem("x");
+ if ( pX == NULL )
+ {
+ exception = CBotErrUndefItem; return true;
+ }
+ pos.x = pX->GivValFloat()*UNIT;
+
+ pY = var->GivItem("y");
+ if ( pY == NULL )
+ {
+ exception = CBotErrUndefItem; return true;
+ }
+ pos.z = pY->GivValFloat()*UNIT; // attention y -> z !
+
+ pZ = var->GivItem("z");
+ if ( pZ == NULL )
+ {
+ exception = CBotErrUndefItem; return true;
+ }
+ pos.y = pZ->GivValFloat()*UNIT; // attention z -> y !
+
+ var = var->GivNext();
+ }
+ return true;
+}
+
+
+
+// Compilation of the instruction "space(center, rMin, rMax, dist)".
+
+int cSpace(CBotVar* &var, CBotString& retClass, void* user)
+{
+ int ret;
+
+ retClass = "point";
+
+ if ( var == 0 ) return CBotTypIntrinsic;
+ ret = cPoint(var, retClass, user);
+ if ( ret != 0 ) return ret;
+
+ if ( var == 0 ) return CBotTypIntrinsic;
+ if ( var->GivType() > CBotTypDouble ) return CBotErrBadNum;
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypIntrinsic;
+ if ( var->GivType() > CBotTypDouble ) return CBotErrBadNum;
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypIntrinsic;
+ if ( var->GivType() > CBotTypDouble ) return CBotErrBadNum;
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotErrOverParam;
+ return CBotTypIntrinsic;
+}
+
+// Instruction "space(center, rMin, rMax, dist)".
+
+bool rSpace(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ CBotVar* pSub;
+ Math::Vector center;
+ float rMin, rMax, dist;
+
+ rMin = 5.0f*UNIT;
+ rMax = 50.0f*UNIT;
+ dist = 4.0f*UNIT;
+
+ if ( var == 0 )
+ {
+ center = pThis->RetPosition(0);
+ }
+ else
+ {
+ if ( !GetPoint(var, exception, center) ) return true;
+
+ if ( var != 0 )
+ {
+ rMin = var->GivValFloat()*UNIT;
+ var = var->GivNext();
+
+ if ( var != 0 )
+ {
+ rMax = var->GivValFloat()*UNIT;
+ var = var->GivNext();
+
+ if ( var != 0 )
+ {
+ dist = var->GivValFloat()*UNIT;
+ var = var->GivNext();
+ }
+ }
+ }
+ }
+ script->m_main->FreeSpace(center, rMin, rMax, dist, pThis);
+
+ if ( result != 0 )
+ {
+ pSub = result->GivItemList();
+ if ( pSub != 0 )
+ {
+ pSub->SetValFloat(center.x/UNIT);
+ pSub = pSub->GivNext(); // "y"
+ pSub->SetValFloat(center.z/UNIT);
+ pSub = pSub->GivNext(); // "z"
+ pSub->SetValFloat(center.y/UNIT);
+ }
+ }
+ return true;
+}
diff --git a/src/script/script.cpp b/src/script/script.cpp
index 266a943..d2946a6 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -1,3776 +1,3776 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// script.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "CBot/CBotDll.h"
-#include "common/struct.h"
-#include "math/geometry.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/global.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "old/math3d.h"
-#include "object/robotmain.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "object/object.h"
-#include "physics/physics.h"
-#include "ui/interface.h"
-#include "ui/edit.h"
-#include "ui/list.h"
-#include "old/text.h"
-#include "ui/displaytext.h"
-#include "object/task/taskmanager.h"
-#include "object/task/task.h"
-#include "object/task/taskmanip.h"
-#include "object/task/taskgoto.h"
-#include "object/task/taskshield.h"
-#include "script/cbottoken.h"
-#include "script/script.h"
-
-
-
-const int CBOT_IPF = 100; // CBOT: number of instructions / frame
-
-const int ERM_CONT = 0; // if error -> continue
-const int ERM_STOP = 1; // if error -> stop
-
-
-
-
-// Compiling a procedure without any parameters.
-
-CBotTypResult cNull(CBotVar* &var, void* user)
-{
- if ( var != 0 ) return CBotErrOverParam;
- return CBotTypResult(CBotTypFloat);
-}
-
-// Compiling a procedure with a single real number.
-
-CBotTypResult cOneFloat(CBotVar* &var, void* user)
-{
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
- return CBotTypResult(CBotTypFloat);
-}
-
-// Compiling a procedure with two real numbers.
-
-CBotTypResult cTwoFloat(CBotVar* &var, void* user)
-{
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
- return CBotTypResult(CBotTypFloat);
-}
-
-// Compiling a procedure with a "dot".
-
-CBotTypResult cPoint(CBotVar* &var, void* user)
-{
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
-
- if ( var->GivType() <= CBotTypDouble )
- {
- var = var->GivNext();
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-//? if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
-//? if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
-//? var = var->GivNext();
- return CBotTypResult(0);
- }
-
- if ( var->GivType() == CBotTypClass )
- {
- if ( !var->IsElemOfClass("point") ) return CBotTypResult(CBotErrBadParam);
- var = var->GivNext();
- return CBotTypResult(0);
- }
-
- return CBotTypResult(CBotErrBadParam);
-}
-
-// Compiling a procedure with a single "point".
-
-CBotTypResult cOnePoint(CBotVar* &var, void* user)
-{
- CBotTypResult ret;
-
- ret = cPoint(var, user);
- if ( ret.GivType() != 0 ) return ret;
-
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
- return CBotTypResult(CBotTypFloat);
-}
-
-// Compiling a procedure with a single string.
-
-CBotTypResult cString(CBotVar* &var, void* user)
-{
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() != CBotTypString &&
- var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
- return CBotTypResult(CBotTypFloat);
-}
-
-
-// Seeking value in an array of integers.
-
-bool FindList(CBotVar* array, int type)
-{
- while ( array != 0 )
- {
- if ( type == array->GivValInt() ) return true;
- array = array->GivNext();
- }
- return false;
-}
-
-
-// Gives a parameter of type "point".
-
-bool GetPoint(CBotVar* &var, int& exception, Math::Vector& pos)
-{
- CBotVar *pX, *pY, *pZ;
-
- if ( var->GivType() <= CBotTypDouble )
- {
- pos.x = var->GivValFloat()*g_unit;
- var = var->GivNext();
-
- pos.z = var->GivValFloat()*g_unit;
- var = var->GivNext();
-
- pos.y = 0.0f;
- }
- else
- {
- pX = var->GivItem("x");
- if ( pX == NULL )
- {
- exception = CBotErrUndefItem; return true;
- }
- pos.x = pX->GivValFloat()*g_unit;
-
- pY = var->GivItem("y");
- if ( pY == NULL )
- {
- exception = CBotErrUndefItem; return true;
- }
- pos.z = pY->GivValFloat()*g_unit; // attention y -> z !
-
- pZ = var->GivItem("z");
- if ( pZ == NULL )
- {
- exception = CBotErrUndefItem; return true;
- }
- pos.y = pZ->GivValFloat()*g_unit; // attention z -> y !
-
- var = var->GivNext();
- }
- return true;
-}
-
-
-// Instruction "sin(degrees)".
-
-bool rSin(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- float value;
-
- value = var->GivValFloat();
- result->SetValFloat(sinf(value*Math::PI/180.0f));
- return true;
-}
-
-// Instruction "cos(degrees)".
-
-bool rCos(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- float value;
-
- value = var->GivValFloat();
- result->SetValFloat(cosf(value*Math::PI/180.0f));
- return true;
-}
-
-// Instruction "tan(degrees)".
-
-bool rTan(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- float value;
-
- value = var->GivValFloat();
- result->SetValFloat(tanf(value*Math::PI/180.0f));
- return true;
-}
-
-// Instruction "asin(degrees)".
-
-bool raSin(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- float value;
-
- value = var->GivValFloat();
- result->SetValFloat(asinf(value)*180.0f/Math::PI);
- return true;
-}
-
-// Instruction "acos(degrees)".
-
-bool raCos(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- float value;
-
- value = var->GivValFloat();
- result->SetValFloat(acosf(value)*180.0f/Math::PI);
- return true;
-}
-
-// Instruction "atan(degrees)".
-
-bool raTan(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- float value;
-
- value = var->GivValFloat();
- result->SetValFloat(atanf(value)*180.0f/Math::PI);
- return true;
-}
-
-// Instruction "sqrt(value)".
-
-bool rSqrt(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- float value;
-
- value = var->GivValFloat();
- result->SetValFloat(sqrtf(value));
- return true;
-}
-
-// Instruction "pow(x, y)".
-
-bool rPow(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- float x, y;
-
- x = var->GivValFloat();
- var = var->GivNext();
- y = var->GivValFloat();
- result->SetValFloat(powf(x, y));
- return true;
-}
-
-// Instruction "rand()".
-
-bool rRand(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- result->SetValFloat(Math::Rand());
- return true;
-}
-
-// Instruction "abs()".
-
-bool rAbs(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- float value;
-
- value = var->GivValFloat();
- result->SetValFloat(fabs(value));
- return true;
-}
-
-
-// Compilation of the instruction "retobject(rank)".
-
-CBotTypResult cRetObject(CBotVar* &var, void* user)
-{
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
-
- return CBotTypResult(CBotTypPointer, "object");
-}
-
-// Instruction "retobject(rank)".
-
-bool rRetObject(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pObj;
- int rank;
-
- rank = var->GivValInt();
-
- pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, rank);
- if ( pObj == 0 )
- {
- result->SetPointer(0);
- }
- else
- {
- result->SetPointer(pObj->RetBotVar());
- }
- return true;
-}
-
-
-// Compilation of the instruction "search(type, pos)".
-
-CBotTypResult cSearch(CBotVar* &var, void* user)
-{
- CBotVar* array;
- CBotTypResult ret;
-
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() == CBotTypArrayPointer )
- {
- array = var->GivItemList();
- if ( array == 0 ) return CBotTypResult(CBotTypPointer);
- if ( array->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- }
- else if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
- if ( var != 0 )
- {
- ret = cPoint(var, user);
- if ( ret.GivType() != 0 ) return ret;
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
- }
-
- return CBotTypResult(CBotTypPointer, "object");
-}
-
-// Instruction "search(type, pos)".
-
-bool rSearch(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject *pObj, *pBest;
- CBotVar* array;
- Math::Vector pos, oPos;
- bool bNearest = false;
- bool bArray;
- float min, dist;
- int type, oType, i;
-
- if ( var->GivType() == CBotTypArrayPointer )
- {
- array = var->GivItemList();
- bArray = true;
- }
- else
- {
- type = var->GivValInt();
- bArray = false;
- }
- var = var->GivNext();
- if ( var != 0 )
- {
- if ( !GetPoint(var, exception, pos) ) return true;
- bNearest = true;
- }
-
- min = 100000.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( !pObj->RetActif() ) continue;
-
- oType = pObj->RetType();
- if ( oType == OBJECT_TOTO ) continue;
-
- if ( oType == OBJECT_RUINmobilew2 ||
- oType == OBJECT_RUINmobilet1 ||
- oType == OBJECT_RUINmobilet2 ||
- oType == OBJECT_RUINmobiler1 ||
- oType == OBJECT_RUINmobiler2 )
- {
- oType = OBJECT_RUINmobilew1; // any ruin
- }
-
- if ( oType == OBJECT_SCRAP2 ||
- oType == OBJECT_SCRAP3 ||
- oType == OBJECT_SCRAP4 ||
- oType == OBJECT_SCRAP5 ) // wastes?
- {
- oType = OBJECT_SCRAP1; // any waste
- }
-
- if ( oType == OBJECT_BARRIER2 ||
- oType == OBJECT_BARRIER3 ) // barriers?
- {
- oType = OBJECT_BARRIER1; // any barrier
- }
-
- if ( bArray )
- {
- if ( !FindList(array, oType) ) continue;
- }
- else
- {
- if ( type != oType && type != OBJECT_NULL ) continue;
- }
-
- if ( bNearest )
- {
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(pos, oPos);
- if ( dist < min )
- {
- min = dist;
- pBest = pObj;
- }
- }
- else
- {
- pBest = pObj;
- break;
- }
- }
-
- if ( pBest == 0 )
- {
- result->SetPointer(0);
- }
- else
- {
- result->SetPointer(pBest->RetBotVar());
- }
- return true;
-}
-
-
-// Compilation of instruction "radar(type, angle, focus, min, max, sens)".
-
-CBotTypResult cRadar(CBotVar* &var, void* user)
-{
- CBotVar* array;
-
- if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
- if ( var->GivType() == CBotTypArrayPointer )
- {
- array = var->GivItemList();
- if ( array == 0 ) return CBotTypResult(CBotTypPointer, "object");
- if ( array->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type
- }
- else if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type
- var = var->GivNext();
- if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // angle
- var = var->GivNext();
- if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // focus
- var = var->GivNext();
- if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // min
- var = var->GivNext();
- if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // max
- var = var->GivNext();
- if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // sense
- var = var->GivNext();
- if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // filter
- var = var->GivNext();
- if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
- return CBotTypResult(CBotErrOverParam);
-}
-
-// Instruction "radar(type, angle, focus, min, max, sens, filter)".
-
-bool rRadar(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pThis = (CObject*)user;
- CObject *pObj, *pBest;
- CPhysics* physics;
- CBotVar* array;
- Math::Vector iPos, oPos;
- RadarFilter filter;
- float best, minDist, maxDist, sens, iAngle, angle, focus, d, a;
- int type, oType, i;
- bool bArray;
-
- type = OBJECT_NULL;
- angle = 0.0f;
- focus = Math::PI*2.0f;
- minDist = 0.0f*g_unit;
- maxDist = 1000.0f*g_unit;
- sens = 1.0f;
- filter = FILTER_NONE;
-
- if ( var != 0 )
- {
- if ( var->GivType() == CBotTypArrayPointer )
- {
- array = var->GivItemList();
- bArray = true;
- }
- else
- {
- type = var->GivValInt();
- bArray = false;
- }
-
- var = var->GivNext();
- if ( var != 0 )
- {
- angle = -var->GivValFloat()*Math::PI/180.0f;
-
- var = var->GivNext();
- if ( var != 0 )
- {
- focus = var->GivValFloat()*Math::PI/180.0f;
-
- var = var->GivNext();
- if ( var != 0 )
- {
- minDist = var->GivValFloat()*g_unit;
-
- var = var->GivNext();
- if ( var != 0 )
- {
- maxDist = var->GivValFloat()*g_unit;
-
- var = var->GivNext();
- if ( var != 0 )
- {
- sens = var->GivValFloat();
-
- var = var->GivNext();
- if ( var != 0 )
- {
- filter = (RadarFilter)var->GivValInt();
- }
- }
- }
- }
- }
- }
- }
-
- iPos = pThis->RetPosition(0);
- iAngle = pThis->RetAngleY(0)+angle;
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- if ( sens >= 0.0f ) best = 100000.0f;
- else best = 0.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
- if ( pObj == pThis ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( !pObj->RetActif() ) continue;
- if ( pObj->RetProxyActivate() ) continue;
-
- oType = pObj->RetType();
- if ( oType == OBJECT_TOTO ) continue;
-
- if ( oType == OBJECT_RUINmobilew2 ||
- oType == OBJECT_RUINmobilet1 ||
- oType == OBJECT_RUINmobilet2 ||
- oType == OBJECT_RUINmobiler1 ||
- oType == OBJECT_RUINmobiler2 )
- {
- oType = OBJECT_RUINmobilew1; // any ruin
- }
-
- if ( oType == OBJECT_SCRAP2 ||
- oType == OBJECT_SCRAP3 ||
- oType == OBJECT_SCRAP4 ||
- oType == OBJECT_SCRAP5 ) // wastes?
- {
- oType = OBJECT_SCRAP1; // any waste
- }
-
- if ( oType == OBJECT_BARRIER2 ||
- oType == OBJECT_BARRIER3 ) // barriers?
- {
- oType = OBJECT_BARRIER1; // any barrier
- }
-
- if ( filter == FILTER_ONLYLANDING )
- {
- physics = pObj->RetPhysics();
- if ( physics != 0 && !physics->RetLand() ) continue;
- }
- if ( filter == FILTER_ONLYFLYING )
- {
- physics = pObj->RetPhysics();
- if ( physics != 0 && physics->RetLand() ) continue;
- }
-
- if ( bArray )
- {
- if ( !FindList(array, oType) ) continue;
- }
- else
- {
- if ( type != oType && type != OBJECT_NULL ) continue;
- }
-
- oPos = pObj->RetPosition(0);
- d = Math::DistanceProjected(iPos, oPos);
- if ( d < minDist || d > maxDist ) continue; // too close or too far?
-
- if ( focus >= Math::PI*2.0f )
- {
- if ( (sens >= 0.0f && d < best) ||
- (sens < 0.0f && d > best) )
- {
- best = d;
- pBest = pObj;
- }
- continue;
- }
-
- a = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( Math::TestAngle(a, iAngle-focus/2.0f, iAngle+focus/2.0f) )
- {
- if ( (sens >= 0.0f && d < best) ||
- (sens < 0.0f && d > best) )
- {
- best = d;
- pBest = pObj;
- }
- }
- }
-
- if ( pBest == 0 )
- {
- result->SetPointer(0);
- }
- else
- {
- result->SetPointer(pBest->RetBotVar());
- }
- return true;
-}
-
-
-// Monitoring a task.
-
-bool Process(CScript* script, CBotVar* result, int &exception)
-{
- Error err;
-
- err = script->m_primaryTask->IsEnded();
- if ( err != ERR_CONTINUE ) // task terminated?
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
-
- script->m_bContinue = false;
-
- if ( err == ERR_STOP ) err = ERR_OK;
- result->SetValInt(err); // indicates the error or ok
- if ( err != ERR_OK && script->m_errMode == ERM_STOP )
- {
- exception = err;
- return false;
- }
- return true; // it's all over
- }
-
- script->m_primaryTask->EventProcess(script->m_event);
- script->m_bContinue = true;
- return false; // not done
-}
-
-
-// Compilation of the instruction "detect(type)".
-
-CBotTypResult cDetect(CBotVar* &var, void* user)
-{
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
- return CBotTypResult(CBotTypBoolean);
-}
-
-// Instruction "detect(type)".
-
-bool rDetect(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pThis = (CObject*)user;
- CObject *pObj, *pGoal, *pBest;
- CPhysics* physics;
- CBotVar* array;
- Math::Vector iPos, oPos;
- RadarFilter filter;
- float bGoal, best, minDist, maxDist, sens, iAngle, angle, focus, d, a;
- int type, oType, i;
- bool bArray;
- Error err;
-
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- type = OBJECT_NULL;
- angle = 0.0f;
- focus = 45.0f*Math::PI/180.0f;
- minDist = 0.0f*g_unit;
- maxDist = 20.0f*g_unit;
- sens = 1.0f;
- filter = FILTER_NONE;
-
- if ( var != 0 )
- {
- if ( var->GivType() == CBotTypArrayPointer )
- {
- array = var->GivItemList();
- bArray = true;
- }
- else
- {
- type = var->GivValInt();
- bArray = false;
- }
- }
-
- iPos = pThis->RetPosition(0);
- iAngle = pThis->RetAngleY(0)+angle;
- iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
-
- bGoal = 100000.0f;
- pGoal = 0;
- if ( sens >= 0.0f ) best = 100000.0f;
- else best = 0.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
- if ( pObj == pThis ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( !pObj->RetActif() ) continue;
- if ( pObj->RetProxyActivate() ) continue;
-
- oType = pObj->RetType();
- if ( oType == OBJECT_TOTO ) continue;
-
- if ( oType == OBJECT_RUINmobilew2 ||
- oType == OBJECT_RUINmobilet1 ||
- oType == OBJECT_RUINmobilet2 ||
- oType == OBJECT_RUINmobiler1 ||
- oType == OBJECT_RUINmobiler2 )
- {
- oType = OBJECT_RUINmobilew1; // any ruin
- }
-
- if ( oType == OBJECT_SCRAP2 ||
- oType == OBJECT_SCRAP3 ||
- oType == OBJECT_SCRAP4 ||
- oType == OBJECT_SCRAP5 ) // wastes?
- {
- oType = OBJECT_SCRAP1; // any waste
- }
-
- if ( oType == OBJECT_BARRIER2 ||
- oType == OBJECT_BARRIER3 ) // barriers?
- {
- oType = OBJECT_BARRIER1; // any barrier
- }
-
- if ( filter == FILTER_ONLYLANDING )
- {
- physics = pObj->RetPhysics();
- if ( physics != 0 && !physics->RetLand() ) continue;
- }
- if ( filter == FILTER_ONLYFLYING )
- {
- physics = pObj->RetPhysics();
- if ( physics != 0 && physics->RetLand() ) continue;
- }
-
- if ( bArray )
- {
- if ( !FindList(array, oType) ) continue;
- }
- else
- {
- if ( type != oType && type != OBJECT_NULL ) continue;
- }
-
- oPos = pObj->RetPosition(0);
- d = Math::DistanceProjected(iPos, oPos);
- a = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
-
- if ( d < bGoal &&
- Math::TestAngle(a, iAngle-(5.0f*Math::PI/180.0f)/2.0f, iAngle+(5.0f*Math::PI/180.0f)/2.0f) )
- {
- bGoal = d;
- pGoal = pObj;
- }
-
- if ( d < minDist || d > maxDist ) continue; // too close or too far?
-
- if ( focus >= Math::PI*2.0f )
- {
- if ( (sens >= 0.0f && d < best) ||
- (sens < 0.0f && d > best) )
- {
- best = d;
- pBest = pObj;
- }
- continue;
- }
-
- if ( Math::TestAngle(a, iAngle-focus/2.0f, iAngle+focus/2.0f) )
- {
- if ( (sens >= 0.0f && d < best) ||
- (sens < 0.0f && d > best) )
- {
- best = d;
- pBest = pObj;
- }
- }
- }
-
- pThis->StartDetectEffect(pGoal, pBest!=0);
-
- if ( pBest == 0 )
- {
- script->m_returnValue = 0.0f;
- }
- else
- {
- script->m_returnValue = 1.0f;
- }
-
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
- err = script->m_primaryTask->StartTaskWait(0.3f);
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- if ( script->m_errMode == ERM_STOP )
- {
- exception = err;
- return false;
- }
- return true;
- }
- }
- if ( !Process(script, result, exception) ) return false; // not finished
- result->SetValFloat(script->m_returnValue);
- return true;
-}
-
-
-// Compilation of the instruction "direction(pos)".
-
-CBotTypResult cDirection(CBotVar* &var, void* user)
-{
- CBotTypResult ret;
-
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- ret = cPoint(var, user);
- if ( ret.GivType() != 0 ) return ret;
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
-
- return CBotTypResult(CBotTypFloat);
-}
-
-// Instruction "direction(pos)".
-
-bool rDirection(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pThis = (CObject*)user;
- Math::Vector iPos, oPos;
- float a, g;
-
- if ( !GetPoint(var, exception, oPos) ) return true;
-
- iPos = pThis->RetPosition(0);
-
- a = pThis->RetAngleY(0);
- g = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
-
- result->SetValFloat(-Math::Direction(a, g)*180.0f/Math::PI);
- return true;
-}
-
-
-// Compilation of the instruction "produce(pos, angle, type, scriptName)".
-
-CBotTypResult cProduce(CBotVar* &var, void* user)
-{
- CBotTypResult ret;
-
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- ret = cPoint(var, user);
- if ( ret.GivType() != 0 ) return ret;
-
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
- var = var->GivNext();
-
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
-
- return CBotTypResult(CBotTypFloat);
-}
-
-// Instruction "produce(pos, angle, type, scriptName)".
-
-bool rProduce(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* object;
- CBotString cbs;
- const char* name;
- Math::Vector pos;
- float angle;
- ObjectType type;
-
- if ( !GetPoint(var, exception, pos) ) return true;
-
- angle = var->GivValFloat()*Math::PI/180.0f;
- var = var->GivNext();
-
- type = (ObjectType)var->GivValInt();
- var = var->GivNext();
-
- cbs = var->GivValString();
- name = cbs;
-
- if ( type == OBJECT_FRET ||
- type == OBJECT_STONE ||
- type == OBJECT_URANIUM ||
- type == OBJECT_METAL ||
- type == OBJECT_POWER ||
- type == OBJECT_ATOMIC ||
- type == OBJECT_BULLET ||
- type == OBJECT_BBOX ||
- type == OBJECT_KEYa ||
- type == OBJECT_KEYb ||
- type == OBJECT_KEYc ||
- type == OBJECT_KEYd ||
- type == OBJECT_TNT ||
- type == OBJECT_SCRAP1 ||
- type == OBJECT_SCRAP2 ||
- type == OBJECT_SCRAP3 ||
- type == OBJECT_SCRAP4 ||
- type == OBJECT_SCRAP5 ||
- type == OBJECT_BOMB ||
- type == OBJECT_WAYPOINT ||
- type == OBJECT_SHOW ||
- type == OBJECT_WINFIRE )
- {
- object = new CObject(script->m_iMan);
- if ( !object->CreateResource(pos, angle, type) )
- {
- delete object;
- result->SetValInt(1); // error
- return true;
- }
- }
- else
- if ( type == OBJECT_MOTHER ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM )
- {
- CObject* egg;
-
- object = new CObject(script->m_iMan);
- if ( !object->CreateInsect(pos, angle, type) )
- {
- delete object;
- result->SetValInt(1); // error
- return true;
- }
-
- egg = new CObject(script->m_iMan);
- if ( !egg->CreateResource(pos, angle, OBJECT_EGG, 0.0f) )
- {
- delete egg;
- }
- }
- else
- {
- result->SetValInt(1); // impossible
- return true;
- }
- object->SetActivity(false);
- object->ReadProgram(0, (char*)name);
- object->RunProgram(0);
-
- result->SetValInt(0); // no error
- return true;
-}
-
-
-// Compilation of the instruction "distance(p1, p2)".
-
-CBotTypResult cDistance(CBotVar* &var, void* user)
-{
- CBotTypResult ret;
-
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- ret = cPoint(var, user);
- if ( ret.GivType() != 0 ) return ret;
-
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- ret = cPoint(var, user);
- if ( ret.GivType() != 0 ) return ret;
-
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
-
- return CBotTypResult(CBotTypFloat);
-}
-
-// Instruction "distance(p1, p2)".
-
-bool rDistance(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- Math::Vector p1, p2;
- float value;
-
- if ( !GetPoint(var, exception, p1) ) return true;
- if ( !GetPoint(var, exception, p2) ) return true;
-
- value = Math::Distance(p1, p2);
- result->SetValFloat(value/g_unit);
- return true;
-}
-
-// Instruction "distance2d(p1, p2)".
-
-bool rDistance2d(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- Math::Vector p1, p2;
- float value;
-
- if ( !GetPoint(var, exception, p1) ) return true;
- if ( !GetPoint(var, exception, p2) ) return true;
-
- value = Math::DistanceProjected(p1, p2);
- result->SetValFloat(value/g_unit);
- return true;
-}
-
-
-// Compilation of the instruction "space(center, rMin, rMax, dist)".
-
-CBotTypResult cSpace(CBotVar* &var, void* user)
-{
- CBotTypResult ret;
-
- if ( var == 0 ) return CBotTypResult(CBotTypIntrinsic, "point");
- ret = cPoint(var, user);
- if ( ret.GivType() != 0 ) return ret;
-
- if ( var == 0 ) return CBotTypResult(CBotTypIntrinsic, "point");
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotTypIntrinsic, "point");
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotTypIntrinsic, "point");
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
- return CBotTypResult(CBotTypIntrinsic, "point");
-}
-
-// Instruction "space(center, rMin, rMax, dist)".
-
-bool rSpace(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pThis = (CObject*)user;
- CBotVar* pSub;
- Math::Vector center;
- float rMin, rMax, dist;
-
- rMin = 10.0f*g_unit;
- rMax = 50.0f*g_unit;
- dist = 4.0f*g_unit;
-
- if ( var == 0 )
- {
- center = pThis->RetPosition(0);
- }
- else
- {
- if ( !GetPoint(var, exception, center) ) return true;
-
- if ( var != 0 )
- {
- rMin = var->GivValFloat()*g_unit;
- var = var->GivNext();
-
- if ( var != 0 )
- {
- rMax = var->GivValFloat()*g_unit;
- var = var->GivNext();
-
- if ( var != 0 )
- {
- dist = var->GivValFloat()*g_unit;
- var = var->GivNext();
- }
- }
- }
- }
- script->m_main->FreeSpace(center, rMin, rMax, dist, pThis);
-
- if ( result != 0 )
- {
- pSub = result->GivItemList();
- if ( pSub != 0 )
- {
- pSub->SetValFloat(center.x/g_unit);
- pSub = pSub->GivNext(); // "y"
- pSub->SetValFloat(center.z/g_unit);
- pSub = pSub->GivNext(); // "z"
- pSub->SetValFloat(center.y/g_unit);
- }
- }
- return true;
-}
-
-
-// Compilation of the instruction "flatground(center, rMax)".
-
-CBotTypResult cFlatGround(CBotVar* &var, void* user)
-{
- CBotTypResult ret;
-
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- ret = cPoint(var, user);
- if ( ret.GivType() != 0 ) return ret;
-
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
-
- return CBotTypResult(CBotTypFloat);
-}
-
-// Instruction "flatground(center, rMax)".
-
-bool rFlatGround(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pThis = (CObject*)user;
- Math::Vector center;
- float rMax, dist;
-
- if ( !GetPoint(var, exception, center) ) return true;
- rMax = var->GivValFloat()*g_unit;
- var = var->GivNext();
-
- dist = script->m_main->RetFlatZoneRadius(center, rMax, pThis);
- result->SetValFloat(dist/g_unit);
-
- return true;
-}
-
-
-// Instruction "wait(t)".
-
-bool rWait(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- float value;
- Error err;
-
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
- value = var->GivValFloat();
- err = script->m_primaryTask->StartTaskWait(value);
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- if ( script->m_errMode == ERM_STOP )
- {
- exception = err;
- return false;
- }
- return true;
- }
- }
- return Process(script, result, exception);
-}
-
-// Instruction "move(dist)".
-
-bool rMove(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- float value;
- Error err;
-
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
- value = var->GivValFloat();
- err = script->m_primaryTask->StartTaskAdvance(value*g_unit);
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- if ( script->m_errMode == ERM_STOP )
- {
- exception = err;
- return false;
- }
- return true;
- }
- }
- return Process(script, result, exception);
-}
-
-// Instruction "turn(angle)".
-
-bool rTurn(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- float value;
- Error err;
-
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
- value = var->GivValFloat();
- err = script->m_primaryTask->StartTaskTurn(-value*Math::PI/180.0f);
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- if ( script->m_errMode == ERM_STOP )
- {
- exception = err;
- return false;
- }
- return true;
- }
- }
- return Process(script, result, exception);
-}
-
-// Compilation of the instruction "goto(pos, altitude, crash, goal)".
-
-CBotTypResult cGoto(CBotVar* &var, void* user)
-{
- CBotTypResult ret;
-
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- ret = cPoint(var, user);
- if ( ret.GivType() != 0 ) return ret;
-
- if ( var == 0 ) return CBotTypResult(CBotTypFloat);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotTypFloat);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotTypFloat);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotTypFloat);
- return CBotTypResult(CBotErrOverParam);
-}
-
-// Instruction "goto(pos, altitude, mode)".
-
-bool rGoto(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- Math::Vector pos;
- TaskGotoGoal goal;
- TaskGotoCrash crash;
- float altitude;
- Error err;
-
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
- if ( !GetPoint(var, exception, pos) ) return true;
-
- goal = TGG_DEFAULT;
- crash = TGC_DEFAULT;
- altitude = 0.0f*g_unit;
-
- if ( var != 0 )
- {
- altitude = var->GivValFloat()*g_unit;
-
- var = var->GivNext();
- if ( var != 0 )
- {
- goal = (TaskGotoGoal)var->GivValInt();
-
- var = var->GivNext();
- if ( var != 0 )
- {
- crash = (TaskGotoCrash)var->GivValInt();
- }
- }
- }
-
- err = script->m_primaryTask->StartTaskGoto(pos, altitude, goal, crash);
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- if ( script->m_errMode == ERM_STOP )
- {
- exception = err;
- return false;
- }
- return true;
- }
- }
- return Process(script, result, exception);
-}
-
-// Instruction "find(type)".
-
-bool rFind(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- Math::Vector pos;
- TaskGotoGoal goal;
- TaskGotoCrash crash;
- float altitude;
- Error err;
- CObject* pThis = (CObject*)user;
- CObject *pObj, *pBest;
- CBotVar* array;
- Math::Vector iPos, oPos;
- float best, minDist, maxDist, sens, iAngle, angle, focus, d, a;
- int type, oType, i;
- bool bArray;
-
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- type = OBJECT_NULL;
- angle = 0.0f;
- focus = Math::PI*2.0f;
- minDist = 0.0f*g_unit;
- maxDist = 1000.0f*g_unit;
- sens = 1.0f;
-
- if ( var->GivType() == CBotTypArrayPointer )
- {
- array = var->GivItemList();
- bArray = true;
- }
- else
- {
- type = var->GivValInt();
- bArray = false;
- }
-
- best = 100000.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
- if ( pObj == pThis ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
- if ( !pObj->RetActif() ) continue;
- if ( pObj->RetProxyActivate() ) continue;
-
- oType = pObj->RetType();
- if ( oType == OBJECT_TOTO ) continue;
-
- if ( oType == OBJECT_RUINmobilew2 ||
- oType == OBJECT_RUINmobilet1 ||
- oType == OBJECT_RUINmobilet2 ||
- oType == OBJECT_RUINmobiler1 ||
- oType == OBJECT_RUINmobiler2 )
- {
- oType = OBJECT_RUINmobilew1; // any ruin
- }
-
- if ( oType == OBJECT_SCRAP2 ||
- oType == OBJECT_SCRAP3 ||
- oType == OBJECT_SCRAP4 ||
- oType == OBJECT_SCRAP5 ) // wastes?
- {
- oType = OBJECT_SCRAP1; // any waste
- }
-
- if ( oType == OBJECT_BARRIER2 ||
- oType == OBJECT_BARRIER3 ) // barriers?
- {
- oType = OBJECT_BARRIER1; // any barrier
- }
-
- if ( bArray )
- {
- if ( !FindList(array, oType) ) continue;
- }
- else
- {
- if ( type != oType && type != OBJECT_NULL ) continue;
- }
-
- oPos = pObj->RetPosition(0);
- d = Math::DistanceProjected(iPos, oPos);
- if ( d < minDist || d > maxDist ) continue; // too close or too far?
-
- if ( focus >= Math::PI*2.0f )
- {
- if ( d < best )
- {
- best = d;
- pBest = pObj;
- }
- continue;
- }
-
- a = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
- if ( Math::TestAngle(a, iAngle-focus/2.0f, iAngle+focus/2.0f) )
- {
- if ( d < best )
- {
- best = d;
- pBest = pObj;
- }
- }
- }
-
- if ( pBest == 0 )
- {
- exception = ERR_FIND_IMPOSSIBLE;
- return false;
- }
-
- pos = pBest->RetPosition(0);
- goal = TGG_DEFAULT;
- crash = TGC_DEFAULT;
- altitude = 0.0f*g_unit;
-
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
- err = script->m_primaryTask->StartTaskGoto(pos, altitude, goal, crash);
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- if ( script->m_errMode == ERM_STOP )
- {
- exception = err;
- return false;
- }
- return true;
- }
- }
- return Process(script, result, exception);
-}
-
-// Compilation "grab/drop(oper)".
-
-CBotTypResult cGrabDrop(CBotVar* &var, void* user)
-{
- if ( var == 0 ) return CBotTypResult(CBotTypFloat);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
- return CBotTypResult(CBotTypFloat);
-}
-
-// Instruction "grab(oper)".
-
-bool rGrab(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pThis = (CObject*)user;
- ObjectType oType;
- TaskManipArm type;
- Error err;
-
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
- if ( var == 0 ) type = TMA_FFRONT;
- else type = (TaskManipArm)var->GivValInt();
-
- oType = pThis->RetType();
- if ( oType == OBJECT_HUMAN ||
- oType == OBJECT_TECH )
- {
- err = script->m_primaryTask->StartTaskTake();
- }
- else
- {
- err = script->m_primaryTask->StartTaskManip(TMO_GRAB, type);
- }
-
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- if ( script->m_errMode == ERM_STOP )
- {
- exception = err;
- return false;
- }
- return true;
- }
- }
- return Process(script, result, exception);
-}
-
-// Instruction "drop(oper)".
-
-bool rDrop(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pThis = (CObject*)user;
- ObjectType oType;
- TaskManipArm type;
- Error err;
-
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
- if ( var == 0 ) type = TMA_FFRONT;
- else type = (TaskManipArm)var->GivValInt();
-
- oType = pThis->RetType();
- if ( oType == OBJECT_HUMAN ||
- oType == OBJECT_TECH )
- {
- err = script->m_primaryTask->StartTaskTake();
- }
- else
- {
- err = script->m_primaryTask->StartTaskManip(TMO_DROP, type);
- }
-
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- if ( script->m_errMode == ERM_STOP )
- {
- exception = err;
- return false;
- }
- return true;
- }
- }
- return Process(script, result, exception);
-}
-
-// Instruction "sniff()".
-
-bool rSniff(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- Error err;
-
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
- err = script->m_primaryTask->StartTaskSearch();
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- if ( script->m_errMode == ERM_STOP )
- {
- exception = err;
- return false;
- }
- return true;
- }
- }
- return Process(script, result, exception);
-}
-
-// Compilation of the instruction "receive(nom, power)".
-
-CBotTypResult cReceive(CBotVar* &var, void* user)
-{
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotTypFloat);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
- return CBotTypResult(CBotTypFloat);
-}
-
-// Instruction "receive(nom, power)".
-
-bool rReceive(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pThis = (CObject*)user;
- CBotString cbs;
- Error err;
- const char* p;
- float value, power;
-
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
-
- cbs = var->GivValString();
- p = cbs;
- var = var->GivNext();
-
- power = 10.0f*g_unit;
- if ( var != 0 )
- {
- power = var->GivValFloat()*g_unit;
- var = var->GivNext();
- }
-
- err = script->m_primaryTask->StartTaskInfo((char*)p, 0.0f, power, false);
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetInit(IS_NAN);
- return true;
- }
- }
- if ( !Process(script, result, exception) ) return false; // not finished
-
- value = pThis->RetInfoReturn();
- if ( value == NAN )
- {
- result->SetInit(IS_NAN);
- }
- else
- {
- result->SetValFloat(value);
- }
- return true;
-}
-
-// Compilation of the instruction "send(nom, value, power)".
-
-CBotTypResult cSend(CBotVar* &var, void* user)
-{
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotTypFloat);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
- return CBotTypResult(CBotTypFloat);
-}
-
-// Instruction "send(nom, value, power)".
-
-bool rSend(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pThis = (CObject*)user;
- CBotString cbs;
- Error err;
- const char* p;
- float value, power;
-
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
-
- cbs = var->GivValString();
- p = cbs;
- var = var->GivNext();
-
- value = var->GivValFloat();
- var = var->GivNext();
-
- power = 10.0f*g_unit;
- if ( var != 0 )
- {
- power = var->GivValFloat()*g_unit;
- var = var->GivNext();
- }
-
- err = script->m_primaryTask->StartTaskInfo((char*)p, value, power, true);
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- if ( script->m_errMode == ERM_STOP )
- {
- exception = err;
- return false;
- }
- return true;
- }
- }
- return Process(script, result, exception);
-}
-
-// Seeks the nearest information terminal.
-
-CObject* SearchInfo(CScript* script, CObject* object, float power)
-{
- CObject *pObj, *pBest;
- Math::Vector iPos, oPos;
- ObjectType type;
- float dist, min;
- int i;
-
- iPos = object->RetPosition(0);
-
- min = 100000.0f;
- pBest = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type != OBJECT_INFO ) continue;
-
- if ( !pObj->RetActif() ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::Distance(oPos, iPos);
- if ( dist > power ) continue; // too far?
- if ( dist < min )
- {
- min = dist;
- pBest = pObj;
- }
- }
-
- return pBest;
-}
-
-// Compilation of the instruction "deleteinfo(nom, power)".
-
-CBotTypResult cDeleteInfo(CBotVar* &var, void* user)
-{
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotTypFloat);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
- return CBotTypResult(CBotTypFloat);
-}
-
-// Instruction "deleteinfo(nom, power)".
-
-bool rDeleteInfo(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pThis = (CObject*)user;
- CObject* pInfo;
- CBotString cbs;
- Info info;
- const char* p;
- float power;
- int i, total;
-
- exception = 0;
-
- cbs = var->GivValString();
- p = cbs;
- var = var->GivNext();
-
- power = 10.0f*g_unit;
- if ( var != 0 )
- {
- power = var->GivValFloat()*g_unit;
- var = var->GivNext();
- }
-
- pInfo = SearchInfo(script, pThis, power);
- if ( pInfo == 0 )
- {
- result->SetValFloat(0.0f); // false
- return true;
- }
-
- total = pInfo->RetInfoTotal();
- for ( i=0 ; i<total ; i++ )
- {
- info = pInfo->RetInfo(i);
- if ( strcmp(info.name, p) == 0 )
- {
- pInfo->DeleteInfo(i);
- result->SetValFloat(1.0f); // true
- return true;
- }
- }
- result->SetValFloat(0.0f); // false
- return true;
-}
-
-// Compilation of the instruction "testinfo(nom, power)".
-
-CBotTypResult cTestInfo(CBotVar* &var, void* user)
-{
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotTypBoolean);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
- return CBotTypResult(CBotTypBoolean);
-}
-
-// Instruction "testinfo(nom, power)".
-
-bool rTestInfo(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pThis = (CObject*)user;
- CObject* pInfo;
- CBotString cbs;
- Info info;
- const char* p;
- float power;
- int i, total;
-
- exception = 0;
-
- cbs = var->GivValString();
- p = cbs;
- var = var->GivNext();
-
- power = 10.0f*g_unit;
- if ( var != 0 )
- {
- power = var->GivValFloat()*g_unit;
- var = var->GivNext();
- }
-
- pInfo = SearchInfo(script, pThis, power);
- if ( pInfo == 0 )
- {
- result->SetValInt(false);
- return true;
- }
-
- total = pInfo->RetInfoTotal();
- for ( i=0 ; i<total ; i++ )
- {
- info = pInfo->RetInfo(i);
- if ( strcmp(info.name, p) == 0 )
- {
- result->SetValInt(true);
- return true;
- }
- }
- result->SetValInt(false);
- return true;
-}
-
-// Instruction "thump()".
-
-bool rThump(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- Error err;
-
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
- err = script->m_primaryTask->StartTaskTerraform();
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- if ( script->m_errMode == ERM_STOP )
- {
- exception = err;
- return false;
- }
- return true;
- }
- }
- return Process(script, result, exception);
-}
-
-// Instruction "recycle()".
-
-bool rRecycle(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- Error err;
-
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
- err = script->m_primaryTask->StartTaskRecover();
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- if ( script->m_errMode == ERM_STOP )
- {
- exception = err;
- return false;
- }
- return true;
- }
- }
- return Process(script, result, exception);
-}
-
-// Compilation "shield(oper, radius)".
-
-CBotTypResult cShield(CBotVar* &var, void* user)
-{
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
-
- return CBotTypResult(CBotTypFloat);
-}
-
-// Instruction "shield(oper, radius)".
-
-bool rShield(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pThis = (CObject*)user;
- float oper, radius;
- Error err;
-
- oper = var->GivValFloat(); // 0=down, 1=up
- var = var->GivNext();
-
- radius = var->GivValFloat();
- if ( radius < 10.0f ) radius = 10.0f;
- if ( radius > 25.0f ) radius = 25.0f;
- radius = (radius-10.0f)/15.0f;
-
- if ( *script->m_secondaryTask == 0 ) // shield folds?
- {
- if ( oper == 0.0f ) // down?
- {
- result->SetValInt(1); // shows the error
- }
- else // up ?
- {
- pThis->SetParam(radius);
-
- *script->m_secondaryTask = new CTaskManager(script->m_iMan, script->m_object);
- err = (*script->m_secondaryTask)->StartTaskShield(TSM_UP, 1000.0f);
- if ( err != ERR_OK )
- {
- delete *script->m_secondaryTask;
- *script->m_secondaryTask = 0;
- result->SetValInt(err); // shows the error
- }
- }
- }
- else // shield deployed?
- {
- if ( oper == 0.0f ) // down?
- {
- (*script->m_secondaryTask)->StartTaskShield(TSM_DOWN, 0.0f);
- }
- else // up?
- {
-//? result->SetValInt(1); // shows the error
- pThis->SetParam(radius);
- (*script->m_secondaryTask)->StartTaskShield(TSM_UPDATE, 0.0f);
- }
- }
-
- return true;
-}
-
-// Compilation "fire(delay)".
-
-CBotTypResult cFire(CBotVar* &var, void* user)
-{
-#if 0
- CObject* pThis = (CObject*)user;
- ObjectType type;
-
- type = pThis->RetType();
-
- if ( type == OBJECT_ANT )
- {
- return cOnePoint(var, user);
- }
- else if ( type == OBJECT_SPIDER )
- {
- return cNull(var, user);
- }
- else
- {
- if ( var == 0 ) return CBotTypResult(CBotTypFloat);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
- return CBotTypResult(CBotTypFloat);
- }
-#else
- return CBotTypResult(CBotTypFloat);
-#endif
-}
-
-// Instruction "fire(delay)".
-
-bool rFire(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pThis = (CObject*)user;
- float delay;
- Math::Vector impact;
- Error err;
- ObjectType type;
-
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
-
- type = pThis->RetType();
-
- if ( type == OBJECT_ANT )
- {
- if ( !GetPoint(var, exception, impact) ) return true;
- impact.y += pThis->RetWaterLevel();
- err = script->m_primaryTask->StartTaskFireAnt(impact);
- }
- else if ( type == OBJECT_SPIDER )
- {
- err = script->m_primaryTask->StartTaskSpiderExplo();
- }
- else
- {
- if ( var == 0 ) delay = 0.0f;
- else delay = var->GivValFloat();
- err = script->m_primaryTask->StartTaskFire(delay);
- }
-
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- return true;
- }
- }
- return Process(script, result, exception);
-}
-
-// Instruction "aim(dir)".
-
-bool rAim(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- float value;
- Error err;
-
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
- value = var->GivValFloat();
- err = script->m_primaryTask->StartTaskGunGoal(value*Math::PI/180.0f, 0.0f);
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- return true;
- }
- }
- return Process(script, result, exception);
-}
-
-// Compilation of the instruction "motor(left, right)".
-
-CBotTypResult cMotor(CBotVar* &var, void* user)
-{
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
-
- return CBotTypResult(CBotTypFloat);
-}
-
-// Instruction "motor(left, right)".
-
-bool rMotor(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CObject* pThis = (CObject*)user;
- CPhysics* physics = ((CObject*)user)->RetPhysics();
- float left, right, speed, turn;
-
- left = var->GivValFloat();
- var = var->GivNext();
- right = var->GivValFloat();
-
- speed = (left+right)/2.0f;
- if ( speed < -1.0f ) speed = -1.0f;
- if ( speed > 1.0f ) speed = 1.0f;
-
- turn = left-right;
- if ( turn < -1.0f ) turn = -1.0f;
- if ( turn > 1.0f ) turn = 1.0f;
-
- if ( pThis->RetFixed() ) // ant on the back?
- {
- speed = 0.0f;
- turn = 0.0f;
- }
-
- physics->SetMotorSpeedX(speed); // forward/backward
- physics->SetMotorSpeedZ(turn); // turns
-
- return true;
-}
-
-// Instruction "jet(power)".
-
-bool rJet(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CPhysics* physics = ((CObject*)user)->RetPhysics();
- float value;
-
- value = var->GivValFloat();
- physics->SetMotorSpeedY(value);
-
- return true;
-}
-
-// Compilation of the instruction "topo(pos)".
-
-CBotTypResult cTopo(CBotVar* &var, void* user)
-{
- CBotTypResult ret;
-
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- ret = cPoint(var, user);
- if ( ret.GivType() != 0 ) return ret;
-
- if ( var == 0 ) return CBotTypResult(CBotTypFloat);
- return CBotTypResult(CBotErrOverParam);
-}
-
-// Instruction "topo(pos)".
-
-bool rTopo(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- Math::Vector pos;
- float level;
-
- exception = 0;
-
- if ( !GetPoint(var, exception, pos) ) return true;
-
- level = script->m_terrain->RetFloorLevel(pos);
- level -= script->m_water->RetLevel();
- result->SetValFloat(level/g_unit);
- return true;
-}
-
-// Compilation of the instruction "message(string, type)".
-
-CBotTypResult cMessage(CBotVar* &var, void* user)
-{
- if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
- if ( var->GivType() != CBotTypString &&
- var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotTypFloat);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotTypFloat);
- return CBotTypResult(CBotErrOverParam);
-}
-
-// Instruction "message(string, type)".
-
-bool rMessage(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CBotString cbs;
- const char* p;
- TextType type;
-
- cbs = var->GivValString();
- p = cbs;
-
- type = TT_MESSAGE;
- var = var->GivNext();
- if ( var != 0 )
- {
- type = (TextType)var->GivValInt();
- }
-
- script->m_displayText->DisplayText((char*)p, script->m_object, 10.0f, type);
- script->m_main->CheckEndMessage((char*)p);
-
- return true;
-}
-
-// Instruction "cmdline(rank)".
-
-bool rCmdline(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pThis = (CObject*)user;
- float value;
- int rank;
-
- rank = var->GivValInt();
- value = pThis->RetCmdLine(rank);
- result->SetValFloat(value);
-
- return true;
-}
-
-// Instruction "ismovie()".
-
-bool rIsMovie(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- float value;
-
- value = script->m_main->RetMovieLock()?1.0f:0.0f;
- result->SetValFloat(value);
-
- return true;
-}
-
-// Instruction "errmode(mode)".
-
-bool rErrMode(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- int value;
-
- value = var->GivValInt();
- if ( value < 0 ) value = 0;
- if ( value > 1 ) value = 1;
- script->m_errMode = value;
-
- return true;
-}
-
-// Instruction "ipf(num)".
-
-bool rIPF(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- int value;
-
- value = var->GivValInt();
- if ( value < 1 ) value = 1;
- if ( value > 10000 ) value = 10000;
- script->m_ipf = value;
-
- return true;
-}
-
-// Instruction "abstime()".
-
-bool rAbsTime(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- float value;
-
- value = script->m_main->RetGameTime();
- result->SetValFloat(value);
- return true;
-}
-
-
-// Prepares a file name.
-
-void PrepareFilename(CBotString &filename, char *dir)
-{
- int pos;
-
- pos = filename.ReverseFind('\\');
- if ( pos > 0 )
- {
- filename = filename.Mid(pos+1); // removes folders
- }
-
- pos = filename.ReverseFind('/');
- if ( pos > 0 )
- {
- filename = filename.Mid(pos+1); // also those with /
- }
-
- pos = filename.ReverseFind(':');
- if ( pos > 0 )
- {
- filename = filename.Mid(pos+1); // also removes the drive letter C:
- }
-
- filename = CBotString(dir) + CBotString("\\") + filename;
-}
-
-// Instruction "deletefile(filename)".
-
-bool rDeleteFile(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CBotString cbs;
- const char* p;
- char* dir;
-
- cbs = var->GivValString();
- dir = script->m_main->RetFilesDir();
- PrepareFilename(cbs, dir);
- p = cbs;
- DeleteFile(p);
-
- return true;
-}
-
-// Compilation of the instruction "pendown(color, width)".
-
-CBotTypResult cPenDown(CBotVar* &var, void* user)
-{
- if ( var == 0 ) return CBotTypResult(CBotTypFloat);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotTypFloat);
- if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
- var = var->GivNext();
-
- if ( var == 0 ) return CBotTypResult(CBotTypFloat);
- return CBotTypResult(CBotErrOverParam);
-}
-
-// Instruction "pendown(color, width)".
-
-bool rPenDown(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pThis = (CObject*)user;
- int color;
- float width;
- Error err;
-
- if ( pThis->RetType() == OBJECT_MOBILEdr )
- {
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- if ( var != 0 )
- {
- color = var->GivValInt();
- if ( color < 0 ) color = 0;
- if ( color > 17 ) color = 17;
- pThis->SetTraceColor(color);
-
- var = var->GivNext();
- if ( var != 0 )
- {
- width = var->GivValFloat();
- if ( width < 0.1f ) width = 0.1f;
- if ( width > 1.0f ) width = 1.0f;
- pThis->SetTraceWidth(width);
- }
- }
- pThis->SetTraceDown(true);
-
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
- err = script->m_primaryTask->StartTaskPen(pThis->RetTraceDown(), pThis->RetTraceColor());
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- if ( script->m_errMode == ERM_STOP )
- {
- exception = err;
- return false;
- }
- return true;
- }
- }
- return Process(script, result, exception);
- }
- else
- {
- if ( var != 0 )
- {
- color = var->GivValInt();
- if ( color < 0 ) color = 0;
- if ( color > 17 ) color = 17;
- pThis->SetTraceColor(color);
-
- var = var->GivNext();
- if ( var != 0 )
- {
- width = var->GivValFloat();
- if ( width < 0.1f ) width = 0.1f;
- if ( width > 1.0f ) width = 1.0f;
- pThis->SetTraceWidth(width);
- }
- }
- pThis->SetTraceDown(true);
-
- return true;
- }
-}
-
-// Instruction "penup()".
-
-bool rPenUp(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CObject* pThis = (CObject*)user;
- Error err;
-
- if ( pThis->RetType() == OBJECT_MOBILEdr )
- {
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- pThis->SetTraceDown(false);
-
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
- err = script->m_primaryTask->StartTaskPen(pThis->RetTraceDown(), pThis->RetTraceColor());
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- if ( script->m_errMode == ERM_STOP )
- {
- exception = err;
- return false;
- }
- return true;
- }
- }
- return Process(script, result, exception);
- }
- else
- {
- pThis->SetTraceDown(false);
- return true;
- }
-}
-
-// Instruction "pencolor()".
-
-bool rPenColor(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CScript* script = ((CObject*)user)->RetRunScript();
- CPhysics* physics = ((CObject*)user)->RetPhysics();
- CObject* pThis = (CObject*)user;
- int color;
- Error err;
-
- if ( pThis->RetType() == OBJECT_MOBILEdr )
- {
- exception = 0;
-
- if ( script->m_primaryTask == 0 ) // no task in progress?
- {
- color = var->GivValInt();
- if ( color < 0 ) color = 0;
- if ( color > 17 ) color = 17;
- pThis->SetTraceColor(color);
-
- script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
- err = script->m_primaryTask->StartTaskPen(pThis->RetTraceDown(), pThis->RetTraceColor());
- if ( err != ERR_OK )
- {
- delete script->m_primaryTask;
- script->m_primaryTask = 0;
- result->SetValInt(err); // shows the error
- if ( script->m_errMode == ERM_STOP )
- {
- exception = err;
- return false;
- }
- return true;
- }
- }
- return Process(script, result, exception);
- }
- else
- {
- color = var->GivValInt();
- if ( color < 0 ) color = 0;
- if ( color > 17 ) color = 17;
- pThis->SetTraceColor(color);
-
- return true;
- }
-}
-
-// Instruction "penwidth()".
-
-bool rPenWidth(CBotVar* var, CBotVar* result, int& exception, void* user)
-{
- CObject* pThis = (CObject*)user;
- float width;
-
- width = var->GivValFloat();
- if ( width < 0.1f ) width = 0.1f;
- if ( width > 1.0f ) width = 1.0f;
- pThis->SetTraceWidth(width);
- return true;
-}
-
-
-
-// Object's constructor.
-
-CScript::CScript(CInstanceManager* iMan, CObject* object, CTaskManager** secondaryTask)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_SCRIPT, this, 100);
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
- m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
- m_botProg = 0;
- m_object = object;
- m_primaryTask = 0;
- m_secondaryTask = secondaryTask;
-
- m_ipf = CBOT_IPF;
- m_errMode = ERM_STOP;
- m_len = 0;
- m_script = 0;
- m_bRun = false;
- m_bStepMode = false;
- m_bCompile = false;
- m_title[0] = 0;
- m_cursor1 = 0;
- m_cursor2 = 0;
- m_filename[0] = 0;
-}
-
-// Initializes all functions for module CBOT.
-
-void CScript::InitFonctions()
-{
- CBotProgram::AddFunction("sin", rSin, cOneFloat);
- CBotProgram::AddFunction("cos", rCos, cOneFloat);
- CBotProgram::AddFunction("tan", rTan, cOneFloat);
- CBotProgram::AddFunction("asin", raSin, cOneFloat);
- CBotProgram::AddFunction("acos", raCos, cOneFloat);
- CBotProgram::AddFunction("atan", raTan, cOneFloat);
- CBotProgram::AddFunction("sqrt", rSqrt, cOneFloat);
- CBotProgram::AddFunction("pow", rPow, cTwoFloat);
- CBotProgram::AddFunction("rand", rRand, cNull);
- CBotProgram::AddFunction("abs", rAbs, cOneFloat);
-
- CBotProgram::AddFunction("retobject", rRetObject, cRetObject);
- CBotProgram::AddFunction("search", rSearch, cSearch);
- CBotProgram::AddFunction("radar", rRadar, cRadar);
- CBotProgram::AddFunction("detect", rDetect, cDetect);
- CBotProgram::AddFunction("direction", rDirection, cDirection);
- CBotProgram::AddFunction("produce", rProduce, cProduce);
- CBotProgram::AddFunction("distance", rDistance, cDistance);
- CBotProgram::AddFunction("distance2d",rDistance2d,cDistance);
- CBotProgram::AddFunction("space", rSpace, cSpace);
- CBotProgram::AddFunction("flatground",rFlatGround,cFlatGround);
- CBotProgram::AddFunction("wait", rWait, cOneFloat);
- CBotProgram::AddFunction("move", rMove, cOneFloat);
- CBotProgram::AddFunction("turn", rTurn, cOneFloat);
- CBotProgram::AddFunction("goto", rGoto, cGoto);
- CBotProgram::AddFunction("find", rFind, cOneFloat);
- CBotProgram::AddFunction("grab", rGrab, cGrabDrop);
- CBotProgram::AddFunction("drop", rDrop, cGrabDrop);
- CBotProgram::AddFunction("sniff", rSniff, cNull);
- CBotProgram::AddFunction("receive", rReceive, cReceive);
- CBotProgram::AddFunction("send", rSend, cSend);
- CBotProgram::AddFunction("deleteinfo",rDeleteInfo,cDeleteInfo);
- CBotProgram::AddFunction("testinfo", rTestInfo, cTestInfo);
- CBotProgram::AddFunction("thump", rThump, cNull);
- CBotProgram::AddFunction("recycle", rRecycle, cNull);
- CBotProgram::AddFunction("shield", rShield, cShield);
- CBotProgram::AddFunction("fire", rFire, cFire);
- CBotProgram::AddFunction("aim", rAim, cOneFloat);
- CBotProgram::AddFunction("motor", rMotor, cMotor);
- CBotProgram::AddFunction("jet", rJet, cOneFloat);
- CBotProgram::AddFunction("topo", rTopo, cTopo);
- CBotProgram::AddFunction("message", rMessage, cMessage);
- CBotProgram::AddFunction("cmdline", rCmdline, cOneFloat);
- CBotProgram::AddFunction("ismovie", rIsMovie, cNull);
- CBotProgram::AddFunction("errmode", rErrMode, cOneFloat);
- CBotProgram::AddFunction("ipf", rIPF, cOneFloat);
- CBotProgram::AddFunction("abstime", rAbsTime, cNull);
- CBotProgram::AddFunction("deletefile",rDeleteFile,cString);
- CBotProgram::AddFunction("pendown", rPenDown, cPenDown);
- CBotProgram::AddFunction("penup", rPenUp, cNull);
- CBotProgram::AddFunction("pencolor", rPenColor, cOneFloat);
- CBotProgram::AddFunction("penwidth", rPenWidth, cOneFloat);
-}
-
-// Object's destructor.
-
-CScript::~CScript()
-{
- delete m_botProg;
- delete m_primaryTask;
- delete m_script;
- m_script = 0;
- m_len = 0;
-
- m_iMan->DeleteInstance(CLASS_SCRIPT, this);
-}
-
-
-// Gives the script editable block of text.
-
-void CScript::PutScript(CEdit* edit, char* name)
-{
- if ( m_script == 0 )
- {
- New(edit, name);
- }
- else
- {
- edit->SetText(m_script);
- edit->SetCursor(m_cursor2, m_cursor1);
- edit->ShowSelect();
- }
- edit->SetFocus(true);
-}
-
-// The script takes a paved text.
-
-bool CScript::GetScript(CEdit* edit)
-{
- int len;
-
- delete m_script;
- m_script = 0;
-
- len = edit->RetTextLength();
- m_script = (char*)malloc(sizeof(char)*(len+1));
-
- edit->GetText(m_script, len+1);
- edit->GetCursor(m_cursor2, m_cursor1);
- m_len = strlen(m_script);
-
- if ( !CheckToken() )
- {
- edit->SetCursor(m_cursor2, m_cursor1);
- edit->ShowSelect();
- edit->SetFocus(true);
- return false;
- }
-
- if ( !Compile() )
- {
- edit->SetCursor(m_cursor2, m_cursor1);
- edit->ShowSelect();
- edit->SetFocus(true);
- return false;
- }
-
- return true;
-}
-
-// Indicates whether a program is compiled correctly.
-
-bool CScript::RetCompile()
-{
- return m_bCompile;
-}
-
-// Indicates whether the program is empty.
-
-bool CScript::IsEmpty()
-{
- int i;
-
- for ( i=0 ; i<m_len ; i++ )
- {
- if ( m_script[i] != ' ' &&
- m_script[i] != '\n' ) return false;
- }
- return true;
-}
-
-// Checks if a program does not contain the prohibited instructions
-// and if it contains well at least once every mandatory instructions.
-
-bool CScript::CheckToken()
-{
- CBotToken* bt;
- CBotString bs;
- const char* token;
- int error, type, cursor1, cursor2, i;
- char used[100];
-
- if ( !m_object->RetCheckToken() ) return true;
-
- m_error = 0;
- m_title[0] = 0;
- m_token[0] = 0;
- m_bCompile = false;
-
- for ( i=0 ; i<m_main->RetObligatoryToken() ; i++ )
- {
- used[i] = 0; // token not used
- }
-
- bt = CBotToken::CompileTokens(m_script, error);
- while ( bt != 0 )
- {
- bs = bt->GivString();
- token = bs;
- type = bt->GivType();
-
- cursor1 = bt->GivStart();
- cursor2 = bt->GivEnd();
-
- i = m_main->IsObligatoryToken((char*)token);
- if ( i != -1 )
- {
- used[i] = 1; // token used
- }
-
- if ( !m_main->IsProhibitedToken((char*)token) )
- {
- m_error = ERR_PROHIBITEDTOKEN;
- m_cursor1 = cursor1;
- m_cursor2 = cursor2;
- strcpy(m_title, "<erreur>");
- CBotToken::Delete(bt);
- return false;
- }
-
- bt = bt->GivNext();
- }
-
- // At least once every obligatory instruction?
- for ( i=0 ; i<m_main->RetObligatoryToken() ; i++ )
- {
- if ( used[i] == 0 ) // token not used?
- {
- strcpy(m_token, m_main->RetObligatoryToken(i));
- m_error = ERR_OBLIGATORYTOKEN;
- strcpy(m_title, "<erreur>");
- CBotToken::Delete(bt);
- return false;
- }
- }
-
- CBotToken::Delete(bt);
- return true;
-}
-
-// Compile the script of a paved text.
-
-bool CScript::Compile()
-{
- CBotStringArray liste;
- int i;
- const char* p;
-
- m_error = 0;
- m_cursor1 = 0;
- m_cursor2 = 0;
- m_title[0] = 0;
- m_bCompile = false;
-
- if ( IsEmpty() ) // program exist?
- {
- delete m_botProg;
- m_botProg = 0;
- return true;
- }
-
- if ( m_botProg == 0 )
- {
- m_botProg = new CBotProgram(m_object->RetBotVar());
- }
-
- if ( m_botProg->Compile(m_script, liste, this) )
- {
- if ( liste.GivSize() == 0 )
- {
- strcpy(m_title, "<sans nom>");
- }
- else
- {
- p = liste[0];
- i = 0;
- while ( true )
- {
- if ( p[i] == 0 || p[i] == '(' ) break;
- if ( i >= 20 )
- {
- m_title[i++] = '.';
- m_title[i++] = '.';
- m_title[i++] = '.';
- break;
- }
- m_title[i] = p[i];
- i ++;
- }
- m_title[i] = 0;
- }
- m_bCompile = true;
- return true;
- }
- else
- {
- m_botProg->GetError(m_error, m_cursor1, m_cursor2);
- if ( m_cursor1 < 0 || m_cursor1 > m_len ||
- m_cursor2 < 0 || m_cursor2 > m_len )
- {
- m_cursor1 = 0;
- m_cursor2 = 0;
- }
- if ( m_error == 0 )
- {
- m_cursor1 = m_cursor2 = 0;
- }
- strcpy(m_title, "<erreur>");
- return false;
- }
-}
-
-
-// Returns the title of the script.
-
-void CScript::GetTitle(char* buffer)
-{
- strcpy(buffer, m_title);
-}
-
-
-// Choice of mode of execution.
-
-void CScript::SetStepMode(bool bStep)
-{
- m_bStepMode = bStep;
-}
-
-
-// Runs the program from the beginning.
-
-bool CScript::Run()
-{
- if( m_botProg == 0 ) return false;
- if ( m_script == 0 || m_len == 0 ) return false;
-
- if ( !m_botProg->Start(m_title) ) return false;
-
- m_object->SetRunScript(this);
- m_bRun = true;
- m_bContinue = false;
- m_ipf = CBOT_IPF;
- m_errMode = ERM_STOP;
-
- if ( m_bStepMode ) // step by step mode?
- {
- Event newEvent;
- ZeroMemory(&newEvent, sizeof(Event));
- Step(newEvent);
- }
-
- return true;
-}
-
-// Continues the execution of current program.
-// Returns true when execution is finished.
-
-bool CScript::Continue(const Event &event)
-{
- if( m_botProg == 0 ) return true;
- if ( !m_bRun ) return true;
-
- m_event = event;
-
- if ( m_bStepMode ) // step by step mode?
- {
- if ( m_bContinue ) // instuction "move", "goto", etc. ?
- {
- if ( m_botProg->Run(m_object, 0) )
- {
- m_botProg->GetError(m_error, m_cursor1, m_cursor2);
- if ( m_cursor1 < 0 || m_cursor1 > m_len ||
- m_cursor2 < 0 || m_cursor2 > m_len )
- {
- m_cursor1 = 0;
- m_cursor2 = 0;
- }
- if ( m_error == 0 )
- {
- m_cursor1 = m_cursor2 = 0;
- }
- m_bRun = false;
-
- if ( m_error != 0 && m_errMode == ERM_STOP )
- {
- char s[100];
- GetError(s);
- m_displayText->DisplayText(s, m_object, 10.0f, TT_ERROR);
- }
- m_engine->SetPause(true); // gives pause
- return true;
- }
- if ( !m_bContinue )
- {
- m_engine->SetPause(true); // gives pause
- }
- }
-
- return false;
- }
-
- if ( m_botProg->Run(m_object, m_ipf) )
- {
- m_botProg->GetError(m_error, m_cursor1, m_cursor2);
- if ( m_cursor1 < 0 || m_cursor1 > m_len ||
- m_cursor2 < 0 || m_cursor2 > m_len )
- {
- m_cursor1 = 0;
- m_cursor2 = 0;
- }
- if ( m_error == 0 )
- {
- m_cursor1 = m_cursor2 = 0;
- }
- m_bRun = false;
-
- if ( m_error != 0 && m_errMode == ERM_STOP )
- {
- char s[100];
- GetError(s);
- m_displayText->DisplayText(s, m_object, 10.0f, TT_ERROR);
- }
- return true;
- }
-
- return false;
-}
-
-// Continues the execution of current program.
-// Returns true when execution is finished.
-
-bool CScript::Step(const Event &event)
-{
- if( m_botProg == 0 ) return true;
- if ( !m_bRun ) return true;
- if ( !m_bStepMode ) return false;
-
- m_engine->SetPause(false);
- m_engine->StepSimul(0.01f); // advance of 10ms
- m_engine->SetPause(true);
-
- m_event = event;
-
- if ( m_botProg->Run(m_object, 0) ) // step mode
- {
- m_botProg->GetError(m_error, m_cursor1, m_cursor2);
- if ( m_cursor1 < 0 || m_cursor1 > m_len ||
- m_cursor2 < 0 || m_cursor2 > m_len )
- {
- m_cursor1 = 0;
- m_cursor2 = 0;
- }
- if ( m_error == 0 )
- {
- m_cursor1 = m_cursor2 = 0;
- }
- m_bRun = false;
-
- if ( m_error != 0 && m_errMode == ERM_STOP )
- {
- char s[100];
- GetError(s);
- m_displayText->DisplayText(s, m_object, 10.0f, TT_ERROR);
- }
- return true;
- }
-
- if ( m_bContinue ) // instuction "move", "goto", etc. ?
- {
- m_engine->SetPause(false); // removes the pause
- }
- return false;
-}
-
-// Stops the program.
-
-void CScript::Stop()
-{
- if ( !m_bRun ) return;
-
- if( m_botProg != 0 )
- {
- m_botProg->Stop();
- }
-
- if ( m_primaryTask != 0 )
- {
- m_primaryTask->Abort();
- delete m_primaryTask;
- m_primaryTask = 0;
- }
-
- m_bRun = false;
-}
-
-// Indicates whether the program runs.
-
-bool CScript::IsRunning()
-{
- return m_bRun;
-}
-
-// Indicates whether the program continues a step.
-
-bool CScript::IsContinue()
-{
- return m_bContinue;
-}
-
-
-// Gives the position of the cursor during the execution.
-
-bool CScript::GetCursor(int &cursor1, int &cursor2)
-{
- const char* funcName;
-
- cursor1 = cursor2 = 0;
-
- if( m_botProg == 0 ) return false;
- if ( !m_bRun ) return false;
-
- m_botProg->GetRunPos(funcName, cursor1, cursor2);
- if ( cursor1 < 0 || cursor1 > m_len ||
- cursor2 < 0 || cursor2 > m_len )
- {
- cursor1 = 0;
- cursor2 = 0;
- }
- return true;
-}
-
-
-// Put of the variables in a list.
-
-void PutList(char *baseName, bool bArray, CBotVar *var, CList *list, int &rankList)
-{
- CBotString bs;
- CBotVar *svar, *pStatic;
- char varName[100];
- char buffer[100];
- const char *p;
- int index, type;
-
- if ( var == 0 && baseName[0] != 0 )
- {
- sprintf(buffer, "%s = null;", baseName);
- list->SetName(rankList++, buffer);
- return;
- }
-
- index = 0;
- while ( var != 0 )
- {
- var->Maj(NULL, false);
- pStatic = var->GivStaticVar(); // finds the static element
-
- bs = pStatic->GivName(); // variable name
- p = bs;
-//? if ( strcmp(p, "this") == 0 )
-//? {
-//? var = var->GivNext();
-//? continue;
-//? }
-
- if ( baseName[0] == 0 )
- {
- sprintf(varName, "%s", p);
- }
- else
- {
- if ( bArray )
- {
- sprintf(varName, "%s[%d]", baseName, index);
- }
- else
- {
- sprintf(varName, "%s.%s", baseName, p);
- }
- }
-
- type = pStatic->GivType();
-
- if ( type < CBotTypBoolean )
- {
- CBotString value;
- value = pStatic->GivValString();
- p = value;
- sprintf(buffer, "%s = %s;", varName, p);
- list->SetName(rankList++, buffer);
- }
- else if ( type == CBotTypString )
- {
- CBotString value;
- value = pStatic->GivValString();
- p = value;
- sprintf(buffer, "%s = \"%s\";", varName, p);
- list->SetName(rankList++, buffer);
- }
- else if ( type == CBotTypArrayPointer )
- {
- svar = pStatic->GivItemList();
- PutList(varName, true, svar, list, rankList);
- }
- else if ( type == CBotTypClass ||
- type == CBotTypPointer )
- {
- svar = pStatic->GivItemList();
- PutList(varName, false, svar, list, rankList);
- }
- else
- {
- sprintf(buffer, "%s = ?;", varName);
- list->SetName(rankList++, buffer);
- }
-
- index ++;
- var = var->GivNext();
- }
-}
-
-// Fills a list with variables.
-
-void CScript::UpdateList(CList* list)
-{
- CBotVar *var;
- const char *progName, *funcName;
- int total, select, level, cursor1, cursor2, rank;
-
- if( m_botProg == 0 ) return;
-
- total = list->RetTotal();
- select = list->RetSelect();
-
- list->Flush(); // empty list
- m_botProg->GetRunPos(progName, cursor1, cursor2);
- if ( progName == 0 ) return;
-
- level = 0;
- rank = 0;
- while ( true )
- {
- var = m_botProg->GivStackVars(funcName, level--);
- if ( funcName != progName ) break;
-
- PutList("", false, var, list, rank);
- }
-
- if ( total == list->RetTotal() ) // same total?
- {
- list->SetSelect(select);
- }
-
- list->SetTooltip("");
- list->SetState(STATE_ENABLE);
-}
-
-
-// Colorize the text according to syntax.
-
-void CScript::ColorizeScript(CEdit* edit)
-{
- CBotToken* bt;
- CBotString bs;
- const char* token;
- int error, type, cursor1, cursor2, color;
-
- edit->ClearFormat();
-
- bt = CBotToken::CompileTokens(edit->RetText(), error);
- while ( bt != 0 )
- {
- bs = bt->GivString();
- token = bs;
- type = bt->GivType();
-
- cursor1 = bt->GivStart();
- cursor2 = bt->GivEnd();
-
- color = 0;
- if ( type >= TokenKeyWord && type < TokenKeyWord+100 )
- {
- color = COLOR_TOKEN;
- }
- if ( type >= TokenKeyDeclare && type < TokenKeyDeclare+100 )
- {
- color = COLOR_TYPE;
- }
- if ( type >= TokenKeyVal && type < TokenKeyVal+100 )
- {
- color = COLOR_CONST;
- }
- if ( type == TokenTypVar )
- {
- if ( IsType(token) )
- {
- color = COLOR_TYPE;
- }
- else if ( IsFunction(token) )
- {
- color = COLOR_TOKEN;
- }
- }
- if ( type == TokenTypDef )
- {
- color = COLOR_CONST;
- }
-
- if ( cursor1 < cursor2 && color != 0 )
- {
- edit->SetFormat(cursor1, cursor2, color);
- }
-
- bt = bt->GivNext();
- }
-
- CBotToken::Delete(bt);
-}
-
-
-// Seeks a token at random in a script.
-// Returns the index of the start of the token found, or -1.
-
-int SearchToken(char* script, char* token)
-{
- int lScript, lToken, i, iFound;
- int found[100];
- char* p;
-
- lScript = strlen(script);
- lToken = strlen(token);
- iFound = 0;
- for ( i=0 ; i<lScript-lToken ; i++ )
- {
- p = strstr(script+i, token);
- if ( p != 0 )
- {
- found[iFound++] = p-script;
- if ( iFound >= 100 ) break;
- }
- }
-
- if ( iFound == 0 ) return -1;
- return found[rand()%iFound];
-}
-
-// Removes a token in a script.
-
-void DeleteToken(char* script, int pos, int len)
-{
- while ( true )
- {
- script[pos] = script[pos+len];
- if ( script[pos++] == 0 ) break;
- }
-}
-
-// Inserts a token in a script.
-
-void InsertToken(char* script, int pos, char* token)
-{
- int lScript, lToken, i;
-
- lScript = strlen(script);
- lToken = strlen(token);
- for ( i=lScript ; i>=pos ; i-- )
- {
- script[i+lToken] = script[i];
- }
- memcpy(script+pos, token, lToken);
-}
-
-// Introduces a virus into a program.
-
-bool CScript::IntroduceVirus()
-{
- int i, start, iFound;
- int found[11*2];
- char* newScript;
-
- char* names[11*2] =
- {
- "==", "!=",
- "!=", "==",
- ">", "<",
- "<", ">",
- "true", "false",
- "false", "true",
- "grab", "drop",
- "drop", "grab",
- "InFront", "Behind",
- "Behind", "EnergyCell",
- "EnergyCell", "InFront",
- };
-
- iFound = 0;
- for ( i=0 ; i<11 ; i++ )
- {
- start = SearchToken(m_script, names[i*2]);
- if ( start != -1 )
- {
- found[iFound++] = i*2;
- found[iFound++] = start;
- }
- }
- if ( iFound == 0 ) return false;
-
- i = (rand()%(iFound/2))*2;
- start = found[i+1];
- i = found[i+0];
-
- newScript = (char*)malloc(sizeof(char)*(m_len+strlen(names[i+1])+1));
- strcpy(newScript, m_script);
- delete m_script;
- m_script = newScript;
-
- DeleteToken(m_script, start, strlen(names[i]));
- InsertToken(m_script, start, names[i+1]);
- m_len = strlen(m_script);
- Compile(); // recompile with the virus
-
- return true;
-}
-
-
-// Returns the number of the error.
-
-int CScript::RetError()
-{
- return m_error;
-}
-
-// Returns the text of the error.
-
-void CScript::GetError(char* buffer)
-{
- if ( m_error == 0 )
- {
- buffer[0] = 0;
- }
- else
- {
- if ( m_error == ERR_OBLIGATORYTOKEN )
- {
- char s[100];
- GetResource(RES_ERR, m_error, s);
- sprintf(buffer, s, m_token);
- }
- else if ( m_error < 1000 )
- {
- GetResource(RES_ERR, m_error, buffer);
- }
- else
- {
- GetResource(RES_CBOT, m_error, buffer);
- }
- }
-}
-
-
-// New program.
-
-void CScript::New(CEdit* edit, char* name)
-{
- FILE *file = NULL;
- char res[100];
- char text[100];
- char filename[100];
- char script[500];
- char buffer[500];
- char *sf;
- int cursor1, cursor2, len, i, j;
-
- GetResource(RES_TEXT, RT_SCRIPT_NEW, res);
- if ( name[0] == 0 ) strcpy(text, res);
- else strcpy(text, name);
-
- sprintf(script, "extern void object::%s()\n{\n\t\n\t\n\t\n}\n", text);
- edit->SetText(script, false);
-
- if ( strcmp(text, res) == 0 )
- {
- cursor1 = 20;
- cursor2 = 20+strlen(text); // update "New"
- }
- else
- {
- if ( edit->RetAutoIndent() )
- {
- cursor1 = 20+strlen(text)+6;
- cursor2 = cursor1; // cursor in { }
- }
- else
- {
- cursor1 = 20+strlen(text)+8;
- cursor2 = cursor1; // cursor in { }
- }
- }
-
- edit->SetCursor(cursor2, cursor1);
- edit->ShowSelect();
- edit->SetFocus(true);
-
- sf = m_main->RetScriptFile();
- if ( sf[0] != 0 ) // Load an empty program specific?
- {
- strcpy(filename, "script\\");
- strcat(filename, sf);
- file = fopen(filename, "rb");
- if ( file != NULL )
- {
- fseek(file, 0, SEEK_END);
- len = ftell(file);
- fseek(file, 0, SEEK_SET);
-
- if ( len > 500-1 ) len = 500-1;
- fread(buffer, 1, len, file);
- buffer[len] = 0;
- fclose(file);
-
- cursor1 = 0;
- i = 0;
- j = 0;
- while ( true )
- {
- if ( buffer[i] == 0 ) break;
-
- if ( buffer[i] == '\r' )
- {
- i ++;
- continue;
- }
-
- if ( buffer[i] == '\t' && edit->RetAutoIndent() )
- {
- i ++;
- continue;
- }
-
- if ( buffer[i+0] == '%' &&
- buffer[i+1] == 's' )
- {
- strcpy(script+j, text);
- j += strlen(text);
- i += 2;
- continue;
- }
-
- if ( buffer[i] == '#' )
- {
- cursor1 = j;
- i ++;
- continue;
- }
-
- script[j++] = buffer[i++];
- }
- script[j] = 0;
- edit->SetText(script, false);
-
- cursor2 = cursor1;
- edit->SetCursor(cursor2, cursor1);
- edit->ShowSelect();
- edit->SetFocus(true);
- }
- }
-
- ColorizeScript(edit);
-}
-
-
-// Provided a script for all parts.
-
-bool CScript::SendScript(char* text)
-{
- m_len = strlen(text);
- m_script = (char*)malloc(sizeof(char)*(m_len+1));
- strcpy(m_script, text);
- if ( !CheckToken() ) return false;
- if ( !Compile() ) return false;
-
- return true;
-}
-
-// Reads a script as a text file.
-
-bool CScript::ReadScript(char* filename)
-{
- FILE* file;
- CEdit* edit;
- char name[100];
-
- if ( strchr(filename, '\\') == 0 )
- {
- strcpy(name, "script\\");
- strcat(name, filename);
- }
- else
- {
-//? strcpy(name, filename);
- UserDir(name, filename, "");
- }
-
- file = fopen(name, "rb");
- if ( file == NULL ) return false;
- fclose(file);
-
- delete m_script;
- m_script = 0;
-
- edit = m_interface->CreateEdit(Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f), 0, EVENT_EDIT9);
- edit->SetMaxChar(EDITSTUDIOMAX);
- edit->SetAutoIndent(m_engine->RetEditIndentMode());
- edit->ReadText(name);
- GetScript(edit);
- m_interface->DeleteControl(EVENT_EDIT9);
- return true;
-}
-
-// Writes a script as a text file.
-
-bool CScript::WriteScript(char* filename)
-{
- CEdit* edit;
- char name[100];
-
- if ( strchr(filename, '\\') == 0 )
- {
- strcpy(name, "script\\");
- strcat(name, filename);
- }
- else
- {
- strcpy(name, filename);
- }
-
- if ( m_script == 0 )
- {
- remove(filename);
- return false;
- }
-
- edit = m_interface->CreateEdit(Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f), 0, EVENT_EDIT9);
- edit->SetMaxChar(EDITSTUDIOMAX);
- edit->SetAutoIndent(m_engine->RetEditIndentMode());
- edit->SetText(m_script);
- edit->WriteText(name);
- m_interface->DeleteControl(EVENT_EDIT9);
- return true;
-}
-
-
-// Reads a stack of script by execution as a file.
-
-bool CScript::ReadStack(FILE *file)
-{
- int nb;
-
- fRead(&nb, sizeof(int), 1, file);
- fRead(&m_ipf, sizeof(int), 1, file);
- fRead(&m_errMode, sizeof(int), 1, file);
-
- if ( m_botProg == 0 ) return false;
- if ( !m_botProg->RestoreState(file) ) return false;
-
- m_object->SetRunScript(this);
- m_bRun = true;
- m_bContinue = false;
- return true;
-}
-
-// Writes a stack of script by execution as a file.
-
-bool CScript::WriteStack(FILE *file)
-{
- int nb;
-
- nb = 2;
- fWrite(&nb, sizeof(int), 1, file);
- fWrite(&m_ipf, sizeof(int), 1, file);
- fWrite(&m_errMode, sizeof(int), 1, file);
-
- return m_botProg->SaveState(file);
-}
-
-
-// Compares two scripts.
-
-bool CScript::Compare(CScript* other)
-{
- if ( m_len != other->m_len ) return false;
-
- return ( strcmp(m_script, other->m_script) == 0 );
-}
-
-
-// Management of the file name when the script is saved.
-
-void CScript::SetFilename(char *filename)
-{
- strcpy(m_filename, filename);
-}
-
-char* CScript::RetFilename()
-{
- return m_filename;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// script.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "CBot/CBotDll.h"
+#include "common/struct.h"
+#include "math/geometry.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/global.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "old/math3d.h"
+#include "object/robotmain.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "object/object.h"
+#include "physics/physics.h"
+#include "ui/interface.h"
+#include "ui/edit.h"
+#include "ui/list.h"
+#include "old/text.h"
+#include "ui/displaytext.h"
+#include "object/task/taskmanager.h"
+#include "object/task/task.h"
+#include "object/task/taskmanip.h"
+#include "object/task/taskgoto.h"
+#include "object/task/taskshield.h"
+#include "script/cbottoken.h"
+#include "script/script.h"
+
+
+
+const int CBOT_IPF = 100; // CBOT: number of instructions / frame
+
+const int ERM_CONT = 0; // if error -> continue
+const int ERM_STOP = 1; // if error -> stop
+
+
+
+
+// Compiling a procedure without any parameters.
+
+CBotTypResult cNull(CBotVar* &var, void* user)
+{
+ if ( var != 0 ) return CBotErrOverParam;
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Compiling a procedure with a single real number.
+
+CBotTypResult cOneFloat(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Compiling a procedure with two real numbers.
+
+CBotTypResult cTwoFloat(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Compiling a procedure with a "dot".
+
+CBotTypResult cPoint(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+
+ if ( var->GivType() <= CBotTypDouble )
+ {
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+//? if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+//? if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+//? var = var->GivNext();
+ return CBotTypResult(0);
+ }
+
+ if ( var->GivType() == CBotTypClass )
+ {
+ if ( !var->IsElemOfClass("point") ) return CBotTypResult(CBotErrBadParam);
+ var = var->GivNext();
+ return CBotTypResult(0);
+ }
+
+ return CBotTypResult(CBotErrBadParam);
+}
+
+// Compiling a procedure with a single "point".
+
+CBotTypResult cOnePoint(CBotVar* &var, void* user)
+{
+ CBotTypResult ret;
+
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Compiling a procedure with a single string.
+
+CBotTypResult cString(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() != CBotTypString &&
+ var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+
+// Seeking value in an array of integers.
+
+bool FindList(CBotVar* array, int type)
+{
+ while ( array != 0 )
+ {
+ if ( type == array->GivValInt() ) return true;
+ array = array->GivNext();
+ }
+ return false;
+}
+
+
+// Gives a parameter of type "point".
+
+bool GetPoint(CBotVar* &var, int& exception, Math::Vector& pos)
+{
+ CBotVar *pX, *pY, *pZ;
+
+ if ( var->GivType() <= CBotTypDouble )
+ {
+ pos.x = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+
+ pos.z = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+
+ pos.y = 0.0f;
+ }
+ else
+ {
+ pX = var->GivItem("x");
+ if ( pX == NULL )
+ {
+ exception = CBotErrUndefItem; return true;
+ }
+ pos.x = pX->GivValFloat()*g_unit;
+
+ pY = var->GivItem("y");
+ if ( pY == NULL )
+ {
+ exception = CBotErrUndefItem; return true;
+ }
+ pos.z = pY->GivValFloat()*g_unit; // attention y -> z !
+
+ pZ = var->GivItem("z");
+ if ( pZ == NULL )
+ {
+ exception = CBotErrUndefItem; return true;
+ }
+ pos.y = pZ->GivValFloat()*g_unit; // attention z -> y !
+
+ var = var->GivNext();
+ }
+ return true;
+}
+
+
+// Instruction "sin(degrees)".
+
+bool rSin(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float value;
+
+ value = var->GivValFloat();
+ result->SetValFloat(sinf(value*Math::PI/180.0f));
+ return true;
+}
+
+// Instruction "cos(degrees)".
+
+bool rCos(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float value;
+
+ value = var->GivValFloat();
+ result->SetValFloat(cosf(value*Math::PI/180.0f));
+ return true;
+}
+
+// Instruction "tan(degrees)".
+
+bool rTan(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float value;
+
+ value = var->GivValFloat();
+ result->SetValFloat(tanf(value*Math::PI/180.0f));
+ return true;
+}
+
+// Instruction "asin(degrees)".
+
+bool raSin(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float value;
+
+ value = var->GivValFloat();
+ result->SetValFloat(asinf(value)*180.0f/Math::PI);
+ return true;
+}
+
+// Instruction "acos(degrees)".
+
+bool raCos(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float value;
+
+ value = var->GivValFloat();
+ result->SetValFloat(acosf(value)*180.0f/Math::PI);
+ return true;
+}
+
+// Instruction "atan(degrees)".
+
+bool raTan(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float value;
+
+ value = var->GivValFloat();
+ result->SetValFloat(atanf(value)*180.0f/Math::PI);
+ return true;
+}
+
+// Instruction "sqrt(value)".
+
+bool rSqrt(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float value;
+
+ value = var->GivValFloat();
+ result->SetValFloat(sqrtf(value));
+ return true;
+}
+
+// Instruction "pow(x, y)".
+
+bool rPow(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float x, y;
+
+ x = var->GivValFloat();
+ var = var->GivNext();
+ y = var->GivValFloat();
+ result->SetValFloat(powf(x, y));
+ return true;
+}
+
+// Instruction "rand()".
+
+bool rRand(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ result->SetValFloat(Math::Rand());
+ return true;
+}
+
+// Instruction "abs()".
+
+bool rAbs(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ float value;
+
+ value = var->GivValFloat();
+ result->SetValFloat(fabs(value));
+ return true;
+}
+
+
+// Compilation of the instruction "retobject(rank)".
+
+CBotTypResult cRetObject(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+
+ return CBotTypResult(CBotTypPointer, "object");
+}
+
+// Instruction "retobject(rank)".
+
+bool rRetObject(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pObj;
+ int rank;
+
+ rank = var->GivValInt();
+
+ pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, rank);
+ if ( pObj == 0 )
+ {
+ result->SetPointer(0);
+ }
+ else
+ {
+ result->SetPointer(pObj->RetBotVar());
+ }
+ return true;
+}
+
+
+// Compilation of the instruction "search(type, pos)".
+
+CBotTypResult cSearch(CBotVar* &var, void* user)
+{
+ CBotVar* array;
+ CBotTypResult ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() == CBotTypArrayPointer )
+ {
+ array = var->GivItemList();
+ if ( array == 0 ) return CBotTypResult(CBotTypPointer);
+ if ( array->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ }
+ else if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ }
+
+ return CBotTypResult(CBotTypPointer, "object");
+}
+
+// Instruction "search(type, pos)".
+
+bool rSearch(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject *pObj, *pBest;
+ CBotVar* array;
+ Math::Vector pos, oPos;
+ bool bNearest = false;
+ bool bArray;
+ float min, dist;
+ int type, oType, i;
+
+ if ( var->GivType() == CBotTypArrayPointer )
+ {
+ array = var->GivItemList();
+ bArray = true;
+ }
+ else
+ {
+ type = var->GivValInt();
+ bArray = false;
+ }
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ if ( !GetPoint(var, exception, pos) ) return true;
+ bNearest = true;
+ }
+
+ min = 100000.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( !pObj->RetActif() ) continue;
+
+ oType = pObj->RetType();
+ if ( oType == OBJECT_TOTO ) continue;
+
+ if ( oType == OBJECT_RUINmobilew2 ||
+ oType == OBJECT_RUINmobilet1 ||
+ oType == OBJECT_RUINmobilet2 ||
+ oType == OBJECT_RUINmobiler1 ||
+ oType == OBJECT_RUINmobiler2 )
+ {
+ oType = OBJECT_RUINmobilew1; // any ruin
+ }
+
+ if ( oType == OBJECT_SCRAP2 ||
+ oType == OBJECT_SCRAP3 ||
+ oType == OBJECT_SCRAP4 ||
+ oType == OBJECT_SCRAP5 ) // wastes?
+ {
+ oType = OBJECT_SCRAP1; // any waste
+ }
+
+ if ( oType == OBJECT_BARRIER2 ||
+ oType == OBJECT_BARRIER3 ) // barriers?
+ {
+ oType = OBJECT_BARRIER1; // any barrier
+ }
+
+ if ( bArray )
+ {
+ if ( !FindList(array, oType) ) continue;
+ }
+ else
+ {
+ if ( type != oType && type != OBJECT_NULL ) continue;
+ }
+
+ if ( bNearest )
+ {
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(pos, oPos);
+ if ( dist < min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+ else
+ {
+ pBest = pObj;
+ break;
+ }
+ }
+
+ if ( pBest == 0 )
+ {
+ result->SetPointer(0);
+ }
+ else
+ {
+ result->SetPointer(pBest->RetBotVar());
+ }
+ return true;
+}
+
+
+// Compilation of instruction "radar(type, angle, focus, min, max, sens)".
+
+CBotTypResult cRadar(CBotVar* &var, void* user)
+{
+ CBotVar* array;
+
+ if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ if ( var->GivType() == CBotTypArrayPointer )
+ {
+ array = var->GivItemList();
+ if ( array == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ if ( array->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type
+ }
+ else if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // angle
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // focus
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // min
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // max
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // sense
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // filter
+ var = var->GivNext();
+ if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object");
+ return CBotTypResult(CBotErrOverParam);
+}
+
+// Instruction "radar(type, angle, focus, min, max, sens, filter)".
+
+bool rRadar(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ CObject *pObj, *pBest;
+ CPhysics* physics;
+ CBotVar* array;
+ Math::Vector iPos, oPos;
+ RadarFilter filter;
+ float best, minDist, maxDist, sens, iAngle, angle, focus, d, a;
+ int type, oType, i;
+ bool bArray;
+
+ type = OBJECT_NULL;
+ angle = 0.0f;
+ focus = Math::PI*2.0f;
+ minDist = 0.0f*g_unit;
+ maxDist = 1000.0f*g_unit;
+ sens = 1.0f;
+ filter = FILTER_NONE;
+
+ if ( var != 0 )
+ {
+ if ( var->GivType() == CBotTypArrayPointer )
+ {
+ array = var->GivItemList();
+ bArray = true;
+ }
+ else
+ {
+ type = var->GivValInt();
+ bArray = false;
+ }
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ angle = -var->GivValFloat()*Math::PI/180.0f;
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ focus = var->GivValFloat()*Math::PI/180.0f;
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ minDist = var->GivValFloat()*g_unit;
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ maxDist = var->GivValFloat()*g_unit;
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ sens = var->GivValFloat();
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ filter = (RadarFilter)var->GivValInt();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ iPos = pThis->RetPosition(0);
+ iAngle = pThis->RetAngleY(0)+angle;
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+
+ if ( sens >= 0.0f ) best = 100000.0f;
+ else best = 0.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pObj == pThis ) continue;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( !pObj->RetActif() ) continue;
+ if ( pObj->RetProxyActivate() ) continue;
+
+ oType = pObj->RetType();
+ if ( oType == OBJECT_TOTO ) continue;
+
+ if ( oType == OBJECT_RUINmobilew2 ||
+ oType == OBJECT_RUINmobilet1 ||
+ oType == OBJECT_RUINmobilet2 ||
+ oType == OBJECT_RUINmobiler1 ||
+ oType == OBJECT_RUINmobiler2 )
+ {
+ oType = OBJECT_RUINmobilew1; // any ruin
+ }
+
+ if ( oType == OBJECT_SCRAP2 ||
+ oType == OBJECT_SCRAP3 ||
+ oType == OBJECT_SCRAP4 ||
+ oType == OBJECT_SCRAP5 ) // wastes?
+ {
+ oType = OBJECT_SCRAP1; // any waste
+ }
+
+ if ( oType == OBJECT_BARRIER2 ||
+ oType == OBJECT_BARRIER3 ) // barriers?
+ {
+ oType = OBJECT_BARRIER1; // any barrier
+ }
+
+ if ( filter == FILTER_ONLYLANDING )
+ {
+ physics = pObj->RetPhysics();
+ if ( physics != 0 && !physics->RetLand() ) continue;
+ }
+ if ( filter == FILTER_ONLYFLYING )
+ {
+ physics = pObj->RetPhysics();
+ if ( physics != 0 && physics->RetLand() ) continue;
+ }
+
+ if ( bArray )
+ {
+ if ( !FindList(array, oType) ) continue;
+ }
+ else
+ {
+ if ( type != oType && type != OBJECT_NULL ) continue;
+ }
+
+ oPos = pObj->RetPosition(0);
+ d = Math::DistanceProjected(iPos, oPos);
+ if ( d < minDist || d > maxDist ) continue; // too close or too far?
+
+ if ( focus >= Math::PI*2.0f )
+ {
+ if ( (sens >= 0.0f && d < best) ||
+ (sens < 0.0f && d > best) )
+ {
+ best = d;
+ pBest = pObj;
+ }
+ continue;
+ }
+
+ a = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+ if ( Math::TestAngle(a, iAngle-focus/2.0f, iAngle+focus/2.0f) )
+ {
+ if ( (sens >= 0.0f && d < best) ||
+ (sens < 0.0f && d > best) )
+ {
+ best = d;
+ pBest = pObj;
+ }
+ }
+ }
+
+ if ( pBest == 0 )
+ {
+ result->SetPointer(0);
+ }
+ else
+ {
+ result->SetPointer(pBest->RetBotVar());
+ }
+ return true;
+}
+
+
+// Monitoring a task.
+
+bool Process(CScript* script, CBotVar* result, int &exception)
+{
+ Error err;
+
+ err = script->m_primaryTask->IsEnded();
+ if ( err != ERR_CONTINUE ) // task terminated?
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+
+ script->m_bContinue = false;
+
+ if ( err == ERR_STOP ) err = ERR_OK;
+ result->SetValInt(err); // indicates the error or ok
+ if ( err != ERR_OK && script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return false;
+ }
+ return true; // it's all over
+ }
+
+ script->m_primaryTask->EventProcess(script->m_event);
+ script->m_bContinue = true;
+ return false; // not done
+}
+
+
+// Compilation of the instruction "detect(type)".
+
+CBotTypResult cDetect(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypBoolean);
+}
+
+// Instruction "detect(type)".
+
+bool rDetect(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ CObject *pObj, *pGoal, *pBest;
+ CPhysics* physics;
+ CBotVar* array;
+ Math::Vector iPos, oPos;
+ RadarFilter filter;
+ float bGoal, best, minDist, maxDist, sens, iAngle, angle, focus, d, a;
+ int type, oType, i;
+ bool bArray;
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ type = OBJECT_NULL;
+ angle = 0.0f;
+ focus = 45.0f*Math::PI/180.0f;
+ minDist = 0.0f*g_unit;
+ maxDist = 20.0f*g_unit;
+ sens = 1.0f;
+ filter = FILTER_NONE;
+
+ if ( var != 0 )
+ {
+ if ( var->GivType() == CBotTypArrayPointer )
+ {
+ array = var->GivItemList();
+ bArray = true;
+ }
+ else
+ {
+ type = var->GivValInt();
+ bArray = false;
+ }
+ }
+
+ iPos = pThis->RetPosition(0);
+ iAngle = pThis->RetAngleY(0)+angle;
+ iAngle = Math::NormAngle(iAngle); // 0..2*Math::PI
+
+ bGoal = 100000.0f;
+ pGoal = 0;
+ if ( sens >= 0.0f ) best = 100000.0f;
+ else best = 0.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pObj == pThis ) continue;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( !pObj->RetActif() ) continue;
+ if ( pObj->RetProxyActivate() ) continue;
+
+ oType = pObj->RetType();
+ if ( oType == OBJECT_TOTO ) continue;
+
+ if ( oType == OBJECT_RUINmobilew2 ||
+ oType == OBJECT_RUINmobilet1 ||
+ oType == OBJECT_RUINmobilet2 ||
+ oType == OBJECT_RUINmobiler1 ||
+ oType == OBJECT_RUINmobiler2 )
+ {
+ oType = OBJECT_RUINmobilew1; // any ruin
+ }
+
+ if ( oType == OBJECT_SCRAP2 ||
+ oType == OBJECT_SCRAP3 ||
+ oType == OBJECT_SCRAP4 ||
+ oType == OBJECT_SCRAP5 ) // wastes?
+ {
+ oType = OBJECT_SCRAP1; // any waste
+ }
+
+ if ( oType == OBJECT_BARRIER2 ||
+ oType == OBJECT_BARRIER3 ) // barriers?
+ {
+ oType = OBJECT_BARRIER1; // any barrier
+ }
+
+ if ( filter == FILTER_ONLYLANDING )
+ {
+ physics = pObj->RetPhysics();
+ if ( physics != 0 && !physics->RetLand() ) continue;
+ }
+ if ( filter == FILTER_ONLYFLYING )
+ {
+ physics = pObj->RetPhysics();
+ if ( physics != 0 && physics->RetLand() ) continue;
+ }
+
+ if ( bArray )
+ {
+ if ( !FindList(array, oType) ) continue;
+ }
+ else
+ {
+ if ( type != oType && type != OBJECT_NULL ) continue;
+ }
+
+ oPos = pObj->RetPosition(0);
+ d = Math::DistanceProjected(iPos, oPos);
+ a = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+
+ if ( d < bGoal &&
+ Math::TestAngle(a, iAngle-(5.0f*Math::PI/180.0f)/2.0f, iAngle+(5.0f*Math::PI/180.0f)/2.0f) )
+ {
+ bGoal = d;
+ pGoal = pObj;
+ }
+
+ if ( d < minDist || d > maxDist ) continue; // too close or too far?
+
+ if ( focus >= Math::PI*2.0f )
+ {
+ if ( (sens >= 0.0f && d < best) ||
+ (sens < 0.0f && d > best) )
+ {
+ best = d;
+ pBest = pObj;
+ }
+ continue;
+ }
+
+ if ( Math::TestAngle(a, iAngle-focus/2.0f, iAngle+focus/2.0f) )
+ {
+ if ( (sens >= 0.0f && d < best) ||
+ (sens < 0.0f && d > best) )
+ {
+ best = d;
+ pBest = pObj;
+ }
+ }
+ }
+
+ pThis->StartDetectEffect(pGoal, pBest!=0);
+
+ if ( pBest == 0 )
+ {
+ script->m_returnValue = 0.0f;
+ }
+ else
+ {
+ script->m_returnValue = 1.0f;
+ }
+
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = script->m_primaryTask->StartTaskWait(0.3f);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+ }
+ if ( !Process(script, result, exception) ) return false; // not finished
+ result->SetValFloat(script->m_returnValue);
+ return true;
+}
+
+
+// Compilation of the instruction "direction(pos)".
+
+CBotTypResult cDirection(CBotVar* &var, void* user)
+{
+ CBotTypResult ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "direction(pos)".
+
+bool rDirection(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ Math::Vector iPos, oPos;
+ float a, g;
+
+ if ( !GetPoint(var, exception, oPos) ) return true;
+
+ iPos = pThis->RetPosition(0);
+
+ a = pThis->RetAngleY(0);
+ g = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+
+ result->SetValFloat(-Math::Direction(a, g)*180.0f/Math::PI);
+ return true;
+}
+
+
+// Compilation of the instruction "produce(pos, angle, type, scriptName)".
+
+CBotTypResult cProduce(CBotVar* &var, void* user)
+{
+ CBotTypResult ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "produce(pos, angle, type, scriptName)".
+
+bool rProduce(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* object;
+ CBotString cbs;
+ const char* name;
+ Math::Vector pos;
+ float angle;
+ ObjectType type;
+
+ if ( !GetPoint(var, exception, pos) ) return true;
+
+ angle = var->GivValFloat()*Math::PI/180.0f;
+ var = var->GivNext();
+
+ type = (ObjectType)var->GivValInt();
+ var = var->GivNext();
+
+ cbs = var->GivValString();
+ name = cbs;
+
+ if ( type == OBJECT_FRET ||
+ type == OBJECT_STONE ||
+ type == OBJECT_URANIUM ||
+ type == OBJECT_METAL ||
+ type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC ||
+ type == OBJECT_BULLET ||
+ type == OBJECT_BBOX ||
+ type == OBJECT_KEYa ||
+ type == OBJECT_KEYb ||
+ type == OBJECT_KEYc ||
+ type == OBJECT_KEYd ||
+ type == OBJECT_TNT ||
+ type == OBJECT_SCRAP1 ||
+ type == OBJECT_SCRAP2 ||
+ type == OBJECT_SCRAP3 ||
+ type == OBJECT_SCRAP4 ||
+ type == OBJECT_SCRAP5 ||
+ type == OBJECT_BOMB ||
+ type == OBJECT_WAYPOINT ||
+ type == OBJECT_SHOW ||
+ type == OBJECT_WINFIRE )
+ {
+ object = new CObject(script->m_iMan);
+ if ( !object->CreateResource(pos, angle, type) )
+ {
+ delete object;
+ result->SetValInt(1); // error
+ return true;
+ }
+ }
+ else
+ if ( type == OBJECT_MOTHER ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM )
+ {
+ CObject* egg;
+
+ object = new CObject(script->m_iMan);
+ if ( !object->CreateInsect(pos, angle, type) )
+ {
+ delete object;
+ result->SetValInt(1); // error
+ return true;
+ }
+
+ egg = new CObject(script->m_iMan);
+ if ( !egg->CreateResource(pos, angle, OBJECT_EGG, 0.0f) )
+ {
+ delete egg;
+ }
+ }
+ else
+ {
+ result->SetValInt(1); // impossible
+ return true;
+ }
+ object->SetActivity(false);
+ object->ReadProgram(0, (char*)name);
+ object->RunProgram(0);
+
+ result->SetValInt(0); // no error
+ return true;
+}
+
+
+// Compilation of the instruction "distance(p1, p2)".
+
+CBotTypResult cDistance(CBotVar* &var, void* user)
+{
+ CBotTypResult ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "distance(p1, p2)".
+
+bool rDistance(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ Math::Vector p1, p2;
+ float value;
+
+ if ( !GetPoint(var, exception, p1) ) return true;
+ if ( !GetPoint(var, exception, p2) ) return true;
+
+ value = Math::Distance(p1, p2);
+ result->SetValFloat(value/g_unit);
+ return true;
+}
+
+// Instruction "distance2d(p1, p2)".
+
+bool rDistance2d(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ Math::Vector p1, p2;
+ float value;
+
+ if ( !GetPoint(var, exception, p1) ) return true;
+ if ( !GetPoint(var, exception, p2) ) return true;
+
+ value = Math::DistanceProjected(p1, p2);
+ result->SetValFloat(value/g_unit);
+ return true;
+}
+
+
+// Compilation of the instruction "space(center, rMin, rMax, dist)".
+
+CBotTypResult cSpace(CBotVar* &var, void* user)
+{
+ CBotTypResult ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotTypIntrinsic, "point");
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotTypIntrinsic, "point");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypIntrinsic, "point");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypIntrinsic, "point");
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypIntrinsic, "point");
+}
+
+// Instruction "space(center, rMin, rMax, dist)".
+
+bool rSpace(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ CBotVar* pSub;
+ Math::Vector center;
+ float rMin, rMax, dist;
+
+ rMin = 10.0f*g_unit;
+ rMax = 50.0f*g_unit;
+ dist = 4.0f*g_unit;
+
+ if ( var == 0 )
+ {
+ center = pThis->RetPosition(0);
+ }
+ else
+ {
+ if ( !GetPoint(var, exception, center) ) return true;
+
+ if ( var != 0 )
+ {
+ rMin = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+
+ if ( var != 0 )
+ {
+ rMax = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+
+ if ( var != 0 )
+ {
+ dist = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+ }
+ }
+ }
+ }
+ script->m_main->FreeSpace(center, rMin, rMax, dist, pThis);
+
+ if ( result != 0 )
+ {
+ pSub = result->GivItemList();
+ if ( pSub != 0 )
+ {
+ pSub->SetValFloat(center.x/g_unit);
+ pSub = pSub->GivNext(); // "y"
+ pSub->SetValFloat(center.z/g_unit);
+ pSub = pSub->GivNext(); // "z"
+ pSub->SetValFloat(center.y/g_unit);
+ }
+ }
+ return true;
+}
+
+
+// Compilation of the instruction "flatground(center, rMax)".
+
+CBotTypResult cFlatGround(CBotVar* &var, void* user)
+{
+ CBotTypResult ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "flatground(center, rMax)".
+
+bool rFlatGround(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ Math::Vector center;
+ float rMax, dist;
+
+ if ( !GetPoint(var, exception, center) ) return true;
+ rMax = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+
+ dist = script->m_main->RetFlatZoneRadius(center, rMax, pThis);
+ result->SetValFloat(dist/g_unit);
+
+ return true;
+}
+
+
+// Instruction "wait(t)".
+
+bool rWait(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ float value;
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ value = var->GivValFloat();
+ err = script->m_primaryTask->StartTaskWait(value);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Instruction "move(dist)".
+
+bool rMove(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ float value;
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ value = var->GivValFloat();
+ err = script->m_primaryTask->StartTaskAdvance(value*g_unit);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Instruction "turn(angle)".
+
+bool rTurn(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ float value;
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ value = var->GivValFloat();
+ err = script->m_primaryTask->StartTaskTurn(-value*Math::PI/180.0f);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Compilation of the instruction "goto(pos, altitude, crash, goal)".
+
+CBotTypResult cGoto(CBotVar* &var, void* user)
+{
+ CBotTypResult ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ return CBotTypResult(CBotErrOverParam);
+}
+
+// Instruction "goto(pos, altitude, mode)".
+
+bool rGoto(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ Math::Vector pos;
+ TaskGotoGoal goal;
+ TaskGotoCrash crash;
+ float altitude;
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ if ( !GetPoint(var, exception, pos) ) return true;
+
+ goal = TGG_DEFAULT;
+ crash = TGC_DEFAULT;
+ altitude = 0.0f*g_unit;
+
+ if ( var != 0 )
+ {
+ altitude = var->GivValFloat()*g_unit;
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ goal = (TaskGotoGoal)var->GivValInt();
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ crash = (TaskGotoCrash)var->GivValInt();
+ }
+ }
+ }
+
+ err = script->m_primaryTask->StartTaskGoto(pos, altitude, goal, crash);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Instruction "find(type)".
+
+bool rFind(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ Math::Vector pos;
+ TaskGotoGoal goal;
+ TaskGotoCrash crash;
+ float altitude;
+ Error err;
+ CObject* pThis = (CObject*)user;
+ CObject *pObj, *pBest;
+ CBotVar* array;
+ Math::Vector iPos, oPos;
+ float best, minDist, maxDist, sens, iAngle, angle, focus, d, a;
+ int type, oType, i;
+ bool bArray;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ type = OBJECT_NULL;
+ angle = 0.0f;
+ focus = Math::PI*2.0f;
+ minDist = 0.0f*g_unit;
+ maxDist = 1000.0f*g_unit;
+ sens = 1.0f;
+
+ if ( var->GivType() == CBotTypArrayPointer )
+ {
+ array = var->GivItemList();
+ bArray = true;
+ }
+ else
+ {
+ type = var->GivValInt();
+ bArray = false;
+ }
+
+ best = 100000.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+ if ( pObj == pThis ) continue;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+ if ( !pObj->RetActif() ) continue;
+ if ( pObj->RetProxyActivate() ) continue;
+
+ oType = pObj->RetType();
+ if ( oType == OBJECT_TOTO ) continue;
+
+ if ( oType == OBJECT_RUINmobilew2 ||
+ oType == OBJECT_RUINmobilet1 ||
+ oType == OBJECT_RUINmobilet2 ||
+ oType == OBJECT_RUINmobiler1 ||
+ oType == OBJECT_RUINmobiler2 )
+ {
+ oType = OBJECT_RUINmobilew1; // any ruin
+ }
+
+ if ( oType == OBJECT_SCRAP2 ||
+ oType == OBJECT_SCRAP3 ||
+ oType == OBJECT_SCRAP4 ||
+ oType == OBJECT_SCRAP5 ) // wastes?
+ {
+ oType = OBJECT_SCRAP1; // any waste
+ }
+
+ if ( oType == OBJECT_BARRIER2 ||
+ oType == OBJECT_BARRIER3 ) // barriers?
+ {
+ oType = OBJECT_BARRIER1; // any barrier
+ }
+
+ if ( bArray )
+ {
+ if ( !FindList(array, oType) ) continue;
+ }
+ else
+ {
+ if ( type != oType && type != OBJECT_NULL ) continue;
+ }
+
+ oPos = pObj->RetPosition(0);
+ d = Math::DistanceProjected(iPos, oPos);
+ if ( d < minDist || d > maxDist ) continue; // too close or too far?
+
+ if ( focus >= Math::PI*2.0f )
+ {
+ if ( d < best )
+ {
+ best = d;
+ pBest = pObj;
+ }
+ continue;
+ }
+
+ a = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW !
+ if ( Math::TestAngle(a, iAngle-focus/2.0f, iAngle+focus/2.0f) )
+ {
+ if ( d < best )
+ {
+ best = d;
+ pBest = pObj;
+ }
+ }
+ }
+
+ if ( pBest == 0 )
+ {
+ exception = ERR_FIND_IMPOSSIBLE;
+ return false;
+ }
+
+ pos = pBest->RetPosition(0);
+ goal = TGG_DEFAULT;
+ crash = TGC_DEFAULT;
+ altitude = 0.0f*g_unit;
+
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = script->m_primaryTask->StartTaskGoto(pos, altitude, goal, crash);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Compilation "grab/drop(oper)".
+
+CBotTypResult cGrabDrop(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "grab(oper)".
+
+bool rGrab(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ ObjectType oType;
+ TaskManipArm type;
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ if ( var == 0 ) type = TMA_FFRONT;
+ else type = (TaskManipArm)var->GivValInt();
+
+ oType = pThis->RetType();
+ if ( oType == OBJECT_HUMAN ||
+ oType == OBJECT_TECH )
+ {
+ err = script->m_primaryTask->StartTaskTake();
+ }
+ else
+ {
+ err = script->m_primaryTask->StartTaskManip(TMO_GRAB, type);
+ }
+
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Instruction "drop(oper)".
+
+bool rDrop(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ ObjectType oType;
+ TaskManipArm type;
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ if ( var == 0 ) type = TMA_FFRONT;
+ else type = (TaskManipArm)var->GivValInt();
+
+ oType = pThis->RetType();
+ if ( oType == OBJECT_HUMAN ||
+ oType == OBJECT_TECH )
+ {
+ err = script->m_primaryTask->StartTaskTake();
+ }
+ else
+ {
+ err = script->m_primaryTask->StartTaskManip(TMO_DROP, type);
+ }
+
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Instruction "sniff()".
+
+bool rSniff(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = script->m_primaryTask->StartTaskSearch();
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Compilation of the instruction "receive(nom, power)".
+
+CBotTypResult cReceive(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "receive(nom, power)".
+
+bool rReceive(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ CBotString cbs;
+ Error err;
+ const char* p;
+ float value, power;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+
+ cbs = var->GivValString();
+ p = cbs;
+ var = var->GivNext();
+
+ power = 10.0f*g_unit;
+ if ( var != 0 )
+ {
+ power = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+ }
+
+ err = script->m_primaryTask->StartTaskInfo((char*)p, 0.0f, power, false);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetInit(IS_NAN);
+ return true;
+ }
+ }
+ if ( !Process(script, result, exception) ) return false; // not finished
+
+ value = pThis->RetInfoReturn();
+ if ( value == NAN )
+ {
+ result->SetInit(IS_NAN);
+ }
+ else
+ {
+ result->SetValFloat(value);
+ }
+ return true;
+}
+
+// Compilation of the instruction "send(nom, value, power)".
+
+CBotTypResult cSend(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "send(nom, value, power)".
+
+bool rSend(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ CBotString cbs;
+ Error err;
+ const char* p;
+ float value, power;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+
+ cbs = var->GivValString();
+ p = cbs;
+ var = var->GivNext();
+
+ value = var->GivValFloat();
+ var = var->GivNext();
+
+ power = 10.0f*g_unit;
+ if ( var != 0 )
+ {
+ power = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+ }
+
+ err = script->m_primaryTask->StartTaskInfo((char*)p, value, power, true);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Seeks the nearest information terminal.
+
+CObject* SearchInfo(CScript* script, CObject* object, float power)
+{
+ CObject *pObj, *pBest;
+ Math::Vector iPos, oPos;
+ ObjectType type;
+ float dist, min;
+ int i;
+
+ iPos = object->RetPosition(0);
+
+ min = 100000.0f;
+ pBest = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type != OBJECT_INFO ) continue;
+
+ if ( !pObj->RetActif() ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::Distance(oPos, iPos);
+ if ( dist > power ) continue; // too far?
+ if ( dist < min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+
+ return pBest;
+}
+
+// Compilation of the instruction "deleteinfo(nom, power)".
+
+CBotTypResult cDeleteInfo(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "deleteinfo(nom, power)".
+
+bool rDeleteInfo(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ CObject* pInfo;
+ CBotString cbs;
+ Info info;
+ const char* p;
+ float power;
+ int i, total;
+
+ exception = 0;
+
+ cbs = var->GivValString();
+ p = cbs;
+ var = var->GivNext();
+
+ power = 10.0f*g_unit;
+ if ( var != 0 )
+ {
+ power = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+ }
+
+ pInfo = SearchInfo(script, pThis, power);
+ if ( pInfo == 0 )
+ {
+ result->SetValFloat(0.0f); // false
+ return true;
+ }
+
+ total = pInfo->RetInfoTotal();
+ for ( i=0 ; i<total ; i++ )
+ {
+ info = pInfo->RetInfo(i);
+ if ( strcmp(info.name, p) == 0 )
+ {
+ pInfo->DeleteInfo(i);
+ result->SetValFloat(1.0f); // true
+ return true;
+ }
+ }
+ result->SetValFloat(0.0f); // false
+ return true;
+}
+
+// Compilation of the instruction "testinfo(nom, power)".
+
+CBotTypResult cTestInfo(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypBoolean);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypBoolean);
+}
+
+// Instruction "testinfo(nom, power)".
+
+bool rTestInfo(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ CObject* pInfo;
+ CBotString cbs;
+ Info info;
+ const char* p;
+ float power;
+ int i, total;
+
+ exception = 0;
+
+ cbs = var->GivValString();
+ p = cbs;
+ var = var->GivNext();
+
+ power = 10.0f*g_unit;
+ if ( var != 0 )
+ {
+ power = var->GivValFloat()*g_unit;
+ var = var->GivNext();
+ }
+
+ pInfo = SearchInfo(script, pThis, power);
+ if ( pInfo == 0 )
+ {
+ result->SetValInt(false);
+ return true;
+ }
+
+ total = pInfo->RetInfoTotal();
+ for ( i=0 ; i<total ; i++ )
+ {
+ info = pInfo->RetInfo(i);
+ if ( strcmp(info.name, p) == 0 )
+ {
+ result->SetValInt(true);
+ return true;
+ }
+ }
+ result->SetValInt(false);
+ return true;
+}
+
+// Instruction "thump()".
+
+bool rThump(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = script->m_primaryTask->StartTaskTerraform();
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Instruction "recycle()".
+
+bool rRecycle(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = script->m_primaryTask->StartTaskRecover();
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Compilation "shield(oper, radius)".
+
+CBotTypResult cShield(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "shield(oper, radius)".
+
+bool rShield(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ float oper, radius;
+ Error err;
+
+ oper = var->GivValFloat(); // 0=down, 1=up
+ var = var->GivNext();
+
+ radius = var->GivValFloat();
+ if ( radius < 10.0f ) radius = 10.0f;
+ if ( radius > 25.0f ) radius = 25.0f;
+ radius = (radius-10.0f)/15.0f;
+
+ if ( *script->m_secondaryTask == 0 ) // shield folds?
+ {
+ if ( oper == 0.0f ) // down?
+ {
+ result->SetValInt(1); // shows the error
+ }
+ else // up ?
+ {
+ pThis->SetParam(radius);
+
+ *script->m_secondaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = (*script->m_secondaryTask)->StartTaskShield(TSM_UP, 1000.0f);
+ if ( err != ERR_OK )
+ {
+ delete *script->m_secondaryTask;
+ *script->m_secondaryTask = 0;
+ result->SetValInt(err); // shows the error
+ }
+ }
+ }
+ else // shield deployed?
+ {
+ if ( oper == 0.0f ) // down?
+ {
+ (*script->m_secondaryTask)->StartTaskShield(TSM_DOWN, 0.0f);
+ }
+ else // up?
+ {
+//? result->SetValInt(1); // shows the error
+ pThis->SetParam(radius);
+ (*script->m_secondaryTask)->StartTaskShield(TSM_UPDATE, 0.0f);
+ }
+ }
+
+ return true;
+}
+
+// Compilation "fire(delay)".
+
+CBotTypResult cFire(CBotVar* &var, void* user)
+{
+#if 0
+ CObject* pThis = (CObject*)user;
+ ObjectType type;
+
+ type = pThis->RetType();
+
+ if ( type == OBJECT_ANT )
+ {
+ return cOnePoint(var, user);
+ }
+ else if ( type == OBJECT_SPIDER )
+ {
+ return cNull(var, user);
+ }
+ else
+ {
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+ return CBotTypResult(CBotTypFloat);
+ }
+#else
+ return CBotTypResult(CBotTypFloat);
+#endif
+}
+
+// Instruction "fire(delay)".
+
+bool rFire(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ float delay;
+ Math::Vector impact;
+ Error err;
+ ObjectType type;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+
+ type = pThis->RetType();
+
+ if ( type == OBJECT_ANT )
+ {
+ if ( !GetPoint(var, exception, impact) ) return true;
+ impact.y += pThis->RetWaterLevel();
+ err = script->m_primaryTask->StartTaskFireAnt(impact);
+ }
+ else if ( type == OBJECT_SPIDER )
+ {
+ err = script->m_primaryTask->StartTaskSpiderExplo();
+ }
+ else
+ {
+ if ( var == 0 ) delay = 0.0f;
+ else delay = var->GivValFloat();
+ err = script->m_primaryTask->StartTaskFire(delay);
+ }
+
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ return true;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Instruction "aim(dir)".
+
+bool rAim(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ float value;
+ Error err;
+
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ value = var->GivValFloat();
+ err = script->m_primaryTask->StartTaskGunGoal(value*Math::PI/180.0f, 0.0f);
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ return true;
+ }
+ }
+ return Process(script, result, exception);
+}
+
+// Compilation of the instruction "motor(left, right)".
+
+CBotTypResult cMotor(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
+
+ return CBotTypResult(CBotTypFloat);
+}
+
+// Instruction "motor(left, right)".
+
+bool rMotor(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CObject* pThis = (CObject*)user;
+ CPhysics* physics = ((CObject*)user)->RetPhysics();
+ float left, right, speed, turn;
+
+ left = var->GivValFloat();
+ var = var->GivNext();
+ right = var->GivValFloat();
+
+ speed = (left+right)/2.0f;
+ if ( speed < -1.0f ) speed = -1.0f;
+ if ( speed > 1.0f ) speed = 1.0f;
+
+ turn = left-right;
+ if ( turn < -1.0f ) turn = -1.0f;
+ if ( turn > 1.0f ) turn = 1.0f;
+
+ if ( pThis->RetFixed() ) // ant on the back?
+ {
+ speed = 0.0f;
+ turn = 0.0f;
+ }
+
+ physics->SetMotorSpeedX(speed); // forward/backward
+ physics->SetMotorSpeedZ(turn); // turns
+
+ return true;
+}
+
+// Instruction "jet(power)".
+
+bool rJet(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CPhysics* physics = ((CObject*)user)->RetPhysics();
+ float value;
+
+ value = var->GivValFloat();
+ physics->SetMotorSpeedY(value);
+
+ return true;
+}
+
+// Compilation of the instruction "topo(pos)".
+
+CBotTypResult cTopo(CBotVar* &var, void* user)
+{
+ CBotTypResult ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ ret = cPoint(var, user);
+ if ( ret.GivType() != 0 ) return ret;
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ return CBotTypResult(CBotErrOverParam);
+}
+
+// Instruction "topo(pos)".
+
+bool rTopo(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ Math::Vector pos;
+ float level;
+
+ exception = 0;
+
+ if ( !GetPoint(var, exception, pos) ) return true;
+
+ level = script->m_terrain->RetFloorLevel(pos);
+ level -= script->m_water->RetLevel();
+ result->SetValFloat(level/g_unit);
+ return true;
+}
+
+// Compilation of the instruction "message(string, type)".
+
+CBotTypResult cMessage(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotErrLowParam);
+ if ( var->GivType() != CBotTypString &&
+ var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ return CBotTypResult(CBotErrOverParam);
+}
+
+// Instruction "message(string, type)".
+
+bool rMessage(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CBotString cbs;
+ const char* p;
+ TextType type;
+
+ cbs = var->GivValString();
+ p = cbs;
+
+ type = TT_MESSAGE;
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ type = (TextType)var->GivValInt();
+ }
+
+ script->m_displayText->DisplayText((char*)p, script->m_object, 10.0f, type);
+ script->m_main->CheckEndMessage((char*)p);
+
+ return true;
+}
+
+// Instruction "cmdline(rank)".
+
+bool rCmdline(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ float value;
+ int rank;
+
+ rank = var->GivValInt();
+ value = pThis->RetCmdLine(rank);
+ result->SetValFloat(value);
+
+ return true;
+}
+
+// Instruction "ismovie()".
+
+bool rIsMovie(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ float value;
+
+ value = script->m_main->RetMovieLock()?1.0f:0.0f;
+ result->SetValFloat(value);
+
+ return true;
+}
+
+// Instruction "errmode(mode)".
+
+bool rErrMode(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ int value;
+
+ value = var->GivValInt();
+ if ( value < 0 ) value = 0;
+ if ( value > 1 ) value = 1;
+ script->m_errMode = value;
+
+ return true;
+}
+
+// Instruction "ipf(num)".
+
+bool rIPF(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ int value;
+
+ value = var->GivValInt();
+ if ( value < 1 ) value = 1;
+ if ( value > 10000 ) value = 10000;
+ script->m_ipf = value;
+
+ return true;
+}
+
+// Instruction "abstime()".
+
+bool rAbsTime(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ float value;
+
+ value = script->m_main->RetGameTime();
+ result->SetValFloat(value);
+ return true;
+}
+
+
+// Prepares a file name.
+
+void PrepareFilename(CBotString &filename, char *dir)
+{
+ int pos;
+
+ pos = filename.ReverseFind('\\');
+ if ( pos > 0 )
+ {
+ filename = filename.Mid(pos+1); // removes folders
+ }
+
+ pos = filename.ReverseFind('/');
+ if ( pos > 0 )
+ {
+ filename = filename.Mid(pos+1); // also those with /
+ }
+
+ pos = filename.ReverseFind(':');
+ if ( pos > 0 )
+ {
+ filename = filename.Mid(pos+1); // also removes the drive letter C:
+ }
+
+ filename = CBotString(dir) + CBotString("\\") + filename;
+}
+
+// Instruction "deletefile(filename)".
+
+bool rDeleteFile(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CBotString cbs;
+ const char* p;
+ char* dir;
+
+ cbs = var->GivValString();
+ dir = script->m_main->RetFilesDir();
+ PrepareFilename(cbs, dir);
+ p = cbs;
+ DeleteFile(p);
+
+ return true;
+}
+
+// Compilation of the instruction "pendown(color, width)".
+
+CBotTypResult cPenDown(CBotVar* &var, void* user)
+{
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
+ var = var->GivNext();
+
+ if ( var == 0 ) return CBotTypResult(CBotTypFloat);
+ return CBotTypResult(CBotErrOverParam);
+}
+
+// Instruction "pendown(color, width)".
+
+bool rPenDown(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ int color;
+ float width;
+ Error err;
+
+ if ( pThis->RetType() == OBJECT_MOBILEdr )
+ {
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ if ( var != 0 )
+ {
+ color = var->GivValInt();
+ if ( color < 0 ) color = 0;
+ if ( color > 17 ) color = 17;
+ pThis->SetTraceColor(color);
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ width = var->GivValFloat();
+ if ( width < 0.1f ) width = 0.1f;
+ if ( width > 1.0f ) width = 1.0f;
+ pThis->SetTraceWidth(width);
+ }
+ }
+ pThis->SetTraceDown(true);
+
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = script->m_primaryTask->StartTaskPen(pThis->RetTraceDown(), pThis->RetTraceColor());
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+ }
+ return Process(script, result, exception);
+ }
+ else
+ {
+ if ( var != 0 )
+ {
+ color = var->GivValInt();
+ if ( color < 0 ) color = 0;
+ if ( color > 17 ) color = 17;
+ pThis->SetTraceColor(color);
+
+ var = var->GivNext();
+ if ( var != 0 )
+ {
+ width = var->GivValFloat();
+ if ( width < 0.1f ) width = 0.1f;
+ if ( width > 1.0f ) width = 1.0f;
+ pThis->SetTraceWidth(width);
+ }
+ }
+ pThis->SetTraceDown(true);
+
+ return true;
+ }
+}
+
+// Instruction "penup()".
+
+bool rPenUp(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CObject* pThis = (CObject*)user;
+ Error err;
+
+ if ( pThis->RetType() == OBJECT_MOBILEdr )
+ {
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ pThis->SetTraceDown(false);
+
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = script->m_primaryTask->StartTaskPen(pThis->RetTraceDown(), pThis->RetTraceColor());
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+ }
+ return Process(script, result, exception);
+ }
+ else
+ {
+ pThis->SetTraceDown(false);
+ return true;
+ }
+}
+
+// Instruction "pencolor()".
+
+bool rPenColor(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CScript* script = ((CObject*)user)->RetRunScript();
+ CPhysics* physics = ((CObject*)user)->RetPhysics();
+ CObject* pThis = (CObject*)user;
+ int color;
+ Error err;
+
+ if ( pThis->RetType() == OBJECT_MOBILEdr )
+ {
+ exception = 0;
+
+ if ( script->m_primaryTask == 0 ) // no task in progress?
+ {
+ color = var->GivValInt();
+ if ( color < 0 ) color = 0;
+ if ( color > 17 ) color = 17;
+ pThis->SetTraceColor(color);
+
+ script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object);
+ err = script->m_primaryTask->StartTaskPen(pThis->RetTraceDown(), pThis->RetTraceColor());
+ if ( err != ERR_OK )
+ {
+ delete script->m_primaryTask;
+ script->m_primaryTask = 0;
+ result->SetValInt(err); // shows the error
+ if ( script->m_errMode == ERM_STOP )
+ {
+ exception = err;
+ return false;
+ }
+ return true;
+ }
+ }
+ return Process(script, result, exception);
+ }
+ else
+ {
+ color = var->GivValInt();
+ if ( color < 0 ) color = 0;
+ if ( color > 17 ) color = 17;
+ pThis->SetTraceColor(color);
+
+ return true;
+ }
+}
+
+// Instruction "penwidth()".
+
+bool rPenWidth(CBotVar* var, CBotVar* result, int& exception, void* user)
+{
+ CObject* pThis = (CObject*)user;
+ float width;
+
+ width = var->GivValFloat();
+ if ( width < 0.1f ) width = 0.1f;
+ if ( width > 1.0f ) width = 1.0f;
+ pThis->SetTraceWidth(width);
+ return true;
+}
+
+
+
+// Object's constructor.
+
+CScript::CScript(CInstanceManager* iMan, CObject* object, CTaskManager** secondaryTask)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_SCRIPT, this, 100);
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+ m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ m_botProg = 0;
+ m_object = object;
+ m_primaryTask = 0;
+ m_secondaryTask = secondaryTask;
+
+ m_ipf = CBOT_IPF;
+ m_errMode = ERM_STOP;
+ m_len = 0;
+ m_script = 0;
+ m_bRun = false;
+ m_bStepMode = false;
+ m_bCompile = false;
+ m_title[0] = 0;
+ m_cursor1 = 0;
+ m_cursor2 = 0;
+ m_filename[0] = 0;
+}
+
+// Initializes all functions for module CBOT.
+
+void CScript::InitFonctions()
+{
+ CBotProgram::AddFunction("sin", rSin, cOneFloat);
+ CBotProgram::AddFunction("cos", rCos, cOneFloat);
+ CBotProgram::AddFunction("tan", rTan, cOneFloat);
+ CBotProgram::AddFunction("asin", raSin, cOneFloat);
+ CBotProgram::AddFunction("acos", raCos, cOneFloat);
+ CBotProgram::AddFunction("atan", raTan, cOneFloat);
+ CBotProgram::AddFunction("sqrt", rSqrt, cOneFloat);
+ CBotProgram::AddFunction("pow", rPow, cTwoFloat);
+ CBotProgram::AddFunction("rand", rRand, cNull);
+ CBotProgram::AddFunction("abs", rAbs, cOneFloat);
+
+ CBotProgram::AddFunction("retobject", rRetObject, cRetObject);
+ CBotProgram::AddFunction("search", rSearch, cSearch);
+ CBotProgram::AddFunction("radar", rRadar, cRadar);
+ CBotProgram::AddFunction("detect", rDetect, cDetect);
+ CBotProgram::AddFunction("direction", rDirection, cDirection);
+ CBotProgram::AddFunction("produce", rProduce, cProduce);
+ CBotProgram::AddFunction("distance", rDistance, cDistance);
+ CBotProgram::AddFunction("distance2d",rDistance2d,cDistance);
+ CBotProgram::AddFunction("space", rSpace, cSpace);
+ CBotProgram::AddFunction("flatground",rFlatGround,cFlatGround);
+ CBotProgram::AddFunction("wait", rWait, cOneFloat);
+ CBotProgram::AddFunction("move", rMove, cOneFloat);
+ CBotProgram::AddFunction("turn", rTurn, cOneFloat);
+ CBotProgram::AddFunction("goto", rGoto, cGoto);
+ CBotProgram::AddFunction("find", rFind, cOneFloat);
+ CBotProgram::AddFunction("grab", rGrab, cGrabDrop);
+ CBotProgram::AddFunction("drop", rDrop, cGrabDrop);
+ CBotProgram::AddFunction("sniff", rSniff, cNull);
+ CBotProgram::AddFunction("receive", rReceive, cReceive);
+ CBotProgram::AddFunction("send", rSend, cSend);
+ CBotProgram::AddFunction("deleteinfo",rDeleteInfo,cDeleteInfo);
+ CBotProgram::AddFunction("testinfo", rTestInfo, cTestInfo);
+ CBotProgram::AddFunction("thump", rThump, cNull);
+ CBotProgram::AddFunction("recycle", rRecycle, cNull);
+ CBotProgram::AddFunction("shield", rShield, cShield);
+ CBotProgram::AddFunction("fire", rFire, cFire);
+ CBotProgram::AddFunction("aim", rAim, cOneFloat);
+ CBotProgram::AddFunction("motor", rMotor, cMotor);
+ CBotProgram::AddFunction("jet", rJet, cOneFloat);
+ CBotProgram::AddFunction("topo", rTopo, cTopo);
+ CBotProgram::AddFunction("message", rMessage, cMessage);
+ CBotProgram::AddFunction("cmdline", rCmdline, cOneFloat);
+ CBotProgram::AddFunction("ismovie", rIsMovie, cNull);
+ CBotProgram::AddFunction("errmode", rErrMode, cOneFloat);
+ CBotProgram::AddFunction("ipf", rIPF, cOneFloat);
+ CBotProgram::AddFunction("abstime", rAbsTime, cNull);
+ CBotProgram::AddFunction("deletefile",rDeleteFile,cString);
+ CBotProgram::AddFunction("pendown", rPenDown, cPenDown);
+ CBotProgram::AddFunction("penup", rPenUp, cNull);
+ CBotProgram::AddFunction("pencolor", rPenColor, cOneFloat);
+ CBotProgram::AddFunction("penwidth", rPenWidth, cOneFloat);
+}
+
+// Object's destructor.
+
+CScript::~CScript()
+{
+ delete m_botProg;
+ delete m_primaryTask;
+ delete m_script;
+ m_script = 0;
+ m_len = 0;
+
+ m_iMan->DeleteInstance(CLASS_SCRIPT, this);
+}
+
+
+// Gives the script editable block of text.
+
+void CScript::PutScript(CEdit* edit, char* name)
+{
+ if ( m_script == 0 )
+ {
+ New(edit, name);
+ }
+ else
+ {
+ edit->SetText(m_script);
+ edit->SetCursor(m_cursor2, m_cursor1);
+ edit->ShowSelect();
+ }
+ edit->SetFocus(true);
+}
+
+// The script takes a paved text.
+
+bool CScript::GetScript(CEdit* edit)
+{
+ int len;
+
+ delete m_script;
+ m_script = 0;
+
+ len = edit->RetTextLength();
+ m_script = (char*)malloc(sizeof(char)*(len+1));
+
+ edit->GetText(m_script, len+1);
+ edit->GetCursor(m_cursor2, m_cursor1);
+ m_len = strlen(m_script);
+
+ if ( !CheckToken() )
+ {
+ edit->SetCursor(m_cursor2, m_cursor1);
+ edit->ShowSelect();
+ edit->SetFocus(true);
+ return false;
+ }
+
+ if ( !Compile() )
+ {
+ edit->SetCursor(m_cursor2, m_cursor1);
+ edit->ShowSelect();
+ edit->SetFocus(true);
+ return false;
+ }
+
+ return true;
+}
+
+// Indicates whether a program is compiled correctly.
+
+bool CScript::RetCompile()
+{
+ return m_bCompile;
+}
+
+// Indicates whether the program is empty.
+
+bool CScript::IsEmpty()
+{
+ int i;
+
+ for ( i=0 ; i<m_len ; i++ )
+ {
+ if ( m_script[i] != ' ' &&
+ m_script[i] != '\n' ) return false;
+ }
+ return true;
+}
+
+// Checks if a program does not contain the prohibited instructions
+// and if it contains well at least once every mandatory instructions.
+
+bool CScript::CheckToken()
+{
+ CBotToken* bt;
+ CBotString bs;
+ const char* token;
+ int error, type, cursor1, cursor2, i;
+ char used[100];
+
+ if ( !m_object->RetCheckToken() ) return true;
+
+ m_error = 0;
+ m_title[0] = 0;
+ m_token[0] = 0;
+ m_bCompile = false;
+
+ for ( i=0 ; i<m_main->RetObligatoryToken() ; i++ )
+ {
+ used[i] = 0; // token not used
+ }
+
+ bt = CBotToken::CompileTokens(m_script, error);
+ while ( bt != 0 )
+ {
+ bs = bt->GivString();
+ token = bs;
+ type = bt->GivType();
+
+ cursor1 = bt->GivStart();
+ cursor2 = bt->GivEnd();
+
+ i = m_main->IsObligatoryToken((char*)token);
+ if ( i != -1 )
+ {
+ used[i] = 1; // token used
+ }
+
+ if ( !m_main->IsProhibitedToken((char*)token) )
+ {
+ m_error = ERR_PROHIBITEDTOKEN;
+ m_cursor1 = cursor1;
+ m_cursor2 = cursor2;
+ strcpy(m_title, "<erreur>");
+ CBotToken::Delete(bt);
+ return false;
+ }
+
+ bt = bt->GivNext();
+ }
+
+ // At least once every obligatory instruction?
+ for ( i=0 ; i<m_main->RetObligatoryToken() ; i++ )
+ {
+ if ( used[i] == 0 ) // token not used?
+ {
+ strcpy(m_token, m_main->RetObligatoryToken(i));
+ m_error = ERR_OBLIGATORYTOKEN;
+ strcpy(m_title, "<erreur>");
+ CBotToken::Delete(bt);
+ return false;
+ }
+ }
+
+ CBotToken::Delete(bt);
+ return true;
+}
+
+// Compile the script of a paved text.
+
+bool CScript::Compile()
+{
+ CBotStringArray liste;
+ int i;
+ const char* p;
+
+ m_error = 0;
+ m_cursor1 = 0;
+ m_cursor2 = 0;
+ m_title[0] = 0;
+ m_bCompile = false;
+
+ if ( IsEmpty() ) // program exist?
+ {
+ delete m_botProg;
+ m_botProg = 0;
+ return true;
+ }
+
+ if ( m_botProg == 0 )
+ {
+ m_botProg = new CBotProgram(m_object->RetBotVar());
+ }
+
+ if ( m_botProg->Compile(m_script, liste, this) )
+ {
+ if ( liste.GivSize() == 0 )
+ {
+ strcpy(m_title, "<sans nom>");
+ }
+ else
+ {
+ p = liste[0];
+ i = 0;
+ while ( true )
+ {
+ if ( p[i] == 0 || p[i] == '(' ) break;
+ if ( i >= 20 )
+ {
+ m_title[i++] = '.';
+ m_title[i++] = '.';
+ m_title[i++] = '.';
+ break;
+ }
+ m_title[i] = p[i];
+ i ++;
+ }
+ m_title[i] = 0;
+ }
+ m_bCompile = true;
+ return true;
+ }
+ else
+ {
+ m_botProg->GetError(m_error, m_cursor1, m_cursor2);
+ if ( m_cursor1 < 0 || m_cursor1 > m_len ||
+ m_cursor2 < 0 || m_cursor2 > m_len )
+ {
+ m_cursor1 = 0;
+ m_cursor2 = 0;
+ }
+ if ( m_error == 0 )
+ {
+ m_cursor1 = m_cursor2 = 0;
+ }
+ strcpy(m_title, "<erreur>");
+ return false;
+ }
+}
+
+
+// Returns the title of the script.
+
+void CScript::GetTitle(char* buffer)
+{
+ strcpy(buffer, m_title);
+}
+
+
+// Choice of mode of execution.
+
+void CScript::SetStepMode(bool bStep)
+{
+ m_bStepMode = bStep;
+}
+
+
+// Runs the program from the beginning.
+
+bool CScript::Run()
+{
+ if( m_botProg == 0 ) return false;
+ if ( m_script == 0 || m_len == 0 ) return false;
+
+ if ( !m_botProg->Start(m_title) ) return false;
+
+ m_object->SetRunScript(this);
+ m_bRun = true;
+ m_bContinue = false;
+ m_ipf = CBOT_IPF;
+ m_errMode = ERM_STOP;
+
+ if ( m_bStepMode ) // step by step mode?
+ {
+ Event newEvent;
+ ZeroMemory(&newEvent, sizeof(Event));
+ Step(newEvent);
+ }
+
+ return true;
+}
+
+// Continues the execution of current program.
+// Returns true when execution is finished.
+
+bool CScript::Continue(const Event &event)
+{
+ if( m_botProg == 0 ) return true;
+ if ( !m_bRun ) return true;
+
+ m_event = event;
+
+ if ( m_bStepMode ) // step by step mode?
+ {
+ if ( m_bContinue ) // instuction "move", "goto", etc. ?
+ {
+ if ( m_botProg->Run(m_object, 0) )
+ {
+ m_botProg->GetError(m_error, m_cursor1, m_cursor2);
+ if ( m_cursor1 < 0 || m_cursor1 > m_len ||
+ m_cursor2 < 0 || m_cursor2 > m_len )
+ {
+ m_cursor1 = 0;
+ m_cursor2 = 0;
+ }
+ if ( m_error == 0 )
+ {
+ m_cursor1 = m_cursor2 = 0;
+ }
+ m_bRun = false;
+
+ if ( m_error != 0 && m_errMode == ERM_STOP )
+ {
+ char s[100];
+ GetError(s);
+ m_displayText->DisplayText(s, m_object, 10.0f, TT_ERROR);
+ }
+ m_engine->SetPause(true); // gives pause
+ return true;
+ }
+ if ( !m_bContinue )
+ {
+ m_engine->SetPause(true); // gives pause
+ }
+ }
+
+ return false;
+ }
+
+ if ( m_botProg->Run(m_object, m_ipf) )
+ {
+ m_botProg->GetError(m_error, m_cursor1, m_cursor2);
+ if ( m_cursor1 < 0 || m_cursor1 > m_len ||
+ m_cursor2 < 0 || m_cursor2 > m_len )
+ {
+ m_cursor1 = 0;
+ m_cursor2 = 0;
+ }
+ if ( m_error == 0 )
+ {
+ m_cursor1 = m_cursor2 = 0;
+ }
+ m_bRun = false;
+
+ if ( m_error != 0 && m_errMode == ERM_STOP )
+ {
+ char s[100];
+ GetError(s);
+ m_displayText->DisplayText(s, m_object, 10.0f, TT_ERROR);
+ }
+ return true;
+ }
+
+ return false;
+}
+
+// Continues the execution of current program.
+// Returns true when execution is finished.
+
+bool CScript::Step(const Event &event)
+{
+ if( m_botProg == 0 ) return true;
+ if ( !m_bRun ) return true;
+ if ( !m_bStepMode ) return false;
+
+ m_engine->SetPause(false);
+ m_engine->StepSimul(0.01f); // advance of 10ms
+ m_engine->SetPause(true);
+
+ m_event = event;
+
+ if ( m_botProg->Run(m_object, 0) ) // step mode
+ {
+ m_botProg->GetError(m_error, m_cursor1, m_cursor2);
+ if ( m_cursor1 < 0 || m_cursor1 > m_len ||
+ m_cursor2 < 0 || m_cursor2 > m_len )
+ {
+ m_cursor1 = 0;
+ m_cursor2 = 0;
+ }
+ if ( m_error == 0 )
+ {
+ m_cursor1 = m_cursor2 = 0;
+ }
+ m_bRun = false;
+
+ if ( m_error != 0 && m_errMode == ERM_STOP )
+ {
+ char s[100];
+ GetError(s);
+ m_displayText->DisplayText(s, m_object, 10.0f, TT_ERROR);
+ }
+ return true;
+ }
+
+ if ( m_bContinue ) // instuction "move", "goto", etc. ?
+ {
+ m_engine->SetPause(false); // removes the pause
+ }
+ return false;
+}
+
+// Stops the program.
+
+void CScript::Stop()
+{
+ if ( !m_bRun ) return;
+
+ if( m_botProg != 0 )
+ {
+ m_botProg->Stop();
+ }
+
+ if ( m_primaryTask != 0 )
+ {
+ m_primaryTask->Abort();
+ delete m_primaryTask;
+ m_primaryTask = 0;
+ }
+
+ m_bRun = false;
+}
+
+// Indicates whether the program runs.
+
+bool CScript::IsRunning()
+{
+ return m_bRun;
+}
+
+// Indicates whether the program continues a step.
+
+bool CScript::IsContinue()
+{
+ return m_bContinue;
+}
+
+
+// Gives the position of the cursor during the execution.
+
+bool CScript::GetCursor(int &cursor1, int &cursor2)
+{
+ const char* funcName;
+
+ cursor1 = cursor2 = 0;
+
+ if( m_botProg == 0 ) return false;
+ if ( !m_bRun ) return false;
+
+ m_botProg->GetRunPos(funcName, cursor1, cursor2);
+ if ( cursor1 < 0 || cursor1 > m_len ||
+ cursor2 < 0 || cursor2 > m_len )
+ {
+ cursor1 = 0;
+ cursor2 = 0;
+ }
+ return true;
+}
+
+
+// Put of the variables in a list.
+
+void PutList(char *baseName, bool bArray, CBotVar *var, CList *list, int &rankList)
+{
+ CBotString bs;
+ CBotVar *svar, *pStatic;
+ char varName[100];
+ char buffer[100];
+ const char *p;
+ int index, type;
+
+ if ( var == 0 && baseName[0] != 0 )
+ {
+ sprintf(buffer, "%s = null;", baseName);
+ list->SetName(rankList++, buffer);
+ return;
+ }
+
+ index = 0;
+ while ( var != 0 )
+ {
+ var->Maj(NULL, false);
+ pStatic = var->GivStaticVar(); // finds the static element
+
+ bs = pStatic->GivName(); // variable name
+ p = bs;
+//? if ( strcmp(p, "this") == 0 )
+//? {
+//? var = var->GivNext();
+//? continue;
+//? }
+
+ if ( baseName[0] == 0 )
+ {
+ sprintf(varName, "%s", p);
+ }
+ else
+ {
+ if ( bArray )
+ {
+ sprintf(varName, "%s[%d]", baseName, index);
+ }
+ else
+ {
+ sprintf(varName, "%s.%s", baseName, p);
+ }
+ }
+
+ type = pStatic->GivType();
+
+ if ( type < CBotTypBoolean )
+ {
+ CBotString value;
+ value = pStatic->GivValString();
+ p = value;
+ sprintf(buffer, "%s = %s;", varName, p);
+ list->SetName(rankList++, buffer);
+ }
+ else if ( type == CBotTypString )
+ {
+ CBotString value;
+ value = pStatic->GivValString();
+ p = value;
+ sprintf(buffer, "%s = \"%s\";", varName, p);
+ list->SetName(rankList++, buffer);
+ }
+ else if ( type == CBotTypArrayPointer )
+ {
+ svar = pStatic->GivItemList();
+ PutList(varName, true, svar, list, rankList);
+ }
+ else if ( type == CBotTypClass ||
+ type == CBotTypPointer )
+ {
+ svar = pStatic->GivItemList();
+ PutList(varName, false, svar, list, rankList);
+ }
+ else
+ {
+ sprintf(buffer, "%s = ?;", varName);
+ list->SetName(rankList++, buffer);
+ }
+
+ index ++;
+ var = var->GivNext();
+ }
+}
+
+// Fills a list with variables.
+
+void CScript::UpdateList(CList* list)
+{
+ CBotVar *var;
+ const char *progName, *funcName;
+ int total, select, level, cursor1, cursor2, rank;
+
+ if( m_botProg == 0 ) return;
+
+ total = list->RetTotal();
+ select = list->RetSelect();
+
+ list->Flush(); // empty list
+ m_botProg->GetRunPos(progName, cursor1, cursor2);
+ if ( progName == 0 ) return;
+
+ level = 0;
+ rank = 0;
+ while ( true )
+ {
+ var = m_botProg->GivStackVars(funcName, level--);
+ if ( funcName != progName ) break;
+
+ PutList("", false, var, list, rank);
+ }
+
+ if ( total == list->RetTotal() ) // same total?
+ {
+ list->SetSelect(select);
+ }
+
+ list->SetTooltip("");
+ list->SetState(STATE_ENABLE);
+}
+
+
+// Colorize the text according to syntax.
+
+void CScript::ColorizeScript(CEdit* edit)
+{
+ CBotToken* bt;
+ CBotString bs;
+ const char* token;
+ int error, type, cursor1, cursor2, color;
+
+ edit->ClearFormat();
+
+ bt = CBotToken::CompileTokens(edit->RetText(), error);
+ while ( bt != 0 )
+ {
+ bs = bt->GivString();
+ token = bs;
+ type = bt->GivType();
+
+ cursor1 = bt->GivStart();
+ cursor2 = bt->GivEnd();
+
+ color = 0;
+ if ( type >= TokenKeyWord && type < TokenKeyWord+100 )
+ {
+ color = COLOR_TOKEN;
+ }
+ if ( type >= TokenKeyDeclare && type < TokenKeyDeclare+100 )
+ {
+ color = COLOR_TYPE;
+ }
+ if ( type >= TokenKeyVal && type < TokenKeyVal+100 )
+ {
+ color = COLOR_CONST;
+ }
+ if ( type == TokenTypVar )
+ {
+ if ( IsType(token) )
+ {
+ color = COLOR_TYPE;
+ }
+ else if ( IsFunction(token) )
+ {
+ color = COLOR_TOKEN;
+ }
+ }
+ if ( type == TokenTypDef )
+ {
+ color = COLOR_CONST;
+ }
+
+ if ( cursor1 < cursor2 && color != 0 )
+ {
+ edit->SetFormat(cursor1, cursor2, color);
+ }
+
+ bt = bt->GivNext();
+ }
+
+ CBotToken::Delete(bt);
+}
+
+
+// Seeks a token at random in a script.
+// Returns the index of the start of the token found, or -1.
+
+int SearchToken(char* script, char* token)
+{
+ int lScript, lToken, i, iFound;
+ int found[100];
+ char* p;
+
+ lScript = strlen(script);
+ lToken = strlen(token);
+ iFound = 0;
+ for ( i=0 ; i<lScript-lToken ; i++ )
+ {
+ p = strstr(script+i, token);
+ if ( p != 0 )
+ {
+ found[iFound++] = p-script;
+ if ( iFound >= 100 ) break;
+ }
+ }
+
+ if ( iFound == 0 ) return -1;
+ return found[rand()%iFound];
+}
+
+// Removes a token in a script.
+
+void DeleteToken(char* script, int pos, int len)
+{
+ while ( true )
+ {
+ script[pos] = script[pos+len];
+ if ( script[pos++] == 0 ) break;
+ }
+}
+
+// Inserts a token in a script.
+
+void InsertToken(char* script, int pos, char* token)
+{
+ int lScript, lToken, i;
+
+ lScript = strlen(script);
+ lToken = strlen(token);
+ for ( i=lScript ; i>=pos ; i-- )
+ {
+ script[i+lToken] = script[i];
+ }
+ memcpy(script+pos, token, lToken);
+}
+
+// Introduces a virus into a program.
+
+bool CScript::IntroduceVirus()
+{
+ int i, start, iFound;
+ int found[11*2];
+ char* newScript;
+
+ char* names[11*2] =
+ {
+ "==", "!=",
+ "!=", "==",
+ ">", "<",
+ "<", ">",
+ "true", "false",
+ "false", "true",
+ "grab", "drop",
+ "drop", "grab",
+ "InFront", "Behind",
+ "Behind", "EnergyCell",
+ "EnergyCell", "InFront",
+ };
+
+ iFound = 0;
+ for ( i=0 ; i<11 ; i++ )
+ {
+ start = SearchToken(m_script, names[i*2]);
+ if ( start != -1 )
+ {
+ found[iFound++] = i*2;
+ found[iFound++] = start;
+ }
+ }
+ if ( iFound == 0 ) return false;
+
+ i = (rand()%(iFound/2))*2;
+ start = found[i+1];
+ i = found[i+0];
+
+ newScript = (char*)malloc(sizeof(char)*(m_len+strlen(names[i+1])+1));
+ strcpy(newScript, m_script);
+ delete m_script;
+ m_script = newScript;
+
+ DeleteToken(m_script, start, strlen(names[i]));
+ InsertToken(m_script, start, names[i+1]);
+ m_len = strlen(m_script);
+ Compile(); // recompile with the virus
+
+ return true;
+}
+
+
+// Returns the number of the error.
+
+int CScript::RetError()
+{
+ return m_error;
+}
+
+// Returns the text of the error.
+
+void CScript::GetError(char* buffer)
+{
+ if ( m_error == 0 )
+ {
+ buffer[0] = 0;
+ }
+ else
+ {
+ if ( m_error == ERR_OBLIGATORYTOKEN )
+ {
+ char s[100];
+ GetResource(RES_ERR, m_error, s);
+ sprintf(buffer, s, m_token);
+ }
+ else if ( m_error < 1000 )
+ {
+ GetResource(RES_ERR, m_error, buffer);
+ }
+ else
+ {
+ GetResource(RES_CBOT, m_error, buffer);
+ }
+ }
+}
+
+
+// New program.
+
+void CScript::New(CEdit* edit, char* name)
+{
+ FILE *file = NULL;
+ char res[100];
+ char text[100];
+ char filename[100];
+ char script[500];
+ char buffer[500];
+ char *sf;
+ int cursor1, cursor2, len, i, j;
+
+ GetResource(RES_TEXT, RT_SCRIPT_NEW, res);
+ if ( name[0] == 0 ) strcpy(text, res);
+ else strcpy(text, name);
+
+ sprintf(script, "extern void object::%s()\n{\n\t\n\t\n\t\n}\n", text);
+ edit->SetText(script, false);
+
+ if ( strcmp(text, res) == 0 )
+ {
+ cursor1 = 20;
+ cursor2 = 20+strlen(text); // update "New"
+ }
+ else
+ {
+ if ( edit->RetAutoIndent() )
+ {
+ cursor1 = 20+strlen(text)+6;
+ cursor2 = cursor1; // cursor in { }
+ }
+ else
+ {
+ cursor1 = 20+strlen(text)+8;
+ cursor2 = cursor1; // cursor in { }
+ }
+ }
+
+ edit->SetCursor(cursor2, cursor1);
+ edit->ShowSelect();
+ edit->SetFocus(true);
+
+ sf = m_main->RetScriptFile();
+ if ( sf[0] != 0 ) // Load an empty program specific?
+ {
+ strcpy(filename, "script\\");
+ strcat(filename, sf);
+ file = fopen(filename, "rb");
+ if ( file != NULL )
+ {
+ fseek(file, 0, SEEK_END);
+ len = ftell(file);
+ fseek(file, 0, SEEK_SET);
+
+ if ( len > 500-1 ) len = 500-1;
+ fread(buffer, 1, len, file);
+ buffer[len] = 0;
+ fclose(file);
+
+ cursor1 = 0;
+ i = 0;
+ j = 0;
+ while ( true )
+ {
+ if ( buffer[i] == 0 ) break;
+
+ if ( buffer[i] == '\r' )
+ {
+ i ++;
+ continue;
+ }
+
+ if ( buffer[i] == '\t' && edit->RetAutoIndent() )
+ {
+ i ++;
+ continue;
+ }
+
+ if ( buffer[i+0] == '%' &&
+ buffer[i+1] == 's' )
+ {
+ strcpy(script+j, text);
+ j += strlen(text);
+ i += 2;
+ continue;
+ }
+
+ if ( buffer[i] == '#' )
+ {
+ cursor1 = j;
+ i ++;
+ continue;
+ }
+
+ script[j++] = buffer[i++];
+ }
+ script[j] = 0;
+ edit->SetText(script, false);
+
+ cursor2 = cursor1;
+ edit->SetCursor(cursor2, cursor1);
+ edit->ShowSelect();
+ edit->SetFocus(true);
+ }
+ }
+
+ ColorizeScript(edit);
+}
+
+
+// Provided a script for all parts.
+
+bool CScript::SendScript(char* text)
+{
+ m_len = strlen(text);
+ m_script = (char*)malloc(sizeof(char)*(m_len+1));
+ strcpy(m_script, text);
+ if ( !CheckToken() ) return false;
+ if ( !Compile() ) return false;
+
+ return true;
+}
+
+// Reads a script as a text file.
+
+bool CScript::ReadScript(char* filename)
+{
+ FILE* file;
+ CEdit* edit;
+ char name[100];
+
+ if ( strchr(filename, '\\') == 0 )
+ {
+ strcpy(name, "script\\");
+ strcat(name, filename);
+ }
+ else
+ {
+//? strcpy(name, filename);
+ UserDir(name, filename, "");
+ }
+
+ file = fopen(name, "rb");
+ if ( file == NULL ) return false;
+ fclose(file);
+
+ delete m_script;
+ m_script = 0;
+
+ edit = m_interface->CreateEdit(Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f), 0, EVENT_EDIT9);
+ edit->SetMaxChar(EDITSTUDIOMAX);
+ edit->SetAutoIndent(m_engine->RetEditIndentMode());
+ edit->ReadText(name);
+ GetScript(edit);
+ m_interface->DeleteControl(EVENT_EDIT9);
+ return true;
+}
+
+// Writes a script as a text file.
+
+bool CScript::WriteScript(char* filename)
+{
+ CEdit* edit;
+ char name[100];
+
+ if ( strchr(filename, '\\') == 0 )
+ {
+ strcpy(name, "script\\");
+ strcat(name, filename);
+ }
+ else
+ {
+ strcpy(name, filename);
+ }
+
+ if ( m_script == 0 )
+ {
+ remove(filename);
+ return false;
+ }
+
+ edit = m_interface->CreateEdit(Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f), 0, EVENT_EDIT9);
+ edit->SetMaxChar(EDITSTUDIOMAX);
+ edit->SetAutoIndent(m_engine->RetEditIndentMode());
+ edit->SetText(m_script);
+ edit->WriteText(name);
+ m_interface->DeleteControl(EVENT_EDIT9);
+ return true;
+}
+
+
+// Reads a stack of script by execution as a file.
+
+bool CScript::ReadStack(FILE *file)
+{
+ int nb;
+
+ fRead(&nb, sizeof(int), 1, file);
+ fRead(&m_ipf, sizeof(int), 1, file);
+ fRead(&m_errMode, sizeof(int), 1, file);
+
+ if ( m_botProg == 0 ) return false;
+ if ( !m_botProg->RestoreState(file) ) return false;
+
+ m_object->SetRunScript(this);
+ m_bRun = true;
+ m_bContinue = false;
+ return true;
+}
+
+// Writes a stack of script by execution as a file.
+
+bool CScript::WriteStack(FILE *file)
+{
+ int nb;
+
+ nb = 2;
+ fWrite(&nb, sizeof(int), 1, file);
+ fWrite(&m_ipf, sizeof(int), 1, file);
+ fWrite(&m_errMode, sizeof(int), 1, file);
+
+ return m_botProg->SaveState(file);
+}
+
+
+// Compares two scripts.
+
+bool CScript::Compare(CScript* other)
+{
+ if ( m_len != other->m_len ) return false;
+
+ return ( strcmp(m_script, other->m_script) == 0 );
+}
+
+
+// Management of the file name when the script is saved.
+
+void CScript::SetFilename(char *filename)
+{
+ strcpy(m_filename, filename);
+}
+
+char* CScript::RetFilename()
+{
+ return m_filename;
+}
+
diff --git a/src/script/script.h b/src/script/script.h
index 2c7066c..8b2ae0b 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -1,118 +1,118 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// script.h
-
-#pragma once
-
-
-#include <stdio.h>
-
-#include "common/event.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CInterface;
-class CDisplayText;
-class CEdit;
-class CList;
-class CObject;
-class CTaskManager;
-class CBotProgram;
-class CRobotMain;
-class CTerrain;
-class CWater;
-
-
-
-class CScript
-{
-public:
- CScript(CInstanceManager* iMan, CObject* object, CTaskManager** secondaryTask);
- ~CScript();
-
- static void InitFonctions();
-
- void PutScript(CEdit* edit, char* name);
- bool GetScript(CEdit* edit);
- bool RetCompile();
-
- void GetTitle(char* buffer);
-
- void SetStepMode(bool bStep);
- bool Run();
- bool Continue(const Event &event);
- bool Step(const Event &event);
- void Stop();
- bool IsRunning();
- bool IsContinue();
- bool GetCursor(int &cursor1, int &cursor2);
- void UpdateList(CList* list);
- void ColorizeScript(CEdit* edit);
- bool IntroduceVirus();
-
- int RetError();
- void GetError(char* buffer);
-
- void New(CEdit* edit, char* name);
- bool SendScript(char* text);
- bool ReadScript(char* filename);
- bool WriteScript(char* filename);
- bool ReadStack(FILE *file);
- bool WriteStack(FILE *file);
- bool Compare(CScript* other);
-
- void SetFilename(char *filename);
- char* RetFilename();
-
-protected:
- bool IsEmpty();
- bool CheckToken();
- bool Compile();
-
-public:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CInterface* m_interface;
- CDisplayText* m_displayText;
- CBotProgram* m_botProg;
- CRobotMain* m_main;
- CTerrain* m_terrain;
- CWater* m_water;
- CTaskManager* m_primaryTask;
- CTaskManager** m_secondaryTask;
- CObject* m_object;
-
- int m_ipf; // number of instructions/second
- int m_errMode; // what to do in case of error
- int m_len; // length of the script (without <0>)
- char* m_script; // script ends with <0>
- bool m_bRun; // program during execution?
- bool m_bStepMode; // step by step
- bool m_bContinue; // external function to continue
- bool m_bCompile; // compilation ok?
- char m_title[50]; // script title
- char m_filename[50]; // file name
- char m_token[50]; // missing instruction
- int m_error; // error (0=ok)
- int m_cursor1;
- int m_cursor2;
- Event m_event;
- float m_returnValue;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// script.h
+
+#pragma once
+
+
+#include <stdio.h>
+
+#include "common/event.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CInterface;
+class CDisplayText;
+class CEdit;
+class CList;
+class CObject;
+class CTaskManager;
+class CBotProgram;
+class CRobotMain;
+class CTerrain;
+class CWater;
+
+
+
+class CScript
+{
+public:
+ CScript(CInstanceManager* iMan, CObject* object, CTaskManager** secondaryTask);
+ ~CScript();
+
+ static void InitFonctions();
+
+ void PutScript(CEdit* edit, char* name);
+ bool GetScript(CEdit* edit);
+ bool RetCompile();
+
+ void GetTitle(char* buffer);
+
+ void SetStepMode(bool bStep);
+ bool Run();
+ bool Continue(const Event &event);
+ bool Step(const Event &event);
+ void Stop();
+ bool IsRunning();
+ bool IsContinue();
+ bool GetCursor(int &cursor1, int &cursor2);
+ void UpdateList(CList* list);
+ void ColorizeScript(CEdit* edit);
+ bool IntroduceVirus();
+
+ int RetError();
+ void GetError(char* buffer);
+
+ void New(CEdit* edit, char* name);
+ bool SendScript(char* text);
+ bool ReadScript(char* filename);
+ bool WriteScript(char* filename);
+ bool ReadStack(FILE *file);
+ bool WriteStack(FILE *file);
+ bool Compare(CScript* other);
+
+ void SetFilename(char *filename);
+ char* RetFilename();
+
+protected:
+ bool IsEmpty();
+ bool CheckToken();
+ bool Compile();
+
+public:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CInterface* m_interface;
+ CDisplayText* m_displayText;
+ CBotProgram* m_botProg;
+ CRobotMain* m_main;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CTaskManager* m_primaryTask;
+ CTaskManager** m_secondaryTask;
+ CObject* m_object;
+
+ int m_ipf; // number of instructions/second
+ int m_errMode; // what to do in case of error
+ int m_len; // length of the script (without <0>)
+ char* m_script; // script ends with <0>
+ bool m_bRun; // program during execution?
+ bool m_bStepMode; // step by step
+ bool m_bContinue; // external function to continue
+ bool m_bCompile; // compilation ok?
+ char m_title[50]; // script title
+ char m_filename[50]; // file name
+ char m_token[50]; // missing instruction
+ int m_error; // error (0=ok)
+ int m_cursor1;
+ int m_cursor2;
+ Event m_event;
+ float m_returnValue;
+};
+
+
diff --git a/src/sound/sound.h b/src/sound/sound.h
index be63558..a2bfc76 100644
--- a/src/sound/sound.h
+++ b/src/sound/sound.h
@@ -27,139 +27,139 @@ class CInstanceManager;
namespace Snd {
-const int MAXFILES = 200;
-const int MAXSOUND = 32;
-const int MAXVOLUME = 20;
-const int MAXOPER = 4;
+const int MAXFILES = 200;
+const int MAXSOUND = 32;
+const int MAXVOLUME = 20;
+const int MAXOPER = 4;
enum Sound
{
- SOUND_CLICK = 0,
- SOUND_BOUM = 1,
- SOUND_EXPLO = 2,
- SOUND_FLYh = 3, // human
- SOUND_FLY = 4,
- SOUND_STEPs = 5, // smooth
- SOUND_MOTORw = 6, // wheel
- SOUND_MOTORt = 7, // tank
- SOUND_MOTORr = 8, // roller
- SOUND_ERROR = 9,
- SOUND_CONVERT = 10,
- SOUND_ENERGY = 11,
- SOUND_PLOUF = 12,
- SOUND_BLUP = 13,
- SOUND_WARNING = 14,
- SOUND_DERRICK = 15,
- SOUND_LABO = 16,
- SOUND_STATION = 17,
- SOUND_REPAIR = 18,
- SOUND_RESEARCH = 19,
- SOUND_INSECTs = 20, // spider
- SOUND_BURN = 21,
- SOUND_TZOING = 22,
- SOUND_GGG = 23,
- SOUND_MANIP = 24,
- SOUND_FIRE = 25, // shooting with fireball
- SOUND_HUMAN1 = 26, // breathing
- SOUND_STEPw = 27, // water
- SOUND_SWIM = 28,
- SOUND_RADAR = 29,
- SOUND_BUILD = 30,
- SOUND_ALARM = 31, // energy alarm
- SOUND_SLIDE = 32,
- SOUND_EXPLOi = 33, // insect
- SOUND_INSECTa = 34, // ant
- SOUND_INSECTb = 35, // bee
- SOUND_INSECTw = 36, // worm
- SOUND_INSECTm = 37, // mother
- SOUND_TREMBLE = 38,
- SOUND_PSHHH = 39,
- SOUND_NUCLEAR = 40,
- SOUND_INFO = 41,
- SOUND_OPEN = 42,
- SOUND_CLOSE = 43,
- SOUND_FACTORY = 44,
- SOUND_EGG = 45,
- SOUND_MOTORs = 46, // submarine
- SOUND_MOTORi = 47, // insect (legs)
- SOUND_SHIELD = 48,
- SOUND_FIREi = 49, // shooting with orgaball (insect)
- SOUND_GUNDEL = 50,
- SOUND_PSHHH2 = 51, // shield
- SOUND_MESSAGE = 52,
- SOUND_BOUMm = 53, // metal
- SOUND_BOUMv = 54, // plant
- SOUND_BOUMs = 55, // smooth
- SOUND_EXPLOl = 56, // little
- SOUND_EXPLOlp = 57, // little power
- SOUND_EXPLOp = 58, // power
- SOUND_STEPh = 59, // hard
- SOUND_STEPm = 60, // metal
- SOUND_POWERON = 61,
- SOUND_POWEROFF = 62,
- SOUND_AIE = 63,
- SOUND_WAYPOINT = 64,
- SOUND_RECOVER = 65,
- SOUND_DEADi = 66,
- SOUND_JOSTLE = 67,
- SOUND_GFLAT = 68,
- SOUND_DEADg = 69, // shooting death
- SOUND_DEADw = 70, // drowning
- SOUND_FLYf = 71, // reactor fail
- SOUND_ALARMt = 72, // temperature alarm
- SOUND_FINDING = 73, // finds a cache object
- SOUND_THUMP = 74,
- SOUND_TOUCH = 75,
- SOUND_BLITZ = 76,
- SOUND_MUSHROOM = 77,
- SOUND_FIREp = 78, // shooting with phazer
- SOUND_EXPLOg1 = 79, // impact gun 1
- SOUND_EXPLOg2 = 80, // impact gun 2
- SOUND_MOTORd = 81, // engine friction
+ SOUND_CLICK = 0,
+ SOUND_BOUM = 1,
+ SOUND_EXPLO = 2,
+ SOUND_FLYh = 3, // human
+ SOUND_FLY = 4,
+ SOUND_STEPs = 5, // smooth
+ SOUND_MOTORw = 6, // wheel
+ SOUND_MOTORt = 7, // tank
+ SOUND_MOTORr = 8, // roller
+ SOUND_ERROR = 9,
+ SOUND_CONVERT = 10,
+ SOUND_ENERGY = 11,
+ SOUND_PLOUF = 12,
+ SOUND_BLUP = 13,
+ SOUND_WARNING = 14,
+ SOUND_DERRICK = 15,
+ SOUND_LABO = 16,
+ SOUND_STATION = 17,
+ SOUND_REPAIR = 18,
+ SOUND_RESEARCH = 19,
+ SOUND_INSECTs = 20, // spider
+ SOUND_BURN = 21,
+ SOUND_TZOING = 22,
+ SOUND_GGG = 23,
+ SOUND_MANIP = 24,
+ SOUND_FIRE = 25, // shooting with fireball
+ SOUND_HUMAN1 = 26, // breathing
+ SOUND_STEPw = 27, // water
+ SOUND_SWIM = 28,
+ SOUND_RADAR = 29,
+ SOUND_BUILD = 30,
+ SOUND_ALARM = 31, // energy alarm
+ SOUND_SLIDE = 32,
+ SOUND_EXPLOi = 33, // insect
+ SOUND_INSECTa = 34, // ant
+ SOUND_INSECTb = 35, // bee
+ SOUND_INSECTw = 36, // worm
+ SOUND_INSECTm = 37, // mother
+ SOUND_TREMBLE = 38,
+ SOUND_PSHHH = 39,
+ SOUND_NUCLEAR = 40,
+ SOUND_INFO = 41,
+ SOUND_OPEN = 42,
+ SOUND_CLOSE = 43,
+ SOUND_FACTORY = 44,
+ SOUND_EGG = 45,
+ SOUND_MOTORs = 46, // submarine
+ SOUND_MOTORi = 47, // insect (legs)
+ SOUND_SHIELD = 48,
+ SOUND_FIREi = 49, // shooting with orgaball (insect)
+ SOUND_GUNDEL = 50,
+ SOUND_PSHHH2 = 51, // shield
+ SOUND_MESSAGE = 52,
+ SOUND_BOUMm = 53, // metal
+ SOUND_BOUMv = 54, // plant
+ SOUND_BOUMs = 55, // smooth
+ SOUND_EXPLOl = 56, // little
+ SOUND_EXPLOlp = 57, // little power
+ SOUND_EXPLOp = 58, // power
+ SOUND_STEPh = 59, // hard
+ SOUND_STEPm = 60, // metal
+ SOUND_POWERON = 61,
+ SOUND_POWEROFF = 62,
+ SOUND_AIE = 63,
+ SOUND_WAYPOINT = 64,
+ SOUND_RECOVER = 65,
+ SOUND_DEADi = 66,
+ SOUND_JOSTLE = 67,
+ SOUND_GFLAT = 68,
+ SOUND_DEADg = 69, // shooting death
+ SOUND_DEADw = 70, // drowning
+ SOUND_FLYf = 71, // reactor fail
+ SOUND_ALARMt = 72, // temperature alarm
+ SOUND_FINDING = 73, // finds a cache object
+ SOUND_THUMP = 74,
+ SOUND_TOUCH = 75,
+ SOUND_BLITZ = 76,
+ SOUND_MUSHROOM = 77,
+ SOUND_FIREp = 78, // shooting with phazer
+ SOUND_EXPLOg1 = 79, // impact gun 1
+ SOUND_EXPLOg2 = 80, // impact gun 2
+ SOUND_MOTORd = 81, // engine friction
};
enum SoundNext
{
- SOPER_CONTINUE = 1,
- SOPER_STOP = 2,
- SOPER_LOOP = 3,
+ SOPER_CONTINUE = 1,
+ SOPER_STOP = 2,
+ SOPER_LOOP = 3,
};
struct SoundOper
{
- char bUsed;
- float finalAmplitude;
- float finalFrequency;
- float totalTime;
- float currentTime;
- Snd::SoundNext nextOper;
+ char bUsed;
+ float finalAmplitude;
+ float finalFrequency;
+ float totalTime;
+ float currentTime;
+ Snd::SoundNext nextOper;
};
struct SoundChannel
{
- char bUsed; // buffer used?
- char bMute; // silence?
- Snd::Sound type; // SOUND_*
- int priority; // so great -> important
- Math::Vector pos; // position in space
- unsigned short uniqueStamp; // unique marker
-// LPDIRECTSOUNDBUFFER soundBuffer;
-// LPDIRECTSOUND3DBUFFER soundBuffer3D;
- float startAmplitude;
- float startFrequency;
- float changeFrequency;
- int initFrequency;
- float volume; // 2D: volume 1..0 depending on position
- float pan; // 2D: pan -1..+1 depending on position
- Snd::SoundOper oper[MAXOPER];
+ char bUsed; // buffer used?
+ char bMute; // silence?
+ Snd::Sound type; // SOUND_*
+ int priority; // so great -> important
+ Math::Vector pos; // position in space
+ unsigned short uniqueStamp; // unique marker
+// LPDIRECTSOUNDBUFFER soundBuffer;
+// LPDIRECTSOUND3DBUFFER soundBuffer3D;
+ float startAmplitude;
+ float startFrequency;
+ float changeFrequency;
+ int initFrequency;
+ float volume; // 2D: volume 1..0 depending on position
+ float pan; // 2D: pan -1..+1 depending on position
+ Snd::SoundOper oper[MAXOPER];
};
class CSound
{
- // TODO
+ // TODO
};
}; // namespace Sound
diff --git a/src/ui/button.cpp b/src/ui/button.cpp
index 3c398c8..0147f63 100644
--- a/src/ui/button.cpp
+++ b/src/ui/button.cpp
@@ -1,246 +1,246 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "common/language.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "ui/button.h"
-
-
-
-const float DELAY1 = 0.4f;
-const float DELAY2 = 0.1f;
-
-
-
-// Object's constructor.
-
-CButton::CButton(CInstanceManager* iMan) : CControl(iMan)
-{
- m_bCapture = false;
- m_bImmediat = false;
- m_bRepeat = false;
- m_repeat = 0.0f;
-}
-
-// Object's destructor.
-
-CButton::~CButton()
-{
-}
-
-
-// Creates a new button.
-
-bool CButton::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- CControl::Create(pos, dim, icon, eventMsg);
-
- if ( icon == -1 )
- {
- char name[100];
- char* p;
-
- GetResource(RES_EVENT, eventMsg, name);
- p = strchr(name, '\\');
- if ( p != 0 ) *p = 0;
- SetName(name);
- }
-
- return true;
-}
-
-
-// Management of an event.
-
-bool CButton::EventProcess(const Event &event)
-{
- if ( (m_state & STATE_VISIBLE) == 0 ) return true;
- if ( m_state & STATE_DEAD ) return true;
-
- CControl::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- if ( m_bRepeat && m_repeat != 0.0f )
- {
- m_repeat -= event.rTime;
- if ( m_repeat <= 0.0f )
- {
- m_repeat = DELAY2;
-
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- return false;
- }
- }
- }
-
- if ( event.event == EVENT_LBUTTONDOWN &&
- (m_state & STATE_VISIBLE) &&
- (m_state & STATE_ENABLE) )
- {
- if ( CControl::Detect(event.pos) )
- {
- m_bCapture = true;
- m_repeat = DELAY1;
-
- if ( m_bImmediat || m_bRepeat )
- {
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- }
- return false;
- }
- }
-
- if ( event.event == EVENT_MOUSEMOVE && m_bCapture )
- {
- }
-
- if ( event.event == EVENT_LBUTTONUP && m_bCapture )
- {
- if ( CControl::Detect(event.pos) )
- {
- if ( !m_bImmediat && !m_bRepeat )
- {
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- }
- }
-
- m_bCapture = false;
- m_repeat = 0.0f;
- }
-
- return true;
-}
-
-
-// Draw button.
-
-void CButton::Draw()
-{
- Math::Point pos, dim, uv1, uv2;
-#if !_NEWLOOK
- float dp;
-#endif
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return;
-
- if ( m_state & STATE_WARNING ) // shading yellow-black?
- {
- pos.x = m_pos.x-( 8.0f/640.0f);
- pos.y = m_pos.y-( 4.0f/480.0f);
- dim.x = m_dim.x+(16.0f/640.0f);
- dim.y = m_dim.y+( 8.0f/480.0f);
- if ( m_state & STATE_SHADOW )
- {
- DrawShadow(pos, dim);
- }
- DrawWarning(pos, dim);
- }
-
- if ( m_state & STATE_SHADOW )
- {
- DrawShadow(m_pos, m_dim);
- }
-
- CControl::Draw();
-
-#if !_NEWLOOK
- if ( m_name[0] != 0 && // button with the name?
- (m_state & STATE_CARD ) == 0 &&
- (m_state & STATE_SIMPLY) == 0 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
-
- dp = 0.5f/256.0f;
-
- uv1.x = 128.0f/256.0f;
- uv1.y = 96.0f/256.0f;
- uv2.x = 136.0f/256.0f;
- uv2.y = 128.0f/256.0f;
-
- if ( (m_state & STATE_ENABLE) == 0 )
- {
- uv1.x += 16.0f/256.0f;
- uv2.x += 16.0f/256.0f;
- }
-
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- pos.y = m_pos.y+5.0f/480.0f;
- dim.y = m_dim.y-10.0f/480.0f;
- pos.x = m_pos.x+5.0f/640.0f;
- dim.x = 3.0f/640.0f;
- DrawIcon(pos, dim, uv1, uv2, 0.0f);
-
- uv1.x += 8.0f/256.0f;
- uv2.x += 8.0f/256.0f;
- pos.x = m_pos.x+m_dim.x-5.0f/640.0f-3.0f/640.0f;
- DrawIcon(pos, dim, uv1, uv2, 0.0f);
- }
-#endif
-}
-
-
-// Management of immediate mode, which sends the event "press"
-// before the mouse button is released.
-
-void CButton::SetImmediat(bool bImmediat)
-{
- m_bImmediat = bImmediat;
-}
-
-bool CButton::RetImmediat()
-{
- return m_bImmediat;
-}
-
-
-// Mode management "autorepeat", when the button
-// mouse is held down.
-
-void CButton::SetRepeat(bool bRepeat)
-{
- m_bRepeat = bRepeat;
-}
-
-bool CButton::RetRepeat()
-{
- return m_bRepeat;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "common/language.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "ui/button.h"
+
+
+
+const float DELAY1 = 0.4f;
+const float DELAY2 = 0.1f;
+
+
+
+// Object's constructor.
+
+CButton::CButton(CInstanceManager* iMan) : CControl(iMan)
+{
+ m_bCapture = false;
+ m_bImmediat = false;
+ m_bRepeat = false;
+ m_repeat = 0.0f;
+}
+
+// Object's destructor.
+
+CButton::~CButton()
+{
+}
+
+
+// Creates a new button.
+
+bool CButton::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ CControl::Create(pos, dim, icon, eventMsg);
+
+ if ( icon == -1 )
+ {
+ char name[100];
+ char* p;
+
+ GetResource(RES_EVENT, eventMsg, name);
+ p = strchr(name, '\\');
+ if ( p != 0 ) *p = 0;
+ SetName(name);
+ }
+
+ return true;
+}
+
+
+// Management of an event.
+
+bool CButton::EventProcess(const Event &event)
+{
+ if ( (m_state & STATE_VISIBLE) == 0 ) return true;
+ if ( m_state & STATE_DEAD ) return true;
+
+ CControl::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ if ( m_bRepeat && m_repeat != 0.0f )
+ {
+ m_repeat -= event.rTime;
+ if ( m_repeat <= 0.0f )
+ {
+ m_repeat = DELAY2;
+
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ return false;
+ }
+ }
+ }
+
+ if ( event.event == EVENT_LBUTTONDOWN &&
+ (m_state & STATE_VISIBLE) &&
+ (m_state & STATE_ENABLE) )
+ {
+ if ( CControl::Detect(event.pos) )
+ {
+ m_bCapture = true;
+ m_repeat = DELAY1;
+
+ if ( m_bImmediat || m_bRepeat )
+ {
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ }
+ return false;
+ }
+ }
+
+ if ( event.event == EVENT_MOUSEMOVE && m_bCapture )
+ {
+ }
+
+ if ( event.event == EVENT_LBUTTONUP && m_bCapture )
+ {
+ if ( CControl::Detect(event.pos) )
+ {
+ if ( !m_bImmediat && !m_bRepeat )
+ {
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ }
+ }
+
+ m_bCapture = false;
+ m_repeat = 0.0f;
+ }
+
+ return true;
+}
+
+
+// Draw button.
+
+void CButton::Draw()
+{
+ Math::Point pos, dim, uv1, uv2;
+#if !_NEWLOOK
+ float dp;
+#endif
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return;
+
+ if ( m_state & STATE_WARNING ) // shading yellow-black?
+ {
+ pos.x = m_pos.x-( 8.0f/640.0f);
+ pos.y = m_pos.y-( 4.0f/480.0f);
+ dim.x = m_dim.x+(16.0f/640.0f);
+ dim.y = m_dim.y+( 8.0f/480.0f);
+ if ( m_state & STATE_SHADOW )
+ {
+ DrawShadow(pos, dim);
+ }
+ DrawWarning(pos, dim);
+ }
+
+ if ( m_state & STATE_SHADOW )
+ {
+ DrawShadow(m_pos, m_dim);
+ }
+
+ CControl::Draw();
+
+#if !_NEWLOOK
+ if ( m_name[0] != 0 && // button with the name?
+ (m_state & STATE_CARD ) == 0 &&
+ (m_state & STATE_SIMPLY) == 0 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+
+ dp = 0.5f/256.0f;
+
+ uv1.x = 128.0f/256.0f;
+ uv1.y = 96.0f/256.0f;
+ uv2.x = 136.0f/256.0f;
+ uv2.y = 128.0f/256.0f;
+
+ if ( (m_state & STATE_ENABLE) == 0 )
+ {
+ uv1.x += 16.0f/256.0f;
+ uv2.x += 16.0f/256.0f;
+ }
+
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+
+ pos.y = m_pos.y+5.0f/480.0f;
+ dim.y = m_dim.y-10.0f/480.0f;
+ pos.x = m_pos.x+5.0f/640.0f;
+ dim.x = 3.0f/640.0f;
+ DrawIcon(pos, dim, uv1, uv2, 0.0f);
+
+ uv1.x += 8.0f/256.0f;
+ uv2.x += 8.0f/256.0f;
+ pos.x = m_pos.x+m_dim.x-5.0f/640.0f-3.0f/640.0f;
+ DrawIcon(pos, dim, uv1, uv2, 0.0f);
+ }
+#endif
+}
+
+
+// Management of immediate mode, which sends the event "press"
+// before the mouse button is released.
+
+void CButton::SetImmediat(bool bImmediat)
+{
+ m_bImmediat = bImmediat;
+}
+
+bool CButton::RetImmediat()
+{
+ return m_bImmediat;
+}
+
+
+// Mode management "autorepeat", when the button
+// mouse is held down.
+
+void CButton::SetRepeat(bool bRepeat)
+{
+ m_bRepeat = bRepeat;
+}
+
+bool CButton::RetRepeat()
+{
+ return m_bRepeat;
+}
+
diff --git a/src/ui/button.h b/src/ui/button.h
index 34c4a96..0a05b11 100644
--- a/src/ui/button.h
+++ b/src/ui/button.h
@@ -1,56 +1,56 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// button.h
-
-#pragma once
-
-
-#include "ui/control.h"
-
-
-class CD3DEngine;
-
-
-
-class CButton : public CControl
-{
-public:
- CButton(CInstanceManager* iMan);
- virtual ~CButton();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
-
- bool EventProcess(const Event &event);
-
- void Draw();
-
- void SetImmediat(bool bRepeat);
- bool RetImmediat();
-
- void SetRepeat(bool bRepeat);
- bool RetRepeat();
-
-protected:
-
-protected:
- bool m_bCapture;
- bool m_bImmediat;
- bool m_bRepeat;
- float m_repeat;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// button.h
+
+#pragma once
+
+
+#include "ui/control.h"
+
+
+class CD3DEngine;
+
+
+
+class CButton : public CControl
+{
+public:
+ CButton(CInstanceManager* iMan);
+ virtual ~CButton();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+
+ bool EventProcess(const Event &event);
+
+ void Draw();
+
+ void SetImmediat(bool bRepeat);
+ bool RetImmediat();
+
+ void SetRepeat(bool bRepeat);
+ bool RetRepeat();
+
+protected:
+
+protected:
+ bool m_bCapture;
+ bool m_bImmediat;
+ bool m_bRepeat;
+ float m_repeat;
+};
+
+
diff --git a/src/ui/check.cpp b/src/ui/check.cpp
index 2b0466d..18c7633 100644
--- a/src/ui/check.cpp
+++ b/src/ui/check.cpp
@@ -1,166 +1,166 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "old/text.h"
-#include "ui/check.h"
-
-
-
-
-// Object's constructor.
-
-CCheck::CCheck(CInstanceManager* iMan) : CControl(iMan)
-{
-}
-
-// Object's destructor.
-
-CCheck::~CCheck()
-{
-}
-
-
-// Creates a new button.
-
-bool CCheck::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- char name[100];
- char* p;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- CControl::Create(pos, dim, icon, eventMsg);
-
- GetResource(RES_EVENT, eventMsg, name);
- p = strchr(name, '\\');
- if ( p != 0 ) *p = 0;
- SetName(name);
-
- return true;
-}
-
-
-// Management of an event.
-
-bool CCheck::EventProcess(const Event &event)
-{
- if ( m_state & STATE_DEAD ) return true;
-
- CControl::EventProcess(event);
-
- if ( event.event == EVENT_LBUTTONDOWN &&
- (m_state & STATE_VISIBLE) &&
- (m_state & STATE_ENABLE) )
- {
- if ( CControl::Detect(event.pos) )
- {
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- return false;
- }
- }
-
- return true;
-}
-
-
-// Draw button.
-
-void CCheck::Draw()
-{
- Math::Point iDim, pos;
- float zoomExt, zoomInt;
- int icon;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return;
-
- iDim = m_dim;
- m_dim.x = m_dim.y*0.75f; // square
-
- if ( m_state & STATE_SHADOW )
- {
- DrawShadow(m_pos, m_dim);
- }
-
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATENORMAL);
-
- zoomExt = 1.00f;
- zoomInt = 0.95f;
-
- icon = 2;
- if ( m_state & STATE_DEFAULT )
- {
- DrawPart(23, 1.3f, 0.0f);
-
- zoomExt *= 1.15f;
- zoomInt *= 1.15f;
- }
- if ( m_state & STATE_HILIGHT )
- {
- icon = 1;
- }
- if ( m_state & STATE_PRESS )
- {
- icon = 3;
- zoomInt *= 0.9f;
- }
- if ( (m_state & STATE_ENABLE) == 0 )
- {
- icon = 7;
- }
- if ( m_state & STATE_DEAD )
- {
- icon = 17;
- }
- DrawPart(icon, zoomExt, 0.0f); // draws the button
-
- if ( (m_state & STATE_DEAD) == 0 )
- {
- m_engine->SetState(D3DSTATETTw);
-
- if ( m_state & STATE_CHECK )
- {
- icon = 16; // seen
- DrawPart(icon, zoomInt, 0.0f); // draw the icon
- }
- }
-
- m_dim = iDim;
-
- if ( m_state & STATE_DEAD ) return;
-
- // Draw the name.
- pos.x = m_pos.x+m_dim.y/0.9f;
- pos.y = m_pos.y+m_dim.y*0.50f;
- pos.y -= m_engine->RetText()->RetHeight(m_fontSize, m_fontType)/2.0f;
- m_engine->RetText()->DrawText(m_name, pos, m_dim.x, 1, m_fontSize, m_fontStretch, m_fontType, 0);
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "old/text.h"
+#include "ui/check.h"
+
+
+
+
+// Object's constructor.
+
+CCheck::CCheck(CInstanceManager* iMan) : CControl(iMan)
+{
+}
+
+// Object's destructor.
+
+CCheck::~CCheck()
+{
+}
+
+
+// Creates a new button.
+
+bool CCheck::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ char name[100];
+ char* p;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ CControl::Create(pos, dim, icon, eventMsg);
+
+ GetResource(RES_EVENT, eventMsg, name);
+ p = strchr(name, '\\');
+ if ( p != 0 ) *p = 0;
+ SetName(name);
+
+ return true;
+}
+
+
+// Management of an event.
+
+bool CCheck::EventProcess(const Event &event)
+{
+ if ( m_state & STATE_DEAD ) return true;
+
+ CControl::EventProcess(event);
+
+ if ( event.event == EVENT_LBUTTONDOWN &&
+ (m_state & STATE_VISIBLE) &&
+ (m_state & STATE_ENABLE) )
+ {
+ if ( CControl::Detect(event.pos) )
+ {
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+// Draw button.
+
+void CCheck::Draw()
+{
+ Math::Point iDim, pos;
+ float zoomExt, zoomInt;
+ int icon;
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return;
+
+ iDim = m_dim;
+ m_dim.x = m_dim.y*0.75f; // square
+
+ if ( m_state & STATE_SHADOW )
+ {
+ DrawShadow(m_pos, m_dim);
+ }
+
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+
+ zoomExt = 1.00f;
+ zoomInt = 0.95f;
+
+ icon = 2;
+ if ( m_state & STATE_DEFAULT )
+ {
+ DrawPart(23, 1.3f, 0.0f);
+
+ zoomExt *= 1.15f;
+ zoomInt *= 1.15f;
+ }
+ if ( m_state & STATE_HILIGHT )
+ {
+ icon = 1;
+ }
+ if ( m_state & STATE_PRESS )
+ {
+ icon = 3;
+ zoomInt *= 0.9f;
+ }
+ if ( (m_state & STATE_ENABLE) == 0 )
+ {
+ icon = 7;
+ }
+ if ( m_state & STATE_DEAD )
+ {
+ icon = 17;
+ }
+ DrawPart(icon, zoomExt, 0.0f); // draws the button
+
+ if ( (m_state & STATE_DEAD) == 0 )
+ {
+ m_engine->SetState(D3DSTATETTw);
+
+ if ( m_state & STATE_CHECK )
+ {
+ icon = 16; // seen
+ DrawPart(icon, zoomInt, 0.0f); // draw the icon
+ }
+ }
+
+ m_dim = iDim;
+
+ if ( m_state & STATE_DEAD ) return;
+
+ // Draw the name.
+ pos.x = m_pos.x+m_dim.y/0.9f;
+ pos.y = m_pos.y+m_dim.y*0.50f;
+ pos.y -= m_engine->RetText()->RetHeight(m_fontSize, m_fontType)/2.0f;
+ m_engine->RetText()->DrawText(m_name, pos, m_dim.x, 1, m_fontSize, m_fontStretch, m_fontType, 0);
+}
+
+
diff --git a/src/ui/check.h b/src/ui/check.h
index 9c1f442..24c58f3 100644
--- a/src/ui/check.h
+++ b/src/ui/check.h
@@ -1,46 +1,46 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// check.h
-
-#pragma once
-
-
-#include "ui/control.h"
-
-
-class CD3DEngine;
-
-
-
-class CCheck : public CControl
-{
-public:
- CCheck(CInstanceManager* iMan);
- virtual ~CCheck();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
-
- bool EventProcess(const Event &event);
-
- void Draw();
-
-protected:
-
-protected:
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// check.h
+
+#pragma once
+
+
+#include "ui/control.h"
+
+
+class CD3DEngine;
+
+
+
+class CCheck : public CControl
+{
+public:
+ CCheck(CInstanceManager* iMan);
+ virtual ~CCheck();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+
+ bool EventProcess(const Event &event);
+
+ void Draw();
+
+protected:
+
+protected:
+};
+
+
diff --git a/src/ui/color.cpp b/src/ui/color.cpp
index 69513af..1038343 100644
--- a/src/ui/color.cpp
+++ b/src/ui/color.cpp
@@ -1,224 +1,224 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "common/language.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "ui/color.h"
-
-
-
-const float DELAY1 = 0.4f;
-const float DELAY2 = 0.1f;
-
-
-
-// Object's constructor.
-
-CColor::CColor(CInstanceManager* iMan) : CControl(iMan)
-{
- m_bRepeat = false;
- m_repeat = 0.0f;
-
- m_color.r = 0.0f;
- m_color.g = 0.0f;
- m_color.b = 0.0f;
- m_color.a = 0.0f;
-}
-
-// Object's destructor.
-
-CColor::~CColor()
-{
-}
-
-
-// Creates a new button.
-
-bool CColor::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- CControl::Create(pos, dim, icon, eventMsg);
-
- if ( icon == -1 )
- {
- char name[100];
- char* p;
-
- GetResource(RES_EVENT, eventMsg, name);
- p = strchr(name, '\\');
- if ( p != 0 ) *p = 0;
- SetName(name);
- }
-
- return true;
-}
-
-
-// Management of an event.
-
-bool CColor::EventProcess(const Event &event)
-{
- if ( m_state & STATE_DEAD ) return true;
-
- CControl::EventProcess(event);
-
- if ( event.event == EVENT_FRAME && m_bRepeat )
- {
- if ( m_repeat != 0.0f )
- {
- m_repeat -= event.rTime;
- if ( m_repeat <= 0.0f )
- {
- m_repeat = DELAY2;
-
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- return false;
- }
- }
- }
-
- if ( event.event == EVENT_LBUTTONDOWN &&
- (m_state & STATE_VISIBLE) &&
- (m_state & STATE_ENABLE) )
- {
- if ( CControl::Detect(event.pos) )
- {
- m_repeat = DELAY1;
-
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- return false;
- }
- }
-
- if ( event.event == EVENT_LBUTTONUP )
- {
- m_repeat = 0.0f;
- }
-
- return true;
-}
-
-
-// Dessine le bouton.
-
-void CColor::Draw()
-{
- LPDIRECT3DDEVICE7 device;
- D3DLVERTEX vertex[4]; // 2 triangles
- D3DCOLOR color;
- Math::Point p1, p2;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return;
-
- if ( m_state & STATE_SHADOW )
- {
- DrawShadow(m_pos, m_dim);
- }
-
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATENORMAL);
- CControl::Draw();
-
-#if _TEEN
- color = ::RetColor(m_color);
-
- m_engine->SetTexture("xxx.tga"); // no texture
- m_engine->SetState(D3DSTATENORMAL);
-
- device = m_engine->RetD3DDevice();
-
- p1.x = m_pos.x+(4.0f/640.0f);
- p1.y = m_pos.y+(4.0f/480.0f);
- p2.x = m_pos.x+m_dim.x-(4.0f/640.0f);
- p2.y = m_pos.y+m_dim.y-(4.0f/480.0f);
- vertex[0] = D3DLVERTEX(D3DVECTOR(p1.x, p1.y, 0.0f), 0x00000000,0x00000000, 0.0f,0.0f);
- vertex[1] = D3DLVERTEX(D3DVECTOR(p1.x, p2.y, 0.0f), 0x00000000,0x00000000, 0.0f,0.0f);
- vertex[2] = D3DLVERTEX(D3DVECTOR(p2.x, p1.y, 0.0f), 0x00000000,0x00000000, 0.0f,0.0f);
- vertex[3] = D3DLVERTEX(D3DVECTOR(p2.x, p2.y, 0.0f), 0x00000000,0x00000000, 0.0f,0.0f);
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, vertex, 4, NULL);
-
- p1.x = m_pos.x+(5.0f/640.0f);
- p1.y = m_pos.y+(5.0f/480.0f);
- p2.x = m_pos.x+m_dim.x-(5.0f/640.0f);
- p2.y = m_pos.y+m_dim.y-(5.0f/480.0f);
- vertex[0] = D3DLVERTEX(D3DVECTOR(p1.x, p1.y, 0.0f), color,0x00000000, 0.0f,0.0f);
- vertex[1] = D3DLVERTEX(D3DVECTOR(p1.x, p2.y, 0.0f), color,0x00000000, 0.0f,0.0f);
- vertex[2] = D3DLVERTEX(D3DVECTOR(p2.x, p1.y, 0.0f), color,0x00000000, 0.0f,0.0f);
- vertex[3] = D3DLVERTEX(D3DVECTOR(p2.x, p2.y, 0.0f), color,0x00000000, 0.0f,0.0f);
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, vertex, 4, NULL);
-
- m_engine->AddStatisticTriangle(4);
-#else
- p1.x = m_pos.x+(3.0f/640.0f);
- p1.y = m_pos.y+(3.0f/480.0f);
- p2.x = m_pos.x+m_dim.x-(3.0f/640.0f);
- p2.y = m_pos.y+m_dim.y-(3.0f/480.0f);
-
- color = ::RetColor(m_color);
-
- m_engine->SetTexture("xxx.tga"); // no texture
- m_engine->SetState(D3DSTATENORMAL);
-
- vertex[0] = D3DLVERTEX(D3DVECTOR(p1.x, p1.y, 0.0f), color,0x00000000, 0.0f,0.0f);
- vertex[1] = D3DLVERTEX(D3DVECTOR(p1.x, p2.y, 0.0f), color,0x00000000, 0.0f,0.0f);
- vertex[2] = D3DLVERTEX(D3DVECTOR(p2.x, p1.y, 0.0f), color,0x00000000, 0.0f,0.0f);
- vertex[3] = D3DLVERTEX(D3DVECTOR(p2.x, p2.y, 0.0f), color,0x00000000, 0.0f,0.0f);
-
- device = m_engine->RetD3DDevice();
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-#endif
-}
-
-
-void CColor::SetRepeat(bool bRepeat)
-{
- m_bRepeat = bRepeat;
-}
-
-bool CColor::RetRepeat()
-{
- return m_bRepeat;
-}
-
-
-void CColor::SetColor(D3DCOLORVALUE color)
-{
- m_color = color;
-}
-
-D3DCOLORVALUE CColor::RetColor()
-{
- return m_color;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "common/language.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "ui/color.h"
+
+
+
+const float DELAY1 = 0.4f;
+const float DELAY2 = 0.1f;
+
+
+
+// Object's constructor.
+
+CColor::CColor(CInstanceManager* iMan) : CControl(iMan)
+{
+ m_bRepeat = false;
+ m_repeat = 0.0f;
+
+ m_color.r = 0.0f;
+ m_color.g = 0.0f;
+ m_color.b = 0.0f;
+ m_color.a = 0.0f;
+}
+
+// Object's destructor.
+
+CColor::~CColor()
+{
+}
+
+
+// Creates a new button.
+
+bool CColor::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ CControl::Create(pos, dim, icon, eventMsg);
+
+ if ( icon == -1 )
+ {
+ char name[100];
+ char* p;
+
+ GetResource(RES_EVENT, eventMsg, name);
+ p = strchr(name, '\\');
+ if ( p != 0 ) *p = 0;
+ SetName(name);
+ }
+
+ return true;
+}
+
+
+// Management of an event.
+
+bool CColor::EventProcess(const Event &event)
+{
+ if ( m_state & STATE_DEAD ) return true;
+
+ CControl::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME && m_bRepeat )
+ {
+ if ( m_repeat != 0.0f )
+ {
+ m_repeat -= event.rTime;
+ if ( m_repeat <= 0.0f )
+ {
+ m_repeat = DELAY2;
+
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ return false;
+ }
+ }
+ }
+
+ if ( event.event == EVENT_LBUTTONDOWN &&
+ (m_state & STATE_VISIBLE) &&
+ (m_state & STATE_ENABLE) )
+ {
+ if ( CControl::Detect(event.pos) )
+ {
+ m_repeat = DELAY1;
+
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ return false;
+ }
+ }
+
+ if ( event.event == EVENT_LBUTTONUP )
+ {
+ m_repeat = 0.0f;
+ }
+
+ return true;
+}
+
+
+// Dessine le bouton.
+
+void CColor::Draw()
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DLVERTEX vertex[4]; // 2 triangles
+ D3DCOLOR color;
+ Math::Point p1, p2;
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return;
+
+ if ( m_state & STATE_SHADOW )
+ {
+ DrawShadow(m_pos, m_dim);
+ }
+
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ CControl::Draw();
+
+#if _TEEN
+ color = ::RetColor(m_color);
+
+ m_engine->SetTexture("xxx.tga"); // no texture
+ m_engine->SetState(D3DSTATENORMAL);
+
+ device = m_engine->RetD3DDevice();
+
+ p1.x = m_pos.x+(4.0f/640.0f);
+ p1.y = m_pos.y+(4.0f/480.0f);
+ p2.x = m_pos.x+m_dim.x-(4.0f/640.0f);
+ p2.y = m_pos.y+m_dim.y-(4.0f/480.0f);
+ vertex[0] = D3DLVERTEX(D3DVECTOR(p1.x, p1.y, 0.0f), 0x00000000,0x00000000, 0.0f,0.0f);
+ vertex[1] = D3DLVERTEX(D3DVECTOR(p1.x, p2.y, 0.0f), 0x00000000,0x00000000, 0.0f,0.0f);
+ vertex[2] = D3DLVERTEX(D3DVECTOR(p2.x, p1.y, 0.0f), 0x00000000,0x00000000, 0.0f,0.0f);
+ vertex[3] = D3DLVERTEX(D3DVECTOR(p2.x, p2.y, 0.0f), 0x00000000,0x00000000, 0.0f,0.0f);
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, vertex, 4, NULL);
+
+ p1.x = m_pos.x+(5.0f/640.0f);
+ p1.y = m_pos.y+(5.0f/480.0f);
+ p2.x = m_pos.x+m_dim.x-(5.0f/640.0f);
+ p2.y = m_pos.y+m_dim.y-(5.0f/480.0f);
+ vertex[0] = D3DLVERTEX(D3DVECTOR(p1.x, p1.y, 0.0f), color,0x00000000, 0.0f,0.0f);
+ vertex[1] = D3DLVERTEX(D3DVECTOR(p1.x, p2.y, 0.0f), color,0x00000000, 0.0f,0.0f);
+ vertex[2] = D3DLVERTEX(D3DVECTOR(p2.x, p1.y, 0.0f), color,0x00000000, 0.0f,0.0f);
+ vertex[3] = D3DLVERTEX(D3DVECTOR(p2.x, p2.y, 0.0f), color,0x00000000, 0.0f,0.0f);
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, vertex, 4, NULL);
+
+ m_engine->AddStatisticTriangle(4);
+#else
+ p1.x = m_pos.x+(3.0f/640.0f);
+ p1.y = m_pos.y+(3.0f/480.0f);
+ p2.x = m_pos.x+m_dim.x-(3.0f/640.0f);
+ p2.y = m_pos.y+m_dim.y-(3.0f/480.0f);
+
+ color = ::RetColor(m_color);
+
+ m_engine->SetTexture("xxx.tga"); // no texture
+ m_engine->SetState(D3DSTATENORMAL);
+
+ vertex[0] = D3DLVERTEX(D3DVECTOR(p1.x, p1.y, 0.0f), color,0x00000000, 0.0f,0.0f);
+ vertex[1] = D3DLVERTEX(D3DVECTOR(p1.x, p2.y, 0.0f), color,0x00000000, 0.0f,0.0f);
+ vertex[2] = D3DLVERTEX(D3DVECTOR(p2.x, p1.y, 0.0f), color,0x00000000, 0.0f,0.0f);
+ vertex[3] = D3DLVERTEX(D3DVECTOR(p2.x, p2.y, 0.0f), color,0x00000000, 0.0f,0.0f);
+
+ device = m_engine->RetD3DDevice();
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+#endif
+}
+
+
+void CColor::SetRepeat(bool bRepeat)
+{
+ m_bRepeat = bRepeat;
+}
+
+bool CColor::RetRepeat()
+{
+ return m_bRepeat;
+}
+
+
+void CColor::SetColor(D3DCOLORVALUE color)
+{
+ m_color = color;
+}
+
+D3DCOLORVALUE CColor::RetColor()
+{
+ return m_color;
+}
+
+
diff --git a/src/ui/color.h b/src/ui/color.h
index 8b912a9..41052a7 100644
--- a/src/ui/color.h
+++ b/src/ui/color.h
@@ -1,56 +1,56 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// color.h
-
-#pragma once
-
-
-#include "ui/control.h"
-#include "old/d3dengine.h"
-
-
-class CD3DEngine;
-
-
-
-class CColor : public CControl
-{
-public:
- CColor(CInstanceManager* iMan);
- virtual ~CColor();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
-
- bool EventProcess(const Event &event);
-
- void Draw();
-
- void SetRepeat(bool bRepeat);
- bool RetRepeat();
-
- void SetColor(D3DCOLORVALUE color);
- D3DCOLORVALUE RetColor();
-
-protected:
-
-protected:
- bool m_bRepeat;
- float m_repeat;
- D3DCOLORVALUE m_color;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// color.h
+
+#pragma once
+
+
+#include "ui/control.h"
+#include "old/d3dengine.h"
+
+
+class CD3DEngine;
+
+
+
+class CColor : public CControl
+{
+public:
+ CColor(CInstanceManager* iMan);
+ virtual ~CColor();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+
+ bool EventProcess(const Event &event);
+
+ void Draw();
+
+ void SetRepeat(bool bRepeat);
+ bool RetRepeat();
+
+ void SetColor(D3DCOLORVALUE color);
+ D3DCOLORVALUE RetColor();
+
+protected:
+
+protected:
+ bool m_bRepeat;
+ float m_repeat;
+ D3DCOLORVALUE m_color;
+};
+
+
diff --git a/src/ui/compass.cpp b/src/ui/compass.cpp
index 9d0ad2f..7ea6e9d 100644
--- a/src/ui/compass.cpp
+++ b/src/ui/compass.cpp
@@ -1,175 +1,175 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/geometry.h"
-#include "old/d3dengine.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "ui/compass.h"
-
-
-
-
-// Object's constructor.
-
-CCompass::CCompass(CInstanceManager* iMan) : CControl(iMan)
-{
- m_dir = 0.0f;
-}
-
-// Object's destructor.
-
-CCompass::~CCompass()
-{
-}
-
-
-// Creates a new button.
-
-bool CCompass::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- CControl::Create(pos, dim, icon, eventMsg);
- return true;
-}
-
-
-// Management of an event.
-
-bool CCompass::EventProcess(const Event &event)
-{
- CControl::EventProcess(event);
-
- if ( event.event == EVENT_LBUTTONDOWN )
- {
- if ( CControl::Detect(event.pos) )
- {
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- return false;
- }
- }
-
- return true;
-}
-
-
-// Draw button.
-
-void CCompass::Draw()
-{
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Point p1, p2, p3, c, uv1, uv2;
- Math::Vector n;
- float dp;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return;
-
- device = m_engine->RetD3DDevice();
-
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
-
- p1.x = m_pos.x;
- p1.y = m_pos.y;
- p2.x = m_pos.x + m_dim.x;
- p2.y = m_pos.y + m_dim.y;
-
- c.x = (p1.x+p2.x)/2.0f;
- c.y = (p1.y+p2.y)/2.0f; // center
-
- uv1.x = 64.0f/256.0f;
- uv1.y = 32.0f/256.0f;
- uv2.x = 96.0f/256.0f;
- uv2.y = 64.0f/256.0f;
-
- dp = 0.5f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x,uv2.y);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, uv1.x,uv1.y);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, uv2.x,uv2.y);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv2.x,uv1.y);
-
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-
- if ( m_state & STATE_ENABLE )
- {
- p1.x = c.x;
- p1.y = c.y+m_dim.x*0.40f;
- p1 = Math::RotatePoint(c, m_dir, p1);
- p1.x = c.x+(p1.x-c.x)*(m_dim.x/m_dim.y);
-
- p2.x = c.x+m_dim.x*0.20f;
- p2.y = c.y-m_dim.x*0.40f;
- p2 = Math::RotatePoint(c, m_dir, p2);
- p2.x = c.x+(p2.x-c.x)*(m_dim.x/m_dim.y);
-
- p3.x = c.x-m_dim.x*0.20f;
- p3.y = c.y-m_dim.x*0.40f;
- p3 = Math::RotatePoint(c, m_dir, p3);
- p3.x = c.x+(p3.x-c.x)*(m_dim.x/m_dim.y);
-
- uv1.x = 96.0f/256.0f;
- uv1.y = 32.0f/256.0f;
- uv2.x = 104.0f/256.0f;
- uv2.y = 64.0f/256.0f;
-
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x,uv1.y);
- vertex[1] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv1.x,uv2.y);
- vertex[2] = D3DVERTEX2(Math::Vector(p3.x, p3.y, 0.0f), n, uv2.x,uv2.y);
-
- device->DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_VERTEX2, vertex, 3, NULL);
- m_engine->AddStatisticTriangle(1);
- }
-}
-
-
-// Management directions of the compass.
-
-void CCompass::SetDirection(float dir)
-{
- m_dir = dir;
-}
-
-float CCompass::RetDirection()
-{
- return m_dir;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/geometry.h"
+#include "old/d3dengine.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "ui/compass.h"
+
+
+
+
+// Object's constructor.
+
+CCompass::CCompass(CInstanceManager* iMan) : CControl(iMan)
+{
+ m_dir = 0.0f;
+}
+
+// Object's destructor.
+
+CCompass::~CCompass()
+{
+}
+
+
+// Creates a new button.
+
+bool CCompass::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ CControl::Create(pos, dim, icon, eventMsg);
+ return true;
+}
+
+
+// Management of an event.
+
+bool CCompass::EventProcess(const Event &event)
+{
+ CControl::EventProcess(event);
+
+ if ( event.event == EVENT_LBUTTONDOWN )
+ {
+ if ( CControl::Detect(event.pos) )
+ {
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+// Draw button.
+
+void CCompass::Draw()
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Point p1, p2, p3, c, uv1, uv2;
+ Math::Vector n;
+ float dp;
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return;
+
+ device = m_engine->RetD3DDevice();
+
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+
+ p1.x = m_pos.x;
+ p1.y = m_pos.y;
+ p2.x = m_pos.x + m_dim.x;
+ p2.y = m_pos.y + m_dim.y;
+
+ c.x = (p1.x+p2.x)/2.0f;
+ c.y = (p1.y+p2.y)/2.0f; // center
+
+ uv1.x = 64.0f/256.0f;
+ uv1.y = 32.0f/256.0f;
+ uv2.x = 96.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+
+ dp = 0.5f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x,uv2.y);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, uv1.x,uv1.y);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, uv2.x,uv2.y);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv2.x,uv1.y);
+
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+
+ if ( m_state & STATE_ENABLE )
+ {
+ p1.x = c.x;
+ p1.y = c.y+m_dim.x*0.40f;
+ p1 = Math::RotatePoint(c, m_dir, p1);
+ p1.x = c.x+(p1.x-c.x)*(m_dim.x/m_dim.y);
+
+ p2.x = c.x+m_dim.x*0.20f;
+ p2.y = c.y-m_dim.x*0.40f;
+ p2 = Math::RotatePoint(c, m_dir, p2);
+ p2.x = c.x+(p2.x-c.x)*(m_dim.x/m_dim.y);
+
+ p3.x = c.x-m_dim.x*0.20f;
+ p3.y = c.y-m_dim.x*0.40f;
+ p3 = Math::RotatePoint(c, m_dir, p3);
+ p3.x = c.x+(p3.x-c.x)*(m_dim.x/m_dim.y);
+
+ uv1.x = 96.0f/256.0f;
+ uv1.y = 32.0f/256.0f;
+ uv2.x = 104.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x,uv1.y);
+ vertex[1] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv1.x,uv2.y);
+ vertex[2] = D3DVERTEX2(Math::Vector(p3.x, p3.y, 0.0f), n, uv2.x,uv2.y);
+
+ device->DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_VERTEX2, vertex, 3, NULL);
+ m_engine->AddStatisticTriangle(1);
+ }
+}
+
+
+// Management directions of the compass.
+
+void CCompass::SetDirection(float dir)
+{
+ m_dir = dir;
+}
+
+float CCompass::RetDirection()
+{
+ return m_dir;
+}
+
+
diff --git a/src/ui/compass.h b/src/ui/compass.h
index 5cad65a..0014f3d 100644
--- a/src/ui/compass.h
+++ b/src/ui/compass.h
@@ -1,50 +1,50 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// compass.h
-
-#pragma once
-
-
-#include "ui/control.h"
-
-
-class CD3DEngine;
-
-
-
-class CCompass : public CControl
-{
-public:
- CCompass(CInstanceManager* iMan);
- virtual ~CCompass();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
-
- bool EventProcess(const Event &event);
-
- void Draw();
-
- void SetDirection(float dir);
- float RetDirection();
-
-protected:
-
-protected:
- float m_dir;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// compass.h
+
+#pragma once
+
+
+#include "ui/control.h"
+
+
+class CD3DEngine;
+
+
+
+class CCompass : public CControl
+{
+public:
+ CCompass(CInstanceManager* iMan);
+ virtual ~CCompass();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+
+ bool EventProcess(const Event &event);
+
+ void Draw();
+
+ void SetDirection(float dir);
+ float RetDirection();
+
+protected:
+
+protected:
+ float m_dir;
+};
+
+
diff --git a/src/ui/control.cpp b/src/ui/control.cpp
index 525cab2..6ff7c2f 100644
--- a/src/ui/control.cpp
+++ b/src/ui/control.cpp
@@ -1,874 +1,874 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "common/language.h"
-#include "common/restext.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "object/robotmain.h"
-#include "old/particule.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/text.h"
-#include "old/sound.h"
-#include "ui/control.h"
-
-
-
-
-// Object's constructor.
-
-CControl::CControl(CInstanceManager* iMan)
-{
- m_iMan = iMan;
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- m_eventMsg = EVENT_NULL;
- m_state = STATE_ENABLE|STATE_VISIBLE|STATE_GLINT;
- m_fontSize = SMALLFONT;
- m_fontStretch = NORMSTRETCH;
- m_fontType = FONT_COLOBOT;
- m_justif = 0;
- m_name[0] = 0;
- m_tooltip[0] = 0;
- m_bFocus = false;
- m_bCapture = false;
-
- m_bGlint = false;
- m_glintCorner1 = Math::Point(0.0f, 0.0f);
- m_glintCorner2 = Math::Point(0.0f, 0.0f);
- m_glintProgress = 999.0f;
- m_glintMouse = Math::Point(0.0f, 0.0f);
-}
-
-// Object's destructor.
-
-CControl::~CControl()
-{
-}
-
-
-// Creates a new button.
-// pos: [0..1]
-
-bool CControl::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- char text[100];
- char* p;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- m_pos = pos;
- m_dim = dim;
- m_icon = icon;
- m_eventMsg = eventMsg;
-
- pos.x = m_pos.x;
- pos.y = m_pos.y+m_dim.y;
- GlintCreate(pos);
-
- GetResource(RES_EVENT, m_eventMsg, text);
- p = strchr(text, '\\');
- if ( p == 0 )
- {
- if ( icon != -1 )
- {
- strcpy(m_tooltip, text);
- }
- }
- else
- {
- strcpy(m_tooltip, p+1); // text after "\\"
- }
-
- return true;
-}
-
-
-void CControl::SetPos(Math::Point pos)
-{
- m_pos = pos;
-
- pos.x = m_pos.x;
- pos.y = m_pos.y+m_dim.y;
- GlintCreate(pos);
-}
-
-Math::Point CControl::RetPos()
-{
- return m_pos;
-}
-
-void CControl::SetDim(Math::Point dim)
-{
- Math::Point pos;
-
- m_dim = dim;
-
- pos.x = m_pos.x;
- pos.y = m_pos.y+m_dim.y;
- GlintCreate(pos);
-}
-
-Math::Point CControl::RetDim()
-{
- return m_dim;
-}
-
-
-// Modify an attribute of state.
-
-bool CControl::SetState(int state, bool bState)
-{
- if ( bState ) m_state |= state;
- else m_state &= ~state;
- return true;
-}
-
-// Sets an attribute of state.
-
-bool CControl::SetState(int state)
-{
- m_state |= state;
- return true;
-}
-
-// Removes an attribute of state.
-
-bool CControl::ClearState(int state)
-{
- m_state &= ~state;
- return true;
-}
-
-// Tests an attribute of state.
-
-bool CControl::TestState(int state)
-{
- return (m_state & state) ? true:false;
-}
-
-// Returns all attributes of state.
-
-int CControl::RetState()
-{
- return m_state;
-}
-
-
-// Management icon.
-
-void CControl::SetIcon(int icon)
-{
- m_icon = icon;
-}
-
-int CControl::RetIcon()
-{
- return m_icon;
-}
-
-
-// Management of the button name.
-
-void CControl::SetName(char* name, bool bTooltip)
-{
- char* p;
-
- if ( bTooltip )
- {
- p = strchr(name, '\\');
- if ( p == 0 )
- {
- strncpy(m_name, name, 100);
- m_name[100-1] = 0;
- }
- else
- {
- char buffer[100];
-
- strncpy(m_tooltip, p+1, 100); // text after "\\"
- m_tooltip[100-1] = 0;
-
- strncpy(buffer, name, 100);
- buffer[100-1] = 0;
- p = strchr(buffer, '\\');
- if ( p != 0 ) *p = 0;
- strncpy(m_name, buffer, 100);
- m_name[100-1] = 0;
- }
- }
- else
- {
- strncpy(m_name, name, 100);
- m_name[100-1] = 0;
- }
-}
-
-char* CControl::RetName()
-{
- return m_name;
-}
-
-
-// Management of the mode of justification (-1,0,1).
-
-void CControl::SetJustif(int mode)
-{
- m_justif = mode;
-}
-
-int CControl::RetJustif()
-{
- return m_justif;
-}
-
-
-// Management of the size of the font.
-
-void CControl::SetFontSize(float size)
-{
- m_fontSize = size;
-}
-
-float CControl::RetFontSize()
-{
- return m_fontSize;
-}
-
-
-// Management of the stretch of font.
-
-void CControl::SetFontStretch(float stretch)
-{
- m_fontStretch = stretch;
-}
-
-float CControl::RetFontStretch()
-{
- return m_fontStretch;
-}
-
-
-// Choice of the font.
-
-void CControl::SetFontType(FontType font)
-{
- m_fontType = font;
-}
-
-FontType CControl::RetFontType()
-{
- return m_fontType;
-}
-
-
-// Specifies the tooltip.
-
-bool CControl::SetTooltip(char* name)
-{
- strcpy(m_tooltip, name);
- return true;
-}
-
-bool CControl::GetTooltip(Math::Point pos, char* name)
-{
- if ( m_tooltip[0] == 0 ) return false;
- if ( (m_state & STATE_VISIBLE) == 0 ) return false;
- if ( (m_state & STATE_ENABLE) == 0 ) return false;
- if ( m_state & STATE_DEAD ) return false;
- if ( !Detect(pos) ) return false;
-
- strcpy(name, m_tooltip);
- return true;
-}
-
-
-// Management of the focus.
-
-void CControl::SetFocus(bool bFocus)
-{
- m_bFocus = bFocus;
-}
-
-bool CControl::RetFocus()
-{
- return m_bFocus;
-}
-
-
-// Returns the event associated with the control.
-
-EventMsg CControl::RetEventMsg()
-{
- return m_eventMsg;
-}
-
-
-// Management of an event.
-
-bool CControl::EventProcess(const Event &event)
-{
- if ( m_state & STATE_DEAD ) return true;
-
- if ( event.event == EVENT_FRAME && m_bGlint )
- {
- GlintFrame(event);
- }
-
- if ( event.event == EVENT_MOUSEMOVE )
- {
- m_glintMouse = event.pos;
-
- if ( Detect(event.pos) )
- {
- if ( (m_state & STATE_VISIBLE) &&
- (m_state & STATE_ENABLE ) )
- {
- m_engine->SetMouseType(D3DMOUSEHAND);
- }
- SetState(STATE_HILIGHT);
- }
- else
- {
- ClearState(STATE_HILIGHT);
- }
- }
-
- if ( event.event == EVENT_LBUTTONDOWN )
- {
- if ( Detect(event.pos) )
- {
- m_bCapture = true;
- SetState(STATE_PRESS);
- }
- }
-
- if ( event.event == EVENT_MOUSEMOVE && m_bCapture )
- {
- if ( Detect(event.pos) )
- {
- SetState(STATE_PRESS);
- }
- else
- {
- ClearState(STATE_PRESS);
- }
- }
-
- if ( event.event == EVENT_LBUTTONUP && m_bCapture )
- {
- m_bCapture = false;
- ClearState(STATE_PRESS);
- }
-
- return true;
-}
-
-
-// Removes the reflection.
-
-void CControl::GlintDelete()
-{
- m_bGlint = false;
-}
-
-// Creates a reflection for that button.
-
-void CControl::GlintCreate(Math::Point ref, bool bLeft, bool bUp)
-{
- float offset;
-
- offset = 8.0f/640.0f;
- if ( offset > m_dim.x/4.0f) offset = m_dim.x/4.0f;
-
- if ( bLeft )
- {
- m_glintCorner1.x = ref.x;
- m_glintCorner2.x = ref.x+offset;
- }
- else
- {
- m_glintCorner1.x = ref.x-offset;
- m_glintCorner2.x = ref.x;
- }
-
- offset = 8.0f/480.0f;
- if ( offset > m_dim.y/4.0f) offset = m_dim.y/4.0f;
-
- if ( bUp )
- {
- m_glintCorner1.y = ref.y-offset;
- m_glintCorner2.y = ref.y;
- }
- else
- {
- m_glintCorner1.y = ref.y;
- m_glintCorner2.y = ref.y+offset;
- }
-
- m_bGlint = true;
-}
-
-// Management of reflection.
-
-void CControl::GlintFrame(const Event &event)
-{
- Math::Vector pos, speed;
- Math::Point dim;
-
- if ( (m_state & STATE_GLINT ) == 0 ||
- (m_state & STATE_ENABLE ) == 0 ||
- (m_state & STATE_VISIBLE) == 0 ) return;
-
- if ( !m_main->RetGlint() ) return;
-
- m_glintProgress += event.rTime;
-
- if ( m_glintProgress >= 2.0f && Detect(m_glintMouse) )
- {
- pos.x = m_glintCorner1.x + (m_glintCorner2.x-m_glintCorner1.x)*Math::Rand();
- pos.y = m_glintCorner1.y + (m_glintCorner2.y-m_glintCorner1.y)*Math::Rand();
- pos.z = 0.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = ((15.0f+Math::Rand()*15.0f)/640.0f);
- dim.y = dim.x/0.75f;
- m_particule->CreateParticule(pos, speed, dim, PARTICONTROL,
- 1.0f, 0.0f, 0.0f, SH_INTERFACE);
-
- m_glintProgress = 0.0f;
- }
-}
-
-
-// Draw button.
-
-void CControl::Draw()
-{
- Math::Point pos;
- float zoomExt, zoomInt;
- int icon;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return;
-
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATENORMAL);
-
- zoomExt = 1.00f;
- zoomInt = 0.95f;
-
- if ( m_icon >= 128 )
- {
- zoomInt = 0.80f;
- }
-
- icon = 2;
- if ( m_state & STATE_CARD )
- {
- icon = 26;
- }
- if ( m_state & STATE_DEFAULT )
- {
- DrawPart(23, 1.3f, 0.0f);
-
- zoomExt *= 1.15f;
- zoomInt *= 1.15f;
- }
- if ( m_state & STATE_HILIGHT )
- {
- icon = 1;
- }
- if ( m_state & STATE_CHECK )
- {
- if ( m_state & STATE_CARD )
- {
- icon = 27;
- }
- else
- {
- icon = 0;
- }
- }
- if ( m_state & STATE_PRESS )
- {
- icon = 3;
- zoomInt *= 0.9f;
- }
- if ( (m_state & STATE_ENABLE) == 0 )
- {
- icon = 7;
- }
- if ( m_state & STATE_DEAD )
- {
- icon = 17;
- }
-
- if ( m_state & STATE_OKAY )
- {
- m_engine->SetTexture("button3.tga");
- icon = 3; // yellow with green point pressed
- }
-
- if ( m_name[0] == 0 ) // button without name?
- {
-//? DrawPart(icon, zoomExt, 0.0f);
- DrawPart(icon, zoomExt, 8.0f/256.0f);
-
- if ( m_state & STATE_DEAD ) return;
-
- icon = m_icon;
- if ( icon >= 192 )
- {
- icon -= 192;
-#if _POLISH
- m_engine->SetTexture("textp.tga");
-#else
- m_engine->SetTexture("text.tga");
-#endif
- m_engine->SetState(D3DSTATETTw);
- }
- else if ( icon >= 128 )
- {
- icon -= 128;
- m_engine->SetTexture("button3.tga");
- m_engine->SetState(D3DSTATETTw);
- }
- else if ( icon >= 64 )
- {
- icon -= 64;
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTw);
- }
- else
- {
- m_engine->SetState(D3DSTATETTw);
- }
- if ( icon != -1 )
- {
- DrawPart(icon, zoomInt, 0.0f);
- }
- }
- else // button with the name?
- {
- DrawPart(icon, 1.0f, 8.0f/256.0f);
-
- if ( m_state & STATE_DEAD ) return;
-
- if ( m_justif < 0 )
- {
- pos.x = m_pos.x+m_dim.x-m_dim.y*0.5f;
- pos.y = m_pos.y+m_dim.y*0.5f;
- pos.y -= m_engine->RetText()->RetHeight(m_fontSize, m_fontType)/2;
- m_engine->RetText()->DrawText(m_name, pos, m_dim.x, m_justif, m_fontSize, m_fontStretch, m_fontType, 0);
- }
- else if ( m_justif > 0 )
- {
- pos.x = m_pos.x+m_dim.y*0.5f;
- pos.y = m_pos.y+m_dim.y*0.5f;
- pos.y -= m_engine->RetText()->RetHeight(m_fontSize, m_fontType)/2.0f;
- m_engine->RetText()->DrawText(m_name, pos, m_dim.x, m_justif, m_fontSize, m_fontStretch, m_fontType, 0);
- }
- else
- {
- pos.x = m_pos.x+m_dim.x*0.5f;
- pos.y = m_pos.y+m_dim.y*0.5f;
- pos.y -= m_engine->RetText()->RetHeight(m_fontSize, m_fontType)/2.0f;
- m_engine->RetText()->DrawText(m_name, pos, m_dim.x, m_justif, m_fontSize, m_fontStretch, m_fontType, 0);
- }
- }
-}
-
-// Draw the vertex array.
-
-void CControl::DrawPart(int icon, float zoom, float ex)
-{
- Math::Point p1, p2, c, uv1, uv2;
- float dp;
-
- p1.x = m_pos.x;
- p1.y = m_pos.y;
- p2.x = m_pos.x + m_dim.x;
- p2.y = m_pos.y + m_dim.y;
-
- if ( (m_state & STATE_CARD ) &&
- (m_state & STATE_CHECK) )
- {
- p2.y += (2.0f/480.0f); // a bit above
- }
-
- c.x = (p1.x+p2.x)/2.0f;
- c.y = (p1.y+p2.y)/2.0f; // center
-
- p1.x = (p1.x-c.x)*zoom + c.x;
- p1.y = (p1.y-c.y)*zoom + c.y;
- p2.x = (p2.x-c.x)*zoom + c.x;
- p2.y = (p2.y-c.y)*zoom + c.y;
-
- p2.x -= p1.x;
- p2.y -= p1.y;
-
- uv1.x = (32.0f/256.0f)*(icon%8);
- uv1.y = (32.0f/256.0f)*(icon/8); // uv texture
- uv2.x = (32.0f/256.0f)+uv1.x;
- uv2.y = (32.0f/256.0f)+uv1.y;
-
- dp = 0.5f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- DrawIcon(p1, p2, uv1, uv2, ex);
-}
-
-// Draws an icon made up of a rectangular (if x = 0)
-// or 3 pieces.
-
-void CControl::DrawIcon(Math::Point pos, Math::Point dim, Math::Point uv1, Math::Point uv2,
- float ex)
-{
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2 vertex[8]; // 6 triangles
- Math::Point p1, p2, p3, p4;
- Math::Vector n;
-
- device = m_engine->RetD3DDevice();
-
- p1.x = pos.x;
- p1.y = pos.y;
- p2.x = pos.x + dim.x;
- p2.y = pos.y + dim.y;
-
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
-
- if ( ex == 0.0f ) // one piece?
- {
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x,uv2.y);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, uv1.x,uv1.y);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, uv2.x,uv2.y);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv2.x,uv1.y);
-
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
- }
- else // 3 pieces?
- {
- if ( dim.x >= dim.y )
- {
- p3.x = p1.x + ex*dim.y/(uv2.y-uv1.y);
- p4.x = p2.x - ex*dim.y/(uv2.y-uv1.y);
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x, uv2.y);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, uv1.x, uv1.y);
- vertex[2] = D3DVERTEX2(Math::Vector(p3.x, p1.y, 0.0f), n, uv1.x+ex,uv2.y);
- vertex[3] = D3DVERTEX2(Math::Vector(p3.x, p2.y, 0.0f), n, uv1.x+ex,uv1.y);
- vertex[4] = D3DVERTEX2(Math::Vector(p4.x, p1.y, 0.0f), n, uv2.x-ex,uv2.y);
- vertex[5] = D3DVERTEX2(Math::Vector(p4.x, p2.y, 0.0f), n, uv2.x-ex,uv1.y);
- vertex[6] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, uv2.x, uv2.y);
- vertex[7] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv2.x, uv1.y);
-
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 8, NULL);
- m_engine->AddStatisticTriangle(6);
- }
- else
- {
- p3.y = p1.y + ex*dim.x/(uv2.x-uv1.x);
- p4.y = p2.y - ex*dim.x/(uv2.x-uv1.x);
-
- vertex[0] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, uv2.x,uv2.y );
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x,uv2.y );
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p3.y, 0.0f), n, uv2.x,uv2.y-ex);
- vertex[3] = D3DVERTEX2(Math::Vector(p1.x, p3.y, 0.0f), n, uv1.x,uv2.y-ex);
- vertex[4] = D3DVERTEX2(Math::Vector(p2.x, p4.y, 0.0f), n, uv2.x,uv1.y+ex);
- vertex[5] = D3DVERTEX2(Math::Vector(p1.x, p4.y, 0.0f), n, uv1.x,uv1.y+ex);
- vertex[6] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv2.x,uv1.y );
- vertex[7] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, uv1.x,uv1.y );
-
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 8, NULL);
- m_engine->AddStatisticTriangle(6);
- }
- }
-}
-
-// Draws a rectangular icon made up of 9 pieces.
-
-void CControl::DrawIcon(Math::Point pos, Math::Point dim, Math::Point uv1, Math::Point uv2,
- Math::Point corner, float ex)
-{
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2 vertex[8]; // 6 triangles
- Math::Point p1, p2, p3, p4;
- Math::Vector n;
-
- device = m_engine->RetD3DDevice();
-
- p1.x = pos.x;
- p1.y = pos.y;
- p2.x = pos.x + dim.x;
- p2.y = pos.y + dim.y;
-
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
-
- if ( corner.x > dim.x/2.0f ) corner.x = dim.x/2.0f;
- if ( corner.y > dim.y/2.0f ) corner.y = dim.y/2.0f;
-
- p1.x = pos.x;
- p1.y = pos.y;
- p2.x = pos.x + dim.x;
- p2.y = pos.y + dim.y;
- p3.x = p1.x + corner.x;
- p3.y = p1.y + corner.y;
- p4.x = p2.x - corner.x;
- p4.y = p2.y - corner.y;
-
- // Bottom horizontal band.
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x, uv2.y );
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p3.y, 0.0f), n, uv1.x, uv2.y-ex);
- vertex[2] = D3DVERTEX2(Math::Vector(p3.x, p1.y, 0.0f), n, uv1.x+ex,uv2.y );
- vertex[3] = D3DVERTEX2(Math::Vector(p3.x, p3.y, 0.0f), n, uv1.x+ex,uv2.y-ex);
- vertex[4] = D3DVERTEX2(Math::Vector(p4.x, p1.y, 0.0f), n, uv2.x-ex,uv2.y );
- vertex[5] = D3DVERTEX2(Math::Vector(p4.x, p3.y, 0.0f), n, uv2.x-ex,uv2.y-ex);
- vertex[6] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, uv2.x, uv2.y );
- vertex[7] = D3DVERTEX2(Math::Vector(p2.x, p3.y, 0.0f), n, uv2.x, uv2.y-ex);
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 8, NULL);
- m_engine->AddStatisticTriangle(6);
-
- // Central horizontal band.
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p3.y, 0.0f), n, uv1.x, uv2.y-ex);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p4.y, 0.0f), n, uv1.x, uv1.y+ex);
- vertex[2] = D3DVERTEX2(Math::Vector(p3.x, p3.y, 0.0f), n, uv1.x+ex,uv2.y-ex);
- vertex[3] = D3DVERTEX2(Math::Vector(p3.x, p4.y, 0.0f), n, uv1.x+ex,uv1.y+ex);
- vertex[4] = D3DVERTEX2(Math::Vector(p4.x, p3.y, 0.0f), n, uv2.x-ex,uv2.y-ex);
- vertex[5] = D3DVERTEX2(Math::Vector(p4.x, p4.y, 0.0f), n, uv2.x-ex,uv1.y+ex);
- vertex[6] = D3DVERTEX2(Math::Vector(p2.x, p3.y, 0.0f), n, uv2.x, uv2.y-ex);
- vertex[7] = D3DVERTEX2(Math::Vector(p2.x, p4.y, 0.0f), n, uv2.x, uv1.y+ex);
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 8, NULL);
- m_engine->AddStatisticTriangle(6);
-
- // Top horizontal band.
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p4.y, 0.0f), n, uv1.x, uv1.y+ex);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, uv1.x, uv1.y );
- vertex[2] = D3DVERTEX2(Math::Vector(p3.x, p4.y, 0.0f), n, uv1.x+ex,uv1.y+ex);
- vertex[3] = D3DVERTEX2(Math::Vector(p3.x, p2.y, 0.0f), n, uv1.x+ex,uv1.y );
- vertex[4] = D3DVERTEX2(Math::Vector(p4.x, p4.y, 0.0f), n, uv2.x-ex,uv1.y+ex);
- vertex[5] = D3DVERTEX2(Math::Vector(p4.x, p2.y, 0.0f), n, uv2.x-ex,uv1.y );
- vertex[6] = D3DVERTEX2(Math::Vector(p2.x, p4.y, 0.0f), n, uv2.x, uv1.y+ex);
- vertex[7] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv2.x, uv1.y );
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 8, NULL);
- m_engine->AddStatisticTriangle(6);
-}
-
-// Draw round the hatch of a button.
-
-void CControl::DrawWarning(Math::Point pos, Math::Point dim)
-{
- Math::Point uv1, uv2;
- float dp;
-
- dp = 0.5f/256.0f;
-
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
-
- uv1.x = 64.0f/256.0f;
- uv1.y = 208.0f/256.0f;
- uv2.x = 160.0f/256.0f;
- uv2.y = 224.0f/256.0f;
-
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- if ( dim.x < dim.y*4.0f )
- {
- dim.y /= 2.0f;
- DrawIcon(pos, dim, uv1, uv2);
- pos.y += dim.y;
- DrawIcon(pos, dim, uv1, uv2);
- }
- else
- {
- dim.x /= 2.0f;
- dim.y /= 2.0f;
- DrawIcon(pos, dim, uv1, uv2);
- pos.x += dim.x;
- DrawIcon(pos, dim, uv1, uv2);
- pos.x -= dim.x;
- pos.y += dim.y;
- DrawIcon(pos, dim, uv1, uv2);
- pos.x += dim.x;
- DrawIcon(pos, dim, uv1, uv2);
- }
-}
-
-// Draw the shade under a button.
-
-void CControl::DrawShadow(Math::Point pos, Math::Point dim, float deep)
-{
- Math::Point uv1, uv2, corner;
- float dp;
-
- dp = 0.5f/256.0f;
-
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTw);
-
- pos.x += deep*0.010f*0.75f;
- pos.y -= deep*0.015f;
- dim.x += deep*0.005f*0.75f;
- dim.y += deep*0.005f;
-
- uv1.x = 192.0f/256.0f;
- uv1.y = 32.0f/256.0f;
- uv2.x = 224.0f/256.0f;
- uv2.y = 64.0f/256.0f;
-
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- corner.x = 10.0f/640.0f;
- corner.y = 10.0f/480.0f;
-
- DrawIcon(pos, dim, uv1, uv2, corner, 6.0f/256.0f);
-}
-
-
-// Detects whether a position is in the button.
-
-bool CControl::Detect(Math::Point pos)
-{
- return ( pos.x >= m_pos.x &&
- pos.x <= m_pos.x+m_dim.x &&
- pos.y >= m_pos.y &&
- pos.y <= m_pos.y+m_dim.y );
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "common/language.h"
+#include "common/restext.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "object/robotmain.h"
+#include "old/particule.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/text.h"
+#include "old/sound.h"
+#include "ui/control.h"
+
+
+
+
+// Object's constructor.
+
+CControl::CControl(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ m_eventMsg = EVENT_NULL;
+ m_state = STATE_ENABLE|STATE_VISIBLE|STATE_GLINT;
+ m_fontSize = SMALLFONT;
+ m_fontStretch = NORMSTRETCH;
+ m_fontType = FONT_COLOBOT;
+ m_justif = 0;
+ m_name[0] = 0;
+ m_tooltip[0] = 0;
+ m_bFocus = false;
+ m_bCapture = false;
+
+ m_bGlint = false;
+ m_glintCorner1 = Math::Point(0.0f, 0.0f);
+ m_glintCorner2 = Math::Point(0.0f, 0.0f);
+ m_glintProgress = 999.0f;
+ m_glintMouse = Math::Point(0.0f, 0.0f);
+}
+
+// Object's destructor.
+
+CControl::~CControl()
+{
+}
+
+
+// Creates a new button.
+// pos: [0..1]
+
+bool CControl::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ char text[100];
+ char* p;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ m_pos = pos;
+ m_dim = dim;
+ m_icon = icon;
+ m_eventMsg = eventMsg;
+
+ pos.x = m_pos.x;
+ pos.y = m_pos.y+m_dim.y;
+ GlintCreate(pos);
+
+ GetResource(RES_EVENT, m_eventMsg, text);
+ p = strchr(text, '\\');
+ if ( p == 0 )
+ {
+ if ( icon != -1 )
+ {
+ strcpy(m_tooltip, text);
+ }
+ }
+ else
+ {
+ strcpy(m_tooltip, p+1); // text after "\\"
+ }
+
+ return true;
+}
+
+
+void CControl::SetPos(Math::Point pos)
+{
+ m_pos = pos;
+
+ pos.x = m_pos.x;
+ pos.y = m_pos.y+m_dim.y;
+ GlintCreate(pos);
+}
+
+Math::Point CControl::RetPos()
+{
+ return m_pos;
+}
+
+void CControl::SetDim(Math::Point dim)
+{
+ Math::Point pos;
+
+ m_dim = dim;
+
+ pos.x = m_pos.x;
+ pos.y = m_pos.y+m_dim.y;
+ GlintCreate(pos);
+}
+
+Math::Point CControl::RetDim()
+{
+ return m_dim;
+}
+
+
+// Modify an attribute of state.
+
+bool CControl::SetState(int state, bool bState)
+{
+ if ( bState ) m_state |= state;
+ else m_state &= ~state;
+ return true;
+}
+
+// Sets an attribute of state.
+
+bool CControl::SetState(int state)
+{
+ m_state |= state;
+ return true;
+}
+
+// Removes an attribute of state.
+
+bool CControl::ClearState(int state)
+{
+ m_state &= ~state;
+ return true;
+}
+
+// Tests an attribute of state.
+
+bool CControl::TestState(int state)
+{
+ return (m_state & state) ? true:false;
+}
+
+// Returns all attributes of state.
+
+int CControl::RetState()
+{
+ return m_state;
+}
+
+
+// Management icon.
+
+void CControl::SetIcon(int icon)
+{
+ m_icon = icon;
+}
+
+int CControl::RetIcon()
+{
+ return m_icon;
+}
+
+
+// Management of the button name.
+
+void CControl::SetName(char* name, bool bTooltip)
+{
+ char* p;
+
+ if ( bTooltip )
+ {
+ p = strchr(name, '\\');
+ if ( p == 0 )
+ {
+ strncpy(m_name, name, 100);
+ m_name[100-1] = 0;
+ }
+ else
+ {
+ char buffer[100];
+
+ strncpy(m_tooltip, p+1, 100); // text after "\\"
+ m_tooltip[100-1] = 0;
+
+ strncpy(buffer, name, 100);
+ buffer[100-1] = 0;
+ p = strchr(buffer, '\\');
+ if ( p != 0 ) *p = 0;
+ strncpy(m_name, buffer, 100);
+ m_name[100-1] = 0;
+ }
+ }
+ else
+ {
+ strncpy(m_name, name, 100);
+ m_name[100-1] = 0;
+ }
+}
+
+char* CControl::RetName()
+{
+ return m_name;
+}
+
+
+// Management of the mode of justification (-1,0,1).
+
+void CControl::SetJustif(int mode)
+{
+ m_justif = mode;
+}
+
+int CControl::RetJustif()
+{
+ return m_justif;
+}
+
+
+// Management of the size of the font.
+
+void CControl::SetFontSize(float size)
+{
+ m_fontSize = size;
+}
+
+float CControl::RetFontSize()
+{
+ return m_fontSize;
+}
+
+
+// Management of the stretch of font.
+
+void CControl::SetFontStretch(float stretch)
+{
+ m_fontStretch = stretch;
+}
+
+float CControl::RetFontStretch()
+{
+ return m_fontStretch;
+}
+
+
+// Choice of the font.
+
+void CControl::SetFontType(FontType font)
+{
+ m_fontType = font;
+}
+
+FontType CControl::RetFontType()
+{
+ return m_fontType;
+}
+
+
+// Specifies the tooltip.
+
+bool CControl::SetTooltip(char* name)
+{
+ strcpy(m_tooltip, name);
+ return true;
+}
+
+bool CControl::GetTooltip(Math::Point pos, char* name)
+{
+ if ( m_tooltip[0] == 0 ) return false;
+ if ( (m_state & STATE_VISIBLE) == 0 ) return false;
+ if ( (m_state & STATE_ENABLE) == 0 ) return false;
+ if ( m_state & STATE_DEAD ) return false;
+ if ( !Detect(pos) ) return false;
+
+ strcpy(name, m_tooltip);
+ return true;
+}
+
+
+// Management of the focus.
+
+void CControl::SetFocus(bool bFocus)
+{
+ m_bFocus = bFocus;
+}
+
+bool CControl::RetFocus()
+{
+ return m_bFocus;
+}
+
+
+// Returns the event associated with the control.
+
+EventMsg CControl::RetEventMsg()
+{
+ return m_eventMsg;
+}
+
+
+// Management of an event.
+
+bool CControl::EventProcess(const Event &event)
+{
+ if ( m_state & STATE_DEAD ) return true;
+
+ if ( event.event == EVENT_FRAME && m_bGlint )
+ {
+ GlintFrame(event);
+ }
+
+ if ( event.event == EVENT_MOUSEMOVE )
+ {
+ m_glintMouse = event.pos;
+
+ if ( Detect(event.pos) )
+ {
+ if ( (m_state & STATE_VISIBLE) &&
+ (m_state & STATE_ENABLE ) )
+ {
+ m_engine->SetMouseType(D3DMOUSEHAND);
+ }
+ SetState(STATE_HILIGHT);
+ }
+ else
+ {
+ ClearState(STATE_HILIGHT);
+ }
+ }
+
+ if ( event.event == EVENT_LBUTTONDOWN )
+ {
+ if ( Detect(event.pos) )
+ {
+ m_bCapture = true;
+ SetState(STATE_PRESS);
+ }
+ }
+
+ if ( event.event == EVENT_MOUSEMOVE && m_bCapture )
+ {
+ if ( Detect(event.pos) )
+ {
+ SetState(STATE_PRESS);
+ }
+ else
+ {
+ ClearState(STATE_PRESS);
+ }
+ }
+
+ if ( event.event == EVENT_LBUTTONUP && m_bCapture )
+ {
+ m_bCapture = false;
+ ClearState(STATE_PRESS);
+ }
+
+ return true;
+}
+
+
+// Removes the reflection.
+
+void CControl::GlintDelete()
+{
+ m_bGlint = false;
+}
+
+// Creates a reflection for that button.
+
+void CControl::GlintCreate(Math::Point ref, bool bLeft, bool bUp)
+{
+ float offset;
+
+ offset = 8.0f/640.0f;
+ if ( offset > m_dim.x/4.0f) offset = m_dim.x/4.0f;
+
+ if ( bLeft )
+ {
+ m_glintCorner1.x = ref.x;
+ m_glintCorner2.x = ref.x+offset;
+ }
+ else
+ {
+ m_glintCorner1.x = ref.x-offset;
+ m_glintCorner2.x = ref.x;
+ }
+
+ offset = 8.0f/480.0f;
+ if ( offset > m_dim.y/4.0f) offset = m_dim.y/4.0f;
+
+ if ( bUp )
+ {
+ m_glintCorner1.y = ref.y-offset;
+ m_glintCorner2.y = ref.y;
+ }
+ else
+ {
+ m_glintCorner1.y = ref.y;
+ m_glintCorner2.y = ref.y+offset;
+ }
+
+ m_bGlint = true;
+}
+
+// Management of reflection.
+
+void CControl::GlintFrame(const Event &event)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+
+ if ( (m_state & STATE_GLINT ) == 0 ||
+ (m_state & STATE_ENABLE ) == 0 ||
+ (m_state & STATE_VISIBLE) == 0 ) return;
+
+ if ( !m_main->RetGlint() ) return;
+
+ m_glintProgress += event.rTime;
+
+ if ( m_glintProgress >= 2.0f && Detect(m_glintMouse) )
+ {
+ pos.x = m_glintCorner1.x + (m_glintCorner2.x-m_glintCorner1.x)*Math::Rand();
+ pos.y = m_glintCorner1.y + (m_glintCorner2.y-m_glintCorner1.y)*Math::Rand();
+ pos.z = 0.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = ((15.0f+Math::Rand()*15.0f)/640.0f);
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim, PARTICONTROL,
+ 1.0f, 0.0f, 0.0f, SH_INTERFACE);
+
+ m_glintProgress = 0.0f;
+ }
+}
+
+
+// Draw button.
+
+void CControl::Draw()
+{
+ Math::Point pos;
+ float zoomExt, zoomInt;
+ int icon;
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return;
+
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+
+ zoomExt = 1.00f;
+ zoomInt = 0.95f;
+
+ if ( m_icon >= 128 )
+ {
+ zoomInt = 0.80f;
+ }
+
+ icon = 2;
+ if ( m_state & STATE_CARD )
+ {
+ icon = 26;
+ }
+ if ( m_state & STATE_DEFAULT )
+ {
+ DrawPart(23, 1.3f, 0.0f);
+
+ zoomExt *= 1.15f;
+ zoomInt *= 1.15f;
+ }
+ if ( m_state & STATE_HILIGHT )
+ {
+ icon = 1;
+ }
+ if ( m_state & STATE_CHECK )
+ {
+ if ( m_state & STATE_CARD )
+ {
+ icon = 27;
+ }
+ else
+ {
+ icon = 0;
+ }
+ }
+ if ( m_state & STATE_PRESS )
+ {
+ icon = 3;
+ zoomInt *= 0.9f;
+ }
+ if ( (m_state & STATE_ENABLE) == 0 )
+ {
+ icon = 7;
+ }
+ if ( m_state & STATE_DEAD )
+ {
+ icon = 17;
+ }
+
+ if ( m_state & STATE_OKAY )
+ {
+ m_engine->SetTexture("button3.tga");
+ icon = 3; // yellow with green point pressed
+ }
+
+ if ( m_name[0] == 0 ) // button without name?
+ {
+//? DrawPart(icon, zoomExt, 0.0f);
+ DrawPart(icon, zoomExt, 8.0f/256.0f);
+
+ if ( m_state & STATE_DEAD ) return;
+
+ icon = m_icon;
+ if ( icon >= 192 )
+ {
+ icon -= 192;
+#if _POLISH
+ m_engine->SetTexture("textp.tga");
+#else
+ m_engine->SetTexture("text.tga");
+#endif
+ m_engine->SetState(D3DSTATETTw);
+ }
+ else if ( icon >= 128 )
+ {
+ icon -= 128;
+ m_engine->SetTexture("button3.tga");
+ m_engine->SetState(D3DSTATETTw);
+ }
+ else if ( icon >= 64 )
+ {
+ icon -= 64;
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTw);
+ }
+ else
+ {
+ m_engine->SetState(D3DSTATETTw);
+ }
+ if ( icon != -1 )
+ {
+ DrawPart(icon, zoomInt, 0.0f);
+ }
+ }
+ else // button with the name?
+ {
+ DrawPart(icon, 1.0f, 8.0f/256.0f);
+
+ if ( m_state & STATE_DEAD ) return;
+
+ if ( m_justif < 0 )
+ {
+ pos.x = m_pos.x+m_dim.x-m_dim.y*0.5f;
+ pos.y = m_pos.y+m_dim.y*0.5f;
+ pos.y -= m_engine->RetText()->RetHeight(m_fontSize, m_fontType)/2;
+ m_engine->RetText()->DrawText(m_name, pos, m_dim.x, m_justif, m_fontSize, m_fontStretch, m_fontType, 0);
+ }
+ else if ( m_justif > 0 )
+ {
+ pos.x = m_pos.x+m_dim.y*0.5f;
+ pos.y = m_pos.y+m_dim.y*0.5f;
+ pos.y -= m_engine->RetText()->RetHeight(m_fontSize, m_fontType)/2.0f;
+ m_engine->RetText()->DrawText(m_name, pos, m_dim.x, m_justif, m_fontSize, m_fontStretch, m_fontType, 0);
+ }
+ else
+ {
+ pos.x = m_pos.x+m_dim.x*0.5f;
+ pos.y = m_pos.y+m_dim.y*0.5f;
+ pos.y -= m_engine->RetText()->RetHeight(m_fontSize, m_fontType)/2.0f;
+ m_engine->RetText()->DrawText(m_name, pos, m_dim.x, m_justif, m_fontSize, m_fontStretch, m_fontType, 0);
+ }
+ }
+}
+
+// Draw the vertex array.
+
+void CControl::DrawPart(int icon, float zoom, float ex)
+{
+ Math::Point p1, p2, c, uv1, uv2;
+ float dp;
+
+ p1.x = m_pos.x;
+ p1.y = m_pos.y;
+ p2.x = m_pos.x + m_dim.x;
+ p2.y = m_pos.y + m_dim.y;
+
+ if ( (m_state & STATE_CARD ) &&
+ (m_state & STATE_CHECK) )
+ {
+ p2.y += (2.0f/480.0f); // a bit above
+ }
+
+ c.x = (p1.x+p2.x)/2.0f;
+ c.y = (p1.y+p2.y)/2.0f; // center
+
+ p1.x = (p1.x-c.x)*zoom + c.x;
+ p1.y = (p1.y-c.y)*zoom + c.y;
+ p2.x = (p2.x-c.x)*zoom + c.x;
+ p2.y = (p2.y-c.y)*zoom + c.y;
+
+ p2.x -= p1.x;
+ p2.y -= p1.y;
+
+ uv1.x = (32.0f/256.0f)*(icon%8);
+ uv1.y = (32.0f/256.0f)*(icon/8); // uv texture
+ uv2.x = (32.0f/256.0f)+uv1.x;
+ uv2.y = (32.0f/256.0f)+uv1.y;
+
+ dp = 0.5f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+
+ DrawIcon(p1, p2, uv1, uv2, ex);
+}
+
+// Draws an icon made up of a rectangular (if x = 0)
+// or 3 pieces.
+
+void CControl::DrawIcon(Math::Point pos, Math::Point dim, Math::Point uv1, Math::Point uv2,
+ float ex)
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DVERTEX2 vertex[8]; // 6 triangles
+ Math::Point p1, p2, p3, p4;
+ Math::Vector n;
+
+ device = m_engine->RetD3DDevice();
+
+ p1.x = pos.x;
+ p1.y = pos.y;
+ p2.x = pos.x + dim.x;
+ p2.y = pos.y + dim.y;
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+
+ if ( ex == 0.0f ) // one piece?
+ {
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x,uv2.y);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, uv1.x,uv1.y);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, uv2.x,uv2.y);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv2.x,uv1.y);
+
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+ }
+ else // 3 pieces?
+ {
+ if ( dim.x >= dim.y )
+ {
+ p3.x = p1.x + ex*dim.y/(uv2.y-uv1.y);
+ p4.x = p2.x - ex*dim.y/(uv2.y-uv1.y);
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x, uv2.y);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, uv1.x, uv1.y);
+ vertex[2] = D3DVERTEX2(Math::Vector(p3.x, p1.y, 0.0f), n, uv1.x+ex,uv2.y);
+ vertex[3] = D3DVERTEX2(Math::Vector(p3.x, p2.y, 0.0f), n, uv1.x+ex,uv1.y);
+ vertex[4] = D3DVERTEX2(Math::Vector(p4.x, p1.y, 0.0f), n, uv2.x-ex,uv2.y);
+ vertex[5] = D3DVERTEX2(Math::Vector(p4.x, p2.y, 0.0f), n, uv2.x-ex,uv1.y);
+ vertex[6] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, uv2.x, uv2.y);
+ vertex[7] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv2.x, uv1.y);
+
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 8, NULL);
+ m_engine->AddStatisticTriangle(6);
+ }
+ else
+ {
+ p3.y = p1.y + ex*dim.x/(uv2.x-uv1.x);
+ p4.y = p2.y - ex*dim.x/(uv2.x-uv1.x);
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, uv2.x,uv2.y );
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x,uv2.y );
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p3.y, 0.0f), n, uv2.x,uv2.y-ex);
+ vertex[3] = D3DVERTEX2(Math::Vector(p1.x, p3.y, 0.0f), n, uv1.x,uv2.y-ex);
+ vertex[4] = D3DVERTEX2(Math::Vector(p2.x, p4.y, 0.0f), n, uv2.x,uv1.y+ex);
+ vertex[5] = D3DVERTEX2(Math::Vector(p1.x, p4.y, 0.0f), n, uv1.x,uv1.y+ex);
+ vertex[6] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv2.x,uv1.y );
+ vertex[7] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, uv1.x,uv1.y );
+
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 8, NULL);
+ m_engine->AddStatisticTriangle(6);
+ }
+ }
+}
+
+// Draws a rectangular icon made up of 9 pieces.
+
+void CControl::DrawIcon(Math::Point pos, Math::Point dim, Math::Point uv1, Math::Point uv2,
+ Math::Point corner, float ex)
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DVERTEX2 vertex[8]; // 6 triangles
+ Math::Point p1, p2, p3, p4;
+ Math::Vector n;
+
+ device = m_engine->RetD3DDevice();
+
+ p1.x = pos.x;
+ p1.y = pos.y;
+ p2.x = pos.x + dim.x;
+ p2.y = pos.y + dim.y;
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+
+ if ( corner.x > dim.x/2.0f ) corner.x = dim.x/2.0f;
+ if ( corner.y > dim.y/2.0f ) corner.y = dim.y/2.0f;
+
+ p1.x = pos.x;
+ p1.y = pos.y;
+ p2.x = pos.x + dim.x;
+ p2.y = pos.y + dim.y;
+ p3.x = p1.x + corner.x;
+ p3.y = p1.y + corner.y;
+ p4.x = p2.x - corner.x;
+ p4.y = p2.y - corner.y;
+
+ // Bottom horizontal band.
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x, uv2.y );
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p3.y, 0.0f), n, uv1.x, uv2.y-ex);
+ vertex[2] = D3DVERTEX2(Math::Vector(p3.x, p1.y, 0.0f), n, uv1.x+ex,uv2.y );
+ vertex[3] = D3DVERTEX2(Math::Vector(p3.x, p3.y, 0.0f), n, uv1.x+ex,uv2.y-ex);
+ vertex[4] = D3DVERTEX2(Math::Vector(p4.x, p1.y, 0.0f), n, uv2.x-ex,uv2.y );
+ vertex[5] = D3DVERTEX2(Math::Vector(p4.x, p3.y, 0.0f), n, uv2.x-ex,uv2.y-ex);
+ vertex[6] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, uv2.x, uv2.y );
+ vertex[7] = D3DVERTEX2(Math::Vector(p2.x, p3.y, 0.0f), n, uv2.x, uv2.y-ex);
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 8, NULL);
+ m_engine->AddStatisticTriangle(6);
+
+ // Central horizontal band.
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p3.y, 0.0f), n, uv1.x, uv2.y-ex);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p4.y, 0.0f), n, uv1.x, uv1.y+ex);
+ vertex[2] = D3DVERTEX2(Math::Vector(p3.x, p3.y, 0.0f), n, uv1.x+ex,uv2.y-ex);
+ vertex[3] = D3DVERTEX2(Math::Vector(p3.x, p4.y, 0.0f), n, uv1.x+ex,uv1.y+ex);
+ vertex[4] = D3DVERTEX2(Math::Vector(p4.x, p3.y, 0.0f), n, uv2.x-ex,uv2.y-ex);
+ vertex[5] = D3DVERTEX2(Math::Vector(p4.x, p4.y, 0.0f), n, uv2.x-ex,uv1.y+ex);
+ vertex[6] = D3DVERTEX2(Math::Vector(p2.x, p3.y, 0.0f), n, uv2.x, uv2.y-ex);
+ vertex[7] = D3DVERTEX2(Math::Vector(p2.x, p4.y, 0.0f), n, uv2.x, uv1.y+ex);
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 8, NULL);
+ m_engine->AddStatisticTriangle(6);
+
+ // Top horizontal band.
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p4.y, 0.0f), n, uv1.x, uv1.y+ex);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, uv1.x, uv1.y );
+ vertex[2] = D3DVERTEX2(Math::Vector(p3.x, p4.y, 0.0f), n, uv1.x+ex,uv1.y+ex);
+ vertex[3] = D3DVERTEX2(Math::Vector(p3.x, p2.y, 0.0f), n, uv1.x+ex,uv1.y );
+ vertex[4] = D3DVERTEX2(Math::Vector(p4.x, p4.y, 0.0f), n, uv2.x-ex,uv1.y+ex);
+ vertex[5] = D3DVERTEX2(Math::Vector(p4.x, p2.y, 0.0f), n, uv2.x-ex,uv1.y );
+ vertex[6] = D3DVERTEX2(Math::Vector(p2.x, p4.y, 0.0f), n, uv2.x, uv1.y+ex);
+ vertex[7] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv2.x, uv1.y );
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 8, NULL);
+ m_engine->AddStatisticTriangle(6);
+}
+
+// Draw round the hatch of a button.
+
+void CControl::DrawWarning(Math::Point pos, Math::Point dim)
+{
+ Math::Point uv1, uv2;
+ float dp;
+
+ dp = 0.5f/256.0f;
+
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+
+ uv1.x = 64.0f/256.0f;
+ uv1.y = 208.0f/256.0f;
+ uv2.x = 160.0f/256.0f;
+ uv2.y = 224.0f/256.0f;
+
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+
+ if ( dim.x < dim.y*4.0f )
+ {
+ dim.y /= 2.0f;
+ DrawIcon(pos, dim, uv1, uv2);
+ pos.y += dim.y;
+ DrawIcon(pos, dim, uv1, uv2);
+ }
+ else
+ {
+ dim.x /= 2.0f;
+ dim.y /= 2.0f;
+ DrawIcon(pos, dim, uv1, uv2);
+ pos.x += dim.x;
+ DrawIcon(pos, dim, uv1, uv2);
+ pos.x -= dim.x;
+ pos.y += dim.y;
+ DrawIcon(pos, dim, uv1, uv2);
+ pos.x += dim.x;
+ DrawIcon(pos, dim, uv1, uv2);
+ }
+}
+
+// Draw the shade under a button.
+
+void CControl::DrawShadow(Math::Point pos, Math::Point dim, float deep)
+{
+ Math::Point uv1, uv2, corner;
+ float dp;
+
+ dp = 0.5f/256.0f;
+
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTw);
+
+ pos.x += deep*0.010f*0.75f;
+ pos.y -= deep*0.015f;
+ dim.x += deep*0.005f*0.75f;
+ dim.y += deep*0.005f;
+
+ uv1.x = 192.0f/256.0f;
+ uv1.y = 32.0f/256.0f;
+ uv2.x = 224.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+
+ corner.x = 10.0f/640.0f;
+ corner.y = 10.0f/480.0f;
+
+ DrawIcon(pos, dim, uv1, uv2, corner, 6.0f/256.0f);
+}
+
+
+// Detects whether a position is in the button.
+
+bool CControl::Detect(Math::Point pos)
+{
+ return ( pos.x >= m_pos.x &&
+ pos.x <= m_pos.x+m_dim.x &&
+ pos.y >= m_pos.y &&
+ pos.y <= m_pos.y+m_dim.y );
+}
+
+
diff --git a/src/ui/control.h b/src/ui/control.h
index 60fdf22..0a12ff1 100644
--- a/src/ui/control.h
+++ b/src/ui/control.h
@@ -1,138 +1,138 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// control.h
-
-#pragma once
-
-
-#include "old/text.h"
-#include "common/struct.h"
-#include "common/event.h"
-
-
-class CInstanceManager;
-class CEvent;
-class CD3DEngine;
-class CRobotMain;
-class CParticule;
-class CSound;
-
-
-enum ControlState
-{
- STATE_ENABLE = (1<<0), // active
- STATE_CHECK = (1<<1), // pressed
- STATE_HILIGHT = (1<<2), // overflown by mouse
- STATE_PRESS = (1<<3), // pressed by mouse
- STATE_VISIBLE = (1<<4), // visible
- STATE_DEAD = (1<<5), // inaccessible (x)
- STATE_DEFAULT = (1<<6), // actuated by RETURN
- STATE_OKAY = (1<<7), // green point at the bottom right
- STATE_SHADOW = (1<<8), // shadow
- STATE_GLINT = (1<<9), // dynamic reflection
- STATE_CARD = (1<<10), // tab
- STATE_EXTEND = (1<<11), // extended mode
- STATE_SIMPLY = (1<<12), // undecorated
- STATE_FRAME = (1<<13), // framework highlighting
- STATE_WARNING = (1<<14), // framework hatched yellow / black
- STATE_VALUE = (1<<15), // displays the value
- STATE_RUN = (1<<16) // running program
-};
-
-
-
-class CControl
-{
-public:
- CControl(CInstanceManager* iMan);
- virtual ~CControl();
-
- virtual bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
-
- virtual bool EventProcess(const Event &event);
-
- virtual void SetPos(Math::Point pos);
- virtual Math::Point RetPos();
- virtual void SetDim(Math::Point dim);
- virtual Math::Point RetDim();
- virtual bool SetState(int state, bool bState);
- virtual bool SetState(int state);
- virtual bool ClearState(int state);
- virtual bool TestState(int state);
- virtual int RetState();
- virtual void SetIcon(int icon);
- virtual int RetIcon();
- virtual void SetName(char* name, bool bTooltip=true);
- virtual char* RetName();
- virtual void SetJustif(int mode);
- virtual int RetJustif();
- virtual void SetFontSize(float size);
- virtual float RetFontSize();
- virtual void SetFontStretch(float stretch);
- virtual float RetFontStretch();
- virtual void SetFontType(FontType font);
- virtual FontType RetFontType();
- virtual bool SetTooltip(char* name);
- virtual bool GetTooltip(Math::Point pos, char* name);
- virtual void SetFocus(bool bFocus);
- virtual bool RetFocus();
-
- virtual EventMsg RetEventMsg();
-
- virtual void Draw();
-
-protected:
- void GlintDelete();
- void GlintCreate(Math::Point ref, bool bLeft=true, bool bUp=true);
- void GlintFrame(const Event &event);
- void DrawPart(int icon, float zoom, float ex);
- void DrawIcon(Math::Point pos, Math::Point dim, Math::Point uv1, Math::Point uv2, float ex=0.0f);
- void DrawIcon(Math::Point pos, Math::Point dim, Math::Point uv1, Math::Point uv2, Math::Point corner, float ex);
- void DrawWarning(Math::Point pos, Math::Point dim);
- void DrawShadow(Math::Point pos, Math::Point dim, float deep=1.0f);
- virtual bool Detect(Math::Point pos);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CEvent* m_event;
- CRobotMain* m_main;
- CParticule* m_particule;
- CSound* m_sound;
-
- Math::Point m_pos; // corner upper / left
- Math::Point m_dim; // dimensions
- int m_icon;
- EventMsg m_eventMsg; // message to send when clicking
- int m_state; // states (STATE_ *)
- float m_fontSize; // size of the button name
- float m_fontStretch; // stretch of the font
- FontType m_fontType; // type of font
- int m_justif; // type of justification (-1,0,1)
- char m_name[100]; // name of the button
- char m_tooltip[100]; // name of tooltip
- bool m_bFocus;
- bool m_bCapture;
-
- bool m_bGlint;
- Math::Point m_glintCorner1;
- Math::Point m_glintCorner2;
- float m_glintProgress;
- Math::Point m_glintMouse;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// control.h
+
+#pragma once
+
+
+#include "old/text.h"
+#include "common/struct.h"
+#include "common/event.h"
+
+
+class CInstanceManager;
+class CEvent;
+class CD3DEngine;
+class CRobotMain;
+class CParticule;
+class CSound;
+
+
+enum ControlState
+{
+ STATE_ENABLE = (1<<0), // active
+ STATE_CHECK = (1<<1), // pressed
+ STATE_HILIGHT = (1<<2), // overflown by mouse
+ STATE_PRESS = (1<<3), // pressed by mouse
+ STATE_VISIBLE = (1<<4), // visible
+ STATE_DEAD = (1<<5), // inaccessible (x)
+ STATE_DEFAULT = (1<<6), // actuated by RETURN
+ STATE_OKAY = (1<<7), // green point at the bottom right
+ STATE_SHADOW = (1<<8), // shadow
+ STATE_GLINT = (1<<9), // dynamic reflection
+ STATE_CARD = (1<<10), // tab
+ STATE_EXTEND = (1<<11), // extended mode
+ STATE_SIMPLY = (1<<12), // undecorated
+ STATE_FRAME = (1<<13), // framework highlighting
+ STATE_WARNING = (1<<14), // framework hatched yellow / black
+ STATE_VALUE = (1<<15), // displays the value
+ STATE_RUN = (1<<16) // running program
+};
+
+
+
+class CControl
+{
+public:
+ CControl(CInstanceManager* iMan);
+ virtual ~CControl();
+
+ virtual bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+
+ virtual bool EventProcess(const Event &event);
+
+ virtual void SetPos(Math::Point pos);
+ virtual Math::Point RetPos();
+ virtual void SetDim(Math::Point dim);
+ virtual Math::Point RetDim();
+ virtual bool SetState(int state, bool bState);
+ virtual bool SetState(int state);
+ virtual bool ClearState(int state);
+ virtual bool TestState(int state);
+ virtual int RetState();
+ virtual void SetIcon(int icon);
+ virtual int RetIcon();
+ virtual void SetName(char* name, bool bTooltip=true);
+ virtual char* RetName();
+ virtual void SetJustif(int mode);
+ virtual int RetJustif();
+ virtual void SetFontSize(float size);
+ virtual float RetFontSize();
+ virtual void SetFontStretch(float stretch);
+ virtual float RetFontStretch();
+ virtual void SetFontType(FontType font);
+ virtual FontType RetFontType();
+ virtual bool SetTooltip(char* name);
+ virtual bool GetTooltip(Math::Point pos, char* name);
+ virtual void SetFocus(bool bFocus);
+ virtual bool RetFocus();
+
+ virtual EventMsg RetEventMsg();
+
+ virtual void Draw();
+
+protected:
+ void GlintDelete();
+ void GlintCreate(Math::Point ref, bool bLeft=true, bool bUp=true);
+ void GlintFrame(const Event &event);
+ void DrawPart(int icon, float zoom, float ex);
+ void DrawIcon(Math::Point pos, Math::Point dim, Math::Point uv1, Math::Point uv2, float ex=0.0f);
+ void DrawIcon(Math::Point pos, Math::Point dim, Math::Point uv1, Math::Point uv2, Math::Point corner, float ex);
+ void DrawWarning(Math::Point pos, Math::Point dim);
+ void DrawShadow(Math::Point pos, Math::Point dim, float deep=1.0f);
+ virtual bool Detect(Math::Point pos);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CEvent* m_event;
+ CRobotMain* m_main;
+ CParticule* m_particule;
+ CSound* m_sound;
+
+ Math::Point m_pos; // corner upper / left
+ Math::Point m_dim; // dimensions
+ int m_icon;
+ EventMsg m_eventMsg; // message to send when clicking
+ int m_state; // states (STATE_ *)
+ float m_fontSize; // size of the button name
+ float m_fontStretch; // stretch of the font
+ FontType m_fontType; // type of font
+ int m_justif; // type of justification (-1,0,1)
+ char m_name[100]; // name of the button
+ char m_tooltip[100]; // name of tooltip
+ bool m_bFocus;
+ bool m_bCapture;
+
+ bool m_bGlint;
+ Math::Point m_glintCorner1;
+ Math::Point m_glintCorner2;
+ float m_glintProgress;
+ Math::Point m_glintMouse;
+};
+
+
diff --git a/src/ui/displayinfo.cpp b/src/ui/displayinfo.cpp
index 37719c1..39a4a14 100644
--- a/src/ui/displayinfo.cpp
+++ b/src/ui/displayinfo.cpp
@@ -1,1219 +1,1219 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// displayinfo.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/language.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "old/math3d.h"
-#include "object/robotmain.h"
-#include "old/camera.h"
-#include "object/object.h"
-#include "object/motion/motion.h"
-#include "object/motion/motiontoto.h"
-#include "ui/interface.h"
-#include "ui/button.h"
-#include "ui/slider.h"
-#include "ui/edit.h"
-#include "ui/group.h"
-#include "ui/window.h"
-#include "old/particule.h"
-#include "old/light.h"
-#include "old/text.h"
-#include "script/cbottoken.h"
-#include "ui/displayinfo.h"
-
-
-
-
-// Object's constructor.
-
-CDisplayInfo::CDisplayInfo(CInstanceManager* iMan)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_STUDIO, this);
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
- m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
-
- m_bInfoMaximized = true;
- m_bInfoMinimized = false;
-
- m_infoFinalPos = m_infoActualPos = m_infoNormalPos = Math::Point(0.00f, 0.00f);
- m_infoFinalDim = m_infoActualPos = m_infoNormalDim = Math::Point(1.00f, 1.00f);
-
- m_lightSuppl = -1;
- m_toto = 0;
-}
-
-// Object's destructor.
-
-CDisplayInfo::~CDisplayInfo()
-{
- m_iMan->DeleteInstance(CLASS_STUDIO, this);
-}
-
-
-// Management of an event.
-
-bool CDisplayInfo::EventProcess(const Event &event)
-{
- CWindow* pw;
- CEdit* edit;
- CSlider* slider;
- CMotionToto* toto;
-
- if ( event.event == EVENT_FRAME )
- {
- EventFrame(event);
- HyperUpdate();
- }
-
- if ( event.event == EVENT_MOUSEMOVE )
- {
- if ( m_toto != 0 )
- {
- toto = (CMotionToto*)m_toto->RetMotion();
- if ( toto != 0 )
- {
- toto->SetMousePos(event.pos);
- }
- }
- }
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
- if ( pw != 0 )
- {
- if ( event.event == pw->RetEventMsgClose() )
- {
- Event newEvent = event;
- newEvent.event = EVENT_OBJECT_INFOOK;
- m_event->AddEvent(newEvent);
- }
-
- if ( event.event == EVENT_SATCOM_HUSTON )
- {
- ChangeIndexButton(SATCOM_HUSTON);
- }
- if ( event.event == EVENT_SATCOM_SAT )
- {
- ChangeIndexButton(SATCOM_SAT);
- }
-//? if ( event.event == EVENT_SATCOM_OBJECT )
-//? {
-//? ChangeIndexButton(SATCOM_OBJECT);
-//? }
- if ( event.event == EVENT_SATCOM_LOADING )
- {
- ChangeIndexButton(SATCOM_LOADING);
- }
- if ( event.event == EVENT_SATCOM_PROG )
- {
- ChangeIndexButton(SATCOM_PROG);
- }
- if ( event.event == EVENT_SATCOM_SOLUCE )
- {
- ChangeIndexButton(SATCOM_SOLUCE);
- }
-
- if ( event.event == EVENT_HYPER_HOME ||
- event.event == EVENT_HYPER_PREV ||
- event.event == EVENT_HYPER_NEXT )
- {
- edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
- if ( edit != 0 )
- {
- edit->HyperGo(event.event);
- HyperUpdate();
- }
- }
-
- if ( event.event == EVENT_HYPER_SIZE1 ) // size 1?
- {
- m_main->SetFontSize(9.0f);
- slider = (CSlider*)pw->SearchControl(EVENT_STUDIO_SIZE);
- if ( slider != 0 ) slider->SetVisibleValue((m_main->RetFontSize()-9.0f)/6.0f);
- ViewDisplayInfo();
- }
- if ( event.event == EVENT_HYPER_SIZE2 ) // size 2?
- {
- m_main->SetFontSize(10.0f);
- slider = (CSlider*)pw->SearchControl(EVENT_STUDIO_SIZE);
- if ( slider != 0 ) slider->SetVisibleValue((m_main->RetFontSize()-9.0f)/6.0f);
- ViewDisplayInfo();
- }
- if ( event.event == EVENT_HYPER_SIZE3 ) // size 3?
- {
- m_main->SetFontSize(12.0f);
- slider = (CSlider*)pw->SearchControl(EVENT_STUDIO_SIZE);
- if ( slider != 0 ) slider->SetVisibleValue((m_main->RetFontSize()-9.0f)/6.0f);
- ViewDisplayInfo();
- }
- if ( event.event == EVENT_HYPER_SIZE4 ) // size 4?
- {
- m_main->SetFontSize(15.0f);
- slider = (CSlider*)pw->SearchControl(EVENT_STUDIO_SIZE);
- if ( slider != 0 ) slider->SetVisibleValue((m_main->RetFontSize()-9.0f)/6.0f);
- ViewDisplayInfo();
- }
-
- if ( event.event == EVENT_STUDIO_SIZE ) // size?
- {
- slider = (CSlider*)pw->SearchControl(EVENT_STUDIO_SIZE);
- if ( slider == 0 ) return false;
- m_main->SetFontSize(9.0f+slider->RetVisibleValue()*6.0f);
- ViewDisplayInfo();
- }
-
- if ( event.event == EVENT_HYPER_COPY ) // copy ?
- {
- edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
- if ( edit != 0 )
- {
- edit->Copy();
- }
- }
-
- if ( event.event == EVENT_LBUTTONDOWN ||
- event.event == EVENT_LBUTTONUP )
- {
- UpdateCopyButton();
- }
-
- if ( event.event == EVENT_WINDOW4 ) // window moved?
- {
- m_infoNormalPos = m_infoActualPos = m_infoFinalPos = pw->RetPos();
- m_infoNormalDim = m_infoActualDim = m_infoFinalDim = pw->RetDim();
- AdjustDisplayInfo(m_infoActualPos, m_infoActualDim);
- }
- if ( event.event == pw->RetEventMsgReduce() )
- {
- if ( m_bInfoMinimized )
- {
- m_infoFinalPos = m_infoNormalPos;
- m_infoFinalDim = m_infoNormalDim;
- m_bInfoMinimized = false;
- m_bInfoMaximized = false;
- }
- else
- {
- m_infoFinalPos.x = 0.00f;
- m_infoFinalPos.y = -0.34f;
- m_infoFinalDim.x = 1.00f;
- m_infoFinalDim.y = 0.40f;
- m_bInfoMinimized = true;
- m_bInfoMaximized = false;
- }
-//? m_main->SetEditFull(m_bInfoMaximized);
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
- if ( pw != 0 )
- {
- pw->SetMaximized(m_bInfoMaximized);
- pw->SetMinimized(m_bInfoMinimized);
- }
- }
- if ( event.event == pw->RetEventMsgFull() )
- {
- if ( m_bInfoMaximized )
- {
- m_infoFinalPos = m_infoNormalPos;
- m_infoFinalDim = m_infoNormalDim;
- m_bInfoMinimized = false;
- m_bInfoMaximized = false;
- }
- else
- {
- m_infoFinalPos.x = 0.00f;
- m_infoFinalPos.y = 0.00f;
- m_infoFinalDim.x = 1.00f;
- m_infoFinalDim.y = 1.00f;
- m_bInfoMinimized = false;
- m_bInfoMaximized = true;
- }
-//? m_main->SetEditFull(m_bInfoMaximized);
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
- if ( pw != 0 )
- {
- pw->SetMaximized(m_bInfoMaximized);
- pw->SetMinimized(m_bInfoMinimized);
- }
- }
- }
- return true;
-}
-
-
-// The brain is changing by time.
-
-bool CDisplayInfo::EventFrame(const Event &event)
-{
- float time;
-
- if ( m_infoFinalPos.x != m_infoActualPos.x ||
- m_infoFinalPos.y != m_infoActualPos.y ||
- m_infoFinalDim.x != m_infoActualDim.x ||
- m_infoFinalDim.y != m_infoActualDim.y )
- {
- time = event.rTime*20.0f;
- m_infoActualPos.x += (m_infoFinalPos.x-m_infoActualPos.x)*time;
- m_infoActualPos.y += (m_infoFinalPos.y-m_infoActualPos.y)*time;
- m_infoActualDim.x += (m_infoFinalDim.x-m_infoActualDim.x)*time;
- m_infoActualDim.y += (m_infoFinalDim.y-m_infoActualDim.y)*time;
- AdjustDisplayInfo(m_infoActualPos, m_infoActualDim);
- }
-
- return true;
-}
-
-
-// Updates the buttons for hyperlinks.
-
-void CDisplayInfo::HyperUpdate()
-{
- CWindow* pw;
- CEdit* edit;
- CButton* button;
- bool bEnable;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
- if ( pw == 0 ) return;
- edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
- if ( edit == 0 ) return;
-
- button = (CButton*)pw->SearchControl(EVENT_HYPER_HOME);
- if ( button != 0 )
- {
- bEnable = edit->HyperTest(EVENT_HYPER_HOME);
- button->SetState(STATE_ENABLE, bEnable);
- }
-
- button = (CButton*)pw->SearchControl(EVENT_HYPER_PREV);
- if ( button != 0 )
- {
- bEnable = edit->HyperTest(EVENT_HYPER_PREV);
- button->SetState(STATE_ENABLE, bEnable);
- }
-
- button = (CButton*)pw->SearchControl(EVENT_HYPER_NEXT);
- if ( button != 0 )
- {
- bEnable = edit->HyperTest(EVENT_HYPER_NEXT);
- button->SetState(STATE_ENABLE, bEnable);
- }
-}
-
-
-// Beginning of the display of information.
-
-void CDisplayInfo::StartDisplayInfo(char *filename, int index, bool bSoluce)
-{
- D3DLIGHT7 light;
- Math::Point pos, dim;
- CWindow* pw;
- CEdit* edit;
- CButton* button;
- CSlider* slider;
- CMotionToto* toto;
-
- m_index = index;
- m_bSoluce = bSoluce;
-
-//? CreateObjectsFile();
-
- m_bEditLock = m_main->RetEditLock();
- if ( m_bEditLock ) // edition running program?
- {
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw != 0 )
- {
- pw->ClearState(STATE_ENABLE); // CStudio inactive
- }
- }
-
- m_main->SetEditLock(true, false);
- m_main->SetEditFull(false);
- m_bInitPause = m_engine->RetPause();
- m_engine->SetPause(true);
- m_infoCamera = m_camera->RetType();
- m_camera->SetType(CAMERA_INFO);
-
- pos = m_infoActualPos = m_infoFinalPos;
- dim = m_infoActualDim = m_infoFinalDim;
- pw = m_interface->CreateWindows(pos, dim, 4, EVENT_WINDOW4);
- if ( pw == 0 ) return;
-//? pw->SetClosable(true);
-//? GetResource(RES_TEXT, RT_DISINFO_TITLE, res);
-//? pw->SetName(res);
-//? pw->SetMinDim(Math::Point(0.56f, 0.40f));
-//? pw->SetMaximized(m_bInfoMaximized);
-//? pw->SetMinimized(m_bInfoMinimized);
-//? m_main->SetEditFull(m_bInfoMaximized);
-
- edit = pw->CreateEdit(pos, dim, 0, EVENT_EDIT1);
- if ( edit == 0 ) return;
- edit->SetState(STATE_SHADOW);
- edit->SetMultiFont(true);
- edit->SetMaxChar(10000);
- edit->SetFontType(FONT_COLOBOT);
- edit->SetSoluceMode(bSoluce);
- edit->ReadText(filename);
- edit->HyperHome(filename);
- edit->SetEditCap(false); // just to see!
- edit->SetHiliteCap(false);
- edit->SetFocus(true);
-
- ViewDisplayInfo();
-
- button = pw->CreateButton(pos, dim, 128+57, EVENT_SATCOM_HUSTON);
- button->SetState(STATE_SHADOW);
-#if _TEEN
-#if !_ENGLISH
- button = pw->CreateButton(pos, dim, 46, EVENT_SATCOM_SAT);
-#endif
-#else
- button = pw->CreateButton(pos, dim, 128+58, EVENT_SATCOM_SAT);
-#endif
- button->SetState(STATE_SHADOW);
-//? button = pw->CreateButton(pos, dim, 128+59, EVENT_SATCOM_OBJECT);
-//? button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 53, EVENT_SATCOM_LOADING);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 128+60, EVENT_SATCOM_PROG);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 20, EVENT_SATCOM_SOLUCE);
- button->SetState(STATE_SHADOW);
-
- pw->CreateGroup(pos, dim, 18, EVENT_LABEL1); // arrow >
- pw->CreateGroup(pos, dim, 19, EVENT_LABEL2); // symbol SatCom
-
- button = pw->CreateButton(pos, dim, 55, EVENT_HYPER_PREV);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 48, EVENT_HYPER_NEXT);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 30, EVENT_HYPER_HOME);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 82, EVENT_HYPER_SIZE1);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 83, EVENT_HYPER_SIZE2);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 90, EVENT_HYPER_SIZE3);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 91, EVENT_HYPER_SIZE4);
- button->SetState(STATE_SHADOW);
- slider = pw->CreateSlider(pos, dim, 0, EVENT_STUDIO_SIZE);
- slider->SetState(STATE_SHADOW);
- slider->SetVisibleValue((m_main->RetFontSize()-9.0f)/6.0f);
- button = pw->CreateButton(pos, dim, 61, EVENT_HYPER_COPY);
- button->SetState(STATE_SHADOW);
- HyperUpdate();
-
- button = pw->CreateButton(pos, dim, -1, EVENT_OBJECT_INFOOK);
- button->SetState(STATE_SHADOW);
- button->SetState(STATE_SIMPLY);
- button->SetState(STATE_DEFAULT);
- pw->CreateGroup(pos, dim, 21, EVENT_LABEL3); // symbol stand-by
-
- AdjustDisplayInfo(m_infoActualPos, m_infoActualDim);
- UpdateIndexButton();
-
- m_engine->SetDrawWorld(false); // doesn't draw anything in the interface
- m_engine->SetDrawFront(true); // toto draws on the interface
- m_particule->SetFrameUpdate(SH_WORLD, false); // particles break into world
-
- m_toto = SearchToto();
- if ( m_toto != 0 )
- {
- m_toto->SetDrawFront(true);
-
- toto = (CMotionToto*)m_toto->RetMotion();
- if ( toto != 0 )
- {
- toto->StartDisplayInfo();
- }
- }
-
- ZeroMemory(&light, sizeof(light));
- light.dltType = D3DLIGHT_DIRECTIONAL;
- light.dcvDiffuse.r = 1.0f;
- light.dcvDiffuse.g = 1.0f;
- light.dcvDiffuse.b = 1.0f;
- light.dvDirection = D3DVECTOR(1.0f, 0.0f, 1.0f);
- m_lightSuppl = m_light->CreateLight();
- m_light->SetLight(m_lightSuppl, light);
- m_light->SetLightExcluType(m_lightSuppl, TYPETERRAIN);
-}
-
-// Repositions all controls editing.
-
-void CDisplayInfo::AdjustDisplayInfo(Math::Point wpos, Math::Point wdim)
-{
- CWindow* pw;
- CEdit* edit;
- CButton* button;
- CSlider* slider;
- CGroup* group;
- Math::Point pos, dim;
-
- wpos.x = 50.0f/640.0f;
- wpos.y = 30.0f/480.0f;
- wdim.x = 540.0f/640.0f;
- wdim.y = 420.0f/480.0f;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
- if ( pw != 0 )
- {
- pw->SetPos(wpos);
- pw->SetDim(wdim);
- wdim = pw->RetDim();
- }
-
- pos.x = (50.0f+10.0f)/640.0f;
- pos.y = (30.0f+10.0f+24.0f+10.0f+324.0f-48.0f)/480.0f;
- dim.x = 48.0f/640.0f;
- dim.y = 48.0f/480.0f;
- button = (CButton*)pw->SearchControl(EVENT_SATCOM_HUSTON);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.y -= (48.0f+4.0f)/480.0f;
- button = (CButton*)pw->SearchControl(EVENT_SATCOM_SAT);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
-//? pos.y -= (48.0f+4.0f)/480.0f;
-//? button = (CButton*)pw->SearchControl(EVENT_SATCOM_OBJECT);
-//? if ( button != 0 )
-//? {
-//? button->SetPos(pos);
-//? button->SetDim(dim);
-//? }
- pos.y -= (48.0f+4.0f)/480.0f;
- button = (CButton*)pw->SearchControl(EVENT_SATCOM_LOADING);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.y -= (48.0f+4.0f)/480.0f;
- button = (CButton*)pw->SearchControl(EVENT_SATCOM_PROG);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.y -= (48.0f+4.0f)/480.0f;
- button = (CButton*)pw->SearchControl(EVENT_SATCOM_SOLUCE);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
-
- pos.x = (50.0f+10.0f+5.0f)/640.0f;
- pos.y = (30.0f+10.0f+4.0f)/480.0f;
- dim.x = (48.0f-10.0f)/640.0f;
- dim.y = 24.0f/480.0f;
- button = (CButton*)pw->SearchControl(EVENT_OBJECT_INFOOK);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
-
- pos.x = (50.0f+10.0f+48.0f+10.0f)/640.0f;
- pos.y = (30.0f+10.0f)/480.0f;
- dim.x = 462.0f/640.0f;
- dim.y = 358.0f/480.0f;
- edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
- if ( edit != 0 )
- {
- edit->SetPos(pos);
- edit->SetDim(dim);
- }
-
- pos.x = (50.0f+10.0f+48.0f+10.0f)/640.0f;
- pos.y = (30.0f+10.0f+358.0f+10.0f)/480.0f;
- dim.x = 32.0f/640.0f;
- dim.y = 32.0f/480.0f;
- button = (CButton*)pw->SearchControl(EVENT_HYPER_PREV);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x += 35.0f/640.0f;
- button = (CButton*)pw->SearchControl(EVENT_HYPER_NEXT);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x += 35.0f/640.0f;
- button = (CButton*)pw->SearchControl(EVENT_HYPER_HOME);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
-
- pos.x += 50.0f/640.0f;
- button = (CButton*)pw->SearchControl(EVENT_HYPER_SIZE1);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x += 35.0f/640.0f;
- button = (CButton*)pw->SearchControl(EVENT_HYPER_SIZE2);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x += 35.0f/640.0f;
- button = (CButton*)pw->SearchControl(EVENT_HYPER_SIZE3);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x += 35.0f/640.0f;
- button = (CButton*)pw->SearchControl(EVENT_HYPER_SIZE4);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x += 35.0f/640.0f;
- dim.x = 18.0f/640.0f;
- slider = (CSlider*)pw->SearchControl(EVENT_STUDIO_SIZE);
- if ( slider != 0 )
- {
- slider->SetPos(pos);
- slider->SetDim(dim);
- }
- pos.x += 50.0f/640.0f;
- dim.x = 32.0f/640.0f;
- button = (CButton*)pw->SearchControl(EVENT_HYPER_COPY);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
-
- pos.x = (50.0f+10.0f)/640.0f;
- pos.y = (30.0f+10.0f+24.0f+10.0f+324.0f+6.0f)/480.0f;
- dim.x = 48.0f/640.0f;
- dim.y = 40.0f/480.0f;
- group = (CGroup*)pw->SearchControl(EVENT_LABEL2); // symbol SatCom
- if ( group != 0 )
- {
- group->SetPos(pos);
- group->SetDim(dim);
- }
-
- pos.x = (50.0f+10.0f+14.0f)/640.0f;
- pos.y = (30.0f+10.0f+6.0f)/480.0f;
- dim.x = 20.0f/640.0f;
- dim.y = 20.0f/480.0f;
- group = (CGroup*)pw->SearchControl(EVENT_LABEL3); // symbol stand-by
- if ( group != 0 )
- {
- group->SetPos(pos);
- group->SetDim(dim);
- }
-}
-
-// Change the index button.
-
-void CDisplayInfo::ChangeIndexButton(int index)
-{
- CWindow* pw;
- CEdit* edit;
- char* filename;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
- if ( pw == 0 ) return;
-
- if ( m_index != -1 )
- {
- m_main->SetDisplayInfoPosition(m_index, RetPosition());
- }
- m_index = index;
-
- edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
- if ( edit != 0 )
- {
- filename = m_main->RetDisplayInfoName(m_index);
- edit->ReadText(filename);
- edit->HyperHome(filename);
- SetPosition(m_main->RetDisplayInfoPosition(m_index));
- }
-
- UpdateIndexButton();
-}
-
-// Adapts the index buttons.
-
-void CDisplayInfo::UpdateIndexButton()
-{
- CWindow* pw;
- CButton* button;
- CGroup* group;
- CEdit* edit;
- Math::Point pos, dim;
- char* filename;
- char* loading;
-
- static int table[SATCOM_MAX] =
- {
- 0, // SATCOM_HUSTON
- 1, // SATCOM_SAT
- -1, // SATCOM_OBJECT
- 2, // SATCOM_LOADING
- 3, // SATCOM_PROG
- 4, // SATCOM_SOLUCE
- };
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
- if ( pw == 0 ) return;
-
- button = (CButton*)pw->SearchControl(EVENT_SATCOM_HUSTON);
- if ( button != 0 )
- {
- button->SetState(STATE_CHECK, m_index==SATCOM_HUSTON);
- filename = m_main->RetDisplayInfoName(SATCOM_HUSTON);
- button->SetState(STATE_VISIBLE, filename[0]!=0);
- }
-
- button = (CButton*)pw->SearchControl(EVENT_SATCOM_SAT);
- if ( button != 0 )
- {
- button->SetState(STATE_CHECK, m_index==SATCOM_SAT);
- filename = m_main->RetDisplayInfoName(SATCOM_SAT);
- button->SetState(STATE_VISIBLE, filename[0]!=0);
- }
-
-//? button = (CButton*)pw->SearchControl(EVENT_SATCOM_OBJECT);
-//? if ( button != 0 )
-//? {
-//? button->SetState(STATE_CHECK, m_index==SATCOM_OBJECT);
-//? filename = m_main->RetDisplayInfoName(SATCOM_OBJECT);
-//? button->SetState(STATE_VISIBLE, filename[0]!=0);
-//? }
-
- loading = 0;
- button = (CButton*)pw->SearchControl(EVENT_SATCOM_LOADING);
- if ( button != 0 )
- {
- button->SetState(STATE_CHECK, m_index==SATCOM_LOADING);
- loading = m_main->RetDisplayInfoName(SATCOM_LOADING);
- button->SetState(STATE_VISIBLE, loading[0]!=0);
- }
-
- button = (CButton*)pw->SearchControl(EVENT_SATCOM_PROG);
- if ( button != 0 )
- {
- button->SetState(STATE_CHECK, m_index==SATCOM_PROG);
- filename = m_main->RetDisplayInfoName(SATCOM_PROG);
- button->SetState(STATE_VISIBLE, filename[0]!=0 && (m_index==SATCOM_LOADING||m_index==SATCOM_PROG||(loading!=0&&loading[0]==0)));
- }
-
- button = (CButton*)pw->SearchControl(EVENT_SATCOM_SOLUCE);
- if ( button != 0 )
- {
- button->SetState(STATE_CHECK, m_index==SATCOM_SOLUCE);
- filename = m_main->RetDisplayInfoName(SATCOM_SOLUCE);
- button->SetState(STATE_VISIBLE, filename[0]!=0 && m_bSoluce);
- }
-
- group = (CGroup*)pw->SearchControl(EVENT_LABEL1);
- if ( group != 0 )
- {
- if ( m_index == -1 )
- {
- group->ClearState(STATE_VISIBLE);
- }
- else
- {
- group->SetState(STATE_VISIBLE);
-
- pos.x = (50.0f+10.0f+48.0f-3.0f)/640.0f;
- pos.y = (30.0f+10.0f+24.0f+10.0f+324.0f-48.0f-1.0f)/480.0f;
- pos.y -= (48.0f+4.0f)/480.0f*table[m_index];
- dim.x = 15.0f/640.0f;
- dim.y = 48.0f/480.0f;
- group->SetPos(pos);
- group->SetDim(dim);
- }
- }
-
-#if 0
- button = (CButton*)pw->SearchControl(EVENT_HYPER_COPY);
- if ( button != 0 )
- {
- button->SetState(STATE_VISIBLE, m_index==SATCOM_LOADING);
- }
-#endif
-
- edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
- if ( edit != 0 )
- {
-//? edit->SetHiliteCap(m_index==SATCOM_LOADING);
- edit->SetHiliteCap(true);
- }
-
- UpdateCopyButton();
-}
-
-// Adjusts the copy button.
-
-void CDisplayInfo::UpdateCopyButton()
-{
- CWindow* pw;
- CButton* button;
- CEdit* edit;
- int c1, c2;
-
-//? if ( m_index != SATCOM_LOADING ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
- if ( pw == 0 ) return;
-
- button = (CButton*)pw->SearchControl(EVENT_HYPER_COPY);
- if ( button == 0 ) return;
-
- edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
- if ( edit == 0 ) return;
-
- edit->GetCursor(c1, c2);
- button->SetState(STATE_ENABLE, c1!=c2);
-
-}
-
-// End of the display of information.
-
-void CDisplayInfo::StopDisplayInfo()
-{
- CWindow* pw;
- CMotionToto* toto;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
- if ( pw == 0 ) return;
-
- m_interface->DeleteControl(EVENT_WINDOW4);
-
- if ( m_bEditLock ) // editing running program?
- {
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw != 0 )
- {
- pw->SetState(STATE_ENABLE); // CStudio operating
- }
- }
- else
- {
- if ( !m_bInitPause ) m_engine->SetPause(false);
- m_main->SetEditLock(false, false);
- }
- m_camera->SetType(m_infoCamera);
-
- m_engine->SetDrawWorld(true); // draws all on the interface
- m_engine->SetDrawFront(false); // draws nothing on the interface
- m_particule->SetFrameUpdate(SH_WORLD, true);
- m_particule->FlushParticule(SH_FRONT);
- m_particule->FlushParticule(SH_INTERFACE);
-
- if ( m_toto != 0 )
- {
- toto = (CMotionToto*)m_toto->RetMotion();
- if ( toto != 0 )
- {
- toto->StopDisplayInfo();
- }
- }
-
- m_light->DeleteLight(m_lightSuppl);
- m_lightSuppl = -1;
-}
-
-
-// Specifies the position.
-
-void CDisplayInfo::SetPosition(int pos)
-{
- CWindow* pw;
- CEdit* edit;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
- if ( pw == 0 ) return;
-
- edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
- if ( edit == 0 ) return;
-
- edit->SetFirstLine(pos);
-}
-
-// Returns the position.
-
-int CDisplayInfo::RetPosition()
-{
- CWindow* pw;
- CEdit* edit;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
- if ( pw == 0 ) return 0;
-
- edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
- if ( edit == 0 ) return 0;
-
- return edit->RetFirstLine();
-}
-
-
-
-// Changing the size of the display of information.
-
-void CDisplayInfo::ViewDisplayInfo()
-{
- CWindow* pw;
- CEdit* edit;
- POINT dim;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
- if ( pw == 0 ) return;
-
- edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
- if ( edit == 0 ) return;
-
- dim = m_engine->RetDim();
- edit->SetFontSize(m_main->RetFontSize()/(dim.x/640.0f));
-}
-
-// Returns the object human.
-
-CObject* CDisplayInfo::SearchToto()
-{
- ObjectType type;
- CObject* pObj;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_TOTO )
- {
- return pObj;
- }
- }
- return 0;
-}
-
-
-// Creating the list of objects.
-
-struct ObjectList
-{
- int total;
- ObjectType type;
-};
-
-void ObjectAdd(ObjectList list[], ObjectType type)
-{
- int i;
-
- for ( i=0 ; i<200 ; i++ )
- {
- if ( list[i].total == 0 )
- {
- list[i].total ++;
- list[i].type = type;
- list[i+1].total = 0;
- return;
- }
- if ( list[i].type == type )
- {
- list[i].total ++;
- return;
- }
- }
-}
-
-void ObjectWrite(FILE* file, ObjectList list[], int i)
-{
- char line[100];
- char res[100];
- char* p;
-
- if ( list[i].total < 10 )
- {
- sprintf(line, "\\c; %dx \\n;\\l;", list[i].total);
- }
- else
- {
- sprintf(line, "\\c;%dx \\n;\\l;", list[i].total);
- }
-
- GetResource(RES_OBJECT, list[i].type, res);
- if ( res[0] == 0 ) return;
- strcat(line, res);
-
- strcat(line, "\\u ");
- p = RetHelpFilename(list[i].type);
- if ( p[0] == 0 ) return;
- strcat(line, p+5); // skip "help\"
- p = strstr(line, ".txt");
- if ( p != 0 ) *p = 0;
- strcat(line, ";\n");
- fputs(line, file);
-}
-
-// Creates the file containing the list of objects.
-
-void CDisplayInfo::CreateObjectsFile()
-{
- FILE* file;
- CObject* pObj;
- ObjectType type;
- ObjectList list[200];
- char line[100];
- int i;
- bool bRadar, bAtLeast;
-
- file = fopen("help\\objects.txt", "w");
- if ( file == 0 ) return;
-
- list[0].total = 0; // empty list
- bRadar = false;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue;
- if ( !pObj->RetSelectable() ) continue;
- if ( pObj->RetProxyActivate() ) continue;
-
- type = pObj->RetType();
- if ( type == OBJECT_NULL ) continue;
- if ( type == OBJECT_FIX ) continue;
-
- ObjectAdd(list, type);
-
- if ( type == OBJECT_RADAR ) bRadar = true;
- }
-
- if ( bRadar )
- {
- GetResource(RES_TEXT, RT_SATCOM_LIST, line);
- fputs(line, file);
- bAtLeast = false;
- for ( i=0 ; i<200 ; i++ )
- {
- if ( list[i].total == 0 ) break; // end of the list?
-
- if ( list[i].type == OBJECT_BASE ||
- list[i].type == OBJECT_HUMAN )
- {
- ObjectWrite(file, list, i);
- bAtLeast = true;
- }
- }
- if ( !bAtLeast )
- {
- GetResource(RES_TEXT, RT_SATCOM_NULL, line);
- fputs(line, file);
- }
-
- strcpy(line, "\n");
- fputs(line, file);
- GetResource(RES_TEXT, RT_SATCOM_BOT, line);
- fputs(line, file);
- bAtLeast = false;
- for ( i=0 ; i<200 ; i++ )
- {
- if ( list[i].total == 0 ) break; // end of the list?
-
- if ( list[i].type == OBJECT_MOBILEwt ||
- list[i].type == OBJECT_MOBILEtt ||
- list[i].type == OBJECT_MOBILEft ||
- list[i].type == OBJECT_MOBILEit ||
- list[i].type == OBJECT_MOBILEwa ||
- list[i].type == OBJECT_MOBILEta ||
- list[i].type == OBJECT_MOBILEfa ||
- list[i].type == OBJECT_MOBILEia ||
- list[i].type == OBJECT_MOBILEwc ||
- list[i].type == OBJECT_MOBILEtc ||
- list[i].type == OBJECT_MOBILEfc ||
- list[i].type == OBJECT_MOBILEic ||
- list[i].type == OBJECT_MOBILEwi ||
- list[i].type == OBJECT_MOBILEti ||
- list[i].type == OBJECT_MOBILEfi ||
- list[i].type == OBJECT_MOBILEii ||
- list[i].type == OBJECT_MOBILEws ||
- list[i].type == OBJECT_MOBILEts ||
- list[i].type == OBJECT_MOBILEfs ||
- list[i].type == OBJECT_MOBILEis ||
- list[i].type == OBJECT_MOBILErt ||
- list[i].type == OBJECT_MOBILErc ||
- list[i].type == OBJECT_MOBILErr ||
- list[i].type == OBJECT_MOBILErs ||
- list[i].type == OBJECT_MOBILEsa ||
- list[i].type == OBJECT_MOBILEtg ||
- list[i].type == OBJECT_MOBILEdr )
- {
- ObjectWrite(file, list, i);
- bAtLeast = true;
- }
- }
- if ( !bAtLeast )
- {
- GetResource(RES_TEXT, RT_SATCOM_NULL, line);
- fputs(line, file);
- }
-
- strcpy(line, "\n");
- fputs(line, file);
- GetResource(RES_TEXT, RT_SATCOM_BUILDING, line);
- fputs(line, file);
- bAtLeast = false;
- for ( i=0 ; i<200 ; i++ )
- {
- if ( list[i].total == 0 ) break; // end of the list?
-
- if ( list[i].type == OBJECT_DERRICK ||
- list[i].type == OBJECT_FACTORY ||
- list[i].type == OBJECT_STATION ||
- list[i].type == OBJECT_CONVERT ||
- list[i].type == OBJECT_REPAIR ||
- list[i].type == OBJECT_DESTROYER||
- list[i].type == OBJECT_TOWER ||
- list[i].type == OBJECT_NEST ||
- list[i].type == OBJECT_RESEARCH ||
- list[i].type == OBJECT_RADAR ||
- list[i].type == OBJECT_ENERGY ||
- list[i].type == OBJECT_LABO ||
- list[i].type == OBJECT_NUCLEAR ||
- list[i].type == OBJECT_START ||
- list[i].type == OBJECT_END ||
- list[i].type == OBJECT_INFO ||
- list[i].type == OBJECT_PARA ||
- list[i].type == OBJECT_TARGET1 ||
- list[i].type == OBJECT_TARGET2 ||
- list[i].type == OBJECT_SAFE ||
- list[i].type == OBJECT_HUSTON )
- {
- ObjectWrite(file, list, i);
- bAtLeast = true;
- }
- }
- if ( !bAtLeast )
- {
- GetResource(RES_TEXT, RT_SATCOM_NULL, line);
- fputs(line, file);
- }
-
- strcpy(line, "\n");
- fputs(line, file);
- GetResource(RES_TEXT, RT_SATCOM_FRET, line);
- fputs(line, file);
- bAtLeast = false;
- for ( i=0 ; i<200 ; i++ )
- {
- if ( list[i].total == 0 ) break; // end of the list?
-
- if ( list[i].type == OBJECT_STONE ||
- list[i].type == OBJECT_URANIUM ||
- list[i].type == OBJECT_METAL ||
- list[i].type == OBJECT_POWER ||
- list[i].type == OBJECT_ATOMIC ||
- list[i].type == OBJECT_BULLET ||
- list[i].type == OBJECT_BBOX ||
- list[i].type == OBJECT_TNT )
- {
- ObjectWrite(file, list, i);
- bAtLeast = true;
- }
- }
- if ( !bAtLeast )
- {
- GetResource(RES_TEXT, RT_SATCOM_NULL, line);
- fputs(line, file);
- }
-
- strcpy(line, "\n");
- fputs(line, file);
- GetResource(RES_TEXT, RT_SATCOM_ALIEN, line);
- fputs(line, file);
- bAtLeast = false;
- for ( i=0 ; i<200 ; i++ )
- {
- if ( list[i].total == 0 ) break; // end of the list?
-
- if ( list[i].type == OBJECT_MOTHER ||
- list[i].type == OBJECT_ANT ||
- list[i].type == OBJECT_BEE ||
- list[i].type == OBJECT_WORM ||
- list[i].type == OBJECT_SPIDER )
- {
- ObjectWrite(file, list, i);
- bAtLeast = true;
- }
- }
- if ( !bAtLeast )
- {
- GetResource(RES_TEXT, RT_SATCOM_NULL, line);
- fputs(line, file);
- }
- }
- else
- {
- GetResource(RES_TEXT, RT_SATCOM_ERROR1, line);
- fputs(line, file);
- GetResource(RES_TEXT, RT_SATCOM_ERROR2, line);
- fputs(line, file);
- }
-
- strcpy(line, "\n");
- fputs(line, file);
-
- fclose(file);
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// displayinfo.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/language.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "old/math3d.h"
+#include "object/robotmain.h"
+#include "old/camera.h"
+#include "object/object.h"
+#include "object/motion/motion.h"
+#include "object/motion/motiontoto.h"
+#include "ui/interface.h"
+#include "ui/button.h"
+#include "ui/slider.h"
+#include "ui/edit.h"
+#include "ui/group.h"
+#include "ui/window.h"
+#include "old/particule.h"
+#include "old/light.h"
+#include "old/text.h"
+#include "script/cbottoken.h"
+#include "ui/displayinfo.h"
+
+
+
+
+// Object's constructor.
+
+CDisplayInfo::CDisplayInfo(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_STUDIO, this);
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
+ m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
+
+ m_bInfoMaximized = true;
+ m_bInfoMinimized = false;
+
+ m_infoFinalPos = m_infoActualPos = m_infoNormalPos = Math::Point(0.00f, 0.00f);
+ m_infoFinalDim = m_infoActualPos = m_infoNormalDim = Math::Point(1.00f, 1.00f);
+
+ m_lightSuppl = -1;
+ m_toto = 0;
+}
+
+// Object's destructor.
+
+CDisplayInfo::~CDisplayInfo()
+{
+ m_iMan->DeleteInstance(CLASS_STUDIO, this);
+}
+
+
+// Management of an event.
+
+bool CDisplayInfo::EventProcess(const Event &event)
+{
+ CWindow* pw;
+ CEdit* edit;
+ CSlider* slider;
+ CMotionToto* toto;
+
+ if ( event.event == EVENT_FRAME )
+ {
+ EventFrame(event);
+ HyperUpdate();
+ }
+
+ if ( event.event == EVENT_MOUSEMOVE )
+ {
+ if ( m_toto != 0 )
+ {
+ toto = (CMotionToto*)m_toto->RetMotion();
+ if ( toto != 0 )
+ {
+ toto->SetMousePos(event.pos);
+ }
+ }
+ }
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
+ if ( pw != 0 )
+ {
+ if ( event.event == pw->RetEventMsgClose() )
+ {
+ Event newEvent = event;
+ newEvent.event = EVENT_OBJECT_INFOOK;
+ m_event->AddEvent(newEvent);
+ }
+
+ if ( event.event == EVENT_SATCOM_HUSTON )
+ {
+ ChangeIndexButton(SATCOM_HUSTON);
+ }
+ if ( event.event == EVENT_SATCOM_SAT )
+ {
+ ChangeIndexButton(SATCOM_SAT);
+ }
+//? if ( event.event == EVENT_SATCOM_OBJECT )
+//? {
+//? ChangeIndexButton(SATCOM_OBJECT);
+//? }
+ if ( event.event == EVENT_SATCOM_LOADING )
+ {
+ ChangeIndexButton(SATCOM_LOADING);
+ }
+ if ( event.event == EVENT_SATCOM_PROG )
+ {
+ ChangeIndexButton(SATCOM_PROG);
+ }
+ if ( event.event == EVENT_SATCOM_SOLUCE )
+ {
+ ChangeIndexButton(SATCOM_SOLUCE);
+ }
+
+ if ( event.event == EVENT_HYPER_HOME ||
+ event.event == EVENT_HYPER_PREV ||
+ event.event == EVENT_HYPER_NEXT )
+ {
+ edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
+ if ( edit != 0 )
+ {
+ edit->HyperGo(event.event);
+ HyperUpdate();
+ }
+ }
+
+ if ( event.event == EVENT_HYPER_SIZE1 ) // size 1?
+ {
+ m_main->SetFontSize(9.0f);
+ slider = (CSlider*)pw->SearchControl(EVENT_STUDIO_SIZE);
+ if ( slider != 0 ) slider->SetVisibleValue((m_main->RetFontSize()-9.0f)/6.0f);
+ ViewDisplayInfo();
+ }
+ if ( event.event == EVENT_HYPER_SIZE2 ) // size 2?
+ {
+ m_main->SetFontSize(10.0f);
+ slider = (CSlider*)pw->SearchControl(EVENT_STUDIO_SIZE);
+ if ( slider != 0 ) slider->SetVisibleValue((m_main->RetFontSize()-9.0f)/6.0f);
+ ViewDisplayInfo();
+ }
+ if ( event.event == EVENT_HYPER_SIZE3 ) // size 3?
+ {
+ m_main->SetFontSize(12.0f);
+ slider = (CSlider*)pw->SearchControl(EVENT_STUDIO_SIZE);
+ if ( slider != 0 ) slider->SetVisibleValue((m_main->RetFontSize()-9.0f)/6.0f);
+ ViewDisplayInfo();
+ }
+ if ( event.event == EVENT_HYPER_SIZE4 ) // size 4?
+ {
+ m_main->SetFontSize(15.0f);
+ slider = (CSlider*)pw->SearchControl(EVENT_STUDIO_SIZE);
+ if ( slider != 0 ) slider->SetVisibleValue((m_main->RetFontSize()-9.0f)/6.0f);
+ ViewDisplayInfo();
+ }
+
+ if ( event.event == EVENT_STUDIO_SIZE ) // size?
+ {
+ slider = (CSlider*)pw->SearchControl(EVENT_STUDIO_SIZE);
+ if ( slider == 0 ) return false;
+ m_main->SetFontSize(9.0f+slider->RetVisibleValue()*6.0f);
+ ViewDisplayInfo();
+ }
+
+ if ( event.event == EVENT_HYPER_COPY ) // copy ?
+ {
+ edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
+ if ( edit != 0 )
+ {
+ edit->Copy();
+ }
+ }
+
+ if ( event.event == EVENT_LBUTTONDOWN ||
+ event.event == EVENT_LBUTTONUP )
+ {
+ UpdateCopyButton();
+ }
+
+ if ( event.event == EVENT_WINDOW4 ) // window moved?
+ {
+ m_infoNormalPos = m_infoActualPos = m_infoFinalPos = pw->RetPos();
+ m_infoNormalDim = m_infoActualDim = m_infoFinalDim = pw->RetDim();
+ AdjustDisplayInfo(m_infoActualPos, m_infoActualDim);
+ }
+ if ( event.event == pw->RetEventMsgReduce() )
+ {
+ if ( m_bInfoMinimized )
+ {
+ m_infoFinalPos = m_infoNormalPos;
+ m_infoFinalDim = m_infoNormalDim;
+ m_bInfoMinimized = false;
+ m_bInfoMaximized = false;
+ }
+ else
+ {
+ m_infoFinalPos.x = 0.00f;
+ m_infoFinalPos.y = -0.34f;
+ m_infoFinalDim.x = 1.00f;
+ m_infoFinalDim.y = 0.40f;
+ m_bInfoMinimized = true;
+ m_bInfoMaximized = false;
+ }
+//? m_main->SetEditFull(m_bInfoMaximized);
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
+ if ( pw != 0 )
+ {
+ pw->SetMaximized(m_bInfoMaximized);
+ pw->SetMinimized(m_bInfoMinimized);
+ }
+ }
+ if ( event.event == pw->RetEventMsgFull() )
+ {
+ if ( m_bInfoMaximized )
+ {
+ m_infoFinalPos = m_infoNormalPos;
+ m_infoFinalDim = m_infoNormalDim;
+ m_bInfoMinimized = false;
+ m_bInfoMaximized = false;
+ }
+ else
+ {
+ m_infoFinalPos.x = 0.00f;
+ m_infoFinalPos.y = 0.00f;
+ m_infoFinalDim.x = 1.00f;
+ m_infoFinalDim.y = 1.00f;
+ m_bInfoMinimized = false;
+ m_bInfoMaximized = true;
+ }
+//? m_main->SetEditFull(m_bInfoMaximized);
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
+ if ( pw != 0 )
+ {
+ pw->SetMaximized(m_bInfoMaximized);
+ pw->SetMinimized(m_bInfoMinimized);
+ }
+ }
+ }
+ return true;
+}
+
+
+// The brain is changing by time.
+
+bool CDisplayInfo::EventFrame(const Event &event)
+{
+ float time;
+
+ if ( m_infoFinalPos.x != m_infoActualPos.x ||
+ m_infoFinalPos.y != m_infoActualPos.y ||
+ m_infoFinalDim.x != m_infoActualDim.x ||
+ m_infoFinalDim.y != m_infoActualDim.y )
+ {
+ time = event.rTime*20.0f;
+ m_infoActualPos.x += (m_infoFinalPos.x-m_infoActualPos.x)*time;
+ m_infoActualPos.y += (m_infoFinalPos.y-m_infoActualPos.y)*time;
+ m_infoActualDim.x += (m_infoFinalDim.x-m_infoActualDim.x)*time;
+ m_infoActualDim.y += (m_infoFinalDim.y-m_infoActualDim.y)*time;
+ AdjustDisplayInfo(m_infoActualPos, m_infoActualDim);
+ }
+
+ return true;
+}
+
+
+// Updates the buttons for hyperlinks.
+
+void CDisplayInfo::HyperUpdate()
+{
+ CWindow* pw;
+ CEdit* edit;
+ CButton* button;
+ bool bEnable;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
+ if ( pw == 0 ) return;
+ edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
+ if ( edit == 0 ) return;
+
+ button = (CButton*)pw->SearchControl(EVENT_HYPER_HOME);
+ if ( button != 0 )
+ {
+ bEnable = edit->HyperTest(EVENT_HYPER_HOME);
+ button->SetState(STATE_ENABLE, bEnable);
+ }
+
+ button = (CButton*)pw->SearchControl(EVENT_HYPER_PREV);
+ if ( button != 0 )
+ {
+ bEnable = edit->HyperTest(EVENT_HYPER_PREV);
+ button->SetState(STATE_ENABLE, bEnable);
+ }
+
+ button = (CButton*)pw->SearchControl(EVENT_HYPER_NEXT);
+ if ( button != 0 )
+ {
+ bEnable = edit->HyperTest(EVENT_HYPER_NEXT);
+ button->SetState(STATE_ENABLE, bEnable);
+ }
+}
+
+
+// Beginning of the display of information.
+
+void CDisplayInfo::StartDisplayInfo(char *filename, int index, bool bSoluce)
+{
+ D3DLIGHT7 light;
+ Math::Point pos, dim;
+ CWindow* pw;
+ CEdit* edit;
+ CButton* button;
+ CSlider* slider;
+ CMotionToto* toto;
+
+ m_index = index;
+ m_bSoluce = bSoluce;
+
+//? CreateObjectsFile();
+
+ m_bEditLock = m_main->RetEditLock();
+ if ( m_bEditLock ) // edition running program?
+ {
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw != 0 )
+ {
+ pw->ClearState(STATE_ENABLE); // CStudio inactive
+ }
+ }
+
+ m_main->SetEditLock(true, false);
+ m_main->SetEditFull(false);
+ m_bInitPause = m_engine->RetPause();
+ m_engine->SetPause(true);
+ m_infoCamera = m_camera->RetType();
+ m_camera->SetType(CAMERA_INFO);
+
+ pos = m_infoActualPos = m_infoFinalPos;
+ dim = m_infoActualDim = m_infoFinalDim;
+ pw = m_interface->CreateWindows(pos, dim, 4, EVENT_WINDOW4);
+ if ( pw == 0 ) return;
+//? pw->SetClosable(true);
+//? GetResource(RES_TEXT, RT_DISINFO_TITLE, res);
+//? pw->SetName(res);
+//? pw->SetMinDim(Math::Point(0.56f, 0.40f));
+//? pw->SetMaximized(m_bInfoMaximized);
+//? pw->SetMinimized(m_bInfoMinimized);
+//? m_main->SetEditFull(m_bInfoMaximized);
+
+ edit = pw->CreateEdit(pos, dim, 0, EVENT_EDIT1);
+ if ( edit == 0 ) return;
+ edit->SetState(STATE_SHADOW);
+ edit->SetMultiFont(true);
+ edit->SetMaxChar(10000);
+ edit->SetFontType(FONT_COLOBOT);
+ edit->SetSoluceMode(bSoluce);
+ edit->ReadText(filename);
+ edit->HyperHome(filename);
+ edit->SetEditCap(false); // just to see!
+ edit->SetHiliteCap(false);
+ edit->SetFocus(true);
+
+ ViewDisplayInfo();
+
+ button = pw->CreateButton(pos, dim, 128+57, EVENT_SATCOM_HUSTON);
+ button->SetState(STATE_SHADOW);
+#if _TEEN
+#if !_ENGLISH
+ button = pw->CreateButton(pos, dim, 46, EVENT_SATCOM_SAT);
+#endif
+#else
+ button = pw->CreateButton(pos, dim, 128+58, EVENT_SATCOM_SAT);
+#endif
+ button->SetState(STATE_SHADOW);
+//? button = pw->CreateButton(pos, dim, 128+59, EVENT_SATCOM_OBJECT);
+//? button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 53, EVENT_SATCOM_LOADING);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 128+60, EVENT_SATCOM_PROG);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 20, EVENT_SATCOM_SOLUCE);
+ button->SetState(STATE_SHADOW);
+
+ pw->CreateGroup(pos, dim, 18, EVENT_LABEL1); // arrow >
+ pw->CreateGroup(pos, dim, 19, EVENT_LABEL2); // symbol SatCom
+
+ button = pw->CreateButton(pos, dim, 55, EVENT_HYPER_PREV);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 48, EVENT_HYPER_NEXT);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 30, EVENT_HYPER_HOME);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 82, EVENT_HYPER_SIZE1);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 83, EVENT_HYPER_SIZE2);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 90, EVENT_HYPER_SIZE3);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 91, EVENT_HYPER_SIZE4);
+ button->SetState(STATE_SHADOW);
+ slider = pw->CreateSlider(pos, dim, 0, EVENT_STUDIO_SIZE);
+ slider->SetState(STATE_SHADOW);
+ slider->SetVisibleValue((m_main->RetFontSize()-9.0f)/6.0f);
+ button = pw->CreateButton(pos, dim, 61, EVENT_HYPER_COPY);
+ button->SetState(STATE_SHADOW);
+ HyperUpdate();
+
+ button = pw->CreateButton(pos, dim, -1, EVENT_OBJECT_INFOOK);
+ button->SetState(STATE_SHADOW);
+ button->SetState(STATE_SIMPLY);
+ button->SetState(STATE_DEFAULT);
+ pw->CreateGroup(pos, dim, 21, EVENT_LABEL3); // symbol stand-by
+
+ AdjustDisplayInfo(m_infoActualPos, m_infoActualDim);
+ UpdateIndexButton();
+
+ m_engine->SetDrawWorld(false); // doesn't draw anything in the interface
+ m_engine->SetDrawFront(true); // toto draws on the interface
+ m_particule->SetFrameUpdate(SH_WORLD, false); // particles break into world
+
+ m_toto = SearchToto();
+ if ( m_toto != 0 )
+ {
+ m_toto->SetDrawFront(true);
+
+ toto = (CMotionToto*)m_toto->RetMotion();
+ if ( toto != 0 )
+ {
+ toto->StartDisplayInfo();
+ }
+ }
+
+ ZeroMemory(&light, sizeof(light));
+ light.dltType = D3DLIGHT_DIRECTIONAL;
+ light.dcvDiffuse.r = 1.0f;
+ light.dcvDiffuse.g = 1.0f;
+ light.dcvDiffuse.b = 1.0f;
+ light.dvDirection = D3DVECTOR(1.0f, 0.0f, 1.0f);
+ m_lightSuppl = m_light->CreateLight();
+ m_light->SetLight(m_lightSuppl, light);
+ m_light->SetLightExcluType(m_lightSuppl, TYPETERRAIN);
+}
+
+// Repositions all controls editing.
+
+void CDisplayInfo::AdjustDisplayInfo(Math::Point wpos, Math::Point wdim)
+{
+ CWindow* pw;
+ CEdit* edit;
+ CButton* button;
+ CSlider* slider;
+ CGroup* group;
+ Math::Point pos, dim;
+
+ wpos.x = 50.0f/640.0f;
+ wpos.y = 30.0f/480.0f;
+ wdim.x = 540.0f/640.0f;
+ wdim.y = 420.0f/480.0f;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
+ if ( pw != 0 )
+ {
+ pw->SetPos(wpos);
+ pw->SetDim(wdim);
+ wdim = pw->RetDim();
+ }
+
+ pos.x = (50.0f+10.0f)/640.0f;
+ pos.y = (30.0f+10.0f+24.0f+10.0f+324.0f-48.0f)/480.0f;
+ dim.x = 48.0f/640.0f;
+ dim.y = 48.0f/480.0f;
+ button = (CButton*)pw->SearchControl(EVENT_SATCOM_HUSTON);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.y -= (48.0f+4.0f)/480.0f;
+ button = (CButton*)pw->SearchControl(EVENT_SATCOM_SAT);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+//? pos.y -= (48.0f+4.0f)/480.0f;
+//? button = (CButton*)pw->SearchControl(EVENT_SATCOM_OBJECT);
+//? if ( button != 0 )
+//? {
+//? button->SetPos(pos);
+//? button->SetDim(dim);
+//? }
+ pos.y -= (48.0f+4.0f)/480.0f;
+ button = (CButton*)pw->SearchControl(EVENT_SATCOM_LOADING);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.y -= (48.0f+4.0f)/480.0f;
+ button = (CButton*)pw->SearchControl(EVENT_SATCOM_PROG);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.y -= (48.0f+4.0f)/480.0f;
+ button = (CButton*)pw->SearchControl(EVENT_SATCOM_SOLUCE);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+
+ pos.x = (50.0f+10.0f+5.0f)/640.0f;
+ pos.y = (30.0f+10.0f+4.0f)/480.0f;
+ dim.x = (48.0f-10.0f)/640.0f;
+ dim.y = 24.0f/480.0f;
+ button = (CButton*)pw->SearchControl(EVENT_OBJECT_INFOOK);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+
+ pos.x = (50.0f+10.0f+48.0f+10.0f)/640.0f;
+ pos.y = (30.0f+10.0f)/480.0f;
+ dim.x = 462.0f/640.0f;
+ dim.y = 358.0f/480.0f;
+ edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
+ if ( edit != 0 )
+ {
+ edit->SetPos(pos);
+ edit->SetDim(dim);
+ }
+
+ pos.x = (50.0f+10.0f+48.0f+10.0f)/640.0f;
+ pos.y = (30.0f+10.0f+358.0f+10.0f)/480.0f;
+ dim.x = 32.0f/640.0f;
+ dim.y = 32.0f/480.0f;
+ button = (CButton*)pw->SearchControl(EVENT_HYPER_PREV);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x += 35.0f/640.0f;
+ button = (CButton*)pw->SearchControl(EVENT_HYPER_NEXT);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x += 35.0f/640.0f;
+ button = (CButton*)pw->SearchControl(EVENT_HYPER_HOME);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+
+ pos.x += 50.0f/640.0f;
+ button = (CButton*)pw->SearchControl(EVENT_HYPER_SIZE1);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x += 35.0f/640.0f;
+ button = (CButton*)pw->SearchControl(EVENT_HYPER_SIZE2);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x += 35.0f/640.0f;
+ button = (CButton*)pw->SearchControl(EVENT_HYPER_SIZE3);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x += 35.0f/640.0f;
+ button = (CButton*)pw->SearchControl(EVENT_HYPER_SIZE4);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x += 35.0f/640.0f;
+ dim.x = 18.0f/640.0f;
+ slider = (CSlider*)pw->SearchControl(EVENT_STUDIO_SIZE);
+ if ( slider != 0 )
+ {
+ slider->SetPos(pos);
+ slider->SetDim(dim);
+ }
+ pos.x += 50.0f/640.0f;
+ dim.x = 32.0f/640.0f;
+ button = (CButton*)pw->SearchControl(EVENT_HYPER_COPY);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+
+ pos.x = (50.0f+10.0f)/640.0f;
+ pos.y = (30.0f+10.0f+24.0f+10.0f+324.0f+6.0f)/480.0f;
+ dim.x = 48.0f/640.0f;
+ dim.y = 40.0f/480.0f;
+ group = (CGroup*)pw->SearchControl(EVENT_LABEL2); // symbol SatCom
+ if ( group != 0 )
+ {
+ group->SetPos(pos);
+ group->SetDim(dim);
+ }
+
+ pos.x = (50.0f+10.0f+14.0f)/640.0f;
+ pos.y = (30.0f+10.0f+6.0f)/480.0f;
+ dim.x = 20.0f/640.0f;
+ dim.y = 20.0f/480.0f;
+ group = (CGroup*)pw->SearchControl(EVENT_LABEL3); // symbol stand-by
+ if ( group != 0 )
+ {
+ group->SetPos(pos);
+ group->SetDim(dim);
+ }
+}
+
+// Change the index button.
+
+void CDisplayInfo::ChangeIndexButton(int index)
+{
+ CWindow* pw;
+ CEdit* edit;
+ char* filename;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
+ if ( pw == 0 ) return;
+
+ if ( m_index != -1 )
+ {
+ m_main->SetDisplayInfoPosition(m_index, RetPosition());
+ }
+ m_index = index;
+
+ edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
+ if ( edit != 0 )
+ {
+ filename = m_main->RetDisplayInfoName(m_index);
+ edit->ReadText(filename);
+ edit->HyperHome(filename);
+ SetPosition(m_main->RetDisplayInfoPosition(m_index));
+ }
+
+ UpdateIndexButton();
+}
+
+// Adapts the index buttons.
+
+void CDisplayInfo::UpdateIndexButton()
+{
+ CWindow* pw;
+ CButton* button;
+ CGroup* group;
+ CEdit* edit;
+ Math::Point pos, dim;
+ char* filename;
+ char* loading;
+
+ static int table[SATCOM_MAX] =
+ {
+ 0, // SATCOM_HUSTON
+ 1, // SATCOM_SAT
+ -1, // SATCOM_OBJECT
+ 2, // SATCOM_LOADING
+ 3, // SATCOM_PROG
+ 4, // SATCOM_SOLUCE
+ };
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
+ if ( pw == 0 ) return;
+
+ button = (CButton*)pw->SearchControl(EVENT_SATCOM_HUSTON);
+ if ( button != 0 )
+ {
+ button->SetState(STATE_CHECK, m_index==SATCOM_HUSTON);
+ filename = m_main->RetDisplayInfoName(SATCOM_HUSTON);
+ button->SetState(STATE_VISIBLE, filename[0]!=0);
+ }
+
+ button = (CButton*)pw->SearchControl(EVENT_SATCOM_SAT);
+ if ( button != 0 )
+ {
+ button->SetState(STATE_CHECK, m_index==SATCOM_SAT);
+ filename = m_main->RetDisplayInfoName(SATCOM_SAT);
+ button->SetState(STATE_VISIBLE, filename[0]!=0);
+ }
+
+//? button = (CButton*)pw->SearchControl(EVENT_SATCOM_OBJECT);
+//? if ( button != 0 )
+//? {
+//? button->SetState(STATE_CHECK, m_index==SATCOM_OBJECT);
+//? filename = m_main->RetDisplayInfoName(SATCOM_OBJECT);
+//? button->SetState(STATE_VISIBLE, filename[0]!=0);
+//? }
+
+ loading = 0;
+ button = (CButton*)pw->SearchControl(EVENT_SATCOM_LOADING);
+ if ( button != 0 )
+ {
+ button->SetState(STATE_CHECK, m_index==SATCOM_LOADING);
+ loading = m_main->RetDisplayInfoName(SATCOM_LOADING);
+ button->SetState(STATE_VISIBLE, loading[0]!=0);
+ }
+
+ button = (CButton*)pw->SearchControl(EVENT_SATCOM_PROG);
+ if ( button != 0 )
+ {
+ button->SetState(STATE_CHECK, m_index==SATCOM_PROG);
+ filename = m_main->RetDisplayInfoName(SATCOM_PROG);
+ button->SetState(STATE_VISIBLE, filename[0]!=0 && (m_index==SATCOM_LOADING||m_index==SATCOM_PROG||(loading!=0&&loading[0]==0)));
+ }
+
+ button = (CButton*)pw->SearchControl(EVENT_SATCOM_SOLUCE);
+ if ( button != 0 )
+ {
+ button->SetState(STATE_CHECK, m_index==SATCOM_SOLUCE);
+ filename = m_main->RetDisplayInfoName(SATCOM_SOLUCE);
+ button->SetState(STATE_VISIBLE, filename[0]!=0 && m_bSoluce);
+ }
+
+ group = (CGroup*)pw->SearchControl(EVENT_LABEL1);
+ if ( group != 0 )
+ {
+ if ( m_index == -1 )
+ {
+ group->ClearState(STATE_VISIBLE);
+ }
+ else
+ {
+ group->SetState(STATE_VISIBLE);
+
+ pos.x = (50.0f+10.0f+48.0f-3.0f)/640.0f;
+ pos.y = (30.0f+10.0f+24.0f+10.0f+324.0f-48.0f-1.0f)/480.0f;
+ pos.y -= (48.0f+4.0f)/480.0f*table[m_index];
+ dim.x = 15.0f/640.0f;
+ dim.y = 48.0f/480.0f;
+ group->SetPos(pos);
+ group->SetDim(dim);
+ }
+ }
+
+#if 0
+ button = (CButton*)pw->SearchControl(EVENT_HYPER_COPY);
+ if ( button != 0 )
+ {
+ button->SetState(STATE_VISIBLE, m_index==SATCOM_LOADING);
+ }
+#endif
+
+ edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
+ if ( edit != 0 )
+ {
+//? edit->SetHiliteCap(m_index==SATCOM_LOADING);
+ edit->SetHiliteCap(true);
+ }
+
+ UpdateCopyButton();
+}
+
+// Adjusts the copy button.
+
+void CDisplayInfo::UpdateCopyButton()
+{
+ CWindow* pw;
+ CButton* button;
+ CEdit* edit;
+ int c1, c2;
+
+//? if ( m_index != SATCOM_LOADING ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
+ if ( pw == 0 ) return;
+
+ button = (CButton*)pw->SearchControl(EVENT_HYPER_COPY);
+ if ( button == 0 ) return;
+
+ edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
+ if ( edit == 0 ) return;
+
+ edit->GetCursor(c1, c2);
+ button->SetState(STATE_ENABLE, c1!=c2);
+
+}
+
+// End of the display of information.
+
+void CDisplayInfo::StopDisplayInfo()
+{
+ CWindow* pw;
+ CMotionToto* toto;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
+ if ( pw == 0 ) return;
+
+ m_interface->DeleteControl(EVENT_WINDOW4);
+
+ if ( m_bEditLock ) // editing running program?
+ {
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw != 0 )
+ {
+ pw->SetState(STATE_ENABLE); // CStudio operating
+ }
+ }
+ else
+ {
+ if ( !m_bInitPause ) m_engine->SetPause(false);
+ m_main->SetEditLock(false, false);
+ }
+ m_camera->SetType(m_infoCamera);
+
+ m_engine->SetDrawWorld(true); // draws all on the interface
+ m_engine->SetDrawFront(false); // draws nothing on the interface
+ m_particule->SetFrameUpdate(SH_WORLD, true);
+ m_particule->FlushParticule(SH_FRONT);
+ m_particule->FlushParticule(SH_INTERFACE);
+
+ if ( m_toto != 0 )
+ {
+ toto = (CMotionToto*)m_toto->RetMotion();
+ if ( toto != 0 )
+ {
+ toto->StopDisplayInfo();
+ }
+ }
+
+ m_light->DeleteLight(m_lightSuppl);
+ m_lightSuppl = -1;
+}
+
+
+// Specifies the position.
+
+void CDisplayInfo::SetPosition(int pos)
+{
+ CWindow* pw;
+ CEdit* edit;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
+ if ( pw == 0 ) return;
+
+ edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
+ if ( edit == 0 ) return;
+
+ edit->SetFirstLine(pos);
+}
+
+// Returns the position.
+
+int CDisplayInfo::RetPosition()
+{
+ CWindow* pw;
+ CEdit* edit;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
+ if ( pw == 0 ) return 0;
+
+ edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
+ if ( edit == 0 ) return 0;
+
+ return edit->RetFirstLine();
+}
+
+
+
+// Changing the size of the display of information.
+
+void CDisplayInfo::ViewDisplayInfo()
+{
+ CWindow* pw;
+ CEdit* edit;
+ POINT dim;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
+ if ( pw == 0 ) return;
+
+ edit = (CEdit*)pw->SearchControl(EVENT_EDIT1);
+ if ( edit == 0 ) return;
+
+ dim = m_engine->RetDim();
+ edit->SetFontSize(m_main->RetFontSize()/(dim.x/640.0f));
+}
+
+// Returns the object human.
+
+CObject* CDisplayInfo::SearchToto()
+{
+ ObjectType type;
+ CObject* pObj;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_TOTO )
+ {
+ return pObj;
+ }
+ }
+ return 0;
+}
+
+
+// Creating the list of objects.
+
+struct ObjectList
+{
+ int total;
+ ObjectType type;
+};
+
+void ObjectAdd(ObjectList list[], ObjectType type)
+{
+ int i;
+
+ for ( i=0 ; i<200 ; i++ )
+ {
+ if ( list[i].total == 0 )
+ {
+ list[i].total ++;
+ list[i].type = type;
+ list[i+1].total = 0;
+ return;
+ }
+ if ( list[i].type == type )
+ {
+ list[i].total ++;
+ return;
+ }
+ }
+}
+
+void ObjectWrite(FILE* file, ObjectList list[], int i)
+{
+ char line[100];
+ char res[100];
+ char* p;
+
+ if ( list[i].total < 10 )
+ {
+ sprintf(line, "\\c; %dx \\n;\\l;", list[i].total);
+ }
+ else
+ {
+ sprintf(line, "\\c;%dx \\n;\\l;", list[i].total);
+ }
+
+ GetResource(RES_OBJECT, list[i].type, res);
+ if ( res[0] == 0 ) return;
+ strcat(line, res);
+
+ strcat(line, "\\u ");
+ p = RetHelpFilename(list[i].type);
+ if ( p[0] == 0 ) return;
+ strcat(line, p+5); // skip "help\"
+ p = strstr(line, ".txt");
+ if ( p != 0 ) *p = 0;
+ strcat(line, ";\n");
+ fputs(line, file);
+}
+
+// Creates the file containing the list of objects.
+
+void CDisplayInfo::CreateObjectsFile()
+{
+ FILE* file;
+ CObject* pObj;
+ ObjectType type;
+ ObjectList list[200];
+ char line[100];
+ int i;
+ bool bRadar, bAtLeast;
+
+ file = fopen("help\\objects.txt", "w");
+ if ( file == 0 ) return;
+
+ list[0].total = 0; // empty list
+ bRadar = false;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue;
+ if ( !pObj->RetSelectable() ) continue;
+ if ( pObj->RetProxyActivate() ) continue;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_NULL ) continue;
+ if ( type == OBJECT_FIX ) continue;
+
+ ObjectAdd(list, type);
+
+ if ( type == OBJECT_RADAR ) bRadar = true;
+ }
+
+ if ( bRadar )
+ {
+ GetResource(RES_TEXT, RT_SATCOM_LIST, line);
+ fputs(line, file);
+ bAtLeast = false;
+ for ( i=0 ; i<200 ; i++ )
+ {
+ if ( list[i].total == 0 ) break; // end of the list?
+
+ if ( list[i].type == OBJECT_BASE ||
+ list[i].type == OBJECT_HUMAN )
+ {
+ ObjectWrite(file, list, i);
+ bAtLeast = true;
+ }
+ }
+ if ( !bAtLeast )
+ {
+ GetResource(RES_TEXT, RT_SATCOM_NULL, line);
+ fputs(line, file);
+ }
+
+ strcpy(line, "\n");
+ fputs(line, file);
+ GetResource(RES_TEXT, RT_SATCOM_BOT, line);
+ fputs(line, file);
+ bAtLeast = false;
+ for ( i=0 ; i<200 ; i++ )
+ {
+ if ( list[i].total == 0 ) break; // end of the list?
+
+ if ( list[i].type == OBJECT_MOBILEwt ||
+ list[i].type == OBJECT_MOBILEtt ||
+ list[i].type == OBJECT_MOBILEft ||
+ list[i].type == OBJECT_MOBILEit ||
+ list[i].type == OBJECT_MOBILEwa ||
+ list[i].type == OBJECT_MOBILEta ||
+ list[i].type == OBJECT_MOBILEfa ||
+ list[i].type == OBJECT_MOBILEia ||
+ list[i].type == OBJECT_MOBILEwc ||
+ list[i].type == OBJECT_MOBILEtc ||
+ list[i].type == OBJECT_MOBILEfc ||
+ list[i].type == OBJECT_MOBILEic ||
+ list[i].type == OBJECT_MOBILEwi ||
+ list[i].type == OBJECT_MOBILEti ||
+ list[i].type == OBJECT_MOBILEfi ||
+ list[i].type == OBJECT_MOBILEii ||
+ list[i].type == OBJECT_MOBILEws ||
+ list[i].type == OBJECT_MOBILEts ||
+ list[i].type == OBJECT_MOBILEfs ||
+ list[i].type == OBJECT_MOBILEis ||
+ list[i].type == OBJECT_MOBILErt ||
+ list[i].type == OBJECT_MOBILErc ||
+ list[i].type == OBJECT_MOBILErr ||
+ list[i].type == OBJECT_MOBILErs ||
+ list[i].type == OBJECT_MOBILEsa ||
+ list[i].type == OBJECT_MOBILEtg ||
+ list[i].type == OBJECT_MOBILEdr )
+ {
+ ObjectWrite(file, list, i);
+ bAtLeast = true;
+ }
+ }
+ if ( !bAtLeast )
+ {
+ GetResource(RES_TEXT, RT_SATCOM_NULL, line);
+ fputs(line, file);
+ }
+
+ strcpy(line, "\n");
+ fputs(line, file);
+ GetResource(RES_TEXT, RT_SATCOM_BUILDING, line);
+ fputs(line, file);
+ bAtLeast = false;
+ for ( i=0 ; i<200 ; i++ )
+ {
+ if ( list[i].total == 0 ) break; // end of the list?
+
+ if ( list[i].type == OBJECT_DERRICK ||
+ list[i].type == OBJECT_FACTORY ||
+ list[i].type == OBJECT_STATION ||
+ list[i].type == OBJECT_CONVERT ||
+ list[i].type == OBJECT_REPAIR ||
+ list[i].type == OBJECT_DESTROYER||
+ list[i].type == OBJECT_TOWER ||
+ list[i].type == OBJECT_NEST ||
+ list[i].type == OBJECT_RESEARCH ||
+ list[i].type == OBJECT_RADAR ||
+ list[i].type == OBJECT_ENERGY ||
+ list[i].type == OBJECT_LABO ||
+ list[i].type == OBJECT_NUCLEAR ||
+ list[i].type == OBJECT_START ||
+ list[i].type == OBJECT_END ||
+ list[i].type == OBJECT_INFO ||
+ list[i].type == OBJECT_PARA ||
+ list[i].type == OBJECT_TARGET1 ||
+ list[i].type == OBJECT_TARGET2 ||
+ list[i].type == OBJECT_SAFE ||
+ list[i].type == OBJECT_HUSTON )
+ {
+ ObjectWrite(file, list, i);
+ bAtLeast = true;
+ }
+ }
+ if ( !bAtLeast )
+ {
+ GetResource(RES_TEXT, RT_SATCOM_NULL, line);
+ fputs(line, file);
+ }
+
+ strcpy(line, "\n");
+ fputs(line, file);
+ GetResource(RES_TEXT, RT_SATCOM_FRET, line);
+ fputs(line, file);
+ bAtLeast = false;
+ for ( i=0 ; i<200 ; i++ )
+ {
+ if ( list[i].total == 0 ) break; // end of the list?
+
+ if ( list[i].type == OBJECT_STONE ||
+ list[i].type == OBJECT_URANIUM ||
+ list[i].type == OBJECT_METAL ||
+ list[i].type == OBJECT_POWER ||
+ list[i].type == OBJECT_ATOMIC ||
+ list[i].type == OBJECT_BULLET ||
+ list[i].type == OBJECT_BBOX ||
+ list[i].type == OBJECT_TNT )
+ {
+ ObjectWrite(file, list, i);
+ bAtLeast = true;
+ }
+ }
+ if ( !bAtLeast )
+ {
+ GetResource(RES_TEXT, RT_SATCOM_NULL, line);
+ fputs(line, file);
+ }
+
+ strcpy(line, "\n");
+ fputs(line, file);
+ GetResource(RES_TEXT, RT_SATCOM_ALIEN, line);
+ fputs(line, file);
+ bAtLeast = false;
+ for ( i=0 ; i<200 ; i++ )
+ {
+ if ( list[i].total == 0 ) break; // end of the list?
+
+ if ( list[i].type == OBJECT_MOTHER ||
+ list[i].type == OBJECT_ANT ||
+ list[i].type == OBJECT_BEE ||
+ list[i].type == OBJECT_WORM ||
+ list[i].type == OBJECT_SPIDER )
+ {
+ ObjectWrite(file, list, i);
+ bAtLeast = true;
+ }
+ }
+ if ( !bAtLeast )
+ {
+ GetResource(RES_TEXT, RT_SATCOM_NULL, line);
+ fputs(line, file);
+ }
+ }
+ else
+ {
+ GetResource(RES_TEXT, RT_SATCOM_ERROR1, line);
+ fputs(line, file);
+ GetResource(RES_TEXT, RT_SATCOM_ERROR2, line);
+ fputs(line, file);
+ }
+
+ strcpy(line, "\n");
+ fputs(line, file);
+
+ fclose(file);
+}
+
+
diff --git a/src/ui/displayinfo.h b/src/ui/displayinfo.h
index 6488309..29677d4 100644
--- a/src/ui/displayinfo.h
+++ b/src/ui/displayinfo.h
@@ -1,90 +1,90 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// displayinfo.h
-
-#pragma once
-
-
-#include "common/struct.h"
-#include "old/camera.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CEvent;
-class CRobotMain;
-class CCamera;
-class CInterface;
-class CObject;
-class CParticule;
-class CLight;
-
-
-class CDisplayInfo
-{
-public:
- CDisplayInfo(CInstanceManager* iMan);
- ~CDisplayInfo();
-
- bool EventProcess(const Event &event);
-
- void StartDisplayInfo(char *filename, int index, bool bSoluce);
- void StopDisplayInfo();
-
- void SetPosition(int pos);
- int RetPosition();
-
-protected:
- bool EventFrame(const Event &event);
- void HyperUpdate();
- void AdjustDisplayInfo(Math::Point wpos, Math::Point wdim);
- void ChangeIndexButton(int index);
- void UpdateIndexButton();
- void UpdateCopyButton();
- void ViewDisplayInfo();
- CObject* SearchToto();
- void CreateObjectsFile();
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CEvent* m_event;
- CRobotMain* m_main;
- CCamera* m_camera;
- CInterface* m_interface;
- CParticule* m_particule;
- CLight* m_light;
-
- bool m_bInfoMaximized;
- bool m_bInfoMinimized;
-
- int m_index;
- CameraType m_infoCamera;
- Math::Point m_infoNormalPos;
- Math::Point m_infoNormalDim;
- Math::Point m_infoActualPos;
- Math::Point m_infoActualDim;
- Math::Point m_infoFinalPos;
- Math::Point m_infoFinalDim;
- int m_lightSuppl;
- bool m_bEditLock;
- bool m_bInitPause;
- bool m_bSoluce;
- CObject* m_toto;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// displayinfo.h
+
+#pragma once
+
+
+#include "common/struct.h"
+#include "old/camera.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CEvent;
+class CRobotMain;
+class CCamera;
+class CInterface;
+class CObject;
+class CParticule;
+class CLight;
+
+
+class CDisplayInfo
+{
+public:
+ CDisplayInfo(CInstanceManager* iMan);
+ ~CDisplayInfo();
+
+ bool EventProcess(const Event &event);
+
+ void StartDisplayInfo(char *filename, int index, bool bSoluce);
+ void StopDisplayInfo();
+
+ void SetPosition(int pos);
+ int RetPosition();
+
+protected:
+ bool EventFrame(const Event &event);
+ void HyperUpdate();
+ void AdjustDisplayInfo(Math::Point wpos, Math::Point wdim);
+ void ChangeIndexButton(int index);
+ void UpdateIndexButton();
+ void UpdateCopyButton();
+ void ViewDisplayInfo();
+ CObject* SearchToto();
+ void CreateObjectsFile();
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CEvent* m_event;
+ CRobotMain* m_main;
+ CCamera* m_camera;
+ CInterface* m_interface;
+ CParticule* m_particule;
+ CLight* m_light;
+
+ bool m_bInfoMaximized;
+ bool m_bInfoMinimized;
+
+ int m_index;
+ CameraType m_infoCamera;
+ Math::Point m_infoNormalPos;
+ Math::Point m_infoNormalDim;
+ Math::Point m_infoActualPos;
+ Math::Point m_infoActualDim;
+ Math::Point m_infoFinalPos;
+ Math::Point m_infoFinalDim;
+ int m_lightSuppl;
+ bool m_bEditLock;
+ bool m_bInitPause;
+ bool m_bSoluce;
+ CObject* m_toto;
+};
+
+
diff --git a/src/ui/displaytext.cpp b/src/ui/displaytext.cpp
index b21d96e..9be81f4 100644
--- a/src/ui/displaytext.cpp
+++ b/src/ui/displaytext.cpp
@@ -1,613 +1,613 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// displaytext.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/restext.h"
-#include "common/iman.h"
-#include "object/object.h"
-#include "object/motion/motion.h"
-#include "object/motion/motiontoto.h"
-#include "ui/interface.h"
-#include "ui/button.h"
-#include "ui/label.h"
-#include "ui/window.h"
-#include "ui/group.h"
-#include "old/text.h"
-#include "old/sound.h"
-#include "ui/displaytext.h"
-
-
-
-const float FONTSIZE = 12.0f;
-
-
-
-// Object's constructor.
-
-CDisplayText::CDisplayText(CInstanceManager* iMan)
-{
- int i;
-
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_DISPLAYTEXT, this);
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
-
- for ( i=0 ; i<MAXDTLINE ; i++ )
- {
- m_bExist[i] = false;
- m_visitGoal[i] = Math::Vector(0.0f, 0.0f, 0.0f);
- m_visitDist[i] = 0.0f;
- m_visitHeight[i] = 0.0f;
- m_time[i] = 0.0f; // nothing displayed
- }
-
- m_bHide = false;
- m_bEnable = true;
- m_delayFactor = 1.0f;
-}
-
-// Object's destructor.
-
-CDisplayText::~CDisplayText()
-{
- m_iMan->DeleteInstance(CLASS_DISPLAYTEXT, this);
-}
-
-
-// Destroys the object.
-
-void CDisplayText::DeleteObject()
-{
- m_interface->DeleteControl(EVENT_WINDOW2);
-}
-
-
-// Management of an event.
-
-bool CDisplayText::EventProcess(const Event &event)
-{
- int i;
-
- if ( m_engine->RetPause() ) return true;
-
- if ( event.event == EVENT_FRAME )
- {
- for ( i=0 ; i<MAXDTLINE ; i++ )
- {
- if ( !m_bExist[i] ) break;
- m_time[i] -= event.rTime;
- }
- while ( true )
- {
- if ( !m_bExist[0] ||
- m_time[0] > 0.0f ) break;
- if ( !ClearLastText() ) break;
- }
- }
-
- return true;
-}
-
-
-// Displays an error.
-
-void CDisplayText::DisplayError(Error err, CObject* pObj, float time)
-{
- Math::Vector pos;
- float h, d;
-
- if ( pObj == 0 ) return;
-
- pos = pObj->RetPosition(0);
- h = RetIdealHeight(pObj);
- d = RetIdealDist(pObj);
- DisplayError(err, pos, h, d, time);
-}
-
-// Displays an error.
-
-void CDisplayText::DisplayError(Error err, Math::Vector goal, float height,
- float dist, float time)
-{
- TextType type;
- char text[100];
-
- if ( err == ERR_OK ) return;
-
-#if 0
- type = TT_INFO;
- if ( err < INFO_FIRST )
- {
- type = TT_ERROR;
- }
- if ( err == ERR_TOWER_POWER ||
- err == ERR_RESEARCH_POWER ||
- err == ERR_ENERGY_EMPTY ||
- err == ERR_LABO_NULL ||
- err == ERR_NUCLEAR_EMPTY ||
- err == ERR_CONVERT_EMPTY )
- {
- type = TT_WARNING;
- }
-#else
- type = TT_WARNING;
- if ( err >= INFO_FIRST )
- {
- type = TT_INFO;
- }
- if ( err == ERR_BAT_VIRUS ||
- err == ERR_VEH_VIRUS ||
- err == ERR_DELETEMOBILE ||
- err == ERR_DELETEBUILDING ||
- err == ERR_TOOMANY ||
- err == INFO_LOST )
- {
- type = TT_ERROR;
- }
-#endif
-
- GetResource(RES_ERR, err, text);
- DisplayText(text, goal, height, dist, time, type);
-}
-
-// Displays text.
-
-void CDisplayText::DisplayText(char *text, CObject* pObj,
- float time, TextType type)
-{
- Math::Vector pos;
- float h, d;
-
- if ( pObj == 0 ) return;
-
- pos = pObj->RetPosition(0);
- h = RetIdealHeight(pObj);
- d = RetIdealDist(pObj);
- DisplayText(text, pos, h, d, time, type);
-}
-
-// Displays text.
-
-void CDisplayText::DisplayText(char *text, Math::Vector goal, float height,
- float dist, float time, TextType type)
-{
- CObject* toto;
- CMotion* motion;
- CWindow* pw;
- CButton* button;
- CGroup* group;
- CLabel* label;
- Math::Point pos, ppos, dim;
- Sound sound;
- float hLine, hBox;
- int nLine, icon, i;
-
- if ( !m_bEnable ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
- if ( pw == 0 )
- {
- pos.x = 0.0f;
- pos.y = 0.0f;
- dim.x = 0.0f;
- dim.y = 0.0f;
- pw = m_interface->CreateWindows(pos, dim, 10, EVENT_WINDOW2);
- }
-
- hBox = 0.045f;
- hLine = m_engine->RetText()->RetHeight(FONTSIZE, FONT_COLOBOT);
-
- nLine = 0;
- for ( i=0 ; i<MAXDTLINE ; i++ )
- {
- group = (CGroup*)pw->SearchControl(EventMsg(EVENT_DT_GROUP0+i));
- if ( group == 0 ) break;
- nLine ++;
- }
-
- if ( nLine == MAXDTLINE )
- {
- ClearLastText();
- nLine --;
- }
-
- pos.x = 0.10f;
- pos.y = 0.92f-hBox-hBox*nLine;
- dim.x = 0.80f;
- dim.y = hBox;
-
- icon = 1; // yellow
- if ( type == TT_ERROR ) icon = 9; // red
- if ( type == TT_WARNING ) icon = 10; // blue
- if ( type == TT_INFO ) icon = 8; // green
- if ( type == TT_MESSAGE ) icon = 11; // yellow
- pw->CreateGroup(pos, dim, icon, EventMsg(EVENT_DT_GROUP0+nLine));
-
- pw->SetTrashEvent(false);
-
- ppos = pos;
- ppos.y -= hLine/2.0f;
- label = pw->CreateLabel(ppos, dim, -1, EventMsg(EVENT_DT_LABEL0+nLine), text);
- if ( label != 0 )
- {
- label->SetFontSize(FONTSIZE);
- }
-
- dim.x = dim.y*0.75f;
- pos.x -= dim.x;
- button = pw->CreateButton(pos, dim, 14, EventMsg(EVENT_DT_VISIT0+nLine));
-
- if ( goal.x == 0.0f &&
- goal.y == 0.0f &&
- goal.z == 0.0f )
- {
- button->ClearState(STATE_ENABLE);
- }
-
- m_bExist[nLine] = true;
- m_visitGoal[nLine] = goal;
- m_visitDist[nLine] = dist;
- m_visitHeight[nLine] = height;
- m_time[nLine] = time*m_delayFactor;
-
- toto = SearchToto();
- if ( toto != 0 )
- {
- motion = toto->RetMotion();
- if ( motion != 0 )
- {
- if ( type == TT_ERROR )
- {
- motion->SetAction(MT_ERROR, 4.0f);
- }
- if ( type == TT_WARNING )
- {
- motion->SetAction(MT_WARNING, 4.0f);
- }
- if ( type == TT_INFO )
- {
- motion->SetAction(MT_INFO, 4.0f);
- }
- if ( type == TT_MESSAGE )
- {
- motion->SetAction(MT_MESSAGE, 4.0f);
- }
- }
- }
-
- if ( m_bHide )
- {
- HideText(m_bHide); // hide all
- }
- else
- {
- sound = SOUND_CLICK;
- if ( type == TT_ERROR ) sound = SOUND_ERROR;
- if ( type == TT_WARNING ) sound = SOUND_WARNING;
- if ( type == TT_INFO ) sound = SOUND_INFO;
- if ( type == TT_MESSAGE ) sound = SOUND_MESSAGE;
-
- if ( sound != SOUND_CLICK )
- {
- m_sound->Play(sound);
- }
- }
-}
-
-// Clears all text.
-
-void CDisplayText::ClearText()
-{
- CWindow* pw;
- int i;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
-
- for ( i=0 ; i<MAXDTLINE ; i++ )
- {
- if ( pw != 0 )
- {
- pw->DeleteControl(EventMsg(EVENT_DT_GROUP0+i));
- pw->DeleteControl(EventMsg(EVENT_DT_LABEL0+i));
- pw->DeleteControl(EventMsg(EVENT_DT_VISIT0+i));
- }
- m_bExist[i] = false;
- m_visitGoal[i] = Math::Vector(0.0f, 0.0f, 0.0f);
- m_visitDist[i] = 0.0f;
- m_visitHeight[i] = 0.0f;
- m_time[i] = 0.0f;
- }
-}
-
-// Hides or shows all texts.
-
-void CDisplayText::HideText(bool bHide)
-{
- CWindow* pw;
- CGroup* pg;
- CLabel* pl;
- CButton* pb;
- int i;
-
- m_bHide = bHide;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
- if ( pw == 0 ) return;
-
- for ( i=0 ; i<MAXDTLINE ; i++ )
- {
- pg = (CGroup*)pw->SearchControl(EventMsg(EVENT_DT_GROUP0+i));
- if ( pg != 0 )
- {
- pg->SetState(STATE_VISIBLE, !bHide);
- }
-
- pl = (CLabel* )pw->SearchControl(EventMsg(EVENT_DT_LABEL0+i));
- if ( pl != 0 )
- {
- pl->SetState(STATE_VISIBLE, !bHide);
- }
-
- pb = (CButton*)pw->SearchControl(EventMsg(EVENT_DT_VISIT0+i));
- if ( pb != 0 )
- {
- pb->SetState(STATE_VISIBLE, !bHide);
- }
- }
-}
-
-// Removes the last text (top of the list).
-
-bool CDisplayText::ClearLastText()
-{
- CWindow *pw;
- CButton *pb1, *pb2;
- CGroup *pg1, *pg2;
- CLabel *pl1, *pl2;
- int i;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
- if ( pw == 0 ) return false;
-
- pb2 = (CButton*)pw->SearchControl(EVENT_DT_VISIT0);
- if ( pb2 == 0 ) return false; // same not of first-line
- pg2 = (CGroup*)pw->SearchControl(EVENT_DT_GROUP0);
- if ( pg2 == 0 ) return false;
- pl2 = (CLabel*)pw->SearchControl(EVENT_DT_LABEL0);
- if ( pl2 == 0 ) return false;
-
- for ( i=0 ; i<MAXDTLINE-1 ; i++ )
- {
- pb1 = pb2;
- pg1 = pg2;
- pl1 = pl2;
-
- pb2 = (CButton*)pw->SearchControl(EventMsg(EVENT_DT_VISIT0+i+1));
- if ( pb2 == 0 ) break;
-
- pg2 = (CGroup*)pw->SearchControl(EventMsg(EVENT_DT_GROUP0+i+1));
- if ( pg2 == 0 ) break;
-
- pl2 = (CLabel*)pw->SearchControl(EventMsg(EVENT_DT_LABEL0+i+1));
- if ( pl2 == 0 ) break;
-
- pb1->SetState(STATE_ENABLE, pb2->TestState(STATE_ENABLE));
- pg1->SetIcon(pg2->RetIcon());
- pl1->SetName(pl2->RetName());
-
- m_time[i] = m_time[i+1];
- m_visitGoal[i] = m_visitGoal[i+1];
- m_visitDist[i] = m_visitDist[i+1];
- m_visitHeight[i] = m_visitHeight[i+1]; // shift
- }
-
- pw->DeleteControl(EventMsg(EVENT_DT_VISIT0+i));
- pw->DeleteControl(EventMsg(EVENT_DT_GROUP0+i));
- pw->DeleteControl(EventMsg(EVENT_DT_LABEL0+i));
- m_bExist[i] = false;
- return true;
-}
-
-
-// Specifies the factor of time.
-
-void CDisplayText::SetDelay(float factor)
-{
- m_delayFactor = factor;
-}
-
-
-// Enables the display of text.
-
-void CDisplayText::SetEnable(bool bEnable)
-{
- m_bEnable = bEnable;
-}
-
-
-// Returns the goal during a visit.
-
-Math::Vector CDisplayText::RetVisitGoal(EventMsg event)
-{
- int i;
-
- i = event-EVENT_DT_VISIT0;
- if ( i < 0 || i >= MAXDTLINE ) return Math::Vector(0.0f, 0.0f, 0.0f);
- return m_visitGoal[i];
-}
-
-// Returns the distance during a visit.
-
-float CDisplayText::RetVisitDist(EventMsg event)
-{
- int i;
-
- i = event-EVENT_DT_VISIT0;
- if ( i < 0 || i >= MAXDTLINE ) return 0.0f;
- return m_visitDist[i];
-}
-
-// Returns the height on a visit.
-
-float CDisplayText::RetVisitHeight(EventMsg event)
-{
- int i;
-
- i = event-EVENT_DT_VISIT0;
- if ( i < 0 || i >= MAXDTLINE ) return 0.0f;
- return m_visitHeight[i];
-}
-
-
-// Ranges from ideal visit for a given object.
-
-float CDisplayText::RetIdealDist(CObject* pObj)
-{
- ObjectType type;
-
- if ( pObj == 0 ) return 40.0f;
-
- type = pObj->RetType();
- if ( type == OBJECT_PORTICO ) return 200.0f;
- if ( type == OBJECT_BASE ) return 200.0f;
- if ( type == OBJECT_NUCLEAR ) return 100.0f;
- if ( type == OBJECT_PARA ) return 100.0f;
- if ( type == OBJECT_SAFE ) return 100.0f;
- if ( type == OBJECT_TOWER ) return 80.0f;
-
- return 60.0f;
-}
-
-// Returns the height of ideal visit for a given object.
-
-float CDisplayText::RetIdealHeight(CObject* pObj)
-{
- ObjectType type;
-
- if ( pObj == 0 ) return 5.0f;
-
- type = pObj->RetType();
- if ( type == OBJECT_DERRICK ) return 35.0f;
- if ( type == OBJECT_FACTORY ) return 22.0f;
- if ( type == OBJECT_REPAIR ) return 30.0f;
- if ( type == OBJECT_DESTROYER) return 30.0f;
- if ( type == OBJECT_STATION ) return 13.0f;
- if ( type == OBJECT_CONVERT ) return 20.0f;
- if ( type == OBJECT_TOWER ) return 30.0f;
- if ( type == OBJECT_RESEARCH ) return 22.0f;
- if ( type == OBJECT_RADAR ) return 19.0f;
- if ( type == OBJECT_INFO ) return 19.0f;
- if ( type == OBJECT_ENERGY ) return 20.0f;
- if ( type == OBJECT_LABO ) return 16.0f;
- if ( type == OBJECT_NUCLEAR ) return 40.0f;
- if ( type == OBJECT_PARA ) return 40.0f;
- if ( type == OBJECT_SAFE ) return 20.0f;
-
- return 15.0f;
-}
-
-
-// Removes all visits.
-
-void CDisplayText::ClearVisit()
-{
- CWindow* pw;
- CButton* pb;
- int i;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
- if ( pw == 0 ) return;
-
- for ( i=0 ; i<MAXDTLINE ; i++ )
- {
- pb = (CButton*)pw->SearchControl(EventMsg(EVENT_DT_VISIT0+i));
- if ( pb == 0 ) break;
- pb->SetIcon(14); // eyes
- }
-}
-
-// Puts a button in "visit".
-
-void CDisplayText::SetVisit(EventMsg event)
-{
- CWindow* pw;
- CButton* pb;
- int i;
-
- i = event-EVENT_DT_VISIT0;
- if ( i < 0 || i >= MAXDTLINE ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
- if ( pw == 0 ) return;
- pb = (CButton*)pw->SearchControl(EventMsg(EVENT_DT_VISIT0+i));
- if ( pb == 0 ) return;
- pb->SetIcon(48); // >
-}
-
-// Indicates whether a button is set to "visit".
-
-bool CDisplayText::IsVisit(EventMsg event)
-{
- CWindow* pw;
- CButton* pb;
- int i;
-
- i = event-EVENT_DT_VISIT0;
- if ( i < 0 || i >= MAXDTLINE ) return false;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
- if ( pw == 0 ) return false;
- pb = (CButton*)pw->SearchControl(EventMsg(EVENT_DT_VISIT0+i));
- if ( pb == 0 ) return false;
- return (pb->RetIcon() == 48); // > ?
-}
-
-
-// Returns the object toto.
-
-CObject* CDisplayText::SearchToto()
-{
- ObjectType type;
- CObject* pObj;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- type = pObj->RetType();
- if ( type == OBJECT_TOTO )
- {
- return pObj;
- }
- }
- return 0;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// displaytext.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/restext.h"
+#include "common/iman.h"
+#include "object/object.h"
+#include "object/motion/motion.h"
+#include "object/motion/motiontoto.h"
+#include "ui/interface.h"
+#include "ui/button.h"
+#include "ui/label.h"
+#include "ui/window.h"
+#include "ui/group.h"
+#include "old/text.h"
+#include "old/sound.h"
+#include "ui/displaytext.h"
+
+
+
+const float FONTSIZE = 12.0f;
+
+
+
+// Object's constructor.
+
+CDisplayText::CDisplayText(CInstanceManager* iMan)
+{
+ int i;
+
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_DISPLAYTEXT, this);
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+
+ for ( i=0 ; i<MAXDTLINE ; i++ )
+ {
+ m_bExist[i] = false;
+ m_visitGoal[i] = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_visitDist[i] = 0.0f;
+ m_visitHeight[i] = 0.0f;
+ m_time[i] = 0.0f; // nothing displayed
+ }
+
+ m_bHide = false;
+ m_bEnable = true;
+ m_delayFactor = 1.0f;
+}
+
+// Object's destructor.
+
+CDisplayText::~CDisplayText()
+{
+ m_iMan->DeleteInstance(CLASS_DISPLAYTEXT, this);
+}
+
+
+// Destroys the object.
+
+void CDisplayText::DeleteObject()
+{
+ m_interface->DeleteControl(EVENT_WINDOW2);
+}
+
+
+// Management of an event.
+
+bool CDisplayText::EventProcess(const Event &event)
+{
+ int i;
+
+ if ( m_engine->RetPause() ) return true;
+
+ if ( event.event == EVENT_FRAME )
+ {
+ for ( i=0 ; i<MAXDTLINE ; i++ )
+ {
+ if ( !m_bExist[i] ) break;
+ m_time[i] -= event.rTime;
+ }
+ while ( true )
+ {
+ if ( !m_bExist[0] ||
+ m_time[0] > 0.0f ) break;
+ if ( !ClearLastText() ) break;
+ }
+ }
+
+ return true;
+}
+
+
+// Displays an error.
+
+void CDisplayText::DisplayError(Error err, CObject* pObj, float time)
+{
+ Math::Vector pos;
+ float h, d;
+
+ if ( pObj == 0 ) return;
+
+ pos = pObj->RetPosition(0);
+ h = RetIdealHeight(pObj);
+ d = RetIdealDist(pObj);
+ DisplayError(err, pos, h, d, time);
+}
+
+// Displays an error.
+
+void CDisplayText::DisplayError(Error err, Math::Vector goal, float height,
+ float dist, float time)
+{
+ TextType type;
+ char text[100];
+
+ if ( err == ERR_OK ) return;
+
+#if 0
+ type = TT_INFO;
+ if ( err < INFO_FIRST )
+ {
+ type = TT_ERROR;
+ }
+ if ( err == ERR_TOWER_POWER ||
+ err == ERR_RESEARCH_POWER ||
+ err == ERR_ENERGY_EMPTY ||
+ err == ERR_LABO_NULL ||
+ err == ERR_NUCLEAR_EMPTY ||
+ err == ERR_CONVERT_EMPTY )
+ {
+ type = TT_WARNING;
+ }
+#else
+ type = TT_WARNING;
+ if ( err >= INFO_FIRST )
+ {
+ type = TT_INFO;
+ }
+ if ( err == ERR_BAT_VIRUS ||
+ err == ERR_VEH_VIRUS ||
+ err == ERR_DELETEMOBILE ||
+ err == ERR_DELETEBUILDING ||
+ err == ERR_TOOMANY ||
+ err == INFO_LOST )
+ {
+ type = TT_ERROR;
+ }
+#endif
+
+ GetResource(RES_ERR, err, text);
+ DisplayText(text, goal, height, dist, time, type);
+}
+
+// Displays text.
+
+void CDisplayText::DisplayText(char *text, CObject* pObj,
+ float time, TextType type)
+{
+ Math::Vector pos;
+ float h, d;
+
+ if ( pObj == 0 ) return;
+
+ pos = pObj->RetPosition(0);
+ h = RetIdealHeight(pObj);
+ d = RetIdealDist(pObj);
+ DisplayText(text, pos, h, d, time, type);
+}
+
+// Displays text.
+
+void CDisplayText::DisplayText(char *text, Math::Vector goal, float height,
+ float dist, float time, TextType type)
+{
+ CObject* toto;
+ CMotion* motion;
+ CWindow* pw;
+ CButton* button;
+ CGroup* group;
+ CLabel* label;
+ Math::Point pos, ppos, dim;
+ Sound sound;
+ float hLine, hBox;
+ int nLine, icon, i;
+
+ if ( !m_bEnable ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
+ if ( pw == 0 )
+ {
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ dim.x = 0.0f;
+ dim.y = 0.0f;
+ pw = m_interface->CreateWindows(pos, dim, 10, EVENT_WINDOW2);
+ }
+
+ hBox = 0.045f;
+ hLine = m_engine->RetText()->RetHeight(FONTSIZE, FONT_COLOBOT);
+
+ nLine = 0;
+ for ( i=0 ; i<MAXDTLINE ; i++ )
+ {
+ group = (CGroup*)pw->SearchControl(EventMsg(EVENT_DT_GROUP0+i));
+ if ( group == 0 ) break;
+ nLine ++;
+ }
+
+ if ( nLine == MAXDTLINE )
+ {
+ ClearLastText();
+ nLine --;
+ }
+
+ pos.x = 0.10f;
+ pos.y = 0.92f-hBox-hBox*nLine;
+ dim.x = 0.80f;
+ dim.y = hBox;
+
+ icon = 1; // yellow
+ if ( type == TT_ERROR ) icon = 9; // red
+ if ( type == TT_WARNING ) icon = 10; // blue
+ if ( type == TT_INFO ) icon = 8; // green
+ if ( type == TT_MESSAGE ) icon = 11; // yellow
+ pw->CreateGroup(pos, dim, icon, EventMsg(EVENT_DT_GROUP0+nLine));
+
+ pw->SetTrashEvent(false);
+
+ ppos = pos;
+ ppos.y -= hLine/2.0f;
+ label = pw->CreateLabel(ppos, dim, -1, EventMsg(EVENT_DT_LABEL0+nLine), text);
+ if ( label != 0 )
+ {
+ label->SetFontSize(FONTSIZE);
+ }
+
+ dim.x = dim.y*0.75f;
+ pos.x -= dim.x;
+ button = pw->CreateButton(pos, dim, 14, EventMsg(EVENT_DT_VISIT0+nLine));
+
+ if ( goal.x == 0.0f &&
+ goal.y == 0.0f &&
+ goal.z == 0.0f )
+ {
+ button->ClearState(STATE_ENABLE);
+ }
+
+ m_bExist[nLine] = true;
+ m_visitGoal[nLine] = goal;
+ m_visitDist[nLine] = dist;
+ m_visitHeight[nLine] = height;
+ m_time[nLine] = time*m_delayFactor;
+
+ toto = SearchToto();
+ if ( toto != 0 )
+ {
+ motion = toto->RetMotion();
+ if ( motion != 0 )
+ {
+ if ( type == TT_ERROR )
+ {
+ motion->SetAction(MT_ERROR, 4.0f);
+ }
+ if ( type == TT_WARNING )
+ {
+ motion->SetAction(MT_WARNING, 4.0f);
+ }
+ if ( type == TT_INFO )
+ {
+ motion->SetAction(MT_INFO, 4.0f);
+ }
+ if ( type == TT_MESSAGE )
+ {
+ motion->SetAction(MT_MESSAGE, 4.0f);
+ }
+ }
+ }
+
+ if ( m_bHide )
+ {
+ HideText(m_bHide); // hide all
+ }
+ else
+ {
+ sound = SOUND_CLICK;
+ if ( type == TT_ERROR ) sound = SOUND_ERROR;
+ if ( type == TT_WARNING ) sound = SOUND_WARNING;
+ if ( type == TT_INFO ) sound = SOUND_INFO;
+ if ( type == TT_MESSAGE ) sound = SOUND_MESSAGE;
+
+ if ( sound != SOUND_CLICK )
+ {
+ m_sound->Play(sound);
+ }
+ }
+}
+
+// Clears all text.
+
+void CDisplayText::ClearText()
+{
+ CWindow* pw;
+ int i;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
+
+ for ( i=0 ; i<MAXDTLINE ; i++ )
+ {
+ if ( pw != 0 )
+ {
+ pw->DeleteControl(EventMsg(EVENT_DT_GROUP0+i));
+ pw->DeleteControl(EventMsg(EVENT_DT_LABEL0+i));
+ pw->DeleteControl(EventMsg(EVENT_DT_VISIT0+i));
+ }
+ m_bExist[i] = false;
+ m_visitGoal[i] = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_visitDist[i] = 0.0f;
+ m_visitHeight[i] = 0.0f;
+ m_time[i] = 0.0f;
+ }
+}
+
+// Hides or shows all texts.
+
+void CDisplayText::HideText(bool bHide)
+{
+ CWindow* pw;
+ CGroup* pg;
+ CLabel* pl;
+ CButton* pb;
+ int i;
+
+ m_bHide = bHide;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
+ if ( pw == 0 ) return;
+
+ for ( i=0 ; i<MAXDTLINE ; i++ )
+ {
+ pg = (CGroup*)pw->SearchControl(EventMsg(EVENT_DT_GROUP0+i));
+ if ( pg != 0 )
+ {
+ pg->SetState(STATE_VISIBLE, !bHide);
+ }
+
+ pl = (CLabel* )pw->SearchControl(EventMsg(EVENT_DT_LABEL0+i));
+ if ( pl != 0 )
+ {
+ pl->SetState(STATE_VISIBLE, !bHide);
+ }
+
+ pb = (CButton*)pw->SearchControl(EventMsg(EVENT_DT_VISIT0+i));
+ if ( pb != 0 )
+ {
+ pb->SetState(STATE_VISIBLE, !bHide);
+ }
+ }
+}
+
+// Removes the last text (top of the list).
+
+bool CDisplayText::ClearLastText()
+{
+ CWindow *pw;
+ CButton *pb1, *pb2;
+ CGroup *pg1, *pg2;
+ CLabel *pl1, *pl2;
+ int i;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
+ if ( pw == 0 ) return false;
+
+ pb2 = (CButton*)pw->SearchControl(EVENT_DT_VISIT0);
+ if ( pb2 == 0 ) return false; // same not of first-line
+ pg2 = (CGroup*)pw->SearchControl(EVENT_DT_GROUP0);
+ if ( pg2 == 0 ) return false;
+ pl2 = (CLabel*)pw->SearchControl(EVENT_DT_LABEL0);
+ if ( pl2 == 0 ) return false;
+
+ for ( i=0 ; i<MAXDTLINE-1 ; i++ )
+ {
+ pb1 = pb2;
+ pg1 = pg2;
+ pl1 = pl2;
+
+ pb2 = (CButton*)pw->SearchControl(EventMsg(EVENT_DT_VISIT0+i+1));
+ if ( pb2 == 0 ) break;
+
+ pg2 = (CGroup*)pw->SearchControl(EventMsg(EVENT_DT_GROUP0+i+1));
+ if ( pg2 == 0 ) break;
+
+ pl2 = (CLabel*)pw->SearchControl(EventMsg(EVENT_DT_LABEL0+i+1));
+ if ( pl2 == 0 ) break;
+
+ pb1->SetState(STATE_ENABLE, pb2->TestState(STATE_ENABLE));
+ pg1->SetIcon(pg2->RetIcon());
+ pl1->SetName(pl2->RetName());
+
+ m_time[i] = m_time[i+1];
+ m_visitGoal[i] = m_visitGoal[i+1];
+ m_visitDist[i] = m_visitDist[i+1];
+ m_visitHeight[i] = m_visitHeight[i+1]; // shift
+ }
+
+ pw->DeleteControl(EventMsg(EVENT_DT_VISIT0+i));
+ pw->DeleteControl(EventMsg(EVENT_DT_GROUP0+i));
+ pw->DeleteControl(EventMsg(EVENT_DT_LABEL0+i));
+ m_bExist[i] = false;
+ return true;
+}
+
+
+// Specifies the factor of time.
+
+void CDisplayText::SetDelay(float factor)
+{
+ m_delayFactor = factor;
+}
+
+
+// Enables the display of text.
+
+void CDisplayText::SetEnable(bool bEnable)
+{
+ m_bEnable = bEnable;
+}
+
+
+// Returns the goal during a visit.
+
+Math::Vector CDisplayText::RetVisitGoal(EventMsg event)
+{
+ int i;
+
+ i = event-EVENT_DT_VISIT0;
+ if ( i < 0 || i >= MAXDTLINE ) return Math::Vector(0.0f, 0.0f, 0.0f);
+ return m_visitGoal[i];
+}
+
+// Returns the distance during a visit.
+
+float CDisplayText::RetVisitDist(EventMsg event)
+{
+ int i;
+
+ i = event-EVENT_DT_VISIT0;
+ if ( i < 0 || i >= MAXDTLINE ) return 0.0f;
+ return m_visitDist[i];
+}
+
+// Returns the height on a visit.
+
+float CDisplayText::RetVisitHeight(EventMsg event)
+{
+ int i;
+
+ i = event-EVENT_DT_VISIT0;
+ if ( i < 0 || i >= MAXDTLINE ) return 0.0f;
+ return m_visitHeight[i];
+}
+
+
+// Ranges from ideal visit for a given object.
+
+float CDisplayText::RetIdealDist(CObject* pObj)
+{
+ ObjectType type;
+
+ if ( pObj == 0 ) return 40.0f;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_PORTICO ) return 200.0f;
+ if ( type == OBJECT_BASE ) return 200.0f;
+ if ( type == OBJECT_NUCLEAR ) return 100.0f;
+ if ( type == OBJECT_PARA ) return 100.0f;
+ if ( type == OBJECT_SAFE ) return 100.0f;
+ if ( type == OBJECT_TOWER ) return 80.0f;
+
+ return 60.0f;
+}
+
+// Returns the height of ideal visit for a given object.
+
+float CDisplayText::RetIdealHeight(CObject* pObj)
+{
+ ObjectType type;
+
+ if ( pObj == 0 ) return 5.0f;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_DERRICK ) return 35.0f;
+ if ( type == OBJECT_FACTORY ) return 22.0f;
+ if ( type == OBJECT_REPAIR ) return 30.0f;
+ if ( type == OBJECT_DESTROYER) return 30.0f;
+ if ( type == OBJECT_STATION ) return 13.0f;
+ if ( type == OBJECT_CONVERT ) return 20.0f;
+ if ( type == OBJECT_TOWER ) return 30.0f;
+ if ( type == OBJECT_RESEARCH ) return 22.0f;
+ if ( type == OBJECT_RADAR ) return 19.0f;
+ if ( type == OBJECT_INFO ) return 19.0f;
+ if ( type == OBJECT_ENERGY ) return 20.0f;
+ if ( type == OBJECT_LABO ) return 16.0f;
+ if ( type == OBJECT_NUCLEAR ) return 40.0f;
+ if ( type == OBJECT_PARA ) return 40.0f;
+ if ( type == OBJECT_SAFE ) return 20.0f;
+
+ return 15.0f;
+}
+
+
+// Removes all visits.
+
+void CDisplayText::ClearVisit()
+{
+ CWindow* pw;
+ CButton* pb;
+ int i;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
+ if ( pw == 0 ) return;
+
+ for ( i=0 ; i<MAXDTLINE ; i++ )
+ {
+ pb = (CButton*)pw->SearchControl(EventMsg(EVENT_DT_VISIT0+i));
+ if ( pb == 0 ) break;
+ pb->SetIcon(14); // eyes
+ }
+}
+
+// Puts a button in "visit".
+
+void CDisplayText::SetVisit(EventMsg event)
+{
+ CWindow* pw;
+ CButton* pb;
+ int i;
+
+ i = event-EVENT_DT_VISIT0;
+ if ( i < 0 || i >= MAXDTLINE ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
+ if ( pw == 0 ) return;
+ pb = (CButton*)pw->SearchControl(EventMsg(EVENT_DT_VISIT0+i));
+ if ( pb == 0 ) return;
+ pb->SetIcon(48); // >
+}
+
+// Indicates whether a button is set to "visit".
+
+bool CDisplayText::IsVisit(EventMsg event)
+{
+ CWindow* pw;
+ CButton* pb;
+ int i;
+
+ i = event-EVENT_DT_VISIT0;
+ if ( i < 0 || i >= MAXDTLINE ) return false;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
+ if ( pw == 0 ) return false;
+ pb = (CButton*)pw->SearchControl(EventMsg(EVENT_DT_VISIT0+i));
+ if ( pb == 0 ) return false;
+ return (pb->RetIcon() == 48); // > ?
+}
+
+
+// Returns the object toto.
+
+CObject* CDisplayText::SearchToto()
+{
+ ObjectType type;
+ CObject* pObj;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_TOTO )
+ {
+ return pObj;
+ }
+ }
+ return 0;
+}
+
diff --git a/src/ui/displaytext.h b/src/ui/displaytext.h
index fbff7c9..c2eea98 100644
--- a/src/ui/displaytext.h
+++ b/src/ui/displaytext.h
@@ -1,96 +1,96 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// displaytext.h
-
-#pragma once
-
-
-#include "common/event.h"
-#include "common/misc.h"
-#include "old/d3dengine.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CInterface;
-class CObject;
-class CSound;
-
-
-enum TextType
-{
- TT_ERROR = 1,
- TT_WARNING = 2,
- TT_INFO = 3,
- TT_MESSAGE = 4,
-};
-
-const int MAXDTLINE = 4;
-
-
-class CDisplayText
-{
-public:
- CDisplayText(CInstanceManager* iMan);
- ~CDisplayText();
-
- void DeleteObject();
-
- bool EventProcess(const Event &event);
-
- void DisplayError(Error err, CObject* pObj, float time=10.0f);
- void DisplayError(Error err, Math::Vector goal, float height=15.0f, float dist=60.0f, float time=10.0f);
- void DisplayText(char *text, CObject* pObj, float time=10.0f, TextType type=TT_INFO);
- void DisplayText(char *text, Math::Vector goal, float height=15.0f, float dist=60.0f, float time=10.0f, TextType type=TT_INFO);
- void HideText(bool bHide);
- void ClearText();
- bool ClearLastText();
- void SetDelay(float factor);
- void SetEnable(bool bEnable);
-
- Math::Vector RetVisitGoal(EventMsg event);
- float RetVisitDist(EventMsg event);
- float RetVisitHeight(EventMsg event);
-
- float RetIdealDist(CObject* pObj);
- float RetIdealHeight(CObject* pObj);
-
- void ClearVisit();
- void SetVisit(EventMsg event);
- bool IsVisit(EventMsg event);
-
-protected:
- CObject* SearchToto();
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CInterface* m_interface;
- CSound* m_sound;
-
- bool m_bExist[MAXDTLINE];
- float m_time[MAXDTLINE];
- Math::Vector m_visitGoal[MAXDTLINE];
- float m_visitDist[MAXDTLINE];
- float m_visitHeight[MAXDTLINE];
-
- bool m_bHide;
- bool m_bEnable;
- float m_delayFactor;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// displaytext.h
+
+#pragma once
+
+
+#include "common/event.h"
+#include "common/misc.h"
+#include "old/d3dengine.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CInterface;
+class CObject;
+class CSound;
+
+
+enum TextType
+{
+ TT_ERROR = 1,
+ TT_WARNING = 2,
+ TT_INFO = 3,
+ TT_MESSAGE = 4,
+};
+
+const int MAXDTLINE = 4;
+
+
+class CDisplayText
+{
+public:
+ CDisplayText(CInstanceManager* iMan);
+ ~CDisplayText();
+
+ void DeleteObject();
+
+ bool EventProcess(const Event &event);
+
+ void DisplayError(Error err, CObject* pObj, float time=10.0f);
+ void DisplayError(Error err, Math::Vector goal, float height=15.0f, float dist=60.0f, float time=10.0f);
+ void DisplayText(char *text, CObject* pObj, float time=10.0f, TextType type=TT_INFO);
+ void DisplayText(char *text, Math::Vector goal, float height=15.0f, float dist=60.0f, float time=10.0f, TextType type=TT_INFO);
+ void HideText(bool bHide);
+ void ClearText();
+ bool ClearLastText();
+ void SetDelay(float factor);
+ void SetEnable(bool bEnable);
+
+ Math::Vector RetVisitGoal(EventMsg event);
+ float RetVisitDist(EventMsg event);
+ float RetVisitHeight(EventMsg event);
+
+ float RetIdealDist(CObject* pObj);
+ float RetIdealHeight(CObject* pObj);
+
+ void ClearVisit();
+ void SetVisit(EventMsg event);
+ bool IsVisit(EventMsg event);
+
+protected:
+ CObject* SearchToto();
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CInterface* m_interface;
+ CSound* m_sound;
+
+ bool m_bExist[MAXDTLINE];
+ float m_time[MAXDTLINE];
+ Math::Vector m_visitGoal[MAXDTLINE];
+ float m_visitDist[MAXDTLINE];
+ float m_visitHeight[MAXDTLINE];
+
+ bool m_bHide;
+ bool m_bEnable;
+ float m_delayFactor;
+};
+
+
diff --git a/src/ui/edit.cpp b/src/ui/edit.cpp
index 56e6dd8..2988798 100644
--- a/src/ui/edit.cpp
+++ b/src/ui/edit.cpp
@@ -1,3316 +1,3316 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// edit.cpp
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <windows.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "common/language.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "ui/scroll.h"
-#include "old/text.h"
-#include "ui/edit.h"
-
-
-const float MARGX = (5.0f/640.0f);
-const float MARGY = (5.0f/480.0f);
-const float MARGYS = (4.0f/480.0f);
-const float MARGY1 = (1.0f/480.0f);
-const float DELAY_DBCLICK = 0.3f; // time limit for double-click
-const float DELAY_SCROLL = 0.1f; // time limit for scroll
-const float BIG_FONT = 1.6f; // expansion for \b;
-
-
-
-
-// Indicates whether a character is a space.
-
-bool IsSpace(int character)
-{
- return ( character == ' ' ||
- character == '\t' ||
- character == '\n' );
-}
-
-// Indicates whether a character is part of a word.
-
-bool IsWord(int character)
-{
- char c;
-
- c = tolower(RetNoAccent(character));
-
- return ( (c >= 'a' && c <= 'z') ||
- (c >= '0' && c <= '9') ||
- c == '_' );
-}
-
-// Indicates whether a character is a word separator.
-
-bool IsSep(int character)
-{
- if ( IsSpace(character) ) return false;
- return !IsWord(character);
-}
-
-
-
-// Object's constructor.
-
-CEdit::CEdit(CInstanceManager* iMan) : CControl(iMan)
-{
- Math::Point pos;
- int i;
-
- m_maxChar = 100;
- m_text = (char*)malloc(sizeof(char)*(m_maxChar+1));
- m_format = 0;
- m_len = 0;
-
- m_fontType = FONT_COURIER;
- m_scroll = 0;
- m_bEdit = true;
- m_bHilite = true;
- m_bInsideScroll = true;
- m_bCapture = false;
- m_bDisplaySpec = false;
- m_bSoluce = false;
- m_bGeneric = false;
- m_bAutoIndent = false;
- m_cursor1 = 0;
- m_cursor2 = 0;
- m_column = 0;
- m_imageTotal = 0;
-
- HyperFlush();
-
- for ( i=0 ; i<EDITUNDOMAX ; i++ )
- {
- m_undo[i].text = 0;
- }
- m_bUndoForce = true;
- m_undoOper = OPERUNDO_SPEC;
-}
-
-// Object's destructor.
-
-CEdit::~CEdit()
-{
- int i;
-
- FreeImage();
-
- for ( i=0 ; i<EDITUNDOMAX ; i++ )
- {
- delete m_undo[i].text;
- }
-
- delete m_text;
- delete m_format;
- delete m_scroll;
-}
-
-
-// Creates a new editable line.
-
-bool CEdit::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CScroll* pc;
- Math::Point start, end;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
- CControl::Create(pos, dim, icon, eventMsg);
-
- m_len = 0;
- m_lineFirst = 0;
- m_time = 0.0f;
- m_timeBlink = 0.0f;
- m_timeLastClick = 0.0f;
- m_timeLastScroll = 0.0f;
-
- m_bMulti = false;
- MoveAdjust();
- if ( m_lineVisible <= 1 )
- {
- m_bMulti = false;
- }
- else
- {
- m_bMulti = true;
- MoveAdjust(); // readjusts multi-line mode
- m_scroll = new CScroll(m_iMan);
- pc = (CScroll*)m_scroll;
- pc->Create(pos, dim, -1, EVENT_NULL);
- MoveAdjust();
- }
-
- return true;
-}
-
-
-void CEdit::SetPos(Math::Point pos)
-{
- CControl::SetPos(pos);
- MoveAdjust();
-}
-
-void CEdit::SetDim(Math::Point dim)
-{
- CControl::SetDim(dim);
- MoveAdjust();
-}
-
-void CEdit::MoveAdjust()
-{
- Math::Point pos, dim;
- float height;
-
- m_lineDescent = m_engine->RetText()->RetDescent(m_fontSize, m_fontType);
- m_lineAscent = m_engine->RetText()->RetAscent(m_fontSize, m_fontType);
- m_lineHeight = m_engine->RetText()->RetHeight(m_fontSize, m_fontType);
-
- height = m_dim.y-(m_bMulti?MARGY*2.0f:MARGY1);
- m_lineVisible = (int)(height/m_lineHeight);
-
- if ( m_scroll != 0 )
- {
- if ( m_bInsideScroll )
- {
- pos.x = m_pos.x+m_dim.x-MARGX-SCROLL_WIDTH;
- pos.y = m_pos.y+MARGYS;
- dim.x = SCROLL_WIDTH;
- dim.y = m_dim.y-MARGYS*2.0f;
- }
- else
- {
- pos.x = m_pos.x+m_dim.x-SCROLL_WIDTH;
- pos.y = m_pos.y;
- dim.x = SCROLL_WIDTH;
- dim.y = m_dim.y;
- }
- m_scroll->SetPos(pos);
- m_scroll->SetDim(dim);
- }
-
- Justif();
-
- if ( m_lineFirst > m_lineTotal-m_lineVisible )
- {
- m_lineFirst = m_lineTotal-m_lineVisible;
- if ( m_lineFirst < 0 ) m_lineFirst = 0;
- }
-
- pos.x = m_pos.x+m_dim.x-(m_bMulti?SCROLL_WIDTH:0.0f);
- pos.y = m_pos.y;
- GlintCreate(pos, false, false);
-}
-
-
-// Management of an event.
-
-bool CEdit::EventProcess(const Event &event)
-{
- bool bShift, bControl;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return true;
-
- if ( event.event == EVENT_KEYDOWN &&
- event.param == VK_WHEELUP &&
- Detect(event.pos) )
- {
- Scroll(m_lineFirst-3, true);
- return true;
- }
- if ( event.event == EVENT_KEYDOWN &&
- event.param == VK_WHEELDOWN &&
- Detect(event.pos) )
- {
- Scroll(m_lineFirst+3, true);
- return true;
- }
-
- CControl::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- m_time += event.rTime;
- m_timeBlink += event.rTime;
- }
-
- if ( event.event == EVENT_MOUSEMOVE )
- {
- if ( Detect(event.pos) &&
- event.pos.x < m_pos.x+m_dim.x-(m_bMulti?MARGX+SCROLL_WIDTH:0.0f) )
- {
- if ( m_bEdit )
- {
- m_engine->SetMouseType(D3DMOUSEEDIT);
- }
- else
- {
- if ( IsLinkPos(event.pos) )
- {
- m_engine->SetMouseType(D3DMOUSEHAND);
- }
- else
- {
- m_engine->SetMouseType(D3DMOUSENORM);
- }
- }
- }
- }
-
- if ( m_scroll != 0 && !m_bGeneric )
- {
- m_scroll->EventProcess(event);
-
- if ( event.event == m_scroll->RetEventMsg() )
- {
- Scroll();
- return true;
- }
- }
-
- if ( event.event == EVENT_KEYDOWN && m_bFocus )
- {
- bShift = (event.keyState&KS_SHIFT);
- bControl = (event.keyState&KS_CONTROL);
-
- if ( (event.param == 'X' && !bShift && bControl) ||
- (event.param == VK_DELETE && bShift && !bControl) )
- {
- Cut();
- return true;
- }
- if ( (event.param == 'C' && !bShift && bControl) ||
- (event.param == VK_INSERT && !bShift && bControl) )
- {
- Copy();
- return true;
- }
- if ( (event.param == 'V' && !bShift && bControl) ||
- (event.param == VK_INSERT && bShift && !bControl) )
- {
- Paste();
- return true;
- }
-
- if ( event.param == 'A' && !bShift && bControl )
- {
- SetCursor(999999, 0);
- return true;
- }
-
- if ( event.param == 'O' && !bShift && bControl )
- {
- Event newEvent;
- m_event->MakeEvent(newEvent, EVENT_STUDIO_OPEN);
- m_event->AddEvent(newEvent);
- }
- if ( event.param == 'S' && !bShift && bControl )
- {
- Event newEvent;
- m_event->MakeEvent(newEvent, EVENT_STUDIO_SAVE);
- m_event->AddEvent(newEvent);
- }
-
- if ( event.param == 'Z' && !bShift && bControl )
- {
- Undo();
- return true;
- }
-
- if ( event.param == 'U' && !bShift && bControl )
- {
- if ( MinMaj(false) ) return true;
- }
- if ( event.param == 'U' && bShift && bControl )
- {
- if ( MinMaj(true) ) return true;
- }
-
- if ( event.param == VK_TAB && !bShift && !bControl && !m_bAutoIndent )
- {
- if ( Shift(false) ) return true;
- }
- if ( event.param == VK_TAB && bShift && !bControl && !m_bAutoIndent )
- {
- if ( Shift(true) ) return true;
- }
-
- if ( m_bEdit )
- {
- if ( event.param == VK_LEFT )
- {
- MoveChar(-1, bControl, bShift);
- return true;
- }
- if ( event.param == VK_RIGHT )
- {
- MoveChar(1, bControl, bShift);
- return true;
- }
- if ( event.param == VK_UP )
- {
- MoveLine(-1, bControl, bShift);
- return true;
- }
- if ( event.param == VK_DOWN )
- {
- MoveLine(1, bControl, bShift);
- return true;
- }
-
- if ( event.param == VK_PRIOR ) // PageUp ?
- {
- MoveLine(-(m_lineVisible-1), bControl, bShift);
- return true;
- }
- if ( event.param == VK_NEXT ) // PageDown ?
- {
- MoveLine(m_lineVisible-1, bControl, bShift);
- return true;
- }
- }
- else
- {
- if ( event.param == VK_LEFT ||
- event.param == VK_UP )
- {
- Scroll(m_lineFirst-1, true);
- return true;
- }
- if ( event.param == VK_RIGHT ||
- event.param == VK_DOWN )
- {
- Scroll(m_lineFirst+1, true);
- return true;
- }
-
- if ( event.param == VK_PRIOR ) // PageUp ?
- {
- Scroll(m_lineFirst-(m_lineVisible-1), true);
- return true;
- }
- if ( event.param == VK_NEXT ) // PageDown ?
- {
- Scroll(m_lineFirst+(m_lineVisible-1), true);
- return true;
- }
- }
-
- if ( event.param == VK_HOME )
- {
- MoveHome(bControl, bShift);
- return true;
- }
- if ( event.param == VK_END )
- {
- MoveEnd(bControl, bShift);
- return true;
- }
-
- if ( event.param == VK_BACK ) // backspace ( <- ) ?
- {
- Delete(-1);
- SendModifEvent();
- return true;
- }
- if ( event.param == VK_DELETE )
- {
- Delete(1);
- SendModifEvent();
- return true;
- }
-
- if ( event.param == VK_RETURN )
- {
- Insert('\n');
- SendModifEvent();
- return true;
- }
- if ( event.param == VK_TAB )
- {
- Insert('\t');
- SendModifEvent();
- return true;
- }
- }
-
- if ( event.event == EVENT_CHAR && m_bFocus )
- {
- if ( event.param >= ' ' && event.param <= 255 )
- {
- Insert((char)event.param);
- SendModifEvent();
- return true;
- }
- }
-
- if ( event.event == EVENT_FOCUS )
- {
- if ( event.param == m_eventMsg )
- {
- m_bFocus = true;
- }
- else
- {
- m_bFocus = false;
- }
- }
-
- if ( event.event == EVENT_LBUTTONDOWN )
- {
- m_mouseFirstPos = event.pos;
- m_mouseLastPos = event.pos;
- if ( Detect(event.pos) )
- {
- if ( event.pos.x < m_pos.x+m_dim.x-(m_bMulti?MARGX+SCROLL_WIDTH:0.0f) )
- {
- MouseClick(event.pos);
- if ( m_bEdit || m_bHilite ) m_bCapture = true;
- }
- m_bFocus = true;
- }
- else
- {
- m_bFocus = false;
- }
- }
-
- if ( event.event == EVENT_MOUSEMOVE && m_bCapture )
- {
- m_mouseLastPos = event.pos;
- MouseMove(event.pos);
- }
-
- if ( event.event == EVENT_FRAME && m_bCapture )
- {
- MouseMove(m_mouseLastPos);
- }
-
- if ( event.event == EVENT_LBUTTONUP )
- {
- if ( Detect(event.pos) )
- {
- if ( event.pos.x < m_pos.x+m_dim.x-(m_bMulti?MARGX+SCROLL_WIDTH:0.0f) )
- {
- MouseRelease(m_mouseFirstPos);
- }
- }
- if ( m_bCapture )
- {
- if ( m_timeLastClick+DELAY_DBCLICK > m_time ) // double-click ?
- {
- MouseDoubleClick(event.pos);
- }
- m_timeLastClick = m_time;
- m_bCapture = false;
- }
- }
-
- return true;
-}
-
-
-// Sends an event to indicate that the text was modified.
-
-void CEdit::SendModifEvent()
-{
- Event newEvent;
-
- m_event->MakeEvent(newEvent, m_eventMsg);
- m_event->AddEvent(newEvent);
-}
-
-
-// Detects whether the mouse is over a hyperlink character.
-
-bool CEdit::IsLinkPos(Math::Point pos)
-{
- int i;
-
- if ( m_format == 0 ) return false;
-
- i = MouseDetect(pos);
- if ( i == -1 ) return false;
- if ( i >= m_len ) return false;
-
- if ( (m_format[i]&COLOR_MASK) == COLOR_LINK ) return true;
- return false;
-}
-
-
-// Positions the cursor after a double click.
-
-void CEdit::MouseDoubleClick(Math::Point mouse)
-{
- int i, character;
-
- if ( m_bMulti ) // Multi-line?
- {
- i = MouseDetect(mouse);
- if ( i == -1 ) return;
-
- while ( i > 0 )
- {
- character = (unsigned char)m_text[i-1];
- if ( !IsWord(character) ) break;
- i --;
- }
- m_cursor2 = i;
-
- while ( i < m_len )
- {
- character = (unsigned char)m_text[i];
- if ( !IsWord(character) ) break;
- i ++;
- }
- m_cursor1 = i;
- }
- else // single-line?
- {
- m_cursor2 = 0;
- m_cursor1 = m_len; // selects all
- }
-
- m_bUndoForce = true;
-
- Justif();
- ColumnFix();
-}
-
-// Positions the cursor when clicked.
-
-void CEdit::MouseClick(Math::Point mouse)
-{
- int i;
-
- i = MouseDetect(mouse);
- if ( i == -1 ) return;
-
- if ( m_bEdit || m_bHilite )
- {
- m_cursor1 = i;
- m_cursor2 = i;
- m_bUndoForce = true;
- m_timeBlink = 0.0f; // lights the cursor immediately
- ColumnFix();
- }
-}
-
-// Positions the cursor when clicked released.
-
-void CEdit::MouseRelease(Math::Point mouse)
-{
- int i, j, rank;
-
- i = MouseDetect(mouse);
- if ( i == -1 ) return;
-
- if ( !m_bEdit )
- {
- if ( m_format != 0 && i < m_len && m_cursor1 == m_cursor2 &&
- (m_format[i]&COLOR_MASK) == COLOR_LINK )
- {
- rank = -1;
- for ( j=0 ; j<=i ; j++ )
- {
- if ( (j == 0 || (m_format[j-1]&COLOR_MASK) != COLOR_LINK) &&
- (m_format[j+0]&COLOR_MASK) == COLOR_LINK )
- {
- rank ++;
- }
- }
- HyperJump(m_link[rank].name, m_link[rank].marker);
- }
- }
-}
-
-// Positions the cursor after movement.
-
-void CEdit::MouseMove(Math::Point mouse)
-{
- int i;
-
- if ( m_bMulti &&
- m_timeLastScroll+DELAY_SCROLL <= m_time )
- {
- if ( mouse.y > m_pos.y+m_dim.y ) // above?
- {
- Scroll(m_lineFirst-1, false);
- mouse.y = m_pos.y+m_dim.y-MARGY-m_lineHeight/2.0f;
- }
- if ( mouse.y < m_pos.y ) // lower?
- {
- Scroll(m_lineFirst+1, false);
- mouse.y = m_pos.y+m_dim.y-MARGY-m_lineVisible*m_lineHeight+m_lineHeight/2.0f;
- }
- m_timeLastScroll = m_time;
- }
-
- i = MouseDetect(mouse);
- if ( i != -1 )
- {
- m_cursor1 = i;
- m_bUndoForce = true;
- m_timeBlink = 0.0f; // lights the cursor immediately
- ColumnFix();
- }
-}
-
-// Positions the cursor when clicked.
-
-int CEdit::MouseDetect(Math::Point mouse)
-{
- Math::Point pos;
- float indentLength, offset, size;
- int i, len, c;
- bool bTitle;
-
- if ( m_bAutoIndent )
- {
- indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType)
- * m_engine->RetEditIndentValue();
- }
-
- pos.y = m_pos.y+m_dim.y-m_lineHeight-(m_bMulti?MARGY:MARGY1);
- for ( i=m_lineFirst ; i<m_lineTotal ; i++ )
- {
- bTitle = ( m_format != 0 && (m_format[m_lineOffset[i]]&TITLE_MASK) == TITLE_BIG );
-
- if ( i >= m_lineFirst+m_lineVisible ) break;
-
- pos.x = m_pos.x+(10.0f/640.0f);
- if ( m_bAutoIndent )
- {
- pos.x += indentLength*m_lineIndent[i];
- }
- offset = mouse.x-pos.x;
-
- if ( bTitle ) pos.y -= m_lineHeight;
-
- if ( mouse.y > pos.y )
- {
- len = m_lineOffset[i+1] - m_lineOffset[i];
-
- if ( m_format == 0 )
- {
- c = m_engine->RetText()->Detect(m_text+m_lineOffset[i],
- len, offset, m_fontSize,
- m_fontStretch, m_fontType);
- }
- else
- {
- size = m_fontSize;
- if ( bTitle ) size *= BIG_FONT;
-
- c = m_engine->RetText()->Detect(m_text+m_lineOffset[i],
- m_format+m_lineOffset[i],
- len, offset, size,
- m_fontStretch);
- }
- return m_lineOffset[i]+c;
- }
-
- if ( bTitle ) i ++;
- pos.y -= m_lineHeight;
- }
- return -1;
-}
-
-
-// Clears all history.
-
-void CEdit::HyperFlush()
-{
- m_historyTotal = 0;
- m_historyCurrent = -1;
-}
-
-// Indicates which is the home page.
-
-void CEdit::HyperHome(char *filename)
-{
- HyperFlush();
- HyperAdd(filename, 0);
-}
-
-// Performs a hyper jump through a link.
-
-void CEdit::HyperJump(char *name, char *marker)
-{
- char filename[100];
- char sMarker[100];
- int i, line, pos;
-
- if ( m_historyCurrent >= 0 )
- {
- m_history[m_historyCurrent].firstLine = m_lineFirst;
- }
-
- strcpy(sMarker, marker);
-
-//? sprintf(filename, "help\\%s.txt", name);
- if ( name[0] == '%' )
- {
- UserDir(filename, name, "");
- strcat(filename, ".txt");
- }
- else
- {
- sprintf(filename, "help\\%s.txt", name);
- }
- if ( ReadText(filename) )
- {
- Justif();
-
- line = 0;
- for ( i=0 ; i<m_markerTotal ; i++ )
- {
- if ( strcmp(sMarker, m_marker[i].name) == 0 )
- {
- pos = m_marker[i].pos;
- for ( i=0 ; i<m_lineTotal ; i++ )
- {
- if ( pos >= m_lineOffset[i] )
- {
- line = i;
- }
- }
- break;
- }
- }
-
- SetFirstLine(line);
- HyperAdd(filename, line);
- }
-}
-
-// Adds text to the history of visited.
-
-bool CEdit::HyperAdd(char *filename, int firstLine)
-{
- if ( m_historyCurrent >= EDITHISTORYMAX-1 ) return false;
-
- m_historyCurrent ++;
- strcpy(m_history[m_historyCurrent].filename, filename);
- m_history[m_historyCurrent].firstLine = firstLine;
-
- m_historyTotal = m_historyCurrent+1;
- return true;
-}
-
-// Indicates whether a button EVENT_HYPER_ * is active or not.
-
-bool CEdit::HyperTest(EventMsg event)
-{
- if ( event == EVENT_HYPER_HOME )
- {
- return ( m_historyCurrent > 0 );
- }
-
- if ( event == EVENT_HYPER_PREV )
- {
- return ( m_historyCurrent > 0 );
- }
-
- if ( event == EVENT_HYPER_NEXT )
- {
- return ( m_historyCurrent < m_historyTotal-1 );
- }
-
- return false;
-}
-
-// Performs the action corresponding to a button EVENT_HYPER_ *.
-
-bool CEdit::HyperGo(EventMsg event)
-{
- if ( !HyperTest(event) ) return false;
-
- m_history[m_historyCurrent].firstLine = m_lineFirst;
-
- if ( event == EVENT_HYPER_HOME )
- {
- m_historyCurrent = 0;
- }
-
- if ( event == EVENT_HYPER_PREV )
- {
- m_historyCurrent --;
- }
-
- if ( event == EVENT_HYPER_NEXT )
- {
- m_historyCurrent ++;
- }
-
- ReadText(m_history[m_historyCurrent].filename);
- Justif();
- SetFirstLine(m_history[m_historyCurrent].firstLine);
- return true;
-}
-
-
-// Draw the editable line.
-
-void CEdit::Draw()
-{
- Math::Point pos, ppos, dim, start, end;
- float size, indentLength;
- int i, j, beg, len, c1, c2, o1, o2, eol, iIndex, line;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return;
-
- if ( m_state & STATE_SHADOW )
- {
- DrawShadow(m_pos, m_dim);
- }
-
- pos.x = m_pos.x;
- pos.y = m_pos.y;
- dim.x = m_dim.x;
- if ( !m_bInsideScroll ) dim.x -= m_bMulti?SCROLL_WIDTH:0.0f;
- dim.y = m_dim.y;
- DrawBack(pos, dim); // background
-
- // Displays all lines.
- c1 = m_cursor1;
- c2 = m_cursor2;
- if ( c1 > c2 ) Math::Swap(c1, c2); // always c1 <= c2
-
- if ( m_bInsideScroll )
- {
- dim.x -= m_bMulti?SCROLL_WIDTH:0.0f + (1.0f/640.0f);
- }
-
- if ( m_bAutoIndent )
- {
- indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType)
- * m_engine->RetEditIndentValue();
- }
-
- pos.y = m_pos.y+m_dim.y-m_lineHeight-(m_bMulti?MARGY:MARGY1);
- for ( i=m_lineFirst ; i<m_lineTotal ; i++ )
- {
- if ( i == m_lineFirst && i < m_lineTotal-1 &&
- m_lineOffset[i] == m_lineOffset[i+1] )
- {
- pos.y -= m_lineHeight; // Double jump line \b;
- i ++;
- }
-
- if ( i >= m_lineFirst+m_lineVisible ) break;
-
- pos.x = m_pos.x+(10.0f/640.0f);
- if ( m_bAutoIndent )
- {
- for ( j=0 ; j<m_lineIndent[i] ; j++ )
- {
- char s = '\t'; // line | dotted
- m_engine->RetText()->DrawText(&s, 1, pos, 1.0f, 1, m_fontSize, m_fontStretch, m_fontType, 0);
- pos.x += indentLength;
- }
- }
-
- beg = m_lineOffset[i];
- len = m_lineOffset[i+1] - m_lineOffset[i];
-
- ppos = pos;
- size = m_fontSize;
-
- // Headline \b;?
- if ( beg+len < m_len && m_format != 0 &&
- (m_format[beg]&TITLE_MASK) == TITLE_BIG )
- {
- start.x = ppos.x-MARGX;
- end.x = dim.x-MARGX*2.0f;
- start.y = ppos.y-(m_bMulti?0.0f:MARGY1)-m_lineHeight*(BIG_FONT-1.0f);
- end.y = m_lineHeight*BIG_FONT;
- DrawPart(start, end, 2); // blue gradient background ->
-
- size *= BIG_FONT;
- ppos.y -= m_lineHeight*(BIG_FONT-1.0f);
- }
-
- // As \t;?
- if ( beg+len < m_len && m_format != 0 &&
- (m_format[beg]&TITLE_MASK) == TITLE_NORM )
- {
- start.x = ppos.x-MARGX;
- end.x = dim.x-MARGX*2.0f;
- start.y = ppos.y-(m_bMulti?0.0f:MARGY1);
- end.y = m_lineHeight;
- DrawPart(start, end, 2); // blue gradient background ->
- }
-
- // Subtitle \s;?
- if ( beg+len < m_len && m_format != 0 &&
- (m_format[beg]&TITLE_MASK) == TITLE_LITTLE )
- {
- start.x = ppos.x-MARGX;
- end.x = dim.x-MARGX*2.0f;
- start.y = ppos.y-(m_bMulti?0.0f:MARGY1);
- end.y = m_lineHeight;
- DrawPart(start, end, 3); // yellow background gradient ->
- }
-
- // Table \tab;?
- if ( beg+len < m_len && m_format != 0 &&
- (m_format[beg]&COLOR_MASK) == COLOR_TABLE )
- {
- start.x = ppos.x-MARGX;
- end.x = dim.x-MARGX*2.0f;
- start.y = ppos.y-(m_bMulti?0.0f:MARGY1);
- end.y = m_lineHeight;
- DrawPart(start, end, 11); // fond orange d�grad� ->
- }
-
- // Image \image; ?
- if ( beg+len < m_len && m_format != 0 &&
- (m_format[beg]&IMAGE_MASK) != 0 )
- {
- line = 1;
- while ( true ) // includes the image slices
- {
- if ( i+line >= m_lineTotal ||
- i+line >= m_lineFirst+m_lineVisible ||
- (m_format[beg+line]&IMAGE_MASK) == 0 ) break;
- line ++;
- }
-
- iIndex = m_text[beg]; // character = index in m_image
- pos.y -= m_lineHeight*(line-1);
- DrawImage(pos, m_image[iIndex].name,
- m_image[iIndex].width*(m_fontSize/SMALLFONT),
- m_image[iIndex].offset, m_image[iIndex].height*line, line);
- pos.y -= m_lineHeight;
- i += line-1;
- continue;
- }
-
- if ( ((m_bEdit && m_bFocus && m_bHilite) ||
- (!m_bEdit && m_bHilite) ) &&
- c1 != c2 && beg <= c2 && beg+len >= c1 ) // selected area?
- {
- o1 = c1; if ( o1 < beg ) o1 = beg;
- o2 = c2; if ( o2 > beg+len ) o2 = beg+len;
-
- if ( m_format == 0 )
- {
- start.x = ppos.x+m_engine->RetText()->RetStringWidth(m_text+beg, o1-beg, size, m_fontStretch, m_fontType);
- end.x = m_engine->RetText()->RetStringWidth(m_text+o1, o2-o1, size, m_fontStretch, m_fontType);
- }
- else
- {
- start.x = ppos.x+m_engine->RetText()->RetStringWidth(m_text+beg, m_format+beg, o1-beg, size, m_fontStretch);
- end.x = m_engine->RetText()->RetStringWidth(m_text+o1, m_format+o1, o2-o1, size, m_fontStretch);
- }
-
- start.y = ppos.y-(m_bMulti?0.0f:MARGY1);
- end.y = m_lineHeight;
- if ( m_format != 0 && (m_format[beg]&TITLE_MASK) == TITLE_BIG ) end.y *= BIG_FONT;
- DrawPart(start, end, 1); // plain yellow background
- }
-
- eol = 16; // >
- if ( len > 0 && m_text[beg+len-1] == '\n' )
- {
- len --; // does not display the '\ n'
- eol = 0; // nothing
- }
- if ( beg+len >= m_len )
- {
- eol = 2; // square (eot)
- }
- if ( !m_bMulti || !m_bDisplaySpec ) eol = 0;
- if ( m_format == 0 )
- {
- m_engine->RetText()->DrawText(m_text+beg, len, ppos, m_dim.x, 1, size, m_fontStretch, m_fontType, eol);
- }
- else
- {
- m_engine->RetText()->DrawText(m_text+beg, m_format+beg, len, ppos, m_dim.x, 1, size, m_fontStretch, eol);
- }
-
- pos.y -= m_lineHeight;
-
- if ( i < m_lineTotal-2 && m_lineOffset[i+1] == m_lineOffset[i+2] )
- {
- pos.y -= m_lineHeight; // double jump line \b;
- i ++;
- }
- }
-
- // Shows the cursor.
- if ( (m_bEdit && m_bFocus && m_bHilite && Math::Mod(m_timeBlink, 1.0f) <= 0.5f) ) // it blinks
- {
- pos.y = m_pos.y+m_dim.y-m_lineHeight-(m_bMulti?MARGY:MARGY1*2.0f);
- for ( i=m_lineFirst ; i<m_lineTotal ; i++ )
- {
- if ( i == m_lineTotal-1 || m_cursor1 < m_lineOffset[i+1] )
- {
- pos.x = m_pos.x+(10.0f/640.0f);
- if ( m_bAutoIndent )
- {
- pos.x += indentLength*m_lineIndent[i];
- }
-
- len = m_cursor1 - m_lineOffset[i];
-
- if ( m_format == 0 )
- {
- m_engine->RetText()->DimText(m_text+m_lineOffset[i], len,
- pos, 1, size,
- m_fontStretch, m_fontType,
- start, end);
- }
- else
- {
- m_engine->RetText()->DimText(m_text+m_lineOffset[i],
- m_format+m_lineOffset[i],
- len, pos, 1, size,
- m_fontStretch,
- start, end);
- }
-
- pos.x = end.x;
- break;
- }
- pos.y -= m_lineHeight;
- }
- pos.x -= 1.0f/640.0f;
- dim.x = 2.0f/640.0f;
- dim.y = m_lineHeight;
- DrawPart(pos, dim, 0); // red
- }
-
- if ( m_scroll != 0 && !m_bGeneric )
- {
- m_scroll->Draw();
- }
-}
-
-// Draw an image part.
-
-void CEdit::DrawImage(Math::Point pos, char *name, float width,
- float offset, float height, int nbLine)
-{
- Math::Point uv1, uv2, dim;
- float dp;
- char filename[100];
-
-//? sprintf(filename, "diagram\\%s.bmp", name);
- UserDir(filename, name, "diagram");
- strcat(filename, ".bmp");
-
- m_engine->SetTexture(filename);
- m_engine->SetState(D3DSTATENORMAL);
-
- uv1.x = 0.0f;
- uv2.x = 1.0f;
- uv1.y = offset;
- uv2.y = offset+height;
-
- dp = 0.5f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- dim.x = width;
- dim.y = m_lineHeight*nbLine;
- DrawIcon(pos, dim, uv1, uv2);
-}
-
-// Draw the background.
-
-void CEdit::DrawBack(Math::Point pos, Math::Point dim)
-{
- Math::Point uv1,uv2, corner;
- float dp;
-
- if ( m_bGeneric ) return;
-
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
-
- if ( m_bMulti )
- {
- uv1.x = 128.0f/256.0f; // light blue
- uv1.y = 64.0f/256.0f;
- uv2.x = 160.0f/256.0f;
- uv2.y = 96.0f/256.0f;
- }
- else
- {
- uv1.x = 160.0f/256.0f; // medium blue
- uv1.y = 192.0f/256.0f;
- uv2.x = 192.0f/256.0f;
- uv2.y = 224.0f/256.0f;
- }
- if ( m_icon == 1 )
- {
- uv1.x = 192.0f/256.0f; // orange
- uv1.y = 96.0f/256.0f;
- uv2.x = 224.0f/256.0f;
- uv2.y = 128.0f/256.0f;
- }
-
- dp = 0.5f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- if ( m_bMulti )
- {
- corner.x = 10.0f/640.0f;
- corner.y = 10.0f/480.0f;
- DrawIcon(pos, dim, uv1, uv2, corner, 8.0f/256.0f);
- }
- else
- {
- DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f);
- }
-}
-
-// Draws an icon background.
-
-void CEdit::DrawPart(Math::Point pos, Math::Point dim, int icon)
-{
- Math::Point uv1, uv2;
- float dp;
-
-#if _POLISH
- m_engine->SetTexture("textp.tga");
-#else
- m_engine->SetTexture("text.tga");
-#endif
- m_engine->SetState(D3DSTATENORMAL);
-
- uv1.x = (16.0f/256.0f)*(icon%16);
- uv1.y = (240.0f/256.0f);
- uv2.x = (16.0f/256.0f)+uv1.x;
- uv2.y = (16.0f/256.0f)+uv1.y;
-
- dp = 0.5f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- DrawIcon(pos, dim, uv1, uv2);
-}
-
-
-// Give the text to edit.
-
-void CEdit::SetText(char *text, bool bNew)
-{
- int i, j, font;
- bool bBOL;
-
- if ( !bNew ) UndoMemorize(OPERUNDO_SPEC);
-
- m_len = strlen(text);
- if ( m_len > m_maxChar ) m_len = m_maxChar;
-
- if ( m_format == 0 )
- {
- if ( m_bAutoIndent )
- {
- j = 0;
- bBOL = true;
- for ( i=0 ; i<m_len ; i++ )
- {
- if ( text[i] == '\t' )
- {
- if ( !bBOL ) m_text[j++] = ' ';
- continue; // removes tabs
- }
- bBOL = ( text[i] == '\n' );
-
- m_text[j++] = text[i];
- }
- m_len = j;
- }
- else
- {
- strncpy(m_text, text, m_len);
- }
- }
- else
- {
- font = m_fontType;
- j = 0;
- bBOL = true;
- for ( i=0 ; i<m_len ; i++ )
- {
- if ( m_bAutoIndent )
- {
- if ( text[i] == '\t' )
- {
- if ( !bBOL )
- {
- m_text[j] = ' ';
- m_format[j] = font;
- j ++;
- }
- continue; // removes tabs
- }
- bBOL = ( text[i] == '\n' );
- }
-
- if ( text[i] == '\\' && text[i+2] == ';' )
- {
- if ( text[i+1] == 'n' ) // normal ?
- {
- font &= ~FONT_MASK;
- font |= FONT_COLOBOT;
- i += 2;
- }
- else if ( text[i+1] == 'c' ) // cbot ?
- {
- font &= ~FONT_MASK;
- font |= FONT_COURIER;
- i += 2;
- }
- else if ( text[i+1] == 'b' ) // big title ?
- {
- font &= ~TITLE_MASK;
- font |= TITLE_BIG;
- i += 2;
- }
- else if ( text[i+1] == 't' ) // title ?
- {
- font &= ~TITLE_MASK;
- font |= TITLE_NORM;
- i += 2;
- }
- else if ( text[i+1] == 's' ) // subtitle ?
- {
- font &= ~TITLE_MASK;
- font |= TITLE_LITTLE;
- i += 2;
- }
- }
- else
- {
- m_text[j] = text[i];
- m_format[j] = font;
- j ++;
-
- font &= ~TITLE_MASK; // reset title
- }
- }
- m_len = j;
- }
-
- if ( bNew ) UndoFlush();
-
- m_cursor1 = 0;
- m_cursor2 = 0; // cursor to the beginning
- Justif();
- ColumnFix();
-}
-
-// Returns a pointer to the edited text.
-
-char* CEdit::RetText()
-{
- m_text[m_len] = 0;
- return m_text;
-}
-
-// Returns the edited text.
-
-void CEdit::GetText(char *buffer, int max)
-{
- if ( m_len < max ) max = m_len;
- if ( m_len > max ) max = max-1;
-
- strncpy(buffer, m_text, max);
- buffer[max] = 0;
-}
-
-// Returns the length of the text.
-
-int CEdit::RetTextLength()
-{
- return m_len;
-}
-
-
-
-// Returns a name in a command.
-// \x nom1 nom2 nom3;
-
-void GetNameParam(char *cmd, int rank, char *buffer)
-{
- int i;
-
- for ( i=0 ; i<rank ; i++ )
- {
- while ( *cmd != ' ' && *cmd != ';' )
- {
- cmd ++;
- }
- if ( *cmd != ';' ) cmd ++;
- }
-
- while ( *cmd != ' ' && *cmd != ';' )
- {
- *buffer++ = *cmd++;
- }
- *buffer = 0;
-}
-
-// Returns a number of a command.
-// \x nom n1 n2;
-
-int RetValueParam(char *cmd, int rank)
-{
- int n, i;
-
- for ( i=0 ; i<rank ; i++ )
- {
- while ( *cmd != ' ' && *cmd != ';' )
- {
- cmd ++;
- }
- if ( *cmd != ';' ) cmd ++;
- }
-
- sscanf(cmd, "%d", &n);
- return n;
-}
-
-// Frees all images.
-
-void CEdit::FreeImage()
-{
- char filename[100];
- int i;
-
- for ( i=0 ; i<m_imageTotal ; i++ )
- {
-//? sprintf(filename, "diagram\\%s.bmp", m_image[i].name);
- UserDir(filename, m_image[i].name, "diagram");
- strcat(filename, ".bmp");
- m_engine->FreeTexture(filename);
- }
-}
-
-// Reads the texture of an image.
-
-void CEdit::LoadImage(char *name)
-{
- char filename[100];
-
-//? sprintf(filename, "diagram\\%s.bmp", name);
- UserDir(filename, name, "diagram");
- strcat(filename, ".bmp");
- m_engine->LoadTexture(filename);
-}
-
-// Read from a text file.
-
-bool CEdit::ReadText(char *filename, int addSize)
-{
- FILE *file = NULL;
- char *buffer;
- int len, i, j, n, font, iIndex, iLines, iCount, iLink, res;
- char iName[50];
- char text[50];
- float iWidth;
- KeyRank key;
- bool bInSoluce, bBOL;
-
- if ( filename[0] == 0 ) return false;
- file = fopen(filename, "rb");
- if ( file == NULL ) return false;
-
- fseek(file, 0, SEEK_END);
- len = ftell(file);
- fseek(file, 0, SEEK_SET);
-
- m_maxChar = len+addSize+100;
- m_len = len;
- m_cursor1 = 0;
- m_cursor2 = 0;
-
- FreeImage();
- delete m_text;
- m_text = (char*)malloc(sizeof(char)*(m_maxChar+1));
- buffer = (char*)malloc(sizeof(char)*(m_maxChar+1));
- fread(buffer, 1, len, file);
-
- if ( m_format != 0 )
- {
- delete m_format;
- m_format = (char*)malloc(sizeof(char)*m_maxChar);
- }
-
- fclose(file);
-
- bInSoluce = false;
- font = m_fontType;
- iIndex = 0;
- iLink = 0;
- m_imageTotal = 0;
- m_markerTotal = 0;
- i = j = 0;
- bBOL = true;
- while ( i < m_len )
- {
- if ( m_bAutoIndent )
- {
- if ( buffer[i] == '\t' )
- {
- if ( !bBOL )
- {
- m_text[j] = buffer[i];
- if ( m_format != 0 ) m_format[j] = font;
- j ++;
- }
- i ++;
- continue; // removes the tabs
- }
- bBOL = ( buffer[i] == '\n' || buffer[i] == '\r' );
- }
-
- if ( buffer[i] == '\r' ) // removes \ r
- {
- i ++;
- }
- else if ( m_format != 0 && buffer[i] == '\\' && buffer[i+2] == ';' )
- {
- if ( buffer[i+1] == 'n' ) // normal ?
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~FONT_MASK;
- font |= FONT_COLOBOT;
- }
- i += 3;
- }
- else if ( buffer[i+1] == 'c' ) // cbot ?
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~FONT_MASK;
- font |= FONT_COURIER;
- }
- i += 3;
- }
- else if ( buffer[i+1] == 'b' ) // big title ?
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~TITLE_MASK;
- font |= TITLE_BIG;
- }
- i += 3;
- }
- else if ( buffer[i+1] == 't' ) // title ?
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~TITLE_MASK;
- font |= TITLE_NORM;
- }
- i += 3;
- }
- else if ( buffer[i+1] == 's' ) // subtitle ?
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~TITLE_MASK;
- font |= TITLE_LITTLE;
- }
- i += 3;
- }
- else if ( buffer[i+1] == 'l' ) // link ?
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~COLOR_MASK;
- font |= COLOR_LINK;
- }
- i += 3;
- }
- else
- {
- i += 3;
- }
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \u marker name; ?
- buffer[i+1] == 'u' &&
- buffer[i+2] == ' ' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- if ( iLink < EDITLINKMAX )
- {
- GetNameParam(buffer+i+3, 0, m_link[iLink].name);
- GetNameParam(buffer+i+3, 1, m_link[iLink].marker);
- iLink ++;
- }
- font &= ~COLOR_MASK;
- }
- i += strchr(buffer+i, ';')-(buffer+i)+1;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \m marker; ?
- buffer[i+1] == 'm' &&
- buffer[i+2] == ' ' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- if ( m_markerTotal < EDITLINKMAX )
- {
- GetNameParam(buffer+i+3, 0, m_marker[m_markerTotal].name);
- m_marker[m_markerTotal].pos = j;
- m_markerTotal ++;
- }
- }
- i += strchr(buffer+i, ';')-(buffer+i)+1;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \image name lx ly; ?
- buffer[i+1] == 'i' &&
- buffer[i+2] == 'm' &&
- buffer[i+3] == 'a' &&
- buffer[i+4] == 'g' &&
- buffer[i+5] == 'e' &&
- buffer[i+6] == ' ' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
-#if _DEMO
- strcpy(iName, "demo");
-#else
- GetNameParam(buffer+i+7, 0, iName);
-#endif
-//? iWidth = m_lineHeight*RetValueParam(buffer+i+7, 1);
- iWidth = (float)RetValueParam(buffer+i+7, 1);
- iWidth *= m_engine->RetText()->RetHeight(SMALLFONT, FONT_COLOBOT);
- iLines = RetValueParam(buffer+i+7, 2);
- LoadImage(iName);
-
- // A part of image per line of text.
- for ( iCount=0 ; iCount<iLines ; iCount++ )
- {
- strcpy(m_image[iIndex].name, iName);
- m_image[iIndex].offset = (float)iCount/iLines;
- m_image[iIndex].height = 1.0f/iLines;
- m_image[iIndex].width = iWidth*0.75f;
-
- m_text[j] = (char)(iIndex++); // as an index into m_image
- m_format[j] = (unsigned char)IMAGE_MASK;
- j ++;
- }
- }
- i += strchr(buffer+i, ';')-(buffer+i)+1;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \button; ?
- buffer[i+1] == 'b' &&
- buffer[i+2] == 'u' &&
- buffer[i+3] == 't' &&
- buffer[i+4] == 't' &&
- buffer[i+5] == 'o' &&
- buffer[i+6] == 'n' &&
- buffer[i+7] == ' ' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- m_text[j] = RetValueParam(buffer+i+8, 0);
- m_format[j] = font|FONT_BUTTON;
- j ++;
- }
- i += strchr(buffer+i, ';')-(buffer+i)+1;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \token; ?
- buffer[i+1] == 't' &&
- buffer[i+2] == 'o' &&
- buffer[i+3] == 'k' &&
- buffer[i+4] == 'e' &&
- buffer[i+5] == 'n' &&
- buffer[i+6] == ';' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~COLOR_MASK;
- font |= COLOR_TOKEN;
- }
- i += 7;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \type; ?
- buffer[i+1] == 't' &&
- buffer[i+2] == 'y' &&
- buffer[i+3] == 'p' &&
- buffer[i+4] == 'e' &&
- buffer[i+5] == ';' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~COLOR_MASK;
- font |= COLOR_TYPE;
- }
- i += 6;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \const; ?
- buffer[i+1] == 'c' &&
- buffer[i+2] == 'o' &&
- buffer[i+3] == 'n' &&
- buffer[i+4] == 's' &&
- buffer[i+5] == 't' &&
- buffer[i+6] == ';' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~COLOR_MASK;
- font |= COLOR_CONST;
- }
- i += 7;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \key; ?
- buffer[i+1] == 'k' &&
- buffer[i+2] == 'e' &&
- buffer[i+3] == 'y' &&
- buffer[i+4] == ';' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~COLOR_MASK;
- font |= COLOR_KEY;
- }
- i += 5;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \tab; ?
- buffer[i+1] == 't' &&
- buffer[i+2] == 'a' &&
- buffer[i+3] == 'b' &&
- buffer[i+4] == ';' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font |= COLOR_TABLE;
- }
- i += 5;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \norm; ?
- buffer[i+1] == 'n' &&
- buffer[i+2] == 'o' &&
- buffer[i+3] == 'r' &&
- buffer[i+4] == 'm' &&
- buffer[i+5] == ';' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- font &= ~COLOR_MASK;
- }
- i += 6;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \begin soluce; ?
- buffer[i+1] == 'b' &&
- buffer[i+2] == 's' &&
- buffer[i+3] == ';' )
- {
- bInSoluce = true;
- i += 4;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \end soluce; ?
- buffer[i+1] == 'e' &&
- buffer[i+2] == 's' &&
- buffer[i+3] == ';' )
- {
- bInSoluce = false;
- i += 4;
- }
- else if ( m_format != 0 &&
- buffer[i+0] == '\\' && // \key name; ?
- buffer[i+1] == 'k' &&
- buffer[i+2] == 'e' &&
- buffer[i+3] == 'y' &&
- buffer[i+4] == ' ' )
- {
- if ( m_bSoluce || !bInSoluce )
- {
- if ( SearchKey(buffer+i+5, key) )
- {
- res = m_engine->RetKey(key, 0);
- if ( res != 0 )
- {
- if ( GetResource(RES_KEY, res, iName) )
- {
- m_text[j] = ' ';
- m_format[j] = font;
- j ++;
- n = 0;
- while ( iName[n] != 0 )
- {
- m_text[j] = iName[n++];
- m_format[j] = font;
- j ++;
- }
- m_text[j] = ' ';
- m_format[j] = font;
- j ++;
-
- res = m_engine->RetKey(key, 1);
- if ( res != 0 )
- {
- if ( GetResource(RES_KEY, res, iName) )
- {
- GetResource(RES_TEXT, RT_KEY_OR, text);
- n = 0;
- while ( text[n] != 0 )
- {
- m_text[j] = text[n++];
- m_format[j] = font&~COLOR_MASK;
- j ++;
- }
- n = 0;
- while ( iName[n] != 0 )
- {
- m_text[j] = iName[n++];
- m_format[j] = font;
- j ++;
- }
- m_text[j] = ' ';
- m_format[j] = font;
- j ++;
- }
- }
- while ( buffer[i++] != ';' );
- continue;
- }
- }
- }
- m_text[j] = '?';
- m_format[j] = font;
- j ++;
- }
- while ( buffer[i++] != ';' );
- }
- else
- {
- if ( m_bSoluce || !bInSoluce )
- {
- m_text[j] = buffer[i];
- if ( m_format != 0 ) m_format[j] = font;
- j ++;
- }
- i ++;
-
- font &= ~TITLE_MASK; // reset title
-
- if ( (font&COLOR_MASK) == COLOR_TABLE )
- {
- font &= ~COLOR_TABLE;
- }
- }
- }
- m_len = j;
- m_imageTotal = iIndex;
-
- delete buffer;
-
- Justif();
- ColumnFix();
- return true;
-}
-
-// Writes all the text in a file.
-
-bool CEdit::WriteText(char *filename)
-{
- FILE* file;
- char buffer[1000+20];
- int i, j, k, n;
- float iDim;
-
- if ( filename[0] == 0 ) return false;
- file = fopen(filename, "wb");
- if ( file == NULL ) return false;
-
- if ( m_bAutoIndent )
- {
- iDim = m_dim.x;
- m_dim.x = 1000.0f; // puts an infinite width!
- Justif();
- }
-
- i = j = k = 0;
- while ( m_text[i] != 0 && i < m_len )
- {
- if ( m_bAutoIndent && i == m_lineOffset[k] )
- {
- for ( n=0 ; n<m_lineIndent[k] ; n++ )
- {
- buffer[j++] = '\t';
- }
- k ++;
- }
-
- buffer[j++] = m_text[i];
-
- if ( m_text[i] == '\n' )
- {
- buffer[j-1] = '\r';
- buffer[j++] = '\n'; // \r\n (0x0D, 0x0A)
- }
-
- if ( j >= 1000-1 )
- {
- fwrite(buffer, 1, j, file);
- j = 0;
- }
-
- i ++;
- }
- if ( j > 0 )
- {
- fwrite(buffer, 1, j, file);
- }
-
- fclose(file);
-
- if ( m_bAutoIndent )
- {
- m_dim.x = iDim; // presents the initial width
- Justif();
- }
-
- return true;
-}
-
-
-// Manage the number of max characters editable.
-
-void CEdit::SetMaxChar(int max)
-{
- m_maxChar = max;
- FreeImage();
- delete m_text;
- m_text = (char*)malloc(sizeof(char)*(m_maxChar+1));
-
- if ( m_format != 0 )
- {
- delete m_format;
- m_format = (char*)malloc(sizeof(char)*m_maxChar);
- }
-
- m_len = 0;
- m_cursor1 = 0;
- m_cursor2 = 0;
- Justif();
- UndoFlush();
-}
-
-int CEdit::RetMaxChar()
-{
- return m_maxChar;
-}
-
-
-// Mode management "editable".
-
-void CEdit::SetEditCap(bool bMode)
-{
- m_bEdit = bMode;
-}
-
-bool CEdit::RetEditCap()
-{
- return m_bEdit;
-}
-
-// Mode management "hilitable" (that's the franch).
-
-void CEdit::SetHiliteCap(bool bEnable)
-{
- m_bHilite = bEnable;
-}
-
-bool CEdit::RetHiliteCap()
-{
- return m_bHilite;
-}
-
-// Lift in / out connection.
-
-void CEdit::SetInsideScroll(bool bInside)
-{
- m_bInsideScroll = bInside;
-}
-
-bool CEdit::RetInsideScroll()
-{
- return m_bInsideScroll;
-}
-
-// Specifies whether to display the links showing the solution.
-
-void CEdit::SetSoluceMode(bool bSoluce)
-{
- m_bSoluce = bSoluce;
-}
-
-bool CEdit::RetSoluceMode()
-{
- return m_bSoluce;
-}
-
-// Indicates whether the text is a defile that generic.
-
-void CEdit::SetGenericMode(bool bGeneric)
-{
- m_bGeneric = bGeneric;
-}
-
-bool CEdit::RetGenericMode()
-{
- return m_bGeneric;
-}
-
-
-// Management of automatic indentation mode with {}.
-
-void CEdit::SetAutoIndent(bool bMode)
-{
- m_bAutoIndent = bMode;
-}
-
-bool CEdit::RetAutoIndent()
-{
- return m_bAutoIndent;
-}
-
-
-
-// Moves the cursors.
-
-void CEdit::SetCursor(int cursor1, int cursor2)
-{
- if ( cursor1 > m_len ) cursor1 = m_len;
- if ( cursor2 > m_len ) cursor2 = m_len;
-
- m_cursor1 = cursor1;
- m_cursor2 = cursor2;
- m_bUndoForce = true;
- ColumnFix();
-}
-
-// Returns the sliders.
-
-void CEdit::GetCursor(int &cursor1, int &cursor2)
-{
- cursor1 = m_cursor1;
- cursor2 = m_cursor2;
-}
-
-
-// Displayed line modifies the first.
-
-void CEdit::SetFirstLine(int rank)
-{
- Scroll(rank, true);
-}
-
-// Returns the first displayed line.
-
-int CEdit::RetFirstLine()
-{
- if ( m_historyTotal > 0 )
- {
- if ( m_historyCurrent == 0 )
- {
- return m_lineFirst;
- }
- else
- {
- return m_history[0].firstLine;
- }
- }
- return m_lineFirst;
-}
-
-
-// Shows the selected area.
-
-void CEdit::ShowSelect()
-{
- int cursor1, cursor2, line;
-
- if ( m_cursor1 < m_cursor2 )
- {
- cursor1 = m_cursor1;
- cursor2 = m_cursor2;
- }
- else
- {
- cursor1 = m_cursor2;
- cursor2 = m_cursor1;
- }
-
- line = RetCursorLine(cursor2);
- if ( line >= m_lineFirst+m_lineVisible )
- {
- line -= m_lineVisible-1;
- if ( line < 0 ) line = 0;
- Scroll(line, false);
- }
-
- line = RetCursorLine(cursor1);
- if ( line < m_lineFirst )
- {
- Scroll(line, false);
- }
-}
-
-
-// Management of the display mode of special characters.
-
-void CEdit::SetDisplaySpec(bool bDisplay)
-{
- m_bDisplaySpec = bDisplay;
-}
-
-bool CEdit::RetDisplaySpec()
-{
- return m_bDisplaySpec;
-}
-
-
-// Multi-fonts mode management.
-
-void CEdit::SetMultiFont(bool bMulti)
-{
- if ( bMulti )
- {
- delete m_format;
- m_format = (char*)malloc(sizeof(char)*m_maxChar);
- memset(m_format, 0, m_maxChar);
- }
- else
- {
- delete m_format;
- m_format = 0;
- }
-}
-
-bool CEdit::RetMultiFont()
-{
- return ( m_format != 0 );
-}
-
-
-// Management of the character size.
-
-void CEdit::SetFontSize(float size)
-{
- CControl::SetFontSize(size);
-
- MoveAdjust();
-}
-
-
-// Moves according to the visible lift.
-
-void CEdit::Scroll()
-{
- float value;
-
- if ( m_scroll != 0 )
- {
- value = m_scroll->RetVisibleValue();
- value *= m_lineTotal-m_lineVisible;
- Scroll((int)(value+0.5f), true);
- }
-}
-
-// Moves according to the visible lift.
-
-void CEdit::Scroll(int pos, bool bAdjustCursor)
-{
- int max, line;
-
- m_lineFirst = pos;
-
- if ( m_lineFirst < 0 ) m_lineFirst = 0;
-
- max = m_lineTotal-m_lineVisible;
- if ( max < 0 ) max = 0;
- if ( m_lineFirst > max ) m_lineFirst = max;
-
- line = RetCursorLine(m_cursor1);
-
- if ( bAdjustCursor && m_bEdit )
- {
- // Cursor too high?
- if ( line < m_lineFirst )
- {
- MoveLine(m_lineFirst-line, false, false);
- return;
- }
-
- // Cursor too low?
- if ( line >= m_lineFirst+m_lineVisible )
- {
- MoveLine(m_lineFirst+m_lineVisible-line-1, false, false);
- return;
- }
- }
-
- Justif();
-}
-
-// Moves the cursor to the beginning of the line.
-
-void CEdit::MoveHome(bool bWord, bool bSelect)
-{
- int begin, tab;
-
- if ( bWord )
- {
- m_cursor1 = 0;
- }
- else
- {
- begin = m_cursor1;
- while ( begin > 0 && m_text[begin-1] != '\n' )
- {
- begin --;
- }
-
- tab = begin;
- while ( tab < m_len && (m_text[tab] == '\t' || m_text[tab] == ' ') )
- {
- tab ++;
- }
-
- if ( m_cursor1 == tab )
- {
- m_cursor1 = begin;
- }
- else
- {
- m_cursor1 = tab;
- }
- }
- if ( !bSelect ) m_cursor2 = m_cursor1;
-
- m_bUndoForce = true;
- Justif();
- ColumnFix();
-}
-
-// Moves the cursor to the end of the line.
-
-void CEdit::MoveEnd(bool bWord, bool bSelect)
-{
- if ( bWord )
- {
- m_cursor1 = m_len;
- }
- else
- {
- while ( m_cursor1 < m_len && m_text[m_cursor1] != '\n' )
- {
- m_cursor1 ++;
- }
- }
- if ( !bSelect ) m_cursor2 = m_cursor1;
-
- m_bUndoForce = true;
- Justif();
- ColumnFix();
-}
-
-// Moves the cursor through characters.
-
-void CEdit::MoveChar(int move, bool bWord, bool bSelect)
-{
- int character;
-
- if ( move == -1 ) // back?
- {
- if ( bWord )
- {
- while ( m_cursor1 > 0 )
- {
- character = (unsigned char)m_text[m_cursor1-1];
- if ( !IsSpace(character) ) break;
- m_cursor1 --;
- }
-
- if ( m_cursor1 > 0 )
- {
- character = (unsigned char)m_text[m_cursor1-1];
- if ( IsSpace(character) )
- {
- while ( m_cursor1 > 0 )
- {
- character = (unsigned char)m_text[m_cursor1-1];
- if ( !IsSpace(character) ) break;
- m_cursor1 --;
- }
- }
- else if ( IsWord(character) )
- {
- while ( m_cursor1 > 0 )
- {
- character = (unsigned char)m_text[m_cursor1-1];
- if ( !IsWord(character) ) break;
- m_cursor1 --;
- }
- }
- else if ( IsSep(character) )
- {
- while ( m_cursor1 > 0 )
- {
- character = (unsigned char)m_text[m_cursor1-1];
- if ( !IsSep(character) ) break;
- m_cursor1 --;
- }
- }
- }
- }
- else
- {
- m_cursor1 --;
- if ( m_cursor1 < 0 ) m_cursor1 = 0;
- }
- }
-
- if ( move == 1 ) // advance?
- {
- if ( bWord )
- {
- if ( m_cursor1 < m_len )
- {
- character = (unsigned char)m_text[m_cursor1];
- if ( IsSpace(character) )
- {
- while ( m_cursor1 < m_len )
- {
- character = (unsigned char)m_text[m_cursor1];
- if ( !IsSpace(character) ) break;
- m_cursor1 ++;
- }
- }
- else if ( IsWord(character) )
- {
- while ( m_cursor1 < m_len )
- {
- character = (unsigned char)m_text[m_cursor1];
- if ( !IsWord(character) ) break;
- m_cursor1 ++;
- }
- }
- else if ( IsSep(character) )
- {
- while ( m_cursor1 < m_len )
- {
- character = (unsigned char)m_text[m_cursor1];
- if ( !IsSep(character) ) break;
- m_cursor1 ++;
- }
- }
- }
-
- while ( m_cursor1 < m_len )
- {
- character = (unsigned char)m_text[m_cursor1];
- if ( !IsSpace(character) ) break;
- m_cursor1 ++;
- }
- }
- else
- {
- m_cursor1 ++;
- if ( m_cursor1 > m_len ) m_cursor1 = m_len;
- }
- }
-
- if ( !bSelect ) m_cursor2 = m_cursor1;
-
- m_bUndoForce = true;
- Justif();
- ColumnFix();
-}
-
-// Moves the cursor lines.
-
-void CEdit::MoveLine(int move, bool bWord, bool bSelect)
-{
- float column, indentLength;
- int i, line, c;
-
- if ( move == 0 ) return;
-
- for ( i=0 ; i>move ; i-- ) // back?
- {
- while ( m_cursor1 > 0 && m_text[m_cursor1-1] != '\n' )
- {
- m_cursor1 --;
- }
- if ( m_cursor1 != 0 )
- {
- m_cursor1 --;
- while ( m_cursor1 > 0 )
- {
- if ( m_text[--m_cursor1] == '\n' )
- {
- m_cursor1 ++;
- break;
- }
- }
- }
- }
-
- for ( i=0 ; i<move ; i++ ) // advance?
- {
- while ( m_cursor1 < m_len )
- {
- if ( m_text[m_cursor1++] == '\n' )
- {
- break;
- }
- }
- }
-
- line = RetCursorLine(m_cursor1);
-
- column = m_column;
- if ( m_bAutoIndent )
- {
- indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType)
- * m_engine->RetEditIndentValue();
- column -= indentLength*m_lineIndent[line];
- }
-
- if ( m_format == 0 )
- {
- c = m_engine->RetText()->Detect(m_text+m_lineOffset[line],
- m_lineOffset[line+1]-m_lineOffset[line],
- column, m_fontSize,
- m_fontStretch, m_fontType);
- }
- else
- {
- c = m_engine->RetText()->Detect(m_text+m_lineOffset[line],
- m_format+m_lineOffset[line],
- m_lineOffset[line+1]-m_lineOffset[line],
- column, m_fontSize, m_fontStretch);
- }
-
- m_cursor1 = m_lineOffset[line]+c;
- if ( !bSelect ) m_cursor2 = m_cursor1;
-
- m_bUndoForce = true;
- Justif();
-}
-
-// Sets the horizontal position.
-
-void CEdit::ColumnFix()
-{
- float indentLength;
- int line;
-
- line = RetCursorLine(m_cursor1);
-
- if ( m_format == 0 )
- {
- m_column = m_engine->RetText()->RetStringWidth
- (
- m_text+m_lineOffset[line],
- m_cursor1-m_lineOffset[line],
- m_fontSize, m_fontStretch, m_fontType
- );
- }
- else
- {
- m_column = m_engine->RetText()->RetStringWidth
- (
- m_text+m_lineOffset[line],
- m_format+m_lineOffset[line],
- m_cursor1-m_lineOffset[line],
- m_fontSize, m_fontStretch
- );
- }
-
- if ( m_bAutoIndent )
- {
- indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType)
- * m_engine->RetEditIndentValue();
- m_column += indentLength*m_lineIndent[line];
- }
-}
-
-
-// Cut the selected characters or entire line.
-
-bool CEdit::Cut()
-{
- HGLOBAL hg;
- char* text;
- char c;
- int c1, c2, start, len, i, j;
-
- if ( !m_bEdit ) return false;
-
- c1 = m_cursor1;
- c2 = m_cursor2;
- if ( c1 > c2 ) Math::Swap(c1, c2); // always c1 <= c2
-
- if ( c1 == c2 )
- {
- while ( c1 > 0 )
- {
- if ( m_text[c1-1] == '\n' ) break;
- c1 --;
- }
- while ( c2 < m_len )
- {
- c2 ++;
- if ( m_text[c2-1] == '\n' ) break;
- }
- }
-
- if ( c1 == c2 ) return false;
-
- start = c1;
- len = c2-c1;
-
- if ( !(hg = GlobalAlloc(GMEM_DDESHARE, len*2+1)) )
- {
- return false;
- }
- if ( !(text = (char*)GlobalLock(hg)) )
- {
- GlobalFree(hg);
- return false;
- }
-
- j = 0;
- for ( i=start ; i<start+len ; i++ )
- {
- c = m_text[i];
- if ( c == '\n' ) text[j++] = '\r';
- text[j++] = c;
- }
- text[j] = 0;
- GlobalUnlock(hg);
-
- if ( !OpenClipboard(NULL) )
- {
- GlobalFree(hg);
- return false;
- }
- if ( !EmptyClipboard() )
- {
- GlobalFree(hg);
- return false;
- }
- if ( !SetClipboardData(CF_TEXT, hg) )
- {
- GlobalFree(hg);
- return false;
- }
- CloseClipboard();
-
- UndoMemorize(OPERUNDO_SPEC);
- m_cursor1 = c1;
- m_cursor2 = c2;
- DeleteOne(0); // deletes the selected characters
- Justif();
- ColumnFix();
- SendModifEvent();
- return true;
-}
-
-// Copy the selected characters or entire line.
-
-bool CEdit::Copy()
-{
- HGLOBAL hg;
- char* text;
- char c;
- int c1, c2, start, len, i, j;
-
- c1 = m_cursor1;
- c2 = m_cursor2;
- if ( c1 > c2 ) Math::Swap(c1, c2); // always c1 <= c2
-
- if ( c1 == c2 )
- {
- while ( c1 > 0 )
- {
- if ( m_text[c1-1] == '\n' ) break;
- c1 --;
- }
- while ( c2 < m_len )
- {
- c2 ++;
- if ( m_text[c2-1] == '\n' ) break;
- }
- }
-
- if ( c1 == c2 ) return false;
-
- start = c1;
- len = c2-c1;
-
- if ( !(hg = GlobalAlloc(GMEM_DDESHARE, len*2+1)) )
- {
- return false;
- }
- if ( !(text = (char*)GlobalLock(hg)) )
- {
- GlobalFree(hg);
- return false;
- }
-
- j = 0;
- for ( i=start ; i<start+len ; i++ )
- {
- c = m_text[i];
- if ( c == '\n' ) text[j++] = '\r';
- text[j++] = c;
- }
- text[j] = 0;
- GlobalUnlock(hg);
-
- if ( !OpenClipboard(NULL) )
- {
- GlobalFree(hg);
- return false;
- }
- if ( !EmptyClipboard() )
- {
- GlobalFree(hg);
- return false;
- }
- if ( !SetClipboardData(CF_TEXT, hg) )
- {
- GlobalFree(hg);
- return false;
- }
- CloseClipboard();
-
- return true;
-}
-
-// Paste the contents of the notebook.
-
-bool CEdit::Paste()
-{
- HANDLE h;
- char c;
- char* p;
-
- if ( !m_bEdit ) return false;
-
- if ( !OpenClipboard(NULL) )
- {
- return false;
- }
-
- if ( !(h = GetClipboardData(CF_TEXT)) )
- {
- CloseClipboard();
- return false;
- }
-
- if ( !(p = (char*)GlobalLock(h)) )
- {
- CloseClipboard();
- return false;
- }
-
- UndoMemorize(OPERUNDO_SPEC);
-
- while ( *p != 0 )
- {
- c = *p++;
- if ( c == '\r' ) continue;
- if ( c == '\t' && m_bAutoIndent ) continue;
- InsertOne(c);
- }
-
- GlobalUnlock(h);
- CloseClipboard();
-
- Justif();
- ColumnFix();
- SendModifEvent();
- return true;
-}
-
-
-// Cancels the last action.
-
-bool CEdit::Undo()
-{
- if ( !m_bEdit ) return false;
-
- return UndoRecall();
-}
-
-
-// Inserts a character.
-
-void CEdit::Insert(char character)
-{
- int i, level, tab;
-
- if ( !m_bEdit ) return;
-
- if ( !m_bMulti ) // single-line?
- {
- if ( character == '\n' ||
- character == '\t' ) return;
- }
-
- UndoMemorize(OPERUNDO_INSERT);
-
- if ( m_bMulti && !m_bAutoIndent )
- {
- if ( character == '\n' )
- {
- InsertOne(character);
- level = IndentCompute();
- for ( i=0 ; i<level ; i++ )
- {
- InsertOne('\t');
- }
- }
- else if ( character == '{' )
- {
- tab = IndentTabCount();
- if ( tab != -1 )
- {
- level = IndentCompute();
- IndentTabAdjust(level-tab);
- }
- InsertOne(character);
- }
- else if ( character == '}' )
- {
- tab = IndentTabCount();
- if ( tab != -1 )
- {
- level = IndentCompute()-1;
- IndentTabAdjust(level-tab);
- }
- InsertOne(character);
- }
- else
- {
- InsertOne(character);
- }
- }
- else if ( m_bAutoIndent )
- {
- if ( character == '{' )
- {
- InsertOne(character);
- InsertOne('\n');
- InsertOne('\n');
- InsertOne('}');
- MoveChar(-1, false, false);
- MoveChar(-1, false, false);
- }
-#if 0
- else if ( character == '(' )
- {
- InsertOne(character);
- InsertOne(')');
- MoveChar(-1, false, false);
- }
- else if ( character == '[' )
- {
- InsertOne(character);
- InsertOne(']');
- MoveChar(-1, false, false);
- }
-#endif
- else if ( character == '\t' )
- {
- for ( i=0 ; i<m_engine->RetEditIndentValue() ; i++ )
- {
- InsertOne(' ');
- }
- }
- else
- {
- InsertOne(character);
- }
- }
- else
- {
- InsertOne(character);
- }
-
- Justif();
- ColumnFix();
-}
-
-// Inserts a plain character.
-
-void CEdit::InsertOne(char character)
-{
- int i;
-
- if ( !m_bEdit ) return;
- if ( !m_bMulti && character == '\n' ) return;
-
- if ( m_cursor1 != m_cursor2 )
- {
- DeleteOne(0); // deletes the selected characters
- }
-
- if ( m_len >= m_maxChar ) return;
-
- for ( i=m_len ; i>=m_cursor1 ; i-- )
- {
- m_text[i] = m_text[i-1]; // shoot
-
- if ( m_format != 0 )
- {
- m_format[i] = m_format[i-1]; // shoot
- }
- }
-
- m_len ++;
-
- m_text[m_cursor1] = character;
-
- if ( m_format != 0 )
- {
- m_format[m_cursor1] = 0;
- }
-
- m_cursor1++;
- m_cursor2 = m_cursor1;
-}
-
-// Deletes the character left of cursor or all selected characters.
-
-void CEdit::Delete(int dir)
-{
- if ( !m_bEdit ) return;
-
- UndoMemorize(OPERUNDO_DELETE);
- DeleteOne(dir);
-
- Justif();
- ColumnFix();
-}
-
-// Deletes the character left of cursor or all selected plain characters.
-
-void CEdit::DeleteOne(int dir)
-{
- int i, end, hole;
-
- if ( !m_bEdit ) return;
-
- if ( m_cursor1 == m_cursor2 )
- {
- if ( dir < 0 )
- {
- if ( m_cursor1 == 0 ) return;
- m_cursor1 --;
- }
- else
- {
- if ( m_cursor2 == m_len ) return;
- m_cursor2 ++;
- }
- }
-
- if ( m_cursor1 > m_cursor2 ) Math::Swap(m_cursor1, m_cursor2);
- hole = m_cursor2-m_cursor1;
- end = m_len-hole;
- for ( i=m_cursor1 ; i<end ; i++ )
- {
- m_text[i] = m_text[i+hole];
-
- if ( m_format != 0 )
- {
- m_format[i] = m_format[i+hole];
- }
- }
- m_len -= hole;
- m_cursor2 = m_cursor1;
-}
-
-
-// Calculates the indentation level of brackets {and}.
-
-int CEdit::IndentCompute()
-{
- int i, level;
-
- level = 0;
- for ( i=0 ; i<m_cursor1 ; i++ )
- {
- if ( m_text[i] == '{' ) level ++;
- if ( m_text[i] == '}' ) level --;
- }
-
- if ( level < 0 ) level = 0;
- return level;
-}
-
-// Counts the number of tabs before the cursor.
-// Returns -1 if there is something else.
-
-int CEdit::IndentTabCount()
-{
- int i, nb;
-
- if ( m_cursor1 != m_cursor2 ) return -1;
-
- i = m_cursor1;
- nb = 0;
- while ( i > 0 )
- {
- if ( m_text[i-1] == '\n' ) return nb;
- if ( m_text[i-1] != '\t' ) return -1;
- nb ++;
- i --;
- }
- return nb;
-}
-
-// Adds or removes qq tabs.
-
-void CEdit::IndentTabAdjust(int number)
-{
- int i;
-
- for ( i=0 ; i<number ; i++ ) // add?
- {
- InsertOne('\t');
- }
-
- for ( i=0 ; i>number ; i-- ) // delete?
- {
- DeleteOne(-1);
- }
-}
-
-
-// Indent the left or right the entire selection.
-
-bool CEdit::Shift(bool bLeft)
-{
- bool bInvert = false;
- int c1, c2, i;
-
- if ( m_cursor1 == m_cursor2 ) return false;
-
- UndoMemorize(OPERUNDO_SPEC);
-
- c1 = m_cursor1;
- c2 = m_cursor2;
- if ( c1 > c2 )
- {
- Math::Swap(c1, c2); // always c1 <= c2
- bInvert = true;
- }
-
- if ( c1 > 0 )
- {
- if ( m_text[c1-1] != '\n' ) return false;
- }
- if ( c2 < m_len )
- {
- if ( m_text[c2-1] != '\n' ) return false;
- }
-
- if ( bLeft ) // shifts left?
- {
- i = c1;
- while ( i < c2 )
- {
- if ( m_text[i] == '\t' )
- {
- m_cursor1 = i;
- m_cursor2 = i+1;
- DeleteOne(0);
- c2 --;
- }
- while ( i < c2 && m_text[i++] != '\n' );
- }
- }
- else // shifts right?
- {
- i = c1;
- while ( i < c2 )
- {
- m_cursor1 = m_cursor2 = i;
- InsertOne('\t');
- c2 ++;
- while ( i < c2 && m_text[i++] != '\n' );
- }
- }
-
- if ( bInvert ) Math::Swap(c1, c2);
- m_cursor1 = c1;
- m_cursor2 = c2;
-
- Justif();
- ColumnFix();
- SendModifEvent();
- return true;
-}
-
-// Math::Min conversion <-> shift the selection.
-
-bool CEdit::MinMaj(bool bMaj)
-{
- int c1, c2, i, character;
-
- if ( m_cursor1 == m_cursor2 ) return false;
-
- UndoMemorize(OPERUNDO_SPEC);
-
- c1 = m_cursor1;
- c2 = m_cursor2;
- if ( c1 > c2 ) Math::Swap(c1, c2); // alwyas c1 <= c2
-
- for ( i=c1 ; i<c2 ; i++ )
- {
- character = (unsigned char)m_text[i];
- if ( bMaj ) character = RetToUpper(character);
- else character = RetToLower(character);
- m_text[i] = character;
- }
-
- Justif();
- ColumnFix();
- SendModifEvent();
- return true;
-}
-
-
-// Cut all text lines.
-
-void CEdit::Justif()
-{
- float width, value, size, indentLength;
- int i, j, line, indent;
- bool bDual, bString, bRem;
-
- indent = 0;
- m_lineTotal = 0;
- m_lineOffset[m_lineTotal] = 0;
- m_lineIndent[m_lineTotal] = indent;
- m_lineTotal ++;
-
- if ( m_bAutoIndent )
- {
- indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType)
- * m_engine->RetEditIndentValue();
- }
-
- bString = bRem = false;
- i = 0;
- while ( true )
- {
- bDual = false;
-
- width = m_dim.x-(10.0f/640.0f)*2.0f-(m_bMulti?MARGX*2.0f+SCROLL_WIDTH:0.0f);
- if ( m_bAutoIndent )
- {
- width -= indentLength*m_lineIndent[m_lineTotal-1];
- }
-
- if ( m_format == 0 )
- {
- i += m_engine->RetText()->Justif(m_text+i, m_len-i, width,
- m_fontSize, m_fontStretch,
- m_fontType);
- }
- else
- {
- size = m_fontSize;
-
- if ( (m_format[i]&TITLE_MASK) == TITLE_BIG ) // headline?
- {
- size *= BIG_FONT;
- bDual = true;
- }
-
- if ( (m_format[i]&IMAGE_MASK) != 0 ) // image part?
- {
- i ++; // jumps just a character (index in m_image)
- }
- else
- {
- i += m_engine->RetText()->Justif(m_text+i, m_format+i,
- m_len-i, width,
- size, m_fontStretch);
- }
- }
-
- if ( i >= m_len ) break;
-
- if ( m_bAutoIndent )
- {
- for ( j=m_lineOffset[m_lineTotal-1] ; j<i ; j++ )
- {
- if ( !bRem && m_text[j] == '\"' ) bString = !bString;
- if ( !bString &&
- m_text[j] == '/' &&
- m_text[j+1] == '/' ) bRem = true;
- if ( m_text[j] == '\n' ) bString = bRem = false;
- if ( m_text[j] == '{' && !bString && !bRem ) indent ++;
- if ( m_text[j] == '}' && !bString && !bRem ) indent --;
- }
- if ( indent < 0 ) indent = 0;
- }
-
- m_lineOffset[m_lineTotal] = i;
- m_lineIndent[m_lineTotal] = indent;
- m_lineTotal ++;
- if ( bDual )
- {
- m_lineOffset[m_lineTotal] = i;
- m_lineIndent[m_lineTotal] = indent;
- m_lineTotal ++;
- }
- if ( m_lineTotal >= EDITLINEMAX-2 ) break;
- }
- if ( m_len > 0 && m_text[m_len-1] == '\n' )
- {
- m_lineOffset[m_lineTotal] = m_len;
- m_lineIndent[m_lineTotal] = 0;
- m_lineTotal ++;
- }
- m_lineOffset[m_lineTotal] = m_len;
- m_lineIndent[m_lineTotal] = 0;
-
- if ( m_bAutoIndent )
- {
- for ( i=0 ; i<=m_lineTotal ; i++ )
- {
- if ( m_text[m_lineOffset[i]] == '}' )
- {
- if ( m_lineIndent[i] > 0 ) m_lineIndent[i] --;
- }
- }
- }
-
- if ( m_bMulti )
- {
- if ( m_bEdit )
- {
- line = RetCursorLine(m_cursor1);
- if ( line < m_lineFirst )
- {
- m_lineFirst = line;
- }
- if ( line >= m_lineFirst+m_lineVisible )
- {
- m_lineFirst = line-m_lineVisible+1;
- }
- }
- }
- else
- {
- m_lineFirst = 0;
- }
-
- if ( m_scroll != 0 )
- {
- if ( m_lineTotal <= m_lineVisible )
- {
- m_scroll->SetVisibleRatio(1.0f);
- m_scroll->SetVisibleValue(0.0f);
- m_scroll->SetArrowStep(0.0f);
- }
- else
- {
- value = (float)m_lineVisible/m_lineTotal;
- m_scroll->SetVisibleRatio(value);
-
- value = (float)m_lineFirst/(m_lineTotal-m_lineVisible);
- m_scroll->SetVisibleValue(value);
-
- value = (float)1.0f/(m_lineTotal-m_lineVisible);
- m_scroll->SetArrowStep(value);
- }
- }
-
- m_timeBlink = 0.0f; // lights the cursor immediately
-}
-
-// Returns the rank of the line where the cursor is located.
-
-int CEdit::RetCursorLine(int cursor)
-{
- int line, i;
-
- line = 0;
- for ( i=0 ; i<m_lineTotal ; i++ )
- {
- if ( cursor >= m_lineOffset[i] )
- {
- line = i;
- }
- }
- return line;
-}
-
-
-// Flush the buffer undo.
-
-void CEdit::UndoFlush()
-{
- int i;
-
- for ( i=0 ; i<EDITUNDOMAX ; i++ )
- {
- delete m_undo[i].text;
- m_undo[i].text = 0;
- }
-
- m_bUndoForce = true;
- m_undoOper = OPERUNDO_SPEC;
-}
-
-// Memorize the current state before a change.
-
-void CEdit::UndoMemorize(OperUndo oper)
-{
- int i, len;
-
- if ( !m_bUndoForce &&
- oper != OPERUNDO_SPEC &&
- m_undoOper != OPERUNDO_SPEC &&
- oper == m_undoOper ) return;
-
- m_bUndoForce = false;
- m_undoOper = oper;
-
- delete m_undo[EDITUNDOMAX-1].text;
-
- for ( i=EDITUNDOMAX-1 ; i>=1 ; i-- )
- {
- m_undo[i] = m_undo[i-1];
- }
-
- len = m_len;
- if ( len == 0 ) len ++;
- m_undo[0].text = (char*)malloc(sizeof(char)*(len+1));
- memcpy(m_undo[0].text, m_text, m_len);
- m_undo[0].len = m_len;
-
- m_undo[0].cursor1 = m_cursor1;
- m_undo[0].cursor2 = m_cursor2;
- m_undo[0].lineFirst = m_lineFirst;
-}
-
-// Back to previous state.
-
-bool CEdit::UndoRecall()
-{
- int i;
-
- if ( m_undo[0].text == 0 ) return false;
-
- m_len = m_undo[0].len;
- memcpy(m_text, m_undo[0].text, m_len);
-
- m_cursor1 = m_undo[0].cursor1;
- m_cursor2 = m_undo[0].cursor2;
- m_lineFirst = m_undo[0].lineFirst;
-
- for ( i=0 ; i<EDITUNDOMAX-1 ; i++ )
- {
- m_undo[i] = m_undo[i+1];
- }
- m_undo[EDITUNDOMAX-1].text = 0;
-
- m_bUndoForce = true;
- Justif();
- ColumnFix();
- SendModifEvent();
- return true;
-}
-
-
-// Clears the format of all characters.
-
-bool CEdit::ClearFormat()
-{
- if ( m_format == 0 )
- {
- SetMultiFont(true);
- }
- memset(m_format, m_fontType, m_len);
-
- return true;
-}
-
-// Changes the format of a sequence of characters.
-
-bool CEdit::SetFormat(int cursor1, int cursor2, int format)
-{
- int i;
-
- if ( m_format == 0 ) return false;
-
- for ( i=cursor1 ; i<cursor2 ; i++ )
- {
- m_format[i] |= format;
- }
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// edit.cpp
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <windows.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "common/language.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "ui/scroll.h"
+#include "old/text.h"
+#include "ui/edit.h"
+
+
+const float MARGX = (5.0f/640.0f);
+const float MARGY = (5.0f/480.0f);
+const float MARGYS = (4.0f/480.0f);
+const float MARGY1 = (1.0f/480.0f);
+const float DELAY_DBCLICK = 0.3f; // time limit for double-click
+const float DELAY_SCROLL = 0.1f; // time limit for scroll
+const float BIG_FONT = 1.6f; // expansion for \b;
+
+
+
+
+// Indicates whether a character is a space.
+
+bool IsSpace(int character)
+{
+ return ( character == ' ' ||
+ character == '\t' ||
+ character == '\n' );
+}
+
+// Indicates whether a character is part of a word.
+
+bool IsWord(int character)
+{
+ char c;
+
+ c = tolower(RetNoAccent(character));
+
+ return ( (c >= 'a' && c <= 'z') ||
+ (c >= '0' && c <= '9') ||
+ c == '_' );
+}
+
+// Indicates whether a character is a word separator.
+
+bool IsSep(int character)
+{
+ if ( IsSpace(character) ) return false;
+ return !IsWord(character);
+}
+
+
+
+// Object's constructor.
+
+CEdit::CEdit(CInstanceManager* iMan) : CControl(iMan)
+{
+ Math::Point pos;
+ int i;
+
+ m_maxChar = 100;
+ m_text = (char*)malloc(sizeof(char)*(m_maxChar+1));
+ m_format = 0;
+ m_len = 0;
+
+ m_fontType = FONT_COURIER;
+ m_scroll = 0;
+ m_bEdit = true;
+ m_bHilite = true;
+ m_bInsideScroll = true;
+ m_bCapture = false;
+ m_bDisplaySpec = false;
+ m_bSoluce = false;
+ m_bGeneric = false;
+ m_bAutoIndent = false;
+ m_cursor1 = 0;
+ m_cursor2 = 0;
+ m_column = 0;
+ m_imageTotal = 0;
+
+ HyperFlush();
+
+ for ( i=0 ; i<EDITUNDOMAX ; i++ )
+ {
+ m_undo[i].text = 0;
+ }
+ m_bUndoForce = true;
+ m_undoOper = OPERUNDO_SPEC;
+}
+
+// Object's destructor.
+
+CEdit::~CEdit()
+{
+ int i;
+
+ FreeImage();
+
+ for ( i=0 ; i<EDITUNDOMAX ; i++ )
+ {
+ delete m_undo[i].text;
+ }
+
+ delete m_text;
+ delete m_format;
+ delete m_scroll;
+}
+
+
+// Creates a new editable line.
+
+bool CEdit::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CScroll* pc;
+ Math::Point start, end;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+ CControl::Create(pos, dim, icon, eventMsg);
+
+ m_len = 0;
+ m_lineFirst = 0;
+ m_time = 0.0f;
+ m_timeBlink = 0.0f;
+ m_timeLastClick = 0.0f;
+ m_timeLastScroll = 0.0f;
+
+ m_bMulti = false;
+ MoveAdjust();
+ if ( m_lineVisible <= 1 )
+ {
+ m_bMulti = false;
+ }
+ else
+ {
+ m_bMulti = true;
+ MoveAdjust(); // readjusts multi-line mode
+ m_scroll = new CScroll(m_iMan);
+ pc = (CScroll*)m_scroll;
+ pc->Create(pos, dim, -1, EVENT_NULL);
+ MoveAdjust();
+ }
+
+ return true;
+}
+
+
+void CEdit::SetPos(Math::Point pos)
+{
+ CControl::SetPos(pos);
+ MoveAdjust();
+}
+
+void CEdit::SetDim(Math::Point dim)
+{
+ CControl::SetDim(dim);
+ MoveAdjust();
+}
+
+void CEdit::MoveAdjust()
+{
+ Math::Point pos, dim;
+ float height;
+
+ m_lineDescent = m_engine->RetText()->RetDescent(m_fontSize, m_fontType);
+ m_lineAscent = m_engine->RetText()->RetAscent(m_fontSize, m_fontType);
+ m_lineHeight = m_engine->RetText()->RetHeight(m_fontSize, m_fontType);
+
+ height = m_dim.y-(m_bMulti?MARGY*2.0f:MARGY1);
+ m_lineVisible = (int)(height/m_lineHeight);
+
+ if ( m_scroll != 0 )
+ {
+ if ( m_bInsideScroll )
+ {
+ pos.x = m_pos.x+m_dim.x-MARGX-SCROLL_WIDTH;
+ pos.y = m_pos.y+MARGYS;
+ dim.x = SCROLL_WIDTH;
+ dim.y = m_dim.y-MARGYS*2.0f;
+ }
+ else
+ {
+ pos.x = m_pos.x+m_dim.x-SCROLL_WIDTH;
+ pos.y = m_pos.y;
+ dim.x = SCROLL_WIDTH;
+ dim.y = m_dim.y;
+ }
+ m_scroll->SetPos(pos);
+ m_scroll->SetDim(dim);
+ }
+
+ Justif();
+
+ if ( m_lineFirst > m_lineTotal-m_lineVisible )
+ {
+ m_lineFirst = m_lineTotal-m_lineVisible;
+ if ( m_lineFirst < 0 ) m_lineFirst = 0;
+ }
+
+ pos.x = m_pos.x+m_dim.x-(m_bMulti?SCROLL_WIDTH:0.0f);
+ pos.y = m_pos.y;
+ GlintCreate(pos, false, false);
+}
+
+
+// Management of an event.
+
+bool CEdit::EventProcess(const Event &event)
+{
+ bool bShift, bControl;
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return true;
+
+ if ( event.event == EVENT_KEYDOWN &&
+ event.param == VK_WHEELUP &&
+ Detect(event.pos) )
+ {
+ Scroll(m_lineFirst-3, true);
+ return true;
+ }
+ if ( event.event == EVENT_KEYDOWN &&
+ event.param == VK_WHEELDOWN &&
+ Detect(event.pos) )
+ {
+ Scroll(m_lineFirst+3, true);
+ return true;
+ }
+
+ CControl::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ m_time += event.rTime;
+ m_timeBlink += event.rTime;
+ }
+
+ if ( event.event == EVENT_MOUSEMOVE )
+ {
+ if ( Detect(event.pos) &&
+ event.pos.x < m_pos.x+m_dim.x-(m_bMulti?MARGX+SCROLL_WIDTH:0.0f) )
+ {
+ if ( m_bEdit )
+ {
+ m_engine->SetMouseType(D3DMOUSEEDIT);
+ }
+ else
+ {
+ if ( IsLinkPos(event.pos) )
+ {
+ m_engine->SetMouseType(D3DMOUSEHAND);
+ }
+ else
+ {
+ m_engine->SetMouseType(D3DMOUSENORM);
+ }
+ }
+ }
+ }
+
+ if ( m_scroll != 0 && !m_bGeneric )
+ {
+ m_scroll->EventProcess(event);
+
+ if ( event.event == m_scroll->RetEventMsg() )
+ {
+ Scroll();
+ return true;
+ }
+ }
+
+ if ( event.event == EVENT_KEYDOWN && m_bFocus )
+ {
+ bShift = (event.keyState&KS_SHIFT);
+ bControl = (event.keyState&KS_CONTROL);
+
+ if ( (event.param == 'X' && !bShift && bControl) ||
+ (event.param == VK_DELETE && bShift && !bControl) )
+ {
+ Cut();
+ return true;
+ }
+ if ( (event.param == 'C' && !bShift && bControl) ||
+ (event.param == VK_INSERT && !bShift && bControl) )
+ {
+ Copy();
+ return true;
+ }
+ if ( (event.param == 'V' && !bShift && bControl) ||
+ (event.param == VK_INSERT && bShift && !bControl) )
+ {
+ Paste();
+ return true;
+ }
+
+ if ( event.param == 'A' && !bShift && bControl )
+ {
+ SetCursor(999999, 0);
+ return true;
+ }
+
+ if ( event.param == 'O' && !bShift && bControl )
+ {
+ Event newEvent;
+ m_event->MakeEvent(newEvent, EVENT_STUDIO_OPEN);
+ m_event->AddEvent(newEvent);
+ }
+ if ( event.param == 'S' && !bShift && bControl )
+ {
+ Event newEvent;
+ m_event->MakeEvent(newEvent, EVENT_STUDIO_SAVE);
+ m_event->AddEvent(newEvent);
+ }
+
+ if ( event.param == 'Z' && !bShift && bControl )
+ {
+ Undo();
+ return true;
+ }
+
+ if ( event.param == 'U' && !bShift && bControl )
+ {
+ if ( MinMaj(false) ) return true;
+ }
+ if ( event.param == 'U' && bShift && bControl )
+ {
+ if ( MinMaj(true) ) return true;
+ }
+
+ if ( event.param == VK_TAB && !bShift && !bControl && !m_bAutoIndent )
+ {
+ if ( Shift(false) ) return true;
+ }
+ if ( event.param == VK_TAB && bShift && !bControl && !m_bAutoIndent )
+ {
+ if ( Shift(true) ) return true;
+ }
+
+ if ( m_bEdit )
+ {
+ if ( event.param == VK_LEFT )
+ {
+ MoveChar(-1, bControl, bShift);
+ return true;
+ }
+ if ( event.param == VK_RIGHT )
+ {
+ MoveChar(1, bControl, bShift);
+ return true;
+ }
+ if ( event.param == VK_UP )
+ {
+ MoveLine(-1, bControl, bShift);
+ return true;
+ }
+ if ( event.param == VK_DOWN )
+ {
+ MoveLine(1, bControl, bShift);
+ return true;
+ }
+
+ if ( event.param == VK_PRIOR ) // PageUp ?
+ {
+ MoveLine(-(m_lineVisible-1), bControl, bShift);
+ return true;
+ }
+ if ( event.param == VK_NEXT ) // PageDown ?
+ {
+ MoveLine(m_lineVisible-1, bControl, bShift);
+ return true;
+ }
+ }
+ else
+ {
+ if ( event.param == VK_LEFT ||
+ event.param == VK_UP )
+ {
+ Scroll(m_lineFirst-1, true);
+ return true;
+ }
+ if ( event.param == VK_RIGHT ||
+ event.param == VK_DOWN )
+ {
+ Scroll(m_lineFirst+1, true);
+ return true;
+ }
+
+ if ( event.param == VK_PRIOR ) // PageUp ?
+ {
+ Scroll(m_lineFirst-(m_lineVisible-1), true);
+ return true;
+ }
+ if ( event.param == VK_NEXT ) // PageDown ?
+ {
+ Scroll(m_lineFirst+(m_lineVisible-1), true);
+ return true;
+ }
+ }
+
+ if ( event.param == VK_HOME )
+ {
+ MoveHome(bControl, bShift);
+ return true;
+ }
+ if ( event.param == VK_END )
+ {
+ MoveEnd(bControl, bShift);
+ return true;
+ }
+
+ if ( event.param == VK_BACK ) // backspace ( <- ) ?
+ {
+ Delete(-1);
+ SendModifEvent();
+ return true;
+ }
+ if ( event.param == VK_DELETE )
+ {
+ Delete(1);
+ SendModifEvent();
+ return true;
+ }
+
+ if ( event.param == VK_RETURN )
+ {
+ Insert('\n');
+ SendModifEvent();
+ return true;
+ }
+ if ( event.param == VK_TAB )
+ {
+ Insert('\t');
+ SendModifEvent();
+ return true;
+ }
+ }
+
+ if ( event.event == EVENT_CHAR && m_bFocus )
+ {
+ if ( event.param >= ' ' && event.param <= 255 )
+ {
+ Insert((char)event.param);
+ SendModifEvent();
+ return true;
+ }
+ }
+
+ if ( event.event == EVENT_FOCUS )
+ {
+ if ( event.param == m_eventMsg )
+ {
+ m_bFocus = true;
+ }
+ else
+ {
+ m_bFocus = false;
+ }
+ }
+
+ if ( event.event == EVENT_LBUTTONDOWN )
+ {
+ m_mouseFirstPos = event.pos;
+ m_mouseLastPos = event.pos;
+ if ( Detect(event.pos) )
+ {
+ if ( event.pos.x < m_pos.x+m_dim.x-(m_bMulti?MARGX+SCROLL_WIDTH:0.0f) )
+ {
+ MouseClick(event.pos);
+ if ( m_bEdit || m_bHilite ) m_bCapture = true;
+ }
+ m_bFocus = true;
+ }
+ else
+ {
+ m_bFocus = false;
+ }
+ }
+
+ if ( event.event == EVENT_MOUSEMOVE && m_bCapture )
+ {
+ m_mouseLastPos = event.pos;
+ MouseMove(event.pos);
+ }
+
+ if ( event.event == EVENT_FRAME && m_bCapture )
+ {
+ MouseMove(m_mouseLastPos);
+ }
+
+ if ( event.event == EVENT_LBUTTONUP )
+ {
+ if ( Detect(event.pos) )
+ {
+ if ( event.pos.x < m_pos.x+m_dim.x-(m_bMulti?MARGX+SCROLL_WIDTH:0.0f) )
+ {
+ MouseRelease(m_mouseFirstPos);
+ }
+ }
+ if ( m_bCapture )
+ {
+ if ( m_timeLastClick+DELAY_DBCLICK > m_time ) // double-click ?
+ {
+ MouseDoubleClick(event.pos);
+ }
+ m_timeLastClick = m_time;
+ m_bCapture = false;
+ }
+ }
+
+ return true;
+}
+
+
+// Sends an event to indicate that the text was modified.
+
+void CEdit::SendModifEvent()
+{
+ Event newEvent;
+
+ m_event->MakeEvent(newEvent, m_eventMsg);
+ m_event->AddEvent(newEvent);
+}
+
+
+// Detects whether the mouse is over a hyperlink character.
+
+bool CEdit::IsLinkPos(Math::Point pos)
+{
+ int i;
+
+ if ( m_format == 0 ) return false;
+
+ i = MouseDetect(pos);
+ if ( i == -1 ) return false;
+ if ( i >= m_len ) return false;
+
+ if ( (m_format[i]&COLOR_MASK) == COLOR_LINK ) return true;
+ return false;
+}
+
+
+// Positions the cursor after a double click.
+
+void CEdit::MouseDoubleClick(Math::Point mouse)
+{
+ int i, character;
+
+ if ( m_bMulti ) // Multi-line?
+ {
+ i = MouseDetect(mouse);
+ if ( i == -1 ) return;
+
+ while ( i > 0 )
+ {
+ character = (unsigned char)m_text[i-1];
+ if ( !IsWord(character) ) break;
+ i --;
+ }
+ m_cursor2 = i;
+
+ while ( i < m_len )
+ {
+ character = (unsigned char)m_text[i];
+ if ( !IsWord(character) ) break;
+ i ++;
+ }
+ m_cursor1 = i;
+ }
+ else // single-line?
+ {
+ m_cursor2 = 0;
+ m_cursor1 = m_len; // selects all
+ }
+
+ m_bUndoForce = true;
+
+ Justif();
+ ColumnFix();
+}
+
+// Positions the cursor when clicked.
+
+void CEdit::MouseClick(Math::Point mouse)
+{
+ int i;
+
+ i = MouseDetect(mouse);
+ if ( i == -1 ) return;
+
+ if ( m_bEdit || m_bHilite )
+ {
+ m_cursor1 = i;
+ m_cursor2 = i;
+ m_bUndoForce = true;
+ m_timeBlink = 0.0f; // lights the cursor immediately
+ ColumnFix();
+ }
+}
+
+// Positions the cursor when clicked released.
+
+void CEdit::MouseRelease(Math::Point mouse)
+{
+ int i, j, rank;
+
+ i = MouseDetect(mouse);
+ if ( i == -1 ) return;
+
+ if ( !m_bEdit )
+ {
+ if ( m_format != 0 && i < m_len && m_cursor1 == m_cursor2 &&
+ (m_format[i]&COLOR_MASK) == COLOR_LINK )
+ {
+ rank = -1;
+ for ( j=0 ; j<=i ; j++ )
+ {
+ if ( (j == 0 || (m_format[j-1]&COLOR_MASK) != COLOR_LINK) &&
+ (m_format[j+0]&COLOR_MASK) == COLOR_LINK )
+ {
+ rank ++;
+ }
+ }
+ HyperJump(m_link[rank].name, m_link[rank].marker);
+ }
+ }
+}
+
+// Positions the cursor after movement.
+
+void CEdit::MouseMove(Math::Point mouse)
+{
+ int i;
+
+ if ( m_bMulti &&
+ m_timeLastScroll+DELAY_SCROLL <= m_time )
+ {
+ if ( mouse.y > m_pos.y+m_dim.y ) // above?
+ {
+ Scroll(m_lineFirst-1, false);
+ mouse.y = m_pos.y+m_dim.y-MARGY-m_lineHeight/2.0f;
+ }
+ if ( mouse.y < m_pos.y ) // lower?
+ {
+ Scroll(m_lineFirst+1, false);
+ mouse.y = m_pos.y+m_dim.y-MARGY-m_lineVisible*m_lineHeight+m_lineHeight/2.0f;
+ }
+ m_timeLastScroll = m_time;
+ }
+
+ i = MouseDetect(mouse);
+ if ( i != -1 )
+ {
+ m_cursor1 = i;
+ m_bUndoForce = true;
+ m_timeBlink = 0.0f; // lights the cursor immediately
+ ColumnFix();
+ }
+}
+
+// Positions the cursor when clicked.
+
+int CEdit::MouseDetect(Math::Point mouse)
+{
+ Math::Point pos;
+ float indentLength, offset, size;
+ int i, len, c;
+ bool bTitle;
+
+ if ( m_bAutoIndent )
+ {
+ indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType)
+ * m_engine->RetEditIndentValue();
+ }
+
+ pos.y = m_pos.y+m_dim.y-m_lineHeight-(m_bMulti?MARGY:MARGY1);
+ for ( i=m_lineFirst ; i<m_lineTotal ; i++ )
+ {
+ bTitle = ( m_format != 0 && (m_format[m_lineOffset[i]]&TITLE_MASK) == TITLE_BIG );
+
+ if ( i >= m_lineFirst+m_lineVisible ) break;
+
+ pos.x = m_pos.x+(10.0f/640.0f);
+ if ( m_bAutoIndent )
+ {
+ pos.x += indentLength*m_lineIndent[i];
+ }
+ offset = mouse.x-pos.x;
+
+ if ( bTitle ) pos.y -= m_lineHeight;
+
+ if ( mouse.y > pos.y )
+ {
+ len = m_lineOffset[i+1] - m_lineOffset[i];
+
+ if ( m_format == 0 )
+ {
+ c = m_engine->RetText()->Detect(m_text+m_lineOffset[i],
+ len, offset, m_fontSize,
+ m_fontStretch, m_fontType);
+ }
+ else
+ {
+ size = m_fontSize;
+ if ( bTitle ) size *= BIG_FONT;
+
+ c = m_engine->RetText()->Detect(m_text+m_lineOffset[i],
+ m_format+m_lineOffset[i],
+ len, offset, size,
+ m_fontStretch);
+ }
+ return m_lineOffset[i]+c;
+ }
+
+ if ( bTitle ) i ++;
+ pos.y -= m_lineHeight;
+ }
+ return -1;
+}
+
+
+// Clears all history.
+
+void CEdit::HyperFlush()
+{
+ m_historyTotal = 0;
+ m_historyCurrent = -1;
+}
+
+// Indicates which is the home page.
+
+void CEdit::HyperHome(char *filename)
+{
+ HyperFlush();
+ HyperAdd(filename, 0);
+}
+
+// Performs a hyper jump through a link.
+
+void CEdit::HyperJump(char *name, char *marker)
+{
+ char filename[100];
+ char sMarker[100];
+ int i, line, pos;
+
+ if ( m_historyCurrent >= 0 )
+ {
+ m_history[m_historyCurrent].firstLine = m_lineFirst;
+ }
+
+ strcpy(sMarker, marker);
+
+//? sprintf(filename, "help\\%s.txt", name);
+ if ( name[0] == '%' )
+ {
+ UserDir(filename, name, "");
+ strcat(filename, ".txt");
+ }
+ else
+ {
+ sprintf(filename, "help\\%s.txt", name);
+ }
+ if ( ReadText(filename) )
+ {
+ Justif();
+
+ line = 0;
+ for ( i=0 ; i<m_markerTotal ; i++ )
+ {
+ if ( strcmp(sMarker, m_marker[i].name) == 0 )
+ {
+ pos = m_marker[i].pos;
+ for ( i=0 ; i<m_lineTotal ; i++ )
+ {
+ if ( pos >= m_lineOffset[i] )
+ {
+ line = i;
+ }
+ }
+ break;
+ }
+ }
+
+ SetFirstLine(line);
+ HyperAdd(filename, line);
+ }
+}
+
+// Adds text to the history of visited.
+
+bool CEdit::HyperAdd(char *filename, int firstLine)
+{
+ if ( m_historyCurrent >= EDITHISTORYMAX-1 ) return false;
+
+ m_historyCurrent ++;
+ strcpy(m_history[m_historyCurrent].filename, filename);
+ m_history[m_historyCurrent].firstLine = firstLine;
+
+ m_historyTotal = m_historyCurrent+1;
+ return true;
+}
+
+// Indicates whether a button EVENT_HYPER_ * is active or not.
+
+bool CEdit::HyperTest(EventMsg event)
+{
+ if ( event == EVENT_HYPER_HOME )
+ {
+ return ( m_historyCurrent > 0 );
+ }
+
+ if ( event == EVENT_HYPER_PREV )
+ {
+ return ( m_historyCurrent > 0 );
+ }
+
+ if ( event == EVENT_HYPER_NEXT )
+ {
+ return ( m_historyCurrent < m_historyTotal-1 );
+ }
+
+ return false;
+}
+
+// Performs the action corresponding to a button EVENT_HYPER_ *.
+
+bool CEdit::HyperGo(EventMsg event)
+{
+ if ( !HyperTest(event) ) return false;
+
+ m_history[m_historyCurrent].firstLine = m_lineFirst;
+
+ if ( event == EVENT_HYPER_HOME )
+ {
+ m_historyCurrent = 0;
+ }
+
+ if ( event == EVENT_HYPER_PREV )
+ {
+ m_historyCurrent --;
+ }
+
+ if ( event == EVENT_HYPER_NEXT )
+ {
+ m_historyCurrent ++;
+ }
+
+ ReadText(m_history[m_historyCurrent].filename);
+ Justif();
+ SetFirstLine(m_history[m_historyCurrent].firstLine);
+ return true;
+}
+
+
+// Draw the editable line.
+
+void CEdit::Draw()
+{
+ Math::Point pos, ppos, dim, start, end;
+ float size, indentLength;
+ int i, j, beg, len, c1, c2, o1, o2, eol, iIndex, line;
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return;
+
+ if ( m_state & STATE_SHADOW )
+ {
+ DrawShadow(m_pos, m_dim);
+ }
+
+ pos.x = m_pos.x;
+ pos.y = m_pos.y;
+ dim.x = m_dim.x;
+ if ( !m_bInsideScroll ) dim.x -= m_bMulti?SCROLL_WIDTH:0.0f;
+ dim.y = m_dim.y;
+ DrawBack(pos, dim); // background
+
+ // Displays all lines.
+ c1 = m_cursor1;
+ c2 = m_cursor2;
+ if ( c1 > c2 ) Math::Swap(c1, c2); // always c1 <= c2
+
+ if ( m_bInsideScroll )
+ {
+ dim.x -= m_bMulti?SCROLL_WIDTH:0.0f + (1.0f/640.0f);
+ }
+
+ if ( m_bAutoIndent )
+ {
+ indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType)
+ * m_engine->RetEditIndentValue();
+ }
+
+ pos.y = m_pos.y+m_dim.y-m_lineHeight-(m_bMulti?MARGY:MARGY1);
+ for ( i=m_lineFirst ; i<m_lineTotal ; i++ )
+ {
+ if ( i == m_lineFirst && i < m_lineTotal-1 &&
+ m_lineOffset[i] == m_lineOffset[i+1] )
+ {
+ pos.y -= m_lineHeight; // Double jump line \b;
+ i ++;
+ }
+
+ if ( i >= m_lineFirst+m_lineVisible ) break;
+
+ pos.x = m_pos.x+(10.0f/640.0f);
+ if ( m_bAutoIndent )
+ {
+ for ( j=0 ; j<m_lineIndent[i] ; j++ )
+ {
+ char s = '\t'; // line | dotted
+ m_engine->RetText()->DrawText(&s, 1, pos, 1.0f, 1, m_fontSize, m_fontStretch, m_fontType, 0);
+ pos.x += indentLength;
+ }
+ }
+
+ beg = m_lineOffset[i];
+ len = m_lineOffset[i+1] - m_lineOffset[i];
+
+ ppos = pos;
+ size = m_fontSize;
+
+ // Headline \b;?
+ if ( beg+len < m_len && m_format != 0 &&
+ (m_format[beg]&TITLE_MASK) == TITLE_BIG )
+ {
+ start.x = ppos.x-MARGX;
+ end.x = dim.x-MARGX*2.0f;
+ start.y = ppos.y-(m_bMulti?0.0f:MARGY1)-m_lineHeight*(BIG_FONT-1.0f);
+ end.y = m_lineHeight*BIG_FONT;
+ DrawPart(start, end, 2); // blue gradient background ->
+
+ size *= BIG_FONT;
+ ppos.y -= m_lineHeight*(BIG_FONT-1.0f);
+ }
+
+ // As \t;?
+ if ( beg+len < m_len && m_format != 0 &&
+ (m_format[beg]&TITLE_MASK) == TITLE_NORM )
+ {
+ start.x = ppos.x-MARGX;
+ end.x = dim.x-MARGX*2.0f;
+ start.y = ppos.y-(m_bMulti?0.0f:MARGY1);
+ end.y = m_lineHeight;
+ DrawPart(start, end, 2); // blue gradient background ->
+ }
+
+ // Subtitle \s;?
+ if ( beg+len < m_len && m_format != 0 &&
+ (m_format[beg]&TITLE_MASK) == TITLE_LITTLE )
+ {
+ start.x = ppos.x-MARGX;
+ end.x = dim.x-MARGX*2.0f;
+ start.y = ppos.y-(m_bMulti?0.0f:MARGY1);
+ end.y = m_lineHeight;
+ DrawPart(start, end, 3); // yellow background gradient ->
+ }
+
+ // Table \tab;?
+ if ( beg+len < m_len && m_format != 0 &&
+ (m_format[beg]&COLOR_MASK) == COLOR_TABLE )
+ {
+ start.x = ppos.x-MARGX;
+ end.x = dim.x-MARGX*2.0f;
+ start.y = ppos.y-(m_bMulti?0.0f:MARGY1);
+ end.y = m_lineHeight;
+ DrawPart(start, end, 11); // fond orange d�grad� ->
+ }
+
+ // Image \image; ?
+ if ( beg+len < m_len && m_format != 0 &&
+ (m_format[beg]&IMAGE_MASK) != 0 )
+ {
+ line = 1;
+ while ( true ) // includes the image slices
+ {
+ if ( i+line >= m_lineTotal ||
+ i+line >= m_lineFirst+m_lineVisible ||
+ (m_format[beg+line]&IMAGE_MASK) == 0 ) break;
+ line ++;
+ }
+
+ iIndex = m_text[beg]; // character = index in m_image
+ pos.y -= m_lineHeight*(line-1);
+ DrawImage(pos, m_image[iIndex].name,
+ m_image[iIndex].width*(m_fontSize/SMALLFONT),
+ m_image[iIndex].offset, m_image[iIndex].height*line, line);
+ pos.y -= m_lineHeight;
+ i += line-1;
+ continue;
+ }
+
+ if ( ((m_bEdit && m_bFocus && m_bHilite) ||
+ (!m_bEdit && m_bHilite) ) &&
+ c1 != c2 && beg <= c2 && beg+len >= c1 ) // selected area?
+ {
+ o1 = c1; if ( o1 < beg ) o1 = beg;
+ o2 = c2; if ( o2 > beg+len ) o2 = beg+len;
+
+ if ( m_format == 0 )
+ {
+ start.x = ppos.x+m_engine->RetText()->RetStringWidth(m_text+beg, o1-beg, size, m_fontStretch, m_fontType);
+ end.x = m_engine->RetText()->RetStringWidth(m_text+o1, o2-o1, size, m_fontStretch, m_fontType);
+ }
+ else
+ {
+ start.x = ppos.x+m_engine->RetText()->RetStringWidth(m_text+beg, m_format+beg, o1-beg, size, m_fontStretch);
+ end.x = m_engine->RetText()->RetStringWidth(m_text+o1, m_format+o1, o2-o1, size, m_fontStretch);
+ }
+
+ start.y = ppos.y-(m_bMulti?0.0f:MARGY1);
+ end.y = m_lineHeight;
+ if ( m_format != 0 && (m_format[beg]&TITLE_MASK) == TITLE_BIG ) end.y *= BIG_FONT;
+ DrawPart(start, end, 1); // plain yellow background
+ }
+
+ eol = 16; // >
+ if ( len > 0 && m_text[beg+len-1] == '\n' )
+ {
+ len --; // does not display the '\ n'
+ eol = 0; // nothing
+ }
+ if ( beg+len >= m_len )
+ {
+ eol = 2; // square (eot)
+ }
+ if ( !m_bMulti || !m_bDisplaySpec ) eol = 0;
+ if ( m_format == 0 )
+ {
+ m_engine->RetText()->DrawText(m_text+beg, len, ppos, m_dim.x, 1, size, m_fontStretch, m_fontType, eol);
+ }
+ else
+ {
+ m_engine->RetText()->DrawText(m_text+beg, m_format+beg, len, ppos, m_dim.x, 1, size, m_fontStretch, eol);
+ }
+
+ pos.y -= m_lineHeight;
+
+ if ( i < m_lineTotal-2 && m_lineOffset[i+1] == m_lineOffset[i+2] )
+ {
+ pos.y -= m_lineHeight; // double jump line \b;
+ i ++;
+ }
+ }
+
+ // Shows the cursor.
+ if ( (m_bEdit && m_bFocus && m_bHilite && Math::Mod(m_timeBlink, 1.0f) <= 0.5f) ) // it blinks
+ {
+ pos.y = m_pos.y+m_dim.y-m_lineHeight-(m_bMulti?MARGY:MARGY1*2.0f);
+ for ( i=m_lineFirst ; i<m_lineTotal ; i++ )
+ {
+ if ( i == m_lineTotal-1 || m_cursor1 < m_lineOffset[i+1] )
+ {
+ pos.x = m_pos.x+(10.0f/640.0f);
+ if ( m_bAutoIndent )
+ {
+ pos.x += indentLength*m_lineIndent[i];
+ }
+
+ len = m_cursor1 - m_lineOffset[i];
+
+ if ( m_format == 0 )
+ {
+ m_engine->RetText()->DimText(m_text+m_lineOffset[i], len,
+ pos, 1, size,
+ m_fontStretch, m_fontType,
+ start, end);
+ }
+ else
+ {
+ m_engine->RetText()->DimText(m_text+m_lineOffset[i],
+ m_format+m_lineOffset[i],
+ len, pos, 1, size,
+ m_fontStretch,
+ start, end);
+ }
+
+ pos.x = end.x;
+ break;
+ }
+ pos.y -= m_lineHeight;
+ }
+ pos.x -= 1.0f/640.0f;
+ dim.x = 2.0f/640.0f;
+ dim.y = m_lineHeight;
+ DrawPart(pos, dim, 0); // red
+ }
+
+ if ( m_scroll != 0 && !m_bGeneric )
+ {
+ m_scroll->Draw();
+ }
+}
+
+// Draw an image part.
+
+void CEdit::DrawImage(Math::Point pos, char *name, float width,
+ float offset, float height, int nbLine)
+{
+ Math::Point uv1, uv2, dim;
+ float dp;
+ char filename[100];
+
+//? sprintf(filename, "diagram\\%s.bmp", name);
+ UserDir(filename, name, "diagram");
+ strcat(filename, ".bmp");
+
+ m_engine->SetTexture(filename);
+ m_engine->SetState(D3DSTATENORMAL);
+
+ uv1.x = 0.0f;
+ uv2.x = 1.0f;
+ uv1.y = offset;
+ uv2.y = offset+height;
+
+ dp = 0.5f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+
+ dim.x = width;
+ dim.y = m_lineHeight*nbLine;
+ DrawIcon(pos, dim, uv1, uv2);
+}
+
+// Draw the background.
+
+void CEdit::DrawBack(Math::Point pos, Math::Point dim)
+{
+ Math::Point uv1,uv2, corner;
+ float dp;
+
+ if ( m_bGeneric ) return;
+
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+
+ if ( m_bMulti )
+ {
+ uv1.x = 128.0f/256.0f; // light blue
+ uv1.y = 64.0f/256.0f;
+ uv2.x = 160.0f/256.0f;
+ uv2.y = 96.0f/256.0f;
+ }
+ else
+ {
+ uv1.x = 160.0f/256.0f; // medium blue
+ uv1.y = 192.0f/256.0f;
+ uv2.x = 192.0f/256.0f;
+ uv2.y = 224.0f/256.0f;
+ }
+ if ( m_icon == 1 )
+ {
+ uv1.x = 192.0f/256.0f; // orange
+ uv1.y = 96.0f/256.0f;
+ uv2.x = 224.0f/256.0f;
+ uv2.y = 128.0f/256.0f;
+ }
+
+ dp = 0.5f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+
+ if ( m_bMulti )
+ {
+ corner.x = 10.0f/640.0f;
+ corner.y = 10.0f/480.0f;
+ DrawIcon(pos, dim, uv1, uv2, corner, 8.0f/256.0f);
+ }
+ else
+ {
+ DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f);
+ }
+}
+
+// Draws an icon background.
+
+void CEdit::DrawPart(Math::Point pos, Math::Point dim, int icon)
+{
+ Math::Point uv1, uv2;
+ float dp;
+
+#if _POLISH
+ m_engine->SetTexture("textp.tga");
+#else
+ m_engine->SetTexture("text.tga");
+#endif
+ m_engine->SetState(D3DSTATENORMAL);
+
+ uv1.x = (16.0f/256.0f)*(icon%16);
+ uv1.y = (240.0f/256.0f);
+ uv2.x = (16.0f/256.0f)+uv1.x;
+ uv2.y = (16.0f/256.0f)+uv1.y;
+
+ dp = 0.5f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+
+ DrawIcon(pos, dim, uv1, uv2);
+}
+
+
+// Give the text to edit.
+
+void CEdit::SetText(char *text, bool bNew)
+{
+ int i, j, font;
+ bool bBOL;
+
+ if ( !bNew ) UndoMemorize(OPERUNDO_SPEC);
+
+ m_len = strlen(text);
+ if ( m_len > m_maxChar ) m_len = m_maxChar;
+
+ if ( m_format == 0 )
+ {
+ if ( m_bAutoIndent )
+ {
+ j = 0;
+ bBOL = true;
+ for ( i=0 ; i<m_len ; i++ )
+ {
+ if ( text[i] == '\t' )
+ {
+ if ( !bBOL ) m_text[j++] = ' ';
+ continue; // removes tabs
+ }
+ bBOL = ( text[i] == '\n' );
+
+ m_text[j++] = text[i];
+ }
+ m_len = j;
+ }
+ else
+ {
+ strncpy(m_text, text, m_len);
+ }
+ }
+ else
+ {
+ font = m_fontType;
+ j = 0;
+ bBOL = true;
+ for ( i=0 ; i<m_len ; i++ )
+ {
+ if ( m_bAutoIndent )
+ {
+ if ( text[i] == '\t' )
+ {
+ if ( !bBOL )
+ {
+ m_text[j] = ' ';
+ m_format[j] = font;
+ j ++;
+ }
+ continue; // removes tabs
+ }
+ bBOL = ( text[i] == '\n' );
+ }
+
+ if ( text[i] == '\\' && text[i+2] == ';' )
+ {
+ if ( text[i+1] == 'n' ) // normal ?
+ {
+ font &= ~FONT_MASK;
+ font |= FONT_COLOBOT;
+ i += 2;
+ }
+ else if ( text[i+1] == 'c' ) // cbot ?
+ {
+ font &= ~FONT_MASK;
+ font |= FONT_COURIER;
+ i += 2;
+ }
+ else if ( text[i+1] == 'b' ) // big title ?
+ {
+ font &= ~TITLE_MASK;
+ font |= TITLE_BIG;
+ i += 2;
+ }
+ else if ( text[i+1] == 't' ) // title ?
+ {
+ font &= ~TITLE_MASK;
+ font |= TITLE_NORM;
+ i += 2;
+ }
+ else if ( text[i+1] == 's' ) // subtitle ?
+ {
+ font &= ~TITLE_MASK;
+ font |= TITLE_LITTLE;
+ i += 2;
+ }
+ }
+ else
+ {
+ m_text[j] = text[i];
+ m_format[j] = font;
+ j ++;
+
+ font &= ~TITLE_MASK; // reset title
+ }
+ }
+ m_len = j;
+ }
+
+ if ( bNew ) UndoFlush();
+
+ m_cursor1 = 0;
+ m_cursor2 = 0; // cursor to the beginning
+ Justif();
+ ColumnFix();
+}
+
+// Returns a pointer to the edited text.
+
+char* CEdit::RetText()
+{
+ m_text[m_len] = 0;
+ return m_text;
+}
+
+// Returns the edited text.
+
+void CEdit::GetText(char *buffer, int max)
+{
+ if ( m_len < max ) max = m_len;
+ if ( m_len > max ) max = max-1;
+
+ strncpy(buffer, m_text, max);
+ buffer[max] = 0;
+}
+
+// Returns the length of the text.
+
+int CEdit::RetTextLength()
+{
+ return m_len;
+}
+
+
+
+// Returns a name in a command.
+// \x nom1 nom2 nom3;
+
+void GetNameParam(char *cmd, int rank, char *buffer)
+{
+ int i;
+
+ for ( i=0 ; i<rank ; i++ )
+ {
+ while ( *cmd != ' ' && *cmd != ';' )
+ {
+ cmd ++;
+ }
+ if ( *cmd != ';' ) cmd ++;
+ }
+
+ while ( *cmd != ' ' && *cmd != ';' )
+ {
+ *buffer++ = *cmd++;
+ }
+ *buffer = 0;
+}
+
+// Returns a number of a command.
+// \x nom n1 n2;
+
+int RetValueParam(char *cmd, int rank)
+{
+ int n, i;
+
+ for ( i=0 ; i<rank ; i++ )
+ {
+ while ( *cmd != ' ' && *cmd != ';' )
+ {
+ cmd ++;
+ }
+ if ( *cmd != ';' ) cmd ++;
+ }
+
+ sscanf(cmd, "%d", &n);
+ return n;
+}
+
+// Frees all images.
+
+void CEdit::FreeImage()
+{
+ char filename[100];
+ int i;
+
+ for ( i=0 ; i<m_imageTotal ; i++ )
+ {
+//? sprintf(filename, "diagram\\%s.bmp", m_image[i].name);
+ UserDir(filename, m_image[i].name, "diagram");
+ strcat(filename, ".bmp");
+ m_engine->FreeTexture(filename);
+ }
+}
+
+// Reads the texture of an image.
+
+void CEdit::LoadImage(char *name)
+{
+ char filename[100];
+
+//? sprintf(filename, "diagram\\%s.bmp", name);
+ UserDir(filename, name, "diagram");
+ strcat(filename, ".bmp");
+ m_engine->LoadTexture(filename);
+}
+
+// Read from a text file.
+
+bool CEdit::ReadText(char *filename, int addSize)
+{
+ FILE *file = NULL;
+ char *buffer;
+ int len, i, j, n, font, iIndex, iLines, iCount, iLink, res;
+ char iName[50];
+ char text[50];
+ float iWidth;
+ KeyRank key;
+ bool bInSoluce, bBOL;
+
+ if ( filename[0] == 0 ) return false;
+ file = fopen(filename, "rb");
+ if ( file == NULL ) return false;
+
+ fseek(file, 0, SEEK_END);
+ len = ftell(file);
+ fseek(file, 0, SEEK_SET);
+
+ m_maxChar = len+addSize+100;
+ m_len = len;
+ m_cursor1 = 0;
+ m_cursor2 = 0;
+
+ FreeImage();
+ delete m_text;
+ m_text = (char*)malloc(sizeof(char)*(m_maxChar+1));
+ buffer = (char*)malloc(sizeof(char)*(m_maxChar+1));
+ fread(buffer, 1, len, file);
+
+ if ( m_format != 0 )
+ {
+ delete m_format;
+ m_format = (char*)malloc(sizeof(char)*m_maxChar);
+ }
+
+ fclose(file);
+
+ bInSoluce = false;
+ font = m_fontType;
+ iIndex = 0;
+ iLink = 0;
+ m_imageTotal = 0;
+ m_markerTotal = 0;
+ i = j = 0;
+ bBOL = true;
+ while ( i < m_len )
+ {
+ if ( m_bAutoIndent )
+ {
+ if ( buffer[i] == '\t' )
+ {
+ if ( !bBOL )
+ {
+ m_text[j] = buffer[i];
+ if ( m_format != 0 ) m_format[j] = font;
+ j ++;
+ }
+ i ++;
+ continue; // removes the tabs
+ }
+ bBOL = ( buffer[i] == '\n' || buffer[i] == '\r' );
+ }
+
+ if ( buffer[i] == '\r' ) // removes \ r
+ {
+ i ++;
+ }
+ else if ( m_format != 0 && buffer[i] == '\\' && buffer[i+2] == ';' )
+ {
+ if ( buffer[i+1] == 'n' ) // normal ?
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+ font &= ~FONT_MASK;
+ font |= FONT_COLOBOT;
+ }
+ i += 3;
+ }
+ else if ( buffer[i+1] == 'c' ) // cbot ?
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+ font &= ~FONT_MASK;
+ font |= FONT_COURIER;
+ }
+ i += 3;
+ }
+ else if ( buffer[i+1] == 'b' ) // big title ?
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+ font &= ~TITLE_MASK;
+ font |= TITLE_BIG;
+ }
+ i += 3;
+ }
+ else if ( buffer[i+1] == 't' ) // title ?
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+ font &= ~TITLE_MASK;
+ font |= TITLE_NORM;
+ }
+ i += 3;
+ }
+ else if ( buffer[i+1] == 's' ) // subtitle ?
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+ font &= ~TITLE_MASK;
+ font |= TITLE_LITTLE;
+ }
+ i += 3;
+ }
+ else if ( buffer[i+1] == 'l' ) // link ?
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+ font &= ~COLOR_MASK;
+ font |= COLOR_LINK;
+ }
+ i += 3;
+ }
+ else
+ {
+ i += 3;
+ }
+ }
+ else if ( m_format != 0 &&
+ buffer[i+0] == '\\' && // \u marker name; ?
+ buffer[i+1] == 'u' &&
+ buffer[i+2] == ' ' )
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+ if ( iLink < EDITLINKMAX )
+ {
+ GetNameParam(buffer+i+3, 0, m_link[iLink].name);
+ GetNameParam(buffer+i+3, 1, m_link[iLink].marker);
+ iLink ++;
+ }
+ font &= ~COLOR_MASK;
+ }
+ i += strchr(buffer+i, ';')-(buffer+i)+1;
+ }
+ else if ( m_format != 0 &&
+ buffer[i+0] == '\\' && // \m marker; ?
+ buffer[i+1] == 'm' &&
+ buffer[i+2] == ' ' )
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+ if ( m_markerTotal < EDITLINKMAX )
+ {
+ GetNameParam(buffer+i+3, 0, m_marker[m_markerTotal].name);
+ m_marker[m_markerTotal].pos = j;
+ m_markerTotal ++;
+ }
+ }
+ i += strchr(buffer+i, ';')-(buffer+i)+1;
+ }
+ else if ( m_format != 0 &&
+ buffer[i+0] == '\\' && // \image name lx ly; ?
+ buffer[i+1] == 'i' &&
+ buffer[i+2] == 'm' &&
+ buffer[i+3] == 'a' &&
+ buffer[i+4] == 'g' &&
+ buffer[i+5] == 'e' &&
+ buffer[i+6] == ' ' )
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+#if _DEMO
+ strcpy(iName, "demo");
+#else
+ GetNameParam(buffer+i+7, 0, iName);
+#endif
+//? iWidth = m_lineHeight*RetValueParam(buffer+i+7, 1);
+ iWidth = (float)RetValueParam(buffer+i+7, 1);
+ iWidth *= m_engine->RetText()->RetHeight(SMALLFONT, FONT_COLOBOT);
+ iLines = RetValueParam(buffer+i+7, 2);
+ LoadImage(iName);
+
+ // A part of image per line of text.
+ for ( iCount=0 ; iCount<iLines ; iCount++ )
+ {
+ strcpy(m_image[iIndex].name, iName);
+ m_image[iIndex].offset = (float)iCount/iLines;
+ m_image[iIndex].height = 1.0f/iLines;
+ m_image[iIndex].width = iWidth*0.75f;
+
+ m_text[j] = (char)(iIndex++); // as an index into m_image
+ m_format[j] = (unsigned char)IMAGE_MASK;
+ j ++;
+ }
+ }
+ i += strchr(buffer+i, ';')-(buffer+i)+1;
+ }
+ else if ( m_format != 0 &&
+ buffer[i+0] == '\\' && // \button; ?
+ buffer[i+1] == 'b' &&
+ buffer[i+2] == 'u' &&
+ buffer[i+3] == 't' &&
+ buffer[i+4] == 't' &&
+ buffer[i+5] == 'o' &&
+ buffer[i+6] == 'n' &&
+ buffer[i+7] == ' ' )
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+ m_text[j] = RetValueParam(buffer+i+8, 0);
+ m_format[j] = font|FONT_BUTTON;
+ j ++;
+ }
+ i += strchr(buffer+i, ';')-(buffer+i)+1;
+ }
+ else if ( m_format != 0 &&
+ buffer[i+0] == '\\' && // \token; ?
+ buffer[i+1] == 't' &&
+ buffer[i+2] == 'o' &&
+ buffer[i+3] == 'k' &&
+ buffer[i+4] == 'e' &&
+ buffer[i+5] == 'n' &&
+ buffer[i+6] == ';' )
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+ font &= ~COLOR_MASK;
+ font |= COLOR_TOKEN;
+ }
+ i += 7;
+ }
+ else if ( m_format != 0 &&
+ buffer[i+0] == '\\' && // \type; ?
+ buffer[i+1] == 't' &&
+ buffer[i+2] == 'y' &&
+ buffer[i+3] == 'p' &&
+ buffer[i+4] == 'e' &&
+ buffer[i+5] == ';' )
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+ font &= ~COLOR_MASK;
+ font |= COLOR_TYPE;
+ }
+ i += 6;
+ }
+ else if ( m_format != 0 &&
+ buffer[i+0] == '\\' && // \const; ?
+ buffer[i+1] == 'c' &&
+ buffer[i+2] == 'o' &&
+ buffer[i+3] == 'n' &&
+ buffer[i+4] == 's' &&
+ buffer[i+5] == 't' &&
+ buffer[i+6] == ';' )
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+ font &= ~COLOR_MASK;
+ font |= COLOR_CONST;
+ }
+ i += 7;
+ }
+ else if ( m_format != 0 &&
+ buffer[i+0] == '\\' && // \key; ?
+ buffer[i+1] == 'k' &&
+ buffer[i+2] == 'e' &&
+ buffer[i+3] == 'y' &&
+ buffer[i+4] == ';' )
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+ font &= ~COLOR_MASK;
+ font |= COLOR_KEY;
+ }
+ i += 5;
+ }
+ else if ( m_format != 0 &&
+ buffer[i+0] == '\\' && // \tab; ?
+ buffer[i+1] == 't' &&
+ buffer[i+2] == 'a' &&
+ buffer[i+3] == 'b' &&
+ buffer[i+4] == ';' )
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+ font |= COLOR_TABLE;
+ }
+ i += 5;
+ }
+ else if ( m_format != 0 &&
+ buffer[i+0] == '\\' && // \norm; ?
+ buffer[i+1] == 'n' &&
+ buffer[i+2] == 'o' &&
+ buffer[i+3] == 'r' &&
+ buffer[i+4] == 'm' &&
+ buffer[i+5] == ';' )
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+ font &= ~COLOR_MASK;
+ }
+ i += 6;
+ }
+ else if ( m_format != 0 &&
+ buffer[i+0] == '\\' && // \begin soluce; ?
+ buffer[i+1] == 'b' &&
+ buffer[i+2] == 's' &&
+ buffer[i+3] == ';' )
+ {
+ bInSoluce = true;
+ i += 4;
+ }
+ else if ( m_format != 0 &&
+ buffer[i+0] == '\\' && // \end soluce; ?
+ buffer[i+1] == 'e' &&
+ buffer[i+2] == 's' &&
+ buffer[i+3] == ';' )
+ {
+ bInSoluce = false;
+ i += 4;
+ }
+ else if ( m_format != 0 &&
+ buffer[i+0] == '\\' && // \key name; ?
+ buffer[i+1] == 'k' &&
+ buffer[i+2] == 'e' &&
+ buffer[i+3] == 'y' &&
+ buffer[i+4] == ' ' )
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+ if ( SearchKey(buffer+i+5, key) )
+ {
+ res = m_engine->RetKey(key, 0);
+ if ( res != 0 )
+ {
+ if ( GetResource(RES_KEY, res, iName) )
+ {
+ m_text[j] = ' ';
+ m_format[j] = font;
+ j ++;
+ n = 0;
+ while ( iName[n] != 0 )
+ {
+ m_text[j] = iName[n++];
+ m_format[j] = font;
+ j ++;
+ }
+ m_text[j] = ' ';
+ m_format[j] = font;
+ j ++;
+
+ res = m_engine->RetKey(key, 1);
+ if ( res != 0 )
+ {
+ if ( GetResource(RES_KEY, res, iName) )
+ {
+ GetResource(RES_TEXT, RT_KEY_OR, text);
+ n = 0;
+ while ( text[n] != 0 )
+ {
+ m_text[j] = text[n++];
+ m_format[j] = font&~COLOR_MASK;
+ j ++;
+ }
+ n = 0;
+ while ( iName[n] != 0 )
+ {
+ m_text[j] = iName[n++];
+ m_format[j] = font;
+ j ++;
+ }
+ m_text[j] = ' ';
+ m_format[j] = font;
+ j ++;
+ }
+ }
+ while ( buffer[i++] != ';' );
+ continue;
+ }
+ }
+ }
+ m_text[j] = '?';
+ m_format[j] = font;
+ j ++;
+ }
+ while ( buffer[i++] != ';' );
+ }
+ else
+ {
+ if ( m_bSoluce || !bInSoluce )
+ {
+ m_text[j] = buffer[i];
+ if ( m_format != 0 ) m_format[j] = font;
+ j ++;
+ }
+ i ++;
+
+ font &= ~TITLE_MASK; // reset title
+
+ if ( (font&COLOR_MASK) == COLOR_TABLE )
+ {
+ font &= ~COLOR_TABLE;
+ }
+ }
+ }
+ m_len = j;
+ m_imageTotal = iIndex;
+
+ delete buffer;
+
+ Justif();
+ ColumnFix();
+ return true;
+}
+
+// Writes all the text in a file.
+
+bool CEdit::WriteText(char *filename)
+{
+ FILE* file;
+ char buffer[1000+20];
+ int i, j, k, n;
+ float iDim;
+
+ if ( filename[0] == 0 ) return false;
+ file = fopen(filename, "wb");
+ if ( file == NULL ) return false;
+
+ if ( m_bAutoIndent )
+ {
+ iDim = m_dim.x;
+ m_dim.x = 1000.0f; // puts an infinite width!
+ Justif();
+ }
+
+ i = j = k = 0;
+ while ( m_text[i] != 0 && i < m_len )
+ {
+ if ( m_bAutoIndent && i == m_lineOffset[k] )
+ {
+ for ( n=0 ; n<m_lineIndent[k] ; n++ )
+ {
+ buffer[j++] = '\t';
+ }
+ k ++;
+ }
+
+ buffer[j++] = m_text[i];
+
+ if ( m_text[i] == '\n' )
+ {
+ buffer[j-1] = '\r';
+ buffer[j++] = '\n'; // \r\n (0x0D, 0x0A)
+ }
+
+ if ( j >= 1000-1 )
+ {
+ fwrite(buffer, 1, j, file);
+ j = 0;
+ }
+
+ i ++;
+ }
+ if ( j > 0 )
+ {
+ fwrite(buffer, 1, j, file);
+ }
+
+ fclose(file);
+
+ if ( m_bAutoIndent )
+ {
+ m_dim.x = iDim; // presents the initial width
+ Justif();
+ }
+
+ return true;
+}
+
+
+// Manage the number of max characters editable.
+
+void CEdit::SetMaxChar(int max)
+{
+ m_maxChar = max;
+ FreeImage();
+ delete m_text;
+ m_text = (char*)malloc(sizeof(char)*(m_maxChar+1));
+
+ if ( m_format != 0 )
+ {
+ delete m_format;
+ m_format = (char*)malloc(sizeof(char)*m_maxChar);
+ }
+
+ m_len = 0;
+ m_cursor1 = 0;
+ m_cursor2 = 0;
+ Justif();
+ UndoFlush();
+}
+
+int CEdit::RetMaxChar()
+{
+ return m_maxChar;
+}
+
+
+// Mode management "editable".
+
+void CEdit::SetEditCap(bool bMode)
+{
+ m_bEdit = bMode;
+}
+
+bool CEdit::RetEditCap()
+{
+ return m_bEdit;
+}
+
+// Mode management "hilitable" (that's the franch).
+
+void CEdit::SetHiliteCap(bool bEnable)
+{
+ m_bHilite = bEnable;
+}
+
+bool CEdit::RetHiliteCap()
+{
+ return m_bHilite;
+}
+
+// Lift in / out connection.
+
+void CEdit::SetInsideScroll(bool bInside)
+{
+ m_bInsideScroll = bInside;
+}
+
+bool CEdit::RetInsideScroll()
+{
+ return m_bInsideScroll;
+}
+
+// Specifies whether to display the links showing the solution.
+
+void CEdit::SetSoluceMode(bool bSoluce)
+{
+ m_bSoluce = bSoluce;
+}
+
+bool CEdit::RetSoluceMode()
+{
+ return m_bSoluce;
+}
+
+// Indicates whether the text is a defile that generic.
+
+void CEdit::SetGenericMode(bool bGeneric)
+{
+ m_bGeneric = bGeneric;
+}
+
+bool CEdit::RetGenericMode()
+{
+ return m_bGeneric;
+}
+
+
+// Management of automatic indentation mode with {}.
+
+void CEdit::SetAutoIndent(bool bMode)
+{
+ m_bAutoIndent = bMode;
+}
+
+bool CEdit::RetAutoIndent()
+{
+ return m_bAutoIndent;
+}
+
+
+
+// Moves the cursors.
+
+void CEdit::SetCursor(int cursor1, int cursor2)
+{
+ if ( cursor1 > m_len ) cursor1 = m_len;
+ if ( cursor2 > m_len ) cursor2 = m_len;
+
+ m_cursor1 = cursor1;
+ m_cursor2 = cursor2;
+ m_bUndoForce = true;
+ ColumnFix();
+}
+
+// Returns the sliders.
+
+void CEdit::GetCursor(int &cursor1, int &cursor2)
+{
+ cursor1 = m_cursor1;
+ cursor2 = m_cursor2;
+}
+
+
+// Displayed line modifies the first.
+
+void CEdit::SetFirstLine(int rank)
+{
+ Scroll(rank, true);
+}
+
+// Returns the first displayed line.
+
+int CEdit::RetFirstLine()
+{
+ if ( m_historyTotal > 0 )
+ {
+ if ( m_historyCurrent == 0 )
+ {
+ return m_lineFirst;
+ }
+ else
+ {
+ return m_history[0].firstLine;
+ }
+ }
+ return m_lineFirst;
+}
+
+
+// Shows the selected area.
+
+void CEdit::ShowSelect()
+{
+ int cursor1, cursor2, line;
+
+ if ( m_cursor1 < m_cursor2 )
+ {
+ cursor1 = m_cursor1;
+ cursor2 = m_cursor2;
+ }
+ else
+ {
+ cursor1 = m_cursor2;
+ cursor2 = m_cursor1;
+ }
+
+ line = RetCursorLine(cursor2);
+ if ( line >= m_lineFirst+m_lineVisible )
+ {
+ line -= m_lineVisible-1;
+ if ( line < 0 ) line = 0;
+ Scroll(line, false);
+ }
+
+ line = RetCursorLine(cursor1);
+ if ( line < m_lineFirst )
+ {
+ Scroll(line, false);
+ }
+}
+
+
+// Management of the display mode of special characters.
+
+void CEdit::SetDisplaySpec(bool bDisplay)
+{
+ m_bDisplaySpec = bDisplay;
+}
+
+bool CEdit::RetDisplaySpec()
+{
+ return m_bDisplaySpec;
+}
+
+
+// Multi-fonts mode management.
+
+void CEdit::SetMultiFont(bool bMulti)
+{
+ if ( bMulti )
+ {
+ delete m_format;
+ m_format = (char*)malloc(sizeof(char)*m_maxChar);
+ memset(m_format, 0, m_maxChar);
+ }
+ else
+ {
+ delete m_format;
+ m_format = 0;
+ }
+}
+
+bool CEdit::RetMultiFont()
+{
+ return ( m_format != 0 );
+}
+
+
+// Management of the character size.
+
+void CEdit::SetFontSize(float size)
+{
+ CControl::SetFontSize(size);
+
+ MoveAdjust();
+}
+
+
+// Moves according to the visible lift.
+
+void CEdit::Scroll()
+{
+ float value;
+
+ if ( m_scroll != 0 )
+ {
+ value = m_scroll->RetVisibleValue();
+ value *= m_lineTotal-m_lineVisible;
+ Scroll((int)(value+0.5f), true);
+ }
+}
+
+// Moves according to the visible lift.
+
+void CEdit::Scroll(int pos, bool bAdjustCursor)
+{
+ int max, line;
+
+ m_lineFirst = pos;
+
+ if ( m_lineFirst < 0 ) m_lineFirst = 0;
+
+ max = m_lineTotal-m_lineVisible;
+ if ( max < 0 ) max = 0;
+ if ( m_lineFirst > max ) m_lineFirst = max;
+
+ line = RetCursorLine(m_cursor1);
+
+ if ( bAdjustCursor && m_bEdit )
+ {
+ // Cursor too high?
+ if ( line < m_lineFirst )
+ {
+ MoveLine(m_lineFirst-line, false, false);
+ return;
+ }
+
+ // Cursor too low?
+ if ( line >= m_lineFirst+m_lineVisible )
+ {
+ MoveLine(m_lineFirst+m_lineVisible-line-1, false, false);
+ return;
+ }
+ }
+
+ Justif();
+}
+
+// Moves the cursor to the beginning of the line.
+
+void CEdit::MoveHome(bool bWord, bool bSelect)
+{
+ int begin, tab;
+
+ if ( bWord )
+ {
+ m_cursor1 = 0;
+ }
+ else
+ {
+ begin = m_cursor1;
+ while ( begin > 0 && m_text[begin-1] != '\n' )
+ {
+ begin --;
+ }
+
+ tab = begin;
+ while ( tab < m_len && (m_text[tab] == '\t' || m_text[tab] == ' ') )
+ {
+ tab ++;
+ }
+
+ if ( m_cursor1 == tab )
+ {
+ m_cursor1 = begin;
+ }
+ else
+ {
+ m_cursor1 = tab;
+ }
+ }
+ if ( !bSelect ) m_cursor2 = m_cursor1;
+
+ m_bUndoForce = true;
+ Justif();
+ ColumnFix();
+}
+
+// Moves the cursor to the end of the line.
+
+void CEdit::MoveEnd(bool bWord, bool bSelect)
+{
+ if ( bWord )
+ {
+ m_cursor1 = m_len;
+ }
+ else
+ {
+ while ( m_cursor1 < m_len && m_text[m_cursor1] != '\n' )
+ {
+ m_cursor1 ++;
+ }
+ }
+ if ( !bSelect ) m_cursor2 = m_cursor1;
+
+ m_bUndoForce = true;
+ Justif();
+ ColumnFix();
+}
+
+// Moves the cursor through characters.
+
+void CEdit::MoveChar(int move, bool bWord, bool bSelect)
+{
+ int character;
+
+ if ( move == -1 ) // back?
+ {
+ if ( bWord )
+ {
+ while ( m_cursor1 > 0 )
+ {
+ character = (unsigned char)m_text[m_cursor1-1];
+ if ( !IsSpace(character) ) break;
+ m_cursor1 --;
+ }
+
+ if ( m_cursor1 > 0 )
+ {
+ character = (unsigned char)m_text[m_cursor1-1];
+ if ( IsSpace(character) )
+ {
+ while ( m_cursor1 > 0 )
+ {
+ character = (unsigned char)m_text[m_cursor1-1];
+ if ( !IsSpace(character) ) break;
+ m_cursor1 --;
+ }
+ }
+ else if ( IsWord(character) )
+ {
+ while ( m_cursor1 > 0 )
+ {
+ character = (unsigned char)m_text[m_cursor1-1];
+ if ( !IsWord(character) ) break;
+ m_cursor1 --;
+ }
+ }
+ else if ( IsSep(character) )
+ {
+ while ( m_cursor1 > 0 )
+ {
+ character = (unsigned char)m_text[m_cursor1-1];
+ if ( !IsSep(character) ) break;
+ m_cursor1 --;
+ }
+ }
+ }
+ }
+ else
+ {
+ m_cursor1 --;
+ if ( m_cursor1 < 0 ) m_cursor1 = 0;
+ }
+ }
+
+ if ( move == 1 ) // advance?
+ {
+ if ( bWord )
+ {
+ if ( m_cursor1 < m_len )
+ {
+ character = (unsigned char)m_text[m_cursor1];
+ if ( IsSpace(character) )
+ {
+ while ( m_cursor1 < m_len )
+ {
+ character = (unsigned char)m_text[m_cursor1];
+ if ( !IsSpace(character) ) break;
+ m_cursor1 ++;
+ }
+ }
+ else if ( IsWord(character) )
+ {
+ while ( m_cursor1 < m_len )
+ {
+ character = (unsigned char)m_text[m_cursor1];
+ if ( !IsWord(character) ) break;
+ m_cursor1 ++;
+ }
+ }
+ else if ( IsSep(character) )
+ {
+ while ( m_cursor1 < m_len )
+ {
+ character = (unsigned char)m_text[m_cursor1];
+ if ( !IsSep(character) ) break;
+ m_cursor1 ++;
+ }
+ }
+ }
+
+ while ( m_cursor1 < m_len )
+ {
+ character = (unsigned char)m_text[m_cursor1];
+ if ( !IsSpace(character) ) break;
+ m_cursor1 ++;
+ }
+ }
+ else
+ {
+ m_cursor1 ++;
+ if ( m_cursor1 > m_len ) m_cursor1 = m_len;
+ }
+ }
+
+ if ( !bSelect ) m_cursor2 = m_cursor1;
+
+ m_bUndoForce = true;
+ Justif();
+ ColumnFix();
+}
+
+// Moves the cursor lines.
+
+void CEdit::MoveLine(int move, bool bWord, bool bSelect)
+{
+ float column, indentLength;
+ int i, line, c;
+
+ if ( move == 0 ) return;
+
+ for ( i=0 ; i>move ; i-- ) // back?
+ {
+ while ( m_cursor1 > 0 && m_text[m_cursor1-1] != '\n' )
+ {
+ m_cursor1 --;
+ }
+ if ( m_cursor1 != 0 )
+ {
+ m_cursor1 --;
+ while ( m_cursor1 > 0 )
+ {
+ if ( m_text[--m_cursor1] == '\n' )
+ {
+ m_cursor1 ++;
+ break;
+ }
+ }
+ }
+ }
+
+ for ( i=0 ; i<move ; i++ ) // advance?
+ {
+ while ( m_cursor1 < m_len )
+ {
+ if ( m_text[m_cursor1++] == '\n' )
+ {
+ break;
+ }
+ }
+ }
+
+ line = RetCursorLine(m_cursor1);
+
+ column = m_column;
+ if ( m_bAutoIndent )
+ {
+ indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType)
+ * m_engine->RetEditIndentValue();
+ column -= indentLength*m_lineIndent[line];
+ }
+
+ if ( m_format == 0 )
+ {
+ c = m_engine->RetText()->Detect(m_text+m_lineOffset[line],
+ m_lineOffset[line+1]-m_lineOffset[line],
+ column, m_fontSize,
+ m_fontStretch, m_fontType);
+ }
+ else
+ {
+ c = m_engine->RetText()->Detect(m_text+m_lineOffset[line],
+ m_format+m_lineOffset[line],
+ m_lineOffset[line+1]-m_lineOffset[line],
+ column, m_fontSize, m_fontStretch);
+ }
+
+ m_cursor1 = m_lineOffset[line]+c;
+ if ( !bSelect ) m_cursor2 = m_cursor1;
+
+ m_bUndoForce = true;
+ Justif();
+}
+
+// Sets the horizontal position.
+
+void CEdit::ColumnFix()
+{
+ float indentLength;
+ int line;
+
+ line = RetCursorLine(m_cursor1);
+
+ if ( m_format == 0 )
+ {
+ m_column = m_engine->RetText()->RetStringWidth
+ (
+ m_text+m_lineOffset[line],
+ m_cursor1-m_lineOffset[line],
+ m_fontSize, m_fontStretch, m_fontType
+ );
+ }
+ else
+ {
+ m_column = m_engine->RetText()->RetStringWidth
+ (
+ m_text+m_lineOffset[line],
+ m_format+m_lineOffset[line],
+ m_cursor1-m_lineOffset[line],
+ m_fontSize, m_fontStretch
+ );
+ }
+
+ if ( m_bAutoIndent )
+ {
+ indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType)
+ * m_engine->RetEditIndentValue();
+ m_column += indentLength*m_lineIndent[line];
+ }
+}
+
+
+// Cut the selected characters or entire line.
+
+bool CEdit::Cut()
+{
+ HGLOBAL hg;
+ char* text;
+ char c;
+ int c1, c2, start, len, i, j;
+
+ if ( !m_bEdit ) return false;
+
+ c1 = m_cursor1;
+ c2 = m_cursor2;
+ if ( c1 > c2 ) Math::Swap(c1, c2); // always c1 <= c2
+
+ if ( c1 == c2 )
+ {
+ while ( c1 > 0 )
+ {
+ if ( m_text[c1-1] == '\n' ) break;
+ c1 --;
+ }
+ while ( c2 < m_len )
+ {
+ c2 ++;
+ if ( m_text[c2-1] == '\n' ) break;
+ }
+ }
+
+ if ( c1 == c2 ) return false;
+
+ start = c1;
+ len = c2-c1;
+
+ if ( !(hg = GlobalAlloc(GMEM_DDESHARE, len*2+1)) )
+ {
+ return false;
+ }
+ if ( !(text = (char*)GlobalLock(hg)) )
+ {
+ GlobalFree(hg);
+ return false;
+ }
+
+ j = 0;
+ for ( i=start ; i<start+len ; i++ )
+ {
+ c = m_text[i];
+ if ( c == '\n' ) text[j++] = '\r';
+ text[j++] = c;
+ }
+ text[j] = 0;
+ GlobalUnlock(hg);
+
+ if ( !OpenClipboard(NULL) )
+ {
+ GlobalFree(hg);
+ return false;
+ }
+ if ( !EmptyClipboard() )
+ {
+ GlobalFree(hg);
+ return false;
+ }
+ if ( !SetClipboardData(CF_TEXT, hg) )
+ {
+ GlobalFree(hg);
+ return false;
+ }
+ CloseClipboard();
+
+ UndoMemorize(OPERUNDO_SPEC);
+ m_cursor1 = c1;
+ m_cursor2 = c2;
+ DeleteOne(0); // deletes the selected characters
+ Justif();
+ ColumnFix();
+ SendModifEvent();
+ return true;
+}
+
+// Copy the selected characters or entire line.
+
+bool CEdit::Copy()
+{
+ HGLOBAL hg;
+ char* text;
+ char c;
+ int c1, c2, start, len, i, j;
+
+ c1 = m_cursor1;
+ c2 = m_cursor2;
+ if ( c1 > c2 ) Math::Swap(c1, c2); // always c1 <= c2
+
+ if ( c1 == c2 )
+ {
+ while ( c1 > 0 )
+ {
+ if ( m_text[c1-1] == '\n' ) break;
+ c1 --;
+ }
+ while ( c2 < m_len )
+ {
+ c2 ++;
+ if ( m_text[c2-1] == '\n' ) break;
+ }
+ }
+
+ if ( c1 == c2 ) return false;
+
+ start = c1;
+ len = c2-c1;
+
+ if ( !(hg = GlobalAlloc(GMEM_DDESHARE, len*2+1)) )
+ {
+ return false;
+ }
+ if ( !(text = (char*)GlobalLock(hg)) )
+ {
+ GlobalFree(hg);
+ return false;
+ }
+
+ j = 0;
+ for ( i=start ; i<start+len ; i++ )
+ {
+ c = m_text[i];
+ if ( c == '\n' ) text[j++] = '\r';
+ text[j++] = c;
+ }
+ text[j] = 0;
+ GlobalUnlock(hg);
+
+ if ( !OpenClipboard(NULL) )
+ {
+ GlobalFree(hg);
+ return false;
+ }
+ if ( !EmptyClipboard() )
+ {
+ GlobalFree(hg);
+ return false;
+ }
+ if ( !SetClipboardData(CF_TEXT, hg) )
+ {
+ GlobalFree(hg);
+ return false;
+ }
+ CloseClipboard();
+
+ return true;
+}
+
+// Paste the contents of the notebook.
+
+bool CEdit::Paste()
+{
+ HANDLE h;
+ char c;
+ char* p;
+
+ if ( !m_bEdit ) return false;
+
+ if ( !OpenClipboard(NULL) )
+ {
+ return false;
+ }
+
+ if ( !(h = GetClipboardData(CF_TEXT)) )
+ {
+ CloseClipboard();
+ return false;
+ }
+
+ if ( !(p = (char*)GlobalLock(h)) )
+ {
+ CloseClipboard();
+ return false;
+ }
+
+ UndoMemorize(OPERUNDO_SPEC);
+
+ while ( *p != 0 )
+ {
+ c = *p++;
+ if ( c == '\r' ) continue;
+ if ( c == '\t' && m_bAutoIndent ) continue;
+ InsertOne(c);
+ }
+
+ GlobalUnlock(h);
+ CloseClipboard();
+
+ Justif();
+ ColumnFix();
+ SendModifEvent();
+ return true;
+}
+
+
+// Cancels the last action.
+
+bool CEdit::Undo()
+{
+ if ( !m_bEdit ) return false;
+
+ return UndoRecall();
+}
+
+
+// Inserts a character.
+
+void CEdit::Insert(char character)
+{
+ int i, level, tab;
+
+ if ( !m_bEdit ) return;
+
+ if ( !m_bMulti ) // single-line?
+ {
+ if ( character == '\n' ||
+ character == '\t' ) return;
+ }
+
+ UndoMemorize(OPERUNDO_INSERT);
+
+ if ( m_bMulti && !m_bAutoIndent )
+ {
+ if ( character == '\n' )
+ {
+ InsertOne(character);
+ level = IndentCompute();
+ for ( i=0 ; i<level ; i++ )
+ {
+ InsertOne('\t');
+ }
+ }
+ else if ( character == '{' )
+ {
+ tab = IndentTabCount();
+ if ( tab != -1 )
+ {
+ level = IndentCompute();
+ IndentTabAdjust(level-tab);
+ }
+ InsertOne(character);
+ }
+ else if ( character == '}' )
+ {
+ tab = IndentTabCount();
+ if ( tab != -1 )
+ {
+ level = IndentCompute()-1;
+ IndentTabAdjust(level-tab);
+ }
+ InsertOne(character);
+ }
+ else
+ {
+ InsertOne(character);
+ }
+ }
+ else if ( m_bAutoIndent )
+ {
+ if ( character == '{' )
+ {
+ InsertOne(character);
+ InsertOne('\n');
+ InsertOne('\n');
+ InsertOne('}');
+ MoveChar(-1, false, false);
+ MoveChar(-1, false, false);
+ }
+#if 0
+ else if ( character == '(' )
+ {
+ InsertOne(character);
+ InsertOne(')');
+ MoveChar(-1, false, false);
+ }
+ else if ( character == '[' )
+ {
+ InsertOne(character);
+ InsertOne(']');
+ MoveChar(-1, false, false);
+ }
+#endif
+ else if ( character == '\t' )
+ {
+ for ( i=0 ; i<m_engine->RetEditIndentValue() ; i++ )
+ {
+ InsertOne(' ');
+ }
+ }
+ else
+ {
+ InsertOne(character);
+ }
+ }
+ else
+ {
+ InsertOne(character);
+ }
+
+ Justif();
+ ColumnFix();
+}
+
+// Inserts a plain character.
+
+void CEdit::InsertOne(char character)
+{
+ int i;
+
+ if ( !m_bEdit ) return;
+ if ( !m_bMulti && character == '\n' ) return;
+
+ if ( m_cursor1 != m_cursor2 )
+ {
+ DeleteOne(0); // deletes the selected characters
+ }
+
+ if ( m_len >= m_maxChar ) return;
+
+ for ( i=m_len ; i>=m_cursor1 ; i-- )
+ {
+ m_text[i] = m_text[i-1]; // shoot
+
+ if ( m_format != 0 )
+ {
+ m_format[i] = m_format[i-1]; // shoot
+ }
+ }
+
+ m_len ++;
+
+ m_text[m_cursor1] = character;
+
+ if ( m_format != 0 )
+ {
+ m_format[m_cursor1] = 0;
+ }
+
+ m_cursor1++;
+ m_cursor2 = m_cursor1;
+}
+
+// Deletes the character left of cursor or all selected characters.
+
+void CEdit::Delete(int dir)
+{
+ if ( !m_bEdit ) return;
+
+ UndoMemorize(OPERUNDO_DELETE);
+ DeleteOne(dir);
+
+ Justif();
+ ColumnFix();
+}
+
+// Deletes the character left of cursor or all selected plain characters.
+
+void CEdit::DeleteOne(int dir)
+{
+ int i, end, hole;
+
+ if ( !m_bEdit ) return;
+
+ if ( m_cursor1 == m_cursor2 )
+ {
+ if ( dir < 0 )
+ {
+ if ( m_cursor1 == 0 ) return;
+ m_cursor1 --;
+ }
+ else
+ {
+ if ( m_cursor2 == m_len ) return;
+ m_cursor2 ++;
+ }
+ }
+
+ if ( m_cursor1 > m_cursor2 ) Math::Swap(m_cursor1, m_cursor2);
+ hole = m_cursor2-m_cursor1;
+ end = m_len-hole;
+ for ( i=m_cursor1 ; i<end ; i++ )
+ {
+ m_text[i] = m_text[i+hole];
+
+ if ( m_format != 0 )
+ {
+ m_format[i] = m_format[i+hole];
+ }
+ }
+ m_len -= hole;
+ m_cursor2 = m_cursor1;
+}
+
+
+// Calculates the indentation level of brackets {and}.
+
+int CEdit::IndentCompute()
+{
+ int i, level;
+
+ level = 0;
+ for ( i=0 ; i<m_cursor1 ; i++ )
+ {
+ if ( m_text[i] == '{' ) level ++;
+ if ( m_text[i] == '}' ) level --;
+ }
+
+ if ( level < 0 ) level = 0;
+ return level;
+}
+
+// Counts the number of tabs before the cursor.
+// Returns -1 if there is something else.
+
+int CEdit::IndentTabCount()
+{
+ int i, nb;
+
+ if ( m_cursor1 != m_cursor2 ) return -1;
+
+ i = m_cursor1;
+ nb = 0;
+ while ( i > 0 )
+ {
+ if ( m_text[i-1] == '\n' ) return nb;
+ if ( m_text[i-1] != '\t' ) return -1;
+ nb ++;
+ i --;
+ }
+ return nb;
+}
+
+// Adds or removes qq tabs.
+
+void CEdit::IndentTabAdjust(int number)
+{
+ int i;
+
+ for ( i=0 ; i<number ; i++ ) // add?
+ {
+ InsertOne('\t');
+ }
+
+ for ( i=0 ; i>number ; i-- ) // delete?
+ {
+ DeleteOne(-1);
+ }
+}
+
+
+// Indent the left or right the entire selection.
+
+bool CEdit::Shift(bool bLeft)
+{
+ bool bInvert = false;
+ int c1, c2, i;
+
+ if ( m_cursor1 == m_cursor2 ) return false;
+
+ UndoMemorize(OPERUNDO_SPEC);
+
+ c1 = m_cursor1;
+ c2 = m_cursor2;
+ if ( c1 > c2 )
+ {
+ Math::Swap(c1, c2); // always c1 <= c2
+ bInvert = true;
+ }
+
+ if ( c1 > 0 )
+ {
+ if ( m_text[c1-1] != '\n' ) return false;
+ }
+ if ( c2 < m_len )
+ {
+ if ( m_text[c2-1] != '\n' ) return false;
+ }
+
+ if ( bLeft ) // shifts left?
+ {
+ i = c1;
+ while ( i < c2 )
+ {
+ if ( m_text[i] == '\t' )
+ {
+ m_cursor1 = i;
+ m_cursor2 = i+1;
+ DeleteOne(0);
+ c2 --;
+ }
+ while ( i < c2 && m_text[i++] != '\n' );
+ }
+ }
+ else // shifts right?
+ {
+ i = c1;
+ while ( i < c2 )
+ {
+ m_cursor1 = m_cursor2 = i;
+ InsertOne('\t');
+ c2 ++;
+ while ( i < c2 && m_text[i++] != '\n' );
+ }
+ }
+
+ if ( bInvert ) Math::Swap(c1, c2);
+ m_cursor1 = c1;
+ m_cursor2 = c2;
+
+ Justif();
+ ColumnFix();
+ SendModifEvent();
+ return true;
+}
+
+// Math::Min conversion <-> shift the selection.
+
+bool CEdit::MinMaj(bool bMaj)
+{
+ int c1, c2, i, character;
+
+ if ( m_cursor1 == m_cursor2 ) return false;
+
+ UndoMemorize(OPERUNDO_SPEC);
+
+ c1 = m_cursor1;
+ c2 = m_cursor2;
+ if ( c1 > c2 ) Math::Swap(c1, c2); // alwyas c1 <= c2
+
+ for ( i=c1 ; i<c2 ; i++ )
+ {
+ character = (unsigned char)m_text[i];
+ if ( bMaj ) character = RetToUpper(character);
+ else character = RetToLower(character);
+ m_text[i] = character;
+ }
+
+ Justif();
+ ColumnFix();
+ SendModifEvent();
+ return true;
+}
+
+
+// Cut all text lines.
+
+void CEdit::Justif()
+{
+ float width, value, size, indentLength;
+ int i, j, line, indent;
+ bool bDual, bString, bRem;
+
+ indent = 0;
+ m_lineTotal = 0;
+ m_lineOffset[m_lineTotal] = 0;
+ m_lineIndent[m_lineTotal] = indent;
+ m_lineTotal ++;
+
+ if ( m_bAutoIndent )
+ {
+ indentLength = m_engine->RetText()->RetCharWidth(' ', 0.0f, m_fontSize, m_fontStretch, m_fontType)
+ * m_engine->RetEditIndentValue();
+ }
+
+ bString = bRem = false;
+ i = 0;
+ while ( true )
+ {
+ bDual = false;
+
+ width = m_dim.x-(10.0f/640.0f)*2.0f-(m_bMulti?MARGX*2.0f+SCROLL_WIDTH:0.0f);
+ if ( m_bAutoIndent )
+ {
+ width -= indentLength*m_lineIndent[m_lineTotal-1];
+ }
+
+ if ( m_format == 0 )
+ {
+ i += m_engine->RetText()->Justif(m_text+i, m_len-i, width,
+ m_fontSize, m_fontStretch,
+ m_fontType);
+ }
+ else
+ {
+ size = m_fontSize;
+
+ if ( (m_format[i]&TITLE_MASK) == TITLE_BIG ) // headline?
+ {
+ size *= BIG_FONT;
+ bDual = true;
+ }
+
+ if ( (m_format[i]&IMAGE_MASK) != 0 ) // image part?
+ {
+ i ++; // jumps just a character (index in m_image)
+ }
+ else
+ {
+ i += m_engine->RetText()->Justif(m_text+i, m_format+i,
+ m_len-i, width,
+ size, m_fontStretch);
+ }
+ }
+
+ if ( i >= m_len ) break;
+
+ if ( m_bAutoIndent )
+ {
+ for ( j=m_lineOffset[m_lineTotal-1] ; j<i ; j++ )
+ {
+ if ( !bRem && m_text[j] == '\"' ) bString = !bString;
+ if ( !bString &&
+ m_text[j] == '/' &&
+ m_text[j+1] == '/' ) bRem = true;
+ if ( m_text[j] == '\n' ) bString = bRem = false;
+ if ( m_text[j] == '{' && !bString && !bRem ) indent ++;
+ if ( m_text[j] == '}' && !bString && !bRem ) indent --;
+ }
+ if ( indent < 0 ) indent = 0;
+ }
+
+ m_lineOffset[m_lineTotal] = i;
+ m_lineIndent[m_lineTotal] = indent;
+ m_lineTotal ++;
+ if ( bDual )
+ {
+ m_lineOffset[m_lineTotal] = i;
+ m_lineIndent[m_lineTotal] = indent;
+ m_lineTotal ++;
+ }
+ if ( m_lineTotal >= EDITLINEMAX-2 ) break;
+ }
+ if ( m_len > 0 && m_text[m_len-1] == '\n' )
+ {
+ m_lineOffset[m_lineTotal] = m_len;
+ m_lineIndent[m_lineTotal] = 0;
+ m_lineTotal ++;
+ }
+ m_lineOffset[m_lineTotal] = m_len;
+ m_lineIndent[m_lineTotal] = 0;
+
+ if ( m_bAutoIndent )
+ {
+ for ( i=0 ; i<=m_lineTotal ; i++ )
+ {
+ if ( m_text[m_lineOffset[i]] == '}' )
+ {
+ if ( m_lineIndent[i] > 0 ) m_lineIndent[i] --;
+ }
+ }
+ }
+
+ if ( m_bMulti )
+ {
+ if ( m_bEdit )
+ {
+ line = RetCursorLine(m_cursor1);
+ if ( line < m_lineFirst )
+ {
+ m_lineFirst = line;
+ }
+ if ( line >= m_lineFirst+m_lineVisible )
+ {
+ m_lineFirst = line-m_lineVisible+1;
+ }
+ }
+ }
+ else
+ {
+ m_lineFirst = 0;
+ }
+
+ if ( m_scroll != 0 )
+ {
+ if ( m_lineTotal <= m_lineVisible )
+ {
+ m_scroll->SetVisibleRatio(1.0f);
+ m_scroll->SetVisibleValue(0.0f);
+ m_scroll->SetArrowStep(0.0f);
+ }
+ else
+ {
+ value = (float)m_lineVisible/m_lineTotal;
+ m_scroll->SetVisibleRatio(value);
+
+ value = (float)m_lineFirst/(m_lineTotal-m_lineVisible);
+ m_scroll->SetVisibleValue(value);
+
+ value = (float)1.0f/(m_lineTotal-m_lineVisible);
+ m_scroll->SetArrowStep(value);
+ }
+ }
+
+ m_timeBlink = 0.0f; // lights the cursor immediately
+}
+
+// Returns the rank of the line where the cursor is located.
+
+int CEdit::RetCursorLine(int cursor)
+{
+ int line, i;
+
+ line = 0;
+ for ( i=0 ; i<m_lineTotal ; i++ )
+ {
+ if ( cursor >= m_lineOffset[i] )
+ {
+ line = i;
+ }
+ }
+ return line;
+}
+
+
+// Flush the buffer undo.
+
+void CEdit::UndoFlush()
+{
+ int i;
+
+ for ( i=0 ; i<EDITUNDOMAX ; i++ )
+ {
+ delete m_undo[i].text;
+ m_undo[i].text = 0;
+ }
+
+ m_bUndoForce = true;
+ m_undoOper = OPERUNDO_SPEC;
+}
+
+// Memorize the current state before a change.
+
+void CEdit::UndoMemorize(OperUndo oper)
+{
+ int i, len;
+
+ if ( !m_bUndoForce &&
+ oper != OPERUNDO_SPEC &&
+ m_undoOper != OPERUNDO_SPEC &&
+ oper == m_undoOper ) return;
+
+ m_bUndoForce = false;
+ m_undoOper = oper;
+
+ delete m_undo[EDITUNDOMAX-1].text;
+
+ for ( i=EDITUNDOMAX-1 ; i>=1 ; i-- )
+ {
+ m_undo[i] = m_undo[i-1];
+ }
+
+ len = m_len;
+ if ( len == 0 ) len ++;
+ m_undo[0].text = (char*)malloc(sizeof(char)*(len+1));
+ memcpy(m_undo[0].text, m_text, m_len);
+ m_undo[0].len = m_len;
+
+ m_undo[0].cursor1 = m_cursor1;
+ m_undo[0].cursor2 = m_cursor2;
+ m_undo[0].lineFirst = m_lineFirst;
+}
+
+// Back to previous state.
+
+bool CEdit::UndoRecall()
+{
+ int i;
+
+ if ( m_undo[0].text == 0 ) return false;
+
+ m_len = m_undo[0].len;
+ memcpy(m_text, m_undo[0].text, m_len);
+
+ m_cursor1 = m_undo[0].cursor1;
+ m_cursor2 = m_undo[0].cursor2;
+ m_lineFirst = m_undo[0].lineFirst;
+
+ for ( i=0 ; i<EDITUNDOMAX-1 ; i++ )
+ {
+ m_undo[i] = m_undo[i+1];
+ }
+ m_undo[EDITUNDOMAX-1].text = 0;
+
+ m_bUndoForce = true;
+ Justif();
+ ColumnFix();
+ SendModifEvent();
+ return true;
+}
+
+
+// Clears the format of all characters.
+
+bool CEdit::ClearFormat()
+{
+ if ( m_format == 0 )
+ {
+ SetMultiFont(true);
+ }
+ memset(m_format, m_fontType, m_len);
+
+ return true;
+}
+
+// Changes the format of a sequence of characters.
+
+bool CEdit::SetFormat(int cursor1, int cursor2, int format)
+{
+ int i;
+
+ if ( m_format == 0 ) return false;
+
+ for ( i=cursor1 ; i<cursor2 ; i++ )
+ {
+ m_format[i] |= format;
+ }
+
+ return true;
+}
+
+
diff --git a/src/ui/edit.h b/src/ui/edit.h
index cd3c5b9..dbd94d1 100644
--- a/src/ui/edit.h
+++ b/src/ui/edit.h
@@ -1,248 +1,248 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// edit.h
-
-#pragma once
-
-
-#include "common/struct.h"
-#include "ui/control.h"
-
-
-class CD3DEngine;
-class CScroll;
-
-
-
-const int EDITSTUDIOMAX = 20000; // maximum number of characters in CBOT edit
-const int EDITLINEMAX = 1000; // maximum total number of lines
-const int EDITIMAGEMAX = 50; // maximum total number of lines with images
-const int EDITLINKMAX = 100; // maximum number of links
-const int EDITHISTORYMAX = 50; // max number of levels preserves
-
-const int EDITUNDOMAX = 20; // max number of successive undo
-
-struct EditUndo
-{
- char* text; // original text
- int len; // length of the text
- int cursor1; // offset cursor
- int cursor2; // offset cursor
- int lineFirst; // the first line displayed.
-
-};
-
-enum OperUndo
-{
- OPERUNDO_SPEC = 0, // special operation
- OPERUNDO_INSERT = 1, // inserting characters
- OPERUNDO_DELETE = 2, // deleting characters
-};
-
-struct ImageLine
-{
- char name[40]; // name of the image (without diagram \)
- float offset; // vertical offset (v texture)
- float height; // height of the part (dv texture)
- float width; // width
-};
-
-struct HyperLink
-{
- char name[40]; // text file name (without help \)
- char marker[20]; // name of the marker
-};
-
-struct HyperMarker
-{
- char name[20]; // name of the marker
- int pos; // position in the text
-};
-
-struct HyperHistory
-{
- char filename[50]; // full file name text
- int firstLine; // rank of the first displayed line
-};
-
-
-
-
-class CEdit : public CControl
-{
-public:
- CEdit(CInstanceManager* iMan);
- virtual ~CEdit();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
-
- void SetPos(Math::Point pos);
- void SetDim(Math::Point dim);
-
- bool EventProcess(const Event &event);
- void Draw();
-
- void SetText(char *text, bool bNew=true);
- void GetText(char *buffer, int max);
- char* RetText();
- int RetTextLength();
-
- bool ReadText(char *filename, int addSize=0);
- bool WriteText(char *filename);
-
- void SetMaxChar(int max);
- int RetMaxChar();
-
- void SetEditCap(bool bMode);
- bool RetEditCap();
-
- void SetHiliteCap(bool bEnable);
- bool RetHiliteCap();
-
- void SetInsideScroll(bool bInside);
- bool RetInsideScroll();
-
- void SetSoluceMode(bool bSoluce);
- bool RetSoluceMode();
-
- void SetGenericMode(bool bGeneric);
- bool RetGenericMode();
-
- void SetAutoIndent(bool bMode);
- bool RetAutoIndent();
-
- void SetCursor(int cursor1, int cursor2);
- void GetCursor(int &cursor1, int &cursor2);
-
- void SetFirstLine(int rank);
- int RetFirstLine();
- void ShowSelect();
-
- void SetDisplaySpec(bool bDisplay);
- bool RetDisplaySpec();
-
- void SetMultiFont(bool bMulti);
- bool RetMultiFont();
-
- bool Cut();
- bool Copy();
- bool Paste();
- bool Undo();
-
- void HyperFlush();
- void HyperHome(char *filename);
- bool HyperTest(EventMsg event);
- bool HyperGo(EventMsg event);
-
- void SetFontSize(float size);
-
- bool ClearFormat();
- bool SetFormat(int cursor1, int cursor2, int format);
-
-protected:
- void SendModifEvent();
- bool IsLinkPos(Math::Point pos);
- void MouseDoubleClick(Math::Point mouse);
- void MouseClick(Math::Point mouse);
- void MouseMove(Math::Point mouse);
- void MouseRelease(Math::Point mouse);
- int MouseDetect(Math::Point mouse);
- void MoveAdjust();
-
- void HyperJump(char *name, char *marker);
- bool HyperAdd(char *filename, int firstLine);
-
- void DrawImage(Math::Point pos, char *name, float width, float offset, float height, int nbLine);
- void DrawBack(Math::Point pos, Math::Point dim);
- void DrawPart(Math::Point pos, Math::Point dim, int icon);
-
- void FreeImage();
- void LoadImage(char *name);
- void Scroll(int pos, bool bAdjustCursor);
- void Scroll();
- void MoveChar(int move, bool bWord, bool bSelect);
- void MoveLine(int move, bool bWord, bool bSelect);
- void MoveHome(bool bWord, bool bSelect);
- void MoveEnd(bool bWord, bool bSelect);
- void ColumnFix();
- void Insert(char character);
- void InsertOne(char character);
- void Delete(int dir);
- void DeleteOne(int dir);
- int IndentCompute();
- int IndentTabCount();
- void IndentTabAdjust(int number);
- bool Shift(bool bLeft);
- bool MinMaj(bool bMaj);
- void Justif();
- int RetCursorLine(int cursor);
-
- void UndoFlush();
- void UndoMemorize(OperUndo oper);
- bool UndoRecall();
-
-protected:
- CScroll* m_scroll; // vertical scrollbar on the right
-
- int m_maxChar; // max length of the buffer m_text
- char* m_text; // text (without zero terminator)
- char* m_format; // format characters
- int m_len; // length used in m_text
- int m_cursor1; // offset cursor
- int m_cursor2; // offset cursor
-
- bool m_bMulti; // true -> multi-line
- bool m_bEdit; // true -> editable
- bool m_bHilite; // true -> hilitable
- bool m_bInsideScroll; // true -> lift as part
- bool m_bDisplaySpec; // true -> displays the special characters
- bool m_bMultiFont; // true -> more fonts possible
- bool m_bSoluce; // true -> shows the links-solution
- bool m_bGeneric; // true -> generic that defile
- bool m_bAutoIndent; // true -> automatic indentation
- float m_lineHeight; // height of a row
- float m_lineAscent; // height above the baseline
- float m_lineDescent; // height below the baseline
- int m_lineVisible; // total number of viewable lines
- int m_lineFirst; // the first line displayed
- int m_lineTotal; // number lines used (in m_lineOffset)
- int m_lineOffset[EDITLINEMAX];
- char m_lineIndent[EDITLINEMAX];
- int m_imageTotal;
- ImageLine m_image[EDITIMAGEMAX];
- HyperLink m_link[EDITLINKMAX];
- int m_markerTotal;
- HyperMarker m_marker[EDITLINKMAX];
- int m_historyTotal;
- int m_historyCurrent;
- HyperHistory m_history[EDITHISTORYMAX];
- float m_time; // absolute time
- float m_timeBlink;
- float m_timeLastClick;
- float m_timeLastScroll;
- Math::Point m_mouseFirstPos;
- Math::Point m_mouseLastPos;
- float m_column;
-
- bool m_bCapture;
-
- bool m_bUndoForce;
- OperUndo m_undoOper;
- EditUndo m_undo[EDITUNDOMAX];
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// edit.h
+
+#pragma once
+
+
+#include "common/struct.h"
+#include "ui/control.h"
+
+
+class CD3DEngine;
+class CScroll;
+
+
+
+const int EDITSTUDIOMAX = 20000; // maximum number of characters in CBOT edit
+const int EDITLINEMAX = 1000; // maximum total number of lines
+const int EDITIMAGEMAX = 50; // maximum total number of lines with images
+const int EDITLINKMAX = 100; // maximum number of links
+const int EDITHISTORYMAX = 50; // max number of levels preserves
+
+const int EDITUNDOMAX = 20; // max number of successive undo
+
+struct EditUndo
+{
+ char* text; // original text
+ int len; // length of the text
+ int cursor1; // offset cursor
+ int cursor2; // offset cursor
+ int lineFirst; // the first line displayed.
+
+};
+
+enum OperUndo
+{
+ OPERUNDO_SPEC = 0, // special operation
+ OPERUNDO_INSERT = 1, // inserting characters
+ OPERUNDO_DELETE = 2, // deleting characters
+};
+
+struct ImageLine
+{
+ char name[40]; // name of the image (without diagram \)
+ float offset; // vertical offset (v texture)
+ float height; // height of the part (dv texture)
+ float width; // width
+};
+
+struct HyperLink
+{
+ char name[40]; // text file name (without help \)
+ char marker[20]; // name of the marker
+};
+
+struct HyperMarker
+{
+ char name[20]; // name of the marker
+ int pos; // position in the text
+};
+
+struct HyperHistory
+{
+ char filename[50]; // full file name text
+ int firstLine; // rank of the first displayed line
+};
+
+
+
+
+class CEdit : public CControl
+{
+public:
+ CEdit(CInstanceManager* iMan);
+ virtual ~CEdit();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+
+ void SetPos(Math::Point pos);
+ void SetDim(Math::Point dim);
+
+ bool EventProcess(const Event &event);
+ void Draw();
+
+ void SetText(char *text, bool bNew=true);
+ void GetText(char *buffer, int max);
+ char* RetText();
+ int RetTextLength();
+
+ bool ReadText(char *filename, int addSize=0);
+ bool WriteText(char *filename);
+
+ void SetMaxChar(int max);
+ int RetMaxChar();
+
+ void SetEditCap(bool bMode);
+ bool RetEditCap();
+
+ void SetHiliteCap(bool bEnable);
+ bool RetHiliteCap();
+
+ void SetInsideScroll(bool bInside);
+ bool RetInsideScroll();
+
+ void SetSoluceMode(bool bSoluce);
+ bool RetSoluceMode();
+
+ void SetGenericMode(bool bGeneric);
+ bool RetGenericMode();
+
+ void SetAutoIndent(bool bMode);
+ bool RetAutoIndent();
+
+ void SetCursor(int cursor1, int cursor2);
+ void GetCursor(int &cursor1, int &cursor2);
+
+ void SetFirstLine(int rank);
+ int RetFirstLine();
+ void ShowSelect();
+
+ void SetDisplaySpec(bool bDisplay);
+ bool RetDisplaySpec();
+
+ void SetMultiFont(bool bMulti);
+ bool RetMultiFont();
+
+ bool Cut();
+ bool Copy();
+ bool Paste();
+ bool Undo();
+
+ void HyperFlush();
+ void HyperHome(char *filename);
+ bool HyperTest(EventMsg event);
+ bool HyperGo(EventMsg event);
+
+ void SetFontSize(float size);
+
+ bool ClearFormat();
+ bool SetFormat(int cursor1, int cursor2, int format);
+
+protected:
+ void SendModifEvent();
+ bool IsLinkPos(Math::Point pos);
+ void MouseDoubleClick(Math::Point mouse);
+ void MouseClick(Math::Point mouse);
+ void MouseMove(Math::Point mouse);
+ void MouseRelease(Math::Point mouse);
+ int MouseDetect(Math::Point mouse);
+ void MoveAdjust();
+
+ void HyperJump(char *name, char *marker);
+ bool HyperAdd(char *filename, int firstLine);
+
+ void DrawImage(Math::Point pos, char *name, float width, float offset, float height, int nbLine);
+ void DrawBack(Math::Point pos, Math::Point dim);
+ void DrawPart(Math::Point pos, Math::Point dim, int icon);
+
+ void FreeImage();
+ void LoadImage(char *name);
+ void Scroll(int pos, bool bAdjustCursor);
+ void Scroll();
+ void MoveChar(int move, bool bWord, bool bSelect);
+ void MoveLine(int move, bool bWord, bool bSelect);
+ void MoveHome(bool bWord, bool bSelect);
+ void MoveEnd(bool bWord, bool bSelect);
+ void ColumnFix();
+ void Insert(char character);
+ void InsertOne(char character);
+ void Delete(int dir);
+ void DeleteOne(int dir);
+ int IndentCompute();
+ int IndentTabCount();
+ void IndentTabAdjust(int number);
+ bool Shift(bool bLeft);
+ bool MinMaj(bool bMaj);
+ void Justif();
+ int RetCursorLine(int cursor);
+
+ void UndoFlush();
+ void UndoMemorize(OperUndo oper);
+ bool UndoRecall();
+
+protected:
+ CScroll* m_scroll; // vertical scrollbar on the right
+
+ int m_maxChar; // max length of the buffer m_text
+ char* m_text; // text (without zero terminator)
+ char* m_format; // format characters
+ int m_len; // length used in m_text
+ int m_cursor1; // offset cursor
+ int m_cursor2; // offset cursor
+
+ bool m_bMulti; // true -> multi-line
+ bool m_bEdit; // true -> editable
+ bool m_bHilite; // true -> hilitable
+ bool m_bInsideScroll; // true -> lift as part
+ bool m_bDisplaySpec; // true -> displays the special characters
+ bool m_bMultiFont; // true -> more fonts possible
+ bool m_bSoluce; // true -> shows the links-solution
+ bool m_bGeneric; // true -> generic that defile
+ bool m_bAutoIndent; // true -> automatic indentation
+ float m_lineHeight; // height of a row
+ float m_lineAscent; // height above the baseline
+ float m_lineDescent; // height below the baseline
+ int m_lineVisible; // total number of viewable lines
+ int m_lineFirst; // the first line displayed
+ int m_lineTotal; // number lines used (in m_lineOffset)
+ int m_lineOffset[EDITLINEMAX];
+ char m_lineIndent[EDITLINEMAX];
+ int m_imageTotal;
+ ImageLine m_image[EDITIMAGEMAX];
+ HyperLink m_link[EDITLINKMAX];
+ int m_markerTotal;
+ HyperMarker m_marker[EDITLINKMAX];
+ int m_historyTotal;
+ int m_historyCurrent;
+ HyperHistory m_history[EDITHISTORYMAX];
+ float m_time; // absolute time
+ float m_timeBlink;
+ float m_timeLastClick;
+ float m_timeLastScroll;
+ Math::Point m_mouseFirstPos;
+ Math::Point m_mouseLastPos;
+ float m_column;
+
+ bool m_bCapture;
+
+ bool m_bUndoForce;
+ OperUndo m_undoOper;
+ EditUndo m_undo[EDITUNDOMAX];
+};
+
+
diff --git a/src/ui/editvalue.cpp b/src/ui/editvalue.cpp
index 7d92b37..71e06f2 100644
--- a/src/ui/editvalue.cpp
+++ b/src/ui/editvalue.cpp
@@ -1,378 +1,378 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// editvalue.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "ui/edit.h"
-#include "ui/button.h"
-#include "ui/editvalue.h"
-
-
-
-
-// Object's constructor.
-
-CEditValue::CEditValue(CInstanceManager* iMan) : CControl(iMan)
-{
- m_edit = 0;
- m_buttonUp = 0;
- m_buttonDown = 0;
-
- m_type = EVT_100; // %
- m_stepValue = 0.1f; // 10%
- m_minValue = 0.0f; // 0%
- m_maxValue = 1.0f; // 100%
-}
-
-// Object's destructor.
-
-CEditValue::~CEditValue()
-{
- delete m_edit;
- delete m_buttonUp;
- delete m_buttonDown;
-}
-
-
-// Creates a new button.
-
-bool CEditValue::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CEdit* pe;
- CButton* pc;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
- CControl::Create(pos, dim, icon, eventMsg);
-
- GlintDelete();
-
- m_edit = new CEdit(m_iMan);
- pe = (CEdit*)m_edit;
- pe->Create(pos, dim, 0, EVENT_NULL);
- pe->SetMaxChar(4);
-
- m_buttonUp = new CButton(m_iMan);
- pc = (CButton*)m_buttonUp;
- pc->Create(pos, dim, 49, EVENT_NULL); // ^
- pc->SetRepeat(true);
-
- m_buttonDown = new CButton(m_iMan);
- pc = (CButton*)m_buttonDown;
- pc->Create(pos, dim, 50, EVENT_NULL); // v
- pc->SetRepeat(true);
-
- MoveAdjust();
- return true;
-}
-
-
-void CEditValue::SetPos(Math::Point pos)
-{
- CControl::SetPos(pos);
- MoveAdjust();
-}
-
-void CEditValue::SetDim(Math::Point dim)
-{
- CControl::SetDim(dim);
- MoveAdjust();
-}
-
-void CEditValue::MoveAdjust()
-{
- Math::Point pos, dim;
-
- if ( m_edit != 0 )
- {
- pos.x = m_pos.x;
- pos.y = m_pos.y;
- dim.x = m_dim.x-m_dim.y*0.6f;
- dim.y = m_dim.y;
- m_edit->SetPos(pos);
- m_edit->SetDim(dim);
- }
-
- if ( m_buttonUp != 0 )
- {
- pos.x = m_pos.x+m_dim.x-m_dim.y*0.6f;
- pos.y = m_pos.y+m_dim.y*0.5f;
- dim.x = m_dim.y*0.6f;
- dim.y = m_dim.y*0.5f;
- m_buttonUp->SetPos(pos);
- m_buttonUp->SetDim(dim);
- }
-
- if ( m_buttonDown != 0 )
- {
- pos.x = m_pos.x+m_dim.x-m_dim.y*0.6f;
- pos.y = m_pos.y;
- dim.x = m_dim.y*0.6f;
- dim.y = m_dim.y*0.5f;
- m_buttonDown->SetPos(pos);
- m_buttonDown->SetDim(dim);
- }
-}
-
-
-// Management of an event.
-
-bool CEditValue::EventProcess(const Event &event)
-{
- float value;
-
- CControl::EventProcess(event);
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return true;
- if ( (m_state & STATE_ENABLE) == 0 ) return true;
-
- if ( m_edit != 0 )
- {
- if ( m_edit->RetFocus() &&
- event.event == EVENT_KEYDOWN &&
- event.param == VK_RETURN )
- {
- value = RetValue();
- if ( value > m_maxValue ) value = m_maxValue;
- if ( value < m_minValue ) value = m_minValue;
- SetValue(value, true);
- HiliteValue(event);
- }
- if ( !m_edit->EventProcess(event) ) return false;
-
- if ( event.event == m_edit->RetEventMsg() )
- {
- Event newEvent;
- m_event->MakeEvent(newEvent, m_eventMsg);
- m_event->AddEvent(newEvent);
- }
- }
-
- if ( m_buttonUp != 0 )
- {
- if ( event.event == m_buttonUp->RetEventMsg() )
- {
- value = RetValue()+m_stepValue;
- if ( value > m_maxValue ) value = m_maxValue;
- SetValue(value, true);
- HiliteValue(event);
- }
- if ( !m_buttonUp->EventProcess(event) ) return false;
- }
-
- if ( m_buttonDown != 0 )
- {
- if ( event.event == m_buttonDown->RetEventMsg() )
- {
- value = RetValue()-m_stepValue;
- if ( value < m_minValue ) value = m_minValue;
- SetValue(value, true);
- HiliteValue(event);
- }
- if ( !m_buttonDown->EventProcess(event) ) return false;
- }
-
- if ( event.event == EVENT_KEYDOWN &&
- event.param == VK_WHEELUP &&
- Detect(event.pos) )
- {
- value = RetValue()+m_stepValue;
- if ( value > m_maxValue ) value = m_maxValue;
- SetValue(value, true);
- HiliteValue(event);
- }
- if ( event.event == EVENT_KEYDOWN &&
- event.param == VK_WHEELDOWN &&
- Detect(event.pos) )
- {
- value = RetValue()-m_stepValue;
- if ( value < m_minValue ) value = m_minValue;
- SetValue(value, true);
- HiliteValue(event);
- }
-
- return true;
-}
-
-
-// Puts in evidence the edited value.
-
-void CEditValue::HiliteValue(const Event &event)
-{
- int pos;
-
- if ( m_edit == 0 ) return;
-
- pos = m_edit->RetTextLength();
- if ( m_type == EVT_100 && pos > 0 )
- {
- pos --; // not only selects the "%"
- }
-
- m_edit->SetCursor(pos, 0);
- m_edit->SetFocus(true);
-
- Event newEvent = event;
- newEvent.event = EVENT_FOCUS;
- newEvent.param = m_edit->RetEventMsg();
- m_event->AddEvent(newEvent); // defocus the other objects
-}
-
-
-// Draw button.
-
-void CEditValue::Draw()
-{
- if ( (m_state & STATE_VISIBLE) == 0 ) return;
-
- if ( m_state & STATE_SHADOW )
- {
- DrawShadow(m_pos, m_dim);
- }
-
- if ( m_edit != 0 )
- {
- m_edit->Draw();
- }
- if ( m_buttonUp != 0 )
- {
- m_buttonUp->Draw();
- }
- if ( m_buttonDown != 0 )
- {
- m_buttonDown->Draw();
- }
-}
-
-
-// Choosing the type of value.
-
-void CEditValue::SetType(EditValueType type)
-{
- m_type = type;
-}
-
-EditValueType CEditValue::RetType()
-{
- return m_type;
-}
-
-
-// Changes the value.
-
-void CEditValue::SetValue(float value, bool bSendMessage)
-{
- char text[100];
-
- if ( m_edit == 0 ) return;
-
- text[0] = 0;
-
- if ( m_type == EVT_INT )
- {
- sprintf(text, "%d", (int)value);
- }
-
- if ( m_type == EVT_FLOAT )
- {
- sprintf(text, "%.2f", value);
- }
-
- if ( m_type == EVT_100 )
- {
- sprintf(text, "%d%%", (int)(value*100.0f));
- }
-
- m_edit->SetText(text);
-
- if ( bSendMessage )
- {
- Event newEvent;
- m_event->MakeEvent(newEvent, m_eventMsg);
- m_event->AddEvent(newEvent);
- }
-}
-
-// Return the edited value.
-
-float CEditValue::RetValue()
-{
- char text[100];
- float value;
-
- if ( m_edit == 0 ) 0.0f;
-
- m_edit->GetText(text, 100);
- sscanf(text, "%f", &value);
-
- if ( m_type == EVT_100 )
- {
- value = (value+0.5f)/100.0f;
- if ( value < 0.01f ) value = 0.0f; // less than 1%?
- }
-
- return value;
-}
-
-
-// Management not for buttons.
-
-void CEditValue::SetStepValue(float value)
-{
- m_stepValue = value;
-}
-
-float CEditValue::RetStepValue()
-{
- return m_stepValue;
-}
-
-
-// Management of the minimum value.
-
-void CEditValue::SetMinValue(float value)
-{
- m_minValue = value;
-}
-
-float CEditValue::RetMinValue()
-{
- return m_minValue;
-}
-
-
-// Management of the maximum value.
-
-void CEditValue::SetMaxValue(float value)
-{
- m_maxValue = value;
-}
-
-float CEditValue::RetMaxValue()
-{
- return m_maxValue;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// editvalue.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "ui/edit.h"
+#include "ui/button.h"
+#include "ui/editvalue.h"
+
+
+
+
+// Object's constructor.
+
+CEditValue::CEditValue(CInstanceManager* iMan) : CControl(iMan)
+{
+ m_edit = 0;
+ m_buttonUp = 0;
+ m_buttonDown = 0;
+
+ m_type = EVT_100; // %
+ m_stepValue = 0.1f; // 10%
+ m_minValue = 0.0f; // 0%
+ m_maxValue = 1.0f; // 100%
+}
+
+// Object's destructor.
+
+CEditValue::~CEditValue()
+{
+ delete m_edit;
+ delete m_buttonUp;
+ delete m_buttonDown;
+}
+
+
+// Creates a new button.
+
+bool CEditValue::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CEdit* pe;
+ CButton* pc;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+ CControl::Create(pos, dim, icon, eventMsg);
+
+ GlintDelete();
+
+ m_edit = new CEdit(m_iMan);
+ pe = (CEdit*)m_edit;
+ pe->Create(pos, dim, 0, EVENT_NULL);
+ pe->SetMaxChar(4);
+
+ m_buttonUp = new CButton(m_iMan);
+ pc = (CButton*)m_buttonUp;
+ pc->Create(pos, dim, 49, EVENT_NULL); // ^
+ pc->SetRepeat(true);
+
+ m_buttonDown = new CButton(m_iMan);
+ pc = (CButton*)m_buttonDown;
+ pc->Create(pos, dim, 50, EVENT_NULL); // v
+ pc->SetRepeat(true);
+
+ MoveAdjust();
+ return true;
+}
+
+
+void CEditValue::SetPos(Math::Point pos)
+{
+ CControl::SetPos(pos);
+ MoveAdjust();
+}
+
+void CEditValue::SetDim(Math::Point dim)
+{
+ CControl::SetDim(dim);
+ MoveAdjust();
+}
+
+void CEditValue::MoveAdjust()
+{
+ Math::Point pos, dim;
+
+ if ( m_edit != 0 )
+ {
+ pos.x = m_pos.x;
+ pos.y = m_pos.y;
+ dim.x = m_dim.x-m_dim.y*0.6f;
+ dim.y = m_dim.y;
+ m_edit->SetPos(pos);
+ m_edit->SetDim(dim);
+ }
+
+ if ( m_buttonUp != 0 )
+ {
+ pos.x = m_pos.x+m_dim.x-m_dim.y*0.6f;
+ pos.y = m_pos.y+m_dim.y*0.5f;
+ dim.x = m_dim.y*0.6f;
+ dim.y = m_dim.y*0.5f;
+ m_buttonUp->SetPos(pos);
+ m_buttonUp->SetDim(dim);
+ }
+
+ if ( m_buttonDown != 0 )
+ {
+ pos.x = m_pos.x+m_dim.x-m_dim.y*0.6f;
+ pos.y = m_pos.y;
+ dim.x = m_dim.y*0.6f;
+ dim.y = m_dim.y*0.5f;
+ m_buttonDown->SetPos(pos);
+ m_buttonDown->SetDim(dim);
+ }
+}
+
+
+// Management of an event.
+
+bool CEditValue::EventProcess(const Event &event)
+{
+ float value;
+
+ CControl::EventProcess(event);
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return true;
+ if ( (m_state & STATE_ENABLE) == 0 ) return true;
+
+ if ( m_edit != 0 )
+ {
+ if ( m_edit->RetFocus() &&
+ event.event == EVENT_KEYDOWN &&
+ event.param == VK_RETURN )
+ {
+ value = RetValue();
+ if ( value > m_maxValue ) value = m_maxValue;
+ if ( value < m_minValue ) value = m_minValue;
+ SetValue(value, true);
+ HiliteValue(event);
+ }
+ if ( !m_edit->EventProcess(event) ) return false;
+
+ if ( event.event == m_edit->RetEventMsg() )
+ {
+ Event newEvent;
+ m_event->MakeEvent(newEvent, m_eventMsg);
+ m_event->AddEvent(newEvent);
+ }
+ }
+
+ if ( m_buttonUp != 0 )
+ {
+ if ( event.event == m_buttonUp->RetEventMsg() )
+ {
+ value = RetValue()+m_stepValue;
+ if ( value > m_maxValue ) value = m_maxValue;
+ SetValue(value, true);
+ HiliteValue(event);
+ }
+ if ( !m_buttonUp->EventProcess(event) ) return false;
+ }
+
+ if ( m_buttonDown != 0 )
+ {
+ if ( event.event == m_buttonDown->RetEventMsg() )
+ {
+ value = RetValue()-m_stepValue;
+ if ( value < m_minValue ) value = m_minValue;
+ SetValue(value, true);
+ HiliteValue(event);
+ }
+ if ( !m_buttonDown->EventProcess(event) ) return false;
+ }
+
+ if ( event.event == EVENT_KEYDOWN &&
+ event.param == VK_WHEELUP &&
+ Detect(event.pos) )
+ {
+ value = RetValue()+m_stepValue;
+ if ( value > m_maxValue ) value = m_maxValue;
+ SetValue(value, true);
+ HiliteValue(event);
+ }
+ if ( event.event == EVENT_KEYDOWN &&
+ event.param == VK_WHEELDOWN &&
+ Detect(event.pos) )
+ {
+ value = RetValue()-m_stepValue;
+ if ( value < m_minValue ) value = m_minValue;
+ SetValue(value, true);
+ HiliteValue(event);
+ }
+
+ return true;
+}
+
+
+// Puts in evidence the edited value.
+
+void CEditValue::HiliteValue(const Event &event)
+{
+ int pos;
+
+ if ( m_edit == 0 ) return;
+
+ pos = m_edit->RetTextLength();
+ if ( m_type == EVT_100 && pos > 0 )
+ {
+ pos --; // not only selects the "%"
+ }
+
+ m_edit->SetCursor(pos, 0);
+ m_edit->SetFocus(true);
+
+ Event newEvent = event;
+ newEvent.event = EVENT_FOCUS;
+ newEvent.param = m_edit->RetEventMsg();
+ m_event->AddEvent(newEvent); // defocus the other objects
+}
+
+
+// Draw button.
+
+void CEditValue::Draw()
+{
+ if ( (m_state & STATE_VISIBLE) == 0 ) return;
+
+ if ( m_state & STATE_SHADOW )
+ {
+ DrawShadow(m_pos, m_dim);
+ }
+
+ if ( m_edit != 0 )
+ {
+ m_edit->Draw();
+ }
+ if ( m_buttonUp != 0 )
+ {
+ m_buttonUp->Draw();
+ }
+ if ( m_buttonDown != 0 )
+ {
+ m_buttonDown->Draw();
+ }
+}
+
+
+// Choosing the type of value.
+
+void CEditValue::SetType(EditValueType type)
+{
+ m_type = type;
+}
+
+EditValueType CEditValue::RetType()
+{
+ return m_type;
+}
+
+
+// Changes the value.
+
+void CEditValue::SetValue(float value, bool bSendMessage)
+{
+ char text[100];
+
+ if ( m_edit == 0 ) return;
+
+ text[0] = 0;
+
+ if ( m_type == EVT_INT )
+ {
+ sprintf(text, "%d", (int)value);
+ }
+
+ if ( m_type == EVT_FLOAT )
+ {
+ sprintf(text, "%.2f", value);
+ }
+
+ if ( m_type == EVT_100 )
+ {
+ sprintf(text, "%d%%", (int)(value*100.0f));
+ }
+
+ m_edit->SetText(text);
+
+ if ( bSendMessage )
+ {
+ Event newEvent;
+ m_event->MakeEvent(newEvent, m_eventMsg);
+ m_event->AddEvent(newEvent);
+ }
+}
+
+// Return the edited value.
+
+float CEditValue::RetValue()
+{
+ char text[100];
+ float value;
+
+ if ( m_edit == 0 ) 0.0f;
+
+ m_edit->GetText(text, 100);
+ sscanf(text, "%f", &value);
+
+ if ( m_type == EVT_100 )
+ {
+ value = (value+0.5f)/100.0f;
+ if ( value < 0.01f ) value = 0.0f; // less than 1%?
+ }
+
+ return value;
+}
+
+
+// Management not for buttons.
+
+void CEditValue::SetStepValue(float value)
+{
+ m_stepValue = value;
+}
+
+float CEditValue::RetStepValue()
+{
+ return m_stepValue;
+}
+
+
+// Management of the minimum value.
+
+void CEditValue::SetMinValue(float value)
+{
+ m_minValue = value;
+}
+
+float CEditValue::RetMinValue()
+{
+ return m_minValue;
+}
+
+
+// Management of the maximum value.
+
+void CEditValue::SetMaxValue(float value)
+{
+ m_maxValue = value;
+}
+
+float CEditValue::RetMaxValue()
+{
+ return m_maxValue;
+}
+
diff --git a/src/ui/editvalue.h b/src/ui/editvalue.h
index 1b45df9..dbb7812 100644
--- a/src/ui/editvalue.h
+++ b/src/ui/editvalue.h
@@ -1,83 +1,83 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// editvalue.h
-
-#pragma once
-
-
-#include "ui/control.h"
-
-
-enum EditValueType
-{
- EVT_INT = 1, // integer
- EVT_FLOAT = 2, // float value
- EVT_100 = 3, // percent (0 .. 1)
-};
-
-
-class CD3DEngine;
-class CEdit;
-class CButton;
-
-
-
-class CEditValue : public CControl
-{
-public:
- CEditValue(CInstanceManager* iMan);
- virtual ~CEditValue();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
-
- void SetPos(Math::Point pos);
- void SetDim(Math::Point dim);
-
- bool EventProcess(const Event &event);
- void Draw();
-
- void SetType(EditValueType type);
- EditValueType RetType();
-
- void SetValue(float value, bool bSendMessage=false);
- float RetValue();
-
- void SetStepValue(float value);
- float RetStepValue();
-
- void SetMinValue(float value);
- float RetMinValue();
-
- void SetMaxValue(float value);
- float RetMaxValue();
-
-protected:
- void MoveAdjust();
- void HiliteValue(const Event &event);
-
-protected:
- CEdit* m_edit;
- CButton* m_buttonUp;
- CButton* m_buttonDown;
-
- EditValueType m_type;
- float m_stepValue;
- float m_minValue;
- float m_maxValue;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// editvalue.h
+
+#pragma once
+
+
+#include "ui/control.h"
+
+
+enum EditValueType
+{
+ EVT_INT = 1, // integer
+ EVT_FLOAT = 2, // float value
+ EVT_100 = 3, // percent (0 .. 1)
+};
+
+
+class CD3DEngine;
+class CEdit;
+class CButton;
+
+
+
+class CEditValue : public CControl
+{
+public:
+ CEditValue(CInstanceManager* iMan);
+ virtual ~CEditValue();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+
+ void SetPos(Math::Point pos);
+ void SetDim(Math::Point dim);
+
+ bool EventProcess(const Event &event);
+ void Draw();
+
+ void SetType(EditValueType type);
+ EditValueType RetType();
+
+ void SetValue(float value, bool bSendMessage=false);
+ float RetValue();
+
+ void SetStepValue(float value);
+ float RetStepValue();
+
+ void SetMinValue(float value);
+ float RetMinValue();
+
+ void SetMaxValue(float value);
+ float RetMaxValue();
+
+protected:
+ void MoveAdjust();
+ void HiliteValue(const Event &event);
+
+protected:
+ CEdit* m_edit;
+ CButton* m_buttonUp;
+ CButton* m_buttonDown;
+
+ EditValueType m_type;
+ float m_stepValue;
+ float m_minValue;
+ float m_maxValue;
+};
+
+
diff --git a/src/ui/gauge.cpp b/src/ui/gauge.cpp
index 84a804d..13cd4f7 100644
--- a/src/ui/gauge.cpp
+++ b/src/ui/gauge.cpp
@@ -1,157 +1,157 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// gauge.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "ui/gauge.h"
-
-
-
-
-// Object's constructor.
-
-CGauge::CGauge(CInstanceManager* iMan) : CControl(iMan)
-{
- m_level = 0.0f;
-}
-
-// Object's destructor.
-
-CGauge::~CGauge()
-{
-}
-
-
-// Creates a new button.
-
-bool CGauge::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- CControl::Create(pos, dim, icon, eventMsg);
- return true;
-}
-
-
-// Management of an event.
-
-bool CGauge::EventProcess(const Event &event)
-{
- CControl::EventProcess(event);
-
- if ( event.event == EVENT_LBUTTONDOWN )
- {
- if ( CControl::Detect(event.pos) )
- {
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- return false;
- }
- }
-
- return true;
-}
-
-
-// Draw the gauge.
-
-void CGauge::Draw()
-{
- Math::Point pos, dim, ddim, uv1, uv2, corner;
- float dp;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return;
-
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
-
- dp = 0.5f/256.0f;
-
- pos = m_pos;
- dim = m_dim;
-
- uv1.x = 32.0f/256.0f;
- uv1.y = 32.0f/256.0f;
- uv2.x = 64.0f/256.0f;
- uv2.y = 64.0f/256.0f;
-
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- corner.x = 10.0f/640.0f;
- corner.y = 10.0f/480.0f;
-
- DrawIcon(pos, dim, uv1, uv2, corner, 8.0f/256.0f);
-
-
- pos.x += 3.0f/640.0f;
- pos.y += 3.0f/480.0f;
- dim.x -= 6.0f/640.0f;
- dim.y -= 6.0f/480.0f;
-
- if ( m_dim.x < m_dim.y ) // vertical gauge?
- {
- uv1.x = (0.0f+m_icon*16.0f)/256.0f;
- uv2.x = uv1.x+16.0f/256.0f;
- uv1.y = 128.0f/256.0f+m_level*(64.0f/256.0f);
- uv2.y = uv1.y+64.0f/256.0f;
- }
- else // horizontal gauge?
- {
- uv1.x = 64.0f/256.0f+(1.0f-m_level)*(64.0f/256.0f);
- uv2.x = uv1.x+64.0f/256.0f;
- uv1.y = (128.0f+m_icon*16.0f)/256.0f;
- uv2.y = uv1.y+16.0f/256.0f;
- }
-
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- DrawIcon(pos, dim, uv1, uv2);
-}
-
-
-// Management of level of the gauge.
-
-void CGauge::SetLevel(float level)
-{
- if ( level < 0.0f ) level = 0.0f;
- if ( level > 1.0f ) level = 1.0f;
- m_level = level;
-}
-
-float CGauge::RetLevel()
-{
- return m_level;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// gauge.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "ui/gauge.h"
+
+
+
+
+// Object's constructor.
+
+CGauge::CGauge(CInstanceManager* iMan) : CControl(iMan)
+{
+ m_level = 0.0f;
+}
+
+// Object's destructor.
+
+CGauge::~CGauge()
+{
+}
+
+
+// Creates a new button.
+
+bool CGauge::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ CControl::Create(pos, dim, icon, eventMsg);
+ return true;
+}
+
+
+// Management of an event.
+
+bool CGauge::EventProcess(const Event &event)
+{
+ CControl::EventProcess(event);
+
+ if ( event.event == EVENT_LBUTTONDOWN )
+ {
+ if ( CControl::Detect(event.pos) )
+ {
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+// Draw the gauge.
+
+void CGauge::Draw()
+{
+ Math::Point pos, dim, ddim, uv1, uv2, corner;
+ float dp;
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return;
+
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+
+ dp = 0.5f/256.0f;
+
+ pos = m_pos;
+ dim = m_dim;
+
+ uv1.x = 32.0f/256.0f;
+ uv1.y = 32.0f/256.0f;
+ uv2.x = 64.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+
+ corner.x = 10.0f/640.0f;
+ corner.y = 10.0f/480.0f;
+
+ DrawIcon(pos, dim, uv1, uv2, corner, 8.0f/256.0f);
+
+
+ pos.x += 3.0f/640.0f;
+ pos.y += 3.0f/480.0f;
+ dim.x -= 6.0f/640.0f;
+ dim.y -= 6.0f/480.0f;
+
+ if ( m_dim.x < m_dim.y ) // vertical gauge?
+ {
+ uv1.x = (0.0f+m_icon*16.0f)/256.0f;
+ uv2.x = uv1.x+16.0f/256.0f;
+ uv1.y = 128.0f/256.0f+m_level*(64.0f/256.0f);
+ uv2.y = uv1.y+64.0f/256.0f;
+ }
+ else // horizontal gauge?
+ {
+ uv1.x = 64.0f/256.0f+(1.0f-m_level)*(64.0f/256.0f);
+ uv2.x = uv1.x+64.0f/256.0f;
+ uv1.y = (128.0f+m_icon*16.0f)/256.0f;
+ uv2.y = uv1.y+16.0f/256.0f;
+ }
+
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+
+ DrawIcon(pos, dim, uv1, uv2);
+}
+
+
+// Management of level of the gauge.
+
+void CGauge::SetLevel(float level)
+{
+ if ( level < 0.0f ) level = 0.0f;
+ if ( level > 1.0f ) level = 1.0f;
+ m_level = level;
+}
+
+float CGauge::RetLevel()
+{
+ return m_level;
+}
+
+
diff --git a/src/ui/gauge.h b/src/ui/gauge.h
index 70eae92..bdc85ff 100644
--- a/src/ui/gauge.h
+++ b/src/ui/gauge.h
@@ -1,50 +1,50 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// gauge.h
-
-#pragma once
-
-
-#include "ui/control.h"
-
-
-class CD3DEngine;
-
-
-
-class CGauge : public CControl
-{
-public:
- CGauge(CInstanceManager* iMan);
- virtual ~CGauge();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
-
- bool EventProcess(const Event &event);
-
- void Draw();
-
- void SetLevel(float level);
- float RetLevel();
-
-protected:
-
-protected:
- float m_level;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// gauge.h
+
+#pragma once
+
+
+#include "ui/control.h"
+
+
+class CD3DEngine;
+
+
+
+class CGauge : public CControl
+{
+public:
+ CGauge(CInstanceManager* iMan);
+ virtual ~CGauge();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+
+ bool EventProcess(const Event &event);
+
+ void Draw();
+
+ void SetLevel(float level);
+ float RetLevel();
+
+protected:
+
+protected:
+ float m_level;
+};
+
+
diff --git a/src/ui/group.cpp b/src/ui/group.cpp
index 212064e..f4b1fe2 100644
--- a/src/ui/group.cpp
+++ b/src/ui/group.cpp
@@ -1,644 +1,644 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// group.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "ui/group.h"
-
-
-
-
-// Object's constructor.
-
-CGroup::CGroup(CInstanceManager* iMan) : CControl(iMan)
-{
-}
-
-// Object's destructor.
-
-CGroup::~CGroup()
-{
-}
-
-
-// Creates a new button.
-
-bool CGroup::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- CControl::Create(pos, dim, icon, eventMsg);
-
- if ( icon == -1 )
- {
- char name[100];
- char* p;
-
- GetResource(RES_EVENT, eventMsg, name);
- p = strchr(name, '\\');
- if ( p != 0 ) *p = 0;
- SetName(name);
- }
-
- return true;
-}
-
-
-// Management of an event.
-
-bool CGroup::EventProcess(const Event &event)
-{
- return true;
-}
-
-
-// Draw button.
-
-void CGroup::Draw()
-{
- Math::Point uv1,uv2, corner, pos, dim;
- float dp;
- int icon;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return;
-
- if ( m_state & STATE_SHADOW )
- {
- DrawShadow(m_pos, m_dim);
- }
-
- dp = 0.5f/256.0f;
-
- if ( m_icon == 0 ) // hollow frame?
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 160.0f/256.0f;
- uv1.y = 192.0f/256.0f; // u-v texture
- uv2.x = 192.0f/256.0f;
- uv2.y = 224.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 10.0f/640.0f;
- corner.y = 10.0f/480.0f;
- DrawIcon(m_pos, m_dim, uv1, uv2, corner, 8.0f/256.0f);
- }
- if ( m_icon == 1 ) // orange solid opaque?
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 104.0f/256.0f;
- uv1.y = 48.0f/256.0f;
- uv2.x = 112.0f/256.0f;
- uv2.y = 64.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(m_pos, m_dim, uv1, uv2);
- }
- if ( m_icon == 2 ) // orange degrade -> transparent?
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTw);
- uv1.x = 112.0f/256.0f;
- uv1.y = 48.0f/256.0f;
- uv2.x = 120.0f/256.0f;
- uv2.y = 64.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(m_pos, m_dim, uv1, uv2);
- }
- if ( m_icon == 3 ) // transparent gradient -> gray?
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTw);
- uv1.x = 120.0f/256.0f;
- uv1.y = 48.0f/256.0f;
- uv2.x = 128.0f/256.0f;
- uv2.y = 64.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(m_pos, m_dim, uv1, uv2);
- }
- if ( m_icon == 4 ) // degrade blue corner?
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTw);
- uv1.x = 192.0f/256.0f;
- uv1.y = 128.0f/256.0f;
- uv2.x = 224.0f/256.0f;
- uv2.y = 160.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(m_pos, m_dim, uv1, uv2);
- }
- if ( m_icon == 5 ) // degrade orange corner?
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTw);
- uv1.x = 224.0f/256.0f;
- uv1.y = 128.0f/256.0f;
- uv2.x = 256.0f/256.0f;
- uv2.y = 160.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(m_pos, m_dim, uv1, uv2);
- }
- if ( m_icon == 6 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTb);
- uv1.x = 0.0f/256.0f; // brown transparent
- uv1.y = 75.0f/256.0f;
- uv2.x = 64.0f/256.0f;
- uv2.y = 128.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 4.0f/640.0f;
- corner.y = 4.0f/480.0f;
- DrawIcon(m_pos, m_dim, uv1, uv2, corner, 8.0f/256.0f);
- }
- if ( m_icon == 7 )
- {
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 64.0f/256.0f;
- uv1.y = 0.0f/256.0f;
- uv2.x = 96.0f/256.0f;
- uv2.y = 32.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(m_pos, m_dim, uv1, uv2, 8.0f/256.0f);
- }
- if ( m_icon == 8 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTb);
- uv1.x = 64.0f/256.0f; // green transparent
- uv1.y = 160.0f/256.0f;
- uv2.x = 160.0f/256.0f;
- uv2.y = 176.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(m_pos, m_dim, uv1, uv2, 8.0f/256.0f);
- }
- if ( m_icon == 9 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTb);
- uv1.x = 64.0f/256.0f; // red transparent
- uv1.y = 176.0f/256.0f;
- uv2.x = 160.0f/256.0f;
- uv2.y = 192.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(m_pos, m_dim, uv1, uv2, 8.0f/256.0f);
- }
- if ( m_icon == 10 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTb);
- uv1.x = 64.0f/256.0f; // blue transparent
- uv1.y = 192.0f/256.0f;
- uv2.x = 160.0f/256.0f;
- uv2.y = 208.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(m_pos, m_dim, uv1, uv2, 8.0f/256.0f);
- }
- if ( m_icon == 11 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTb);
- uv1.x = 64.0f/256.0f; // yellow transparent
- uv1.y = 224.0f/256.0f;
- uv2.x = 160.0f/256.0f;
- uv2.y = 240.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(m_pos, m_dim, uv1, uv2, 8.0f/256.0f);
- }
- if ( m_icon == 12 ) // viewfinder cross?
- {
- dim.x = m_dim.x/2.0f;
- dim.y = m_dim.y/2.0f;
-
- m_engine->SetTexture("mouse.tga");
- m_engine->SetState(D3DSTATETTb);
- pos.x = m_pos.x-m_dim.x/300.0f;
- pos.y = m_pos.y+m_dim.y/300.0f+dim.y;
- uv1.x = 0.5f/256.0f;
- uv1.y = 192.5f/256.0f;
- uv2.x = 63.5f/256.0f;
- uv2.y = 255.5f/256.0f;
- DrawIcon(pos, dim, uv1, uv2); // ul
- pos.x += dim.x;
- Math::Swap(uv1.x, uv2.x);
- DrawIcon(pos, dim, uv1, uv2); // ur
- pos.y -= dim.y;
- Math::Swap(uv1.y, uv2.y);
- DrawIcon(pos, dim, uv1, uv2); // dr
- pos.x -= dim.x;
- Math::Swap(uv1.x, uv2.x);
- DrawIcon(pos, dim, uv1, uv2); // dl
-
- m_engine->SetState(D3DSTATETTw);
- pos.x = m_pos.x+m_dim.x/300.0f;
- pos.y = m_pos.y-m_dim.y/300.0f+dim.y;
- uv1.x = 64.5f/256.0f;
- uv1.y = 192.5f/256.0f;
- uv2.x = 127.5f/256.0f;
- uv2.y = 255.5f/256.0f;
- DrawIcon(pos, dim, uv1, uv2); // ul
- pos.x += dim.x;
- Math::Swap(uv1.x, uv2.x);
- DrawIcon(pos, dim, uv1, uv2); // ur
- pos.y -= dim.y;
- Math::Swap(uv1.y, uv2.y);
- DrawIcon(pos, dim, uv1, uv2); // dr
- pos.x -= dim.x;
- Math::Swap(uv1.x, uv2.x);
- DrawIcon(pos, dim, uv1, uv2); // dl
- }
- if ( m_icon == 13 ) // corner upper / left?
- {
- m_engine->SetTexture("mouse.tga");
- m_engine->SetState(D3DSTATETTb);
- pos.x = m_pos.x-m_dim.x/150.0f;
- pos.y = m_pos.y+m_dim.y/150.0f;
- uv1.x = 128.5f/256.0f;
- uv1.y = 192.5f/256.0f;
- uv2.x = 191.5f/256.0f;
- uv2.y = 255.5f/256.0f;
- DrawIcon(pos, m_dim, uv1, uv2);
-
- m_engine->SetState(D3DSTATETTw);
- pos.x = m_pos.x+m_dim.x/150.0f;
- pos.y = m_pos.y-m_dim.y/150.0f;
- uv1.x = 192.5f/256.0f;
- uv1.y = 192.5f/256.0f;
- uv2.x = 255.5f/256.0f;
- uv2.y = 255.5f/256.0f;
- DrawIcon(pos, m_dim, uv1, uv2);
- }
- if ( m_icon == 14 ) // corner upper / right?
- {
- m_engine->SetTexture("mouse.tga");
- m_engine->SetState(D3DSTATETTb);
- pos.x = m_pos.x-m_dim.x/150.0f;
- pos.y = m_pos.y+m_dim.y/150.0f;
- uv2.x = 128.5f/256.0f;
- uv1.y = 192.5f/256.0f;
- uv1.x = 191.5f/256.0f;
- uv2.y = 255.5f/256.0f;
- DrawIcon(pos, m_dim, uv1, uv2);
-
- m_engine->SetState(D3DSTATETTw);
- pos.x = m_pos.x+m_dim.x/150.0f;
- pos.y = m_pos.y-m_dim.y/150.0f;
- uv2.x = 192.5f/256.0f;
- uv1.y = 192.5f/256.0f;
- uv1.x = 255.5f/256.0f;
- uv2.y = 255.5f/256.0f;
- DrawIcon(pos, m_dim, uv1, uv2);
- }
- if ( m_icon == 15 ) // corner lower / left?
- {
- m_engine->SetTexture("mouse.tga");
- m_engine->SetState(D3DSTATETTb);
- pos.x = m_pos.x-m_dim.x/150.0f;
- pos.y = m_pos.y+m_dim.y/150.0f;
- uv1.x = 128.5f/256.0f;
- uv2.y = 192.5f/256.0f;
- uv2.x = 191.5f/256.0f;
- uv1.y = 255.5f/256.0f;
- DrawIcon(pos, m_dim, uv1, uv2);
-
- m_engine->SetState(D3DSTATETTw);
- pos.x = m_pos.x+m_dim.x/150.0f;
- pos.y = m_pos.y-m_dim.y/150.0f;
- uv1.x = 192.5f/256.0f;
- uv2.y = 192.5f/256.0f;
- uv2.x = 255.5f/256.0f;
- uv1.y = 255.5f/256.0f;
- DrawIcon(pos, m_dim, uv1, uv2);
- }
- if ( m_icon == 16 ) // corner lower / left?
- {
- m_engine->SetTexture("mouse.tga");
- m_engine->SetState(D3DSTATETTb);
- pos.x = m_pos.x-m_dim.x/150.0f;
- pos.y = m_pos.y+m_dim.y/150.0f;
- uv2.x = 128.5f/256.0f;
- uv2.y = 192.5f/256.0f;
- uv1.x = 191.5f/256.0f;
- uv1.y = 255.5f/256.0f;
- DrawIcon(pos, m_dim, uv1, uv2);
-
- m_engine->SetState(D3DSTATETTw);
- pos.x = m_pos.x+m_dim.x/150.0f;
- pos.y = m_pos.y-m_dim.y/150.0f;
- uv2.x = 192.5f/256.0f;
- uv2.y = 192.5f/256.0f;
- uv1.x = 255.5f/256.0f;
- uv1.y = 255.5f/256.0f;
- DrawIcon(pos, m_dim, uv1, uv2);
- }
- if ( m_icon == 17 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 0.0f/256.0f; // blue frame
- uv1.y = 75.0f/256.0f;
- uv2.x = 64.0f/256.0f;
- uv2.y = 128.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 6.0f/640.0f;
- corner.y = 6.0f/480.0f;
- DrawIcon(m_pos, m_dim, uv1, uv2, corner, 2.0f/256.0f);
- }
- if ( m_icon == 18 ) // arrow> for SatCom?
- {
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATETTw);
- uv1.x = 0.0f/256.0f; // >
- uv1.y = 192.0f/256.0f;
- uv2.x = 32.0f/256.0f;
- uv2.y = 224.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(m_pos, m_dim, uv1, uv2);
- }
- if ( m_icon == 19 ) // SatCom symbol?
- {
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATETTw);
- uv1.x = 224.0f/256.0f; // SatCom symbol
- uv1.y = 224.0f/256.0f;
- uv2.x = 256.0f/256.0f;
- uv2.y = 256.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(m_pos, m_dim, uv1, uv2);
- }
- if ( m_icon == 20 ) // solid blue background?
- {
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATETTw);
- uv1.x = 224.0f/256.0f;
- uv1.y = 32.0f/256.0f;
- uv2.x = 256.0f/256.0f;
- uv2.y = 64.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(m_pos, m_dim, uv1, uv2);
- }
- if ( m_icon == 21 ) // stand-by symbol?
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTw);
- uv1.x = 160.0f/256.0f;
- uv1.y = 32.0f/256.0f;
- uv2.x = 192.0f/256.0f;
- uv2.y = 64.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(m_pos, m_dim, uv1, uv2);
- }
- if ( m_icon == 22 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 64.0f/256.0f; // opaque yellow
- uv1.y = 224.0f/256.0f;
- uv2.x = 160.0f/256.0f;
- uv2.y = 240.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 5.0f/640.0f;
- corner.y = 5.0f/480.0f;
- DrawIcon(m_pos, m_dim, uv1, uv2, corner, 3.0f/256.0f);
- }
-
- if ( m_icon == 23 )
- {
- m_engine->SetTexture("button3.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 64.0f/256.0f; // yellow
- uv1.y = 192.0f/256.0f;
- uv2.x = 80.0f/256.0f;
- uv2.y = 208.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 4.0f/640.0f;
- corner.y = 4.0f/480.0f;
- DrawIcon(m_pos, m_dim, uv1, uv2, corner, 2.0f/256.0f);
- }
- if ( m_icon == 24 )
- {
- m_engine->SetTexture("button3.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 80.0f/256.0f; // orange
- uv1.y = 192.0f/256.0f;
- uv2.x = 96.0f/256.0f;
- uv2.y = 208.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 4.0f/640.0f;
- corner.y = 4.0f/480.0f;
- DrawIcon(m_pos, m_dim, uv1, uv2, corner, 2.0f/256.0f);
- }
- if ( m_icon == 25 )
- {
- m_engine->SetTexture("button3.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 64.0f/256.0f; // orange
- uv1.y = 208.0f/256.0f;
- uv2.x = 80.0f/256.0f;
- uv2.y = 224.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 4.0f/640.0f;
- corner.y = 4.0f/480.0f;
- DrawIcon(m_pos, m_dim, uv1, uv2, corner, 2.0f/256.0f);
- }
- if ( m_icon == 26 )
- {
- m_engine->SetTexture("button3.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 80.0f/256.0f; // red
- uv1.y = 208.0f/256.0f;
- uv2.x = 96.0f/256.0f;
- uv2.y = 224.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 4.0f/640.0f;
- corner.y = 4.0f/480.0f;
- DrawIcon(m_pos, m_dim, uv1, uv2, corner, 2.0f/256.0f);
- }
- if ( m_icon == 27 )
- {
- m_engine->SetTexture("button3.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 32.0f/256.0f;
- uv1.y = 0.0f/256.0f;
- uv2.x = 64.0f/256.0f;
- uv2.y = 32.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(m_pos, m_dim, uv1, uv2);
- }
-
- if ( m_icon >= 100 && m_icon <= 120 ) // building?
- {
- pos = m_pos;
- dim = m_dim;
-
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 32.0f/256.0f;
- uv1.y = 32.0f/256.0f;
- uv2.x = uv1.x+32.0f/256.0f;
- uv2.y = uv1.y+32.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2);
-
- m_engine->SetTexture("button3.tga");
- m_engine->SetState(D3DSTATENORMAL);
- pos.x += 8.0f/640.0f;
- pos.y += 8.0f/480.0f;
- dim.x -= 16.0f/640.0f;
- dim.y -= 16.0f/480.0f;
- uv1.x = 32.0f/256.0f;
- uv1.y = 0.0f/256.0f;
- uv2.x = uv1.x+32.0f/256.0f;
- uv2.y = uv1.y+32.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2);
-
- m_engine->SetState(D3DSTATENORMAL);
- pos.x += 2.0f/640.0f;
- pos.y += 2.0f/480.0f;
- dim.x -= 4.0f/640.0f;
- dim.y -= 4.0f/480.0f;
- uv1.x = 0.0f/256.0f;
- uv1.y = 0.0f/256.0f;
- uv2.x = uv1.x+32.0f/256.0f;
- uv2.y = uv1.y+32.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2);
-
- m_engine->SetState(D3DSTATETTb);
- pos.x += 8.0f/640.0f;
- pos.y += 8.0f/480.0f;
- dim.x -= 16.0f/640.0f;
- dim.y -= 16.0f/480.0f;
- if ( m_icon == 100 ) icon = 43; // base ?
- if ( m_icon == 101 ) icon = 32; // factory ?
- if ( m_icon == 102 ) icon = 35; // research ?
- if ( m_icon == 103 ) icon = 34; // convert ?
- if ( m_icon == 104 ) icon = 36; // station ?
- if ( m_icon == 105 ) icon = 40; // radar ?
- if ( m_icon == 106 ) icon = 41; // repair ?
- if ( m_icon == 107 ) icon = 37; // tower ?
- if ( m_icon == 108 ) icon = 39; // energy ?
- if ( m_icon == 109 ) icon = 33; // derrick ?
- if ( m_icon == 110 ) icon = 42; // nuclear ?
- if ( m_icon == 111 ) icon = 38; // labo ?
- if ( m_icon == 112 ) icon = 44; // info ?
- if ( m_icon == 113 ) icon = 46; // lightning protection ?
- if ( m_icon == 114 ) icon = 47; // vault ?
- if ( m_icon == 115 ) icon = 48; // control center?
- uv1.x = (32.0f/256.0f)*(icon%8);
- uv1.y = (32.0f/256.0f)*(icon/8); // uv texture
- uv2.x = uv1.x+32.0f/256.0f;
- uv2.y = uv1.y+32.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2);
- }
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// group.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "ui/group.h"
+
+
+
+
+// Object's constructor.
+
+CGroup::CGroup(CInstanceManager* iMan) : CControl(iMan)
+{
+}
+
+// Object's destructor.
+
+CGroup::~CGroup()
+{
+}
+
+
+// Creates a new button.
+
+bool CGroup::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ CControl::Create(pos, dim, icon, eventMsg);
+
+ if ( icon == -1 )
+ {
+ char name[100];
+ char* p;
+
+ GetResource(RES_EVENT, eventMsg, name);
+ p = strchr(name, '\\');
+ if ( p != 0 ) *p = 0;
+ SetName(name);
+ }
+
+ return true;
+}
+
+
+// Management of an event.
+
+bool CGroup::EventProcess(const Event &event)
+{
+ return true;
+}
+
+
+// Draw button.
+
+void CGroup::Draw()
+{
+ Math::Point uv1,uv2, corner, pos, dim;
+ float dp;
+ int icon;
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return;
+
+ if ( m_state & STATE_SHADOW )
+ {
+ DrawShadow(m_pos, m_dim);
+ }
+
+ dp = 0.5f/256.0f;
+
+ if ( m_icon == 0 ) // hollow frame?
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 160.0f/256.0f;
+ uv1.y = 192.0f/256.0f; // u-v texture
+ uv2.x = 192.0f/256.0f;
+ uv2.y = 224.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 10.0f/640.0f;
+ corner.y = 10.0f/480.0f;
+ DrawIcon(m_pos, m_dim, uv1, uv2, corner, 8.0f/256.0f);
+ }
+ if ( m_icon == 1 ) // orange solid opaque?
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 104.0f/256.0f;
+ uv1.y = 48.0f/256.0f;
+ uv2.x = 112.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(m_pos, m_dim, uv1, uv2);
+ }
+ if ( m_icon == 2 ) // orange degrade -> transparent?
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTw);
+ uv1.x = 112.0f/256.0f;
+ uv1.y = 48.0f/256.0f;
+ uv2.x = 120.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(m_pos, m_dim, uv1, uv2);
+ }
+ if ( m_icon == 3 ) // transparent gradient -> gray?
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTw);
+ uv1.x = 120.0f/256.0f;
+ uv1.y = 48.0f/256.0f;
+ uv2.x = 128.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(m_pos, m_dim, uv1, uv2);
+ }
+ if ( m_icon == 4 ) // degrade blue corner?
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTw);
+ uv1.x = 192.0f/256.0f;
+ uv1.y = 128.0f/256.0f;
+ uv2.x = 224.0f/256.0f;
+ uv2.y = 160.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(m_pos, m_dim, uv1, uv2);
+ }
+ if ( m_icon == 5 ) // degrade orange corner?
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTw);
+ uv1.x = 224.0f/256.0f;
+ uv1.y = 128.0f/256.0f;
+ uv2.x = 256.0f/256.0f;
+ uv2.y = 160.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(m_pos, m_dim, uv1, uv2);
+ }
+ if ( m_icon == 6 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTb);
+ uv1.x = 0.0f/256.0f; // brown transparent
+ uv1.y = 75.0f/256.0f;
+ uv2.x = 64.0f/256.0f;
+ uv2.y = 128.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 4.0f/640.0f;
+ corner.y = 4.0f/480.0f;
+ DrawIcon(m_pos, m_dim, uv1, uv2, corner, 8.0f/256.0f);
+ }
+ if ( m_icon == 7 )
+ {
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 64.0f/256.0f;
+ uv1.y = 0.0f/256.0f;
+ uv2.x = 96.0f/256.0f;
+ uv2.y = 32.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(m_pos, m_dim, uv1, uv2, 8.0f/256.0f);
+ }
+ if ( m_icon == 8 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTb);
+ uv1.x = 64.0f/256.0f; // green transparent
+ uv1.y = 160.0f/256.0f;
+ uv2.x = 160.0f/256.0f;
+ uv2.y = 176.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(m_pos, m_dim, uv1, uv2, 8.0f/256.0f);
+ }
+ if ( m_icon == 9 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTb);
+ uv1.x = 64.0f/256.0f; // red transparent
+ uv1.y = 176.0f/256.0f;
+ uv2.x = 160.0f/256.0f;
+ uv2.y = 192.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(m_pos, m_dim, uv1, uv2, 8.0f/256.0f);
+ }
+ if ( m_icon == 10 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTb);
+ uv1.x = 64.0f/256.0f; // blue transparent
+ uv1.y = 192.0f/256.0f;
+ uv2.x = 160.0f/256.0f;
+ uv2.y = 208.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(m_pos, m_dim, uv1, uv2, 8.0f/256.0f);
+ }
+ if ( m_icon == 11 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTb);
+ uv1.x = 64.0f/256.0f; // yellow transparent
+ uv1.y = 224.0f/256.0f;
+ uv2.x = 160.0f/256.0f;
+ uv2.y = 240.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(m_pos, m_dim, uv1, uv2, 8.0f/256.0f);
+ }
+ if ( m_icon == 12 ) // viewfinder cross?
+ {
+ dim.x = m_dim.x/2.0f;
+ dim.y = m_dim.y/2.0f;
+
+ m_engine->SetTexture("mouse.tga");
+ m_engine->SetState(D3DSTATETTb);
+ pos.x = m_pos.x-m_dim.x/300.0f;
+ pos.y = m_pos.y+m_dim.y/300.0f+dim.y;
+ uv1.x = 0.5f/256.0f;
+ uv1.y = 192.5f/256.0f;
+ uv2.x = 63.5f/256.0f;
+ uv2.y = 255.5f/256.0f;
+ DrawIcon(pos, dim, uv1, uv2); // ul
+ pos.x += dim.x;
+ Math::Swap(uv1.x, uv2.x);
+ DrawIcon(pos, dim, uv1, uv2); // ur
+ pos.y -= dim.y;
+ Math::Swap(uv1.y, uv2.y);
+ DrawIcon(pos, dim, uv1, uv2); // dr
+ pos.x -= dim.x;
+ Math::Swap(uv1.x, uv2.x);
+ DrawIcon(pos, dim, uv1, uv2); // dl
+
+ m_engine->SetState(D3DSTATETTw);
+ pos.x = m_pos.x+m_dim.x/300.0f;
+ pos.y = m_pos.y-m_dim.y/300.0f+dim.y;
+ uv1.x = 64.5f/256.0f;
+ uv1.y = 192.5f/256.0f;
+ uv2.x = 127.5f/256.0f;
+ uv2.y = 255.5f/256.0f;
+ DrawIcon(pos, dim, uv1, uv2); // ul
+ pos.x += dim.x;
+ Math::Swap(uv1.x, uv2.x);
+ DrawIcon(pos, dim, uv1, uv2); // ur
+ pos.y -= dim.y;
+ Math::Swap(uv1.y, uv2.y);
+ DrawIcon(pos, dim, uv1, uv2); // dr
+ pos.x -= dim.x;
+ Math::Swap(uv1.x, uv2.x);
+ DrawIcon(pos, dim, uv1, uv2); // dl
+ }
+ if ( m_icon == 13 ) // corner upper / left?
+ {
+ m_engine->SetTexture("mouse.tga");
+ m_engine->SetState(D3DSTATETTb);
+ pos.x = m_pos.x-m_dim.x/150.0f;
+ pos.y = m_pos.y+m_dim.y/150.0f;
+ uv1.x = 128.5f/256.0f;
+ uv1.y = 192.5f/256.0f;
+ uv2.x = 191.5f/256.0f;
+ uv2.y = 255.5f/256.0f;
+ DrawIcon(pos, m_dim, uv1, uv2);
+
+ m_engine->SetState(D3DSTATETTw);
+ pos.x = m_pos.x+m_dim.x/150.0f;
+ pos.y = m_pos.y-m_dim.y/150.0f;
+ uv1.x = 192.5f/256.0f;
+ uv1.y = 192.5f/256.0f;
+ uv2.x = 255.5f/256.0f;
+ uv2.y = 255.5f/256.0f;
+ DrawIcon(pos, m_dim, uv1, uv2);
+ }
+ if ( m_icon == 14 ) // corner upper / right?
+ {
+ m_engine->SetTexture("mouse.tga");
+ m_engine->SetState(D3DSTATETTb);
+ pos.x = m_pos.x-m_dim.x/150.0f;
+ pos.y = m_pos.y+m_dim.y/150.0f;
+ uv2.x = 128.5f/256.0f;
+ uv1.y = 192.5f/256.0f;
+ uv1.x = 191.5f/256.0f;
+ uv2.y = 255.5f/256.0f;
+ DrawIcon(pos, m_dim, uv1, uv2);
+
+ m_engine->SetState(D3DSTATETTw);
+ pos.x = m_pos.x+m_dim.x/150.0f;
+ pos.y = m_pos.y-m_dim.y/150.0f;
+ uv2.x = 192.5f/256.0f;
+ uv1.y = 192.5f/256.0f;
+ uv1.x = 255.5f/256.0f;
+ uv2.y = 255.5f/256.0f;
+ DrawIcon(pos, m_dim, uv1, uv2);
+ }
+ if ( m_icon == 15 ) // corner lower / left?
+ {
+ m_engine->SetTexture("mouse.tga");
+ m_engine->SetState(D3DSTATETTb);
+ pos.x = m_pos.x-m_dim.x/150.0f;
+ pos.y = m_pos.y+m_dim.y/150.0f;
+ uv1.x = 128.5f/256.0f;
+ uv2.y = 192.5f/256.0f;
+ uv2.x = 191.5f/256.0f;
+ uv1.y = 255.5f/256.0f;
+ DrawIcon(pos, m_dim, uv1, uv2);
+
+ m_engine->SetState(D3DSTATETTw);
+ pos.x = m_pos.x+m_dim.x/150.0f;
+ pos.y = m_pos.y-m_dim.y/150.0f;
+ uv1.x = 192.5f/256.0f;
+ uv2.y = 192.5f/256.0f;
+ uv2.x = 255.5f/256.0f;
+ uv1.y = 255.5f/256.0f;
+ DrawIcon(pos, m_dim, uv1, uv2);
+ }
+ if ( m_icon == 16 ) // corner lower / left?
+ {
+ m_engine->SetTexture("mouse.tga");
+ m_engine->SetState(D3DSTATETTb);
+ pos.x = m_pos.x-m_dim.x/150.0f;
+ pos.y = m_pos.y+m_dim.y/150.0f;
+ uv2.x = 128.5f/256.0f;
+ uv2.y = 192.5f/256.0f;
+ uv1.x = 191.5f/256.0f;
+ uv1.y = 255.5f/256.0f;
+ DrawIcon(pos, m_dim, uv1, uv2);
+
+ m_engine->SetState(D3DSTATETTw);
+ pos.x = m_pos.x+m_dim.x/150.0f;
+ pos.y = m_pos.y-m_dim.y/150.0f;
+ uv2.x = 192.5f/256.0f;
+ uv2.y = 192.5f/256.0f;
+ uv1.x = 255.5f/256.0f;
+ uv1.y = 255.5f/256.0f;
+ DrawIcon(pos, m_dim, uv1, uv2);
+ }
+ if ( m_icon == 17 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 0.0f/256.0f; // blue frame
+ uv1.y = 75.0f/256.0f;
+ uv2.x = 64.0f/256.0f;
+ uv2.y = 128.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 6.0f/640.0f;
+ corner.y = 6.0f/480.0f;
+ DrawIcon(m_pos, m_dim, uv1, uv2, corner, 2.0f/256.0f);
+ }
+ if ( m_icon == 18 ) // arrow> for SatCom?
+ {
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATETTw);
+ uv1.x = 0.0f/256.0f; // >
+ uv1.y = 192.0f/256.0f;
+ uv2.x = 32.0f/256.0f;
+ uv2.y = 224.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(m_pos, m_dim, uv1, uv2);
+ }
+ if ( m_icon == 19 ) // SatCom symbol?
+ {
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATETTw);
+ uv1.x = 224.0f/256.0f; // SatCom symbol
+ uv1.y = 224.0f/256.0f;
+ uv2.x = 256.0f/256.0f;
+ uv2.y = 256.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(m_pos, m_dim, uv1, uv2);
+ }
+ if ( m_icon == 20 ) // solid blue background?
+ {
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATETTw);
+ uv1.x = 224.0f/256.0f;
+ uv1.y = 32.0f/256.0f;
+ uv2.x = 256.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(m_pos, m_dim, uv1, uv2);
+ }
+ if ( m_icon == 21 ) // stand-by symbol?
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTw);
+ uv1.x = 160.0f/256.0f;
+ uv1.y = 32.0f/256.0f;
+ uv2.x = 192.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(m_pos, m_dim, uv1, uv2);
+ }
+ if ( m_icon == 22 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 64.0f/256.0f; // opaque yellow
+ uv1.y = 224.0f/256.0f;
+ uv2.x = 160.0f/256.0f;
+ uv2.y = 240.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 5.0f/640.0f;
+ corner.y = 5.0f/480.0f;
+ DrawIcon(m_pos, m_dim, uv1, uv2, corner, 3.0f/256.0f);
+ }
+
+ if ( m_icon == 23 )
+ {
+ m_engine->SetTexture("button3.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 64.0f/256.0f; // yellow
+ uv1.y = 192.0f/256.0f;
+ uv2.x = 80.0f/256.0f;
+ uv2.y = 208.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 4.0f/640.0f;
+ corner.y = 4.0f/480.0f;
+ DrawIcon(m_pos, m_dim, uv1, uv2, corner, 2.0f/256.0f);
+ }
+ if ( m_icon == 24 )
+ {
+ m_engine->SetTexture("button3.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 80.0f/256.0f; // orange
+ uv1.y = 192.0f/256.0f;
+ uv2.x = 96.0f/256.0f;
+ uv2.y = 208.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 4.0f/640.0f;
+ corner.y = 4.0f/480.0f;
+ DrawIcon(m_pos, m_dim, uv1, uv2, corner, 2.0f/256.0f);
+ }
+ if ( m_icon == 25 )
+ {
+ m_engine->SetTexture("button3.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 64.0f/256.0f; // orange
+ uv1.y = 208.0f/256.0f;
+ uv2.x = 80.0f/256.0f;
+ uv2.y = 224.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 4.0f/640.0f;
+ corner.y = 4.0f/480.0f;
+ DrawIcon(m_pos, m_dim, uv1, uv2, corner, 2.0f/256.0f);
+ }
+ if ( m_icon == 26 )
+ {
+ m_engine->SetTexture("button3.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 80.0f/256.0f; // red
+ uv1.y = 208.0f/256.0f;
+ uv2.x = 96.0f/256.0f;
+ uv2.y = 224.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 4.0f/640.0f;
+ corner.y = 4.0f/480.0f;
+ DrawIcon(m_pos, m_dim, uv1, uv2, corner, 2.0f/256.0f);
+ }
+ if ( m_icon == 27 )
+ {
+ m_engine->SetTexture("button3.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 32.0f/256.0f;
+ uv1.y = 0.0f/256.0f;
+ uv2.x = 64.0f/256.0f;
+ uv2.y = 32.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(m_pos, m_dim, uv1, uv2);
+ }
+
+ if ( m_icon >= 100 && m_icon <= 120 ) // building?
+ {
+ pos = m_pos;
+ dim = m_dim;
+
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 32.0f/256.0f;
+ uv1.y = 32.0f/256.0f;
+ uv2.x = uv1.x+32.0f/256.0f;
+ uv2.y = uv1.y+32.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2);
+
+ m_engine->SetTexture("button3.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ pos.x += 8.0f/640.0f;
+ pos.y += 8.0f/480.0f;
+ dim.x -= 16.0f/640.0f;
+ dim.y -= 16.0f/480.0f;
+ uv1.x = 32.0f/256.0f;
+ uv1.y = 0.0f/256.0f;
+ uv2.x = uv1.x+32.0f/256.0f;
+ uv2.y = uv1.y+32.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2);
+
+ m_engine->SetState(D3DSTATENORMAL);
+ pos.x += 2.0f/640.0f;
+ pos.y += 2.0f/480.0f;
+ dim.x -= 4.0f/640.0f;
+ dim.y -= 4.0f/480.0f;
+ uv1.x = 0.0f/256.0f;
+ uv1.y = 0.0f/256.0f;
+ uv2.x = uv1.x+32.0f/256.0f;
+ uv2.y = uv1.y+32.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2);
+
+ m_engine->SetState(D3DSTATETTb);
+ pos.x += 8.0f/640.0f;
+ pos.y += 8.0f/480.0f;
+ dim.x -= 16.0f/640.0f;
+ dim.y -= 16.0f/480.0f;
+ if ( m_icon == 100 ) icon = 43; // base ?
+ if ( m_icon == 101 ) icon = 32; // factory ?
+ if ( m_icon == 102 ) icon = 35; // research ?
+ if ( m_icon == 103 ) icon = 34; // convert ?
+ if ( m_icon == 104 ) icon = 36; // station ?
+ if ( m_icon == 105 ) icon = 40; // radar ?
+ if ( m_icon == 106 ) icon = 41; // repair ?
+ if ( m_icon == 107 ) icon = 37; // tower ?
+ if ( m_icon == 108 ) icon = 39; // energy ?
+ if ( m_icon == 109 ) icon = 33; // derrick ?
+ if ( m_icon == 110 ) icon = 42; // nuclear ?
+ if ( m_icon == 111 ) icon = 38; // labo ?
+ if ( m_icon == 112 ) icon = 44; // info ?
+ if ( m_icon == 113 ) icon = 46; // lightning protection ?
+ if ( m_icon == 114 ) icon = 47; // vault ?
+ if ( m_icon == 115 ) icon = 48; // control center?
+ uv1.x = (32.0f/256.0f)*(icon%8);
+ uv1.y = (32.0f/256.0f)*(icon/8); // uv texture
+ uv2.x = uv1.x+32.0f/256.0f;
+ uv2.y = uv1.y+32.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2);
+ }
+}
+
+
diff --git a/src/ui/group.h b/src/ui/group.h
index 3133b54..baf609f 100644
--- a/src/ui/group.h
+++ b/src/ui/group.h
@@ -1,46 +1,46 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// group.h
-
-#pragma once
-
-
-#include "ui/control.h"
-
-
-class CD3DEngine;
-
-
-
-class CGroup : public CControl
-{
-public:
- CGroup(CInstanceManager* iMan);
- virtual ~CGroup();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
-
- bool EventProcess(const Event &event);
-
- void Draw();
-
-protected:
-
-protected:
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// group.h
+
+#pragma once
+
+
+#include "ui/control.h"
+
+
+class CD3DEngine;
+
+
+
+class CGroup : public CControl
+{
+public:
+ CGroup(CInstanceManager* iMan);
+ virtual ~CGroup();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+
+ bool EventProcess(const Event &event);
+
+ void Draw();
+
+protected:
+
+protected:
+};
+
+
diff --git a/src/ui/image.cpp b/src/ui/image.cpp
index 1803a1c..8bf46fb 100644
--- a/src/ui/image.cpp
+++ b/src/ui/image.cpp
@@ -1,155 +1,155 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// image.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "ui/image.h"
-
-
-
-
-// Object's constructor.
-
-CImage::CImage(CInstanceManager* iMan) : CControl(iMan)
-{
- m_filename[0] = 0;
-}
-
-// Object's destructor.
-
-CImage::~CImage()
-{
- if ( m_filename[0] != 0 )
- {
- m_engine->FreeTexture(m_filename);
- }
-}
-
-
-// Creates a new button.
-
-bool CImage::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- CControl::Create(pos, dim, icon, eventMsg);
-
- if ( icon == -1 )
- {
- char name[100];
- char* p;
-
- GetResource(RES_EVENT, eventMsg, name);
- p = strchr(name, '\\');
- if ( p != 0 ) *p = 0;
- SetName(name);
- }
-
- return true;
-}
-
-
-// Specifies the name of the image display.
-
-void CImage::SetFilenameImage(char *name)
-{
- if ( m_filename[0] != 0 )
- {
- m_engine->FreeTexture(m_filename);
- }
-
- strcpy(m_filename, name);
-}
-
-char* CImage::RetFilenameImage()
-{
- return m_filename;
-}
-
-
-// Management of an event.
-
-bool CImage::EventProcess(const Event &event)
-{
- return true;
-}
-
-
-// Draws button.
-
-void CImage::Draw()
-{
- Math::Point uv1,uv2, corner, pos, dim;
- float dp;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return;
-
- if ( m_state & STATE_SHADOW )
- {
- DrawShadow(m_pos, m_dim);
- }
-
- dp = 0.5f/256.0f;
-
- if ( m_icon == 0 ) // hollow frame?
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 160.0f/256.0f;
- uv1.y = 192.0f/256.0f; // u-v texture
- uv2.x = 192.0f/256.0f;
- uv2.y = 224.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 10.0f/640.0f;
- corner.y = 10.0f/480.0f;
- DrawIcon(m_pos, m_dim, uv1, uv2, corner, 8.0f/256.0f);
- }
-
- if ( m_filename[0] != 0 ) // displays an image?
- {
- m_engine->LoadTexture(m_filename);
- m_engine->SetTexture(m_filename);
- m_engine->SetState(D3DSTATENORMAL);
- pos = m_pos;
- dim = m_dim;
- pos.x += 5.0f/640.0f;
- pos.y += 5.0f/480.0f;
- dim.x -= 10.0f/640.0f;
- dim.y -= 10.0f/480.0f;
- uv1.x = 0.0f;
- uv1.y = 0.0f;
- uv2.x = 1.0f;
- uv2.y = 1.0f;
- DrawIcon(pos, dim, uv1, uv2);
- }
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// image.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "ui/image.h"
+
+
+
+
+// Object's constructor.
+
+CImage::CImage(CInstanceManager* iMan) : CControl(iMan)
+{
+ m_filename[0] = 0;
+}
+
+// Object's destructor.
+
+CImage::~CImage()
+{
+ if ( m_filename[0] != 0 )
+ {
+ m_engine->FreeTexture(m_filename);
+ }
+}
+
+
+// Creates a new button.
+
+bool CImage::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ CControl::Create(pos, dim, icon, eventMsg);
+
+ if ( icon == -1 )
+ {
+ char name[100];
+ char* p;
+
+ GetResource(RES_EVENT, eventMsg, name);
+ p = strchr(name, '\\');
+ if ( p != 0 ) *p = 0;
+ SetName(name);
+ }
+
+ return true;
+}
+
+
+// Specifies the name of the image display.
+
+void CImage::SetFilenameImage(char *name)
+{
+ if ( m_filename[0] != 0 )
+ {
+ m_engine->FreeTexture(m_filename);
+ }
+
+ strcpy(m_filename, name);
+}
+
+char* CImage::RetFilenameImage()
+{
+ return m_filename;
+}
+
+
+// Management of an event.
+
+bool CImage::EventProcess(const Event &event)
+{
+ return true;
+}
+
+
+// Draws button.
+
+void CImage::Draw()
+{
+ Math::Point uv1,uv2, corner, pos, dim;
+ float dp;
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return;
+
+ if ( m_state & STATE_SHADOW )
+ {
+ DrawShadow(m_pos, m_dim);
+ }
+
+ dp = 0.5f/256.0f;
+
+ if ( m_icon == 0 ) // hollow frame?
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 160.0f/256.0f;
+ uv1.y = 192.0f/256.0f; // u-v texture
+ uv2.x = 192.0f/256.0f;
+ uv2.y = 224.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 10.0f/640.0f;
+ corner.y = 10.0f/480.0f;
+ DrawIcon(m_pos, m_dim, uv1, uv2, corner, 8.0f/256.0f);
+ }
+
+ if ( m_filename[0] != 0 ) // displays an image?
+ {
+ m_engine->LoadTexture(m_filename);
+ m_engine->SetTexture(m_filename);
+ m_engine->SetState(D3DSTATENORMAL);
+ pos = m_pos;
+ dim = m_dim;
+ pos.x += 5.0f/640.0f;
+ pos.y += 5.0f/480.0f;
+ dim.x -= 10.0f/640.0f;
+ dim.y -= 10.0f/480.0f;
+ uv1.x = 0.0f;
+ uv1.y = 0.0f;
+ uv2.x = 1.0f;
+ uv2.y = 1.0f;
+ DrawIcon(pos, dim, uv1, uv2);
+ }
+}
+
+
diff --git a/src/ui/image.h b/src/ui/image.h
index d327598..85c5962 100644
--- a/src/ui/image.h
+++ b/src/ui/image.h
@@ -1,50 +1,50 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// image.h
-
-#pragma once
-
-
-#include "ui/control.h"
-
-
-class CD3DEngine;
-
-
-
-class CImage : public CControl
-{
-public:
- CImage(CInstanceManager* iMan);
- virtual ~CImage();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
-
- bool EventProcess(const Event &event);
-
- void Draw();
-
- void SetFilenameImage(char *name);
- char* RetFilenameImage();
-
-protected:
-
-protected:
- char m_filename[100];
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// image.h
+
+#pragma once
+
+
+#include "ui/control.h"
+
+
+class CD3DEngine;
+
+
+
+class CImage : public CControl
+{
+public:
+ CImage(CInstanceManager* iMan);
+ virtual ~CImage();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+
+ bool EventProcess(const Event &event);
+
+ void Draw();
+
+ void SetFilenameImage(char *name);
+ char* RetFilenameImage();
+
+protected:
+
+protected:
+ char m_filename[100];
+};
+
+
diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp
index a089dc3..50d2352 100644
--- a/src/ui/interface.cpp
+++ b/src/ui/interface.cpp
@@ -1,605 +1,605 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// interface.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "ui/control.h"
-#include "ui/button.h"
-#include "ui/color.h"
-#include "ui/check.h"
-#include "ui/key.h"
-#include "ui/group.h"
-#include "ui/image.h"
-#include "ui/label.h"
-#include "ui/edit.h"
-#include "ui/editvalue.h"
-#include "ui/scroll.h"
-#include "ui/slider.h"
-#include "ui/list.h"
-#include "ui/shortcut.h"
-#include "ui/compass.h"
-#include "ui/target.h"
-#include "ui/map.h"
-#include "ui/window.h"
-#include "old/camera.h"
-#include "ui/interface.h"
-
-
-
-
-// Object's constructor.
-
-CInterface::CInterface(CInstanceManager* iMan)
-{
- int i;
-
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_INTERFACE, this);
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_camera = 0;
-
- for ( i=0 ; i<MAXCONTROL ; i++ )
- {
- m_table[i] = 0;
- }
-}
-
-// Object's destructor.
-
-CInterface::~CInterface()
-{
- Flush();
-}
-
-
-// Purge all controls.
-
-void CInterface::Flush()
-{
- int i;
-
- for ( i=0 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] != 0 )
- {
- delete m_table[i];
- m_table[i] = 0;
- }
- }
-}
-
-
-// Creates a new button.
-
-CWindow* CInterface::CreateWindows(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CWindow* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- if ( eventMsg == EVENT_WINDOW0 ) {i=0; goto create;}
- if ( eventMsg == EVENT_WINDOW1 ) {i=1; goto create;}
- if ( eventMsg == EVENT_WINDOW2 ) {i=2; goto create;}
- if ( eventMsg == EVENT_WINDOW3 ) {i=3; goto create;}
- if ( eventMsg == EVENT_WINDOW4 ) {i=4; goto create;}
- if ( eventMsg == EVENT_WINDOW5 ) {i=5; goto create;}
- if ( eventMsg == EVENT_WINDOW6 ) {i=6; goto create;}
- if ( eventMsg == EVENT_WINDOW7 ) {i=7; goto create;}
- if ( eventMsg == EVENT_WINDOW8 ) {i=8; goto create;}
- if ( eventMsg == EVENT_WINDOW9 ) {i=9; goto create;}
-
- if ( eventMsg == EVENT_TOOLTIP ) {i=MAXCONTROL-1; goto create;}
-
- for ( i=10 ; i<MAXCONTROL-1 ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- create:
- m_table[i] = new CWindow(m_iMan);
- pc = (CWindow*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new button.
-
-CButton* CInterface::CreateButton(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CButton* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=10 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CButton(m_iMan);
- pc = (CButton*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new button.
-
-CColor* CInterface::CreateColor(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CColor* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=10 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CColor(m_iMan);
- pc = (CColor*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new button.
-
-CCheck* CInterface::CreateCheck(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CCheck* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=10 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CCheck(m_iMan);
- pc = (CCheck*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new button.
-
-CKey* CInterface::CreateKey(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CKey* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=10 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CKey(m_iMan);
- pc = (CKey*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new button.
-
-CGroup* CInterface::CreateGroup(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CGroup* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=10 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CGroup(m_iMan);
- pc = (CGroup*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new button.
-
-CImage* CInterface::CreateImage(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CImage* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=10 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CImage(m_iMan);
- pc = (CImage*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new label.
-
-CLabel* CInterface::CreateLabel(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg,
- char *name)
-{
- CLabel* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=10 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CLabel(m_iMan);
- pc = (CLabel*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- pc->SetName(name);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new pave editable.
-
-CEdit* CInterface::CreateEdit(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CEdit* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=10 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CEdit(m_iMan);
- pc = (CEdit*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new pave editable.
-
-CEditValue* CInterface::CreateEditValue(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CEditValue* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=10 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CEditValue(m_iMan);
- pc = (CEditValue*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new lift.
-
-CScroll* CInterface::CreateScroll(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CScroll* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=10 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CScroll(m_iMan);
- pc = (CScroll*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new cursor.
-
-CSlider* CInterface::CreateSlider(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CSlider* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=10 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CSlider(m_iMan);
- pc = (CSlider*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new list.
-
-CList* CInterface::CreateList(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg,
- float expand)
-{
- CList* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=10 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CList(m_iMan);
- pc = (CList*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg, expand);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new shortcut.
-
-CShortcut* CInterface::CreateShortcut(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CShortcut* ps;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=10 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CShortcut(m_iMan);
- ps = (CShortcut*)m_table[i];
- ps->Create(pos, dim, icon, eventMsg);
- return ps;
- }
- }
- return 0;
-}
-
-// Creates a new compass.
-
-CCompass* CInterface::CreateCompass(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CCompass* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=10 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CCompass(m_iMan);
- pc = (CCompass*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new target.
-
-CTarget* CInterface::CreateTarget(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CTarget* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=10 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CTarget(m_iMan);
- pc = (CTarget*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new map.
-
-CMap* CInterface::CreateMap(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CMap* pm;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=10 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CMap(m_iMan);
- pm = (CMap*)m_table[i];
- pm->Create(pos, dim, icon, eventMsg);
- return pm;
- }
- }
- return 0;
-}
-
-// Removes a control.
-
-bool CInterface::DeleteControl(EventMsg eventMsg)
-{
- int i;
-
- for ( i=0 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] != 0 )
- {
- if ( eventMsg == m_table[i]->RetEventMsg() )
- {
- delete m_table[i];
- m_table[i] = 0;
- return true;
- }
- }
- }
- return false;
-}
-
-// Gives a control.
-
-CControl* CInterface::SearchControl(EventMsg eventMsg)
-{
- int i;
-
- for ( i=0 ; i<MAXCONTROL ; i++ )
- {
- if ( m_table[i] != 0 )
- {
- if ( eventMsg == m_table[i]->RetEventMsg() )
- {
- return m_table[i];
- }
- }
- }
- return 0;
-}
-
-// Management of an event.
-
-bool CInterface::EventProcess(const Event &event)
-{
- int i;
-
- if ( event.event == EVENT_MOUSEMOVE )
- {
- if ( m_camera == 0 )
- {
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- }
- m_engine->SetMouseType(m_camera->RetMouseDef(event.pos));
- }
-
- for ( i=MAXCONTROL-1 ; i>=0 ; i-- )
- {
- if ( m_table[i] != 0 &&
- m_table[i]->TestState(STATE_ENABLE) )
- {
- if ( !m_table[i]->EventProcess(event) )
- {
- return false;
- }
- }
- }
-
- return true;
-}
-
-
-// Gives the tooltip binding to the window.
-
-bool CInterface::GetTooltip(Math::Point pos, char* name)
-{
- int i;
-
- for ( i=MAXCONTROL-1 ; i>=0 ; i-- )
- {
- if ( m_table[i] != 0 )
- {
- if ( m_table[i]->GetTooltip(pos, name) )
- {
- return true;
- }
- }
- }
- return false;
-}
-
-
-// Draws all buttons.
-
-void CInterface::Draw()
-{
- D3DMATERIAL7 material;
- int i;
-
- ZeroMemory( &material, sizeof(D3DMATERIAL7) );
- material.diffuse.r = 1.0f;
- material.diffuse.g = 1.0f;
- material.diffuse.b = 1.0f;
- material.ambient.r = 0.5f;
- material.ambient.g = 0.5f;
- material.ambient.b = 0.5f;
- m_engine->SetMaterial(material);
-
- for ( i=0 ; i<MAXCONTROL ; i++ )
-//? for ( i=MAXCONTROL-1 ; i>=0 ; i-- )
- {
- if ( m_table[i] != 0 )
- {
- m_table[i]->Draw();
- }
- }
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// interface.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "ui/control.h"
+#include "ui/button.h"
+#include "ui/color.h"
+#include "ui/check.h"
+#include "ui/key.h"
+#include "ui/group.h"
+#include "ui/image.h"
+#include "ui/label.h"
+#include "ui/edit.h"
+#include "ui/editvalue.h"
+#include "ui/scroll.h"
+#include "ui/slider.h"
+#include "ui/list.h"
+#include "ui/shortcut.h"
+#include "ui/compass.h"
+#include "ui/target.h"
+#include "ui/map.h"
+#include "ui/window.h"
+#include "old/camera.h"
+#include "ui/interface.h"
+
+
+
+
+// Object's constructor.
+
+CInterface::CInterface(CInstanceManager* iMan)
+{
+ int i;
+
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_INTERFACE, this);
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_camera = 0;
+
+ for ( i=0 ; i<MAXCONTROL ; i++ )
+ {
+ m_table[i] = 0;
+ }
+}
+
+// Object's destructor.
+
+CInterface::~CInterface()
+{
+ Flush();
+}
+
+
+// Purge all controls.
+
+void CInterface::Flush()
+{
+ int i;
+
+ for ( i=0 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] != 0 )
+ {
+ delete m_table[i];
+ m_table[i] = 0;
+ }
+ }
+}
+
+
+// Creates a new button.
+
+CWindow* CInterface::CreateWindows(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CWindow* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ if ( eventMsg == EVENT_WINDOW0 ) {i=0; goto create;}
+ if ( eventMsg == EVENT_WINDOW1 ) {i=1; goto create;}
+ if ( eventMsg == EVENT_WINDOW2 ) {i=2; goto create;}
+ if ( eventMsg == EVENT_WINDOW3 ) {i=3; goto create;}
+ if ( eventMsg == EVENT_WINDOW4 ) {i=4; goto create;}
+ if ( eventMsg == EVENT_WINDOW5 ) {i=5; goto create;}
+ if ( eventMsg == EVENT_WINDOW6 ) {i=6; goto create;}
+ if ( eventMsg == EVENT_WINDOW7 ) {i=7; goto create;}
+ if ( eventMsg == EVENT_WINDOW8 ) {i=8; goto create;}
+ if ( eventMsg == EVENT_WINDOW9 ) {i=9; goto create;}
+
+ if ( eventMsg == EVENT_TOOLTIP ) {i=MAXCONTROL-1; goto create;}
+
+ for ( i=10 ; i<MAXCONTROL-1 ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ create:
+ m_table[i] = new CWindow(m_iMan);
+ pc = (CWindow*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new button.
+
+CButton* CInterface::CreateButton(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CButton* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=10 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CButton(m_iMan);
+ pc = (CButton*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new button.
+
+CColor* CInterface::CreateColor(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CColor* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=10 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CColor(m_iMan);
+ pc = (CColor*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new button.
+
+CCheck* CInterface::CreateCheck(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CCheck* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=10 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CCheck(m_iMan);
+ pc = (CCheck*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new button.
+
+CKey* CInterface::CreateKey(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CKey* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=10 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CKey(m_iMan);
+ pc = (CKey*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new button.
+
+CGroup* CInterface::CreateGroup(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CGroup* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=10 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CGroup(m_iMan);
+ pc = (CGroup*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new button.
+
+CImage* CInterface::CreateImage(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CImage* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=10 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CImage(m_iMan);
+ pc = (CImage*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new label.
+
+CLabel* CInterface::CreateLabel(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg,
+ char *name)
+{
+ CLabel* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=10 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CLabel(m_iMan);
+ pc = (CLabel*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ pc->SetName(name);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new pave editable.
+
+CEdit* CInterface::CreateEdit(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CEdit* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=10 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CEdit(m_iMan);
+ pc = (CEdit*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new pave editable.
+
+CEditValue* CInterface::CreateEditValue(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CEditValue* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=10 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CEditValue(m_iMan);
+ pc = (CEditValue*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new lift.
+
+CScroll* CInterface::CreateScroll(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CScroll* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=10 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CScroll(m_iMan);
+ pc = (CScroll*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new cursor.
+
+CSlider* CInterface::CreateSlider(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CSlider* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=10 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CSlider(m_iMan);
+ pc = (CSlider*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new list.
+
+CList* CInterface::CreateList(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg,
+ float expand)
+{
+ CList* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=10 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CList(m_iMan);
+ pc = (CList*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg, expand);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new shortcut.
+
+CShortcut* CInterface::CreateShortcut(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CShortcut* ps;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=10 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CShortcut(m_iMan);
+ ps = (CShortcut*)m_table[i];
+ ps->Create(pos, dim, icon, eventMsg);
+ return ps;
+ }
+ }
+ return 0;
+}
+
+// Creates a new compass.
+
+CCompass* CInterface::CreateCompass(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CCompass* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=10 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CCompass(m_iMan);
+ pc = (CCompass*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new target.
+
+CTarget* CInterface::CreateTarget(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CTarget* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=10 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CTarget(m_iMan);
+ pc = (CTarget*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new map.
+
+CMap* CInterface::CreateMap(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CMap* pm;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=10 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CMap(m_iMan);
+ pm = (CMap*)m_table[i];
+ pm->Create(pos, dim, icon, eventMsg);
+ return pm;
+ }
+ }
+ return 0;
+}
+
+// Removes a control.
+
+bool CInterface::DeleteControl(EventMsg eventMsg)
+{
+ int i;
+
+ for ( i=0 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] != 0 )
+ {
+ if ( eventMsg == m_table[i]->RetEventMsg() )
+ {
+ delete m_table[i];
+ m_table[i] = 0;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// Gives a control.
+
+CControl* CInterface::SearchControl(EventMsg eventMsg)
+{
+ int i;
+
+ for ( i=0 ; i<MAXCONTROL ; i++ )
+ {
+ if ( m_table[i] != 0 )
+ {
+ if ( eventMsg == m_table[i]->RetEventMsg() )
+ {
+ return m_table[i];
+ }
+ }
+ }
+ return 0;
+}
+
+// Management of an event.
+
+bool CInterface::EventProcess(const Event &event)
+{
+ int i;
+
+ if ( event.event == EVENT_MOUSEMOVE )
+ {
+ if ( m_camera == 0 )
+ {
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ }
+ m_engine->SetMouseType(m_camera->RetMouseDef(event.pos));
+ }
+
+ for ( i=MAXCONTROL-1 ; i>=0 ; i-- )
+ {
+ if ( m_table[i] != 0 &&
+ m_table[i]->TestState(STATE_ENABLE) )
+ {
+ if ( !m_table[i]->EventProcess(event) )
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+// Gives the tooltip binding to the window.
+
+bool CInterface::GetTooltip(Math::Point pos, char* name)
+{
+ int i;
+
+ for ( i=MAXCONTROL-1 ; i>=0 ; i-- )
+ {
+ if ( m_table[i] != 0 )
+ {
+ if ( m_table[i]->GetTooltip(pos, name) )
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+
+// Draws all buttons.
+
+void CInterface::Draw()
+{
+ D3DMATERIAL7 material;
+ int i;
+
+ ZeroMemory( &material, sizeof(D3DMATERIAL7) );
+ material.diffuse.r = 1.0f;
+ material.diffuse.g = 1.0f;
+ material.diffuse.b = 1.0f;
+ material.ambient.r = 0.5f;
+ material.ambient.g = 0.5f;
+ material.ambient.b = 0.5f;
+ m_engine->SetMaterial(material);
+
+ for ( i=0 ; i<MAXCONTROL ; i++ )
+//? for ( i=MAXCONTROL-1 ; i>=0 ; i-- )
+ {
+ if ( m_table[i] != 0 )
+ {
+ m_table[i]->Draw();
+ }
+ }
+}
+
+
diff --git a/src/ui/interface.h b/src/ui/interface.h
index 0b3ba0d..8aa7f44 100644
--- a/src/ui/interface.h
+++ b/src/ui/interface.h
@@ -1,95 +1,95 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// interface.h
-
-#pragma once
-
-
-#include "common/event.h"
-#include "math/point.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CControl;
-class CWindow;
-class CButton;
-class CColor;
-class CCheck;
-class CKey;
-class CGroup;
-class CImage;
-class CLabel;
-class CEdit;
-class CEditValue;
-class CScroll;
-class CSlider;
-class CList;
-class CShortcut;
-class CMap;
-class CGauge;
-class CCompass;
-class CTarget;
-class CCamera;
-
-
-const int MAXCONTROL = 100;
-
-
-class CInterface
-{
-public:
- CInterface(CInstanceManager* iMan);
- ~CInterface();
-
- bool EventProcess(const Event &event);
- bool GetTooltip(Math::Point pos, char* name);
-
- void Flush();
- CWindow* CreateWindows(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CButton* CreateButton(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CColor* CreateColor(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CCheck* CreateCheck(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CKey* CreateKey(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CGroup* CreateGroup(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CImage* CreateImage(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CLabel* CreateLabel(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg, char *name);
- CEdit* CreateEdit(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CEditValue* CreateEditValue(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CScroll* CreateScroll(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CSlider* CreateSlider(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CList* CreateList(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg, float expand=1.2f);
- CShortcut* CreateShortcut(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CCompass* CreateCompass(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CTarget* CreateTarget(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CMap* CreateMap(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- bool DeleteControl(EventMsg eventMsg);
- CControl* SearchControl(EventMsg eventMsg);
-
- void Draw();
-
-protected:
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CCamera* m_camera;
-
- CControl* m_table[MAXCONTROL];
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// interface.h
+
+#pragma once
+
+
+#include "common/event.h"
+#include "math/point.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CControl;
+class CWindow;
+class CButton;
+class CColor;
+class CCheck;
+class CKey;
+class CGroup;
+class CImage;
+class CLabel;
+class CEdit;
+class CEditValue;
+class CScroll;
+class CSlider;
+class CList;
+class CShortcut;
+class CMap;
+class CGauge;
+class CCompass;
+class CTarget;
+class CCamera;
+
+
+const int MAXCONTROL = 100;
+
+
+class CInterface
+{
+public:
+ CInterface(CInstanceManager* iMan);
+ ~CInterface();
+
+ bool EventProcess(const Event &event);
+ bool GetTooltip(Math::Point pos, char* name);
+
+ void Flush();
+ CWindow* CreateWindows(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CButton* CreateButton(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CColor* CreateColor(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CCheck* CreateCheck(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CKey* CreateKey(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CGroup* CreateGroup(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CImage* CreateImage(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CLabel* CreateLabel(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg, char *name);
+ CEdit* CreateEdit(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CEditValue* CreateEditValue(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CScroll* CreateScroll(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CSlider* CreateSlider(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CList* CreateList(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg, float expand=1.2f);
+ CShortcut* CreateShortcut(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CCompass* CreateCompass(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CTarget* CreateTarget(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CMap* CreateMap(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ bool DeleteControl(EventMsg eventMsg);
+ CControl* SearchControl(EventMsg eventMsg);
+
+ void Draw();
+
+protected:
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CCamera* m_camera;
+
+ CControl* m_table[MAXCONTROL];
+};
+
+
diff --git a/src/ui/key.cpp b/src/ui/key.cpp
index 941dd8a..a1eebb3 100644
--- a/src/ui/key.cpp
+++ b/src/ui/key.cpp
@@ -1,288 +1,288 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// key.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "old/sound.h"
-#include "old/text.h"
-#include "ui/key.h"
-
-
-
-
-// Constructs the name of a button.
-
-void GetKeyName(char *name, int key)
-{
- if ( !GetResource(RES_KEY, key, name) )
- {
- if ( (key >= '0' && key <= '9') ||
- (key >= 'A' && key <= 'Z') ||
- (key >= 'a' && key <= 'z') )
- {
- name[0] = key;
- name[1] = 0;
- }
- else
- {
- sprintf(name, "Code %d", key);
- }
- }
-}
-
-
-
-
-// Object's constructor.
-
-CKey::CKey(CInstanceManager* iMan) : CControl(iMan)
-{
- m_key[0] = 0;
- m_key[1] = 0;
- m_bCatch = false;
-}
-
-// Object's destructor.
-
-CKey::~CKey()
-{
-}
-
-
-// Creates a new button.
-
-bool CKey::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- char name[100];
- char* p;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- CControl::Create(pos, dim, icon, eventMsg);
-
- GetResource(RES_EVENT, eventMsg, name);
- p = strchr(name, '\\');
- if ( p != 0 ) *p = 0;
- SetName(name);
-
- return true;
-}
-
-
-// Management of an event.
-
-bool CKey::EventProcess(const Event &event)
-{
- if ( m_state & STATE_DEAD ) return true;
-
- CControl::EventProcess(event);
-
- if ( event.event == EVENT_LBUTTONDOWN )
- {
- if ( Detect(event.pos) )
- {
- m_bCatch = true;
- }
- else
- {
- m_bCatch = false;
- }
- }
-
- if ( event.event == EVENT_KEYDOWN && m_bCatch )
- {
- m_bCatch = false;
-
- if ( TestKey(event.param) ) // impossible ?
- {
- m_sound->Play(SOUND_TZOING);
- }
- else
- {
- if ( event.param == m_key[0] ||
- event.param == m_key[1] )
- {
- m_key[0] = event.param;
- m_key[1] = 0;
- }
- else
- {
- m_key[1] = m_key[0];
- m_key[0] = event.param;
- }
- m_sound->Play(SOUND_CLICK);
-
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- }
- return false;
- }
-
- return true;
-}
-
-
-// Seeks when a key is already used.
-
-bool CKey::TestKey(int key)
-{
- int i, j;
-
- if ( key == VK_PAUSE ||
- key == VK_SNAPSHOT ) return true; // blocked key
-
- for ( i=0 ; i<20 ; i++ )
- {
- for ( j=0 ; j<2 ; j++ )
- {
- if ( key == m_engine->RetKey(i, j) ) // key used?
- {
- m_engine->SetKey(i, j, 0); // nothing!
- }
- }
-
- if ( m_engine->RetKey(i, 0) == 0 ) // first free option?
- {
- m_engine->SetKey(i, 0, m_engine->RetKey(i, 1)); // shift
- m_engine->SetKey(i, 1, 0);
- }
- }
-
- 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 ) return;
-
- iDim = m_dim;
- m_dim.x = 200.0f/640.0f;
-
- if ( m_state & STATE_SHADOW )
- {
- DrawShadow(m_pos, m_dim);
- }
-
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATENORMAL);
-
- zoomExt = 1.00f;
- zoomInt = 0.95f;
-
- icon = 2;
- if ( m_key[0] == 0 &&
- m_key[1] == 0 ) // no shortcut?
- {
- icon = 3;
- }
- if ( m_state & STATE_DEFAULT )
- {
- DrawPart(23, 1.3f, 0.0f);
-
- zoomExt *= 1.15f;
- zoomInt *= 1.15f;
- }
- if ( m_state & STATE_HILIGHT )
- {
- icon = 1;
- }
- if ( m_state & STATE_CHECK )
- {
- icon = 0;
- }
- if ( m_state & STATE_PRESS )
- {
- icon = 3;
- zoomInt *= 0.9f;
- }
- if ( (m_state & STATE_ENABLE) == 0 )
- {
- icon = 7;
- }
- if ( m_state & STATE_DEAD )
- {
- icon = 17;
- }
- if ( m_bCatch )
- {
- icon = 23;
- }
- DrawPart(icon, zoomExt, 8.0f/256.0f); // draws the button
-
- h = m_engine->RetText()->RetHeight(m_fontSize, m_fontType)/2.0f;
-
- GetKeyName(text, m_key[0]);
- if ( m_key[1] != 0 )
- {
- GetResource(RES_TEXT, RT_KEY_OR, text+strlen(text));
- GetKeyName(text+strlen(text), m_key[1]);
- }
-
- pos.x = m_pos.x+m_dim.x*0.5f;
- pos.y = m_pos.y+m_dim.y*0.5f;
- pos.y -= h;
- m_engine->RetText()->DrawText(text, pos, m_dim.x, 0, m_fontSize, m_fontStretch, m_fontType, 0);
-
- m_dim = iDim;
-
- if ( m_state & STATE_DEAD ) return;
-
- // Draws the name.
- pos.x = m_pos.x+(214.0f/640.0f);
- pos.y = m_pos.y+m_dim.y*0.5f;
- pos.y -= h;
- m_engine->RetText()->DrawText(m_name, pos, m_dim.x, 1, m_fontSize, m_fontStretch, m_fontType, 0);
-}
-
-
-
-void CKey::SetKey(int option, int key)
-{
- if ( option < 0 ||
- option > 1 ) return;
-
- m_key[option] = key;
-}
-
-int CKey::RetKey(int option)
-{
- if ( option < 0 ||
- option > 1 ) return 0;
-
- return m_key[option];
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// key.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "old/sound.h"
+#include "old/text.h"
+#include "ui/key.h"
+
+
+
+
+// Constructs the name of a button.
+
+void GetKeyName(char *name, int key)
+{
+ if ( !GetResource(RES_KEY, key, name) )
+ {
+ if ( (key >= '0' && key <= '9') ||
+ (key >= 'A' && key <= 'Z') ||
+ (key >= 'a' && key <= 'z') )
+ {
+ name[0] = key;
+ name[1] = 0;
+ }
+ else
+ {
+ sprintf(name, "Code %d", key);
+ }
+ }
+}
+
+
+
+
+// Object's constructor.
+
+CKey::CKey(CInstanceManager* iMan) : CControl(iMan)
+{
+ m_key[0] = 0;
+ m_key[1] = 0;
+ m_bCatch = false;
+}
+
+// Object's destructor.
+
+CKey::~CKey()
+{
+}
+
+
+// Creates a new button.
+
+bool CKey::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ char name[100];
+ char* p;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ CControl::Create(pos, dim, icon, eventMsg);
+
+ GetResource(RES_EVENT, eventMsg, name);
+ p = strchr(name, '\\');
+ if ( p != 0 ) *p = 0;
+ SetName(name);
+
+ return true;
+}
+
+
+// Management of an event.
+
+bool CKey::EventProcess(const Event &event)
+{
+ if ( m_state & STATE_DEAD ) return true;
+
+ CControl::EventProcess(event);
+
+ if ( event.event == EVENT_LBUTTONDOWN )
+ {
+ if ( Detect(event.pos) )
+ {
+ m_bCatch = true;
+ }
+ else
+ {
+ m_bCatch = false;
+ }
+ }
+
+ if ( event.event == EVENT_KEYDOWN && m_bCatch )
+ {
+ m_bCatch = false;
+
+ if ( TestKey(event.param) ) // impossible ?
+ {
+ m_sound->Play(SOUND_TZOING);
+ }
+ else
+ {
+ if ( event.param == m_key[0] ||
+ event.param == m_key[1] )
+ {
+ m_key[0] = event.param;
+ m_key[1] = 0;
+ }
+ else
+ {
+ m_key[1] = m_key[0];
+ m_key[0] = event.param;
+ }
+ m_sound->Play(SOUND_CLICK);
+
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ }
+ return false;
+ }
+
+ return true;
+}
+
+
+// Seeks when a key is already used.
+
+bool CKey::TestKey(int key)
+{
+ int i, j;
+
+ if ( key == VK_PAUSE ||
+ key == VK_SNAPSHOT ) return true; // blocked key
+
+ for ( i=0 ; i<20 ; i++ )
+ {
+ for ( j=0 ; j<2 ; j++ )
+ {
+ if ( key == m_engine->RetKey(i, j) ) // key used?
+ {
+ m_engine->SetKey(i, j, 0); // nothing!
+ }
+ }
+
+ if ( m_engine->RetKey(i, 0) == 0 ) // first free option?
+ {
+ m_engine->SetKey(i, 0, m_engine->RetKey(i, 1)); // shift
+ m_engine->SetKey(i, 1, 0);
+ }
+ }
+
+ 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 ) return;
+
+ iDim = m_dim;
+ m_dim.x = 200.0f/640.0f;
+
+ if ( m_state & STATE_SHADOW )
+ {
+ DrawShadow(m_pos, m_dim);
+ }
+
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+
+ zoomExt = 1.00f;
+ zoomInt = 0.95f;
+
+ icon = 2;
+ if ( m_key[0] == 0 &&
+ m_key[1] == 0 ) // no shortcut?
+ {
+ icon = 3;
+ }
+ if ( m_state & STATE_DEFAULT )
+ {
+ DrawPart(23, 1.3f, 0.0f);
+
+ zoomExt *= 1.15f;
+ zoomInt *= 1.15f;
+ }
+ if ( m_state & STATE_HILIGHT )
+ {
+ icon = 1;
+ }
+ if ( m_state & STATE_CHECK )
+ {
+ icon = 0;
+ }
+ if ( m_state & STATE_PRESS )
+ {
+ icon = 3;
+ zoomInt *= 0.9f;
+ }
+ if ( (m_state & STATE_ENABLE) == 0 )
+ {
+ icon = 7;
+ }
+ if ( m_state & STATE_DEAD )
+ {
+ icon = 17;
+ }
+ if ( m_bCatch )
+ {
+ icon = 23;
+ }
+ DrawPart(icon, zoomExt, 8.0f/256.0f); // draws the button
+
+ h = m_engine->RetText()->RetHeight(m_fontSize, m_fontType)/2.0f;
+
+ GetKeyName(text, m_key[0]);
+ if ( m_key[1] != 0 )
+ {
+ GetResource(RES_TEXT, RT_KEY_OR, text+strlen(text));
+ GetKeyName(text+strlen(text), m_key[1]);
+ }
+
+ pos.x = m_pos.x+m_dim.x*0.5f;
+ pos.y = m_pos.y+m_dim.y*0.5f;
+ pos.y -= h;
+ m_engine->RetText()->DrawText(text, pos, m_dim.x, 0, m_fontSize, m_fontStretch, m_fontType, 0);
+
+ m_dim = iDim;
+
+ if ( m_state & STATE_DEAD ) return;
+
+ // Draws the name.
+ pos.x = m_pos.x+(214.0f/640.0f);
+ pos.y = m_pos.y+m_dim.y*0.5f;
+ pos.y -= h;
+ m_engine->RetText()->DrawText(m_name, pos, m_dim.x, 1, m_fontSize, m_fontStretch, m_fontType, 0);
+}
+
+
+
+void CKey::SetKey(int option, int key)
+{
+ if ( option < 0 ||
+ option > 1 ) return;
+
+ m_key[option] = key;
+}
+
+int CKey::RetKey(int option)
+{
+ if ( option < 0 ||
+ option > 1 ) return 0;
+
+ return m_key[option];
+}
+
diff --git a/src/ui/key.h b/src/ui/key.h
index ebca010..314f39b 100644
--- a/src/ui/key.h
+++ b/src/ui/key.h
@@ -1,52 +1,52 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// key.h
-
-#pragma once
-
-
-#include "ui/control.h"
-
-
-class CD3DEngine;
-
-
-
-class CKey : public CControl
-{
-public:
- CKey(CInstanceManager* iMan);
- virtual ~CKey();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
-
- bool EventProcess(const Event &event);
-
- void Draw();
-
- void SetKey(int option, int key);
- int RetKey(int option);
-
-protected:
- bool TestKey(int key);
-
-protected:
- int m_key[2];
- bool m_bCatch;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// key.h
+
+#pragma once
+
+
+#include "ui/control.h"
+
+
+class CD3DEngine;
+
+
+
+class CKey : public CControl
+{
+public:
+ CKey(CInstanceManager* iMan);
+ virtual ~CKey();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+
+ bool EventProcess(const Event &event);
+
+ void Draw();
+
+ void SetKey(int option, int key);
+ int RetKey(int option);
+
+protected:
+ bool TestKey(int key);
+
+protected:
+ int m_key[2];
+ bool m_bCatch;
+};
+
+
diff --git a/src/ui/label.cpp b/src/ui/label.cpp
index ef61cc5..cd96493 100644
--- a/src/ui/label.cpp
+++ b/src/ui/label.cpp
@@ -1,93 +1,93 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// label.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/text.h"
-#include "ui/label.h"
-
-
-
-
-// Object's constructor.
-
-CLabel::CLabel(CInstanceManager* iMan) : CControl(iMan)
-{
-}
-
-// Object's destructor.
-
-CLabel::~CLabel()
-{
-}
-
-
-// Creates a new button.
-
-bool CLabel::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- CControl::Create(pos, dim, icon, eventMsg);
- return true;
-}
-
-
-// Management of an event.
-
-bool CLabel::EventProcess(const Event &event)
-{
-//? CControl::EventProcess(event);
- return true;
-}
-
-
-// Draws button.
-
-void CLabel::Draw()
-{
- Math::Point pos;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return;
-
- pos.y = m_pos.y+m_dim.y/2.0f;
-
- if ( m_justif > 0 )
- {
- pos.x = m_pos.x;
- }
- if ( m_justif == 0 )
- {
- pos.x = m_pos.x+m_dim.x/2.0f;
- }
- if ( m_justif < 0 )
- {
- pos.x = m_pos.x+m_dim.x;
- }
- m_engine->RetText()->DrawText(m_name, pos, m_dim.x, m_justif, m_fontSize, m_fontStretch, m_fontType, 0);
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// label.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/text.h"
+#include "ui/label.h"
+
+
+
+
+// Object's constructor.
+
+CLabel::CLabel(CInstanceManager* iMan) : CControl(iMan)
+{
+}
+
+// Object's destructor.
+
+CLabel::~CLabel()
+{
+}
+
+
+// Creates a new button.
+
+bool CLabel::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ CControl::Create(pos, dim, icon, eventMsg);
+ return true;
+}
+
+
+// Management of an event.
+
+bool CLabel::EventProcess(const Event &event)
+{
+//? CControl::EventProcess(event);
+ return true;
+}
+
+
+// Draws button.
+
+void CLabel::Draw()
+{
+ Math::Point pos;
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return;
+
+ pos.y = m_pos.y+m_dim.y/2.0f;
+
+ if ( m_justif > 0 )
+ {
+ pos.x = m_pos.x;
+ }
+ if ( m_justif == 0 )
+ {
+ pos.x = m_pos.x+m_dim.x/2.0f;
+ }
+ if ( m_justif < 0 )
+ {
+ pos.x = m_pos.x+m_dim.x;
+ }
+ m_engine->RetText()->DrawText(m_name, pos, m_dim.x, m_justif, m_fontSize, m_fontStretch, m_fontType, 0);
+}
+
diff --git a/src/ui/label.h b/src/ui/label.h
index c6199ba..d3cb915 100644
--- a/src/ui/label.h
+++ b/src/ui/label.h
@@ -1,46 +1,46 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// label.h
-
-#pragma once
-
-
-#include "ui/control.h"
-
-
-class CD3DEngine;
-
-
-
-class CLabel : public CControl
-{
-public:
- CLabel(CInstanceManager* iMan);
- virtual ~CLabel();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
-
- bool EventProcess(const Event &event);
-
- void Draw();
-
-protected:
-
-protected:
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// label.h
+
+#pragma once
+
+
+#include "ui/control.h"
+
+
+class CD3DEngine;
+
+
+
+class CLabel : public CControl
+{
+public:
+ CLabel(CInstanceManager* iMan);
+ virtual ~CLabel();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+
+ bool EventProcess(const Event &event);
+
+ void Draw();
+
+protected:
+
+protected:
+};
+
+
diff --git a/src/ui/list.cpp b/src/ui/list.cpp
index fd137eb..75c740d 100644
--- a/src/ui/list.cpp
+++ b/src/ui/list.cpp
@@ -1,868 +1,868 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// list.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "ui/button.h"
-#include "ui/scroll.h"
-#include "old/text.h"
-#include "ui/list.h"
-
-
-
-const float MARGING = 4.0f;
-
-
-
-// Object's constructor.
-
-CList::CList(CInstanceManager* iMan) : CControl(iMan)
-{
- int i;
-
- for ( i=0 ; i<LISTMAXDISPLAY ; i++ )
- {
- m_button[i] = 0;
- }
- m_scroll = 0;
-
- for ( i=0 ; i<LISTMAXTOTAL ; i++ )
- {
- m_text[i][0] = 0;
- m_check[i] = false;
- m_enable[i] = true;
- }
-
- for ( i=0 ; i<10 ; i++ )
- {
- m_tabs[i] = 0.0f;
- m_justifs[i] = 1;
- }
-
- m_totalLine = 0;
- m_displayLine = 0;
- m_selectLine = -1;
- m_firstLine = 0;
- m_bBlink = false;
- m_bSelectCap = true;
- m_blinkTime = 0.0f;
-}
-
-// Object's destructor.
-
-CList::~CList()
-{
- int i;
-
- for ( i=0 ; i<LISTMAXDISPLAY ; i++ )
- {
- delete m_button[i];
- }
- delete m_scroll;
-}
-
-
-// Creates a new list.
-
-bool CList::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg,
- float expand)
-{
- m_expand = expand;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
- CControl::Create(pos, dim, icon, eventMsg);
-
- m_scroll = new CScroll(m_iMan);
- m_scroll->Create(pos, dim, 0, EVENT_NULL);
- m_eventScroll = m_scroll->RetEventMsg();
-
- return MoveAdjust();
-}
-
-// Adjusted after a change of dimensions.
-
-bool CList::MoveAdjust()
-{
- Math::Point ipos, idim, ppos, ddim;
- float marging, h;
- int i;
-
- for ( i=0 ; i<LISTMAXDISPLAY ; i++ )
- {
- delete m_button[i];
- m_button[i] = 0;
- }
-
- if ( m_icon == 0 ) marging = MARGING;
- else marging = 0.0f;
-
- ipos.x = m_pos.x+marging/640.f;
- ipos.y = m_pos.y+marging/480.f;
- idim.x = m_dim.x-marging*2.0f/640.f;
- idim.y = m_dim.y-marging*2.0f/480.f;
-
- h = m_engine->RetText()->RetHeight(m_fontSize, m_fontType)*m_expand;
-
- m_displayLine = (int)(idim.y/h);
- if ( m_displayLine == 0 ) return false;
- if ( m_displayLine > LISTMAXDISPLAY ) m_displayLine = LISTMAXDISPLAY;
- idim.y = h*m_displayLine;
- m_dim.y = idim.y+marging*2.0f/480.f;
-
- ppos.x = ipos.x;
- ppos.y = ipos.y+idim.y-h;
- ddim.x = idim.x-SCROLL_WIDTH;
- ddim.y = h;
- for ( i=0 ; i<m_displayLine ; i++ )
- {
- m_button[i] = new CButton(m_iMan);
- m_button[i]->Create(ppos, ddim, -1, EVENT_NULL);
- m_button[i]->SetJustif(1);
- m_button[i]->SetState(STATE_SIMPLY);
- m_button[i]->SetFontType(m_fontType);
- m_button[i]->SetFontSize(m_fontSize);
- ppos.y -= h;
-
- m_eventButton[i] = m_button[i]->RetEventMsg();
- }
-
- if ( m_scroll != 0 )
- {
- ppos.x = ipos.x+idim.x-SCROLL_WIDTH;
- ppos.y = ipos.y;
- ddim.x = SCROLL_WIDTH;
- ddim.y = idim.y;
- m_scroll->SetPos(ppos);
- m_scroll->SetDim(ddim);
- }
-
- UpdateScroll();
- UpdateButton();
- return true;
-}
-
-
-// Returns the message of a button.
-
-EventMsg CList::RetEventMsgButton(int i)
-{
- if ( i < 0 || i >= m_displayLine ) return EVENT_NULL;
- if ( m_button[i] == 0 ) return EVENT_NULL;
- return m_button[i]->RetEventMsg();
-}
-
-// Returns the message from the elevator.
-
-EventMsg CList::RetEventMsgScroll()
-{
- if ( m_scroll == 0 ) return EVENT_NULL;
- return m_scroll->RetEventMsg();
-}
-
-
-void CList::SetPos(Math::Point pos)
-{
- CControl::SetPos(pos);
-}
-
-void CList::SetDim(Math::Point dim)
-{
- m_dim = dim;
- MoveAdjust();
- CControl::SetDim(dim);
-}
-
-
-bool CList::SetState(int state, bool bState)
-{
- int i;
-
- if ( state & STATE_ENABLE )
- {
- for ( i=0 ; i<m_displayLine ; i++ )
- {
- if ( m_button[i] != 0 ) m_button[i]->SetState(state, bState);
- }
- if ( m_scroll != 0 ) m_scroll->SetState(state, bState);
- }
-
- return CControl::SetState(state, bState);
-}
-
-bool CList::SetState(int state)
-{
- int i;
-
- if ( state & STATE_ENABLE )
- {
- for ( i=0 ; i<m_displayLine ; i++ )
- {
- if ( m_button[i] != 0 ) m_button[i]->SetState(state);
- }
- if ( m_scroll != 0 ) m_scroll->SetState(state);
- }
-
- return CControl::SetState(state);
-}
-
-bool CList::ClearState(int state)
-{
- int i;
-
- if ( state & STATE_ENABLE )
- {
- for ( i=0 ; i<m_displayLine ; i++ )
- {
- if ( m_button[i] != 0 ) m_button[i]->ClearState(state);
- }
- if ( m_scroll != 0 ) m_scroll->ClearState(state);
- }
-
- return CControl::ClearState(state);
-}
-
-
-// Management of an event.
-
-bool CList::EventProcess(const Event &event)
-{
- int i;
-
- if ( m_bBlink && // blinks?
- event.event == EVENT_FRAME )
- {
- i = m_selectLine-m_firstLine;
-
- if ( i >= 0 && i < 4 &&
- m_button[i] != 0 )
- {
- m_blinkTime += event.rTime;
- if ( Math::Mod(m_blinkTime, 0.7f) < 0.3f )
- {
- m_button[i]->ClearState(STATE_ENABLE);
- m_button[i]->ClearState(STATE_CHECK);
- }
- else
- {
- m_button[i]->SetState(STATE_ENABLE);
- m_button[i]->SetState(STATE_CHECK);
- }
- }
- }
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return true;
- if ( (m_state & STATE_ENABLE) == 0 ) return true;
-
- if ( event.event == EVENT_KEYDOWN &&
- event.param == VK_WHEELUP &&
- Detect(event.pos) )
- {
- if ( m_firstLine > 0 ) m_firstLine --;
- UpdateScroll();
- UpdateButton();
- return true;
- }
- if ( event.event == EVENT_KEYDOWN &&
- event.param == VK_WHEELDOWN &&
- Detect(event.pos) )
- {
- if ( m_firstLine < m_totalLine-m_displayLine ) m_firstLine ++;
- UpdateScroll();
- UpdateButton();
- return true;
- }
-
- CControl::EventProcess(event);
-
- if ( event.event == EVENT_MOUSEMOVE && Detect(event.pos) )
- {
- m_engine->SetMouseType(D3DMOUSENORM);
- for ( i=0 ; i<m_displayLine ; i++ )
- {
- if ( i+m_firstLine >= m_totalLine ) break;
- if ( m_button[i] != 0 )
- {
- m_button[i]->EventProcess(event);
- }
- }
- }
-
- if ( m_bSelectCap )
- {
- for ( i=0 ; i<m_displayLine ; i++ )
- {
- if ( i+m_firstLine >= m_totalLine ) break;
- if ( m_button[i] != 0 )
- {
- if ( !m_button[i]->EventProcess(event) ) return false;
-
- if ( event.event == m_eventButton[i] )
- {
- SetSelect(m_firstLine+i);
-
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent); // selected line changes
- }
- }
- }
- }
-
- if ( m_scroll != 0 )
- {
- if ( !m_scroll->EventProcess(event) ) return false;
-
- if ( event.event == m_eventScroll )
- {
- MoveScroll();
- UpdateButton();
- }
- }
-
- return true;
-}
-
-
-// Draws the list.
-
-void CList::Draw()
-{
- Math::Point uv1, uv2, corner, pos, dim, ppos, ddim;
- float dp;
- int i, j;
- char text[100];
- char *pb, *pe;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return;
-
- if ( m_state & STATE_SHADOW )
- {
- DrawShadow(m_pos, m_dim);
- }
-
- dp = 0.5f/256.0f;
-
- if ( m_icon != -1 )
- {
- dim = m_dim;
-
- if ( m_icon == 0 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
-
- uv1.x = 128.0f/256.0f;
- uv1.y = 64.0f/256.0f; // u-v texture
- uv2.x = 160.0f/256.0f;
- uv2.y = 96.0f/256.0f;
- }
- else
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
-
- uv1.x = 132.0f/256.0f;
- uv1.y = 68.0f/256.0f; // u-v texture
- uv2.x = 156.0f/256.0f;
- uv2.y = 92.0f/256.0f;
-
- if ( m_button[0] != 0 )
- {
- dim = m_button[0]->RetDim();
- dim.y *= m_displayLine; // background sounds spot behind
- }
- }
-
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- corner.x = 10.0f/640.0f;
- corner.y = 10.0f/480.0f;
- DrawIcon(m_pos, dim, uv1, uv2, corner, 8.0f/256.0f);
- }
-
- if ( m_totalLine < m_displayLine ) // no buttons to the bottom?
- {
- i = m_totalLine;
- if ( m_button[i] != 0 )
- {
- pos = m_button[i]->RetPos();
- dim = m_button[i]->RetDim();
- pos.y += dim.y*1.1f;
- dim.y *= 0.4f;
- pos.y -= dim.y;
-
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTw);
- uv1.x = 120.0f/256.0f;
- uv1.y = 64.0f/256.0f;
- uv2.x = 128.0f/256.0f;
- uv2.y = 48.0f/256.0f;
- uv1.x += dp;
- uv1.y -= dp;
- uv2.x -= dp;
- uv2.y += dp;
- DrawIcon(pos, dim, uv1, uv2); // ch'tite shadow cute (?)
- }
- }
-
- for ( i=0 ; i<m_displayLine ; i++ )
- {
- if ( i+m_firstLine >= m_totalLine ) break;
-
- if ( m_button[i] != 0 )
- {
- if ( !m_bBlink && i+m_firstLine < m_totalLine )
- {
- m_button[i]->SetState(STATE_ENABLE, m_enable[i+m_firstLine] && (m_state & STATE_ENABLE) );
- }
- m_button[i]->Draw(); // draws a box without text
-
- // draws text in the box
- pos = m_button[i]->RetPos();
- dim = m_button[i]->RetDim();
- if ( m_tabs[0] == 0.0f )
- {
- ppos.x = pos.x+dim.y*0.5f;
- ppos.y = pos.y+dim.y*0.5f;
- ppos.y -= m_engine->RetText()->RetHeight(m_fontSize, m_fontType)/2.0f;
- ddim.x = dim.x-dim.y;
- DrawCase(m_text[i+m_firstLine], ppos, ddim.x, 1);
- }
- else
- {
- ppos.x = pos.x+dim.y*0.5f;
- ppos.y = pos.y+dim.y*0.5f;
- ppos.y -= m_engine->RetText()->RetHeight(m_fontSize, m_fontType)/2.0f;
- pb = m_text[i+m_firstLine];
- for ( j=0 ; j<10 ; j++ )
- {
- pe = strchr(pb, '\t');
- if ( pe == 0 )
- {
- strcpy(text, pb);
- }
- else
- {
- strncpy(text, pb, pe-pb);
- text[pe-pb] = 0;
- }
- DrawCase(text, ppos, m_tabs[j], m_justifs[j]);
-
- if ( pe == 0 ) break;
- ppos.x += m_tabs[j];
- pb = pe+1;
- }
- }
-
- if ( (m_state & STATE_EXTEND) && i < m_totalLine )
- {
- pos = m_button[i]->RetPos();
- dim = m_button[i]->RetDim();
- pos.x += dim.x-dim.y*0.75f;
- dim.x = dim.y*0.75f;
- pos.x += 2.0f/640.0f;
- pos.y += 2.0f/480.0f;
- dim.x -= 4.0f/640.0f;
- dim.y -= 4.0f/480.0f;
-
- if ( m_check[i+m_firstLine] )
- {
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 64.0f/256.0f;
- uv1.y = 0.0f/256.0f;
- uv2.x = 96.0f/256.0f;
- uv2.y = 32.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2); // square shape
-
- m_engine->SetState(D3DSTATETTw);
- uv1.x = 0.0f/256.0f; // v
- uv1.y = 64.0f/256.0f;
- uv2.x = 32.0f/256.0f;
- uv2.y = 96.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2); // draws v
- }
- else
- {
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATETTw);
- if ( i+m_firstLine == m_selectLine )
- {
- uv1.x =224.0f/256.0f; // <
- uv1.y =192.0f/256.0f;
- uv2.x =256.0f/256.0f;
- uv2.y =224.0f/256.0f;
- }
- else
- {
- uv1.x = 96.0f/256.0f; // x
- uv1.y = 32.0f/256.0f;
- uv2.x =128.0f/256.0f;
- uv2.y = 64.0f/256.0f;
- }
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2); // draws x
- }
- }
- }
- }
-
- if ( m_scroll != 0 )
- {
- m_scroll->Draw(); // draws the lift
- }
-}
-
-// Displays text in a box.
-
-void CList::DrawCase(char *text, Math::Point pos, float width, int justif)
-{
- if ( justif == 1 )
- {
- m_engine->RetText()->DrawText(text, pos, width, 1, m_fontSize, m_fontStretch, m_fontType, 0);
- }
- else if ( justif == 0 )
- {
- pos.x += width/2.0f;
- m_engine->RetText()->DrawText(text, pos, width, 0, m_fontSize, m_fontStretch, m_fontType, 0);
- }
- else
- {
- pos.x += width;
- m_engine->RetText()->DrawText(text, pos, width, -1, m_fontSize, m_fontStretch, m_fontType, 0);
- }
-}
-
-
-// Empty the list completely.
-
-void CList::Flush()
-{
- m_totalLine = 0;
- m_selectLine = -1;
- m_firstLine = 0;
- UpdateButton();
- UpdateScroll();
-}
-
-
-// Specifies the total number of lines.
-
-void CList::SetTotal(int i)
-{
- m_totalLine = i;
-}
-
-// Returns the total number of lines.
-
-int CList::RetTotal()
-{
- return m_totalLine;
-}
-
-
-// Selects a line.
-
-void CList::SetSelect(int i)
-{
- if ( m_bSelectCap )
- {
- m_selectLine = i;
- }
- else
- {
- m_firstLine = i;
- UpdateScroll();
- }
-
- UpdateButton();
-}
-
-// Returns the selected line.
-
-int CList::RetSelect()
-{
- if ( m_bSelectCap )
- {
- return m_selectLine;
- }
- else
- {
- return m_firstLine;
- }
-}
-
-
-// Management of capability has a select box.
-
-void CList::SetSelectCap(bool bEnable)
-{
- m_bSelectCap = bEnable;
-}
-
-bool CList::RetSelectCap()
-{
- return m_bSelectCap;
-}
-
-
-// Blink a line.
-
-void CList::SetBlink(bool bEnable)
-{
- int i;
-
- m_bBlink = bEnable;
- m_blinkTime = 0.0f;
-
- i = m_selectLine-m_firstLine;
-
- if ( i >= 0 && i < 4 &&
- m_button[i] != 0 )
- {
- if ( !bEnable )
- {
- m_button[i]->SetState(STATE_CHECK);
- m_button[i]->ClearState(STATE_ENABLE);
- }
- }
-}
-
-bool CList::RetBlink()
-{
- return m_bBlink;
-}
-
-
-// Specifies the text of a line.
-
-void CList::SetName(int i, char* name)
-{
- if ( i < 0 || i >= LISTMAXTOTAL ) return;
-
- if ( i >= m_totalLine )
- {
- m_totalLine = i+1; // expands the list
- }
-
- if ( name[0] == 0 )
- {
- strcpy(m_text[i], " ");
- }
- else
- {
- strcpy(m_text[i], name);
- }
- UpdateButton();
- UpdateScroll();
-}
-
-// Returns the text of a line.
-
-char* CList::RetName(int i)
-{
- if ( i < 0 || i >= m_totalLine ) return 0;
-
- return m_text[i];
-}
-
-
-// Specifies the bit "check" for a box.
-
-void CList::SetCheck(int i, bool bMode)
-{
- if ( i < 0 || i >= m_totalLine ) return;
-
- m_check[i] = bMode;
-}
-
-// Returns the bit "check" for a box.
-
-bool CList::RetCheck(int i)
-{
- if ( i < 0 || i >= m_totalLine ) return false;
-
- return m_check[i];
-}
-
-
-// Specifies the bit "enable" for a box.
-
-void CList::SetEnable(int i, bool bMode)
-{
- if ( i < 0 || i >= m_totalLine ) return;
-
- m_enable[i] = bMode;
-}
-
-// Returns the bit "enable" for a box.
-
-bool CList::RetEnable(int i)
-{
- if ( i < 0 || i >= m_totalLine ) return false;
-
- return m_enable[i];
-}
-
-
-// Management of the position of the tabs.
-
-void CList::SetTabs(int i, float pos, int justif)
-{
- if ( i < 0 || i >= 10 ) return;
- m_tabs[i] = pos;
- m_justifs[i] = justif;
-}
-
-float CList::RetTabs(int i)
-{
- if ( i < 0 || i >= 10 ) return 0.0f;
- return m_tabs[i];
-}
-
-
-// Moves the lift to see the list of the selected line.
-
-void CList::ShowSelect(bool bFixed)
-{
- int sel;
-
- if ( bFixed &&
- m_selectLine >= m_firstLine &&
- m_selectLine < m_firstLine+m_displayLine ) return; // all good
-
- sel = m_selectLine;
-
- // Down from 1/2 * h.
- sel += m_displayLine/2;
- if ( sel > m_totalLine-1 ) sel = m_totalLine-1;
-
- // Back to h-1.
- sel -= m_displayLine-1;
- if ( sel < 0 ) sel = 0;
-
- m_firstLine = sel;
-
- UpdateButton();
- UpdateScroll();
-}
-
-
-// Updates all button names.
-
-void CList::UpdateButton()
-{
- int state, i, j;
-
- state = CControl::RetState();
-
- j = m_firstLine;
- for ( i=0 ; i<m_displayLine ; i++ )
- {
- if ( m_button[i] == 0 ) continue;
-
- m_button[i]->SetState(STATE_CHECK, (j == m_selectLine));
-
- if ( j < m_totalLine )
- {
-//? m_button[i]->SetName(m_text[j]);
- m_button[i]->SetName(" "); // blank button
- m_button[i]->SetState(STATE_ENABLE, (state & STATE_ENABLE));
- }
- else
- {
- m_button[i]->SetName(" "); // blank button
- m_button[i]->ClearState(STATE_ENABLE);
- }
- j ++;
- }
-}
-
-// Updates the lift.
-
-void CList::UpdateScroll()
-{
- float ratio, value, step;
-
- if ( m_scroll == 0 ) return;
-
- if ( m_totalLine <= m_displayLine )
- {
- ratio = 1.0f;
- value = 0.0f;
- step = 0.0f;
- }
- else
- {
- ratio = (float)m_displayLine/m_totalLine;
- if ( ratio > 1.0f ) ratio = 1.0f;
-
- value = (float)m_firstLine/(m_totalLine-m_displayLine);
- if ( value < 0.0f ) value = 0.0f;
- if ( value > 1.0f ) value = 1.0f;
-
- step = (float)1.0f/(m_totalLine-m_displayLine);
- if ( step < 0.0f ) step = 0.0f;
- }
-
- m_scroll->SetVisibleRatio(ratio);
- m_scroll->SetVisibleValue(value);
- m_scroll->SetArrowStep(step);
-}
-
-// Update when the lift is moving.
-
-void CList::MoveScroll()
-{
- float pos;
- int n;
-
- if ( m_scroll == 0 ) return;
-
- n = m_totalLine-m_displayLine;
- pos = m_scroll->RetVisibleValue();
- pos += m_scroll->RetArrowStep()/2.0f; // it's magic!
- m_firstLine = (int)(pos*n);
- if ( m_firstLine < 0 ) m_firstLine = 0;
- if ( m_firstLine > n ) m_firstLine = n;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// list.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "ui/button.h"
+#include "ui/scroll.h"
+#include "old/text.h"
+#include "ui/list.h"
+
+
+
+const float MARGING = 4.0f;
+
+
+
+// Object's constructor.
+
+CList::CList(CInstanceManager* iMan) : CControl(iMan)
+{
+ int i;
+
+ for ( i=0 ; i<LISTMAXDISPLAY ; i++ )
+ {
+ m_button[i] = 0;
+ }
+ m_scroll = 0;
+
+ for ( i=0 ; i<LISTMAXTOTAL ; i++ )
+ {
+ m_text[i][0] = 0;
+ m_check[i] = false;
+ m_enable[i] = true;
+ }
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ m_tabs[i] = 0.0f;
+ m_justifs[i] = 1;
+ }
+
+ m_totalLine = 0;
+ m_displayLine = 0;
+ m_selectLine = -1;
+ m_firstLine = 0;
+ m_bBlink = false;
+ m_bSelectCap = true;
+ m_blinkTime = 0.0f;
+}
+
+// Object's destructor.
+
+CList::~CList()
+{
+ int i;
+
+ for ( i=0 ; i<LISTMAXDISPLAY ; i++ )
+ {
+ delete m_button[i];
+ }
+ delete m_scroll;
+}
+
+
+// Creates a new list.
+
+bool CList::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg,
+ float expand)
+{
+ m_expand = expand;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+ CControl::Create(pos, dim, icon, eventMsg);
+
+ m_scroll = new CScroll(m_iMan);
+ m_scroll->Create(pos, dim, 0, EVENT_NULL);
+ m_eventScroll = m_scroll->RetEventMsg();
+
+ return MoveAdjust();
+}
+
+// Adjusted after a change of dimensions.
+
+bool CList::MoveAdjust()
+{
+ Math::Point ipos, idim, ppos, ddim;
+ float marging, h;
+ int i;
+
+ for ( i=0 ; i<LISTMAXDISPLAY ; i++ )
+ {
+ delete m_button[i];
+ m_button[i] = 0;
+ }
+
+ if ( m_icon == 0 ) marging = MARGING;
+ else marging = 0.0f;
+
+ ipos.x = m_pos.x+marging/640.f;
+ ipos.y = m_pos.y+marging/480.f;
+ idim.x = m_dim.x-marging*2.0f/640.f;
+ idim.y = m_dim.y-marging*2.0f/480.f;
+
+ h = m_engine->RetText()->RetHeight(m_fontSize, m_fontType)*m_expand;
+
+ m_displayLine = (int)(idim.y/h);
+ if ( m_displayLine == 0 ) return false;
+ if ( m_displayLine > LISTMAXDISPLAY ) m_displayLine = LISTMAXDISPLAY;
+ idim.y = h*m_displayLine;
+ m_dim.y = idim.y+marging*2.0f/480.f;
+
+ ppos.x = ipos.x;
+ ppos.y = ipos.y+idim.y-h;
+ ddim.x = idim.x-SCROLL_WIDTH;
+ ddim.y = h;
+ for ( i=0 ; i<m_displayLine ; i++ )
+ {
+ m_button[i] = new CButton(m_iMan);
+ m_button[i]->Create(ppos, ddim, -1, EVENT_NULL);
+ m_button[i]->SetJustif(1);
+ m_button[i]->SetState(STATE_SIMPLY);
+ m_button[i]->SetFontType(m_fontType);
+ m_button[i]->SetFontSize(m_fontSize);
+ ppos.y -= h;
+
+ m_eventButton[i] = m_button[i]->RetEventMsg();
+ }
+
+ if ( m_scroll != 0 )
+ {
+ ppos.x = ipos.x+idim.x-SCROLL_WIDTH;
+ ppos.y = ipos.y;
+ ddim.x = SCROLL_WIDTH;
+ ddim.y = idim.y;
+ m_scroll->SetPos(ppos);
+ m_scroll->SetDim(ddim);
+ }
+
+ UpdateScroll();
+ UpdateButton();
+ return true;
+}
+
+
+// Returns the message of a button.
+
+EventMsg CList::RetEventMsgButton(int i)
+{
+ if ( i < 0 || i >= m_displayLine ) return EVENT_NULL;
+ if ( m_button[i] == 0 ) return EVENT_NULL;
+ return m_button[i]->RetEventMsg();
+}
+
+// Returns the message from the elevator.
+
+EventMsg CList::RetEventMsgScroll()
+{
+ if ( m_scroll == 0 ) return EVENT_NULL;
+ return m_scroll->RetEventMsg();
+}
+
+
+void CList::SetPos(Math::Point pos)
+{
+ CControl::SetPos(pos);
+}
+
+void CList::SetDim(Math::Point dim)
+{
+ m_dim = dim;
+ MoveAdjust();
+ CControl::SetDim(dim);
+}
+
+
+bool CList::SetState(int state, bool bState)
+{
+ int i;
+
+ if ( state & STATE_ENABLE )
+ {
+ for ( i=0 ; i<m_displayLine ; i++ )
+ {
+ if ( m_button[i] != 0 ) m_button[i]->SetState(state, bState);
+ }
+ if ( m_scroll != 0 ) m_scroll->SetState(state, bState);
+ }
+
+ return CControl::SetState(state, bState);
+}
+
+bool CList::SetState(int state)
+{
+ int i;
+
+ if ( state & STATE_ENABLE )
+ {
+ for ( i=0 ; i<m_displayLine ; i++ )
+ {
+ if ( m_button[i] != 0 ) m_button[i]->SetState(state);
+ }
+ if ( m_scroll != 0 ) m_scroll->SetState(state);
+ }
+
+ return CControl::SetState(state);
+}
+
+bool CList::ClearState(int state)
+{
+ int i;
+
+ if ( state & STATE_ENABLE )
+ {
+ for ( i=0 ; i<m_displayLine ; i++ )
+ {
+ if ( m_button[i] != 0 ) m_button[i]->ClearState(state);
+ }
+ if ( m_scroll != 0 ) m_scroll->ClearState(state);
+ }
+
+ return CControl::ClearState(state);
+}
+
+
+// Management of an event.
+
+bool CList::EventProcess(const Event &event)
+{
+ int i;
+
+ if ( m_bBlink && // blinks?
+ event.event == EVENT_FRAME )
+ {
+ i = m_selectLine-m_firstLine;
+
+ if ( i >= 0 && i < 4 &&
+ m_button[i] != 0 )
+ {
+ m_blinkTime += event.rTime;
+ if ( Math::Mod(m_blinkTime, 0.7f) < 0.3f )
+ {
+ m_button[i]->ClearState(STATE_ENABLE);
+ m_button[i]->ClearState(STATE_CHECK);
+ }
+ else
+ {
+ m_button[i]->SetState(STATE_ENABLE);
+ m_button[i]->SetState(STATE_CHECK);
+ }
+ }
+ }
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return true;
+ if ( (m_state & STATE_ENABLE) == 0 ) return true;
+
+ if ( event.event == EVENT_KEYDOWN &&
+ event.param == VK_WHEELUP &&
+ Detect(event.pos) )
+ {
+ if ( m_firstLine > 0 ) m_firstLine --;
+ UpdateScroll();
+ UpdateButton();
+ return true;
+ }
+ if ( event.event == EVENT_KEYDOWN &&
+ event.param == VK_WHEELDOWN &&
+ Detect(event.pos) )
+ {
+ if ( m_firstLine < m_totalLine-m_displayLine ) m_firstLine ++;
+ UpdateScroll();
+ UpdateButton();
+ return true;
+ }
+
+ CControl::EventProcess(event);
+
+ if ( event.event == EVENT_MOUSEMOVE && Detect(event.pos) )
+ {
+ m_engine->SetMouseType(D3DMOUSENORM);
+ for ( i=0 ; i<m_displayLine ; i++ )
+ {
+ if ( i+m_firstLine >= m_totalLine ) break;
+ if ( m_button[i] != 0 )
+ {
+ m_button[i]->EventProcess(event);
+ }
+ }
+ }
+
+ if ( m_bSelectCap )
+ {
+ for ( i=0 ; i<m_displayLine ; i++ )
+ {
+ if ( i+m_firstLine >= m_totalLine ) break;
+ if ( m_button[i] != 0 )
+ {
+ if ( !m_button[i]->EventProcess(event) ) return false;
+
+ if ( event.event == m_eventButton[i] )
+ {
+ SetSelect(m_firstLine+i);
+
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent); // selected line changes
+ }
+ }
+ }
+ }
+
+ if ( m_scroll != 0 )
+ {
+ if ( !m_scroll->EventProcess(event) ) return false;
+
+ if ( event.event == m_eventScroll )
+ {
+ MoveScroll();
+ UpdateButton();
+ }
+ }
+
+ return true;
+}
+
+
+// Draws the list.
+
+void CList::Draw()
+{
+ Math::Point uv1, uv2, corner, pos, dim, ppos, ddim;
+ float dp;
+ int i, j;
+ char text[100];
+ char *pb, *pe;
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return;
+
+ if ( m_state & STATE_SHADOW )
+ {
+ DrawShadow(m_pos, m_dim);
+ }
+
+ dp = 0.5f/256.0f;
+
+ if ( m_icon != -1 )
+ {
+ dim = m_dim;
+
+ if ( m_icon == 0 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+
+ uv1.x = 128.0f/256.0f;
+ uv1.y = 64.0f/256.0f; // u-v texture
+ uv2.x = 160.0f/256.0f;
+ uv2.y = 96.0f/256.0f;
+ }
+ else
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+
+ uv1.x = 132.0f/256.0f;
+ uv1.y = 68.0f/256.0f; // u-v texture
+ uv2.x = 156.0f/256.0f;
+ uv2.y = 92.0f/256.0f;
+
+ if ( m_button[0] != 0 )
+ {
+ dim = m_button[0]->RetDim();
+ dim.y *= m_displayLine; // background sounds spot behind
+ }
+ }
+
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+
+ corner.x = 10.0f/640.0f;
+ corner.y = 10.0f/480.0f;
+ DrawIcon(m_pos, dim, uv1, uv2, corner, 8.0f/256.0f);
+ }
+
+ if ( m_totalLine < m_displayLine ) // no buttons to the bottom?
+ {
+ i = m_totalLine;
+ if ( m_button[i] != 0 )
+ {
+ pos = m_button[i]->RetPos();
+ dim = m_button[i]->RetDim();
+ pos.y += dim.y*1.1f;
+ dim.y *= 0.4f;
+ pos.y -= dim.y;
+
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTw);
+ uv1.x = 120.0f/256.0f;
+ uv1.y = 64.0f/256.0f;
+ uv2.x = 128.0f/256.0f;
+ uv2.y = 48.0f/256.0f;
+ uv1.x += dp;
+ uv1.y -= dp;
+ uv2.x -= dp;
+ uv2.y += dp;
+ DrawIcon(pos, dim, uv1, uv2); // ch'tite shadow cute (?)
+ }
+ }
+
+ for ( i=0 ; i<m_displayLine ; i++ )
+ {
+ if ( i+m_firstLine >= m_totalLine ) break;
+
+ if ( m_button[i] != 0 )
+ {
+ if ( !m_bBlink && i+m_firstLine < m_totalLine )
+ {
+ m_button[i]->SetState(STATE_ENABLE, m_enable[i+m_firstLine] && (m_state & STATE_ENABLE) );
+ }
+ m_button[i]->Draw(); // draws a box without text
+
+ // draws text in the box
+ pos = m_button[i]->RetPos();
+ dim = m_button[i]->RetDim();
+ if ( m_tabs[0] == 0.0f )
+ {
+ ppos.x = pos.x+dim.y*0.5f;
+ ppos.y = pos.y+dim.y*0.5f;
+ ppos.y -= m_engine->RetText()->RetHeight(m_fontSize, m_fontType)/2.0f;
+ ddim.x = dim.x-dim.y;
+ DrawCase(m_text[i+m_firstLine], ppos, ddim.x, 1);
+ }
+ else
+ {
+ ppos.x = pos.x+dim.y*0.5f;
+ ppos.y = pos.y+dim.y*0.5f;
+ ppos.y -= m_engine->RetText()->RetHeight(m_fontSize, m_fontType)/2.0f;
+ pb = m_text[i+m_firstLine];
+ for ( j=0 ; j<10 ; j++ )
+ {
+ pe = strchr(pb, '\t');
+ if ( pe == 0 )
+ {
+ strcpy(text, pb);
+ }
+ else
+ {
+ strncpy(text, pb, pe-pb);
+ text[pe-pb] = 0;
+ }
+ DrawCase(text, ppos, m_tabs[j], m_justifs[j]);
+
+ if ( pe == 0 ) break;
+ ppos.x += m_tabs[j];
+ pb = pe+1;
+ }
+ }
+
+ if ( (m_state & STATE_EXTEND) && i < m_totalLine )
+ {
+ pos = m_button[i]->RetPos();
+ dim = m_button[i]->RetDim();
+ pos.x += dim.x-dim.y*0.75f;
+ dim.x = dim.y*0.75f;
+ pos.x += 2.0f/640.0f;
+ pos.y += 2.0f/480.0f;
+ dim.x -= 4.0f/640.0f;
+ dim.y -= 4.0f/480.0f;
+
+ if ( m_check[i+m_firstLine] )
+ {
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 64.0f/256.0f;
+ uv1.y = 0.0f/256.0f;
+ uv2.x = 96.0f/256.0f;
+ uv2.y = 32.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2); // square shape
+
+ m_engine->SetState(D3DSTATETTw);
+ uv1.x = 0.0f/256.0f; // v
+ uv1.y = 64.0f/256.0f;
+ uv2.x = 32.0f/256.0f;
+ uv2.y = 96.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2); // draws v
+ }
+ else
+ {
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATETTw);
+ if ( i+m_firstLine == m_selectLine )
+ {
+ uv1.x =224.0f/256.0f; // <
+ uv1.y =192.0f/256.0f;
+ uv2.x =256.0f/256.0f;
+ uv2.y =224.0f/256.0f;
+ }
+ else
+ {
+ uv1.x = 96.0f/256.0f; // x
+ uv1.y = 32.0f/256.0f;
+ uv2.x =128.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+ }
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2); // draws x
+ }
+ }
+ }
+ }
+
+ if ( m_scroll != 0 )
+ {
+ m_scroll->Draw(); // draws the lift
+ }
+}
+
+// Displays text in a box.
+
+void CList::DrawCase(char *text, Math::Point pos, float width, int justif)
+{
+ if ( justif == 1 )
+ {
+ m_engine->RetText()->DrawText(text, pos, width, 1, m_fontSize, m_fontStretch, m_fontType, 0);
+ }
+ else if ( justif == 0 )
+ {
+ pos.x += width/2.0f;
+ m_engine->RetText()->DrawText(text, pos, width, 0, m_fontSize, m_fontStretch, m_fontType, 0);
+ }
+ else
+ {
+ pos.x += width;
+ m_engine->RetText()->DrawText(text, pos, width, -1, m_fontSize, m_fontStretch, m_fontType, 0);
+ }
+}
+
+
+// Empty the list completely.
+
+void CList::Flush()
+{
+ m_totalLine = 0;
+ m_selectLine = -1;
+ m_firstLine = 0;
+ UpdateButton();
+ UpdateScroll();
+}
+
+
+// Specifies the total number of lines.
+
+void CList::SetTotal(int i)
+{
+ m_totalLine = i;
+}
+
+// Returns the total number of lines.
+
+int CList::RetTotal()
+{
+ return m_totalLine;
+}
+
+
+// Selects a line.
+
+void CList::SetSelect(int i)
+{
+ if ( m_bSelectCap )
+ {
+ m_selectLine = i;
+ }
+ else
+ {
+ m_firstLine = i;
+ UpdateScroll();
+ }
+
+ UpdateButton();
+}
+
+// Returns the selected line.
+
+int CList::RetSelect()
+{
+ if ( m_bSelectCap )
+ {
+ return m_selectLine;
+ }
+ else
+ {
+ return m_firstLine;
+ }
+}
+
+
+// Management of capability has a select box.
+
+void CList::SetSelectCap(bool bEnable)
+{
+ m_bSelectCap = bEnable;
+}
+
+bool CList::RetSelectCap()
+{
+ return m_bSelectCap;
+}
+
+
+// Blink a line.
+
+void CList::SetBlink(bool bEnable)
+{
+ int i;
+
+ m_bBlink = bEnable;
+ m_blinkTime = 0.0f;
+
+ i = m_selectLine-m_firstLine;
+
+ if ( i >= 0 && i < 4 &&
+ m_button[i] != 0 )
+ {
+ if ( !bEnable )
+ {
+ m_button[i]->SetState(STATE_CHECK);
+ m_button[i]->ClearState(STATE_ENABLE);
+ }
+ }
+}
+
+bool CList::RetBlink()
+{
+ return m_bBlink;
+}
+
+
+// Specifies the text of a line.
+
+void CList::SetName(int i, char* name)
+{
+ if ( i < 0 || i >= LISTMAXTOTAL ) return;
+
+ if ( i >= m_totalLine )
+ {
+ m_totalLine = i+1; // expands the list
+ }
+
+ if ( name[0] == 0 )
+ {
+ strcpy(m_text[i], " ");
+ }
+ else
+ {
+ strcpy(m_text[i], name);
+ }
+ UpdateButton();
+ UpdateScroll();
+}
+
+// Returns the text of a line.
+
+char* CList::RetName(int i)
+{
+ if ( i < 0 || i >= m_totalLine ) return 0;
+
+ return m_text[i];
+}
+
+
+// Specifies the bit "check" for a box.
+
+void CList::SetCheck(int i, bool bMode)
+{
+ if ( i < 0 || i >= m_totalLine ) return;
+
+ m_check[i] = bMode;
+}
+
+// Returns the bit "check" for a box.
+
+bool CList::RetCheck(int i)
+{
+ if ( i < 0 || i >= m_totalLine ) return false;
+
+ return m_check[i];
+}
+
+
+// Specifies the bit "enable" for a box.
+
+void CList::SetEnable(int i, bool bMode)
+{
+ if ( i < 0 || i >= m_totalLine ) return;
+
+ m_enable[i] = bMode;
+}
+
+// Returns the bit "enable" for a box.
+
+bool CList::RetEnable(int i)
+{
+ if ( i < 0 || i >= m_totalLine ) return false;
+
+ return m_enable[i];
+}
+
+
+// Management of the position of the tabs.
+
+void CList::SetTabs(int i, float pos, int justif)
+{
+ if ( i < 0 || i >= 10 ) return;
+ m_tabs[i] = pos;
+ m_justifs[i] = justif;
+}
+
+float CList::RetTabs(int i)
+{
+ if ( i < 0 || i >= 10 ) return 0.0f;
+ return m_tabs[i];
+}
+
+
+// Moves the lift to see the list of the selected line.
+
+void CList::ShowSelect(bool bFixed)
+{
+ int sel;
+
+ if ( bFixed &&
+ m_selectLine >= m_firstLine &&
+ m_selectLine < m_firstLine+m_displayLine ) return; // all good
+
+ sel = m_selectLine;
+
+ // Down from 1/2 * h.
+ sel += m_displayLine/2;
+ if ( sel > m_totalLine-1 ) sel = m_totalLine-1;
+
+ // Back to h-1.
+ sel -= m_displayLine-1;
+ if ( sel < 0 ) sel = 0;
+
+ m_firstLine = sel;
+
+ UpdateButton();
+ UpdateScroll();
+}
+
+
+// Updates all button names.
+
+void CList::UpdateButton()
+{
+ int state, i, j;
+
+ state = CControl::RetState();
+
+ j = m_firstLine;
+ for ( i=0 ; i<m_displayLine ; i++ )
+ {
+ if ( m_button[i] == 0 ) continue;
+
+ m_button[i]->SetState(STATE_CHECK, (j == m_selectLine));
+
+ if ( j < m_totalLine )
+ {
+//? m_button[i]->SetName(m_text[j]);
+ m_button[i]->SetName(" "); // blank button
+ m_button[i]->SetState(STATE_ENABLE, (state & STATE_ENABLE));
+ }
+ else
+ {
+ m_button[i]->SetName(" "); // blank button
+ m_button[i]->ClearState(STATE_ENABLE);
+ }
+ j ++;
+ }
+}
+
+// Updates the lift.
+
+void CList::UpdateScroll()
+{
+ float ratio, value, step;
+
+ if ( m_scroll == 0 ) return;
+
+ if ( m_totalLine <= m_displayLine )
+ {
+ ratio = 1.0f;
+ value = 0.0f;
+ step = 0.0f;
+ }
+ else
+ {
+ ratio = (float)m_displayLine/m_totalLine;
+ if ( ratio > 1.0f ) ratio = 1.0f;
+
+ value = (float)m_firstLine/(m_totalLine-m_displayLine);
+ if ( value < 0.0f ) value = 0.0f;
+ if ( value > 1.0f ) value = 1.0f;
+
+ step = (float)1.0f/(m_totalLine-m_displayLine);
+ if ( step < 0.0f ) step = 0.0f;
+ }
+
+ m_scroll->SetVisibleRatio(ratio);
+ m_scroll->SetVisibleValue(value);
+ m_scroll->SetArrowStep(step);
+}
+
+// Update when the lift is moving.
+
+void CList::MoveScroll()
+{
+ float pos;
+ int n;
+
+ if ( m_scroll == 0 ) return;
+
+ n = m_totalLine-m_displayLine;
+ pos = m_scroll->RetVisibleValue();
+ pos += m_scroll->RetArrowStep()/2.0f; // it's magic!
+ m_firstLine = (int)(pos*n);
+ if ( m_firstLine < 0 ) m_firstLine = 0;
+ if ( m_firstLine > n ) m_firstLine = n;
+}
+
+
diff --git a/src/ui/list.h b/src/ui/list.h
index ead058b..cc9e646 100644
--- a/src/ui/list.h
+++ b/src/ui/list.h
@@ -1,115 +1,115 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// list.h
-
-#pragma once
-
-
-#include "ui/control.h"
-#include "common/event.h"
-
-
-class CD3DEngine;
-class CButton;
-class CScroll;
-
-
-const int LISTMAXDISPLAY = 20; // maximum number of visible lines
-const int LISTMAXTOTAL = 100; // maximum total number of lines
-
-
-
-class CList : public CControl
-{
-public:
- CList(CInstanceManager* iMan);
- ~CList();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg, float expand);
-
- void SetPos(Math::Point pos);
- void SetDim(Math::Point dim);
-
- bool SetState(int state, bool bState);
- bool SetState(int state);
- bool ClearState(int state);
-
- bool EventProcess(const Event &event);
- void Draw();
-
- void Flush();
-
- void SetTotal(int i);
- int RetTotal();
-
- void SetSelect(int i);
- int RetSelect();
-
- void SetSelectCap(bool bEnable);
- bool RetSelectCap();
-
- void SetBlink(bool bEnable);
- bool RetBlink();
-
- void SetName(int i, char* name);
- char* RetName(int i);
-
- void SetCheck(int i, bool bMode);
- bool RetCheck(int i);
-
- void SetEnable(int i, bool bEnable);
- bool RetEnable(int i);
-
- void SetTabs(int i, float pos, int justif=1);
- float RetTabs(int i);
-
- void ShowSelect(bool bFixed);
-
- EventMsg RetEventMsgButton(int i);
- EventMsg RetEventMsgScroll();
-
-protected:
- bool MoveAdjust();
- void UpdateButton();
- void UpdateScroll();
- void MoveScroll();
- void DrawCase(char *text, Math::Point pos, float width, int justif);
-
-protected:
- CButton* m_button[LISTMAXDISPLAY];
- CScroll* m_scroll;
-
- EventMsg m_eventButton[LISTMAXDISPLAY];
- EventMsg m_eventScroll;
-
- float m_expand;
- int m_totalLine; // total number of lines
- int m_displayLine; // number of visible lines
- int m_selectLine; // selected line
- int m_firstLine; // first visible line
- bool m_bBlink;
- bool m_bSelectCap;
- float m_blinkTime;
- float m_tabs[10];
- int m_justifs[10];
-
- char m_text[LISTMAXTOTAL][100];
- char m_check[LISTMAXTOTAL];
- char m_enable[LISTMAXTOTAL];
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// list.h
+
+#pragma once
+
+
+#include "ui/control.h"
+#include "common/event.h"
+
+
+class CD3DEngine;
+class CButton;
+class CScroll;
+
+
+const int LISTMAXDISPLAY = 20; // maximum number of visible lines
+const int LISTMAXTOTAL = 100; // maximum total number of lines
+
+
+
+class CList : public CControl
+{
+public:
+ CList(CInstanceManager* iMan);
+ ~CList();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg, float expand);
+
+ void SetPos(Math::Point pos);
+ void SetDim(Math::Point dim);
+
+ bool SetState(int state, bool bState);
+ bool SetState(int state);
+ bool ClearState(int state);
+
+ bool EventProcess(const Event &event);
+ void Draw();
+
+ void Flush();
+
+ void SetTotal(int i);
+ int RetTotal();
+
+ void SetSelect(int i);
+ int RetSelect();
+
+ void SetSelectCap(bool bEnable);
+ bool RetSelectCap();
+
+ void SetBlink(bool bEnable);
+ bool RetBlink();
+
+ void SetName(int i, char* name);
+ char* RetName(int i);
+
+ void SetCheck(int i, bool bMode);
+ bool RetCheck(int i);
+
+ void SetEnable(int i, bool bEnable);
+ bool RetEnable(int i);
+
+ void SetTabs(int i, float pos, int justif=1);
+ float RetTabs(int i);
+
+ void ShowSelect(bool bFixed);
+
+ EventMsg RetEventMsgButton(int i);
+ EventMsg RetEventMsgScroll();
+
+protected:
+ bool MoveAdjust();
+ void UpdateButton();
+ void UpdateScroll();
+ void MoveScroll();
+ void DrawCase(char *text, Math::Point pos, float width, int justif);
+
+protected:
+ CButton* m_button[LISTMAXDISPLAY];
+ CScroll* m_scroll;
+
+ EventMsg m_eventButton[LISTMAXDISPLAY];
+ EventMsg m_eventScroll;
+
+ float m_expand;
+ int m_totalLine; // total number of lines
+ int m_displayLine; // number of visible lines
+ int m_selectLine; // selected line
+ int m_firstLine; // first visible line
+ bool m_bBlink;
+ bool m_bSelectCap;
+ float m_blinkTime;
+ float m_tabs[10];
+ int m_justifs[10];
+
+ char m_text[LISTMAXTOTAL][100];
+ char m_check[LISTMAXTOTAL];
+ char m_enable[LISTMAXTOTAL];
+};
+
+
diff --git a/src/ui/maindialog.cpp b/src/ui/maindialog.cpp
index 267c4b1..a45846e 100644
--- a/src/ui/maindialog.cpp
+++ b/src/ui/maindialog.cpp
@@ -1,6935 +1,6935 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// maindialog.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <time.h>
-#include <direct.h>
-#include <io.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/global.h"
-#include "common/language.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/profile.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "old/math3d.h"
-#include "old/particule.h"
-#include "ui/interface.h"
-#include "ui/button.h"
-#include "ui/color.h"
-#include "ui/check.h"
-#include "ui/key.h"
-#include "ui/group.h"
-#include "ui/image.h"
-#include "ui/scroll.h"
-#include "ui/slider.h"
-#include "ui/list.h"
-#include "ui/label.h"
-#include "ui/window.h"
-#include "ui/edit.h"
-#include "ui/editvalue.h"
-#include "old/text.h"
-#include "old/camera.h"
-#include "old/sound.h"
-#include "script/cmdtoken.h"
-#include "object/robotmain.h"
-#include "ui/maindialog.h"
-
-
-
-const int KEY_VISIBLE = 6; // number of visible keys redefinable
-
-#if _SCHOOL & _TEEN
-const int KEY_TOTAL = 13; // total number of keys redefinable
-#else
-const int KEY_TOTAL = 21; // total number of keys redefinable
-#endif
-
-const int WELCOME_LENGTH = 6.0f;
-
-
-
-static int perso_color[3*10*3] =
-{
- // hair:
- 193, 221, 226, // white
- 255, 255, 181, // yellow
- 204, 155, 84, // blond
- 165, 48, 10, // red
- 140, 75, 84, // brown
- 83, 64, 51, // brown
- 90, 95, 85, // black
- 85, 48, 9, // brown
- 60, 0, 23, // black
- 0, 0, 0, //
- // spacesuit:
- 203, 206, 204, // dirty white
- 0, 205, 203, // bluish
- 108, 176, 0, // greenish
- 207, 207, 32, // yellow
- 170, 141, 0, // orange
- 108, 84, 0, // brown
- 0, 84, 136, // bluish
- 56, 61, 146, // bluish
- 56, 56, 56, // black
- 0, 0, 0, //
- // strips:
- 255, 255, 255, // white
- 255, 255, 0, // yellow
- 255, 132, 1, // orange
- 255, 0, 255, // magenta
- 255, 0, 0, // red
- 0, 255, 0, // green
- 0, 255, 255, // cyan
- 0, 0, 255, // blue
- 70, 51, 84, // dark
- 0, 0, 0, //
-};
-
-
-#if _NET
-// Check if the key "school" is present in the registry.
-
-bool SchoolCheck()
-{
- HKEY key;
- char buffer[100];
- LONG i;
- DWORD type, len;
-
- i = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-#if _NEWLOOK
- "Software\\Epsitec\\CeeBot\\Setup",
-#else
- "Software\\Epsitec\\Colobot\\Setup",
-#endif
- 0, KEY_READ, &key);
- if ( i != ERROR_SUCCESS ) return false;
-
- type = REG_SZ;
- len = sizeof(buffer);
- i = RegQueryValueEx(key, "School", NULL, &type, (LPBYTE)buffer, &len);
- if ( i != ERROR_SUCCESS || type != REG_SZ ) return false;
-
- if ( strcmp(buffer, "ToBoLoC") != 0 ) return false;
-
- return true;
-}
-#endif
-
-
-// Constructor of robot application.
-
-CMainDialog::CMainDialog(CInstanceManager* iMan)
-{
- int i;
-
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_DIALOG, this);
-
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
- m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
-
- m_phase = PHASE_NAME;
- m_phaseSetup = PHASE_SETUPg;
- m_phaseTerm = PHASE_TRAINER;
- m_sceneRead[0] = 0;
- m_stackRead[0] = 0;
- m_sceneName[0] = 0;
- m_sceneRank = 0;
- m_bSceneSoluce = false;
- m_bSimulSetup = false;
-#if _NET
- m_accessEnable = SchoolCheck();
- m_accessMission= false;
- m_accessUser = false;
-#else
- m_accessEnable = true;
- m_accessMission= true;
- m_accessUser = true;
-#endif
- m_bDeleteGamer = true;
-
- for ( i=0 ; i<10 ; i++ )
- {
- m_chap[i] = 0;
- m_sel[i] = 0;
- }
- m_index = 0;
- m_maxList = 0;
-
- ZeroMemory(&m_perso, sizeof(GamerPerso));
- DefPerso();
-
- m_bTooltip = true;
- m_bGlint = true;
- m_bRain = true;
- m_bSoluce4 = true;
- m_bMovies = true;
- m_bNiceReset = true;
- m_bHimselfDamage = true;
-#if _TEEN
- m_bCameraScroll = false;
-#else
- m_bCameraScroll = true;
-#endif
- m_bCameraInvertX = false;
- m_bCameraInvertY = false;
- m_bEffect = true;
- m_shotDelay = 0;
-
- m_glintMouse = Math::Point(0.0f, 0.0f);
- m_glintTime = 1000.0f;
-
- for ( i=0 ; i<10 ; i++ )
- {
- m_partiPhase[i] = 0;
- m_partiTime[i] = 0.0f;
- }
-
- strcpy(m_sceneDir, "scene");
- strcpy(m_savegameDir, "savegame");
- strcpy(m_publicDir, "program");
- strcpy(m_userDir, "user");
- strcpy(m_filesDir, "files");
-
- m_bDialog = false;
-}
-
-// Destructor of robot application.
-
-CMainDialog::~CMainDialog()
-{
-}
-
-
-// Changes phase.
-
-void CMainDialog::ChangePhase(Phase phase)
-{
- CWindow* pw;
- CEdit* pe;
- CEditValue* pv;
- CLabel* pl;
- CList* pli;
- CCheck* pc;
- CScroll* ps;
- CSlider* psl;
- CButton* pb;
- CColor* pco;
- CGroup* pg;
- CImage* pi;
- Math::Point pos, dim, ddim;
- float ox, oy, sx, sy;
- char name[100];
- char* gamer;
- int res, i, j;
-
- m_camera->SetType(CAMERA_DIALOG);
- m_engine->SetOverFront(false);
- m_engine->SetOverColor(RetColor(0.0f), D3DSTATETCb);
-
- if ( phase == PHASE_TERM )
- {
- phase = m_phaseTerm;
- }
- m_phase = phase; // copy the info to CRobotMain
- m_phaseTime = 0.0f;
-
- dim.x = 32.0f/640.0f;
- dim.y = 32.0f/480.0f;
- ox = 3.0f/640.0f;
- oy = 3.0f/480.0f;
- sx = (32.0f+2.0f)/640.0f;
- sy = (32.0f+2.0f)/480.0f;
-
- if ( m_phase == PHASE_INIT )
- {
- pos.x = 0.35f;
- pos.y = 0.10f;
- ddim.x = 0.30f;
- ddim.y = 0.80f;
-#if _TEEN
- pw = m_interface->CreateWindows(pos, ddim, 12, EVENT_WINDOW5);
-#else
- pw = m_interface->CreateWindows(pos, ddim, 10, EVENT_WINDOW5);
-#endif
- GetResource(RES_TEXT, RT_TITLE_INIT, name);
- pw->SetName(name);
-
- pos.x = 0.35f;
- pos.y = 0.60f;
- ddim.x = 0.30f;
- ddim.y = 0.30f;
- pw->CreateGroup(pos, ddim, 5, EVENT_INTERFACE_GLINTl); // orange corner
- pos.x = 0.35f;
- pos.y = 0.10f;
- ddim.x = 0.30f;
- ddim.y = 0.30f;
- pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner
-
-#if _SCHOOL
- ddim.x = 0.20f;
- ddim.y = dim.y*2.4f;
- pos.x = 0.40f;
- pos.y = oy+sy*7.9f;
- pg = pw->CreateGroup(pos, ddim, 24, EVENT_LABEL1); // orange
- pg->SetState(STATE_SHADOW);
- pos.y = oy+sy*3.9f;
- pg = pw->CreateGroup(pos, ddim, 25, EVENT_LABEL1); // orange
- pg->SetState(STATE_SHADOW);
- ddim.y = dim.y*1.2f;
- pos.y = oy+sy*1.9f;
- pg = pw->CreateGroup(pos, ddim, 26, EVENT_LABEL1); // red
- pg->SetState(STATE_SHADOW);
-#else
- ddim.x = 0.20f;
- ddim.y = dim.y*2.4f;
- pos.x = 0.40f;
- if ( m_accessEnable && m_accessMission )
- {
- pos.y = oy+sy*9.1f;
- pg = pw->CreateGroup(pos, ddim, 23, EVENT_LABEL1); // yellow
- pg->SetState(STATE_SHADOW);
- }
- pos.y = oy+sy*6.8f;
- pg = pw->CreateGroup(pos, ddim, 24, EVENT_LABEL1); // orange
- pg->SetState(STATE_SHADOW);
- pos.y = oy+sy*3.9f;
- pg = pw->CreateGroup(pos, ddim, 25, EVENT_LABEL1); // orange
- pg->SetState(STATE_SHADOW);
- ddim.y = dim.y*1.2f;
- pos.y = oy+sy*1.9f;
- pg = pw->CreateGroup(pos, ddim, 26, EVENT_LABEL1); // red
- pg->SetState(STATE_SHADOW);
-#endif
-
-#if _SCHOOL
- ddim.x = 0.18f;
- ddim.y = dim.y*1;
- pos.x = 0.41f;
- pos.y = oy+sy*9.1f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_TRAINER);
- pb->SetState(STATE_SHADOW);
-
- pos.y = oy+sy*8.0f;
-#if _TEEN
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_TEEN);
-#else
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_DEFI);
-#endif
-#if _CEEBOTDEMO
- pb->ClearState(STATE_ENABLE);
-#endif
- pb->SetState(STATE_SHADOW);
-#else
- ddim.x = 0.18f;
- ddim.y = dim.y*1;
- pos.x = 0.41f;
-
- if ( m_accessEnable && m_accessMission )
- {
- pos.y = oy+sy*10.3f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_MISSION);
- pb->SetState(STATE_SHADOW);
-
- pos.y = oy+sy*9.2f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_FREE);
- pb->SetState(STATE_SHADOW);
- }
-
- pos.y = oy+sy*8.0f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_TRAINER);
- pb->SetState(STATE_SHADOW);
-
- pos.y = oy+sy*6.9f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_DEFI);
- pb->SetState(STATE_SHADOW);
-#endif
-
- if ( m_engine->RetSetupMode() )
- {
- pos.y = oy+sy*5.1f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_SETUP);
- pb->SetState(STATE_SHADOW);
- }
-
- pos.y = oy+sy*4.0f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_NAME);
- pb->SetState(STATE_SHADOW);
-
- pos.y = oy+sy*2.0f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_QUIT);
- pb->SetState(STATE_SHADOW);
-
-#if !_DEMO & !_SCHOOL
- if ( m_accessEnable && m_accessUser )
- {
- pos.x = 447.0f/640.0f;
- pos.y = 313.0f/480.0f;
- ddim.x = 0.09f;
-#if _POLISH
- pos.x -= 5.0f/640.0f;
- ddim.x += 10.0f/640.0f;
-#endif
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_USER);
- pb->SetState(STATE_SHADOW);
- }
-#endif
-
- if ( m_engine->RetDebugMode() )
- {
- pos.x = 139.0f/640.0f;
- pos.y = 313.0f/480.0f;
- ddim.x = 0.09f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PROTO);
- pb->SetState(STATE_SHADOW);
- }
-
- pos.x = 0.40f;
- ddim.x = 0.20f;
- pos.y = 26.0f/480.0f;
- ddim.y = 12.0f/480.0f;
- pg = pw->CreateGroup(pos, ddim, 1, EVENT_LABEL1);
- pg->SetState(STATE_SHADOW);
- pos.y -= 5.0f/480.0f;
-#if _WG
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, " ");
-#else
-#if _NEWLOOK
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, "www.epsitec.ch");
-#else
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, "www.ceebot.com");
-#endif
-#endif
- pl->SetFontType(FONT_COURIER);
- pl->SetFontSize(8.0f);
-
- m_engine->SetBackground("inter01.tga", 0,0, 0,0, true, true);
- m_engine->SetBackForce(true);
- }
-
- if ( m_phase == PHASE_NAME )
- {
- pos.x = 0.10f;
- pos.y = 0.10f;
- ddim.x = 0.80f;
- ddim.y = 0.80f;
- pw = m_interface->CreateWindows(pos, ddim, 12, EVENT_WINDOW5);
- GetResource(RES_TEXT, RT_TITLE_NAME, name);
- pw->SetName(name);
-
-#if _NEWLOOK
- pos.x = 80.0f/640.0f;
- pos.y = 93.0f/480.0f;
- ddim.x = 285.0f/640.0f;
- ddim.y = 266.0f/480.0f;
- pg = pw->CreateGroup(pos, ddim, 23, EVENT_LABEL1); // blue
- pg->SetState(STATE_SHADOW);
- pos.x = 372.0f/640.0f;
- ddim.x = 188.0f/640.0f;
- pg = pw->CreateGroup(pos, ddim, 26, EVENT_LABEL1); // violet
- pg->SetState(STATE_SHADOW);
-#endif
-
- pos.x = 0.10f;
- pos.y = 0.40f;
- ddim.x = 0.50f;
- ddim.y = 0.50f;
- pw->CreateGroup(pos, ddim, 5, EVENT_INTERFACE_GLINTl); // orange corner
- pos.x = 0.40f;
- pos.y = 0.10f;
- ddim.x = 0.50f;
- ddim.y = 0.50f;
- pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner
-
- pos.x = 60.0f/640.0f;
- pos.y = 313.0f/480.0f;
- ddim.x = 120.0f/640.0f;
- ddim.y = 32.0f/480.0f;
- GetResource(RES_EVENT, EVENT_INTERFACE_NLABEL, name);
- pl = pw->CreateLabel(pos, ddim, -1, EVENT_INTERFACE_NLABEL, name);
- pl->SetJustif(-1);
-
- pos.x = 200.0f/640.0f;
- pos.y = 320.0f/480.0f;
- ddim.x = 160.0f/640.0f;
- ddim.y = 32.0f/480.0f;
- pg = pw->CreateGroup(pos, ddim, 7, EVENT_LABEL1);
- pg->SetState(STATE_SHADOW);
-
- pos.x = 207.0f/640.0f;
- pos.y = 328.0f/480.0f;
- ddim.x = 144.0f/640.0f;
- ddim.y = 18.0f/480.0f;
- pe = pw->CreateEdit(pos, ddim, 0, EVENT_INTERFACE_NEDIT);
- pe->SetMaxChar(15);
- gamer = m_main->RetGamerName();
- if ( gamer[0] == 0 )
- {
- GetResource(RES_TEXT, RT_NAME_DEFAULT, name);
- }
- else
- {
- strcpy(name, gamer);
- }
- pe->SetText(name);
- pe->SetCursor(strlen(name), 0);
- pe->SetFocus(true);
-
- pos.x = 380.0f/640.0f;
- pos.y = 320.0f/480.0f;
- ddim.x =100.0f/640.0f;
- ddim.y = 32.0f/480.0f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_NOK);
- pb->SetState(STATE_SHADOW);
-
-#if !_TEEN
- pos.x = 380.0f/640.0f;
- pos.y = 250.0f/480.0f;
- ddim.x =100.0f/640.0f;
- ddim.y = 52.0f/480.0f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PERSO);
- pb->SetState(STATE_SHADOW);
-#endif
-
- pos.x = 200.0f/640.0f;
- pos.y = 150.0f/480.0f;
- ddim.x = 160.0f/640.0f;
- ddim.y = 160.0f/480.0f;
- pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_NLIST);
- pli->SetState(STATE_SHADOW);
-
- if ( m_bDeleteGamer )
- {
- pos.x = 200.0f/640.0f;
- pos.y = 100.0f/480.0f;
- ddim.x = 160.0f/640.0f;
- ddim.y = 32.0f/480.0f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_NDELETE);
- pb->SetState(STATE_SHADOW);
- }
-
- pos.x = 380.0f/640.0f;
- pos.y = 100.0f/480.0f;
- ddim.x =100.0f/640.0f;
- ddim.y = 32.0f/480.0f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_NCANCEL);
- pb->SetState(STATE_SHADOW);
-
- ReadNameList();
- UpdateNameList();
- UpdateNameControl();
- UpdateNameFace();
-
- m_engine->SetBackground("inter01.tga", 0,0, 0,0, true, true);
- m_engine->SetBackForce(true);
- }
-
- if ( m_phase == PHASE_PERSO )
- {
- pos.x = 0.10f;
- pos.y = 0.10f;
- ddim.x = 0.80f;
- ddim.y = 0.80f;
- pw = m_interface->CreateWindows(pos, ddim, 12, EVENT_WINDOW5);
- GetResource(RES_TEXT, RT_TITLE_PERSO, name);
- pw->SetName(name);
-
-#if _NEWLOOK
- pos.x = 95.0f/640.0f;
- pos.y = 66.0f/480.0f;
- ddim.x = 443.0f/640.0f;
- ddim.y = 42.0f/480.0f;
- pg = pw->CreateGroup(pos, ddim, 26, EVENT_LABEL1); // violet
- pg->SetState(STATE_SHADOW);
-#endif
-
- pos.x = 0.10f;
- pos.y = 0.40f;
- ddim.x = 0.50f;
- ddim.y = 0.50f;
- pw->CreateGroup(pos, ddim, 5, EVENT_INTERFACE_GLINTl); // orange corner
- pos.x = 0.40f;
- pos.y = 0.10f;
- ddim.x = 0.50f;
- ddim.y = 0.50f;
- pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner
-
- pos.x = 95.0f/640.0f;
- pos.y = 108.0f/480.0f;
- ddim.x = 220.0f/640.0f;
- ddim.y = 274.0f/480.0f;
- pw->CreateGroup(pos, ddim, 17, EVENT_NULL); // frame
-
- pos.x = 100.0f/640.0f;
- pos.y = 364.0f/480.0f;
- ddim.x = 210.0f/640.0f;
- ddim.y = 14.0f/480.0f;
- pw->CreateGroup(pos, ddim, 3, EVENT_NULL); // transparent -> gray
-
- pos.x = 120.0f/640.0f;
- pos.y = 364.0f/480.0f;
- ddim.x = 80.0f/640.0f;
- ddim.y = 28.0f/480.0f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PHEAD);
- pb->SetState(STATE_SHADOW);
- pb->SetState(STATE_CARD);
-
- pos.x = 210.0f/640.0f;
- pos.y = 364.0f/480.0f;
- ddim.x = 80.0f/640.0f;
- ddim.y = 28.0f/480.0f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PBODY);
- pb->SetState(STATE_SHADOW);
- pb->SetState(STATE_CARD);
-
- pos.x = 100.0f/640.0f;
- pos.y = 354.0f/480.0f;
- ddim.x = 210.0f/640.0f;
- ddim.y = 10.0f/480.0f;
- pw->CreateGroup(pos, ddim, 1, EVENT_INTERFACE_GLINTb); // orange bar
- pos.x = 100.0f/640.0f;
- pos.y = 154.0f/480.0f;
- ddim.x = 210.0f/640.0f;
- ddim.y = 200.0f/480.0f;
- pw->CreateGroup(pos, ddim, 2, EVENT_INTERFACE_GLINTu); // orange -> transparent
-
- // Face
- pos.x = 340.0f/640.0f;
- pos.y = 356.0f/480.0f;
- ddim.x = 200.0f/640.0f;
- ddim.y = 16.0f/480.0f;
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL11, "");
- pl->SetJustif(1);
-
- pos.x = 340.0f/640.0f;
- pos.y = 312.0f/480.0f;
- ddim.x = 44.0f/640.0f;
- ddim.y = 44.0f/480.0f;
- pb = pw->CreateButton(pos, ddim, 43, EVENT_INTERFACE_PFACE1);
- pb->SetState(STATE_SHADOW);
- pos.x += 50.0f/640.0f;
- pb = pw->CreateButton(pos, ddim, 46, EVENT_INTERFACE_PFACE4);
- pb->SetState(STATE_SHADOW);
- pos.x += 50.0f/640.0f;
- pb = pw->CreateButton(pos, ddim, 45, EVENT_INTERFACE_PFACE3);
- pb->SetState(STATE_SHADOW);
- pos.x += 50.0f/640.0f;
- pb = pw->CreateButton(pos, ddim, 44, EVENT_INTERFACE_PFACE2);
- pb->SetState(STATE_SHADOW);
-
- // Glasses
- pos.x = 340.0f/640.0f;
- pos.y = 270.0f/480.0f;
- ddim.x = 200.0f/640.0f;
- ddim.y = 16.0f/480.0f;
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL12, "");
- pl->SetJustif(1);
-
- pos.x = 340.0f/640.0f;
- pos.y = 240.0f/480.0f;
- ddim.x = 30.0f/640.0f;
- ddim.y = 30.0f/480.0f;
- for ( i=0 ; i<6 ; i++ )
- {
- int ti[6] = {11, 179, 180, 181, 182, 183};
- pb = pw->CreateButton(pos, ddim, ti[i], (EventMsg)(EVENT_INTERFACE_PGLASS0+i));
- pb->SetState(STATE_SHADOW);
- pos.x += (30.0f+2.8f)/640.0f;
- }
-
- // Color A
- pos.x = 340.0f/640.0f;
- pos.y = 300.0f/480.0f;
- ddim.x = 200.0f/640.0f;
- ddim.y = 16.0f/480.0f;
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL14, "");
- pl->SetJustif(1);
-
- pos.y = 282.0f/480.0f;
- ddim.x = 18.0f/640.0f;
- ddim.y = 18.0f/480.0f;
- for ( j=0 ; j<3 ; j++ )
- {
- pos.x = 340.0f/640.0f;
- for ( i=0 ; i<3 ; i++ )
- {
- pco = pw->CreateColor(pos, ddim, -1, (EventMsg)(EVENT_INTERFACE_PC0a+j*3+i));
- pco->SetState(STATE_SHADOW);
- pos.x += 20.0f/640.0f;
- }
- pos.y -= 20.0f/480.0f;
- }
-
- pos.x = 420.0f/640.0f;
- pos.y = 282.0f/480.0f;
- ddim.x = 100.0f/640.0f;
- ddim.y = 18.0f/480.0f;
- for ( i=0 ; i<3 ; i++ )
- {
- psl = pw->CreateSlider(pos, ddim, 0, (EventMsg)(EVENT_INTERFACE_PCRa+i));
- psl->SetState(STATE_SHADOW);
- psl->SetLimit(0.0f, 255.0f);
- psl->SetArrowStep(16.0f);
- pos.y -= 20.0f/480.0f;
- }
-
- // Color B
- pos.x = 340.0f/640.0f;
- pos.y = 192.0f/480.0f;
- ddim.x = 200.0f/640.0f;
- ddim.y = 16.0f/480.0f;
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL13, "");
- pl->SetJustif(1);
-
- pos.y = 174.0f/480.0f;
- ddim.x = 18.0f/640.0f;
- ddim.y = 18.0f/480.0f;
- for ( j=0 ; j<3 ; j++ )
- {
- pos.x = 340.0f/640.0f;
- for ( i=0 ; i<3 ; i++ )
- {
- pco = pw->CreateColor(pos, ddim, -1, (EventMsg)(EVENT_INTERFACE_PC0b+j*3+i));
- pco->SetState(STATE_SHADOW);
- pos.x += 20.0f/640.0f;
- }
- pos.y -= 20.0f/480.0f;
- }
-
- pos.x = 420.0f/640.0f;
- pos.y = 174.0f/480.0f;
- ddim.x = 100.0f/640.0f;
- ddim.y = 18.0f/480.0f;
- for ( i=0 ; i<3 ; i++ )
- {
- psl = pw->CreateSlider(pos, ddim, 0, (EventMsg)(EVENT_INTERFACE_PCRb+i));
- psl->SetState(STATE_SHADOW);
- psl->SetLimit(0.0f, 255.0f);
- psl->SetArrowStep(16.0f);
- pos.y -= 20.0f/480.0f;
- }
-
- // Rotation
- pos.x = 100.0f/640.0f;
- pos.y = 113.0f/480.0f;
- ddim.x = 20.0f/640.0f;
- ddim.y = 20.0f/480.0f;
- pb = pw->CreateButton(pos, ddim, 55, EVENT_INTERFACE_PLROT); // <
- pb->SetState(STATE_SHADOW);
- pb->SetRepeat(true);
-
- pos.x = 290.0f/640.0f;
- pos.y = 113.0f/480.0f;
- ddim.x = 20.0f/640.0f;
- ddim.y = 20.0f/480.0f;
- pb = pw->CreateButton(pos, ddim, 48, EVENT_INTERFACE_PRROT); // >
- pb->SetState(STATE_SHADOW);
- pb->SetRepeat(true);
-
- pos.x = 100.0f/640.0f;
- pos.y = 70.0f/480.0f;
- ddim.x = 100.0f/640.0f;
- ddim.y = 32.0f/480.0f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_POK);
- pb->SetState(STATE_SHADOW);
-
- pos.x = 210.0f/640.0f;
- pos.y = 70.0f/480.0f;
- ddim.x =100.0f/640.0f;
- ddim.y = 32.0f/480.0f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PCANCEL);
- pb->SetState(STATE_SHADOW);
-
- pos.x = 340.0f/640.0f;
- pos.y = 70.0f/480.0f;
- ddim.x =194.0f/640.0f;
- ddim.y = 32.0f/480.0f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PDEF);
- pb->SetState(STATE_SHADOW);
-
- m_persoCopy = m_perso;
- m_persoTab = 0;
- m_persoAngle = -0.6f;
- UpdatePerso();
- m_main->ScenePerso();
- CameraPerso();
- }
-
- if ( m_phase == PHASE_TRAINER ||
- m_phase == PHASE_DEFI ||
- m_phase == PHASE_MISSION ||
- m_phase == PHASE_FREE ||
- m_phase == PHASE_TEEN ||
- m_phase == PHASE_USER ||
- m_phase == PHASE_PROTO )
- {
- if ( m_phase == PHASE_TRAINER ) m_index = 0;
- if ( m_phase == PHASE_DEFI ) m_index = 1;
- if ( m_phase == PHASE_MISSION ) m_index = 2;
- if ( m_phase == PHASE_FREE ) m_index = 3;
- if ( m_phase == PHASE_USER ) m_index = 4;
- if ( m_phase == PHASE_PROTO ) m_index = 5;
- if ( m_phase == PHASE_TEEN ) m_index = 6;
-
- if ( m_phase == PHASE_FREE )
- {
- strcpy(m_sceneName, "scene");
- ReadGamerInfo();
- m_accessChap = RetChapPassed();
- }
-
- if ( m_phase == PHASE_TRAINER ) strcpy(m_sceneName, "train");
- if ( m_phase == PHASE_DEFI ) strcpy(m_sceneName, "defi" );
- if ( m_phase == PHASE_MISSION ) strcpy(m_sceneName, "scene");
- if ( m_phase == PHASE_FREE ) strcpy(m_sceneName, "free");
- if ( m_phase == PHASE_TEEN ) strcpy(m_sceneName, "teen");
- if ( m_phase == PHASE_USER ) strcpy(m_sceneName, "user");
- if ( m_phase == PHASE_PROTO ) strcpy(m_sceneName, "proto");
-
- ReadGamerInfo();
-
- pos.x = 0.10f;
- pos.y = 0.10f;
- ddim.x = 0.80f;
- ddim.y = 0.80f;
- pw = m_interface->CreateWindows(pos, ddim, 12, EVENT_WINDOW5);
- pw->SetClosable(true);
- if ( m_phase == PHASE_TRAINER ) res = RT_TITLE_TRAINER;
- if ( m_phase == PHASE_DEFI ) res = RT_TITLE_DEFI;
- if ( m_phase == PHASE_MISSION ) res = RT_TITLE_MISSION;
- if ( m_phase == PHASE_FREE ) res = RT_TITLE_FREE;
- if ( m_phase == PHASE_TEEN ) res = RT_TITLE_TEEN;
- if ( m_phase == PHASE_USER ) res = RT_TITLE_USER;
- if ( m_phase == PHASE_PROTO ) res = RT_TITLE_PROTO;
- GetResource(RES_TEXT, res, name);
- pw->SetName(name);
-
-#if _NEWLOOK
- pos.x = 100.0f/640.0f;
- pos.y = 226.0f/480.0f;
- ddim.x = 216.0f/640.0f;
- ddim.y = 160.0f/480.0f;
- pg = pw->CreateGroup(pos, ddim, 23, EVENT_LABEL1); // blue
- pg->SetState(STATE_SHADOW);
- pos.x = 322.0f/640.0f;
- pg = pw->CreateGroup(pos, ddim, 24, EVENT_LABEL1); // cyan
- pg->SetState(STATE_SHADOW);
-
- pos.x = 100.0f/640.0f;
- pos.y = 122.0f/480.0f;
- ddim.x = 438.0f/640.0f;
- ddim.y = 98.0f/480.0f;
- pg = pw->CreateGroup(pos, ddim, 25, EVENT_LABEL1); // green
- pg->SetState(STATE_SHADOW);
- pos.y = 66.0f/480.0f;
- ddim.y = 42.0f/480.0f;
- pg = pw->CreateGroup(pos, ddim, 26, EVENT_LABEL1); // violet
- pg->SetState(STATE_SHADOW);
-#endif
-
- pos.x = 0.10f;
- pos.y = 0.40f;
- ddim.x = 0.50f;
- ddim.y = 0.50f;
- pw->CreateGroup(pos, ddim, 5, EVENT_INTERFACE_GLINTl); // orange corner
- pos.x = 0.40f;
- pos.y = 0.10f;
- ddim.x = 0.50f;
- ddim.y = 0.50f;
- pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner
-
- // Displays a list of chapters:
- pos.x = ox+sx*3;
- pos.y = oy+sy*10.5f;
- ddim.x = dim.x*7.5f;
- ddim.y = dim.y*0.6f;
- if ( m_phase == PHASE_TRAINER ) res = RT_PLAY_CHAPt;
- if ( m_phase == PHASE_DEFI ) res = RT_PLAY_CHAPd;
- if ( m_phase == PHASE_MISSION ) res = RT_PLAY_CHAPm;
- if ( m_phase == PHASE_FREE ) res = RT_PLAY_CHAPf;
- if ( m_phase == PHASE_TEEN ) res = RT_PLAY_CHAPte;
- if ( m_phase == PHASE_USER ) res = RT_PLAY_CHAPu;
- if ( m_phase == PHASE_PROTO ) res = RT_PLAY_CHAPp;
- GetResource(RES_TEXT, res, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL11, name);
- pl->SetJustif(1);
-
- pos.y = oy+sy*6.7f;
- ddim.y = dim.y*4.5f;
- ddim.x = dim.x*6.5f;
- pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_CHAP);
- pli->SetState(STATE_SHADOW);
- UpdateSceneChap(m_chap[m_index]);
- if ( m_phase != PHASE_USER ) pli->SetState(STATE_EXTEND);
-
- // Displays a list of missions:
- pos.x = ox+sx*9.5f;
- pos.y = oy+sy*10.5f;
- ddim.x = dim.x*7.5f;
- ddim.y = dim.y*0.6f;
- if ( m_phase == PHASE_TRAINER ) res = RT_PLAY_LISTt;
- if ( m_phase == PHASE_DEFI ) res = RT_PLAY_LISTd;
- if ( m_phase == PHASE_MISSION ) res = RT_PLAY_LISTm;
- if ( m_phase == PHASE_FREE ) res = RT_PLAY_LISTf;
- if ( m_phase == PHASE_TEEN ) res = RT_PLAY_LISTk;
- if ( m_phase == PHASE_USER ) res = RT_PLAY_LISTu;
- if ( m_phase == PHASE_PROTO ) res = RT_PLAY_LISTp;
- GetResource(RES_TEXT, res, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL12, name);
- pl->SetJustif(1);
-
- pos.y = oy+sy*6.7f;
- ddim.y = dim.y*4.5f;
- ddim.x = dim.x*6.5f;
- pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_LIST);
- pli->SetState(STATE_SHADOW);
- UpdateSceneList(m_chap[m_index], m_sel[m_index]);
- if ( m_phase != PHASE_USER ) pli->SetState(STATE_EXTEND);
- pos = pli->RetPos();
- ddim = pli->RetDim();
-
- // Displays the summary:
- pos.x = ox+sx*3;
- pos.y = oy+sy*5.4f;
- ddim.x = dim.x*6.5f;
- ddim.y = dim.y*0.6f;
- GetResource(RES_TEXT, RT_PLAY_RESUME, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL13, name);
- pl->SetJustif(1);
-
- pos.x = ox+sx*3;
- pos.y = oy+sy*3.6f;
- ddim.x = dim.x*13.4f;
- ddim.y = dim.y*1.9f;
- pe = pw->CreateEdit(pos, ddim, 0, EVENT_INTERFACE_RESUME);
- pe->SetState(STATE_SHADOW);
- pe->SetMaxChar(500);
- pe->SetEditCap(false); // just to see
- pe->SetHiliteCap(false);
-
- // Button displays the "soluce":
- if ( m_phase != PHASE_TRAINER &&
- m_phase != PHASE_FREE &&
- m_phase != PHASE_TEEN )
- {
- pos.x = ox+sx*9.5f;
- pos.y = oy+sy*5.8f;
- ddim.x = dim.x*6.5f;
- ddim.y = dim.y*0.5f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_SOLUCE);
- pc->SetState(STATE_SHADOW);
- pc->ClearState(STATE_CHECK);
- }
- m_bSceneSoluce = false;
-
- UpdateSceneResume((m_chap[m_index]+1)*100+(m_sel[m_index]+1));
-
- if ( m_phase == PHASE_MISSION ||
- m_phase == PHASE_FREE ||
- m_phase == PHASE_USER )
- {
- pos.x = ox+sx*9.5f;
- pos.y = oy+sy*2;
- ddim.x = dim.x*3.7f;
- ddim.y = dim.y*1;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PLAY);
- pb->SetState(STATE_SHADOW);
- if ( m_maxList == 0 )
- {
- pb->ClearState(STATE_ENABLE);
- }
-
- pos.x += dim.x*4.0f;
- ddim.x = dim.x*2.5f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_READ);
- pb->SetState(STATE_SHADOW);
- if ( !IsIOReadScene() ) // no file to read?
- {
- pb->ClearState(STATE_ENABLE);
- }
- }
- else
- {
- pos.x = ox+sx*9.5f;
- pos.y = oy+sy*2;
- ddim.x = dim.x*6.5f;
- ddim.y = dim.y*1;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PLAY);
- pb->SetState(STATE_SHADOW);
- if ( m_maxList == 0 )
- {
- pb->ClearState(STATE_ENABLE);
- }
- }
-
- pos.x = ox+sx*3;
- ddim.x = dim.x*4;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_BACK);
- pb->SetState(STATE_SHADOW);
-
- m_engine->SetBackground("inter01.tga", 0,0, 0,0, true, true);
- m_engine->SetBackForce(true);
- }
-
- if ( m_phase == PHASE_SETUPd ||
- m_phase == PHASE_SETUPg ||
- m_phase == PHASE_SETUPp ||
- m_phase == PHASE_SETUPc ||
- m_phase == PHASE_SETUPs ||
- m_phase == PHASE_SETUPds ||
- m_phase == PHASE_SETUPgs ||
- m_phase == PHASE_SETUPps ||
- m_phase == PHASE_SETUPcs ||
- m_phase == PHASE_SETUPss )
- {
- if ( m_phase == PHASE_SETUPds )
- {
- m_phaseSetup = PHASE_SETUPd;
- m_bSimulSetup = true;
- }
- else if ( m_phase == PHASE_SETUPgs )
- {
- m_phaseSetup = PHASE_SETUPg;
- m_bSimulSetup = true;
- }
- else if ( m_phase == PHASE_SETUPps )
- {
- m_phaseSetup = PHASE_SETUPp;
- m_bSimulSetup = true;
- }
- else if ( m_phase == PHASE_SETUPcs )
- {
- m_phaseSetup = PHASE_SETUPc;
- m_bSimulSetup = true;
- }
- else if ( m_phase == PHASE_SETUPss )
- {
- m_phaseSetup = PHASE_SETUPs;
- m_bSimulSetup = true;
- }
- else
- {
- m_phaseSetup = m_phase;
- m_bSimulSetup = false;
- }
-
- pos.x = 0.10f;
- pos.y = 0.10f;
- ddim.x = 0.80f;
- ddim.y = 0.80f;
- pw = m_interface->CreateWindows(pos, ddim, 12, EVENT_WINDOW5);
- pw->SetClosable(true);
- GetResource(RES_TEXT, RT_TITLE_SETUP, name);
- pw->SetName(name);
-
- pos.x = 0.70f;
- pos.y = 0.10f;
- ddim.x = 0.20f;
- ddim.y = 0.20f;
- pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner
-
- pos.x = 0.10f;
- ddim.x = 0.80f;
- pos.y = 0.76f;
- ddim.y = 0.05f;
- pw->CreateGroup(pos, ddim, 3, EVENT_NULL); // transparent -> gray
-
-#if _NEWLOOK
- if ( m_phase == PHASE_SETUPd || // setup/display ?
- m_phase == PHASE_SETUPds )
- {
- pos.x = 100.0f/640.0f;
- pos.y = 130.0f/480.0f;
- ddim.x = 216.0f/640.0f;
- ddim.y = 212.0f/480.0f;
- pg = pw->CreateGroup(pos, ddim, 23, EVENT_LABEL1); // blue
- pg->SetState(STATE_SHADOW);
- pos.x = 324.0f/640.0f;
- pg = pw->CreateGroup(pos, ddim, 24, EVENT_LABEL1); // cyan
- pg->SetState(STATE_SHADOW);
- }
- if ( m_phase == PHASE_SETUPg || // setup/graphic ?
- m_phase == PHASE_SETUPgs )
- {
- pos.x = 100.0f/640.0f;
- pos.y = 130.0f/480.0f;
- ddim.x = 174.0f/640.0f;
- ddim.y = 212.0f/480.0f;
- pg = pw->CreateGroup(pos, ddim, 23, EVENT_LABEL1); // blue
- pg->SetState(STATE_SHADOW);
- pos.x = 282.0f/640.0f;
- ddim.x = 258.0f/640.0f;
- pg = pw->CreateGroup(pos, ddim, 24, EVENT_LABEL1); // cyan
- pg->SetState(STATE_SHADOW);
- }
- if ( m_phase == PHASE_SETUPp || // setup/game ?
- m_phase == PHASE_SETUPps )
- {
- pos.x = 100.0f/640.0f;
- pos.y = 130.0f/480.0f;
- ddim.x = 226.0f/640.0f;
- ddim.y = 212.0f/480.0f;
- pg = pw->CreateGroup(pos, ddim, 23, EVENT_LABEL1); // blue
- pg->SetState(STATE_SHADOW);
- pos.x = 334.0f/640.0f;
- ddim.x = 206.0f/640.0f;
- pg = pw->CreateGroup(pos, ddim, 24, EVENT_LABEL1); // cyan
- pg->SetState(STATE_SHADOW);
- }
- if ( m_phase == PHASE_SETUPc || // setup/command ?
- m_phase == PHASE_SETUPcs )
- {
- pos.x = 100.0f/640.0f;
- pos.y = 125.0f/480.0f;
- ddim.x = 440.0f/640.0f;
- ddim.y = 222.0f/480.0f;
- pg = pw->CreateGroup(pos, ddim, 23, EVENT_LABEL1); // blue
- pg->SetState(STATE_SHADOW);
- }
- if ( m_phase == PHASE_SETUPs || // setup/sound ?
- m_phase == PHASE_SETUPss )
- {
- pos.x = 100.0f/640.0f;
- pos.y = 130.0f/480.0f;
- ddim.x = 216.0f/640.0f;
- ddim.y = 212.0f/480.0f;
- pg = pw->CreateGroup(pos, ddim, 23, EVENT_LABEL1); // blue
- pg->SetState(STATE_SHADOW);
- pos.x = 324.0f/640.0f;
- pg = pw->CreateGroup(pos, ddim, 24, EVENT_LABEL1); // cyan
- pg->SetState(STATE_SHADOW);
- }
-
- pos.x = 100.0f/640.0f;
- pos.y = 66.0f/480.0f;
- ddim.x = 440.0f/640.0f;
- ddim.y = 42.0f/480.0f;
- pg = pw->CreateGroup(pos, ddim, 26, EVENT_LABEL1); // violet
- pg->SetState(STATE_SHADOW);
-#endif
-
- ddim.x = 0.78f/5-0.01f;
- ddim.y = 0.06f;
- pos.x = 0.115f;
- pos.y = 0.76f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_SETUPd);
- pb->SetState(STATE_SHADOW);
- pb->SetState(STATE_CARD);
- pb->SetState(STATE_CHECK, (m_phase == PHASE_SETUPd || m_phase == PHASE_SETUPds));
-
- pos.x += ddim.x+0.01f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_SETUPg);
- pb->SetState(STATE_SHADOW);
- pb->SetState(STATE_CARD);
- pb->SetState(STATE_CHECK, (m_phase == PHASE_SETUPg || m_phase == PHASE_SETUPgs));
-
- pos.x += ddim.x+0.01f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_SETUPp);
- pb->SetState(STATE_SHADOW);
- pb->SetState(STATE_CARD);
- pb->SetState(STATE_CHECK, (m_phase == PHASE_SETUPp || m_phase == PHASE_SETUPps));
-
- pos.x += ddim.x+0.01f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_SETUPc);
- pb->SetState(STATE_SHADOW);
- pb->SetState(STATE_CARD);
- pb->SetState(STATE_CHECK, (m_phase == PHASE_SETUPc || m_phase == PHASE_SETUPcs));
-
- pos.x += ddim.x+0.01f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_SETUPs);
- pb->SetState(STATE_SHADOW);
- pb->SetState(STATE_CARD);
- pb->SetState(STATE_CHECK, (m_phase == PHASE_SETUPs || m_phase == PHASE_SETUPss));
-
- pos.x = 0.10f;
- ddim.x = 0.80f;
- pos.y = 0.34f;
- ddim.y = 0.42f;
- pw->CreateGroup(pos, ddim, 2, EVENT_INTERFACE_GLINTu); // orange -> transparent
- pos.x = 0.10f+(6.0f/640.0f);
- ddim.x = 0.80f-(11.0f/640.0f);
- pos.y = 0.74f;
- ddim.y = 0.02f;
- pw->CreateGroup(pos, ddim, 1, EVENT_INTERFACE_GLINTb); // orange bar
-
- ddim.x = dim.x*4;
- ddim.y = dim.y*1;
- pos.x = ox+sx*3;
- pos.y = oy+sy*2;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_BACK);
- pb->SetState(STATE_SHADOW);
-
- if ( !m_bSimulSetup )
- {
- m_engine->SetBackground("inter01.tga", 0,0, 0,0, true, true);
- m_engine->SetBackForce(true);
- }
- }
-
- if ( m_phase == PHASE_SETUPd || // setup/display ?
- m_phase == PHASE_SETUPds )
- {
- pos.x = ox+sx*3;
- pos.y = oy+sy*9;
- ddim.x = dim.x*6;
- ddim.y = dim.y*1;
- GetResource(RES_TEXT, RT_SETUP_DEVICE, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, name);
- pl->SetJustif(1);
-
- pos.x = ox+sx*3;
- pos.y = oy+sy*5.2f;
- ddim.x = dim.x*6;
- ddim.y = dim.y*4.5f;
- pli = pw->CreateList(pos, ddim, 0, EVENT_LIST1);
- pli->SetState(STATE_SHADOW);
- UpdateDisplayDevice();
-
- pos.x = ox+sx*10;
- pos.y = oy+sy*9;
- ddim.x = dim.x*6;
- ddim.y = dim.y*1;
- GetResource(RES_TEXT, RT_SETUP_MODE, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL2, name);
- pl->SetJustif(1);
-
- m_setupFull = m_engine->RetFullScreen();
- pos.x = ox+sx*10;
- pos.y = oy+sy*5.2f;
- ddim.x = dim.x*6;
- ddim.y = dim.y*4.5f;
- pli = pw->CreateList(pos, ddim, 0, EVENT_LIST2);
- pli->SetState(STATE_SHADOW);
- UpdateDisplayMode();
- pli->SetState(STATE_ENABLE, m_setupFull);
-
- ddim.x = dim.x*4;
- ddim.y = dim.y*0.5f;
- pos.x = ox+sx*3;
- pos.y = oy+sy*4.1f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_FULL);
- pc->SetState(STATE_SHADOW);
- pc->SetState(STATE_CHECK, m_setupFull);
-
- ddim.x = dim.x*6;
- ddim.y = dim.y*1;
- pos.x = ox+sx*10;
- pos.y = oy+sy*2;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_APPLY);
- pb->SetState(STATE_SHADOW);
- UpdateApply();
- }
-
- if ( m_phase == PHASE_SETUPg || // setup/graphic ?
- m_phase == PHASE_SETUPgs )
- {
- ddim.x = dim.x*6;
- ddim.y = dim.y*0.5f;
- pos.x = ox+sx*3;
- pos.y = 0.65f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_SHADOW);
- pc->SetState(STATE_SHADOW);
- pos.y -= 0.048f;
- if ( !m_bSimulSetup )
- {
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_GROUND);
- pc->SetState(STATE_SHADOW);
- if ( m_engine->IsVideo8MB() ) pc->ClearState(STATE_ENABLE);
- }
- pos.y -= 0.048f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_DIRTY);
- pc->SetState(STATE_SHADOW);
- pos.y -= 0.048f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_SKY);
- pc->SetState(STATE_SHADOW);
- if ( m_engine->IsVideo8MB() ) pc->ClearState(STATE_ENABLE);
- pos.y -= 0.048f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_LENS);
- pc->SetState(STATE_SHADOW);
- pos.y -= 0.048f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_PLANET);
- pc->SetState(STATE_SHADOW);
- pos.y -= 0.048f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_FOG);
- pc->SetState(STATE_SHADOW);
- pos.y -= 0.048f;
- if ( !m_bSimulSetup )
- {
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_LIGHT);
- pc->SetState(STATE_SHADOW);
- }
-
- pos.x = ox+sx*8.5f;
- pos.y = 0.65f;
- ddim.x = dim.x*2.2f;
- ddim.y = 18.0f/480.0f;
- pv = pw->CreateEditValue(pos, ddim, 0, EVENT_INTERFACE_PARTI);
- pv->SetState(STATE_SHADOW);
- pv->SetMinValue(0.0f);
- pv->SetMaxValue(2.0f);
- pos.x += 0.13f;
- pos.y -= 0.015f;
- ddim.x = 0.40f;
- GetResource(RES_EVENT, EVENT_INTERFACE_PARTI, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL10, name);
- pl->SetJustif(1);
-
- pos.x = ox+sx*8.5f;
- pos.y = 0.59f;
- ddim.x = dim.x*2.2f;
- ddim.y = 18.0f/480.0f;
- pv = pw->CreateEditValue(pos, ddim, 0, EVENT_INTERFACE_CLIP);
- pv->SetState(STATE_SHADOW);
- pv->SetMinValue(0.5f);
- pv->SetMaxValue(2.0f);
- pos.x += 0.13f;
- pos.y -= 0.015f;
- ddim.x = 0.40f;
- GetResource(RES_EVENT, EVENT_INTERFACE_CLIP, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL11, name);
- pl->SetJustif(1);
-
- pos.x = ox+sx*8.5f;
- pos.y = 0.53f;
- ddim.x = dim.x*2.2f;
- ddim.y = 18.0f/480.0f;
- pv = pw->CreateEditValue(pos, ddim, 0, EVENT_INTERFACE_DETAIL);
- pv->SetState(STATE_SHADOW);
- pv->SetMinValue(0.0f);
- pv->SetMaxValue(2.0f);
- pos.x += 0.13f;
- pos.y -= 0.015f;
- ddim.x = 0.40f;
- GetResource(RES_EVENT, EVENT_INTERFACE_DETAIL, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL12, name);
- pl->SetJustif(1);
-
- if ( !m_bSimulSetup )
- {
- pos.x = ox+sx*8.5f;
- pos.y = 0.47f;
- ddim.x = dim.x*2.2f;
- ddim.y = 18.0f/480.0f;
- pv = pw->CreateEditValue(pos, ddim, 0, EVENT_INTERFACE_GADGET);
- pv->SetState(STATE_SHADOW);
- pv->SetMinValue(0.0f);
- pv->SetMaxValue(1.0f);
- pos.x += 0.13f;
- pos.y -= 0.015f;
- ddim.x = 0.40f;
- GetResource(RES_EVENT, EVENT_INTERFACE_GADGET, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL13, name);
- pl->SetJustif(1);
- }
-
-#if 0
- if ( !m_bSimulSetup )
- {
- pos.x = ox+sx*8.5f;
- pos.y = 0.41f;
- ddim.x = dim.x*2.2f;
- ddim.y = 18.0f/480.0f;
- pv = pw->CreateEditValue(pos, ddim, 0, EVENT_INTERFACE_TEXTURE);
- pv->SetState(STATE_SHADOW);
- pv->SetType(EVT_INT);
- pv->SetMinValue(0.0f);
- pv->SetMaxValue(2.0f);
- pv->SetStepValue(1.0f);
- pos.x += 0.13f;
- pos.y -= 0.015f;
- ddim.x = 0.40f;
- GetResource(RES_EVENT, EVENT_INTERFACE_TEXTURE, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL14, name);
- pl->SetJustif(1);
- }
-#endif
-
- ddim.x = dim.x*2;
- ddim.y = dim.y*1;
- pos.x = ox+sx*10;
- pos.y = oy+sy*2;
-#if _POLISH
- ddim.x += 20.0f/640.0f;
- pos.x -= 20.0f/640.0f*3.0f;
-#endif
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_MIN);
- pb->SetState(STATE_SHADOW);
- pos.x += ddim.x;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_NORM);
- pb->SetState(STATE_SHADOW);
- pos.x += ddim.x;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_MAX);
- pb->SetState(STATE_SHADOW);
-
- UpdateSetupButtons();
- }
-
- if ( m_phase == PHASE_SETUPp || // setup/game ?
- m_phase == PHASE_SETUPps )
- {
- ddim.x = dim.x*6;
- ddim.y = dim.y*0.5f;
- pos.x = ox+sx*3;
- pos.y = 0.65f;
-//? pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_TOTO);
-//? pc->SetState(STATE_SHADOW);
-//? pos.y -= 0.048f;
-#if _SCHOOL
- #if _EDU
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_SOLUCE4);
- pc->SetState(STATE_SHADOW);
- pos.y -= 0.048f;
- #endif
-#else
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_MOVIES);
- pc->SetState(STATE_SHADOW);
- pos.y -= 0.048f;
-#endif
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_SCROLL);
- pc->SetState(STATE_SHADOW);
- pos.y -= 0.048f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_INVERTX);
- pc->SetState(STATE_SHADOW);
- pos.y -= 0.048f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_INVERTY);
- pc->SetState(STATE_SHADOW);
- pos.y -= 0.048f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_EFFECT);
- pc->SetState(STATE_SHADOW);
-//? pos.y -= 0.048f;
-//? pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_NICERST);
-//? pc->SetState(STATE_SHADOW);
-//? pos.y -= 0.048f;
-//? pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_HIMSELF);
-//? pc->SetState(STATE_SHADOW);
-
- ddim.x = dim.x*6;
- ddim.y = dim.y*0.5f;
- pos.x = ox+sx*10;
- pos.y = 0.65f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_TOOLTIP);
- pc->SetState(STATE_SHADOW);
- pos.y -= 0.048f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_GLINT);
- pc->SetState(STATE_SHADOW);
- pos.y -= 0.048f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_RAIN);
- pc->SetState(STATE_SHADOW);
- pos.y -= 0.048f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_MOUSE);
- pc->SetState(STATE_SHADOW);
- pos.y -= 0.048f;
- pos.y -= 0.048f;
- if ( !m_bSimulSetup )
- {
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_EDITMODE);
- pc->SetState(STATE_SHADOW);
- }
- pos.y -= 0.048f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_EDITVALUE);
- pc->SetState(STATE_SHADOW);
-
- UpdateSetupButtons();
- }
-
- if ( m_phase == PHASE_SETUPc || // setup/commands ?
- m_phase == PHASE_SETUPcs )
- {
- pos.x = ox+sx*3;
- pos.y = 320.0f/480.0f;
- ddim.x = dim.x*15.0f;
- ddim.y = 18.0f/480.0f;
- GetResource(RES_TEXT, RT_SETUP_KEY1, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_INTERFACE_KINFO1, name);
- pl->SetJustif(1);
-
- pos.x = ox+sx*3;
- pos.y = 302.0f/480.0f;
- ddim.x = dim.x*15.0f;
- ddim.y = 18.0f/480.0f;
- GetResource(RES_TEXT, RT_SETUP_KEY2, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_INTERFACE_KINFO2, name);
- pl->SetJustif(1);
-
- ddim.x = 428.0f/640.0f;
- ddim.y = 128.0f/480.0f;
- pos.x = 105.0f/640.0f;
- pos.y = 164.0f/480.0f;
- pg = pw->CreateGroup(pos, ddim, 0, EVENT_INTERFACE_KGROUP);
- pg->ClearState(STATE_ENABLE);
- pg->SetState(STATE_DEAD);
- pg->SetState(STATE_SHADOW);
-
- ddim.x = 18.0f/640.0f;
- ddim.y = (20.0f/480.0f)*KEY_VISIBLE;
- pos.x = 510.0f/640.0f;
- pos.y = 168.0f/480.0f;
- ps = pw->CreateScroll(pos, ddim, -1, EVENT_INTERFACE_KSCROLL);
- ps->SetVisibleRatio((float)KEY_VISIBLE/KEY_TOTAL);
- ps->SetArrowStep(1.0f/((float)KEY_TOTAL-KEY_VISIBLE));
- UpdateKey();
-
- ddim.x = dim.x*6;
- ddim.y = dim.y*0.5f;
- pos.x = ox+sx*3;
- pos.y = 130.0f/480.0f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_JOYSTICK);
- pc->SetState(STATE_SHADOW);
-
- ddim.x = dim.x*6;
- ddim.y = dim.y*1;
- pos.x = ox+sx*10;
- pos.y = oy+sy*2;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_KDEF);
- pb->SetState(STATE_SHADOW);
-
- UpdateSetupButtons();
- }
-
- if ( m_phase == PHASE_SETUPs || // setup/sound ?
- m_phase == PHASE_SETUPss )
- {
- pos.x = ox+sx*3;
- pos.y = 0.55f;
- ddim.x = dim.x*4.0f;
- ddim.y = 18.0f/480.0f;
- psl = pw->CreateSlider(pos, ddim, 0, EVENT_INTERFACE_VOLSOUND);
- psl->SetState(STATE_SHADOW);
- psl->SetLimit(0.0f, MAXVOLUME);
- psl->SetArrowStep(1.0f);
- pos.y += ddim.y;
- GetResource(RES_EVENT, EVENT_INTERFACE_VOLSOUND, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, name);
- pl->SetJustif(1);
-
-#if (_FULL | _NET) & _SOUNDTRACKS
- pos.x = ox+sx*3;
- pos.y = 0.40f;
- ddim.x = dim.x*4.0f;
- ddim.y = 18.0f/480.0f;
- psl = pw->CreateSlider(pos, ddim, 0, EVENT_INTERFACE_VOLMUSIC);
- psl->SetState(STATE_SHADOW);
- psl->SetLimit(0.0f, MAXVOLUME);
- psl->SetArrowStep(1.0f);
- pos.y += ddim.y;
- GetResource(RES_EVENT, EVENT_INTERFACE_VOLMUSIC, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL2, name);
- pl->SetJustif(1);
-#endif
-
- ddim.x = dim.x*6;
- ddim.y = dim.y*0.5f;
- pos.x = ox+sx*10;
- pos.y = 0.55f;
- pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_SOUND3D);
- pc->SetState(STATE_SHADOW);
-
- ddim.x = dim.x*3;
- ddim.y = dim.y*1;
- pos.x = ox+sx*10;
- pos.y = oy+sy*2;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_SILENT);
- pb->SetState(STATE_SHADOW);
- pos.x += ddim.x;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_NOISY);
- pb->SetState(STATE_SHADOW);
-
- UpdateSetupButtons();
- }
-
- if ( m_phase == PHASE_WRITE ||
- m_phase == PHASE_WRITEs )
- {
- pos.x = 0.10f;
- pos.y = 0.10f;
- ddim.x = 0.80f;
- ddim.y = 0.80f;
- pw = m_interface->CreateWindows(pos, ddim, 13, EVENT_WINDOW5);
- pw->SetClosable(true);
- GetResource(RES_TEXT, RT_TITLE_WRITE, name);
- pw->SetName(name);
-
- pos.x = 0.10f;
- pos.y = 0.40f;
- ddim.x = 0.50f;
- ddim.y = 0.50f;
- pw->CreateGroup(pos, ddim, 5, EVENT_INTERFACE_GLINTl); // orange corner
- pos.x = 0.40f;
- pos.y = 0.10f;
- ddim.x = 0.50f;
- ddim.y = 0.50f;
- pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner
-
-#if _NEWLOOK
- pos.x = 100.0f/640.0f;
- pos.y = 66.0f/480.0f;
- ddim.x = 438.0f/640.0f;
- ddim.y = 42.0f/480.0f;
- pg = pw->CreateGroup(pos, ddim, 26, EVENT_LABEL1); // violet
- pg->SetState(STATE_SHADOW);
-#endif
-
- pos.x = 290.0f/640.0f;
- ddim.x = 245.0f/640.0f;
-
- pos.y = 146.0f/480.0f;
- ddim.y = 18.0f/480.0f;
- GetResource(RES_EVENT, EVENT_INTERFACE_IOLABEL, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_INTERFACE_IOLABEL, name);
- pl->SetJustif(1);
-
- pos.y = 130.0f/480.0f;
- ddim.y = 18.0f/480.0f;
- pe = pw->CreateEdit(pos, ddim, 0, EVENT_INTERFACE_IONAME);
- pe->SetState(STATE_SHADOW);
- pe->SetFontType(FONT_COLOBOT);
- pe->SetMaxChar(35);
- IOReadName();
-
- pos.y = 190.0f/480.0f;
- ddim.y = 190.0f/480.0f;
- pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_IOLIST);
- pli->SetState(STATE_SHADOW);
-
- pos.y = oy+sy*2;
- ddim.y = dim.y*1;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_IOWRITE);
- pb->SetState(STATE_SHADOW);
-
- pos.x = 105.0f/640.0f;
- pos.y = 190.0f/480.0f;
- ddim.x = 170.0f/640.0f;
- ddim.y = dim.y*1;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_IODELETE);
- pb->SetState(STATE_SHADOW);
-
- pos.x = 105.0f/640.0f;
- pos.y = 250.0f/480.0f;
- ddim.x = 170.0f/640.0f;
- ddim.y = 128.0f/480.0f;
- pi = pw->CreateImage(pos, ddim, 0, EVENT_INTERFACE_IOIMAGE);
- pi->SetState(STATE_SHADOW);
-
- ddim.x = dim.x*4;
- ddim.y = dim.y*1;
- pos.x = ox+sx*3;
- pos.y = oy+sy*2;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_BACK);
- pb->SetState(STATE_SHADOW);
-
- IOReadList();
- IOUpdateList();
- }
-
- if ( m_phase == PHASE_READ ||
- m_phase == PHASE_READs )
- {
- pos.x = 0.10f;
- pos.y = 0.10f;
- ddim.x = 0.80f;
- ddim.y = 0.80f;
- pw = m_interface->CreateWindows(pos, ddim, 14, EVENT_WINDOW5);
- pw->SetClosable(true);
- GetResource(RES_TEXT, RT_TITLE_READ, name);
- pw->SetName(name);
-
- pos.x = 0.10f;
- pos.y = 0.40f;
- ddim.x = 0.50f;
- ddim.y = 0.50f;
- pw->CreateGroup(pos, ddim, 5, EVENT_INTERFACE_GLINTl); // orange corner
- pos.x = 0.40f;
- pos.y = 0.10f;
- ddim.x = 0.50f;
- ddim.y = 0.50f;
- pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner
-
-#if _NEWLOOK
- pos.x = 100.0f/640.0f;
- pos.y = 66.0f/480.0f;
- ddim.x = 438.0f/640.0f;
- ddim.y = 42.0f/480.0f;
- pg = pw->CreateGroup(pos, ddim, 26, EVENT_LABEL1); // violet
- pg->SetState(STATE_SHADOW);
-#endif
-
- pos.x = 290.0f/640.0f;
- ddim.x = 245.0f/640.0f;
-
- pos.y = 160.0f/480.0f;
- ddim.y = 190.0f/480.0f;
- pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_IOLIST);
- pli->SetState(STATE_SHADOW);
-
- pos.y = oy+sy*2;
- ddim.y = dim.y*1;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_IOREAD);
- pb->SetState(STATE_SHADOW);
- if ( m_phase == PHASE_READs )
- {
- pb->SetState(STATE_WARNING);
- }
-
- pos.x = 105.0f/640.0f;
- pos.y = 160.0f/480.0f;
- ddim.x = 170.0f/640.0f;
- ddim.y = dim.y*1;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_IODELETE);
- pb->SetState(STATE_SHADOW);
-
- pos.x = 105.0f/640.0f;
- pos.y = 220.0f/480.0f;
- ddim.x = 170.0f/640.0f;
- ddim.y = 128.0f/480.0f;
- pi = pw->CreateImage(pos, ddim, 0, EVENT_INTERFACE_IOIMAGE);
- pi->SetState(STATE_SHADOW);
-
- ddim.x = dim.x*4;
- ddim.y = dim.y*1;
- pos.x = ox+sx*3;
- pos.y = oy+sy*2;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_BACK);
- pb->SetState(STATE_SHADOW);
-
- IOReadList();
- IOUpdateList();
-
- if ( m_phase == PHASE_READ )
- {
- m_engine->SetBackground("inter01.tga", 0,0, 0,0, true, true);
- m_engine->SetBackForce(true);
- }
- }
-
- if ( m_phase == PHASE_LOADING )
- {
- pos.x = 0.35f;
- pos.y = 0.10f;
- ddim.x = 0.30f;
- ddim.y = 0.80f;
-#if _TEEN
- pw = m_interface->CreateWindows(pos, ddim, 12, EVENT_WINDOW5);
-#else
- pw = m_interface->CreateWindows(pos, ddim, 10, EVENT_WINDOW5);
-#endif
- pw->SetName(" ");
-
- pos.x = 0.35f;
- pos.y = 0.60f;
- ddim.x = 0.30f;
- ddim.y = 0.30f;
- pw->CreateGroup(pos, ddim, 5, EVENT_INTERFACE_GLINTl); // orange corner
- pos.x = 0.35f;
- pos.y = 0.10f;
- ddim.x = 0.30f;
- ddim.y = 0.30f;
- pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner
-
- pos.x = 254.0f/640.0f;
- pos.y = 208.0f/480.0f;
- ddim.x = 132.0f/640.0f;
- ddim.y = 42.0f/480.0f;
- pg = pw->CreateGroup(pos, ddim, 22, EVENT_NULL);
- pg->SetState(STATE_SHADOW);
-
- pos.x = 220.0f/640.0f;
- pos.y = 210.0f/480.0f;
- ddim.x = 200.0f/640.0f;
- ddim.y = 20.0f/480.0f;
- GetResource(RES_TEXT, RT_DIALOG_LOADING, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, name);
- pl->SetFontSize(12.0f);
- pl->SetJustif(0);
-
- m_engine->SetBackground("inter01.tga", 0,0, 0,0, true, true);
- m_engine->SetBackForce(true);
-
- m_loadingCounter = 1; // enough time to display!
- }
-
- if ( m_phase == PHASE_WELCOME1 )
- {
- m_sound->StopMusic();
- m_sound->PlayMusic(11, false);
-
- pos.x = 0.0f;
- pos.y = 0.0f;
- ddim.x = 0.0f;
- ddim.y = 0.0f;
- pw = m_interface->CreateWindows(pos, ddim, -1, EVENT_WINDOW5);
-
- m_engine->SetOverColor(RetColor(1.0f), D3DSTATETCb);
- m_engine->SetOverFront(true);
-
-#if _FRENCH
- m_engine->SetBackground("alsyd.tga", 0,0, 0,0, true, false);
-#endif
-#if _POLISH
- m_engine->SetBackground("manta.tga", 0,0, 0,0, true, false);
-#endif
-#if _WG
- m_engine->SetBackground("wg.tga", 0,0, 0,0, true, false);
-#endif
- m_engine->SetBackForce(true);
- }
- if ( m_phase == PHASE_WELCOME2 )
- {
-#if _ENGLISH
- m_sound->StopMusic();
- m_sound->PlayMusic(11, false);
-#endif
-#if _POLISH
- m_sound->StopMusic();
- m_sound->PlayMusic(11, false);
-#endif
-
- pos.x = 0.0f;
- pos.y = 0.0f;
- ddim.x = 0.0f;
- ddim.y = 0.0f;
- pw = m_interface->CreateWindows(pos, ddim, -1, EVENT_WINDOW5);
-
- m_engine->SetOverColor(RetColor(1.0f), D3DSTATETCb);
- m_engine->SetOverFront(true);
-
- m_engine->SetBackground("colobot.tga", 0,0, 0,0, true, false);
- m_engine->SetBackForce(true);
- }
- if ( m_phase == PHASE_WELCOME3 )
- {
- pos.x = 0.0f;
- pos.y = 0.0f;
- ddim.x = 0.0f;
- ddim.y = 0.0f;
- pw = m_interface->CreateWindows(pos, ddim, -1, EVENT_WINDOW5);
-
- m_engine->SetOverColor(RetColor(0.0f), D3DSTATETCw);
- m_engine->SetOverFront(true);
-
-#if _FRENCH
- m_engine->SetBackground("epsitecf.tga", 0,0, 0,0, true, false);
-#endif
-#if _ENGLISH
- m_engine->SetBackground("epsitece.tga", 0,0, 0,0, true, false);
-#endif
-#if _GERMAN | _WG
- m_engine->SetBackground("epsitecd.tga", 0,0, 0,0, true, false);
-#endif
-#if _POLISH
- m_engine->SetBackground("epsitecp.tga", 0,0, 0,0, true, false);
-#endif
- m_engine->SetBackForce(true);
- }
-
- if ( m_phase == PHASE_GENERIC )
- {
- pos.x = 0.0f;
- pos.y = 0.0f;
- ddim.x = 0.0f;
- ddim.y = 0.0f;
- pw = m_interface->CreateWindows(pos, ddim, -1, EVENT_WINDOW5);
-
-#if _FULL | _NET
- pos.x = 80.0f/640.0f;
- pos.y = 240.0f/480.0f;
- ddim.x = 490.0f/640.0f;
- ddim.y = 110.0f/480.0f;
- pe = pw->CreateEdit(pos, ddim, 0, EVENT_EDIT1);
- pe->SetGenericMode(true);
- pe->SetEditCap(false);
- pe->SetHiliteCap(false);
- pe->SetFontType(FONT_COURIER);
- pe->SetFontSize(8.0f);
- pe->ReadText("help\\authors.txt");
-
- pos.x = 80.0f/640.0f;
- pos.y = 140.0f/480.0f;
- ddim.x = 490.0f/640.0f;
- ddim.y = 100.0f/480.0f;
- pe = pw->CreateEdit(pos, ddim, 0, EVENT_EDIT2);
- pe->SetGenericMode(true);
- pe->SetEditCap(false);
- pe->SetHiliteCap(false);
- pe->SetFontType(FONT_COURIER);
- pe->SetFontSize(6.5f);
- pe->ReadText("help\\licences.txt");
-#endif
-#if _SCHOOL
-#if _CEEBOTDEMO
- pos.x = 80.0f/640.0f;
- pos.y = 210.0f/480.0f;
- ddim.x = 490.0f/640.0f;
- ddim.y = 150.0f/480.0f;
-#else
- pos.x = 80.0f/640.0f;
- pos.y = 200.0f/480.0f;
- ddim.x = 490.0f/640.0f;
- ddim.y = 150.0f/480.0f;
-#endif
- pe = pw->CreateEdit(pos, ddim, 0, EVENT_EDIT1);
- pe->SetGenericMode(true);
- pe->SetEditCap(false);
- pe->SetHiliteCap(false);
- pe->SetFontType(FONT_COURIER);
- pe->SetFontSize(8.0f);
- pe->ReadText("help\\authors.txt");
-#endif
-#if _DEMO
-//? pos.x = 80.0f/640.0f;
-//? pos.y = 240.0f/480.0f;
-//? ddim.x = 490.0f/640.0f;
-//? ddim.y = 110.0f/480.0f;
-//? pe = pw->CreateEdit(pos, ddim, 0, EVENT_EDIT1);
-//? pe->SetGenericMode(true);
-//? pe->SetEditCap(false);
-//? pe->SetHiliteCap(false);
-//? pe->SetFontType(FONT_COURIER);
-//? pe->SetFontSize(8.0f);
-//? pe->ReadText("help\\demo.txt");
-
-//? pos.x = 80.0f/640.0f;
-//? pos.y = 140.0f/480.0f;
-//? ddim.x = 490.0f/640.0f;
-//? ddim.y = 100.0f/480.0f;
-//? pe = pw->CreateEdit(pos, ddim, 0, EVENT_EDIT2);
-//? pe->SetGenericMode(true);
-//? pe->SetEditCap(false);
-//? pe->SetHiliteCap(false);
-//? pe->SetFontType(FONT_COURIER);
-//? pe->SetFontSize(8.0f);
-//? pe->ReadText("help\\authors.txt");
-#endif
-
-#if !_DEMO
- pos.x = 40.0f/640.0f;
- pos.y = 83.0f/480.0f;
- ddim.x = 246.0f/640.0f;
- ddim.y = 16.0f/480.0f;
- GetResource(RES_TEXT, RT_GENERIC_DEV1, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, name);
- pl->SetFontType(FONT_COURIER);
- pl->SetFontSize(8.0f);
-
- pos.y = 13.0f/480.0f;
- GetResource(RES_TEXT, RT_GENERIC_DEV2, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL2, name);
- pl->SetFontType(FONT_COURIER);
- pl->SetFontSize(8.0f);
-
- pos.x = 355.0f/640.0f;
- pos.y = 83.0f/480.0f;
- ddim.x = 246.0f/640.0f;
- ddim.y = 16.0f/480.0f;
- GetResource(RES_TEXT, RT_GENERIC_EDIT1, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL3, name);
- pl->SetFontType(FONT_COURIER);
- pl->SetFontSize(8.0f);
-
- pos.y = 13.0f/480.0f;
- GetResource(RES_TEXT, RT_GENERIC_EDIT2, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL4, name);
- pl->SetFontType(FONT_COURIER);
- pl->SetFontSize(8.0f);
-#endif
-
-#if _DEMO
- pos.x = 481.0f/640.0f;
- pos.y = 51.0f/480.0f;
- ddim.x = 30.0f/640.0f;
- ddim.y = 30.0f/480.0f;
- pb = pw->CreateButton(pos, ddim, 49, EVENT_INTERFACE_ABORT);
- pb->SetState(STATE_SHADOW);
-#else
- pos.x = 306.0f/640.0f;
- pos.y = 17.0f/480.0f;
- ddim.x = 30.0f/640.0f;
- ddim.y = 30.0f/480.0f;
- pb = pw->CreateButton(pos, ddim, 49, EVENT_INTERFACE_ABORT);
- pb->SetState(STATE_SHADOW);
-#endif
-
-#if _NEWLOOK
-#if _CEEBOTDEMO
-#if _TEEN
- m_engine->SetBackground("genedt.tga", 0,0, 0,0, true, true);
-#else
- m_engine->SetBackground("geneda.tga", 0,0, 0,0, true, true);
-#endif
-#else
- m_engine->SetBackground("genern.tga", 0,0, 0,0, true, true);
-#endif
-#else
-#if _FRENCH
-#if _DEMO
- m_engine->SetBackground("genedf.tga", 0,0, 0,0, true, true);
-#else
- m_engine->SetBackground("generf.tga", 0,0, 0,0, true, true);
-#endif
-#endif
-#if _ENGLISH
-#if _DEMO
- m_engine->SetBackground("genede.tga", 0,0, 0,0, true, true);
-#else
- m_engine->SetBackground("genere.tga", 0,0, 0,0, true, true);
-#endif
-#endif
-#if _GERMAN
-#if _DEMO
- m_engine->SetBackground("genedd.tga", 0,0, 0,0, true, true);
-#else
- m_engine->SetBackground("genere.tga", 0,0, 0,0, true, true);
-#endif
-#endif
-#if _WG
-#if _DEMO
- m_engine->SetBackground("genedd.tga", 0,0, 0,0, true, true);
-#else
- m_engine->SetBackground("generd.tga", 0,0, 0,0, true, true);
-#endif
-#endif
-#if _POLISH
-#if _DEMO
- m_engine->SetBackground("genedp.tga", 0,0, 0,0, true, true);
-#else
- m_engine->SetBackground("generp.tga", 0,0, 0,0, true, true);
-#endif
-#endif
-#endif
- m_engine->SetBackForce(true);
- }
-
- if ( m_phase == PHASE_INIT ||
- m_phase == PHASE_NAME ||
- m_phase == PHASE_TRAINER ||
- m_phase == PHASE_DEFI ||
- m_phase == PHASE_MISSION ||
- m_phase == PHASE_FREE ||
- m_phase == PHASE_TEEN ||
- m_phase == PHASE_USER ||
- m_phase == PHASE_PROTO ||
- m_phase == PHASE_SETUPd ||
- m_phase == PHASE_SETUPg ||
- m_phase == PHASE_SETUPp ||
- m_phase == PHASE_SETUPc ||
- m_phase == PHASE_SETUPs ||
- m_phase == PHASE_READ ||
- m_phase == PHASE_LOADING )
- {
-#if _SCHOOL
-#if _TEEN
- pos.x = 50.0f/640.0f;
- pos.y = 430.0f/480.0f;
- ddim.x = 200.0f/640.0f;
- ddim.y = 10.0f/480.0f;
-#else
- pos.x = 450.0f/640.0f;
- pos.y = 0.0f/480.0f;
- ddim.x = 170.0f/640.0f;
- ddim.y = 9.0f/480.0f;
-#endif
-#else
- pos.x = 540.0f/640.0f;
- pos.y = 9.0f/480.0f;
- ddim.x = 90.0f/640.0f;
- ddim.y = 10.0f/480.0f;
-#endif
- GetResource(RES_TEXT, RT_VERSION_ID, name);
- pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, name);
- pl->SetFontType(FONT_COURIER);
- pl->SetFontSize(9.0f);
- }
-
- m_engine->LoadAllTexture();
-}
-
-
-// Processing an event.
-// Returns false if the event has been processed completely.
-
-bool CMainDialog::EventProcess(const Event &event)
-{
- CWindow* pw;
- CList* pl;
- CButton* pb;
- CCheck* pc;
- Event newEvent;
- float welcomeLength;
-
- if ( event.event == EVENT_FRAME )
- {
- m_phaseTime += event.rTime;
-
-//? if ( m_phase == PHASE_WELCOME1 ) welcomeLength = WELCOME_LENGTH+2.0f;
-//? else welcomeLength = WELCOME_LENGTH;
- welcomeLength = WELCOME_LENGTH;
-
- if ( m_phase == PHASE_WELCOME1 ||
- m_phase == PHASE_WELCOME2 ||
- m_phase == PHASE_WELCOME3 )
- {
- float intensity;
- int mode = D3DSTATETCb;
-
- if ( m_phaseTime < 1.5f )
- {
- intensity = 1.0f-(m_phaseTime-0.5f);
- }
- else if ( m_phaseTime < welcomeLength-1.0f )
- {
- intensity = 0.0f;
- }
- else
- {
- intensity = m_phaseTime-(welcomeLength-1.0f);
- }
- if ( intensity < 0.0f ) intensity = 0.0f;
- if ( intensity > 1.0f ) intensity = 1.0f;
-
- if ( (m_phase == PHASE_WELCOME2 && m_phaseTime > welcomeLength/2.0f) ||
- m_phase == PHASE_WELCOME3 )
- {
- intensity = 1.0f-intensity;
- mode = D3DSTATETCw;
- }
-
- m_engine->SetOverColor(RetColor(intensity), mode);
- }
-
- if ( m_phase == PHASE_WELCOME1 && m_phaseTime >= welcomeLength )
- {
- ChangePhase(PHASE_WELCOME2);
- return true;
- }
- if ( m_phase == PHASE_WELCOME2 && m_phaseTime >= welcomeLength )
- {
- ChangePhase(PHASE_WELCOME3);
- return true;
- }
- if ( m_phase == PHASE_WELCOME3 && m_phaseTime >= welcomeLength )
- {
- ChangePhase(PHASE_NAME);
- return true;
- }
-
- if ( m_shotDelay > 0 && !m_bDialog ) // screenshot done?
- {
- m_shotDelay --;
- if ( m_shotDelay == 0 )
- {
- m_engine->WriteScreenShot(m_shotName, 320, 240);
-//? m_engine->WriteScreenShot(m_shotName, 160, 120);
- }
- }
-
- if ( m_phase == PHASE_LOADING )
- {
- if ( m_loadingCounter == 0 )
- {
- m_main->ChangePhase(PHASE_SIMUL);
- }
- m_loadingCounter --;
- return false;
- }
-
- m_glintTime += event.rTime;
- GlintMove(); // moves reflections
-
- FrameParticule(event.rTime);
-
- if ( m_bDialog ) // this dialogue?
- {
- FrameDialog(event.rTime);
- }
-
- return true;
- }
-
- if ( event.event == EVENT_MOUSEMOVE )
- {
- m_glintMouse = event.pos;
- NiceParticule(event.pos, event.keyState&KS_MLEFT);
- }
-
- if ( m_bDialog ) // this dialogue?
- {
- m_interface->EventProcess(event);
-
- if ( event.event == EVENT_DIALOG_OK ||
- (event.event == EVENT_KEYDOWN && event.param == VK_RETURN ) )
- {
- StopDialog();
- if ( m_phase == PHASE_NAME )
- {
- NameDelete();
- }
- if ( m_phase == PHASE_INIT )
- {
-//? m_event->MakeEvent(newEvent, EVENT_QUIT);
-//? m_event->AddEvent(newEvent);
- m_main->ChangePhase(PHASE_GENERIC);
- }
- if ( m_phase == PHASE_SIMUL )
- {
- if ( m_bDialogDelete )
- {
- m_main->DeleteObject();
- }
- else
- {
- m_main->ChangePhase(PHASE_TERM);
- }
- }
- }
- if ( event.event == EVENT_DIALOG_CANCEL ||
- (event.event == EVENT_KEYDOWN && event.param == VK_ESCAPE ) )
- {
- StopDialog();
- }
- if ( event.event == EVENT_INTERFACE_SETUP )
- {
- StopDialog();
- StartSuspend();
- if ( m_phaseSetup == PHASE_SETUPd ) ChangePhase(PHASE_SETUPds);
- if ( m_phaseSetup == PHASE_SETUPg ) ChangePhase(PHASE_SETUPgs);
- if ( m_phaseSetup == PHASE_SETUPp ) ChangePhase(PHASE_SETUPps);
- if ( m_phaseSetup == PHASE_SETUPc ) ChangePhase(PHASE_SETUPcs);
- if ( m_phaseSetup == PHASE_SETUPs ) ChangePhase(PHASE_SETUPss);
- }
- if ( event.event == EVENT_INTERFACE_AGAIN )
- {
- StopDialog();
- m_main->ChangePhase(PHASE_LOADING);
- }
- if ( event.event == EVENT_INTERFACE_WRITE )
- {
- StopDialog();
- StartSuspend();
- ChangePhase(PHASE_WRITEs);
- }
- if ( event.event == EVENT_INTERFACE_READ )
- {
- StopDialog();
- StartSuspend();
- ChangePhase(PHASE_READs);
- }
-
- return false;
- }
-
- if ( !m_engine->RetMouseHide() &&
- !m_interface->EventProcess(event) )
- {
- return false;
- }
-
- if ( m_phase == PHASE_INIT )
- {
- switch( event.event )
- {
- case EVENT_KEYDOWN:
- if ( event.param == VK_ESCAPE )
- {
-//? StartQuit(); // would you leave?
- m_sound->Play(SOUND_TZOING);
- m_main->ChangePhase(PHASE_GENERIC);
- }
- break;
-
- case EVENT_INTERFACE_QUIT:
-//? StartQuit(); // would you leave?
- m_sound->Play(SOUND_TZOING);
- m_main->ChangePhase(PHASE_GENERIC);
- break;
-
- case EVENT_INTERFACE_TRAINER:
- m_main->ChangePhase(PHASE_TRAINER);
- break;
-
- case EVENT_INTERFACE_DEFI:
- m_main->ChangePhase(PHASE_DEFI);
- break;
-
- case EVENT_INTERFACE_MISSION:
- m_main->ChangePhase(PHASE_MISSION);
- break;
-
- case EVENT_INTERFACE_FREE:
- m_main->ChangePhase(PHASE_FREE);
- break;
-
- case EVENT_INTERFACE_TEEN:
- m_main->ChangePhase(PHASE_TEEN);
- break;
-
- case EVENT_INTERFACE_USER:
- m_main->ChangePhase(PHASE_USER);
- break;
-
- case EVENT_INTERFACE_PROTO:
- m_main->ChangePhase(PHASE_PROTO);
- break;
-
- case EVENT_INTERFACE_SETUP:
- m_main->ChangePhase(m_phaseSetup);
- break;
-
- case EVENT_INTERFACE_NAME:
- m_main->ChangePhase(PHASE_NAME);
- break;
- }
- return false;
- }
-
- if ( m_phase == PHASE_NAME )
- {
- switch( event.event )
- {
- case EVENT_KEYDOWN:
- if ( event.param == VK_RETURN )
- {
- NameSelect();
- }
- if ( event.param == VK_ESCAPE )
- {
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) break;
- pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_NCANCEL);
- if ( pb == 0 ) break;
- if ( pb->TestState(STATE_ENABLE) )
- {
- m_main->ChangePhase(PHASE_INIT);
- }
- }
- break;
-
- case EVENT_INTERFACE_NEDIT:
- UpdateNameList();
- UpdateNameControl();
- break;
-
- case EVENT_INTERFACE_NLIST:
- UpdateNameEdit();
- break;
-
- case EVENT_INTERFACE_NOK:
- NameSelect();
- break;
-
- case EVENT_INTERFACE_PERSO:
- NameSelect();
- m_main->ChangePhase(PHASE_PERSO);
- break;
-
- case EVENT_INTERFACE_NCANCEL:
- m_main->ChangePhase(PHASE_INIT);
- break;
-
- case EVENT_INTERFACE_NDELETE:
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) break;
- pl = (CList*)pw->SearchControl(EVENT_INTERFACE_NLIST);
- if ( pl == 0 ) break;
- StartDeleteGame(pl->RetName(pl->RetSelect()));
- break;
- }
- }
-
- if ( m_phase == PHASE_PERSO )
- {
- switch( event.event )
- {
- case EVENT_KEYDOWN:
- if ( event.param == VK_RETURN )
- {
- m_main->ChangePhase(PHASE_INIT);
- }
- if ( event.param == VK_ESCAPE )
- {
- m_main->ChangePhase(PHASE_NAME);
- }
- break;
-
- case EVENT_INTERFACE_PHEAD:
- m_persoTab = 0;
- UpdatePerso();
- m_main->ScenePerso();
- CameraPerso();
- break;
- case EVENT_INTERFACE_PBODY:
- m_persoTab = 1;
- UpdatePerso();
- m_main->ScenePerso();
- CameraPerso();
- break;
-
- case EVENT_INTERFACE_PFACE1:
- case EVENT_INTERFACE_PFACE2:
- case EVENT_INTERFACE_PFACE3:
- case EVENT_INTERFACE_PFACE4:
- m_perso.face = event.event-EVENT_INTERFACE_PFACE1;
- WriteGamerPerso(m_main->RetGamerName());
- UpdatePerso();
- m_main->ScenePerso();
- break;
-
- case EVENT_INTERFACE_PGLASS0:
- case EVENT_INTERFACE_PGLASS1:
- case EVENT_INTERFACE_PGLASS2:
- case EVENT_INTERFACE_PGLASS3:
- case EVENT_INTERFACE_PGLASS4:
- case EVENT_INTERFACE_PGLASS5:
- case EVENT_INTERFACE_PGLASS6:
- case EVENT_INTERFACE_PGLASS7:
- case EVENT_INTERFACE_PGLASS8:
- case EVENT_INTERFACE_PGLASS9:
- m_perso.glasses = event.event-EVENT_INTERFACE_PGLASS0;
- WriteGamerPerso(m_main->RetGamerName());
- UpdatePerso();
- m_main->ScenePerso();
- break;
-
- case EVENT_INTERFACE_PC0a:
- case EVENT_INTERFACE_PC1a:
- case EVENT_INTERFACE_PC2a:
- case EVENT_INTERFACE_PC3a:
- case EVENT_INTERFACE_PC4a:
- case EVENT_INTERFACE_PC5a:
- case EVENT_INTERFACE_PC6a:
- case EVENT_INTERFACE_PC7a:
- case EVENT_INTERFACE_PC8a:
- case EVENT_INTERFACE_PC9a:
- FixPerso(event.event-EVENT_INTERFACE_PC0a, 0);
- WriteGamerPerso(m_main->RetGamerName());
- UpdatePerso();
- m_main->ScenePerso();
- break;
-
- case EVENT_INTERFACE_PC0b:
- case EVENT_INTERFACE_PC1b:
- case EVENT_INTERFACE_PC2b:
- case EVENT_INTERFACE_PC3b:
- case EVENT_INTERFACE_PC4b:
- case EVENT_INTERFACE_PC5b:
- case EVENT_INTERFACE_PC6b:
- case EVENT_INTERFACE_PC7b:
- case EVENT_INTERFACE_PC8b:
- case EVENT_INTERFACE_PC9b:
- FixPerso(event.event-EVENT_INTERFACE_PC0b, 1);
- WriteGamerPerso(m_main->RetGamerName());
- UpdatePerso();
- m_main->ScenePerso();
- break;
-
- case EVENT_INTERFACE_PCRa:
- case EVENT_INTERFACE_PCGa:
- case EVENT_INTERFACE_PCBa:
- case EVENT_INTERFACE_PCRb:
- case EVENT_INTERFACE_PCGb:
- case EVENT_INTERFACE_PCBb:
- ColorPerso();
- WriteGamerPerso(m_main->RetGamerName());
- UpdatePerso();
- m_main->ScenePerso();
- break;
-
- case EVENT_INTERFACE_PDEF:
- DefPerso();
- WriteGamerPerso(m_main->RetGamerName());
- UpdatePerso();
- m_main->ScenePerso();
- break;
-
- case EVENT_INTERFACE_PLROT:
- m_persoAngle += 0.2f;
- break;
- case EVENT_INTERFACE_PRROT:
- m_persoAngle -= 0.2f;
- break;
-
- case EVENT_INTERFACE_POK:
- m_main->ChangePhase(PHASE_INIT);
- break;
-
- case EVENT_INTERFACE_PCANCEL:
- m_perso = m_persoCopy;
- WriteGamerPerso(m_main->RetGamerName());
- m_main->ChangePhase(PHASE_NAME);
- break;
- }
- }
-
- if ( m_phase == PHASE_TRAINER ||
- m_phase == PHASE_DEFI ||
- m_phase == PHASE_MISSION ||
- m_phase == PHASE_FREE ||
- m_phase == PHASE_TEEN ||
- m_phase == PHASE_USER ||
- m_phase == PHASE_PROTO )
- {
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return false;
-
- if ( event.event == pw->RetEventMsgClose() ||
- event.event == EVENT_INTERFACE_BACK ||
- (event.event == EVENT_KEYDOWN && event.param == VK_ESCAPE) )
- {
- m_main->ChangePhase(PHASE_INIT);
- return false;
- }
- }
-
- if ( m_phase == PHASE_TRAINER ||
- m_phase == PHASE_DEFI ||
- m_phase == PHASE_MISSION ||
- m_phase == PHASE_FREE ||
- m_phase == PHASE_TEEN ||
- m_phase == PHASE_USER ||
- m_phase == PHASE_PROTO )
- {
- switch( event.event )
- {
- case EVENT_INTERFACE_CHAP:
- pl = (CList*)pw->SearchControl(EVENT_INTERFACE_CHAP);
- if ( pl == 0 ) break;
- m_chap[m_index] = pl->RetSelect();
- UpdateSceneList(m_chap[m_index], m_sel[m_index]);
- UpdateSceneResume((m_chap[m_index]+1)*100+(m_sel[m_index]+1));
- break;
-
- case EVENT_INTERFACE_LIST:
- pl = (CList*)pw->SearchControl(EVENT_INTERFACE_LIST);
- if ( pl == 0 ) break;
- m_sel[m_index] = pl->RetSelect();
- UpdateSceneResume((m_chap[m_index]+1)*100+(m_sel[m_index]+1));
- break;
-
- case EVENT_INTERFACE_SOLUCE:
- pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_SOLUCE);
- if ( pb == 0 ) break;
- m_bSceneSoluce = !m_bSceneSoluce;
- pb->SetState(STATE_CHECK, m_bSceneSoluce);
- break;
-
- case EVENT_INTERFACE_PLAY:
- if ( m_phase == PHASE_PROTO && m_chap[m_index] == 0 && m_sel[m_index] == 0 )
- {
- m_main->ChangePhase(PHASE_MODEL);
- break;
- }
- m_sceneRank = (m_chap[m_index]+1)*100+(m_sel[m_index]+1);
- m_phaseTerm = m_phase;
- m_main->ChangePhase(PHASE_LOADING);
- break;
-
- case EVENT_INTERFACE_READ:
- m_phaseTerm = m_phase;
- m_main->ChangePhase(PHASE_READ);
- break;
- }
- return false;
- }
-
- if ( m_phase == PHASE_SETUPd ||
- m_phase == PHASE_SETUPg ||
- m_phase == PHASE_SETUPp ||
- m_phase == PHASE_SETUPc ||
- m_phase == PHASE_SETUPs )
- {
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return false;
-
- if ( event.event == pw->RetEventMsgClose() ||
- event.event == EVENT_INTERFACE_BACK ||
- (event.event == EVENT_KEYDOWN && event.param == VK_ESCAPE) )
- {
- SetupMemorize();
- m_engine->ApplyChange();
- m_main->ChangePhase(PHASE_INIT);
- return false;
- }
-
- switch( event.event )
- {
- case EVENT_INTERFACE_SETUPd:
- m_main->ChangePhase(PHASE_SETUPd);
- break;
-
- case EVENT_INTERFACE_SETUPg:
- m_main->ChangePhase(PHASE_SETUPg);
- break;
-
- case EVENT_INTERFACE_SETUPp:
- m_main->ChangePhase(PHASE_SETUPp);
- break;
-
- case EVENT_INTERFACE_SETUPc:
- m_main->ChangePhase(PHASE_SETUPc);
- break;
-
- case EVENT_INTERFACE_SETUPs:
- m_main->ChangePhase(PHASE_SETUPs);
- break;
- }
- }
-
- if ( m_phase == PHASE_SETUPds ||
- m_phase == PHASE_SETUPgs ||
- m_phase == PHASE_SETUPps ||
- m_phase == PHASE_SETUPcs ||
- m_phase == PHASE_SETUPss )
- {
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return false;
-
- if ( event.event == pw->RetEventMsgClose() ||
- event.event == EVENT_INTERFACE_BACK ||
- (event.event == EVENT_KEYDOWN && event.param == VK_ESCAPE) )
- {
- SetupMemorize();
- m_engine->ApplyChange();
- m_interface->DeleteControl(EVENT_WINDOW5);
- ChangePhase(PHASE_SIMUL);
- StopSuspend();
- return false;
- }
-
- switch( event.event )
- {
- case EVENT_INTERFACE_SETUPd:
- ChangePhase(PHASE_SETUPds);
- break;
-
- case EVENT_INTERFACE_SETUPg:
- ChangePhase(PHASE_SETUPgs);
- break;
-
- case EVENT_INTERFACE_SETUPp:
- ChangePhase(PHASE_SETUPps);
- break;
-
- case EVENT_INTERFACE_SETUPc:
- ChangePhase(PHASE_SETUPcs);
- break;
-
- case EVENT_INTERFACE_SETUPs:
- ChangePhase(PHASE_SETUPss);
- break;
- }
- }
-
- if ( m_phase == PHASE_SETUPd || // setup/display ?
- m_phase == PHASE_SETUPds )
- {
- switch( event.event )
- {
- case EVENT_LIST1:
- case EVENT_LIST2:
- UpdateApply();
- break;
-
- case EVENT_INTERFACE_FULL:
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) break;
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_FULL);
- if ( pc == 0 ) break;
- pl = (CList*)pw->SearchControl(EVENT_LIST2);
- if ( pl == 0 ) break;
- if ( pc->TestState(STATE_CHECK) )
- {
- pc->ClearState(STATE_CHECK); // window
- pl->ClearState(STATE_ENABLE);
- }
- else
- {
- pc->SetState(STATE_CHECK); // fullscreen
- pl->SetState(STATE_ENABLE);
- }
- UpdateApply();
- break;
-
- case EVENT_INTERFACE_APPLY:
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) break;
- pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_APPLY);
- if ( pb == 0 ) break;
- pb->ClearState(STATE_PRESS);
- pb->ClearState(STATE_HILIGHT);
- ChangeDisplay();
- UpdateApply();
- break;
- }
- return false;
- }
-
- if ( m_phase == PHASE_SETUPg || // setup/graphic ?
- m_phase == PHASE_SETUPgs )
- {
- switch( event.event )
- {
- case EVENT_INTERFACE_SHADOW:
- m_engine->SetShadow(!m_engine->RetShadow());
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_GROUND:
- m_engine->SetGroundSpot(!m_engine->RetGroundSpot());
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_DIRTY:
- m_engine->SetDirty(!m_engine->RetDirty());
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_FOG:
- m_engine->SetFog(!m_engine->RetFog());
- m_camera->SetOverBaseColor(RetColor(RetColor(0.0f)));
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_LENS:
- m_engine->SetLensMode(!m_engine->RetLensMode());
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_SKY:
- m_engine->SetSkyMode(!m_engine->RetSkyMode());
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_PLANET:
- m_engine->SetPlanetMode(!m_engine->RetPlanetMode());
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_LIGHT:
- m_engine->SetLightMode(!m_engine->RetLightMode());
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_PARTI:
- case EVENT_INTERFACE_CLIP:
- case EVENT_INTERFACE_DETAIL:
- case EVENT_INTERFACE_GADGET:
- case EVENT_INTERFACE_TEXTURE:
- ChangeSetupButtons();
- break;
-
- case EVENT_INTERFACE_MIN:
- ChangeSetupQuality(-1);
- UpdateSetupButtons();
- break;
- case EVENT_INTERFACE_NORM:
- ChangeSetupQuality(0);
- UpdateSetupButtons();
- break;
- case EVENT_INTERFACE_MAX:
- ChangeSetupQuality(1);
- UpdateSetupButtons();
- break;
- }
- return false;
- }
-
- if ( m_phase == PHASE_SETUPp || // setup/game ?
- m_phase == PHASE_SETUPps )
- {
- switch( event.event )
- {
- case EVENT_INTERFACE_TOTO:
- m_engine->SetTotoMode(!m_engine->RetTotoMode());
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_TOOLTIP:
- m_bTooltip = !m_bTooltip;
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_GLINT:
- m_bGlint = !m_bGlint;
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_RAIN:
- m_bRain = !m_bRain;
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_MOUSE:
- m_engine->SetNiceMouse(!m_engine->RetNiceMouse());
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_EDITMODE:
- m_engine->SetEditIndentMode(!m_engine->RetEditIndentMode());
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_EDITVALUE:
- if ( m_engine->RetEditIndentValue() == 2 )
- {
- m_engine->SetEditIndentValue(4);
- }
- else
- {
- m_engine->SetEditIndentValue(2);
- }
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_SOLUCE4:
- m_bSoluce4 = !m_bSoluce4;
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_MOVIES:
- m_bMovies = !m_bMovies;
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_NICERST:
- m_bNiceReset = !m_bNiceReset;
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_HIMSELF:
- m_bHimselfDamage = !m_bHimselfDamage;
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_SCROLL:
- m_bCameraScroll = !m_bCameraScroll;
- m_camera->SetCameraScroll(m_bCameraScroll);
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_INVERTX:
- m_bCameraInvertX = !m_bCameraInvertX;
- m_camera->SetCameraInvertX(m_bCameraInvertX);
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_INVERTY:
- m_bCameraInvertY = !m_bCameraInvertY;
- m_camera->SetCameraInvertY(m_bCameraInvertY);
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_EFFECT:
- m_bEffect = !m_bEffect;
- m_camera->SetEffect(m_bEffect);
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
- }
- return false;
- }
-
- if ( m_phase == PHASE_SETUPc || // setup/commands ?
- m_phase == PHASE_SETUPcs )
- {
- switch( event.event )
- {
- case EVENT_INTERFACE_KSCROLL:
- UpdateKey();
- break;
-
- case EVENT_INTERFACE_KLEFT:
- case EVENT_INTERFACE_KRIGHT:
- case EVENT_INTERFACE_KUP:
- case EVENT_INTERFACE_KDOWN:
- case EVENT_INTERFACE_KGUP:
- case EVENT_INTERFACE_KGDOWN:
- case EVENT_INTERFACE_KCAMERA:
- case EVENT_INTERFACE_KDESEL:
- case EVENT_INTERFACE_KACTION:
- case EVENT_INTERFACE_KNEAR:
- case EVENT_INTERFACE_KAWAY:
- case EVENT_INTERFACE_KNEXT:
- case EVENT_INTERFACE_KHUMAN:
- case EVENT_INTERFACE_KQUIT:
- case EVENT_INTERFACE_KHELP:
- case EVENT_INTERFACE_KPROG:
- case EVENT_INTERFACE_KCBOT:
- case EVENT_INTERFACE_KSPEED10:
- case EVENT_INTERFACE_KSPEED15:
- case EVENT_INTERFACE_KSPEED20:
- case EVENT_INTERFACE_KSPEED30:
- case EVENT_INTERFACE_KVISIT:
- ChangeKey(event.event);
- UpdateKey();
- break;
-
- case EVENT_INTERFACE_KDEF:
- m_engine->ResetKey();
- UpdateKey();
- break;
-
- case EVENT_INTERFACE_JOYSTICK:
- m_engine->SetJoystick(!m_engine->RetJoystick());
- UpdateSetupButtons();
- break;
- }
- return false;
- }
-
- if ( m_phase == PHASE_SETUPs || // setup/sound ?
- m_phase == PHASE_SETUPss )
- {
- switch( event.event )
- {
- case EVENT_INTERFACE_VOLSOUND:
- case EVENT_INTERFACE_VOLMUSIC:
- ChangeSetupButtons();
- break;
-
- case EVENT_INTERFACE_SOUND3D:
- m_sound->SetSound3D(!m_sound->RetSound3D());
- ChangeSetupButtons();
- UpdateSetupButtons();
- break;
-
- case EVENT_INTERFACE_SILENT:
- m_sound->SetAudioVolume(0);
- m_sound->SetMidiVolume(0);
- UpdateSetupButtons();
- break;
- case EVENT_INTERFACE_NOISY:
- m_sound->SetAudioVolume(MAXVOLUME);
- m_sound->SetMidiVolume(MAXVOLUME*3/4);
- UpdateSetupButtons();
- break;
- }
- return false;
- }
-
- if ( m_phase == PHASE_READ )
- {
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return false;
-
- if ( event.event == pw->RetEventMsgClose() ||
- event.event == EVENT_INTERFACE_BACK ||
- (event.event == EVENT_KEYDOWN && event.param == VK_ESCAPE) )
- {
- ChangePhase(m_phaseTerm);
- }
-
- if ( event.event == EVENT_INTERFACE_IOLIST )
- {
- IOUpdateList();
- }
- if ( event.event == EVENT_INTERFACE_IODELETE )
- {
- IODeleteScene();
- IOUpdateList();
- }
- if ( event.event == EVENT_INTERFACE_IOREAD )
- {
- if ( IOReadScene() )
- {
- m_main->ChangePhase(PHASE_LOADING);
- }
- }
-
- return false;
- }
-
- if ( m_phase == PHASE_WRITEs ||
- m_phase == PHASE_READs )
- {
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return false;
-
- if ( event.event == pw->RetEventMsgClose() ||
- event.event == EVENT_INTERFACE_BACK ||
- (event.event == EVENT_KEYDOWN && event.param == VK_ESCAPE) )
- {
- m_interface->DeleteControl(EVENT_WINDOW5);
- ChangePhase(PHASE_SIMUL);
- StopSuspend();
- }
-
- if ( event.event == EVENT_INTERFACE_IOLIST )
- {
- IOUpdateList();
- }
- if ( event.event == EVENT_INTERFACE_IODELETE )
- {
- IODeleteScene();
- IOUpdateList();
- }
- if ( event.event == EVENT_INTERFACE_IOWRITE )
- {
- IOWriteScene();
- m_interface->DeleteControl(EVENT_WINDOW5);
- ChangePhase(PHASE_SIMUL);
- StopSuspend();
- }
- if ( event.event == EVENT_INTERFACE_IOREAD )
- {
- if ( IOReadScene() )
- {
- m_interface->DeleteControl(EVENT_WINDOW5);
- ChangePhase(PHASE_SIMUL);
- StopSuspend();
- m_main->ChangePhase(PHASE_LOADING);
- }
- }
-
- return false;
- }
-
- if ( m_phase == PHASE_WELCOME1 )
- {
- if ( event.event == EVENT_KEYDOWN ||
- event.event == EVENT_LBUTTONDOWN ||
- event.event == EVENT_RBUTTONDOWN )
- {
- ChangePhase(PHASE_WELCOME2);
- return true;
- }
- }
- if ( m_phase == PHASE_WELCOME2 )
- {
- if ( event.event == EVENT_KEYDOWN ||
- event.event == EVENT_LBUTTONDOWN ||
- event.event == EVENT_RBUTTONDOWN )
- {
- ChangePhase(PHASE_WELCOME3);
- return true;
- }
- }
- if ( m_phase == PHASE_WELCOME3 )
- {
- if ( event.event == EVENT_KEYDOWN ||
- event.event == EVENT_LBUTTONDOWN ||
- event.event == EVENT_RBUTTONDOWN )
- {
- ChangePhase(PHASE_NAME);
- return true;
- }
- }
-
- if ( m_phase == PHASE_GENERIC )
- {
- if ( event.event == EVENT_INTERFACE_ABORT )
- {
- ChangePhase(PHASE_INIT);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
- if ( event.param == VK_ESCAPE )
- {
- ChangePhase(PHASE_INIT);
- }
- else
- {
- m_event->MakeEvent(newEvent, EVENT_QUIT);
- m_event->AddEvent(newEvent);
- }
- }
-
- if ( event.event == EVENT_LBUTTONDOWN ||
- event.event == EVENT_RBUTTONDOWN )
- {
- m_event->MakeEvent(newEvent, EVENT_QUIT);
- m_event->AddEvent(newEvent);
- }
- }
-
- return true;
-}
-
-
-// Moves the reflections.
-
-void CMainDialog::GlintMove()
-{
- CWindow* pw;
- CGroup* pg;
- Math::Point pos, dim, zoom;
-
- if ( m_phase == PHASE_SIMUL ) return;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
-
- if ( m_phase == PHASE_INIT )
- {
- pg = (CGroup*)pw->SearchControl(EVENT_INTERFACE_GLINTl);
- if ( pg != 0 )
- {
- zoom.x = sinf(m_glintTime*0.23f);
- zoom.y = sinf(m_glintTime*0.37f);
- pos.x = 0.35f;
- pos.y = 0.90f;
- dim.x = 0.30f-0.10f*(zoom.x+1.0f)/2.0f;
- dim.y = 0.50f-0.30f*(zoom.y+1.0f)/2.0f;
- pos.y -= dim.y;
- pg->SetPos(pos);
- pg->SetDim(dim);
- }
-
- pg = (CGroup*)pw->SearchControl(EVENT_INTERFACE_GLINTr);
- if ( pg != 0 )
- {
- zoom.x = sinf(m_glintTime*0.21f);
- zoom.y = sinf(m_glintTime*0.26f);
- pos.x = 0.65f;
- pos.y = 0.10f;
- dim.x = 0.30f-0.10f*(zoom.x+1.0f)/2.0f;
- dim.y = 0.50f-0.30f*(zoom.y+1.0f)/2.0f;
- pos.x -= dim.x;
- pg->SetPos(pos);
- pg->SetDim(dim);
- }
- }
-
- if ( m_phase == PHASE_NAME ||
- m_phase == PHASE_TRAINER ||
- m_phase == PHASE_MISSION ||
- m_phase == PHASE_FREE ||
- m_phase == PHASE_TEEN ||
- m_phase == PHASE_USER ||
- m_phase == PHASE_PROTO )
- {
- pg = (CGroup*)pw->SearchControl(EVENT_INTERFACE_GLINTl);
- if ( pg != 0 )
- {
- zoom.x = sinf(m_glintTime*0.22f);
- zoom.y = sinf(m_glintTime*0.37f);
- pos.x = 0.10f;
- pos.y = 0.90f;
- dim.x = 0.60f+0.30f*zoom.x;
- dim.y = 0.60f+0.30f*zoom.y;
- pos.y -= dim.y;
- pg->SetPos(pos);
- pg->SetDim(dim);
- }
-
- pg = (CGroup*)pw->SearchControl(EVENT_INTERFACE_GLINTr);
- if ( pg != 0 )
- {
- zoom.x = sinf(m_glintTime*0.19f);
- zoom.y = sinf(m_glintTime*0.28f);
- pos.x = 0.90f;
- pos.y = 0.10f;
- dim.x = 0.60f+0.30f*zoom.x;
- dim.y = 0.60f+0.30f*zoom.y;
- pos.x -= dim.x;
- pg->SetPos(pos);
- pg->SetDim(dim);
- }
- }
-
- if ( m_phase == PHASE_SETUPd ||
- m_phase == PHASE_SETUPg ||
- m_phase == PHASE_SETUPp ||
- m_phase == PHASE_SETUPc ||
- m_phase == PHASE_SETUPs ||
- m_phase == PHASE_SETUPds ||
- m_phase == PHASE_SETUPgs ||
- m_phase == PHASE_SETUPps ||
- m_phase == PHASE_SETUPcs ||
- m_phase == PHASE_SETUPss )
- {
- pg = (CGroup*)pw->SearchControl(EVENT_INTERFACE_GLINTu);
- if ( pg != 0 )
- {
- zoom.y = sinf(m_glintTime*0.27f);
- pos.x = 0.10f;
- pos.y = 0.76f;
- dim.x = 0.80f;
- dim.y = 0.32f+0.20f*zoom.y;
- pos.y -= dim.y;
- pg->SetPos(pos);
- pg->SetDim(dim);
- }
-
- pg = (CGroup*)pw->SearchControl(EVENT_INTERFACE_GLINTr);
- if ( pg != 0 )
- {
- zoom.x = sinf(m_glintTime*0.29f);
- zoom.y = sinf(m_glintTime*0.14f);
- pos.x = 0.90f;
- pos.y = 0.10f;
- dim.x = 0.40f+0.20f*zoom.x;
- dim.y = 0.40f+0.20f*zoom.y;
- pos.x -= dim.x;
- pg->SetPos(pos);
- pg->SetDim(dim);
- }
- }
-
- if ( m_phase == PHASE_WRITE ||
- m_phase == PHASE_READ ||
- m_phase == PHASE_WRITEs ||
- m_phase == PHASE_READs )
- {
- pg = (CGroup*)pw->SearchControl(EVENT_INTERFACE_GLINTl);
- if ( pg != 0 )
- {
- zoom.x = sinf(m_glintTime*0.22f);
- zoom.y = sinf(m_glintTime*0.37f);
- pos.x = 0.10f;
- pos.y = 0.90f;
- dim.x = 0.60f+0.30f*zoom.x;
- dim.y = 0.60f+0.30f*zoom.y;
- pos.y -= dim.y;
- pg->SetPos(pos);
- pg->SetDim(dim);
- }
-
- pg = (CGroup*)pw->SearchControl(EVENT_INTERFACE_GLINTr);
- if ( pg != 0 )
- {
- zoom.x = sinf(m_glintTime*0.19f);
- zoom.y = sinf(m_glintTime*0.28f);
- pos.x = 0.90f;
- pos.y = 0.10f;
- dim.x = 0.60f+0.30f*zoom.x;
- dim.y = 0.60f+0.30f*zoom.y;
- pos.x -= dim.x;
- pg->SetPos(pos);
- pg->SetDim(dim);
- }
- }
-}
-
-
-// Returns the position for a sound.
-
-Math::Vector SoundPos(Math::Point pos)
-{
- Math::Vector s;
-
- s.x = (pos.x-0.5f)*2.0f;
- s.y = (pos.y-0.5f)*2.0f;
- s.z = 0.0f;
-
- return s;
-}
-
-// Returns a random position for a sound.
-
-Math::Vector SoundRand()
-{
- Math::Vector s;
-
- s.x = (Math::Rand()-0.5f)*2.0f;
- s.y = (Math::Rand()-0.5f)*2.0f;
- s.z = 0.0f;
-
- return s;
-}
-
-// Makes pretty qq particles evolve.
-
-void CMainDialog::FrameParticule(float rTime)
-{
-#if _NEWLOOK
-#else
- Math::Vector pos, speed;
- Math::Point dim;
- float *pParti, *pGlint;
- int nParti, nGlint;
- int i, r, ii;
-
- static float partiPosInit[1+5*12] =
- { // x x t2 t2 type
- 12.0f,
- 607.0f, 164.0f, 0.2f, 0.8f, 1.0f, // upper cable
- 604.0f, 205.0f, 0.1f, 0.3f, 1.0f, // middle cable
- 603.0f, 247.0f, 0.1f, 0.3f, 1.0f, // lower cable
- 119.0f, 155.0f, 0.2f, 0.4f, 2.0f, // left pipe
- 366.0f, 23.0f, 0.5f, 1.5f, 4.0f, // upper pipe
- 560.0f, 414.0f, 0.1f, 0.1f, 1.0f, // button lower/right
- 20.0f, 413.0f, 0.1f, 0.1f, 2.0f, // button lower/left
- 39.0f, 78.0f, 0.1f, 0.2f, 1.0f, // left pot
- 39.0f, 78.0f, 0.5f, 0.9f, 1.0f, // left pot
- 170.0f, 229.0f, 0.5f, 0.5f, 3.0f, // left smoke
- 170.0f, 229.0f, 0.5f, 0.5f, 3.0f, // left smoke
- 474.0f, 229.0f, 0.5f, 0.5f, 3.0f, // right smoke
- };
-
- static float glintPosInit[1+2*14] =
- {
- 14.0f,
- 15.0f, 407.0f,
- 68.0f, 417.0f,
- 548.0f, 36.0f,
- 611.0f, 37.0f,
- 611.0f, 100.0f,
- 611.0f, 395.0f,
- 36.0f, 35.0f,
- 166.0f, 55.0f,
- 166.0f, 94.0f,
- 477.0f, 56.0f,
- 31.0f, 190.0f,
- 32.0f, 220.0f,
- 65.0f, 221.0f,
- 65.0f, 250.0f,
- };
-
- static float partiPosBig[1+5*12] =
- { // x x t2 t2 type
- 12.0f,
- 607.0f, 164.0f, 0.2f, 0.8f, 1.0f, // upper cable
- 604.0f, 205.0f, 0.1f, 0.3f, 1.0f, // middle cable
- 603.0f, 247.0f, 0.1f, 0.3f, 1.0f, // lower cable
- 64.0f, 444.0f, 0.2f, 0.8f, 1.0f, // down the left cable
- 113.0f, 449.0f, 0.1f, 0.3f, 1.0f, // down the left cable
- 340.0f, 463.0f, 0.2f, 0.8f, 1.0f, // down the middle cable
- 36.0f, 155.0f, 0.2f, 0.4f, 2.0f, // left pipe
- 366.0f, 23.0f, 0.5f, 1.5f, 4.0f, // upper pipe
- 612.0f, 414.0f, 0.1f, 0.1f, 1.0f, // button lower/right
- 20.0f, 413.0f, 0.1f, 0.1f, 2.0f, // button lower/left
- 39.0f, 78.0f, 0.1f, 0.2f, 1.0f, // left pot
- 39.0f, 78.0f, 0.5f, 0.9f, 1.0f, // left pot
- };
-
- static float glintPosBig[1+2*12] =
- {
- 12.0f,
- 15.0f, 407.0f,
- 48.0f, 399.0f,
- 611.0f, 37.0f,
- 611.0f, 100.0f,
- 611.0f, 395.0f,
- 36.0f, 35.0f,
- 31.0f, 190.0f,
- 32.0f, 220.0f,
- 31.0f, 221.0f,
- 31.0f, 189.0f,
- 255.0f, 18.0f,
- 279.0f, 18.0f,
- };
-
- if ( m_bDialog || !m_bRain ) return;
-
- if ( m_phase == PHASE_INIT )
- {
- pParti = partiPosInit;
- pGlint = glintPosInit;
- }
- else if ( m_phase == PHASE_NAME ||
- m_phase == PHASE_TRAINER ||
- m_phase == PHASE_DEFI ||
- m_phase == PHASE_MISSION ||
- m_phase == PHASE_FREE ||
- m_phase == PHASE_TEEN ||
- m_phase == PHASE_USER ||
- m_phase == PHASE_PROTO ||
- m_phase == PHASE_SETUPd ||
- m_phase == PHASE_SETUPg ||
- m_phase == PHASE_SETUPp ||
- m_phase == PHASE_SETUPc ||
- m_phase == PHASE_SETUPs ||
- m_phase == PHASE_WRITE ||
- m_phase == PHASE_READ )
- {
- pParti = partiPosBig;
- pGlint = glintPosBig;
- }
- else
- {
- return;
- }
-
- nParti = (int)(*pParti++);
- nGlint = (int)(*pGlint++);
-
- for ( i=0 ; i<10 ; i++ )
- {
- if ( m_partiPhase[i] == 0 ) // waiting?
- {
- m_partiTime[i] -= rTime;
- if ( m_partiTime[i] <= 0.0f )
- {
- r = rand()%3;
-
- if ( r == 0 )
- {
- ii = rand()%nParti;
- m_partiPos[i].x = pParti[ii*5+0]/640.0f;
- m_partiPos[i].y = (480.0f-pParti[ii*5+1])/480.0f;
- m_partiTime[i] = pParti[ii*5+2]+Math::Rand()*pParti[ii*5+3];
- m_partiPhase[i] = (int)pParti[ii*5+4];
- if ( m_partiPhase[i] == 3 )
- {
- m_sound->Play(SOUND_PSHHH, SoundPos(m_partiPos[i]), 0.3f+Math::Rand()*0.3f);
- }
- else
- {
- m_sound->Play(SOUND_GGG, SoundPos(m_partiPos[i]), 0.1f+Math::Rand()*0.4f);
- }
- }
-
- if ( r == 1 )
- {
- ii = rand()%nGlint;
- pos.x = pGlint[ii*2+0]/640.0f;
- pos.y = (480.0f-pGlint[ii*2+1])/480.0f;
- pos.z = 0.0f;
- speed.x = 0.0f;
- speed.y = 0.0f;
- speed.z = 0.0f;
- dim.x = 0.04f+Math::Rand()*0.04f;
- dim.y = dim.x/0.75f;
- m_particule->CreateParticule(pos, speed, dim,
- rand()%2?PARTIGLINT:PARTICONTROL,
- Math::Rand()*0.4f+0.4f, 0.0f, 0.0f,
- SH_INTERFACE);
- m_partiTime[i] = 0.5f+Math::Rand()*0.5f;
- }
-
- if ( r == 2 )
- {
- ii = rand()%7;
- if ( ii == 0 )
- {
- m_sound->Play(SOUND_ENERGY, SoundRand(), 0.2f+Math::Rand()*0.2f);
- m_partiTime[i] = 1.0f+Math::Rand()*1.0f;
- }
- if ( ii == 1 )
- {
- m_sound->Play(SOUND_STATION, SoundRand(), 0.2f+Math::Rand()*0.2f);
- m_partiTime[i] = 1.0f+Math::Rand()*2.0f;
- }
- if ( ii == 2 )
- {
- m_sound->Play(SOUND_ALARM, SoundRand(), 0.1f+Math::Rand()*0.1f);
- m_partiTime[i] = 2.0f+Math::Rand()*4.0f;
- }
- if ( ii == 3 )
- {
- m_sound->Play(SOUND_INFO, SoundRand(), 0.1f+Math::Rand()*0.1f);
- m_partiTime[i] = 2.0f+Math::Rand()*4.0f;
- }
- if ( ii == 4 )
- {
- m_sound->Play(SOUND_RADAR, SoundRand(), 0.2f+Math::Rand()*0.2f);
- m_partiTime[i] = 0.5f+Math::Rand()*1.0f;
- }
- if ( ii == 5 )
- {
- m_sound->Play(SOUND_GFLAT, SoundRand(), 0.3f+Math::Rand()*0.3f);
- m_partiTime[i] = 2.0f+Math::Rand()*4.0f;
- }
- if ( ii == 6 )
- {
- m_sound->Play(SOUND_ALARMt, SoundRand(), 0.1f+Math::Rand()*0.1f);
- m_partiTime[i] = 2.0f+Math::Rand()*4.0f;
- }
- }
- }
- }
-
- if ( m_partiPhase[i] != 0 ) // generates?
- {
- m_partiTime[i] -= rTime;
- if ( m_partiTime[i] > 0.0f )
- {
- if ( m_partiPhase[i] == 1 ) // sparks?
- {
- pos.x = m_partiPos[i].x;
- pos.y = m_partiPos[i].y;
- pos.z = 0.0f;
- pos.x += (Math::Rand()-0.5f)*0.01f;
- pos.y += (Math::Rand()-0.5f)*0.01f;
- speed.x = (Math::Rand()-0.5f)*0.2f;
- speed.y = (Math::Rand()-0.5f)*0.2f;
- speed.z = 0.0f;
- dim.x = 0.005f+Math::Rand()*0.005f;
- dim.y = dim.x/0.75f;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ,
- Math::Rand()*0.2f+0.2f, 0.0f, 0.0f,
- SH_INTERFACE);
- pos.x = m_partiPos[i].x;
- pos.y = m_partiPos[i].y;
- pos.z = 0.0f;
- speed.x = (Math::Rand()-0.5f)*0.5f;
- speed.y = (0.3f+Math::Rand()*0.3f);
- speed.z = 0.0f;
- dim.x = 0.01f+Math::Rand()*0.01f;
- dim.y = dim.x/0.75f;
- m_particule->CreateParticule(pos, speed, dim,
- (ParticuleType)(PARTILENS1+rand()%3),
- Math::Rand()*0.5f+0.5f, 2.0f, 0.0f,
- SH_INTERFACE);
- }
- if ( m_partiPhase[i] == 2 ) // sparks?
- {
- pos.x = m_partiPos[i].x;
- pos.y = m_partiPos[i].y;
- pos.z = 0.0f;
- pos.x += (Math::Rand()-0.5f)*0.01f;
- pos.y += (Math::Rand()-0.5f)*0.01f;
- speed.x = (Math::Rand()-0.5f)*0.2f;
- speed.y = (Math::Rand()-0.5f)*0.2f;
- speed.z = 0.0f;
- dim.x = 0.005f+Math::Rand()*0.005f;
- dim.y = dim.x/0.75f;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ,
- Math::Rand()*0.2f+0.2f, 0.0f, 0.0f,
- SH_INTERFACE);
- pos.x = m_partiPos[i].x;
- pos.y = m_partiPos[i].y;
- pos.z = 0.0f;
- speed.x = (Math::Rand()-0.5f)*0.5f;
- speed.y = (0.3f+Math::Rand()*0.3f);
- speed.z = 0.0f;
- dim.x = 0.005f+Math::Rand()*0.005f;
- dim.y = dim.x/0.75f;
- m_particule->CreateParticule(pos, speed, dim, PARTISCRAPS,
- Math::Rand()*0.5f+0.5f, 2.0f, 0.0f,
- SH_INTERFACE);
- }
- if ( m_partiPhase[i] == 3 ) // smoke?
- {
- pos.x = m_partiPos[i].x;
- pos.y = m_partiPos[i].y;
- pos.z = 0.0f;
- pos.x += (Math::Rand()-0.5f)*0.03f;
- pos.y += (Math::Rand()-0.5f)*0.03f;
- speed.x = (Math::Rand()-0.5f)*0.2f;
- speed.y = Math::Rand()*0.5f;
- speed.z = 0.0f;
- dim.x = 0.03f+Math::Rand()*0.07f;
- dim.y = dim.x/0.75f;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH,
- Math::Rand()*0.4f+0.4f, 0.0f, 0.0f,
- SH_INTERFACE);
- }
- }
- else
- {
- m_partiPhase[i] = 0;
- m_partiTime[i] = 2.0f+Math::Rand()*4.0f;
- }
- }
- }
-#endif
-}
-
-// Some nice particles following the mouse.
-
-void CMainDialog::NiceParticule(Math::Point mouse, bool bPress)
-{
- Math::Vector pos, speed;
- Math::Point dim;
-
- if ( !m_bRain ) return;
- if ( (m_phase == PHASE_SIMUL ||
- m_phase == PHASE_WIN ||
- m_phase == PHASE_LOST ||
- m_phase == PHASE_MODEL ) &&
- !m_bDialog ) return;
-
- if ( bPress )
- {
- pos.x = mouse.x;
- pos.y = mouse.y;
- pos.z = 0.0f;
- speed.x = (Math::Rand()-0.5f)*0.5f;
- speed.y = (0.3f+Math::Rand()*0.3f);
- speed.z = 0.0f;
- dim.x = 0.005f+Math::Rand()*0.005f;
- dim.y = dim.x/0.75f;
- m_particule->CreateParticule(pos, speed, dim, PARTISCRAPS,
- Math::Rand()*0.5f+0.5f, 2.0f, 0.0f,
- SH_INTERFACE);
- }
- else
- {
- pos.x = mouse.x;
- pos.y = mouse.y;
- pos.z = 0.0f;
- speed.x = (Math::Rand()-0.5f)*0.5f;
- speed.y = (0.3f+Math::Rand()*0.3f);
- speed.z = 0.0f;
- dim.x = 0.01f+Math::Rand()*0.01f;
- dim.y = dim.x/0.75f;
- m_particule->CreateParticule(pos, speed, dim,
- (ParticuleType)(PARTILENS1+rand()%3),
- Math::Rand()*0.5f+0.5f, 2.0f, 0.0f,
- SH_INTERFACE);
- }
-}
-
-
-
-// Specifies the special user folder if needed.
-
-void CMainDialog::SetUserDir(char *base, int rank)
-{
- char dir[100];
-
- if ( strcmp(base, "user") == 0 && rank >= 100 )
- {
- sprintf(dir, "%s\\%s", m_userDir, m_userList[rank/100-1]);
- UserDir(true, dir);
- }
- else
- {
- UserDir(false, "");
- }
-}
-
-// Builds the file name of a mission.
-
-void CMainDialog::BuildSceneName(char *filename, char *base, int rank)
-{
- if ( strcmp(base, "user") == 0 )
- {
- sprintf(filename, "%s\\%s\\scene%.2d.txt", m_userDir, m_userList[rank/100-1], rank%100);
- }
- else
- {
- sprintf(filename, "%s\\%s%.3d.txt", m_sceneDir, base, rank);
- }
-}
-
-// Built the default descriptive name of a mission.
-
-void CMainDialog::BuildResumeName(char *filename, char *base, int rank)
-{
- sprintf(filename, "Scene %s %d", base, rank);
-}
-
-// Returns the name of the file or save the files.
-
-char* CMainDialog::RetFilesDir()
-{
- return m_filesDir;
-}
-
-
-// Updates the list of players after checking the files on disk.
-
-void CMainDialog::ReadNameList()
-{
- CWindow* pw;
- CList* pl;
- long hFile;
- struct _finddata_t fBuffer;
- bool bDo;
- char dir[_MAX_FNAME];
- char temp[_MAX_FNAME];
- char filenames[_MAX_FNAME][100];
- int nbFilenames, i;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pl = (CList*)pw->SearchControl(EVENT_INTERFACE_NLIST);
- if ( pl == 0 ) return;
- pl->Flush();
-
- nbFilenames = 0;
- sprintf(dir, "%s\\*", m_savegameDir);
- hFile = _findfirst(dir, &fBuffer);
- if ( hFile != -1 )
- {
- do
- {
- if ( (fBuffer.attrib & _A_SUBDIR) && fBuffer.name[0] != '.' )
- {
- strcpy(filenames[nbFilenames++], fBuffer.name);
- }
- }
- while ( _findnext(hFile, &fBuffer) == 0 && nbFilenames < 100 );
- }
- do // sorts all names:
- {
- bDo = false;
- for ( i=0 ; i<nbFilenames-1 ; i++ )
- {
- if ( strcmp(filenames[i], filenames[i+1]) > 0 )
- {
- strcpy(temp, filenames[i]);
- strcpy(filenames[i], filenames[i+1]);
- strcpy(filenames[i+1], temp);
- bDo = true;
- }
- }
- }
- while ( bDo );
-
- for ( i=0 ; i<nbFilenames ; i++ )
- {
- pl->SetName(i, filenames[i]);
- }
-}
-
-// Updates the controls of the players.
-
-void CMainDialog::UpdateNameControl()
-{
- CWindow* pw;
- CList* pl;
- CButton* pb;
- CEdit* pe;
- char name[100];
- char* gamer;
- int total, sel;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pl = (CList*)pw->SearchControl(EVENT_INTERFACE_NLIST);
- if ( pl == 0 ) return;
- pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_NEDIT);
- if ( pe == 0 ) return;
-
- gamer = m_main->RetGamerName();
- total = pl->RetTotal();
- sel = pl->RetSelect();
- pe->GetText(name, 100);
-
- pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_NCANCEL);
- if ( pb != 0 )
- {
- pb->SetState(STATE_ENABLE, gamer[0]!=0);
- }
-
- pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_NDELETE);
- if ( pb != 0 )
- {
- pb->SetState(STATE_ENABLE, total>0 && sel!=-1);
- }
-
- pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_NOK);
- if ( pb != 0 )
- {
- pb->SetState(STATE_ENABLE, name[0]!=0 || sel!=-1);
- }
-
- pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_PERSO);
- if ( pb != 0 )
- {
- pb->SetState(STATE_ENABLE, name[0]!=0 || sel!=-1);
- }
-}
-
-// Updates the list of players by name frape.
-
-void CMainDialog::UpdateNameList()
-{
- CWindow* pw;
- CList* pl;
- CEdit* pe;
- char name[100];
- int total, sel, i;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pl = (CList*)pw->SearchControl(EVENT_INTERFACE_NLIST);
- if ( pl == 0 ) return;
- pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_NEDIT);
- if ( pe == 0 ) return;
-
- pe->GetText(name, 100);
- total = pl->RetTotal();
- sel = pl->RetSelect();
-
- for ( i=0 ; i<total ; i++ )
- {
- if ( stricmp(name, pl->RetName(i)) == 0 )
- {
- pl->SetSelect(i);
- pl->ShowSelect(false);
- return;
- }
- }
-
- pl->SetSelect(-1);
-}
-
-// Updates the player's name and function of the selected list.
-
-void CMainDialog::UpdateNameEdit()
-{
- CWindow* pw;
- CList* pl;
- CEdit* pe;
- char* name;
- int sel;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pl = (CList*)pw->SearchControl(EVENT_INTERFACE_NLIST);
- if ( pl == 0 ) return;
- pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_NEDIT);
- if ( pe == 0 ) return;
-
- sel = pl->RetSelect();
- if ( sel == -1 )
- {
- pe->SetText("");
- pe->SetCursor(0, 0);
- }
- else
- {
- name = pl->RetName(sel);
- pe->SetText(name);
- pe->SetCursor(strlen(name), 0);
- }
-
- UpdateNameControl();
-}
-
-// Updates the representation of the player depending on the selected list.
-
-void CMainDialog::UpdateNameFace()
-{
- CWindow* pw;
- CList* pl;
- char* name;
- int sel;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pl = (CList*)pw->SearchControl(EVENT_INTERFACE_NLIST);
- if ( pl == 0 ) return;
-
- sel = pl->RetSelect();
- if ( sel == -1 ) return;
- name = pl->RetName(sel);
-
- ReadGamerPerso(name);
-}
-
-// Selects a player.
-
-void CMainDialog::NameSelect()
-{
- CWindow* pw;
- CList* pl;
- CEdit* pe;
- char name[100];
- int sel;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pl = (CList*)pw->SearchControl(EVENT_INTERFACE_NLIST);
- if ( pl == 0 ) return;
- pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_NEDIT);
- if ( pe == 0 ) return;
-
- pe->GetText(name, 100);
- sel = pl->RetSelect();
-
- if ( sel == -1 )
- {
- NameCreate();
- }
- else
- {
- m_main->SetGamerName(pl->RetName(sel));
- m_main->ChangePhase(PHASE_INIT);
- }
-
- RetGamerFace(m_main->RetGamerName());
-
- SetProfileString("Gamer", "LastName", m_main->RetGamerName());
-}
-
-// Creates a new player.
-
-void CMainDialog::NameCreate()
-{
- CWindow* pw;
- CEdit* pe;
- char name[100];
- char dir[100];
- char c;
- int len, i, j;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_NEDIT);
- if ( pe == 0 ) return;
-
- pe->GetText(name, 100);
- if ( name[0] == 0 )
- {
- m_sound->Play(SOUND_TZOING);
- return;
- }
-
- len = strlen(name);
- j = 0;
- for ( i=0 ; i<len ; i++ )
- {
- c = RetNoAccent(RetToLower(name[i]));
- if ( (c >= '0' && c <= '9') ||
- (c >= 'a' && c <= 'z') ||
- c == ' ' ||
- c == '-' ||
- c == '_' ||
- c == '.' ||
- c == ',' ||
- c == '\'' )
- {
- name[j++] = name[i];
- }
- }
- name[j] = 0;
- if ( j == 0 )
- {
- m_sound->Play(SOUND_TZOING);
- return;
- }
-
- _mkdir(m_savegameDir); // if does not exist yet!
-
- sprintf(dir, "%s\\%s", m_savegameDir, name);
- if ( _mkdir(dir) != 0 )
- {
- m_sound->Play(SOUND_TZOING);
- pe->SetText(name);
- pe->SetCursor(strlen(name), 0);
- pe->SetFocus(true);
- return;
- }
-
- SetGamerFace(name, 0);
-
- m_main->SetGamerName(name);
- m_main->ChangePhase(PHASE_INIT);
-}
-
-// Deletes a folder and all its offspring.
-
-bool RemoveDir(char *dirname)
-{
- long hFile;
- struct _finddata_t fBuffer;
- char filename[100];
-
- sprintf(filename, "%s\\*", dirname);
- hFile = _findfirst(filename, &fBuffer);
- if ( hFile != -1 )
- {
- do
- {
- if ( fBuffer.name[0] != '.' )
- {
- if ( fBuffer.attrib & _A_SUBDIR )
- {
- sprintf(filename, "%s\\%s", dirname, fBuffer.name);
- RemoveDir(filename);
- }
- else
- {
- sprintf(filename, "%s\\%s", dirname, fBuffer.name);
- remove(filename);
- }
- }
- }
- while ( _findnext(hFile, &fBuffer) == 0 );
- }
-
- if ( _rmdir(dirname) != 0 )
- {
- return false;
- }
- return true;
-}
-
-// Removes a player.
-
-void CMainDialog::NameDelete()
-{
- CWindow* pw;
- CList* pl;
- int sel;
- char* gamer;
- char dir[100];
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pl = (CList*)pw->SearchControl(EVENT_INTERFACE_NLIST);
- if ( pl == 0 ) return;
-
- sel = pl->RetSelect();
- if ( sel == -1 )
- {
- m_sound->Play(SOUND_TZOING);
- return;
- }
- gamer = pl->RetName(sel);
-
- // Deletes all the contents of the file.
- sprintf(dir, "%s\\%s", m_savegameDir, gamer);
- if ( !RemoveDir(dir) )
- {
- m_sound->Play(SOUND_TZOING);
- return;
- }
-
- m_main->SetGamerName("");
- pl->SetSelect(-1);
-
- ReadNameList();
- UpdateNameList();
- UpdateNameControl();
-}
-
-
-
-// ests whether two colors are equal or nearly are.
-
-bool EqColor(const D3DCOLORVALUE &c1, const D3DCOLORVALUE &c2)
-{
- return (fabs(c1.r-c2.r) < 0.01f &&
- fabs(c1.g-c2.g) < 0.01f &&
- fabs(c1.b-c2.b) < 0.01f );
-}
-
-// Updates all the buttons for the character.
-
-void CMainDialog::UpdatePerso()
-{
- CWindow* pw;
- CLabel* pl;
- CButton* pb;
- CColor* pc;
- CSlider* ps;
- D3DCOLORVALUE color;
- char name[100];
- int i;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
-
- pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_PHEAD);
- if ( pb != 0 )
- {
- pb->SetState(STATE_CHECK, m_persoTab==0);
- }
- pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_PBODY);
- if ( pb != 0 )
- {
- pb->SetState(STATE_CHECK, m_persoTab==1);
- }
-
- pl = (CLabel*)pw->SearchControl(EVENT_LABEL11);
- if ( pl != 0 )
- {
- if ( m_persoTab == 0 )
- {
- pl->SetState(STATE_VISIBLE);
- GetResource(RES_TEXT, RT_PERSO_FACE, name);
- pl->SetName(name);
- }
- else
- {
- pl->ClearState(STATE_VISIBLE);
- }
- }
-
- pl = (CLabel*)pw->SearchControl(EVENT_LABEL12);
- if ( pl != 0 )
- {
- if ( m_persoTab == 0 )
- {
- pl->SetState(STATE_VISIBLE);
- GetResource(RES_TEXT, RT_PERSO_GLASSES, name);
- pl->SetName(name);
- }
- else
- {
- pl->ClearState(STATE_VISIBLE);
- }
- }
-
- pl = (CLabel*)pw->SearchControl(EVENT_LABEL13);
- if ( pl != 0 )
- {
- if ( m_persoTab == 0 ) GetResource(RES_TEXT, RT_PERSO_HAIR, name);
- else GetResource(RES_TEXT, RT_PERSO_BAND, name);
- pl->SetName(name);
- }
-
- pl = (CLabel*)pw->SearchControl(EVENT_LABEL14);
- if ( pl != 0 )
- {
- if ( m_persoTab == 0 )
- {
- pl->ClearState(STATE_VISIBLE);
- }
- else
- {
- pl->SetState(STATE_VISIBLE);
- GetResource(RES_TEXT, RT_PERSO_COMBI, name);
- pl->SetName(name);
- }
- }
-
- for ( i=0 ; i<4 ; i++ )
- {
- pb = (CButton*)pw->SearchControl((EventMsg)(EVENT_INTERFACE_PFACE1+i));
- if ( pb == 0 ) break;
- pb->SetState(STATE_VISIBLE, m_persoTab==0);
- pb->SetState(STATE_CHECK, i==m_perso.face);
- }
-
- for ( i=0 ; i<10 ; i++ )
- {
- pb = (CButton*)pw->SearchControl((EventMsg)(EVENT_INTERFACE_PGLASS0+i));
- if ( pb == 0 ) break;
- pb->SetState(STATE_VISIBLE, m_persoTab==0);
- pb->SetState(STATE_CHECK, i==m_perso.glasses);
- }
-
- for ( i=0 ; i<3*3 ; i++ )
- {
- pc = (CColor*)pw->SearchControl((EventMsg)(EVENT_INTERFACE_PC0a+i));
- if ( pc == 0 ) break;
- if ( m_persoTab == 0 )
- {
- pc->ClearState(STATE_VISIBLE);
- }
- else
- {
- pc->SetState(STATE_VISIBLE);
- color.r = perso_color[3*10*1+3*i+0]/255.0f;
- color.g = perso_color[3*10*1+3*i+1]/255.0f;
- color.b = perso_color[3*10*1+3*i+2]/255.0f;
- color.a = 0.0f;
- pc->SetColor(color);
- pc->SetState(STATE_CHECK, EqColor(color, m_perso.colorCombi));
- }
-
- pc = (CColor*)pw->SearchControl((EventMsg)(EVENT_INTERFACE_PC0b+i));
- if ( pc == 0 ) break;
- color.r = perso_color[3*10*2*m_persoTab+3*i+0]/255.0f;
- color.g = perso_color[3*10*2*m_persoTab+3*i+1]/255.0f;
- color.b = perso_color[3*10*2*m_persoTab+3*i+2]/255.0f;
- color.a = 0.0f;
- pc->SetColor(color);
- pc->SetState(STATE_CHECK, EqColor(color, m_persoTab?m_perso.colorBand:m_perso.colorHair));
- }
-
- for ( i=0 ; i<3 ; i++ )
- {
- ps = (CSlider*)pw->SearchControl((EventMsg)(EVENT_INTERFACE_PCRa+i));
- if ( ps == 0 ) break;
- ps->SetState(STATE_VISIBLE, m_persoTab==1);
- }
-
- if ( m_persoTab == 1 )
- {
- color = m_perso.colorCombi;
- ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCRa);
- if ( ps != 0 ) ps->SetVisibleValue(color.r*255.0f);
- ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCGa);
- if ( ps != 0 ) ps->SetVisibleValue(color.g*255.0f);
- ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCBa);
- if ( ps != 0 ) ps->SetVisibleValue(color.b*255.0f);
- }
-
- if ( m_persoTab == 0 ) color = m_perso.colorHair;
- else color = m_perso.colorBand;
- ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCRb);
- if ( ps != 0 ) ps->SetVisibleValue(color.r*255.0f);
- ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCGb);
- if ( ps != 0 ) ps->SetVisibleValue(color.g*255.0f);
- ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCBb);
- if ( ps != 0 ) ps->SetVisibleValue(color.b*255.0f);
-}
-
-// Updates the camera for the character.
-
-void CMainDialog::CameraPerso()
-{
- if ( m_persoTab == 0 )
- {
-//? m_camera->Init(Math::Vector(4.0f, 0.0f, 0.0f),
-//? Math::Vector(0.0f, 0.0f, 1.0f), 0.0f);
- m_camera->Init(Math::Vector(6.0f, 0.0f, 0.0f),
- Math::Vector(0.0f, 0.2f, 1.5f), 0.0f);
- }
- else
- {
- m_camera->Init(Math::Vector(18.0f, 0.0f, 4.5f),
- Math::Vector(0.0f, 1.6f, 4.5f), 0.0f);
- }
-
- m_camera->SetType(CAMERA_SCRIPT);
- m_camera->FixCamera();
-}
-
-// Sets a fixed color.
-
-void CMainDialog::FixPerso(int rank, int index)
-{
- if ( m_persoTab == 0 )
- {
- if ( index == 1 )
- {
- m_perso.colorHair.r = perso_color[3*10*0+rank*3+0]/255.0f;
- m_perso.colorHair.g = perso_color[3*10*0+rank*3+1]/255.0f;
- m_perso.colorHair.b = perso_color[3*10*0+rank*3+2]/255.0f;
- }
- }
- if ( m_persoTab == 1 )
- {
- if ( index == 0 )
- {
- m_perso.colorCombi.r = perso_color[3*10*1+rank*3+0]/255.0f;
- m_perso.colorCombi.g = perso_color[3*10*1+rank*3+1]/255.0f;
- m_perso.colorCombi.b = perso_color[3*10*1+rank*3+2]/255.0f;
- }
- if ( index == 1 )
- {
- m_perso.colorBand.r = perso_color[3*10*2+rank*3+0]/255.0f;
- m_perso.colorBand.g = perso_color[3*10*2+rank*3+1]/255.0f;
- m_perso.colorBand.b = perso_color[3*10*2+rank*3+2]/255.0f;
- }
- }
-}
-
-// Updates the color of the character.
-
-void CMainDialog::ColorPerso()
-{
- CWindow* pw;
- CSlider* ps;
- D3DCOLORVALUE color;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
-
- color.a = 0.0f;
-
- ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCRa);
- if ( ps != 0 ) color.r = ps->RetVisibleValue()/255.0f;
- ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCGa);
- if ( ps != 0 ) color.g = ps->RetVisibleValue()/255.0f;
- ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCBa);
- if ( ps != 0 ) color.b = ps->RetVisibleValue()/255.0f;
- if ( m_persoTab == 1 ) m_perso.colorCombi = color;
-
- ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCRb);
- if ( ps != 0 ) color.r = ps->RetVisibleValue()/255.0f;
- ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCGb);
- if ( ps != 0 ) color.g = ps->RetVisibleValue()/255.0f;
- ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCBb);
- if ( ps != 0 ) color.b = ps->RetVisibleValue()/255.0f;
- if ( m_persoTab == 0 ) m_perso.colorHair = color;
- else m_perso.colorBand = color;
-}
-
-// Updates the default settings of the character.
-
-void CMainDialog::DefPerso()
-{
- m_perso.colorCombi.r = 206.0f/256.0f;
- m_perso.colorCombi.g = 206.0f/256.0f;
- m_perso.colorCombi.b = 204.0f/256.0f; // ~white
- m_perso.colorBand.r = 255.0f/256.0f;
- m_perso.colorBand.g = 132.0f/256.0f;
- m_perso.colorBand.b = 1.0f/256.0f; // orange
-
- if ( m_perso.face == 0 ) // normal ?
- {
- m_perso.glasses = 0;
- m_perso.colorHair.r = 90.0f/256.0f;
- m_perso.colorHair.g = 95.0f/256.0f;
- m_perso.colorHair.b = 85.0f/256.0f; // black
- }
- if ( m_perso.face == 1 ) // bald ?
- {
- m_perso.glasses = 0;
- m_perso.colorHair.r = 83.0f/256.0f;
- m_perso.colorHair.g = 64.0f/256.0f;
- m_perso.colorHair.b = 51.0f/256.0f; // brown
- }
- if ( m_perso.face == 2 ) // carlos ?
- {
- m_perso.glasses = 1;
- m_perso.colorHair.r = 85.0f/256.0f;
- m_perso.colorHair.g = 48.0f/256.0f;
- m_perso.colorHair.b = 9.0f/256.0f; // brown
- }
- if ( m_perso.face == 3 ) // blond ?
- {
- m_perso.glasses = 4;
- m_perso.colorHair.r = 255.0f/256.0f;
- m_perso.colorHair.g = 255.0f/256.0f;
- m_perso.colorHair.b = 181.0f/256.0f; // yellow
- }
-
- m_perso.colorHair.a = 0.0f;
- m_perso.colorCombi.a = 0.0f;
- m_perso.colorBand.a = 0.0f;
-}
-
-
-// Indicates if there is at least one backup.
-
-bool CMainDialog::IsIOReadScene()
-{
- FILE* file;
- char filename[100];
-
- sprintf(filename, "%s\\%s\\save%c%.3d\\data.sav", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], 0);
- file = fopen(filename, "r");
- if ( file == NULL ) return false;
- fclose(file);
- return true;
-}
-
-// Builds the file name by default.
-
-void CMainDialog::IOReadName()
-{
- FILE* file;
- CWindow* pw;
- CEdit* pe;
- char filename[_MAX_FNAME];
- char op[100];
- char line[500];
- char resume[100];
- char name[100];
- time_t now;
- int i;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_IONAME);
- if ( pe == 0 ) return;
-
- sprintf(resume, "%s %d", m_sceneName, m_chap[m_index]+1);
- BuildSceneName(filename, m_sceneName, (m_chap[m_index]+1)*100);
- file = fopen(filename, "r");
- if ( file != NULL )
- {
- while ( fgets(line, 500, file) != NULL )
- {
- for ( i=0 ; i<500 ; i++ )
- {
- if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space
- if ( line[i] == '/' && line[i+1] == '/' )
- {
- line[i] = 0;
- break;
- }
- }
-
- sprintf(op, "Title.%c", RetLanguageLetter());
- if ( Cmd(line, op) )
- {
- OpString(line, "resume", resume);
- break;
- }
- }
- fclose(file);
- }
-
- time(&now);
- TimeToAscii(now, line);
- sprintf(name, "%s %d - %s", resume, m_sel[m_index]+1, line);
- pe->SetText(name);
- pe->SetCursor(strlen(name), 0);
- pe->SetFocus(true);
-}
-
-// Updates the list of games recorded on disk.
-
-void CMainDialog::IOReadList()
-{
- FILE* file = NULL;
- CWindow* pw;
- CList* pl;
- char filename[100];
- char line[500];
- char name[100];
- int i, j;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pl = (CList*)pw->SearchControl(EVENT_INTERFACE_IOLIST);
- if ( pl == 0 ) return;
-
- pl->Flush();
-
- for ( j=0 ; j<999 ; j++ )
- {
- sprintf(filename, "%s\\%s\\save%c%.3d\\data.sav", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], j);
- file = fopen(filename, "r");
- if ( file == NULL ) break;
-
- strcmp(name, filename); // default name
- while ( fgets(line, 500, file) != NULL )
- {
- for ( i=0 ; i<500 ; i++ )
- {
- if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space
- if ( line[i] == '/' && line[i+1] == '/' )
- {
- line[i] = 0;
- break;
- }
- }
-
- if ( Cmd(line, "Title") )
- {
- OpString(line, "text", name);
- break;
- }
- }
- fclose(file);
-
- pl->SetName(j, name);
- }
-
- if ( m_phase == PHASE_WRITE ||
- m_phase == PHASE_WRITEs )
- {
- GetResource(RES_TEXT, RT_IO_NEW, name);
- pl->SetName(j, name);
- j ++;
- }
-
- pl->SetSelect(j-1);
- pl->ShowSelect(false); // shows the selected columns
-}
-
-// Updates the buttons according to the selected part in the list.
-
-void CMainDialog::IOUpdateList()
-{
- FILE* file = NULL;
- CWindow* pw;
- CList* pl;
- CButton* pb;
- CImage* pi;
- char filename[100];
- int sel, max;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pl = (CList*)pw->SearchControl(EVENT_INTERFACE_IOLIST);
- if ( pl == 0 ) return;
- pi = (CImage*)pw->SearchControl(EVENT_INTERFACE_IOIMAGE);
- if ( pi == 0 ) return;
-
- sel = pl->RetSelect();
- max = pl->RetTotal();
-
- sprintf(filename, "%s\\%s\\save%c%.3d\\screen.bmp", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
-
- if ( m_phase == PHASE_WRITE ||
- m_phase == PHASE_WRITEs )
- {
- if ( sel < max-1 )
- {
- pi->SetFilenameImage(filename);
- }
- else
- {
- pi->SetFilenameImage("");
- }
-
- pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_IODELETE);
- if ( pb != 0 )
- {
- pb->SetState(STATE_ENABLE, sel < max-1);
- }
- }
- else
- {
- pi->SetFilenameImage(filename);
- }
-}
-
-// Deletes the selected scene.
-
-void CMainDialog::IODeleteScene()
-{
- CWindow* pw;
- CList* pl;
- char dir[100];
- char old[100];
- long hFile;
- struct _finddata_t fBuffer;
- int sel, max, i;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pl = (CList*)pw->SearchControl(EVENT_INTERFACE_IOLIST);
- if ( pl == 0 ) return;
-
- sel = pl->RetSelect();
- if ( sel == -1 )
- {
- m_sound->Play(SOUND_TZOING);
- return;
- }
-
- // Deletes all the contents of the file.
- sprintf(dir, "%s\\%s\\save%c%.3d\\*", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
- hFile = _findfirst(dir, &fBuffer);
- if ( hFile != -1 )
- {
- do
- {
- if ( fBuffer.name[0] != '.' )
- {
- sprintf(dir, "%s\\%s\\save%c%.3d\\%s", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel, fBuffer.name);
- remove(dir);
- }
- }
- while ( _findnext(hFile, &fBuffer) == 0 );
- }
-
- sprintf(dir, "%s\\%s\\save%c%.3d", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
- if ( _rmdir(dir) != 0 )
- {
- m_sound->Play(SOUND_TZOING);
- return;
- }
-
- max = pl->RetTotal();
- for ( i=sel+1 ; i<max ; i++ )
- {
- sprintf(old, "%s\\%s\\save%c%.3d", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], i);
- sprintf(dir, "%s\\%s\\save%c%.3d", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], i-1);
- rename(old, dir);
- }
- IOReadList();
-}
-
-// Writes the scene.
-
-bool CMainDialog::IOWriteScene()
-{
- CWindow* pw;
- CList* pl;
- CEdit* pe;
- char filename[100];
- char filecbot[100];
- char info[100];
- int sel;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return false;
- pl = (CList*)pw->SearchControl(EVENT_INTERFACE_IOLIST);
- if ( pl == 0 ) return false;
- pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_IONAME);
- if ( pe == 0 ) return false;
-
- sel = pl->RetSelect();
- if ( sel == -1 ) return false;
-
- _mkdir("Savegame"); // if doesn't exist yet!
- sprintf(filename, "%s\\%s", m_savegameDir, m_main->RetGamerName());
- _mkdir(filename);
- sprintf(filename, "%s\\%s\\save%c%.3d", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
- _mkdir(filename);
-
- sprintf(filename, "%s\\%s\\save%c%.3d\\data.sav", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
- sprintf(filecbot, "%s\\%s\\save%c%.3d\\cbot.run", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
- pe->GetText(info, 100);
- m_main->IOWriteScene(filename, filecbot, info);
-
- m_shotDelay = 3;
- sprintf(m_shotName, "%s\\%s\\save%c%.3d\\screen.bmp", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
-
- return true;
-}
-
-// Reads the scene.
-
-bool CMainDialog::IOReadScene()
-{
- FILE* file;
- CWindow* pw;
- CList* pl;
- char filename[100];
- char filecbot[100];
- char line[500];
- char dir[100];
- int sel, i;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return false;
- pl = (CList*)pw->SearchControl(EVENT_INTERFACE_IOLIST);
- if ( pl == 0 ) return false;
-
- sel = pl->RetSelect();
- if ( sel == -1 ) return false;
-
- sprintf(filename, "%s\\%s\\save%c%.3d\\data.sav", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
- sprintf(filecbot, "%s\\%s\\save%c%.3d\\cbot.run", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
-
- file = fopen(filename, "r");
- if ( file == NULL ) return false;
-
- while ( fgets(line, 500, file) != NULL )
- {
- for ( i=0 ; i<500 ; i++ )
- {
- if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space
- if ( line[i] == '/' && line[i+1] == '/' )
- {
- line[i] = 0;
- break;
- }
- }
-
- if ( Cmd(line, "Mission") )
- {
- OpString(line, "base", m_sceneName);
- m_sceneRank = OpInt(line, "rank", 0);
-
- if ( strcmp(m_sceneName, "user") == 0 )
- {
- m_sceneRank = m_sceneRank%100;
- OpString(line, "dir", dir);
- for ( i=0 ; i<m_userTotal ; i++ )
- {
- if ( strcmp(m_userList[i], dir) == 0 )
- {
- m_sceneRank += (i+1)*100;
- break;
- }
- }
- if ( m_sceneRank/100 == 0 )
- {
- fclose(file);
- return false;
- }
- }
- }
- }
- fclose(file);
-
- m_chap[m_index] = (m_sceneRank/100)-1;
- m_sel[m_index] = (m_sceneRank%100)-1;
-
- strcpy(m_sceneRead, filename);
- strcpy(m_stackRead, filecbot);
- return true;
-}
-
-
-// Returns the number of accessible chapters.
-
-int CMainDialog::RetChapPassed()
-{
- int j;
-
- if ( m_main->RetShowAll() ) return 9;
-
- for ( j=0 ; j<9 ; j++ )
- {
- if ( !RetGamerInfoPassed((j+1)*100) )
- {
- return j;
- }
- }
- return 9;
-}
-
-// Updates the lists according to the cheat code.
-
-void CMainDialog::AllMissionUpdate()
-{
- if ( m_phase == PHASE_TRAINER ||
- m_phase == PHASE_DEFI ||
- m_phase == PHASE_MISSION ||
- m_phase == PHASE_FREE ||
- m_phase == PHASE_TEEN ||
- m_phase == PHASE_USER ||
- m_phase == PHASE_PROTO )
- {
- UpdateSceneChap(m_chap[m_index]);
- UpdateSceneList(m_chap[m_index], m_sel[m_index]);
- }
-}
-
-// Updates the chapters of exercises or missions.
-
-void CMainDialog::UpdateSceneChap(int &chap)
-{
- FILE* file = NULL;
- CWindow* pw;
- CList* pl;
- long hFile;
- struct _finddata_t fileBuffer;
- char filename[_MAX_FNAME];
- char op[100];
- char line[500];
- char name[100];
- int i, j;
- bool bPassed, bDo;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pl = (CList*)pw->SearchControl(EVENT_INTERFACE_CHAP);
- if ( pl == 0 ) return;
-
- pl->Flush();
-
- if ( m_phase == PHASE_USER )
- {
- j = 0;
- hFile = _findfirst("user\\*", &fileBuffer);
- if ( hFile != -1 )
- {
- do
- {
- if ( (fileBuffer.attrib & _A_SUBDIR) != 0 &&
- fileBuffer.name[0] != '.' )
- {
- strcpy(m_userList[j++], fileBuffer.name);
- }
- }
- while ( _findnext(hFile, &fileBuffer) == 0 && j < 100 );
- }
- m_userTotal = j;
-
- do // sorts all names:
- {
- bDo = false;
- for ( i=0 ; i<m_userTotal-1 ; i++ )
- {
- if ( strcmp(m_userList[i], m_userList[i+1]) > 0 )
- {
- strcpy(name, m_userList[i]);
- strcpy(m_userList[i], m_userList[i+1]);
- strcpy(m_userList[i+1], name);
- bDo = true;
- }
- }
- }
- while ( bDo );
-
- for ( j=0 ; j<m_userTotal ; j++ )
- {
- BuildSceneName(filename, m_sceneName, (j+1)*100);
- file = fopen(filename, "r");
- if ( file == NULL )
- {
- strcpy(name, m_userList[j]);
- }
- else
- {
- BuildResumeName(name, m_sceneName, j+1); // default name
- while ( fgets(line, 500, file) != NULL )
- {
- for ( i=0 ; i<500 ; i++ )
- {
- if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space
- if ( line[i] == '/' && line[i+1] == '/' )
- {
- line[i] = 0;
- break;
- }
- }
-
- sprintf(op, "Title.%c", RetLanguageLetter());
- if ( Cmd(line, op) )
- {
- OpString(line, "text", name);
- break;
- }
- }
- fclose(file);
- }
-
- pl->SetName(j, name);
- pl->SetEnable(j, true);
- }
- }
- else
- {
- for ( j=0 ; j<9 ; j++ )
- {
-#if _SCHOOL
- if ( m_phase == PHASE_MISSION ) break;
- if ( m_phase == PHASE_FREE ) break;
-#if _CEEBOTDEMO
- if ( m_phase == PHASE_TRAINER && j >= 2 ) break;
-#endif
-#endif
-#if _DEMO
- if ( m_phase == PHASE_MISSION && j >= 4 ) break;
- if ( m_phase == PHASE_TRAINER && j >= 1 ) break;
-#endif
- BuildSceneName(filename, m_sceneName, (j+1)*100);
- file = fopen(filename, "r");
- if ( file == NULL ) break;
-
- BuildResumeName(name, m_sceneName, j+1); // default name
- while ( fgets(line, 500, file) != NULL )
- {
- for ( i=0 ; i<500 ; i++ )
- {
- if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space
- if ( line[i] == '/' && line[i+1] == '/' )
- {
- line[i] = 0;
- break;
- }
- }
-
- sprintf(op, "Title.%c", RetLanguageLetter());
- if ( Cmd(line, op) )
- {
- OpString(line, "text", name);
- break;
- }
- }
- fclose(file);
-
- bPassed = RetGamerInfoPassed((j+1)*100);
- sprintf(line, "%d: %s", j+1, name);
- pl->SetName(j, line);
- pl->SetCheck(j, bPassed);
- pl->SetEnable(j, true);
-
- if ( m_phase == PHASE_MISSION && !m_main->RetShowAll() && !bPassed )
- {
- j ++;
- break;
- }
-
-#if _TEEN
- if ( m_phase == PHASE_TRAINER && !m_main->RetShowAll() && !bPassed )
- {
- j ++;
- break;
- }
-#endif
-
- if ( m_phase == PHASE_FREE && j == m_accessChap )
- {
- j ++;
- break;
- }
- }
- }
-
- if ( chap > j-1 ) chap = j-1;
-
- pl->SetSelect(chap);
- pl->ShowSelect(false); // shows the selected columns
-}
-
-// Updates the list of exercises or missions.
-
-void CMainDialog::UpdateSceneList(int chap, int &sel)
-{
- FILE* file = NULL;
- CWindow* pw;
- CList* pl;
- char filename[_MAX_FNAME];
- char op[100];
- char line[500];
- char name[100];
- int i, j;
- bool bPassed;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pl = (CList*)pw->SearchControl(EVENT_INTERFACE_LIST);
- if ( pl == 0 ) return;
-
- pl->Flush();
-
- for ( j=0 ; j<99 ; j++ )
- {
-#if _SCHOOL
- if ( m_phase == PHASE_MISSION ) break;
- if ( m_phase == PHASE_FREE ) break;
-#if _CEEBOTDEMO
-#if _TEEN
- if ( m_phase == PHASE_TRAINER && j >= 5 ) break;
-#else
- if ( m_phase == PHASE_TRAINER && j >= 3 ) break;
-#endif
-#endif
-#endif
-#if _DEMO
- if ( m_phase == PHASE_MISSION && j >= 3 ) break;
- if ( m_phase == PHASE_TRAINER && j >= 5 ) break;
-#endif
- BuildSceneName(filename, m_sceneName, (chap+1)*100+(j+1));
- file = fopen(filename, "r");
- if ( file == NULL ) break;
-
- BuildResumeName(name, m_sceneName, j+1); // default name
- while ( fgets(line, 500, file) != NULL )
- {
- for ( i=0 ; i<500 ; i++ )
- {
- if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space
- if ( line[i] == '/' && line[i+1] == '/' )
- {
- line[i] = 0;
- break;
- }
- }
-
- sprintf(op, "Title.%c", RetLanguageLetter());
- if ( Cmd(line, op) )
- {
- OpString(line, "text", name);
- break;
- }
- }
- fclose(file);
-
- bPassed = RetGamerInfoPassed((chap+1)*100+(j+1));
- sprintf(line, "%d: %s", j+1, name);
- pl->SetName(j, line);
- pl->SetCheck(j, bPassed);
- pl->SetEnable(j, true);
-
- if ( m_phase == PHASE_MISSION && !m_main->RetShowAll() && !bPassed )
- {
- j ++;
- break;
- }
-
-#if _TEEN
- if ( m_phase == PHASE_TRAINER && !m_main->RetShowAll() && !bPassed )
- {
- j ++;
- break;
- }
-#endif
- }
-
- BuildSceneName(filename, m_sceneName, (chap+1)*100+(j+1));
- file = fopen(filename, "r");
- if ( file == NULL )
- {
- m_maxList = j;
- }
- else
- {
- m_maxList = j+1; // this is not the last!
- fclose(file);
- }
-
- if ( sel > j-1 ) sel = j-1;
-
- pl->SetSelect(sel);
- pl->ShowSelect(false); // shows the selected columns
-}
-
-// Updates the button "solution" according to cheat code.
-
-void CMainDialog::ShowSoluceUpdate()
-{
- CWindow* pw;
- CEdit* pe;
- CCheck* pc;
-
- if ( m_phase == PHASE_TRAINER ||
- m_phase == PHASE_DEFI ||
- m_phase == PHASE_MISSION ||
- m_phase == PHASE_FREE ||
- m_phase == PHASE_TEEN ||
- m_phase == PHASE_USER ||
- m_phase == PHASE_PROTO )
- {
- m_bSceneSoluce = false;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_RESUME);
- if ( pe == 0 ) return;
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_SOLUCE);
- if ( pc == 0 ) return;
-
- if ( m_main->RetShowSoluce() )
- {
- pc->SetState(STATE_VISIBLE);
- pc->SetState(STATE_CHECK);
- m_bSceneSoluce = true;
- }
- else
- {
- pc->ClearState(STATE_VISIBLE);
- pc->ClearState(STATE_CHECK);
- m_bSceneSoluce = false;
- }
- }
-}
-
-// Updates a summary of exercise or mission.
-
-void CMainDialog::UpdateSceneResume(int rank)
-{
- FILE* file = NULL;
- CWindow* pw;
- CEdit* pe;
- CCheck* pc;
- char filename[_MAX_FNAME];
- char op[100];
- char line[500];
- char name[500];
- int i, numTry;
- bool bPassed, bVisible;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_RESUME);
- if ( pe == 0 ) return;
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_SOLUCE);
-
- if ( pc == 0 )
- {
- m_bSceneSoluce = false;
- }
- else
- {
- numTry = RetGamerInfoTry(rank);
- bPassed = RetGamerInfoPassed(rank);
- bVisible = ( numTry > 2 || bPassed || m_main->RetShowSoluce() );
- if ( !RetSoluce4() ) bVisible = false;
- pc->SetState(STATE_VISIBLE, bVisible);
- if ( !bVisible )
- {
- pc->ClearState(STATE_CHECK);
- m_bSceneSoluce = false;
- }
- }
-
- BuildSceneName(filename, m_sceneName, rank);
- file = fopen(filename, "r");
- if ( file == NULL ) return;
-
- name[0] = 0;
- while ( fgets(line, 500, file) != NULL )
- {
- for ( i=0 ; i<500 ; i++ )
- {
- if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space
- if ( line[i] == '/' && line[i+1] == '/' )
- {
- line[i] = 0;
- break;
- }
- }
-
- sprintf(op, "Resume.%c", RetLanguageLetter());
- if ( Cmd(line, op) )
- {
- OpString(line, "text", name);
- break;
- }
- }
- fclose(file);
-
- pe->SetText(name);
-}
-
-// Updates the list of devices.
-
-void CMainDialog::UpdateDisplayDevice()
-{
- CWindow* pw;
- CList* pl;
- char bufDevices[1000];
- char bufModes[5000];
- int i, j, totalDevices, selectDevices, totalModes, selectModes;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pl = (CList*)pw->SearchControl(EVENT_LIST1);
- if ( pl == 0 ) return;
- pl->Flush();
-
- m_engine->EnumDevices(bufDevices, 1000,
- bufModes, 5000,
- totalDevices, selectDevices,
- totalModes, selectModes);
-
- i = 0;
- j = 0;
- while ( bufDevices[i] != 0 )
- {
- pl->SetName(j++, bufDevices+i);
- while ( bufDevices[i++] != 0 );
- }
-
- pl->SetSelect(selectDevices);
- pl->ShowSelect(false);
-
- m_setupSelDevice = selectDevices;
-}
-
-// Updates the list of modes.
-
-void CMainDialog::UpdateDisplayMode()
-{
- CWindow* pw;
- CList* pl;
- char bufDevices[1000];
- char bufModes[5000];
- int i, j, totalDevices, selectDevices, totalModes, selectModes;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
- pl = (CList*)pw->SearchControl(EVENT_LIST2);
- if ( pl == 0 ) return;
- pl->Flush();
-
- m_engine->EnumDevices(bufDevices, 1000,
- bufModes, 5000,
- totalDevices, selectDevices,
- totalModes, selectModes);
-
- i = 0;
- j = 0;
- while ( bufModes[i] != 0 )
- {
- pl->SetName(j++, bufModes+i);
- while ( bufModes[i++] != 0 );
- }
-
- pl->SetSelect(selectModes);
- pl->ShowSelect(false);
-
- m_setupSelMode = selectModes;
-}
-
-// Change the graphics mode.
-
-void CMainDialog::ChangeDisplay()
-{
- CWindow* pw;
- CList* pl;
- CCheck* pc;
- char* device;
- char* mode;
- bool bFull;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
-
- pl = (CList*)pw->SearchControl(EVENT_LIST1);
- if ( pl == 0 ) return;
- m_setupSelDevice = pl->RetSelect();
- device = pl->RetName(m_setupSelDevice);
-
- pl = (CList*)pw->SearchControl(EVENT_LIST2);
- if ( pl == 0 ) return;
- m_setupSelMode = pl->RetSelect();
- mode = pl->RetName(m_setupSelMode);
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_FULL);
- if ( pc == 0 ) return;
- bFull = pc->TestState(STATE_CHECK);
- m_setupFull = bFull;
-
- m_engine->ChangeDevice(device, mode, bFull);
-
- if ( m_bSimulSetup )
- {
- m_main->ChangeColor();
- m_main->UpdateMap();
- }
-}
-
-
-
-// Updates the "apply" button.
-
-void CMainDialog::UpdateApply()
-{
- CWindow* pw;
- CButton* pb;
- CList* pl;
- CCheck* pc;
- int sel1, sel2;
- bool bFull;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
-
- pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_APPLY);
- if ( pb == 0 ) return;
-
- pl = (CList*)pw->SearchControl(EVENT_LIST1);
- if ( pl == 0 ) return;
- sel1 = pl->RetSelect();
-
- pl = (CList*)pw->SearchControl(EVENT_LIST2);
- if ( pl == 0 ) return;
- sel2 = pl->RetSelect();
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_FULL);
- bFull = pc->TestState(STATE_CHECK);
-
- if ( sel1 == m_setupSelDevice &&
- sel2 == m_setupSelMode &&
- bFull == m_setupFull )
- {
- pb->ClearState(STATE_ENABLE);
- }
- else
- {
- pb->SetState(STATE_ENABLE);
- }
-}
-
-// Updates the buttons during the setup phase.
-
-void CMainDialog::UpdateSetupButtons()
-{
- CWindow* pw;
- CCheck* pc;
- CEditValue* pv;
- CSlider* ps;
- float value;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_TOTO);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_engine->RetTotoMode());
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_TOOLTIP);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_bTooltip);
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_GLINT);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_bGlint);
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_RAIN);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_bRain);
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_MOUSE);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_engine->RetNiceMouse());
- pc->SetState(STATE_ENABLE, m_engine->RetNiceMouseCap());
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_EDITMODE);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_engine->RetEditIndentMode());
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_EDITVALUE);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_engine->RetEditIndentValue()>2);
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_SOLUCE4);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_bSoluce4);
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_MOVIES);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_bMovies);
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_NICERST);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_bNiceReset);
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_HIMSELF);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_bHimselfDamage);
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_SCROLL);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_bCameraScroll);
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_INVERTX);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_bCameraInvertX);
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_INVERTY);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_bCameraInvertY);
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_EFFECT);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_bEffect);
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_SHADOW);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_engine->RetShadow());
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_GROUND);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_engine->RetGroundSpot());
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_DIRTY);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_engine->RetDirty());
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_FOG);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_engine->RetFog());
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_LENS);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_engine->RetLensMode());
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_SKY);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_engine->RetSkyMode());
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_PLANET);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_engine->RetPlanetMode());
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_LIGHT);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_engine->RetLightMode());
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_JOYSTICK);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_engine->RetJoystick());
- }
-
- pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_PARTI);
- if ( pv != 0 )
- {
- value = m_engine->RetParticuleDensity();
- pv->SetValue(value);
- }
-
- pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_CLIP);
- if ( pv != 0 )
- {
- value = m_engine->RetClippingDistance();
- pv->SetValue(value);
- }
-
- pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_DETAIL);
- if ( pv != 0 )
- {
- value = m_engine->RetObjectDetail();
- pv->SetValue(value);
- }
-
- pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_GADGET);
- if ( pv != 0 )
- {
- value = m_engine->RetGadgetQuantity();
- pv->SetValue(value);
- }
-
- pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_TEXTURE);
- if ( pv != 0 )
- {
- value = (float)m_engine->RetTextureQuality();
- pv->SetValue(value);
- }
-
- ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_VOLSOUND);
- if ( ps != 0 )
- {
- value = (float)m_sound->RetAudioVolume();
- ps->SetVisibleValue(value);
- }
-
- ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_VOLMUSIC);
- if ( ps != 0 )
- {
- value = (float)m_sound->RetMidiVolume();
- ps->SetVisibleValue(value);
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_SOUND3D);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_sound->RetSound3D());
- pc->SetState(STATE_ENABLE, m_sound->RetSound3DCap());
- }
-}
-
-// Updates the engine function of the buttons after the setup phase.
-
-void CMainDialog::ChangeSetupButtons()
-{
- CWindow* pw;
- CEditValue* pv;
- CSlider* ps;
- float value;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
-
- pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_PARTI);
- if ( pv != 0 )
- {
- value = pv->RetValue();
- m_engine->SetParticuleDensity(value);
- }
-
- pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_CLIP);
- if ( pv != 0 )
- {
- value = pv->RetValue();
- m_engine->SetClippingDistance(value);
- }
-
- pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_DETAIL);
- if ( pv != 0 )
- {
- value = pv->RetValue();
- m_engine->SetObjectDetail(value);
- }
-
- pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_GADGET);
- if ( pv != 0 )
- {
- value = pv->RetValue();
- m_engine->SetGadgetQuantity(value);
- }
-
- pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_TEXTURE);
- if ( pv != 0 )
- {
- value = pv->RetValue();
- m_engine->SetTextureQuality((int)value);
- }
-
- ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_VOLSOUND);
- if ( ps != 0 )
- {
- value = ps->RetVisibleValue();
- m_sound->SetAudioVolume((int)value);
- }
-
- ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_VOLMUSIC);
- if ( ps != 0 )
- {
- value = ps->RetVisibleValue();
- m_sound->SetMidiVolume((int)value);
- }
-}
-
-
-// Memorizes all the settings.
-
-void CMainDialog::SetupMemorize()
-{
- float fValue;
- int iValue, i, j;
- char key[500];
- char num[10];
-
- SetProfileString("Directory", "scene", m_sceneDir);
- SetProfileString("Directory", "savegame", m_savegameDir);
- SetProfileString("Directory", "public", m_publicDir);
- SetProfileString("Directory", "user", m_userDir);
- SetProfileString("Directory", "files", m_filesDir);
-
- iValue = m_engine->RetTotoMode();
- SetProfileInt("Setup", "TotoMode", iValue);
-
- iValue = m_bTooltip;
- SetProfileInt("Setup", "Tooltips", iValue);
-
- iValue = m_bGlint;
- SetProfileInt("Setup", "InterfaceGlint", iValue);
-
- iValue = m_bRain;
- SetProfileInt("Setup", "InterfaceGlint", iValue);
-
- iValue = m_engine->RetNiceMouse();
- SetProfileInt("Setup", "NiceMouse", iValue);
-
- iValue = m_bSoluce4;
- SetProfileInt("Setup", "Soluce4", iValue);
-
- iValue = m_bMovies;
- SetProfileInt("Setup", "Movies", iValue);
-
- iValue = m_bNiceReset;
- SetProfileInt("Setup", "NiceReset", iValue);
-
- iValue = m_bHimselfDamage;
- SetProfileInt("Setup", "HimselfDamage", iValue);
-
- iValue = m_bCameraScroll;
- SetProfileInt("Setup", "CameraScroll", iValue);
-
- iValue = m_bCameraInvertX;
- SetProfileInt("Setup", "CameraInvertX", iValue);
-
- iValue = m_bEffect;
- SetProfileInt("Setup", "InterfaceEffect", iValue);
-
- iValue = m_engine->RetShadow();
- SetProfileInt("Setup", "GroundShadow", iValue);
-
- iValue = m_engine->RetGroundSpot();
- SetProfileInt("Setup", "GroundSpot", iValue);
-
- iValue = m_engine->RetDirty();
- SetProfileInt("Setup", "ObjectDirty", iValue);
-
- iValue = m_engine->RetFog();
- SetProfileInt("Setup", "FogMode", iValue);
-
- iValue = m_engine->RetLensMode();
- SetProfileInt("Setup", "LensMode", iValue);
-
- iValue = m_engine->RetSkyMode();
- SetProfileInt("Setup", "SkyMode", iValue);
-
- iValue = m_engine->RetPlanetMode();
- SetProfileInt("Setup", "PlanetMode", iValue);
-
- iValue = m_engine->RetLightMode();
- SetProfileInt("Setup", "LightMode", iValue);
-
- iValue = m_engine->RetJoystick();
- SetProfileInt("Setup", "UseJoystick", iValue);
-
- fValue = m_engine->RetParticuleDensity();
- SetProfileFloat("Setup", "ParticuleDensity", fValue);
-
- fValue = m_engine->RetClippingDistance();
- SetProfileFloat("Setup", "ClippingDistance", fValue);
-
- fValue = m_engine->RetObjectDetail();
- SetProfileFloat("Setup", "ObjectDetail", fValue);
-
- fValue = m_engine->RetGadgetQuantity();
- SetProfileFloat("Setup", "GadgetQuantity", fValue);
-
- iValue = m_engine->RetTextureQuality();
- SetProfileInt("Setup", "TextureQuality", iValue);
-
- iValue = m_sound->RetAudioVolume();
- SetProfileInt("Setup", "AudioVolume", iValue);
-
- iValue = m_sound->RetMidiVolume();
- SetProfileInt("Setup", "MidiVolume", iValue);
-
- iValue = m_sound->RetSound3D();
- SetProfileInt("Setup", "Sound3D", iValue);
-
- iValue = m_engine->RetEditIndentMode();
- SetProfileInt("Setup", "EditIndentMode", iValue);
-
- iValue = m_engine->RetEditIndentValue();
- SetProfileInt("Setup", "EditIndentValue", iValue);
-
- key[0] = 0;
- for ( i=0 ; i<100 ; i++ )
- {
- if ( m_engine->RetKey(i, 0) == 0 ) break;
-
- for ( j=0 ; j<2 ; j++ )
- {
- iValue = m_engine->RetKey(i, j);
- sprintf(num, "%d%c", iValue, j==0?'+':' ');
- strcat(key, num);
- }
- }
- SetProfileString("Setup", "KeyMap", key);
-
-#if _NET
- if ( m_accessEnable )
- {
- iValue = m_accessMission;
- SetProfileInt("Setup", "AccessMission", iValue);
-
- iValue = m_accessUser;
- SetProfileInt("Setup", "AccessUser", iValue);
- }
-#endif
-
- iValue = m_bDeleteGamer;
- SetProfileInt("Setup", "DeleteGamer", iValue);
-
- m_engine->WriteProfile();
-}
-
-// Remember all the settings.
-
-void CMainDialog::SetupRecall()
-{
- float fValue;
- int iValue, i, j;
- char key[500];
- char* p;
-
- if ( GetProfileString("Directory", "scene", key, _MAX_FNAME) )
- {
- strcpy(m_sceneDir, key);
- }
-
- if ( GetProfileString("Directory", "savegame", key, _MAX_FNAME) )
- {
- strcpy(m_savegameDir, key);
- }
-
- if ( GetProfileString("Directory", "public", key, _MAX_FNAME) )
- {
- strcpy(m_publicDir, key);
- }
-
- if ( GetProfileString("Directory", "user", key, _MAX_FNAME) )
- {
- strcpy(m_userDir, key);
- }
-
- if ( GetProfileString("Directory", "files", key, _MAX_FNAME) )
- {
- strcpy(m_filesDir, key);
- }
-
-
- if ( GetProfileInt("Setup", "TotoMode", iValue) )
- {
- m_engine->SetTotoMode(iValue);
- }
-
- if ( GetProfileInt("Setup", "Tooltips", iValue) )
- {
- m_bTooltip = iValue;
- }
-
- if ( GetProfileInt("Setup", "InterfaceGlint", iValue) )
- {
- m_bGlint = iValue;
- }
-
- if ( GetProfileInt("Setup", "InterfaceGlint", iValue) )
- {
- m_bRain = iValue;
- }
-
- if ( GetProfileInt("Setup", "NiceMouse", iValue) )
- {
- m_engine->SetNiceMouse(iValue);
- }
-
- if ( GetProfileInt("Setup", "Soluce4", iValue) )
- {
- m_bSoluce4 = iValue;
- }
-
- if ( GetProfileInt("Setup", "Movies", iValue) )
- {
- m_bMovies = iValue;
- }
-
- if ( GetProfileInt("Setup", "NiceReset", iValue) )
- {
- m_bNiceReset = iValue;
- }
-
- if ( GetProfileInt("Setup", "HimselfDamage", iValue) )
- {
- m_bHimselfDamage = iValue;
- }
-
- if ( GetProfileInt("Setup", "CameraScroll", iValue) )
- {
- m_bCameraScroll = iValue;
- m_camera->SetCameraScroll(m_bCameraScroll);
- }
-
- if ( GetProfileInt("Setup", "CameraInvertX", iValue) )
- {
- m_bCameraInvertX = iValue;
- m_camera->SetCameraInvertX(m_bCameraInvertX);
- }
-
- if ( GetProfileInt("Setup", "CameraInvertY", iValue) )
- {
- m_bCameraInvertY = iValue;
- m_camera->SetCameraInvertY(m_bCameraInvertY);
- }
-
- if ( GetProfileInt("Setup", "InterfaceEffect", iValue) )
- {
- m_bEffect = iValue;
- }
-
- if ( GetProfileInt("Setup", "GroundShadow", iValue) )
- {
- m_engine->SetShadow(iValue);
- }
-
- if ( GetProfileInt("Setup", "GroundSpot", iValue) )
- {
- m_engine->SetGroundSpot(iValue);
- }
-
- if ( GetProfileInt("Setup", "ObjectDirty", iValue) )
- {
- m_engine->SetDirty(iValue);
- }
-
- if ( GetProfileInt("Setup", "FogMode", iValue) )
- {
- m_engine->SetFog(iValue);
- m_camera->SetOverBaseColor(RetColor(RetColor(0.0f)));
- }
-
- if ( GetProfileInt("Setup", "LensMode", iValue) )
- {
- m_engine->SetLensMode(iValue);
- }
-
- if ( GetProfileInt("Setup", "SkyMode", iValue) )
- {
- m_engine->SetSkyMode(iValue);
- }
-
- if ( GetProfileInt("Setup", "PlanetMode", iValue) )
- {
- m_engine->SetPlanetMode(iValue);
- }
-
- if ( GetProfileInt("Setup", "LightMode", iValue) )
- {
- m_engine->SetLightMode(iValue);
- }
-
- if ( GetProfileInt("Setup", "UseJoystick", iValue) )
- {
- m_engine->SetJoystick(iValue);
- }
-
- if ( GetProfileFloat("Setup", "ParticuleDensity", fValue) )
- {
- m_engine->SetParticuleDensity(fValue);
- }
-
- if ( GetProfileFloat("Setup", "ClippingDistance", fValue) )
- {
- m_engine->SetClippingDistance(fValue);
- }
-
- if ( GetProfileFloat("Setup", "ObjectDetail", fValue) )
- {
- m_engine->SetObjectDetail(fValue);
- }
-
- if ( GetProfileFloat("Setup", "GadgetQuantity", fValue) )
- {
- m_engine->SetGadgetQuantity(fValue);
- }
-
- if ( GetProfileInt("Setup", "TextureQuality", iValue) )
- {
- m_engine->SetTextureQuality(iValue);
- }
-
- if ( GetProfileInt("Setup", "AudioVolume", iValue) )
- {
- m_sound->SetAudioVolume(iValue);
- }
-
- if ( GetProfileInt("Setup", "MidiVolume", iValue) )
- {
- m_sound->SetMidiVolume(iValue);
- }
-
- if ( GetProfileInt("Setup", "EditIndentMode", iValue) )
- {
- m_engine->SetEditIndentMode(iValue);
- }
-
- if ( GetProfileInt("Setup", "EditIndentValue", iValue) )
- {
- m_engine->SetEditIndentValue(iValue);
- }
-
- if ( GetProfileString("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 _NET
- if ( m_accessEnable )
- {
- if ( GetProfileInt("Setup", "AccessMission", iValue) )
- {
- m_accessMission = iValue;
- }
-
- if ( GetProfileInt("Setup", "AccessUser", iValue) )
- {
- m_accessUser = iValue;
- }
- }
-#endif
-
- if ( GetProfileInt("Setup", "DeleteGamer", iValue) )
- {
- m_bDeleteGamer = iValue;
- }
-}
-
-
-// Changes the general level of quality.
-
-void CMainDialog::ChangeSetupQuality(int quality)
-{
- bool bEnable;
- float value;
- int iValue;
-
- bEnable = (quality >= 0);
- m_engine->SetShadow(bEnable);
- m_engine->SetGroundSpot(bEnable);
- m_engine->SetDirty(bEnable);
- m_engine->SetFog(bEnable);
- m_engine->SetLensMode(bEnable);
- m_engine->SetSkyMode(bEnable);
- m_engine->SetPlanetMode(bEnable);
- m_engine->SetLightMode(bEnable);
- m_camera->SetOverBaseColor(RetColor(RetColor(0.0f)));
-
- if ( quality < 0 ) value = 0.0f;
- if ( quality == 0 ) value = 1.0f;
- if ( quality > 0 ) value = 2.0f;
- m_engine->SetParticuleDensity(value);
-
- if ( quality < 0 ) value = 0.5f;
- if ( quality == 0 ) value = 1.0f;
- if ( quality > 0 ) value = 2.0f;
- m_engine->SetClippingDistance(value);
-
- if ( quality < 0 ) value = 0.0f;
- if ( quality == 0 ) value = 1.0f;
- if ( quality > 0 ) value = 2.0f;
- m_engine->SetObjectDetail(value);
-
- if ( quality < 0 ) value = 0.5f;
- if ( quality == 0 ) value = 1.0f;
- if ( quality > 0 ) value = 1.0f;
- m_engine->SetGadgetQuantity(value);
-
- if ( quality < 0 ) iValue = 0;
- if ( quality == 0 ) iValue = 1;
- if ( quality > 0 ) iValue = 2;
- m_engine->SetTextureQuality(iValue);
-
- m_engine->FirstExecuteAdapt(false);
-}
-
-
-// Redefinable keys:
-
-static int key_table[KEY_TOTAL] =
-{
-#if _SCHOOL & _TEEN
- KEYRANK_LEFT,
- KEYRANK_RIGHT,
- KEYRANK_UP,
- KEYRANK_DOWN,
- KEYRANK_CAMERA,
- KEYRANK_NEAR,
- KEYRANK_AWAY,
- KEYRANK_HELP,
- KEYRANK_PROG,
- KEYRANK_SPEED10,
- KEYRANK_SPEED15,
- KEYRANK_SPEED20,
- KEYRANK_QUIT,
-#else
- KEYRANK_LEFT,
- KEYRANK_RIGHT,
- KEYRANK_UP,
- KEYRANK_DOWN,
- KEYRANK_GUP,
- KEYRANK_GDOWN,
- KEYRANK_ACTION,
- KEYRANK_CAMERA,
- KEYRANK_VISIT,
- KEYRANK_NEXT,
- KEYRANK_HUMAN,
- KEYRANK_DESEL,
- KEYRANK_NEAR,
- KEYRANK_AWAY,
- KEYRANK_HELP,
- KEYRANK_PROG,
- KEYRANK_CBOT,
- KEYRANK_SPEED10,
- KEYRANK_SPEED15,
- KEYRANK_SPEED20,
- KEYRANK_QUIT,
-#endif
-};
-
-static EventMsg key_event[KEY_TOTAL] =
-{
-#if _SCHOOL & _TEEN
- EVENT_INTERFACE_KLEFT,
- EVENT_INTERFACE_KRIGHT,
- EVENT_INTERFACE_KUP,
- EVENT_INTERFACE_KDOWN,
- EVENT_INTERFACE_KCAMERA,
- EVENT_INTERFACE_KNEAR,
- EVENT_INTERFACE_KAWAY,
- EVENT_INTERFACE_KHELP,
- EVENT_INTERFACE_KPROG,
- EVENT_INTERFACE_KSPEED10,
- EVENT_INTERFACE_KSPEED15,
- EVENT_INTERFACE_KSPEED20,
- EVENT_INTERFACE_KQUIT,
-#else
- EVENT_INTERFACE_KLEFT,
- EVENT_INTERFACE_KRIGHT,
- EVENT_INTERFACE_KUP,
- EVENT_INTERFACE_KDOWN,
- EVENT_INTERFACE_KGUP,
- EVENT_INTERFACE_KGDOWN,
- EVENT_INTERFACE_KACTION,
- EVENT_INTERFACE_KCAMERA,
- EVENT_INTERFACE_KVISIT,
- EVENT_INTERFACE_KNEXT,
- EVENT_INTERFACE_KHUMAN,
- EVENT_INTERFACE_KDESEL,
- EVENT_INTERFACE_KNEAR,
- EVENT_INTERFACE_KAWAY,
- EVENT_INTERFACE_KHELP,
- EVENT_INTERFACE_KPROG,
- EVENT_INTERFACE_KCBOT,
- EVENT_INTERFACE_KSPEED10,
- EVENT_INTERFACE_KSPEED15,
- EVENT_INTERFACE_KSPEED20,
- EVENT_INTERFACE_KQUIT,
-#endif
-};
-
-// Updates the list of keys.
-
-void CMainDialog::UpdateKey()
-{
- CWindow* pw;
- CScroll* ps;
- CKey* pk;
- Math::Point pos, dim;
- int first, i;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
-
- ps = (CScroll*)pw->SearchControl(EVENT_INTERFACE_KSCROLL);
- if ( ps == 0 ) return;
-
- first = (int)(ps->RetVisibleValue()*(KEY_TOTAL-KEY_VISIBLE));
-
- for ( i=0 ; i<KEY_TOTAL ; i++ )
- {
- pw->DeleteControl(key_event[i]);
- }
-
- dim.x = 400.0f/640.0f;
- dim.y = 20.0f/480.0f;
- pos.x = 110.0f/640.0f;
- pos.y = 168.0f/480.0f + dim.y*(KEY_VISIBLE-1);
- for ( i=0 ; i<KEY_VISIBLE ; i++ )
- {
- pw->CreateKey(pos, dim, -1, key_event[first+i]);
- pk = (CKey*)pw->SearchControl(key_event[first+i]);
- if ( pk == 0 ) break;
- pk->SetKey(0, m_engine->RetKey(key_table[first+i], 0));
- pk->SetKey(1, m_engine->RetKey(key_table[first+i], 1));
- pos.y -= dim.y;
- }
-}
-
-// Change a key.
-
-void CMainDialog::ChangeKey(EventMsg event)
-{
- CWindow* pw;
- CScroll* ps;
- CKey* pk;
- int i;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw == 0 ) return;
-
- ps = (CScroll*)pw->SearchControl(EVENT_INTERFACE_KSCROLL);
- if ( ps == 0 ) return;
-
- for ( i=0 ; i<KEY_TOTAL ; i++ )
- {
- if ( key_event[i] == event )
- {
- pk = (CKey*)pw->SearchControl(key_event[i]);
- if ( pk == 0 ) break;
- m_engine->SetKey(key_table[i], 0, pk->RetKey(0));
- m_engine->SetKey(key_table[i], 1, pk->RetKey(1));
- }
- }
-}
-
-
-
-// Do you want to quit the current mission?
-
-void CMainDialog::StartAbort()
-{
- CWindow* pw;
- CButton* pb;
- Math::Point pos, dim;
- char name[100];
-
- StartDialog(Math::Point(0.3f, 0.8f), true, false, false);
- m_bDialogDelete = false;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
- if ( pw == 0 ) return;
-
- pos.x = 0.35f;
- pos.y = 0.60f;
- dim.x = 0.30f;
- dim.y = 0.30f;
- pw->CreateGroup(pos, dim, 5, EVENT_INTERFACE_GLINTl); // orange corner
- pos.x = 0.35f;
- pos.y = 0.10f;
- dim.x = 0.30f;
- dim.y = 0.30f;
- pw->CreateGroup(pos, dim, 4, EVENT_INTERFACE_GLINTr); // blue corner
-
- pos.x = 0.40f;
- dim.x = 0.20f;
-#if _POLISH
- pos.x -= 7.0f/640.0f;
- dim.x += 14.0f/640.0f;
-#endif
- dim.y = 32.0f/480.0f;
-
- pos.y = 0.74f;
- pb = pw->CreateButton(pos, dim, -1, EVENT_DIALOG_CANCEL);
- pb->SetState(STATE_SHADOW);
- GetResource(RES_TEXT, RT_DIALOG_NO, name);
- pb->SetName(name);
-
- if ( m_index == 2 || // missions ?
- m_index == 3 || // free games?
- m_index == 4 ) // user ?
- {
- pos.y = 0.62f;
- pb = pw->CreateButton(pos, dim, -1, EVENT_INTERFACE_WRITE);
- pb->SetState(STATE_SHADOW);
- if ( m_main->IsBusy() ) // current task?
- {
- pb->ClearState(STATE_ENABLE);
- }
-
- pos.y = 0.53f;
- pb = pw->CreateButton(pos, dim, -1, EVENT_INTERFACE_READ);
- pb->SetState(STATE_SHADOW);
- if ( !IsIOReadScene() ) // no file to read?
- {
- pb->ClearState(STATE_ENABLE);
- }
- pb->SetState(STATE_WARNING);
- }
-
- if ( m_engine->RetSetupMode() )
- {
- pos.y = 0.39f;
- pb = pw->CreateButton(pos, dim, -1, EVENT_INTERFACE_SETUP);
- pb->SetState(STATE_SHADOW);
- }
-
- pos.y = 0.25f;
- pb = pw->CreateButton(pos, dim, -1, EVENT_INTERFACE_AGAIN);
- pb->SetState(STATE_SHADOW);
- pb->SetState(STATE_WARNING);
-
- pos.y = 0.16f;
- pb = pw->CreateButton(pos, dim, -1, EVENT_DIALOG_OK);
- pb->SetState(STATE_SHADOW);
- pb->SetState(STATE_WARNING);
- GetResource(RES_TEXT, RT_DIALOG_YES, name);
- pb->SetName(name);
-}
-
-// Do you want to destroy the building?
-
-void CMainDialog::StartDeleteObject()
-{
- CWindow* pw;
- CButton* pb;
- Math::Point pos, dim;
- char name[100];
-
- StartDialog(Math::Point(0.7f, 0.3f), false, true, true);
- m_bDialogDelete = true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
- if ( pw == 0 ) return;
-
- pos.x = 0.00f;
- pos.y = 0.50f;
- dim.x = 1.00f;
- dim.y = 0.05f;
- GetResource(RES_TEXT, RT_DIALOG_DELOBJ, name);
- pw->CreateLabel(pos, dim, -1, EVENT_DIALOG_LABEL, name);
-
- pb = (CButton*)pw->SearchControl(EVENT_DIALOG_OK);
- if ( pb == 0 ) return;
- GetResource(RES_TEXT, RT_DIALOG_YESDEL, name);
- pb->SetName(name);
- pb->SetState(STATE_WARNING);
-
- pb = (CButton*)pw->SearchControl(EVENT_DIALOG_CANCEL);
- if ( pb == 0 ) return;
- GetResource(RES_TEXT, RT_DIALOG_NODEL, name);
- pb->SetName(name);
-}
-
-// Do you want to delete the player?
-
-void CMainDialog::StartDeleteGame(char *gamer)
-{
- CWindow* pw;
- CButton* pb;
- Math::Point pos, dim;
- char name[100];
- char text[100];
-
- StartDialog(Math::Point(0.7f, 0.3f), false, true, true);
- m_bDialogDelete = true;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
- if ( pw == 0 ) return;
-
- pos.x = 0.00f;
- pos.y = 0.50f;
- dim.x = 1.00f;
- dim.y = 0.05f;
- GetResource(RES_TEXT, RT_DIALOG_DELGAME, name);
- sprintf(text, name, gamer);
- pw->CreateLabel(pos, dim, -1, EVENT_DIALOG_LABEL, text);
-
- pb = (CButton*)pw->SearchControl(EVENT_DIALOG_OK);
- if ( pb == 0 ) return;
- GetResource(RES_TEXT, RT_DIALOG_YESDEL, name);
- pb->SetName(name);
- pb->SetState(STATE_WARNING);
-
- pb = (CButton*)pw->SearchControl(EVENT_DIALOG_CANCEL);
- if ( pb == 0 ) return;
- GetResource(RES_TEXT, RT_DIALOG_NODEL, name);
- pb->SetName(name);
-}
-
-// Would you quit the game?
-
-void CMainDialog::StartQuit()
-{
- CWindow* pw;
- CButton* pb;
- Math::Point pos, dim;
- char name[100];
-
- StartDialog(Math::Point(0.6f, 0.3f), false, true, true);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
- if ( pw == 0 ) return;
-
- pos.x = 0.00f;
- pos.y = 0.50f;
- dim.x = 1.00f;
- dim.y = 0.05f;
- GetResource(RES_TEXT, RT_DIALOG_QUIT, name);
- pw->CreateLabel(pos, dim, -1, EVENT_DIALOG_LABEL, name);
-
- pb = (CButton*)pw->SearchControl(EVENT_DIALOG_OK);
- if ( pb == 0 ) return;
- GetResource(RES_TEXT, RT_DIALOG_YESQUIT, name);
- pb->SetName(name);
- pb->SetState(STATE_WARNING);
-
- pb = (CButton*)pw->SearchControl(EVENT_DIALOG_CANCEL);
- if ( pb == 0 ) return;
- GetResource(RES_TEXT, RT_DIALOG_NOQUIT, name);
- pb->SetName(name);
-}
-
-// Beginning of displaying a dialog.
-
-void CMainDialog::StartDialog(Math::Point dim, bool bFire, bool bOK, bool bCancel)
-{
- CWindow* pw;
- CButton* pb;
- Math::Point pos, ddim;
- char name[100];
-
- StartSuspend();
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW6);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW7);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW8);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
- if ( pb != 0 )
- {
- pb->ClearState(STATE_VISIBLE);
- }
-
- m_bDialogFire = bFire;
-
- pos.x = (1.0f-dim.x)/2.0f;
- pos.y = (1.0f-dim.y)/2.0f;
- pw = m_interface->CreateWindows(pos, dim, bFire?12:8, EVENT_WINDOW9);
- pw->SetState(STATE_SHADOW);
- GetResource(RES_TEXT, RT_TITLE_BASE, name);
- pw->SetName(name);
-
- m_dialogPos = pos;
- m_dialogDim = dim;
- m_dialogTime = 0.0f;
- m_dialogParti = 999.0f;
-
- if ( bOK )
- {
- pos.x = 0.50f-0.15f-0.02f;
- pos.y = 0.50f-dim.y/2.0f+0.03f;
- ddim.x = 0.15f;
- ddim.y = 0.06f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_DIALOG_OK);
- pb->SetState(STATE_SHADOW);
- GetResource(RES_EVENT, EVENT_DIALOG_OK, name);
- pb->SetName(name);
- }
-
- if ( bCancel )
- {
- pos.x = 0.50f+0.02f;
- pos.y = 0.50f-dim.y/2.0f+0.03f;
- ddim.x = 0.15f;
- ddim.y = 0.06f;
- pb = pw->CreateButton(pos, ddim, -1, EVENT_DIALOG_CANCEL);
- pb->SetState(STATE_SHADOW);
- GetResource(RES_EVENT, EVENT_DIALOG_CANCEL, name);
- pb->SetName(name);
- }
-
- m_sound->Play(SOUND_TZOING);
- m_bDialog = true;
-}
-
-// Animation of a dialog.
-
-void CMainDialog::FrameDialog(float rTime)
-{
- CWindow* pw;
- Math::Vector pos, speed;
- Math::Point dim, dpos, ddim;
- float zoom;
- int i;
-
- dpos = m_dialogPos;
- ddim = m_dialogDim;
-
- m_dialogTime += rTime;
- if ( m_dialogTime < 1.0f )
- {
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
- if ( pw != 0 )
- {
- if ( m_dialogTime < 0.50f )
- {
- zoom = Math::Bounce(m_dialogTime/0.50f);
- }
- else
- {
- zoom = 1.0f;
- }
-
- dpos.x += ddim.x/2.0f;
- dpos.y += ddim.y/2.0f;
-
- ddim.x *= zoom;
-//? ddim.y *= zoom;
-
- dpos.x -= ddim.x/2.0f;
- dpos.y -= ddim.y/2.0f;
-
- pw->SetPos(dpos);
- pw->SetDim(ddim);
- }
- }
-
- if ( !m_bGlint ) return;
-
- m_dialogParti += rTime;
- if ( m_dialogParti < m_engine->ParticuleAdapt(0.05f) ) return;
- m_dialogParti = 0.0f;
-
- if ( !m_bDialogFire ) return;
-
- dpos = m_dialogPos;
- ddim = m_dialogDim;
-
- pos.z = 0.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
-
- for ( i=0 ; i<2 ; i++ )
- {
- // Bottom.
- pos.x = dpos.x + ddim.x*Math::Rand();
- pos.y = dpos.y;
- pos.x += (Math::Rand()-0.5f)*(6.0f/640.0f);
- pos.y += Math::Rand()*(16.0f/480.0f)-(10.0f/480.0f);
- dim.x = 0.01f+Math::Rand()*0.01f;
- dim.y = dim.x/0.75f;
- m_particule->CreateParticule(pos, speed, dim,
- (ParticuleType)(PARTILENS1+rand()%3),
- 1.0f, 0.0f, 0.0f, SH_INTERFACE);
-
- // Top.
- pos.x = dpos.x + ddim.x*Math::Rand();
- pos.y = dpos.y + ddim.y;
- pos.x += (Math::Rand()-0.5f)*(6.0f/640.0f);
- pos.y -= Math::Rand()*(16.0f/480.0f)-(10.0f/480.0f);
- dim.x = 0.01f+Math::Rand()*0.01f;
- dim.y = dim.x/0.75f;
- m_particule->CreateParticule(pos, speed, dim,
- (ParticuleType)(PARTILENS1+rand()%3),
- 1.0f, 0.0f, 0.0f, SH_INTERFACE);
-
- // Left.
- pos.y = dpos.y + ddim.y*Math::Rand();
- pos.x = dpos.x;
- pos.x += Math::Rand()*(16.0f/640.0f)-(10.0f/640.0f);
- pos.y += (Math::Rand()-0.5f)*(6.0f/480.0f);
- dim.x = 0.01f+Math::Rand()*0.01f;
- dim.y = dim.x/0.75f;
- m_particule->CreateParticule(pos, speed, dim,
- (ParticuleType)(PARTILENS1+rand()%3),
- 1.0f, 0.0f, 0.0f, SH_INTERFACE);
-
- // Right.
- pos.y = dpos.y + ddim.y*Math::Rand();
- pos.x = dpos.x + ddim.x;
- pos.x -= Math::Rand()*(16.0f/640.0f)-(10.0f/640.0f);
- pos.y += (Math::Rand()-0.5f)*(6.0f/480.0f);
- dim.x = 0.01f+Math::Rand()*0.01f;
- dim.y = dim.x/0.75f;
- m_particule->CreateParticule(pos, speed, dim,
- (ParticuleType)(PARTILENS1+rand()%3),
- 1.0f, 0.0f, 0.0f, SH_INTERFACE);
- }
-}
-
-// End of the display of a dialogue.
-
-void CMainDialog::StopDialog()
-{
- CWindow* pw;
- CButton* pb;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW6);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW7);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW8);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
- if ( pb != 0 )
- {
- pb->SetState(STATE_VISIBLE);
- }
-
- StopSuspend();
- m_interface->DeleteControl(EVENT_WINDOW9);
- m_bDialog = false;
-}
-
-// Suspends the simulation for a dialog phase.
-
-void CMainDialog::StartSuspend()
-{
- m_sound->MuteAll(true);
- m_main->ClearInterface();
- m_bInitPause = m_engine->RetPause();
- m_engine->SetPause(true);
- m_engine->SetOverFront(false); // over flat behind
- m_main->CreateShortcuts();
- m_main->StartSuspend();
- m_initCamera = m_camera->RetType();
- m_camera->SetType(CAMERA_DIALOG);
-}
-
-// Resume the simulation after a period of dialog.
-
-void CMainDialog::StopSuspend()
-{
- m_sound->MuteAll(false);
- m_main->ClearInterface();
- if ( !m_bInitPause ) m_engine->SetPause(false);
- m_engine->SetOverFront(true); // over flat front
- m_main->CreateShortcuts();
- m_main->StopSuspend();
- m_camera->SetType(m_initCamera);
-}
-
-
-// Whether to use tooltips.
-
-bool CMainDialog::RetTooltip()
-{
- return m_bTooltip;
-}
-
-// Specifies whether a dialog is displayed.
-
-bool CMainDialog::IsDialog()
-{
- return m_bDialog;
-}
-
-
-
-
-// Specifies the name of the scene to read.
-
-void CMainDialog::SetSceneRead(char* name)
-{
- strcpy(m_sceneRead, name);
-}
-
-// Returns the name of the scene to read.
-
-char* CMainDialog::RetSceneRead()
-{
- return m_sceneRead;
-}
-
-// Specifies the name of the scene to read.
-
-void CMainDialog::SetStackRead(char* name)
-{
- strcpy(m_stackRead, name);
-}
-
-// Returns the name of the scene to read.
-
-char* CMainDialog::RetStackRead()
-{
- return m_stackRead;
-}
-
-// Specifies the name of the chosen to play scene.
-
-void CMainDialog::SetSceneName(char* name)
-{
- strcpy(m_sceneName, name);
-}
-
-// Returns the name of the chosen to play scene.
-
-char* CMainDialog::RetSceneName()
-{
- return m_sceneName;
-}
-
-// Specifies the rank of the chosen to play scene.
-
-void CMainDialog::SetSceneRank(int rank)
-{
- m_sceneRank = rank;
-}
-
-// Returns the rank of the chosen to play scene.
-
-int CMainDialog::RetSceneRank()
-{
- return m_sceneRank;
-}
-
-// Returns folder name of the scene that user selected to play.
-
-char* CMainDialog::RetSceneDir()
-{
- int i;
-
- i = (m_sceneRank/100)-1;
-
- if ( i < 0 || i >= m_userTotal ) return 0;
- return m_userList[i];
-}
-
-// Whether to show the solution.
-
-bool CMainDialog::RetSceneSoluce()
-{
- return m_bSceneSoluce;
-}
-
-// Returns the name of the folder to save.
-
-char* CMainDialog::RetSavegameDir()
-{
- return m_savegameDir;
-}
-
-// Returns the name of public folder.
-
-char* CMainDialog::RetPublicDir()
-{
- return m_publicDir;
-}
-
-
-// Indicates if there are reflections on the buttons.
-
-bool CMainDialog::RetGlint()
-{
- return m_bGlint;
-}
-
-// Whether to show 4:solutions.
-
-bool CMainDialog::RetSoluce4()
-{
- return m_bSoluce4;
-}
-
-// Whether to show the cinematics.
-
-bool CMainDialog::RetMovies()
-{
- return m_bMovies;
-}
-
-// IWhether to make an animation in CTaskReset.
-
-bool CMainDialog::RetNiceReset()
-{
- return m_bNiceReset;
-}
-
-// Indicates whether the fire causes damage to its own units.
-
-bool CMainDialog::RetHimselfDamage()
-{
- return m_bHimselfDamage;
-}
-
-
-
-// Saves the personalized player.
-
-void CMainDialog::WriteGamerPerso(char *gamer)
-{
- FILE* file;
- char filename[100];
- char line[100];
-
- sprintf(filename, "%s\\%s\\face.gam", m_savegameDir, gamer);
- file = fopen(filename, "w");
- if ( file == NULL ) return;
-
- sprintf(line, "Head face=%d glasses=%d hair=%.2f;%.2f;%.2f;%.2f\n",
- m_perso.face, m_perso.glasses,
- m_perso.colorHair.r, m_perso.colorHair.g, m_perso.colorHair.b, m_perso.colorHair.a);
- fputs(line, file);
-
- sprintf(line, "Body combi=%.2f;%.2f;%.2f;%.2f band=%.2f;%.2f;%.2f;%.2f\n",
- m_perso.colorCombi.r, m_perso.colorCombi.g, m_perso.colorCombi.b, m_perso.colorCombi.a,
- m_perso.colorBand.r, m_perso.colorBand.g, m_perso.colorBand.b, m_perso.colorBand.a);
- fputs(line, file);
-
- fclose(file);
-}
-
-// Reads the personalized player.
-
-void CMainDialog::ReadGamerPerso(char *gamer)
-{
- FILE* file;
- char filename[100];
- char line[100];
- D3DCOLORVALUE color;
-
- m_perso.face = 0;
- DefPerso();
-
- sprintf(filename, "%s\\%s\\face.gam", m_savegameDir, gamer);
- file = fopen(filename, "r");
- if ( file == NULL ) return;
-
- while ( fgets(line, 100, file) != NULL )
- {
- if ( Cmd(line, "Head") )
- {
- m_perso.face = OpInt(line, "face", 0);
- m_perso.glasses = OpInt(line, "glasses", 0);
-
- color.r = 0.0f;
- color.g = 0.0f;
- color.b = 0.0f;
- color.a = 0.0f;
- m_perso.colorHair = OpColorValue(line, "hair", color);
- }
-
- if ( Cmd(line, "Body") )
- {
- color.r = 0.0f;
- color.g = 0.0f;
- color.b = 0.0f;
- color.a = 0.0f;
- m_perso.colorCombi = OpColorValue(line, "combi", color);
-
- color.r = 0.0f;
- color.g = 0.0f;
- color.b = 0.0f;
- color.a = 0.0f;
- m_perso.colorBand = OpColorValue(line, "band", color);
- }
- }
-
- fclose(file);
-}
-
-// Specifies the face of the player.
-
-void CMainDialog::SetGamerFace(char *gamer, int face)
-{
- m_perso.face = face;
- WriteGamerPerso(gamer);
-}
-
-// Gives the face of the player.
-
-int CMainDialog::RetGamerFace(char *gamer)
-{
- ReadGamerPerso(gamer);
- return m_perso.face;
-}
-
-// Gives the face of the player.
-
-int CMainDialog::RetGamerFace()
-{
- return m_perso.face;
-}
-
-int CMainDialog::RetGamerGlasses()
-{
- return m_perso.glasses;
-}
-
-bool CMainDialog::RetGamerOnlyHead()
-{
- return (m_phase == PHASE_PERSO && m_persoTab == 0);
-}
-
-float CMainDialog::RetPersoAngle()
-{
- return m_persoAngle;
-}
-
-D3DCOLORVALUE CMainDialog::RetGamerColorHair()
-{
- return m_perso.colorHair;
-}
-
-D3DCOLORVALUE CMainDialog::RetGamerColorCombi()
-{
- return m_perso.colorCombi;
-}
-
-D3DCOLORVALUE CMainDialog::RetGamerColorBand()
-{
- return m_perso.colorBand;
-}
-
-
-// Reads the file of the player.
-
-bool CMainDialog::ReadGamerInfo()
-{
- FILE* file;
- char line[100];
- int chap, i, numTry, passed;
-
- for ( i=0 ; i<MAXSCENE ; i++ )
- {
- m_sceneInfo[i].numTry = 0;
- m_sceneInfo[i].bPassed = false;
- }
-
- sprintf(line, "%s\\%s\\%s.gam", m_savegameDir, m_main->RetGamerName(), m_sceneName);
- file = fopen(line, "r");
- if ( file == NULL ) return false;
-
- if ( fgets(line, 100, file) != NULL )
- {
- sscanf(line, "CurrentChapter=%d CurrentSel=%d\n", &chap, &i);
- m_chap[m_index] = chap-1;
- m_sel[m_index] = i-1;
- }
-
- while ( fgets(line, 100, file) != NULL )
- {
- sscanf(line, "Chapter %d: Scene %d: numTry=%d passed=%d\n",
- &chap, &i, &numTry, &passed);
-
- i += chap*100;
- if ( i >= 0 && i < MAXSCENE )
- {
- m_sceneInfo[i].numTry = numTry;
- m_sceneInfo[i].bPassed = passed;
- }
- }
-
- fclose(file);
- return true;
-}
-
-// Writes the file of the player.
-
-bool CMainDialog::WriteGamerInfo()
-{
- FILE* file;
- char line[100];
- int i;
-
- sprintf(line, "%s\\%s\\%s.gam", m_savegameDir, m_main->RetGamerName(), m_sceneName);
- file = fopen(line, "w");
- if ( file == NULL ) return false;
-
- sprintf(line, "CurrentChapter=%d CurrentSel=%d\n",
- m_chap[m_index]+1, m_sel[m_index]+1);
- fputs(line, file);
-
- for ( i=0 ; i<MAXSCENE ; i++ )
- {
- if ( m_sceneInfo[i].numTry == 0 ) continue;
-
- sprintf(line, "Chapter %d: Scene %d: numTry=%d passed=%d\n",
- i/100, i%100, m_sceneInfo[i].numTry, m_sceneInfo[i].bPassed);
- fputs(line, file);
- }
-
- fclose(file);
- return true;
-}
-
-void CMainDialog::SetGamerInfoTry(int rank, int numTry)
-{
- if ( rank < 0 || rank >= MAXSCENE ) return;
- if ( numTry > 100 ) numTry = 100;
- m_sceneInfo[rank].numTry = numTry;
-}
-
-int CMainDialog::RetGamerInfoTry(int rank)
-{
- if ( rank < 0 || rank >= MAXSCENE ) return 0;
- return m_sceneInfo[rank].numTry;
-}
-
-void CMainDialog::SetGamerInfoPassed(int rank, bool bPassed)
-{
- int chap, i;
- bool bAll;
-
- if ( rank < 0 || rank >= MAXSCENE ) return;
- m_sceneInfo[rank].bPassed = bPassed;
-
- if ( bPassed )
- {
- bAll = true;
- chap = rank/100;
- for ( i=0 ; i<m_maxList ; i++ )
- {
- bAll &= m_sceneInfo[chap*100+i+1].bPassed;
- }
- m_sceneInfo[chap*100].numTry ++;
- m_sceneInfo[chap*100].bPassed = bAll;
- }
-}
-
-bool CMainDialog::RetGamerInfoPassed(int rank)
-{
- if ( rank < 0 || rank >= MAXSCENE ) return false;
- return m_sceneInfo[rank].bPassed;
-}
-
-
-// Passes to the next mission, and possibly in the next chapter.
-
-bool CMainDialog::NextMission()
-{
- m_sel[m_index] ++; // next mission
-
- if ( m_sel[m_index] >= m_maxList ) // last mission of the chapter?
- {
- m_chap[m_index] ++; // next chapter
- m_sel[m_index] = 0; // first mission
- }
-
- return true;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// maindialog.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <time.h>
+#include <direct.h>
+#include <io.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/global.h"
+#include "common/language.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/profile.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "old/math3d.h"
+#include "old/particule.h"
+#include "ui/interface.h"
+#include "ui/button.h"
+#include "ui/color.h"
+#include "ui/check.h"
+#include "ui/key.h"
+#include "ui/group.h"
+#include "ui/image.h"
+#include "ui/scroll.h"
+#include "ui/slider.h"
+#include "ui/list.h"
+#include "ui/label.h"
+#include "ui/window.h"
+#include "ui/edit.h"
+#include "ui/editvalue.h"
+#include "old/text.h"
+#include "old/camera.h"
+#include "old/sound.h"
+#include "script/cmdtoken.h"
+#include "object/robotmain.h"
+#include "ui/maindialog.h"
+
+
+
+const int KEY_VISIBLE = 6; // number of visible keys redefinable
+
+#if _SCHOOL & _TEEN
+const int KEY_TOTAL = 13; // total number of keys redefinable
+#else
+const int KEY_TOTAL = 21; // total number of keys redefinable
+#endif
+
+const int WELCOME_LENGTH = 6.0f;
+
+
+
+static int perso_color[3*10*3] =
+{
+ // hair:
+ 193, 221, 226, // white
+ 255, 255, 181, // yellow
+ 204, 155, 84, // blond
+ 165, 48, 10, // red
+ 140, 75, 84, // brown
+ 83, 64, 51, // brown
+ 90, 95, 85, // black
+ 85, 48, 9, // brown
+ 60, 0, 23, // black
+ 0, 0, 0, //
+ // spacesuit:
+ 203, 206, 204, // dirty white
+ 0, 205, 203, // bluish
+ 108, 176, 0, // greenish
+ 207, 207, 32, // yellow
+ 170, 141, 0, // orange
+ 108, 84, 0, // brown
+ 0, 84, 136, // bluish
+ 56, 61, 146, // bluish
+ 56, 56, 56, // black
+ 0, 0, 0, //
+ // strips:
+ 255, 255, 255, // white
+ 255, 255, 0, // yellow
+ 255, 132, 1, // orange
+ 255, 0, 255, // magenta
+ 255, 0, 0, // red
+ 0, 255, 0, // green
+ 0, 255, 255, // cyan
+ 0, 0, 255, // blue
+ 70, 51, 84, // dark
+ 0, 0, 0, //
+};
+
+
+#if _NET
+// Check if the key "school" is present in the registry.
+
+bool SchoolCheck()
+{
+ HKEY key;
+ char buffer[100];
+ LONG i;
+ DWORD type, len;
+
+ i = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+#if _NEWLOOK
+ "Software\\Epsitec\\CeeBot\\Setup",
+#else
+ "Software\\Epsitec\\Colobot\\Setup",
+#endif
+ 0, KEY_READ, &key);
+ if ( i != ERROR_SUCCESS ) return false;
+
+ type = REG_SZ;
+ len = sizeof(buffer);
+ i = RegQueryValueEx(key, "School", NULL, &type, (LPBYTE)buffer, &len);
+ if ( i != ERROR_SUCCESS || type != REG_SZ ) return false;
+
+ if ( strcmp(buffer, "ToBoLoC") != 0 ) return false;
+
+ return true;
+}
+#endif
+
+
+// Constructor of robot application.
+
+CMainDialog::CMainDialog(CInstanceManager* iMan)
+{
+ int i;
+
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_DIALOG, this);
+
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+ m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+
+ m_phase = PHASE_NAME;
+ m_phaseSetup = PHASE_SETUPg;
+ m_phaseTerm = PHASE_TRAINER;
+ m_sceneRead[0] = 0;
+ m_stackRead[0] = 0;
+ m_sceneName[0] = 0;
+ m_sceneRank = 0;
+ m_bSceneSoluce = false;
+ m_bSimulSetup = false;
+#if _NET
+ m_accessEnable = SchoolCheck();
+ m_accessMission= false;
+ m_accessUser = false;
+#else
+ m_accessEnable = true;
+ m_accessMission= true;
+ m_accessUser = true;
+#endif
+ m_bDeleteGamer = true;
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ m_chap[i] = 0;
+ m_sel[i] = 0;
+ }
+ m_index = 0;
+ m_maxList = 0;
+
+ ZeroMemory(&m_perso, sizeof(GamerPerso));
+ DefPerso();
+
+ m_bTooltip = true;
+ m_bGlint = true;
+ m_bRain = true;
+ m_bSoluce4 = true;
+ m_bMovies = true;
+ m_bNiceReset = true;
+ m_bHimselfDamage = true;
+#if _TEEN
+ m_bCameraScroll = false;
+#else
+ m_bCameraScroll = true;
+#endif
+ m_bCameraInvertX = false;
+ m_bCameraInvertY = false;
+ m_bEffect = true;
+ m_shotDelay = 0;
+
+ m_glintMouse = Math::Point(0.0f, 0.0f);
+ m_glintTime = 1000.0f;
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ m_partiPhase[i] = 0;
+ m_partiTime[i] = 0.0f;
+ }
+
+ strcpy(m_sceneDir, "scene");
+ strcpy(m_savegameDir, "savegame");
+ strcpy(m_publicDir, "program");
+ strcpy(m_userDir, "user");
+ strcpy(m_filesDir, "files");
+
+ m_bDialog = false;
+}
+
+// Destructor of robot application.
+
+CMainDialog::~CMainDialog()
+{
+}
+
+
+// Changes phase.
+
+void CMainDialog::ChangePhase(Phase phase)
+{
+ CWindow* pw;
+ CEdit* pe;
+ CEditValue* pv;
+ CLabel* pl;
+ CList* pli;
+ CCheck* pc;
+ CScroll* ps;
+ CSlider* psl;
+ CButton* pb;
+ CColor* pco;
+ CGroup* pg;
+ CImage* pi;
+ Math::Point pos, dim, ddim;
+ float ox, oy, sx, sy;
+ char name[100];
+ char* gamer;
+ int res, i, j;
+
+ m_camera->SetType(CAMERA_DIALOG);
+ m_engine->SetOverFront(false);
+ m_engine->SetOverColor(RetColor(0.0f), D3DSTATETCb);
+
+ if ( phase == PHASE_TERM )
+ {
+ phase = m_phaseTerm;
+ }
+ m_phase = phase; // copy the info to CRobotMain
+ m_phaseTime = 0.0f;
+
+ dim.x = 32.0f/640.0f;
+ dim.y = 32.0f/480.0f;
+ ox = 3.0f/640.0f;
+ oy = 3.0f/480.0f;
+ sx = (32.0f+2.0f)/640.0f;
+ sy = (32.0f+2.0f)/480.0f;
+
+ if ( m_phase == PHASE_INIT )
+ {
+ pos.x = 0.35f;
+ pos.y = 0.10f;
+ ddim.x = 0.30f;
+ ddim.y = 0.80f;
+#if _TEEN
+ pw = m_interface->CreateWindows(pos, ddim, 12, EVENT_WINDOW5);
+#else
+ pw = m_interface->CreateWindows(pos, ddim, 10, EVENT_WINDOW5);
+#endif
+ GetResource(RES_TEXT, RT_TITLE_INIT, name);
+ pw->SetName(name);
+
+ pos.x = 0.35f;
+ pos.y = 0.60f;
+ ddim.x = 0.30f;
+ ddim.y = 0.30f;
+ pw->CreateGroup(pos, ddim, 5, EVENT_INTERFACE_GLINTl); // orange corner
+ pos.x = 0.35f;
+ pos.y = 0.10f;
+ ddim.x = 0.30f;
+ ddim.y = 0.30f;
+ pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner
+
+#if _SCHOOL
+ ddim.x = 0.20f;
+ ddim.y = dim.y*2.4f;
+ pos.x = 0.40f;
+ pos.y = oy+sy*7.9f;
+ pg = pw->CreateGroup(pos, ddim, 24, EVENT_LABEL1); // orange
+ pg->SetState(STATE_SHADOW);
+ pos.y = oy+sy*3.9f;
+ pg = pw->CreateGroup(pos, ddim, 25, EVENT_LABEL1); // orange
+ pg->SetState(STATE_SHADOW);
+ ddim.y = dim.y*1.2f;
+ pos.y = oy+sy*1.9f;
+ pg = pw->CreateGroup(pos, ddim, 26, EVENT_LABEL1); // red
+ pg->SetState(STATE_SHADOW);
+#else
+ ddim.x = 0.20f;
+ ddim.y = dim.y*2.4f;
+ pos.x = 0.40f;
+ if ( m_accessEnable && m_accessMission )
+ {
+ pos.y = oy+sy*9.1f;
+ pg = pw->CreateGroup(pos, ddim, 23, EVENT_LABEL1); // yellow
+ pg->SetState(STATE_SHADOW);
+ }
+ pos.y = oy+sy*6.8f;
+ pg = pw->CreateGroup(pos, ddim, 24, EVENT_LABEL1); // orange
+ pg->SetState(STATE_SHADOW);
+ pos.y = oy+sy*3.9f;
+ pg = pw->CreateGroup(pos, ddim, 25, EVENT_LABEL1); // orange
+ pg->SetState(STATE_SHADOW);
+ ddim.y = dim.y*1.2f;
+ pos.y = oy+sy*1.9f;
+ pg = pw->CreateGroup(pos, ddim, 26, EVENT_LABEL1); // red
+ pg->SetState(STATE_SHADOW);
+#endif
+
+#if _SCHOOL
+ ddim.x = 0.18f;
+ ddim.y = dim.y*1;
+ pos.x = 0.41f;
+ pos.y = oy+sy*9.1f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_TRAINER);
+ pb->SetState(STATE_SHADOW);
+
+ pos.y = oy+sy*8.0f;
+#if _TEEN
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_TEEN);
+#else
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_DEFI);
+#endif
+#if _CEEBOTDEMO
+ pb->ClearState(STATE_ENABLE);
+#endif
+ pb->SetState(STATE_SHADOW);
+#else
+ ddim.x = 0.18f;
+ ddim.y = dim.y*1;
+ pos.x = 0.41f;
+
+ if ( m_accessEnable && m_accessMission )
+ {
+ pos.y = oy+sy*10.3f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_MISSION);
+ pb->SetState(STATE_SHADOW);
+
+ pos.y = oy+sy*9.2f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_FREE);
+ pb->SetState(STATE_SHADOW);
+ }
+
+ pos.y = oy+sy*8.0f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_TRAINER);
+ pb->SetState(STATE_SHADOW);
+
+ pos.y = oy+sy*6.9f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_DEFI);
+ pb->SetState(STATE_SHADOW);
+#endif
+
+ if ( m_engine->RetSetupMode() )
+ {
+ pos.y = oy+sy*5.1f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_SETUP);
+ pb->SetState(STATE_SHADOW);
+ }
+
+ pos.y = oy+sy*4.0f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_NAME);
+ pb->SetState(STATE_SHADOW);
+
+ pos.y = oy+sy*2.0f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_QUIT);
+ pb->SetState(STATE_SHADOW);
+
+#if !_DEMO & !_SCHOOL
+ if ( m_accessEnable && m_accessUser )
+ {
+ pos.x = 447.0f/640.0f;
+ pos.y = 313.0f/480.0f;
+ ddim.x = 0.09f;
+#if _POLISH
+ pos.x -= 5.0f/640.0f;
+ ddim.x += 10.0f/640.0f;
+#endif
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_USER);
+ pb->SetState(STATE_SHADOW);
+ }
+#endif
+
+ if ( m_engine->RetDebugMode() )
+ {
+ pos.x = 139.0f/640.0f;
+ pos.y = 313.0f/480.0f;
+ ddim.x = 0.09f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PROTO);
+ pb->SetState(STATE_SHADOW);
+ }
+
+ pos.x = 0.40f;
+ ddim.x = 0.20f;
+ pos.y = 26.0f/480.0f;
+ ddim.y = 12.0f/480.0f;
+ pg = pw->CreateGroup(pos, ddim, 1, EVENT_LABEL1);
+ pg->SetState(STATE_SHADOW);
+ pos.y -= 5.0f/480.0f;
+#if _WG
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, " ");
+#else
+#if _NEWLOOK
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, "www.epsitec.ch");
+#else
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, "www.ceebot.com");
+#endif
+#endif
+ pl->SetFontType(FONT_COURIER);
+ pl->SetFontSize(8.0f);
+
+ m_engine->SetBackground("inter01.tga", 0,0, 0,0, true, true);
+ m_engine->SetBackForce(true);
+ }
+
+ if ( m_phase == PHASE_NAME )
+ {
+ pos.x = 0.10f;
+ pos.y = 0.10f;
+ ddim.x = 0.80f;
+ ddim.y = 0.80f;
+ pw = m_interface->CreateWindows(pos, ddim, 12, EVENT_WINDOW5);
+ GetResource(RES_TEXT, RT_TITLE_NAME, name);
+ pw->SetName(name);
+
+#if _NEWLOOK
+ pos.x = 80.0f/640.0f;
+ pos.y = 93.0f/480.0f;
+ ddim.x = 285.0f/640.0f;
+ ddim.y = 266.0f/480.0f;
+ pg = pw->CreateGroup(pos, ddim, 23, EVENT_LABEL1); // blue
+ pg->SetState(STATE_SHADOW);
+ pos.x = 372.0f/640.0f;
+ ddim.x = 188.0f/640.0f;
+ pg = pw->CreateGroup(pos, ddim, 26, EVENT_LABEL1); // violet
+ pg->SetState(STATE_SHADOW);
+#endif
+
+ pos.x = 0.10f;
+ pos.y = 0.40f;
+ ddim.x = 0.50f;
+ ddim.y = 0.50f;
+ pw->CreateGroup(pos, ddim, 5, EVENT_INTERFACE_GLINTl); // orange corner
+ pos.x = 0.40f;
+ pos.y = 0.10f;
+ ddim.x = 0.50f;
+ ddim.y = 0.50f;
+ pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner
+
+ pos.x = 60.0f/640.0f;
+ pos.y = 313.0f/480.0f;
+ ddim.x = 120.0f/640.0f;
+ ddim.y = 32.0f/480.0f;
+ GetResource(RES_EVENT, EVENT_INTERFACE_NLABEL, name);
+ pl = pw->CreateLabel(pos, ddim, -1, EVENT_INTERFACE_NLABEL, name);
+ pl->SetJustif(-1);
+
+ pos.x = 200.0f/640.0f;
+ pos.y = 320.0f/480.0f;
+ ddim.x = 160.0f/640.0f;
+ ddim.y = 32.0f/480.0f;
+ pg = pw->CreateGroup(pos, ddim, 7, EVENT_LABEL1);
+ pg->SetState(STATE_SHADOW);
+
+ pos.x = 207.0f/640.0f;
+ pos.y = 328.0f/480.0f;
+ ddim.x = 144.0f/640.0f;
+ ddim.y = 18.0f/480.0f;
+ pe = pw->CreateEdit(pos, ddim, 0, EVENT_INTERFACE_NEDIT);
+ pe->SetMaxChar(15);
+ gamer = m_main->RetGamerName();
+ if ( gamer[0] == 0 )
+ {
+ GetResource(RES_TEXT, RT_NAME_DEFAULT, name);
+ }
+ else
+ {
+ strcpy(name, gamer);
+ }
+ pe->SetText(name);
+ pe->SetCursor(strlen(name), 0);
+ pe->SetFocus(true);
+
+ pos.x = 380.0f/640.0f;
+ pos.y = 320.0f/480.0f;
+ ddim.x =100.0f/640.0f;
+ ddim.y = 32.0f/480.0f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_NOK);
+ pb->SetState(STATE_SHADOW);
+
+#if !_TEEN
+ pos.x = 380.0f/640.0f;
+ pos.y = 250.0f/480.0f;
+ ddim.x =100.0f/640.0f;
+ ddim.y = 52.0f/480.0f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PERSO);
+ pb->SetState(STATE_SHADOW);
+#endif
+
+ pos.x = 200.0f/640.0f;
+ pos.y = 150.0f/480.0f;
+ ddim.x = 160.0f/640.0f;
+ ddim.y = 160.0f/480.0f;
+ pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_NLIST);
+ pli->SetState(STATE_SHADOW);
+
+ if ( m_bDeleteGamer )
+ {
+ pos.x = 200.0f/640.0f;
+ pos.y = 100.0f/480.0f;
+ ddim.x = 160.0f/640.0f;
+ ddim.y = 32.0f/480.0f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_NDELETE);
+ pb->SetState(STATE_SHADOW);
+ }
+
+ pos.x = 380.0f/640.0f;
+ pos.y = 100.0f/480.0f;
+ ddim.x =100.0f/640.0f;
+ ddim.y = 32.0f/480.0f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_NCANCEL);
+ pb->SetState(STATE_SHADOW);
+
+ ReadNameList();
+ UpdateNameList();
+ UpdateNameControl();
+ UpdateNameFace();
+
+ m_engine->SetBackground("inter01.tga", 0,0, 0,0, true, true);
+ m_engine->SetBackForce(true);
+ }
+
+ if ( m_phase == PHASE_PERSO )
+ {
+ pos.x = 0.10f;
+ pos.y = 0.10f;
+ ddim.x = 0.80f;
+ ddim.y = 0.80f;
+ pw = m_interface->CreateWindows(pos, ddim, 12, EVENT_WINDOW5);
+ GetResource(RES_TEXT, RT_TITLE_PERSO, name);
+ pw->SetName(name);
+
+#if _NEWLOOK
+ pos.x = 95.0f/640.0f;
+ pos.y = 66.0f/480.0f;
+ ddim.x = 443.0f/640.0f;
+ ddim.y = 42.0f/480.0f;
+ pg = pw->CreateGroup(pos, ddim, 26, EVENT_LABEL1); // violet
+ pg->SetState(STATE_SHADOW);
+#endif
+
+ pos.x = 0.10f;
+ pos.y = 0.40f;
+ ddim.x = 0.50f;
+ ddim.y = 0.50f;
+ pw->CreateGroup(pos, ddim, 5, EVENT_INTERFACE_GLINTl); // orange corner
+ pos.x = 0.40f;
+ pos.y = 0.10f;
+ ddim.x = 0.50f;
+ ddim.y = 0.50f;
+ pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner
+
+ pos.x = 95.0f/640.0f;
+ pos.y = 108.0f/480.0f;
+ ddim.x = 220.0f/640.0f;
+ ddim.y = 274.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 17, EVENT_NULL); // frame
+
+ pos.x = 100.0f/640.0f;
+ pos.y = 364.0f/480.0f;
+ ddim.x = 210.0f/640.0f;
+ ddim.y = 14.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 3, EVENT_NULL); // transparent -> gray
+
+ pos.x = 120.0f/640.0f;
+ pos.y = 364.0f/480.0f;
+ ddim.x = 80.0f/640.0f;
+ ddim.y = 28.0f/480.0f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PHEAD);
+ pb->SetState(STATE_SHADOW);
+ pb->SetState(STATE_CARD);
+
+ pos.x = 210.0f/640.0f;
+ pos.y = 364.0f/480.0f;
+ ddim.x = 80.0f/640.0f;
+ ddim.y = 28.0f/480.0f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PBODY);
+ pb->SetState(STATE_SHADOW);
+ pb->SetState(STATE_CARD);
+
+ pos.x = 100.0f/640.0f;
+ pos.y = 354.0f/480.0f;
+ ddim.x = 210.0f/640.0f;
+ ddim.y = 10.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 1, EVENT_INTERFACE_GLINTb); // orange bar
+ pos.x = 100.0f/640.0f;
+ pos.y = 154.0f/480.0f;
+ ddim.x = 210.0f/640.0f;
+ ddim.y = 200.0f/480.0f;
+ pw->CreateGroup(pos, ddim, 2, EVENT_INTERFACE_GLINTu); // orange -> transparent
+
+ // Face
+ pos.x = 340.0f/640.0f;
+ pos.y = 356.0f/480.0f;
+ ddim.x = 200.0f/640.0f;
+ ddim.y = 16.0f/480.0f;
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL11, "");
+ pl->SetJustif(1);
+
+ pos.x = 340.0f/640.0f;
+ pos.y = 312.0f/480.0f;
+ ddim.x = 44.0f/640.0f;
+ ddim.y = 44.0f/480.0f;
+ pb = pw->CreateButton(pos, ddim, 43, EVENT_INTERFACE_PFACE1);
+ pb->SetState(STATE_SHADOW);
+ pos.x += 50.0f/640.0f;
+ pb = pw->CreateButton(pos, ddim, 46, EVENT_INTERFACE_PFACE4);
+ pb->SetState(STATE_SHADOW);
+ pos.x += 50.0f/640.0f;
+ pb = pw->CreateButton(pos, ddim, 45, EVENT_INTERFACE_PFACE3);
+ pb->SetState(STATE_SHADOW);
+ pos.x += 50.0f/640.0f;
+ pb = pw->CreateButton(pos, ddim, 44, EVENT_INTERFACE_PFACE2);
+ pb->SetState(STATE_SHADOW);
+
+ // Glasses
+ pos.x = 340.0f/640.0f;
+ pos.y = 270.0f/480.0f;
+ ddim.x = 200.0f/640.0f;
+ ddim.y = 16.0f/480.0f;
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL12, "");
+ pl->SetJustif(1);
+
+ pos.x = 340.0f/640.0f;
+ pos.y = 240.0f/480.0f;
+ ddim.x = 30.0f/640.0f;
+ ddim.y = 30.0f/480.0f;
+ for ( i=0 ; i<6 ; i++ )
+ {
+ int ti[6] = {11, 179, 180, 181, 182, 183};
+ pb = pw->CreateButton(pos, ddim, ti[i], (EventMsg)(EVENT_INTERFACE_PGLASS0+i));
+ pb->SetState(STATE_SHADOW);
+ pos.x += (30.0f+2.8f)/640.0f;
+ }
+
+ // Color A
+ pos.x = 340.0f/640.0f;
+ pos.y = 300.0f/480.0f;
+ ddim.x = 200.0f/640.0f;
+ ddim.y = 16.0f/480.0f;
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL14, "");
+ pl->SetJustif(1);
+
+ pos.y = 282.0f/480.0f;
+ ddim.x = 18.0f/640.0f;
+ ddim.y = 18.0f/480.0f;
+ for ( j=0 ; j<3 ; j++ )
+ {
+ pos.x = 340.0f/640.0f;
+ for ( i=0 ; i<3 ; i++ )
+ {
+ pco = pw->CreateColor(pos, ddim, -1, (EventMsg)(EVENT_INTERFACE_PC0a+j*3+i));
+ pco->SetState(STATE_SHADOW);
+ pos.x += 20.0f/640.0f;
+ }
+ pos.y -= 20.0f/480.0f;
+ }
+
+ pos.x = 420.0f/640.0f;
+ pos.y = 282.0f/480.0f;
+ ddim.x = 100.0f/640.0f;
+ ddim.y = 18.0f/480.0f;
+ for ( i=0 ; i<3 ; i++ )
+ {
+ psl = pw->CreateSlider(pos, ddim, 0, (EventMsg)(EVENT_INTERFACE_PCRa+i));
+ psl->SetState(STATE_SHADOW);
+ psl->SetLimit(0.0f, 255.0f);
+ psl->SetArrowStep(16.0f);
+ pos.y -= 20.0f/480.0f;
+ }
+
+ // Color B
+ pos.x = 340.0f/640.0f;
+ pos.y = 192.0f/480.0f;
+ ddim.x = 200.0f/640.0f;
+ ddim.y = 16.0f/480.0f;
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL13, "");
+ pl->SetJustif(1);
+
+ pos.y = 174.0f/480.0f;
+ ddim.x = 18.0f/640.0f;
+ ddim.y = 18.0f/480.0f;
+ for ( j=0 ; j<3 ; j++ )
+ {
+ pos.x = 340.0f/640.0f;
+ for ( i=0 ; i<3 ; i++ )
+ {
+ pco = pw->CreateColor(pos, ddim, -1, (EventMsg)(EVENT_INTERFACE_PC0b+j*3+i));
+ pco->SetState(STATE_SHADOW);
+ pos.x += 20.0f/640.0f;
+ }
+ pos.y -= 20.0f/480.0f;
+ }
+
+ pos.x = 420.0f/640.0f;
+ pos.y = 174.0f/480.0f;
+ ddim.x = 100.0f/640.0f;
+ ddim.y = 18.0f/480.0f;
+ for ( i=0 ; i<3 ; i++ )
+ {
+ psl = pw->CreateSlider(pos, ddim, 0, (EventMsg)(EVENT_INTERFACE_PCRb+i));
+ psl->SetState(STATE_SHADOW);
+ psl->SetLimit(0.0f, 255.0f);
+ psl->SetArrowStep(16.0f);
+ pos.y -= 20.0f/480.0f;
+ }
+
+ // Rotation
+ pos.x = 100.0f/640.0f;
+ pos.y = 113.0f/480.0f;
+ ddim.x = 20.0f/640.0f;
+ ddim.y = 20.0f/480.0f;
+ pb = pw->CreateButton(pos, ddim, 55, EVENT_INTERFACE_PLROT); // <
+ pb->SetState(STATE_SHADOW);
+ pb->SetRepeat(true);
+
+ pos.x = 290.0f/640.0f;
+ pos.y = 113.0f/480.0f;
+ ddim.x = 20.0f/640.0f;
+ ddim.y = 20.0f/480.0f;
+ pb = pw->CreateButton(pos, ddim, 48, EVENT_INTERFACE_PRROT); // >
+ pb->SetState(STATE_SHADOW);
+ pb->SetRepeat(true);
+
+ pos.x = 100.0f/640.0f;
+ pos.y = 70.0f/480.0f;
+ ddim.x = 100.0f/640.0f;
+ ddim.y = 32.0f/480.0f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_POK);
+ pb->SetState(STATE_SHADOW);
+
+ pos.x = 210.0f/640.0f;
+ pos.y = 70.0f/480.0f;
+ ddim.x =100.0f/640.0f;
+ ddim.y = 32.0f/480.0f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PCANCEL);
+ pb->SetState(STATE_SHADOW);
+
+ pos.x = 340.0f/640.0f;
+ pos.y = 70.0f/480.0f;
+ ddim.x =194.0f/640.0f;
+ ddim.y = 32.0f/480.0f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PDEF);
+ pb->SetState(STATE_SHADOW);
+
+ m_persoCopy = m_perso;
+ m_persoTab = 0;
+ m_persoAngle = -0.6f;
+ UpdatePerso();
+ m_main->ScenePerso();
+ CameraPerso();
+ }
+
+ if ( m_phase == PHASE_TRAINER ||
+ m_phase == PHASE_DEFI ||
+ m_phase == PHASE_MISSION ||
+ m_phase == PHASE_FREE ||
+ m_phase == PHASE_TEEN ||
+ m_phase == PHASE_USER ||
+ m_phase == PHASE_PROTO )
+ {
+ if ( m_phase == PHASE_TRAINER ) m_index = 0;
+ if ( m_phase == PHASE_DEFI ) m_index = 1;
+ if ( m_phase == PHASE_MISSION ) m_index = 2;
+ if ( m_phase == PHASE_FREE ) m_index = 3;
+ if ( m_phase == PHASE_USER ) m_index = 4;
+ if ( m_phase == PHASE_PROTO ) m_index = 5;
+ if ( m_phase == PHASE_TEEN ) m_index = 6;
+
+ if ( m_phase == PHASE_FREE )
+ {
+ strcpy(m_sceneName, "scene");
+ ReadGamerInfo();
+ m_accessChap = RetChapPassed();
+ }
+
+ if ( m_phase == PHASE_TRAINER ) strcpy(m_sceneName, "train");
+ if ( m_phase == PHASE_DEFI ) strcpy(m_sceneName, "defi" );
+ if ( m_phase == PHASE_MISSION ) strcpy(m_sceneName, "scene");
+ if ( m_phase == PHASE_FREE ) strcpy(m_sceneName, "free");
+ if ( m_phase == PHASE_TEEN ) strcpy(m_sceneName, "teen");
+ if ( m_phase == PHASE_USER ) strcpy(m_sceneName, "user");
+ if ( m_phase == PHASE_PROTO ) strcpy(m_sceneName, "proto");
+
+ ReadGamerInfo();
+
+ pos.x = 0.10f;
+ pos.y = 0.10f;
+ ddim.x = 0.80f;
+ ddim.y = 0.80f;
+ pw = m_interface->CreateWindows(pos, ddim, 12, EVENT_WINDOW5);
+ pw->SetClosable(true);
+ if ( m_phase == PHASE_TRAINER ) res = RT_TITLE_TRAINER;
+ if ( m_phase == PHASE_DEFI ) res = RT_TITLE_DEFI;
+ if ( m_phase == PHASE_MISSION ) res = RT_TITLE_MISSION;
+ if ( m_phase == PHASE_FREE ) res = RT_TITLE_FREE;
+ if ( m_phase == PHASE_TEEN ) res = RT_TITLE_TEEN;
+ if ( m_phase == PHASE_USER ) res = RT_TITLE_USER;
+ if ( m_phase == PHASE_PROTO ) res = RT_TITLE_PROTO;
+ GetResource(RES_TEXT, res, name);
+ pw->SetName(name);
+
+#if _NEWLOOK
+ pos.x = 100.0f/640.0f;
+ pos.y = 226.0f/480.0f;
+ ddim.x = 216.0f/640.0f;
+ ddim.y = 160.0f/480.0f;
+ pg = pw->CreateGroup(pos, ddim, 23, EVENT_LABEL1); // blue
+ pg->SetState(STATE_SHADOW);
+ pos.x = 322.0f/640.0f;
+ pg = pw->CreateGroup(pos, ddim, 24, EVENT_LABEL1); // cyan
+ pg->SetState(STATE_SHADOW);
+
+ pos.x = 100.0f/640.0f;
+ pos.y = 122.0f/480.0f;
+ ddim.x = 438.0f/640.0f;
+ ddim.y = 98.0f/480.0f;
+ pg = pw->CreateGroup(pos, ddim, 25, EVENT_LABEL1); // green
+ pg->SetState(STATE_SHADOW);
+ pos.y = 66.0f/480.0f;
+ ddim.y = 42.0f/480.0f;
+ pg = pw->CreateGroup(pos, ddim, 26, EVENT_LABEL1); // violet
+ pg->SetState(STATE_SHADOW);
+#endif
+
+ pos.x = 0.10f;
+ pos.y = 0.40f;
+ ddim.x = 0.50f;
+ ddim.y = 0.50f;
+ pw->CreateGroup(pos, ddim, 5, EVENT_INTERFACE_GLINTl); // orange corner
+ pos.x = 0.40f;
+ pos.y = 0.10f;
+ ddim.x = 0.50f;
+ ddim.y = 0.50f;
+ pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner
+
+ // Displays a list of chapters:
+ pos.x = ox+sx*3;
+ pos.y = oy+sy*10.5f;
+ ddim.x = dim.x*7.5f;
+ ddim.y = dim.y*0.6f;
+ if ( m_phase == PHASE_TRAINER ) res = RT_PLAY_CHAPt;
+ if ( m_phase == PHASE_DEFI ) res = RT_PLAY_CHAPd;
+ if ( m_phase == PHASE_MISSION ) res = RT_PLAY_CHAPm;
+ if ( m_phase == PHASE_FREE ) res = RT_PLAY_CHAPf;
+ if ( m_phase == PHASE_TEEN ) res = RT_PLAY_CHAPte;
+ if ( m_phase == PHASE_USER ) res = RT_PLAY_CHAPu;
+ if ( m_phase == PHASE_PROTO ) res = RT_PLAY_CHAPp;
+ GetResource(RES_TEXT, res, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL11, name);
+ pl->SetJustif(1);
+
+ pos.y = oy+sy*6.7f;
+ ddim.y = dim.y*4.5f;
+ ddim.x = dim.x*6.5f;
+ pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_CHAP);
+ pli->SetState(STATE_SHADOW);
+ UpdateSceneChap(m_chap[m_index]);
+ if ( m_phase != PHASE_USER ) pli->SetState(STATE_EXTEND);
+
+ // Displays a list of missions:
+ pos.x = ox+sx*9.5f;
+ pos.y = oy+sy*10.5f;
+ ddim.x = dim.x*7.5f;
+ ddim.y = dim.y*0.6f;
+ if ( m_phase == PHASE_TRAINER ) res = RT_PLAY_LISTt;
+ if ( m_phase == PHASE_DEFI ) res = RT_PLAY_LISTd;
+ if ( m_phase == PHASE_MISSION ) res = RT_PLAY_LISTm;
+ if ( m_phase == PHASE_FREE ) res = RT_PLAY_LISTf;
+ if ( m_phase == PHASE_TEEN ) res = RT_PLAY_LISTk;
+ if ( m_phase == PHASE_USER ) res = RT_PLAY_LISTu;
+ if ( m_phase == PHASE_PROTO ) res = RT_PLAY_LISTp;
+ GetResource(RES_TEXT, res, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL12, name);
+ pl->SetJustif(1);
+
+ pos.y = oy+sy*6.7f;
+ ddim.y = dim.y*4.5f;
+ ddim.x = dim.x*6.5f;
+ pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_LIST);
+ pli->SetState(STATE_SHADOW);
+ UpdateSceneList(m_chap[m_index], m_sel[m_index]);
+ if ( m_phase != PHASE_USER ) pli->SetState(STATE_EXTEND);
+ pos = pli->RetPos();
+ ddim = pli->RetDim();
+
+ // Displays the summary:
+ pos.x = ox+sx*3;
+ pos.y = oy+sy*5.4f;
+ ddim.x = dim.x*6.5f;
+ ddim.y = dim.y*0.6f;
+ GetResource(RES_TEXT, RT_PLAY_RESUME, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL13, name);
+ pl->SetJustif(1);
+
+ pos.x = ox+sx*3;
+ pos.y = oy+sy*3.6f;
+ ddim.x = dim.x*13.4f;
+ ddim.y = dim.y*1.9f;
+ pe = pw->CreateEdit(pos, ddim, 0, EVENT_INTERFACE_RESUME);
+ pe->SetState(STATE_SHADOW);
+ pe->SetMaxChar(500);
+ pe->SetEditCap(false); // just to see
+ pe->SetHiliteCap(false);
+
+ // Button displays the "soluce":
+ if ( m_phase != PHASE_TRAINER &&
+ m_phase != PHASE_FREE &&
+ m_phase != PHASE_TEEN )
+ {
+ pos.x = ox+sx*9.5f;
+ pos.y = oy+sy*5.8f;
+ ddim.x = dim.x*6.5f;
+ ddim.y = dim.y*0.5f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_SOLUCE);
+ pc->SetState(STATE_SHADOW);
+ pc->ClearState(STATE_CHECK);
+ }
+ m_bSceneSoluce = false;
+
+ UpdateSceneResume((m_chap[m_index]+1)*100+(m_sel[m_index]+1));
+
+ if ( m_phase == PHASE_MISSION ||
+ m_phase == PHASE_FREE ||
+ m_phase == PHASE_USER )
+ {
+ pos.x = ox+sx*9.5f;
+ pos.y = oy+sy*2;
+ ddim.x = dim.x*3.7f;
+ ddim.y = dim.y*1;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PLAY);
+ pb->SetState(STATE_SHADOW);
+ if ( m_maxList == 0 )
+ {
+ pb->ClearState(STATE_ENABLE);
+ }
+
+ pos.x += dim.x*4.0f;
+ ddim.x = dim.x*2.5f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_READ);
+ pb->SetState(STATE_SHADOW);
+ if ( !IsIOReadScene() ) // no file to read?
+ {
+ pb->ClearState(STATE_ENABLE);
+ }
+ }
+ else
+ {
+ pos.x = ox+sx*9.5f;
+ pos.y = oy+sy*2;
+ ddim.x = dim.x*6.5f;
+ ddim.y = dim.y*1;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PLAY);
+ pb->SetState(STATE_SHADOW);
+ if ( m_maxList == 0 )
+ {
+ pb->ClearState(STATE_ENABLE);
+ }
+ }
+
+ pos.x = ox+sx*3;
+ ddim.x = dim.x*4;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_BACK);
+ pb->SetState(STATE_SHADOW);
+
+ m_engine->SetBackground("inter01.tga", 0,0, 0,0, true, true);
+ m_engine->SetBackForce(true);
+ }
+
+ if ( m_phase == PHASE_SETUPd ||
+ m_phase == PHASE_SETUPg ||
+ m_phase == PHASE_SETUPp ||
+ m_phase == PHASE_SETUPc ||
+ m_phase == PHASE_SETUPs ||
+ m_phase == PHASE_SETUPds ||
+ m_phase == PHASE_SETUPgs ||
+ m_phase == PHASE_SETUPps ||
+ m_phase == PHASE_SETUPcs ||
+ m_phase == PHASE_SETUPss )
+ {
+ if ( m_phase == PHASE_SETUPds )
+ {
+ m_phaseSetup = PHASE_SETUPd;
+ m_bSimulSetup = true;
+ }
+ else if ( m_phase == PHASE_SETUPgs )
+ {
+ m_phaseSetup = PHASE_SETUPg;
+ m_bSimulSetup = true;
+ }
+ else if ( m_phase == PHASE_SETUPps )
+ {
+ m_phaseSetup = PHASE_SETUPp;
+ m_bSimulSetup = true;
+ }
+ else if ( m_phase == PHASE_SETUPcs )
+ {
+ m_phaseSetup = PHASE_SETUPc;
+ m_bSimulSetup = true;
+ }
+ else if ( m_phase == PHASE_SETUPss )
+ {
+ m_phaseSetup = PHASE_SETUPs;
+ m_bSimulSetup = true;
+ }
+ else
+ {
+ m_phaseSetup = m_phase;
+ m_bSimulSetup = false;
+ }
+
+ pos.x = 0.10f;
+ pos.y = 0.10f;
+ ddim.x = 0.80f;
+ ddim.y = 0.80f;
+ pw = m_interface->CreateWindows(pos, ddim, 12, EVENT_WINDOW5);
+ pw->SetClosable(true);
+ GetResource(RES_TEXT, RT_TITLE_SETUP, name);
+ pw->SetName(name);
+
+ pos.x = 0.70f;
+ pos.y = 0.10f;
+ ddim.x = 0.20f;
+ ddim.y = 0.20f;
+ pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner
+
+ pos.x = 0.10f;
+ ddim.x = 0.80f;
+ pos.y = 0.76f;
+ ddim.y = 0.05f;
+ pw->CreateGroup(pos, ddim, 3, EVENT_NULL); // transparent -> gray
+
+#if _NEWLOOK
+ if ( m_phase == PHASE_SETUPd || // setup/display ?
+ m_phase == PHASE_SETUPds )
+ {
+ pos.x = 100.0f/640.0f;
+ pos.y = 130.0f/480.0f;
+ ddim.x = 216.0f/640.0f;
+ ddim.y = 212.0f/480.0f;
+ pg = pw->CreateGroup(pos, ddim, 23, EVENT_LABEL1); // blue
+ pg->SetState(STATE_SHADOW);
+ pos.x = 324.0f/640.0f;
+ pg = pw->CreateGroup(pos, ddim, 24, EVENT_LABEL1); // cyan
+ pg->SetState(STATE_SHADOW);
+ }
+ if ( m_phase == PHASE_SETUPg || // setup/graphic ?
+ m_phase == PHASE_SETUPgs )
+ {
+ pos.x = 100.0f/640.0f;
+ pos.y = 130.0f/480.0f;
+ ddim.x = 174.0f/640.0f;
+ ddim.y = 212.0f/480.0f;
+ pg = pw->CreateGroup(pos, ddim, 23, EVENT_LABEL1); // blue
+ pg->SetState(STATE_SHADOW);
+ pos.x = 282.0f/640.0f;
+ ddim.x = 258.0f/640.0f;
+ pg = pw->CreateGroup(pos, ddim, 24, EVENT_LABEL1); // cyan
+ pg->SetState(STATE_SHADOW);
+ }
+ if ( m_phase == PHASE_SETUPp || // setup/game ?
+ m_phase == PHASE_SETUPps )
+ {
+ pos.x = 100.0f/640.0f;
+ pos.y = 130.0f/480.0f;
+ ddim.x = 226.0f/640.0f;
+ ddim.y = 212.0f/480.0f;
+ pg = pw->CreateGroup(pos, ddim, 23, EVENT_LABEL1); // blue
+ pg->SetState(STATE_SHADOW);
+ pos.x = 334.0f/640.0f;
+ ddim.x = 206.0f/640.0f;
+ pg = pw->CreateGroup(pos, ddim, 24, EVENT_LABEL1); // cyan
+ pg->SetState(STATE_SHADOW);
+ }
+ if ( m_phase == PHASE_SETUPc || // setup/command ?
+ m_phase == PHASE_SETUPcs )
+ {
+ pos.x = 100.0f/640.0f;
+ pos.y = 125.0f/480.0f;
+ ddim.x = 440.0f/640.0f;
+ ddim.y = 222.0f/480.0f;
+ pg = pw->CreateGroup(pos, ddim, 23, EVENT_LABEL1); // blue
+ pg->SetState(STATE_SHADOW);
+ }
+ if ( m_phase == PHASE_SETUPs || // setup/sound ?
+ m_phase == PHASE_SETUPss )
+ {
+ pos.x = 100.0f/640.0f;
+ pos.y = 130.0f/480.0f;
+ ddim.x = 216.0f/640.0f;
+ ddim.y = 212.0f/480.0f;
+ pg = pw->CreateGroup(pos, ddim, 23, EVENT_LABEL1); // blue
+ pg->SetState(STATE_SHADOW);
+ pos.x = 324.0f/640.0f;
+ pg = pw->CreateGroup(pos, ddim, 24, EVENT_LABEL1); // cyan
+ pg->SetState(STATE_SHADOW);
+ }
+
+ pos.x = 100.0f/640.0f;
+ pos.y = 66.0f/480.0f;
+ ddim.x = 440.0f/640.0f;
+ ddim.y = 42.0f/480.0f;
+ pg = pw->CreateGroup(pos, ddim, 26, EVENT_LABEL1); // violet
+ pg->SetState(STATE_SHADOW);
+#endif
+
+ ddim.x = 0.78f/5-0.01f;
+ ddim.y = 0.06f;
+ pos.x = 0.115f;
+ pos.y = 0.76f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_SETUPd);
+ pb->SetState(STATE_SHADOW);
+ pb->SetState(STATE_CARD);
+ pb->SetState(STATE_CHECK, (m_phase == PHASE_SETUPd || m_phase == PHASE_SETUPds));
+
+ pos.x += ddim.x+0.01f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_SETUPg);
+ pb->SetState(STATE_SHADOW);
+ pb->SetState(STATE_CARD);
+ pb->SetState(STATE_CHECK, (m_phase == PHASE_SETUPg || m_phase == PHASE_SETUPgs));
+
+ pos.x += ddim.x+0.01f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_SETUPp);
+ pb->SetState(STATE_SHADOW);
+ pb->SetState(STATE_CARD);
+ pb->SetState(STATE_CHECK, (m_phase == PHASE_SETUPp || m_phase == PHASE_SETUPps));
+
+ pos.x += ddim.x+0.01f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_SETUPc);
+ pb->SetState(STATE_SHADOW);
+ pb->SetState(STATE_CARD);
+ pb->SetState(STATE_CHECK, (m_phase == PHASE_SETUPc || m_phase == PHASE_SETUPcs));
+
+ pos.x += ddim.x+0.01f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_SETUPs);
+ pb->SetState(STATE_SHADOW);
+ pb->SetState(STATE_CARD);
+ pb->SetState(STATE_CHECK, (m_phase == PHASE_SETUPs || m_phase == PHASE_SETUPss));
+
+ pos.x = 0.10f;
+ ddim.x = 0.80f;
+ pos.y = 0.34f;
+ ddim.y = 0.42f;
+ pw->CreateGroup(pos, ddim, 2, EVENT_INTERFACE_GLINTu); // orange -> transparent
+ pos.x = 0.10f+(6.0f/640.0f);
+ ddim.x = 0.80f-(11.0f/640.0f);
+ pos.y = 0.74f;
+ ddim.y = 0.02f;
+ pw->CreateGroup(pos, ddim, 1, EVENT_INTERFACE_GLINTb); // orange bar
+
+ ddim.x = dim.x*4;
+ ddim.y = dim.y*1;
+ pos.x = ox+sx*3;
+ pos.y = oy+sy*2;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_BACK);
+ pb->SetState(STATE_SHADOW);
+
+ if ( !m_bSimulSetup )
+ {
+ m_engine->SetBackground("inter01.tga", 0,0, 0,0, true, true);
+ m_engine->SetBackForce(true);
+ }
+ }
+
+ if ( m_phase == PHASE_SETUPd || // setup/display ?
+ m_phase == PHASE_SETUPds )
+ {
+ pos.x = ox+sx*3;
+ pos.y = oy+sy*9;
+ ddim.x = dim.x*6;
+ ddim.y = dim.y*1;
+ GetResource(RES_TEXT, RT_SETUP_DEVICE, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, name);
+ pl->SetJustif(1);
+
+ pos.x = ox+sx*3;
+ pos.y = oy+sy*5.2f;
+ ddim.x = dim.x*6;
+ ddim.y = dim.y*4.5f;
+ pli = pw->CreateList(pos, ddim, 0, EVENT_LIST1);
+ pli->SetState(STATE_SHADOW);
+ UpdateDisplayDevice();
+
+ pos.x = ox+sx*10;
+ pos.y = oy+sy*9;
+ ddim.x = dim.x*6;
+ ddim.y = dim.y*1;
+ GetResource(RES_TEXT, RT_SETUP_MODE, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL2, name);
+ pl->SetJustif(1);
+
+ m_setupFull = m_engine->RetFullScreen();
+ pos.x = ox+sx*10;
+ pos.y = oy+sy*5.2f;
+ ddim.x = dim.x*6;
+ ddim.y = dim.y*4.5f;
+ pli = pw->CreateList(pos, ddim, 0, EVENT_LIST2);
+ pli->SetState(STATE_SHADOW);
+ UpdateDisplayMode();
+ pli->SetState(STATE_ENABLE, m_setupFull);
+
+ ddim.x = dim.x*4;
+ ddim.y = dim.y*0.5f;
+ pos.x = ox+sx*3;
+ pos.y = oy+sy*4.1f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_FULL);
+ pc->SetState(STATE_SHADOW);
+ pc->SetState(STATE_CHECK, m_setupFull);
+
+ ddim.x = dim.x*6;
+ ddim.y = dim.y*1;
+ pos.x = ox+sx*10;
+ pos.y = oy+sy*2;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_APPLY);
+ pb->SetState(STATE_SHADOW);
+ UpdateApply();
+ }
+
+ if ( m_phase == PHASE_SETUPg || // setup/graphic ?
+ m_phase == PHASE_SETUPgs )
+ {
+ ddim.x = dim.x*6;
+ ddim.y = dim.y*0.5f;
+ pos.x = ox+sx*3;
+ pos.y = 0.65f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_SHADOW);
+ pc->SetState(STATE_SHADOW);
+ pos.y -= 0.048f;
+ if ( !m_bSimulSetup )
+ {
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_GROUND);
+ pc->SetState(STATE_SHADOW);
+ if ( m_engine->IsVideo8MB() ) pc->ClearState(STATE_ENABLE);
+ }
+ pos.y -= 0.048f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_DIRTY);
+ pc->SetState(STATE_SHADOW);
+ pos.y -= 0.048f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_SKY);
+ pc->SetState(STATE_SHADOW);
+ if ( m_engine->IsVideo8MB() ) pc->ClearState(STATE_ENABLE);
+ pos.y -= 0.048f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_LENS);
+ pc->SetState(STATE_SHADOW);
+ pos.y -= 0.048f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_PLANET);
+ pc->SetState(STATE_SHADOW);
+ pos.y -= 0.048f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_FOG);
+ pc->SetState(STATE_SHADOW);
+ pos.y -= 0.048f;
+ if ( !m_bSimulSetup )
+ {
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_LIGHT);
+ pc->SetState(STATE_SHADOW);
+ }
+
+ pos.x = ox+sx*8.5f;
+ pos.y = 0.65f;
+ ddim.x = dim.x*2.2f;
+ ddim.y = 18.0f/480.0f;
+ pv = pw->CreateEditValue(pos, ddim, 0, EVENT_INTERFACE_PARTI);
+ pv->SetState(STATE_SHADOW);
+ pv->SetMinValue(0.0f);
+ pv->SetMaxValue(2.0f);
+ pos.x += 0.13f;
+ pos.y -= 0.015f;
+ ddim.x = 0.40f;
+ GetResource(RES_EVENT, EVENT_INTERFACE_PARTI, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL10, name);
+ pl->SetJustif(1);
+
+ pos.x = ox+sx*8.5f;
+ pos.y = 0.59f;
+ ddim.x = dim.x*2.2f;
+ ddim.y = 18.0f/480.0f;
+ pv = pw->CreateEditValue(pos, ddim, 0, EVENT_INTERFACE_CLIP);
+ pv->SetState(STATE_SHADOW);
+ pv->SetMinValue(0.5f);
+ pv->SetMaxValue(2.0f);
+ pos.x += 0.13f;
+ pos.y -= 0.015f;
+ ddim.x = 0.40f;
+ GetResource(RES_EVENT, EVENT_INTERFACE_CLIP, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL11, name);
+ pl->SetJustif(1);
+
+ pos.x = ox+sx*8.5f;
+ pos.y = 0.53f;
+ ddim.x = dim.x*2.2f;
+ ddim.y = 18.0f/480.0f;
+ pv = pw->CreateEditValue(pos, ddim, 0, EVENT_INTERFACE_DETAIL);
+ pv->SetState(STATE_SHADOW);
+ pv->SetMinValue(0.0f);
+ pv->SetMaxValue(2.0f);
+ pos.x += 0.13f;
+ pos.y -= 0.015f;
+ ddim.x = 0.40f;
+ GetResource(RES_EVENT, EVENT_INTERFACE_DETAIL, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL12, name);
+ pl->SetJustif(1);
+
+ if ( !m_bSimulSetup )
+ {
+ pos.x = ox+sx*8.5f;
+ pos.y = 0.47f;
+ ddim.x = dim.x*2.2f;
+ ddim.y = 18.0f/480.0f;
+ pv = pw->CreateEditValue(pos, ddim, 0, EVENT_INTERFACE_GADGET);
+ pv->SetState(STATE_SHADOW);
+ pv->SetMinValue(0.0f);
+ pv->SetMaxValue(1.0f);
+ pos.x += 0.13f;
+ pos.y -= 0.015f;
+ ddim.x = 0.40f;
+ GetResource(RES_EVENT, EVENT_INTERFACE_GADGET, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL13, name);
+ pl->SetJustif(1);
+ }
+
+#if 0
+ if ( !m_bSimulSetup )
+ {
+ pos.x = ox+sx*8.5f;
+ pos.y = 0.41f;
+ ddim.x = dim.x*2.2f;
+ ddim.y = 18.0f/480.0f;
+ pv = pw->CreateEditValue(pos, ddim, 0, EVENT_INTERFACE_TEXTURE);
+ pv->SetState(STATE_SHADOW);
+ pv->SetType(EVT_INT);
+ pv->SetMinValue(0.0f);
+ pv->SetMaxValue(2.0f);
+ pv->SetStepValue(1.0f);
+ pos.x += 0.13f;
+ pos.y -= 0.015f;
+ ddim.x = 0.40f;
+ GetResource(RES_EVENT, EVENT_INTERFACE_TEXTURE, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL14, name);
+ pl->SetJustif(1);
+ }
+#endif
+
+ ddim.x = dim.x*2;
+ ddim.y = dim.y*1;
+ pos.x = ox+sx*10;
+ pos.y = oy+sy*2;
+#if _POLISH
+ ddim.x += 20.0f/640.0f;
+ pos.x -= 20.0f/640.0f*3.0f;
+#endif
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_MIN);
+ pb->SetState(STATE_SHADOW);
+ pos.x += ddim.x;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_NORM);
+ pb->SetState(STATE_SHADOW);
+ pos.x += ddim.x;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_MAX);
+ pb->SetState(STATE_SHADOW);
+
+ UpdateSetupButtons();
+ }
+
+ if ( m_phase == PHASE_SETUPp || // setup/game ?
+ m_phase == PHASE_SETUPps )
+ {
+ ddim.x = dim.x*6;
+ ddim.y = dim.y*0.5f;
+ pos.x = ox+sx*3;
+ pos.y = 0.65f;
+//? pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_TOTO);
+//? pc->SetState(STATE_SHADOW);
+//? pos.y -= 0.048f;
+#if _SCHOOL
+ #if _EDU
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_SOLUCE4);
+ pc->SetState(STATE_SHADOW);
+ pos.y -= 0.048f;
+ #endif
+#else
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_MOVIES);
+ pc->SetState(STATE_SHADOW);
+ pos.y -= 0.048f;
+#endif
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_SCROLL);
+ pc->SetState(STATE_SHADOW);
+ pos.y -= 0.048f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_INVERTX);
+ pc->SetState(STATE_SHADOW);
+ pos.y -= 0.048f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_INVERTY);
+ pc->SetState(STATE_SHADOW);
+ pos.y -= 0.048f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_EFFECT);
+ pc->SetState(STATE_SHADOW);
+//? pos.y -= 0.048f;
+//? pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_NICERST);
+//? pc->SetState(STATE_SHADOW);
+//? pos.y -= 0.048f;
+//? pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_HIMSELF);
+//? pc->SetState(STATE_SHADOW);
+
+ ddim.x = dim.x*6;
+ ddim.y = dim.y*0.5f;
+ pos.x = ox+sx*10;
+ pos.y = 0.65f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_TOOLTIP);
+ pc->SetState(STATE_SHADOW);
+ pos.y -= 0.048f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_GLINT);
+ pc->SetState(STATE_SHADOW);
+ pos.y -= 0.048f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_RAIN);
+ pc->SetState(STATE_SHADOW);
+ pos.y -= 0.048f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_MOUSE);
+ pc->SetState(STATE_SHADOW);
+ pos.y -= 0.048f;
+ pos.y -= 0.048f;
+ if ( !m_bSimulSetup )
+ {
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_EDITMODE);
+ pc->SetState(STATE_SHADOW);
+ }
+ pos.y -= 0.048f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_EDITVALUE);
+ pc->SetState(STATE_SHADOW);
+
+ UpdateSetupButtons();
+ }
+
+ if ( m_phase == PHASE_SETUPc || // setup/commands ?
+ m_phase == PHASE_SETUPcs )
+ {
+ pos.x = ox+sx*3;
+ pos.y = 320.0f/480.0f;
+ ddim.x = dim.x*15.0f;
+ ddim.y = 18.0f/480.0f;
+ GetResource(RES_TEXT, RT_SETUP_KEY1, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_INTERFACE_KINFO1, name);
+ pl->SetJustif(1);
+
+ pos.x = ox+sx*3;
+ pos.y = 302.0f/480.0f;
+ ddim.x = dim.x*15.0f;
+ ddim.y = 18.0f/480.0f;
+ GetResource(RES_TEXT, RT_SETUP_KEY2, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_INTERFACE_KINFO2, name);
+ pl->SetJustif(1);
+
+ ddim.x = 428.0f/640.0f;
+ ddim.y = 128.0f/480.0f;
+ pos.x = 105.0f/640.0f;
+ pos.y = 164.0f/480.0f;
+ pg = pw->CreateGroup(pos, ddim, 0, EVENT_INTERFACE_KGROUP);
+ pg->ClearState(STATE_ENABLE);
+ pg->SetState(STATE_DEAD);
+ pg->SetState(STATE_SHADOW);
+
+ ddim.x = 18.0f/640.0f;
+ ddim.y = (20.0f/480.0f)*KEY_VISIBLE;
+ pos.x = 510.0f/640.0f;
+ pos.y = 168.0f/480.0f;
+ ps = pw->CreateScroll(pos, ddim, -1, EVENT_INTERFACE_KSCROLL);
+ ps->SetVisibleRatio((float)KEY_VISIBLE/KEY_TOTAL);
+ ps->SetArrowStep(1.0f/((float)KEY_TOTAL-KEY_VISIBLE));
+ UpdateKey();
+
+ ddim.x = dim.x*6;
+ ddim.y = dim.y*0.5f;
+ pos.x = ox+sx*3;
+ pos.y = 130.0f/480.0f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_JOYSTICK);
+ pc->SetState(STATE_SHADOW);
+
+ ddim.x = dim.x*6;
+ ddim.y = dim.y*1;
+ pos.x = ox+sx*10;
+ pos.y = oy+sy*2;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_KDEF);
+ pb->SetState(STATE_SHADOW);
+
+ UpdateSetupButtons();
+ }
+
+ if ( m_phase == PHASE_SETUPs || // setup/sound ?
+ m_phase == PHASE_SETUPss )
+ {
+ pos.x = ox+sx*3;
+ pos.y = 0.55f;
+ ddim.x = dim.x*4.0f;
+ ddim.y = 18.0f/480.0f;
+ psl = pw->CreateSlider(pos, ddim, 0, EVENT_INTERFACE_VOLSOUND);
+ psl->SetState(STATE_SHADOW);
+ psl->SetLimit(0.0f, MAXVOLUME);
+ psl->SetArrowStep(1.0f);
+ pos.y += ddim.y;
+ GetResource(RES_EVENT, EVENT_INTERFACE_VOLSOUND, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, name);
+ pl->SetJustif(1);
+
+#if (_FULL | _NET) & _SOUNDTRACKS
+ pos.x = ox+sx*3;
+ pos.y = 0.40f;
+ ddim.x = dim.x*4.0f;
+ ddim.y = 18.0f/480.0f;
+ psl = pw->CreateSlider(pos, ddim, 0, EVENT_INTERFACE_VOLMUSIC);
+ psl->SetState(STATE_SHADOW);
+ psl->SetLimit(0.0f, MAXVOLUME);
+ psl->SetArrowStep(1.0f);
+ pos.y += ddim.y;
+ GetResource(RES_EVENT, EVENT_INTERFACE_VOLMUSIC, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL2, name);
+ pl->SetJustif(1);
+#endif
+
+ ddim.x = dim.x*6;
+ ddim.y = dim.y*0.5f;
+ pos.x = ox+sx*10;
+ pos.y = 0.55f;
+ pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_SOUND3D);
+ pc->SetState(STATE_SHADOW);
+
+ ddim.x = dim.x*3;
+ ddim.y = dim.y*1;
+ pos.x = ox+sx*10;
+ pos.y = oy+sy*2;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_SILENT);
+ pb->SetState(STATE_SHADOW);
+ pos.x += ddim.x;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_NOISY);
+ pb->SetState(STATE_SHADOW);
+
+ UpdateSetupButtons();
+ }
+
+ if ( m_phase == PHASE_WRITE ||
+ m_phase == PHASE_WRITEs )
+ {
+ pos.x = 0.10f;
+ pos.y = 0.10f;
+ ddim.x = 0.80f;
+ ddim.y = 0.80f;
+ pw = m_interface->CreateWindows(pos, ddim, 13, EVENT_WINDOW5);
+ pw->SetClosable(true);
+ GetResource(RES_TEXT, RT_TITLE_WRITE, name);
+ pw->SetName(name);
+
+ pos.x = 0.10f;
+ pos.y = 0.40f;
+ ddim.x = 0.50f;
+ ddim.y = 0.50f;
+ pw->CreateGroup(pos, ddim, 5, EVENT_INTERFACE_GLINTl); // orange corner
+ pos.x = 0.40f;
+ pos.y = 0.10f;
+ ddim.x = 0.50f;
+ ddim.y = 0.50f;
+ pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner
+
+#if _NEWLOOK
+ pos.x = 100.0f/640.0f;
+ pos.y = 66.0f/480.0f;
+ ddim.x = 438.0f/640.0f;
+ ddim.y = 42.0f/480.0f;
+ pg = pw->CreateGroup(pos, ddim, 26, EVENT_LABEL1); // violet
+ pg->SetState(STATE_SHADOW);
+#endif
+
+ pos.x = 290.0f/640.0f;
+ ddim.x = 245.0f/640.0f;
+
+ pos.y = 146.0f/480.0f;
+ ddim.y = 18.0f/480.0f;
+ GetResource(RES_EVENT, EVENT_INTERFACE_IOLABEL, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_INTERFACE_IOLABEL, name);
+ pl->SetJustif(1);
+
+ pos.y = 130.0f/480.0f;
+ ddim.y = 18.0f/480.0f;
+ pe = pw->CreateEdit(pos, ddim, 0, EVENT_INTERFACE_IONAME);
+ pe->SetState(STATE_SHADOW);
+ pe->SetFontType(FONT_COLOBOT);
+ pe->SetMaxChar(35);
+ IOReadName();
+
+ pos.y = 190.0f/480.0f;
+ ddim.y = 190.0f/480.0f;
+ pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_IOLIST);
+ pli->SetState(STATE_SHADOW);
+
+ pos.y = oy+sy*2;
+ ddim.y = dim.y*1;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_IOWRITE);
+ pb->SetState(STATE_SHADOW);
+
+ pos.x = 105.0f/640.0f;
+ pos.y = 190.0f/480.0f;
+ ddim.x = 170.0f/640.0f;
+ ddim.y = dim.y*1;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_IODELETE);
+ pb->SetState(STATE_SHADOW);
+
+ pos.x = 105.0f/640.0f;
+ pos.y = 250.0f/480.0f;
+ ddim.x = 170.0f/640.0f;
+ ddim.y = 128.0f/480.0f;
+ pi = pw->CreateImage(pos, ddim, 0, EVENT_INTERFACE_IOIMAGE);
+ pi->SetState(STATE_SHADOW);
+
+ ddim.x = dim.x*4;
+ ddim.y = dim.y*1;
+ pos.x = ox+sx*3;
+ pos.y = oy+sy*2;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_BACK);
+ pb->SetState(STATE_SHADOW);
+
+ IOReadList();
+ IOUpdateList();
+ }
+
+ if ( m_phase == PHASE_READ ||
+ m_phase == PHASE_READs )
+ {
+ pos.x = 0.10f;
+ pos.y = 0.10f;
+ ddim.x = 0.80f;
+ ddim.y = 0.80f;
+ pw = m_interface->CreateWindows(pos, ddim, 14, EVENT_WINDOW5);
+ pw->SetClosable(true);
+ GetResource(RES_TEXT, RT_TITLE_READ, name);
+ pw->SetName(name);
+
+ pos.x = 0.10f;
+ pos.y = 0.40f;
+ ddim.x = 0.50f;
+ ddim.y = 0.50f;
+ pw->CreateGroup(pos, ddim, 5, EVENT_INTERFACE_GLINTl); // orange corner
+ pos.x = 0.40f;
+ pos.y = 0.10f;
+ ddim.x = 0.50f;
+ ddim.y = 0.50f;
+ pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner
+
+#if _NEWLOOK
+ pos.x = 100.0f/640.0f;
+ pos.y = 66.0f/480.0f;
+ ddim.x = 438.0f/640.0f;
+ ddim.y = 42.0f/480.0f;
+ pg = pw->CreateGroup(pos, ddim, 26, EVENT_LABEL1); // violet
+ pg->SetState(STATE_SHADOW);
+#endif
+
+ pos.x = 290.0f/640.0f;
+ ddim.x = 245.0f/640.0f;
+
+ pos.y = 160.0f/480.0f;
+ ddim.y = 190.0f/480.0f;
+ pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_IOLIST);
+ pli->SetState(STATE_SHADOW);
+
+ pos.y = oy+sy*2;
+ ddim.y = dim.y*1;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_IOREAD);
+ pb->SetState(STATE_SHADOW);
+ if ( m_phase == PHASE_READs )
+ {
+ pb->SetState(STATE_WARNING);
+ }
+
+ pos.x = 105.0f/640.0f;
+ pos.y = 160.0f/480.0f;
+ ddim.x = 170.0f/640.0f;
+ ddim.y = dim.y*1;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_IODELETE);
+ pb->SetState(STATE_SHADOW);
+
+ pos.x = 105.0f/640.0f;
+ pos.y = 220.0f/480.0f;
+ ddim.x = 170.0f/640.0f;
+ ddim.y = 128.0f/480.0f;
+ pi = pw->CreateImage(pos, ddim, 0, EVENT_INTERFACE_IOIMAGE);
+ pi->SetState(STATE_SHADOW);
+
+ ddim.x = dim.x*4;
+ ddim.y = dim.y*1;
+ pos.x = ox+sx*3;
+ pos.y = oy+sy*2;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_BACK);
+ pb->SetState(STATE_SHADOW);
+
+ IOReadList();
+ IOUpdateList();
+
+ if ( m_phase == PHASE_READ )
+ {
+ m_engine->SetBackground("inter01.tga", 0,0, 0,0, true, true);
+ m_engine->SetBackForce(true);
+ }
+ }
+
+ if ( m_phase == PHASE_LOADING )
+ {
+ pos.x = 0.35f;
+ pos.y = 0.10f;
+ ddim.x = 0.30f;
+ ddim.y = 0.80f;
+#if _TEEN
+ pw = m_interface->CreateWindows(pos, ddim, 12, EVENT_WINDOW5);
+#else
+ pw = m_interface->CreateWindows(pos, ddim, 10, EVENT_WINDOW5);
+#endif
+ pw->SetName(" ");
+
+ pos.x = 0.35f;
+ pos.y = 0.60f;
+ ddim.x = 0.30f;
+ ddim.y = 0.30f;
+ pw->CreateGroup(pos, ddim, 5, EVENT_INTERFACE_GLINTl); // orange corner
+ pos.x = 0.35f;
+ pos.y = 0.10f;
+ ddim.x = 0.30f;
+ ddim.y = 0.30f;
+ pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner
+
+ pos.x = 254.0f/640.0f;
+ pos.y = 208.0f/480.0f;
+ ddim.x = 132.0f/640.0f;
+ ddim.y = 42.0f/480.0f;
+ pg = pw->CreateGroup(pos, ddim, 22, EVENT_NULL);
+ pg->SetState(STATE_SHADOW);
+
+ pos.x = 220.0f/640.0f;
+ pos.y = 210.0f/480.0f;
+ ddim.x = 200.0f/640.0f;
+ ddim.y = 20.0f/480.0f;
+ GetResource(RES_TEXT, RT_DIALOG_LOADING, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, name);
+ pl->SetFontSize(12.0f);
+ pl->SetJustif(0);
+
+ m_engine->SetBackground("inter01.tga", 0,0, 0,0, true, true);
+ m_engine->SetBackForce(true);
+
+ m_loadingCounter = 1; // enough time to display!
+ }
+
+ if ( m_phase == PHASE_WELCOME1 )
+ {
+ m_sound->StopMusic();
+ m_sound->PlayMusic(11, false);
+
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ ddim.x = 0.0f;
+ ddim.y = 0.0f;
+ pw = m_interface->CreateWindows(pos, ddim, -1, EVENT_WINDOW5);
+
+ m_engine->SetOverColor(RetColor(1.0f), D3DSTATETCb);
+ m_engine->SetOverFront(true);
+
+#if _FRENCH
+ m_engine->SetBackground("alsyd.tga", 0,0, 0,0, true, false);
+#endif
+#if _POLISH
+ m_engine->SetBackground("manta.tga", 0,0, 0,0, true, false);
+#endif
+#if _WG
+ m_engine->SetBackground("wg.tga", 0,0, 0,0, true, false);
+#endif
+ m_engine->SetBackForce(true);
+ }
+ if ( m_phase == PHASE_WELCOME2 )
+ {
+#if _ENGLISH
+ m_sound->StopMusic();
+ m_sound->PlayMusic(11, false);
+#endif
+#if _POLISH
+ m_sound->StopMusic();
+ m_sound->PlayMusic(11, false);
+#endif
+
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ ddim.x = 0.0f;
+ ddim.y = 0.0f;
+ pw = m_interface->CreateWindows(pos, ddim, -1, EVENT_WINDOW5);
+
+ m_engine->SetOverColor(RetColor(1.0f), D3DSTATETCb);
+ m_engine->SetOverFront(true);
+
+ m_engine->SetBackground("colobot.tga", 0,0, 0,0, true, false);
+ m_engine->SetBackForce(true);
+ }
+ if ( m_phase == PHASE_WELCOME3 )
+ {
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ ddim.x = 0.0f;
+ ddim.y = 0.0f;
+ pw = m_interface->CreateWindows(pos, ddim, -1, EVENT_WINDOW5);
+
+ m_engine->SetOverColor(RetColor(0.0f), D3DSTATETCw);
+ m_engine->SetOverFront(true);
+
+#if _FRENCH
+ m_engine->SetBackground("epsitecf.tga", 0,0, 0,0, true, false);
+#endif
+#if _ENGLISH
+ m_engine->SetBackground("epsitece.tga", 0,0, 0,0, true, false);
+#endif
+#if _GERMAN | _WG
+ m_engine->SetBackground("epsitecd.tga", 0,0, 0,0, true, false);
+#endif
+#if _POLISH
+ m_engine->SetBackground("epsitecp.tga", 0,0, 0,0, true, false);
+#endif
+ m_engine->SetBackForce(true);
+ }
+
+ if ( m_phase == PHASE_GENERIC )
+ {
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ ddim.x = 0.0f;
+ ddim.y = 0.0f;
+ pw = m_interface->CreateWindows(pos, ddim, -1, EVENT_WINDOW5);
+
+#if _FULL | _NET
+ pos.x = 80.0f/640.0f;
+ pos.y = 240.0f/480.0f;
+ ddim.x = 490.0f/640.0f;
+ ddim.y = 110.0f/480.0f;
+ pe = pw->CreateEdit(pos, ddim, 0, EVENT_EDIT1);
+ pe->SetGenericMode(true);
+ pe->SetEditCap(false);
+ pe->SetHiliteCap(false);
+ pe->SetFontType(FONT_COURIER);
+ pe->SetFontSize(8.0f);
+ pe->ReadText("help\\authors.txt");
+
+ pos.x = 80.0f/640.0f;
+ pos.y = 140.0f/480.0f;
+ ddim.x = 490.0f/640.0f;
+ ddim.y = 100.0f/480.0f;
+ pe = pw->CreateEdit(pos, ddim, 0, EVENT_EDIT2);
+ pe->SetGenericMode(true);
+ pe->SetEditCap(false);
+ pe->SetHiliteCap(false);
+ pe->SetFontType(FONT_COURIER);
+ pe->SetFontSize(6.5f);
+ pe->ReadText("help\\licences.txt");
+#endif
+#if _SCHOOL
+#if _CEEBOTDEMO
+ pos.x = 80.0f/640.0f;
+ pos.y = 210.0f/480.0f;
+ ddim.x = 490.0f/640.0f;
+ ddim.y = 150.0f/480.0f;
+#else
+ pos.x = 80.0f/640.0f;
+ pos.y = 200.0f/480.0f;
+ ddim.x = 490.0f/640.0f;
+ ddim.y = 150.0f/480.0f;
+#endif
+ pe = pw->CreateEdit(pos, ddim, 0, EVENT_EDIT1);
+ pe->SetGenericMode(true);
+ pe->SetEditCap(false);
+ pe->SetHiliteCap(false);
+ pe->SetFontType(FONT_COURIER);
+ pe->SetFontSize(8.0f);
+ pe->ReadText("help\\authors.txt");
+#endif
+#if _DEMO
+//? pos.x = 80.0f/640.0f;
+//? pos.y = 240.0f/480.0f;
+//? ddim.x = 490.0f/640.0f;
+//? ddim.y = 110.0f/480.0f;
+//? pe = pw->CreateEdit(pos, ddim, 0, EVENT_EDIT1);
+//? pe->SetGenericMode(true);
+//? pe->SetEditCap(false);
+//? pe->SetHiliteCap(false);
+//? pe->SetFontType(FONT_COURIER);
+//? pe->SetFontSize(8.0f);
+//? pe->ReadText("help\\demo.txt");
+
+//? pos.x = 80.0f/640.0f;
+//? pos.y = 140.0f/480.0f;
+//? ddim.x = 490.0f/640.0f;
+//? ddim.y = 100.0f/480.0f;
+//? pe = pw->CreateEdit(pos, ddim, 0, EVENT_EDIT2);
+//? pe->SetGenericMode(true);
+//? pe->SetEditCap(false);
+//? pe->SetHiliteCap(false);
+//? pe->SetFontType(FONT_COURIER);
+//? pe->SetFontSize(8.0f);
+//? pe->ReadText("help\\authors.txt");
+#endif
+
+#if !_DEMO
+ pos.x = 40.0f/640.0f;
+ pos.y = 83.0f/480.0f;
+ ddim.x = 246.0f/640.0f;
+ ddim.y = 16.0f/480.0f;
+ GetResource(RES_TEXT, RT_GENERIC_DEV1, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, name);
+ pl->SetFontType(FONT_COURIER);
+ pl->SetFontSize(8.0f);
+
+ pos.y = 13.0f/480.0f;
+ GetResource(RES_TEXT, RT_GENERIC_DEV2, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL2, name);
+ pl->SetFontType(FONT_COURIER);
+ pl->SetFontSize(8.0f);
+
+ pos.x = 355.0f/640.0f;
+ pos.y = 83.0f/480.0f;
+ ddim.x = 246.0f/640.0f;
+ ddim.y = 16.0f/480.0f;
+ GetResource(RES_TEXT, RT_GENERIC_EDIT1, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL3, name);
+ pl->SetFontType(FONT_COURIER);
+ pl->SetFontSize(8.0f);
+
+ pos.y = 13.0f/480.0f;
+ GetResource(RES_TEXT, RT_GENERIC_EDIT2, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL4, name);
+ pl->SetFontType(FONT_COURIER);
+ pl->SetFontSize(8.0f);
+#endif
+
+#if _DEMO
+ pos.x = 481.0f/640.0f;
+ pos.y = 51.0f/480.0f;
+ ddim.x = 30.0f/640.0f;
+ ddim.y = 30.0f/480.0f;
+ pb = pw->CreateButton(pos, ddim, 49, EVENT_INTERFACE_ABORT);
+ pb->SetState(STATE_SHADOW);
+#else
+ pos.x = 306.0f/640.0f;
+ pos.y = 17.0f/480.0f;
+ ddim.x = 30.0f/640.0f;
+ ddim.y = 30.0f/480.0f;
+ pb = pw->CreateButton(pos, ddim, 49, EVENT_INTERFACE_ABORT);
+ pb->SetState(STATE_SHADOW);
+#endif
+
+#if _NEWLOOK
+#if _CEEBOTDEMO
+#if _TEEN
+ m_engine->SetBackground("genedt.tga", 0,0, 0,0, true, true);
+#else
+ m_engine->SetBackground("geneda.tga", 0,0, 0,0, true, true);
+#endif
+#else
+ m_engine->SetBackground("genern.tga", 0,0, 0,0, true, true);
+#endif
+#else
+#if _FRENCH
+#if _DEMO
+ m_engine->SetBackground("genedf.tga", 0,0, 0,0, true, true);
+#else
+ m_engine->SetBackground("generf.tga", 0,0, 0,0, true, true);
+#endif
+#endif
+#if _ENGLISH
+#if _DEMO
+ m_engine->SetBackground("genede.tga", 0,0, 0,0, true, true);
+#else
+ m_engine->SetBackground("genere.tga", 0,0, 0,0, true, true);
+#endif
+#endif
+#if _GERMAN
+#if _DEMO
+ m_engine->SetBackground("genedd.tga", 0,0, 0,0, true, true);
+#else
+ m_engine->SetBackground("genere.tga", 0,0, 0,0, true, true);
+#endif
+#endif
+#if _WG
+#if _DEMO
+ m_engine->SetBackground("genedd.tga", 0,0, 0,0, true, true);
+#else
+ m_engine->SetBackground("generd.tga", 0,0, 0,0, true, true);
+#endif
+#endif
+#if _POLISH
+#if _DEMO
+ m_engine->SetBackground("genedp.tga", 0,0, 0,0, true, true);
+#else
+ m_engine->SetBackground("generp.tga", 0,0, 0,0, true, true);
+#endif
+#endif
+#endif
+ m_engine->SetBackForce(true);
+ }
+
+ if ( m_phase == PHASE_INIT ||
+ m_phase == PHASE_NAME ||
+ m_phase == PHASE_TRAINER ||
+ m_phase == PHASE_DEFI ||
+ m_phase == PHASE_MISSION ||
+ m_phase == PHASE_FREE ||
+ m_phase == PHASE_TEEN ||
+ m_phase == PHASE_USER ||
+ m_phase == PHASE_PROTO ||
+ m_phase == PHASE_SETUPd ||
+ m_phase == PHASE_SETUPg ||
+ m_phase == PHASE_SETUPp ||
+ m_phase == PHASE_SETUPc ||
+ m_phase == PHASE_SETUPs ||
+ m_phase == PHASE_READ ||
+ m_phase == PHASE_LOADING )
+ {
+#if _SCHOOL
+#if _TEEN
+ pos.x = 50.0f/640.0f;
+ pos.y = 430.0f/480.0f;
+ ddim.x = 200.0f/640.0f;
+ ddim.y = 10.0f/480.0f;
+#else
+ pos.x = 450.0f/640.0f;
+ pos.y = 0.0f/480.0f;
+ ddim.x = 170.0f/640.0f;
+ ddim.y = 9.0f/480.0f;
+#endif
+#else
+ pos.x = 540.0f/640.0f;
+ pos.y = 9.0f/480.0f;
+ ddim.x = 90.0f/640.0f;
+ ddim.y = 10.0f/480.0f;
+#endif
+ GetResource(RES_TEXT, RT_VERSION_ID, name);
+ pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL1, name);
+ pl->SetFontType(FONT_COURIER);
+ pl->SetFontSize(9.0f);
+ }
+
+ m_engine->LoadAllTexture();
+}
+
+
+// Processing an event.
+// Returns false if the event has been processed completely.
+
+bool CMainDialog::EventProcess(const Event &event)
+{
+ CWindow* pw;
+ CList* pl;
+ CButton* pb;
+ CCheck* pc;
+ Event newEvent;
+ float welcomeLength;
+
+ if ( event.event == EVENT_FRAME )
+ {
+ m_phaseTime += event.rTime;
+
+//? if ( m_phase == PHASE_WELCOME1 ) welcomeLength = WELCOME_LENGTH+2.0f;
+//? else welcomeLength = WELCOME_LENGTH;
+ welcomeLength = WELCOME_LENGTH;
+
+ if ( m_phase == PHASE_WELCOME1 ||
+ m_phase == PHASE_WELCOME2 ||
+ m_phase == PHASE_WELCOME3 )
+ {
+ float intensity;
+ int mode = D3DSTATETCb;
+
+ if ( m_phaseTime < 1.5f )
+ {
+ intensity = 1.0f-(m_phaseTime-0.5f);
+ }
+ else if ( m_phaseTime < welcomeLength-1.0f )
+ {
+ intensity = 0.0f;
+ }
+ else
+ {
+ intensity = m_phaseTime-(welcomeLength-1.0f);
+ }
+ if ( intensity < 0.0f ) intensity = 0.0f;
+ if ( intensity > 1.0f ) intensity = 1.0f;
+
+ if ( (m_phase == PHASE_WELCOME2 && m_phaseTime > welcomeLength/2.0f) ||
+ m_phase == PHASE_WELCOME3 )
+ {
+ intensity = 1.0f-intensity;
+ mode = D3DSTATETCw;
+ }
+
+ m_engine->SetOverColor(RetColor(intensity), mode);
+ }
+
+ if ( m_phase == PHASE_WELCOME1 && m_phaseTime >= welcomeLength )
+ {
+ ChangePhase(PHASE_WELCOME2);
+ return true;
+ }
+ if ( m_phase == PHASE_WELCOME2 && m_phaseTime >= welcomeLength )
+ {
+ ChangePhase(PHASE_WELCOME3);
+ return true;
+ }
+ if ( m_phase == PHASE_WELCOME3 && m_phaseTime >= welcomeLength )
+ {
+ ChangePhase(PHASE_NAME);
+ return true;
+ }
+
+ if ( m_shotDelay > 0 && !m_bDialog ) // screenshot done?
+ {
+ m_shotDelay --;
+ if ( m_shotDelay == 0 )
+ {
+ m_engine->WriteScreenShot(m_shotName, 320, 240);
+//? m_engine->WriteScreenShot(m_shotName, 160, 120);
+ }
+ }
+
+ if ( m_phase == PHASE_LOADING )
+ {
+ if ( m_loadingCounter == 0 )
+ {
+ m_main->ChangePhase(PHASE_SIMUL);
+ }
+ m_loadingCounter --;
+ return false;
+ }
+
+ m_glintTime += event.rTime;
+ GlintMove(); // moves reflections
+
+ FrameParticule(event.rTime);
+
+ if ( m_bDialog ) // this dialogue?
+ {
+ FrameDialog(event.rTime);
+ }
+
+ return true;
+ }
+
+ if ( event.event == EVENT_MOUSEMOVE )
+ {
+ m_glintMouse = event.pos;
+ NiceParticule(event.pos, event.keyState&KS_MLEFT);
+ }
+
+ if ( m_bDialog ) // this dialogue?
+ {
+ m_interface->EventProcess(event);
+
+ if ( event.event == EVENT_DIALOG_OK ||
+ (event.event == EVENT_KEYDOWN && event.param == VK_RETURN ) )
+ {
+ StopDialog();
+ if ( m_phase == PHASE_NAME )
+ {
+ NameDelete();
+ }
+ if ( m_phase == PHASE_INIT )
+ {
+//? m_event->MakeEvent(newEvent, EVENT_QUIT);
+//? m_event->AddEvent(newEvent);
+ m_main->ChangePhase(PHASE_GENERIC);
+ }
+ if ( m_phase == PHASE_SIMUL )
+ {
+ if ( m_bDialogDelete )
+ {
+ m_main->DeleteObject();
+ }
+ else
+ {
+ m_main->ChangePhase(PHASE_TERM);
+ }
+ }
+ }
+ if ( event.event == EVENT_DIALOG_CANCEL ||
+ (event.event == EVENT_KEYDOWN && event.param == VK_ESCAPE ) )
+ {
+ StopDialog();
+ }
+ if ( event.event == EVENT_INTERFACE_SETUP )
+ {
+ StopDialog();
+ StartSuspend();
+ if ( m_phaseSetup == PHASE_SETUPd ) ChangePhase(PHASE_SETUPds);
+ if ( m_phaseSetup == PHASE_SETUPg ) ChangePhase(PHASE_SETUPgs);
+ if ( m_phaseSetup == PHASE_SETUPp ) ChangePhase(PHASE_SETUPps);
+ if ( m_phaseSetup == PHASE_SETUPc ) ChangePhase(PHASE_SETUPcs);
+ if ( m_phaseSetup == PHASE_SETUPs ) ChangePhase(PHASE_SETUPss);
+ }
+ if ( event.event == EVENT_INTERFACE_AGAIN )
+ {
+ StopDialog();
+ m_main->ChangePhase(PHASE_LOADING);
+ }
+ if ( event.event == EVENT_INTERFACE_WRITE )
+ {
+ StopDialog();
+ StartSuspend();
+ ChangePhase(PHASE_WRITEs);
+ }
+ if ( event.event == EVENT_INTERFACE_READ )
+ {
+ StopDialog();
+ StartSuspend();
+ ChangePhase(PHASE_READs);
+ }
+
+ return false;
+ }
+
+ if ( !m_engine->RetMouseHide() &&
+ !m_interface->EventProcess(event) )
+ {
+ return false;
+ }
+
+ if ( m_phase == PHASE_INIT )
+ {
+ switch( event.event )
+ {
+ case EVENT_KEYDOWN:
+ if ( event.param == VK_ESCAPE )
+ {
+//? StartQuit(); // would you leave?
+ m_sound->Play(SOUND_TZOING);
+ m_main->ChangePhase(PHASE_GENERIC);
+ }
+ break;
+
+ case EVENT_INTERFACE_QUIT:
+//? StartQuit(); // would you leave?
+ m_sound->Play(SOUND_TZOING);
+ m_main->ChangePhase(PHASE_GENERIC);
+ break;
+
+ case EVENT_INTERFACE_TRAINER:
+ m_main->ChangePhase(PHASE_TRAINER);
+ break;
+
+ case EVENT_INTERFACE_DEFI:
+ m_main->ChangePhase(PHASE_DEFI);
+ break;
+
+ case EVENT_INTERFACE_MISSION:
+ m_main->ChangePhase(PHASE_MISSION);
+ break;
+
+ case EVENT_INTERFACE_FREE:
+ m_main->ChangePhase(PHASE_FREE);
+ break;
+
+ case EVENT_INTERFACE_TEEN:
+ m_main->ChangePhase(PHASE_TEEN);
+ break;
+
+ case EVENT_INTERFACE_USER:
+ m_main->ChangePhase(PHASE_USER);
+ break;
+
+ case EVENT_INTERFACE_PROTO:
+ m_main->ChangePhase(PHASE_PROTO);
+ break;
+
+ case EVENT_INTERFACE_SETUP:
+ m_main->ChangePhase(m_phaseSetup);
+ break;
+
+ case EVENT_INTERFACE_NAME:
+ m_main->ChangePhase(PHASE_NAME);
+ break;
+ }
+ return false;
+ }
+
+ if ( m_phase == PHASE_NAME )
+ {
+ switch( event.event )
+ {
+ case EVENT_KEYDOWN:
+ if ( event.param == VK_RETURN )
+ {
+ NameSelect();
+ }
+ if ( event.param == VK_ESCAPE )
+ {
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) break;
+ pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_NCANCEL);
+ if ( pb == 0 ) break;
+ if ( pb->TestState(STATE_ENABLE) )
+ {
+ m_main->ChangePhase(PHASE_INIT);
+ }
+ }
+ break;
+
+ case EVENT_INTERFACE_NEDIT:
+ UpdateNameList();
+ UpdateNameControl();
+ break;
+
+ case EVENT_INTERFACE_NLIST:
+ UpdateNameEdit();
+ break;
+
+ case EVENT_INTERFACE_NOK:
+ NameSelect();
+ break;
+
+ case EVENT_INTERFACE_PERSO:
+ NameSelect();
+ m_main->ChangePhase(PHASE_PERSO);
+ break;
+
+ case EVENT_INTERFACE_NCANCEL:
+ m_main->ChangePhase(PHASE_INIT);
+ break;
+
+ case EVENT_INTERFACE_NDELETE:
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) break;
+ pl = (CList*)pw->SearchControl(EVENT_INTERFACE_NLIST);
+ if ( pl == 0 ) break;
+ StartDeleteGame(pl->RetName(pl->RetSelect()));
+ break;
+ }
+ }
+
+ if ( m_phase == PHASE_PERSO )
+ {
+ switch( event.event )
+ {
+ case EVENT_KEYDOWN:
+ if ( event.param == VK_RETURN )
+ {
+ m_main->ChangePhase(PHASE_INIT);
+ }
+ if ( event.param == VK_ESCAPE )
+ {
+ m_main->ChangePhase(PHASE_NAME);
+ }
+ break;
+
+ case EVENT_INTERFACE_PHEAD:
+ m_persoTab = 0;
+ UpdatePerso();
+ m_main->ScenePerso();
+ CameraPerso();
+ break;
+ case EVENT_INTERFACE_PBODY:
+ m_persoTab = 1;
+ UpdatePerso();
+ m_main->ScenePerso();
+ CameraPerso();
+ break;
+
+ case EVENT_INTERFACE_PFACE1:
+ case EVENT_INTERFACE_PFACE2:
+ case EVENT_INTERFACE_PFACE3:
+ case EVENT_INTERFACE_PFACE4:
+ m_perso.face = event.event-EVENT_INTERFACE_PFACE1;
+ WriteGamerPerso(m_main->RetGamerName());
+ UpdatePerso();
+ m_main->ScenePerso();
+ break;
+
+ case EVENT_INTERFACE_PGLASS0:
+ case EVENT_INTERFACE_PGLASS1:
+ case EVENT_INTERFACE_PGLASS2:
+ case EVENT_INTERFACE_PGLASS3:
+ case EVENT_INTERFACE_PGLASS4:
+ case EVENT_INTERFACE_PGLASS5:
+ case EVENT_INTERFACE_PGLASS6:
+ case EVENT_INTERFACE_PGLASS7:
+ case EVENT_INTERFACE_PGLASS8:
+ case EVENT_INTERFACE_PGLASS9:
+ m_perso.glasses = event.event-EVENT_INTERFACE_PGLASS0;
+ WriteGamerPerso(m_main->RetGamerName());
+ UpdatePerso();
+ m_main->ScenePerso();
+ break;
+
+ case EVENT_INTERFACE_PC0a:
+ case EVENT_INTERFACE_PC1a:
+ case EVENT_INTERFACE_PC2a:
+ case EVENT_INTERFACE_PC3a:
+ case EVENT_INTERFACE_PC4a:
+ case EVENT_INTERFACE_PC5a:
+ case EVENT_INTERFACE_PC6a:
+ case EVENT_INTERFACE_PC7a:
+ case EVENT_INTERFACE_PC8a:
+ case EVENT_INTERFACE_PC9a:
+ FixPerso(event.event-EVENT_INTERFACE_PC0a, 0);
+ WriteGamerPerso(m_main->RetGamerName());
+ UpdatePerso();
+ m_main->ScenePerso();
+ break;
+
+ case EVENT_INTERFACE_PC0b:
+ case EVENT_INTERFACE_PC1b:
+ case EVENT_INTERFACE_PC2b:
+ case EVENT_INTERFACE_PC3b:
+ case EVENT_INTERFACE_PC4b:
+ case EVENT_INTERFACE_PC5b:
+ case EVENT_INTERFACE_PC6b:
+ case EVENT_INTERFACE_PC7b:
+ case EVENT_INTERFACE_PC8b:
+ case EVENT_INTERFACE_PC9b:
+ FixPerso(event.event-EVENT_INTERFACE_PC0b, 1);
+ WriteGamerPerso(m_main->RetGamerName());
+ UpdatePerso();
+ m_main->ScenePerso();
+ break;
+
+ case EVENT_INTERFACE_PCRa:
+ case EVENT_INTERFACE_PCGa:
+ case EVENT_INTERFACE_PCBa:
+ case EVENT_INTERFACE_PCRb:
+ case EVENT_INTERFACE_PCGb:
+ case EVENT_INTERFACE_PCBb:
+ ColorPerso();
+ WriteGamerPerso(m_main->RetGamerName());
+ UpdatePerso();
+ m_main->ScenePerso();
+ break;
+
+ case EVENT_INTERFACE_PDEF:
+ DefPerso();
+ WriteGamerPerso(m_main->RetGamerName());
+ UpdatePerso();
+ m_main->ScenePerso();
+ break;
+
+ case EVENT_INTERFACE_PLROT:
+ m_persoAngle += 0.2f;
+ break;
+ case EVENT_INTERFACE_PRROT:
+ m_persoAngle -= 0.2f;
+ break;
+
+ case EVENT_INTERFACE_POK:
+ m_main->ChangePhase(PHASE_INIT);
+ break;
+
+ case EVENT_INTERFACE_PCANCEL:
+ m_perso = m_persoCopy;
+ WriteGamerPerso(m_main->RetGamerName());
+ m_main->ChangePhase(PHASE_NAME);
+ break;
+ }
+ }
+
+ if ( m_phase == PHASE_TRAINER ||
+ m_phase == PHASE_DEFI ||
+ m_phase == PHASE_MISSION ||
+ m_phase == PHASE_FREE ||
+ m_phase == PHASE_TEEN ||
+ m_phase == PHASE_USER ||
+ m_phase == PHASE_PROTO )
+ {
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return false;
+
+ if ( event.event == pw->RetEventMsgClose() ||
+ event.event == EVENT_INTERFACE_BACK ||
+ (event.event == EVENT_KEYDOWN && event.param == VK_ESCAPE) )
+ {
+ m_main->ChangePhase(PHASE_INIT);
+ return false;
+ }
+ }
+
+ if ( m_phase == PHASE_TRAINER ||
+ m_phase == PHASE_DEFI ||
+ m_phase == PHASE_MISSION ||
+ m_phase == PHASE_FREE ||
+ m_phase == PHASE_TEEN ||
+ m_phase == PHASE_USER ||
+ m_phase == PHASE_PROTO )
+ {
+ switch( event.event )
+ {
+ case EVENT_INTERFACE_CHAP:
+ pl = (CList*)pw->SearchControl(EVENT_INTERFACE_CHAP);
+ if ( pl == 0 ) break;
+ m_chap[m_index] = pl->RetSelect();
+ UpdateSceneList(m_chap[m_index], m_sel[m_index]);
+ UpdateSceneResume((m_chap[m_index]+1)*100+(m_sel[m_index]+1));
+ break;
+
+ case EVENT_INTERFACE_LIST:
+ pl = (CList*)pw->SearchControl(EVENT_INTERFACE_LIST);
+ if ( pl == 0 ) break;
+ m_sel[m_index] = pl->RetSelect();
+ UpdateSceneResume((m_chap[m_index]+1)*100+(m_sel[m_index]+1));
+ break;
+
+ case EVENT_INTERFACE_SOLUCE:
+ pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_SOLUCE);
+ if ( pb == 0 ) break;
+ m_bSceneSoluce = !m_bSceneSoluce;
+ pb->SetState(STATE_CHECK, m_bSceneSoluce);
+ break;
+
+ case EVENT_INTERFACE_PLAY:
+ if ( m_phase == PHASE_PROTO && m_chap[m_index] == 0 && m_sel[m_index] == 0 )
+ {
+ m_main->ChangePhase(PHASE_MODEL);
+ break;
+ }
+ m_sceneRank = (m_chap[m_index]+1)*100+(m_sel[m_index]+1);
+ m_phaseTerm = m_phase;
+ m_main->ChangePhase(PHASE_LOADING);
+ break;
+
+ case EVENT_INTERFACE_READ:
+ m_phaseTerm = m_phase;
+ m_main->ChangePhase(PHASE_READ);
+ break;
+ }
+ return false;
+ }
+
+ if ( m_phase == PHASE_SETUPd ||
+ m_phase == PHASE_SETUPg ||
+ m_phase == PHASE_SETUPp ||
+ m_phase == PHASE_SETUPc ||
+ m_phase == PHASE_SETUPs )
+ {
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return false;
+
+ if ( event.event == pw->RetEventMsgClose() ||
+ event.event == EVENT_INTERFACE_BACK ||
+ (event.event == EVENT_KEYDOWN && event.param == VK_ESCAPE) )
+ {
+ SetupMemorize();
+ m_engine->ApplyChange();
+ m_main->ChangePhase(PHASE_INIT);
+ return false;
+ }
+
+ switch( event.event )
+ {
+ case EVENT_INTERFACE_SETUPd:
+ m_main->ChangePhase(PHASE_SETUPd);
+ break;
+
+ case EVENT_INTERFACE_SETUPg:
+ m_main->ChangePhase(PHASE_SETUPg);
+ break;
+
+ case EVENT_INTERFACE_SETUPp:
+ m_main->ChangePhase(PHASE_SETUPp);
+ break;
+
+ case EVENT_INTERFACE_SETUPc:
+ m_main->ChangePhase(PHASE_SETUPc);
+ break;
+
+ case EVENT_INTERFACE_SETUPs:
+ m_main->ChangePhase(PHASE_SETUPs);
+ break;
+ }
+ }
+
+ if ( m_phase == PHASE_SETUPds ||
+ m_phase == PHASE_SETUPgs ||
+ m_phase == PHASE_SETUPps ||
+ m_phase == PHASE_SETUPcs ||
+ m_phase == PHASE_SETUPss )
+ {
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return false;
+
+ if ( event.event == pw->RetEventMsgClose() ||
+ event.event == EVENT_INTERFACE_BACK ||
+ (event.event == EVENT_KEYDOWN && event.param == VK_ESCAPE) )
+ {
+ SetupMemorize();
+ m_engine->ApplyChange();
+ m_interface->DeleteControl(EVENT_WINDOW5);
+ ChangePhase(PHASE_SIMUL);
+ StopSuspend();
+ return false;
+ }
+
+ switch( event.event )
+ {
+ case EVENT_INTERFACE_SETUPd:
+ ChangePhase(PHASE_SETUPds);
+ break;
+
+ case EVENT_INTERFACE_SETUPg:
+ ChangePhase(PHASE_SETUPgs);
+ break;
+
+ case EVENT_INTERFACE_SETUPp:
+ ChangePhase(PHASE_SETUPps);
+ break;
+
+ case EVENT_INTERFACE_SETUPc:
+ ChangePhase(PHASE_SETUPcs);
+ break;
+
+ case EVENT_INTERFACE_SETUPs:
+ ChangePhase(PHASE_SETUPss);
+ break;
+ }
+ }
+
+ if ( m_phase == PHASE_SETUPd || // setup/display ?
+ m_phase == PHASE_SETUPds )
+ {
+ switch( event.event )
+ {
+ case EVENT_LIST1:
+ case EVENT_LIST2:
+ UpdateApply();
+ break;
+
+ case EVENT_INTERFACE_FULL:
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) break;
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_FULL);
+ if ( pc == 0 ) break;
+ pl = (CList*)pw->SearchControl(EVENT_LIST2);
+ if ( pl == 0 ) break;
+ if ( pc->TestState(STATE_CHECK) )
+ {
+ pc->ClearState(STATE_CHECK); // window
+ pl->ClearState(STATE_ENABLE);
+ }
+ else
+ {
+ pc->SetState(STATE_CHECK); // fullscreen
+ pl->SetState(STATE_ENABLE);
+ }
+ UpdateApply();
+ break;
+
+ case EVENT_INTERFACE_APPLY:
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) break;
+ pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_APPLY);
+ if ( pb == 0 ) break;
+ pb->ClearState(STATE_PRESS);
+ pb->ClearState(STATE_HILIGHT);
+ ChangeDisplay();
+ UpdateApply();
+ break;
+ }
+ return false;
+ }
+
+ if ( m_phase == PHASE_SETUPg || // setup/graphic ?
+ m_phase == PHASE_SETUPgs )
+ {
+ switch( event.event )
+ {
+ case EVENT_INTERFACE_SHADOW:
+ m_engine->SetShadow(!m_engine->RetShadow());
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_GROUND:
+ m_engine->SetGroundSpot(!m_engine->RetGroundSpot());
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_DIRTY:
+ m_engine->SetDirty(!m_engine->RetDirty());
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_FOG:
+ m_engine->SetFog(!m_engine->RetFog());
+ m_camera->SetOverBaseColor(RetColor(RetColor(0.0f)));
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_LENS:
+ m_engine->SetLensMode(!m_engine->RetLensMode());
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_SKY:
+ m_engine->SetSkyMode(!m_engine->RetSkyMode());
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_PLANET:
+ m_engine->SetPlanetMode(!m_engine->RetPlanetMode());
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_LIGHT:
+ m_engine->SetLightMode(!m_engine->RetLightMode());
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_PARTI:
+ case EVENT_INTERFACE_CLIP:
+ case EVENT_INTERFACE_DETAIL:
+ case EVENT_INTERFACE_GADGET:
+ case EVENT_INTERFACE_TEXTURE:
+ ChangeSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_MIN:
+ ChangeSetupQuality(-1);
+ UpdateSetupButtons();
+ break;
+ case EVENT_INTERFACE_NORM:
+ ChangeSetupQuality(0);
+ UpdateSetupButtons();
+ break;
+ case EVENT_INTERFACE_MAX:
+ ChangeSetupQuality(1);
+ UpdateSetupButtons();
+ break;
+ }
+ return false;
+ }
+
+ if ( m_phase == PHASE_SETUPp || // setup/game ?
+ m_phase == PHASE_SETUPps )
+ {
+ switch( event.event )
+ {
+ case EVENT_INTERFACE_TOTO:
+ m_engine->SetTotoMode(!m_engine->RetTotoMode());
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_TOOLTIP:
+ m_bTooltip = !m_bTooltip;
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_GLINT:
+ m_bGlint = !m_bGlint;
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_RAIN:
+ m_bRain = !m_bRain;
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_MOUSE:
+ m_engine->SetNiceMouse(!m_engine->RetNiceMouse());
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_EDITMODE:
+ m_engine->SetEditIndentMode(!m_engine->RetEditIndentMode());
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_EDITVALUE:
+ if ( m_engine->RetEditIndentValue() == 2 )
+ {
+ m_engine->SetEditIndentValue(4);
+ }
+ else
+ {
+ m_engine->SetEditIndentValue(2);
+ }
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_SOLUCE4:
+ m_bSoluce4 = !m_bSoluce4;
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_MOVIES:
+ m_bMovies = !m_bMovies;
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_NICERST:
+ m_bNiceReset = !m_bNiceReset;
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_HIMSELF:
+ m_bHimselfDamage = !m_bHimselfDamage;
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_SCROLL:
+ m_bCameraScroll = !m_bCameraScroll;
+ m_camera->SetCameraScroll(m_bCameraScroll);
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_INVERTX:
+ m_bCameraInvertX = !m_bCameraInvertX;
+ m_camera->SetCameraInvertX(m_bCameraInvertX);
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_INVERTY:
+ m_bCameraInvertY = !m_bCameraInvertY;
+ m_camera->SetCameraInvertY(m_bCameraInvertY);
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_EFFECT:
+ m_bEffect = !m_bEffect;
+ m_camera->SetEffect(m_bEffect);
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+ }
+ return false;
+ }
+
+ if ( m_phase == PHASE_SETUPc || // setup/commands ?
+ m_phase == PHASE_SETUPcs )
+ {
+ switch( event.event )
+ {
+ case EVENT_INTERFACE_KSCROLL:
+ UpdateKey();
+ break;
+
+ case EVENT_INTERFACE_KLEFT:
+ case EVENT_INTERFACE_KRIGHT:
+ case EVENT_INTERFACE_KUP:
+ case EVENT_INTERFACE_KDOWN:
+ case EVENT_INTERFACE_KGUP:
+ case EVENT_INTERFACE_KGDOWN:
+ case EVENT_INTERFACE_KCAMERA:
+ case EVENT_INTERFACE_KDESEL:
+ case EVENT_INTERFACE_KACTION:
+ case EVENT_INTERFACE_KNEAR:
+ case EVENT_INTERFACE_KAWAY:
+ case EVENT_INTERFACE_KNEXT:
+ case EVENT_INTERFACE_KHUMAN:
+ case EVENT_INTERFACE_KQUIT:
+ case EVENT_INTERFACE_KHELP:
+ case EVENT_INTERFACE_KPROG:
+ case EVENT_INTERFACE_KCBOT:
+ case EVENT_INTERFACE_KSPEED10:
+ case EVENT_INTERFACE_KSPEED15:
+ case EVENT_INTERFACE_KSPEED20:
+ case EVENT_INTERFACE_KSPEED30:
+ case EVENT_INTERFACE_KVISIT:
+ ChangeKey(event.event);
+ UpdateKey();
+ break;
+
+ case EVENT_INTERFACE_KDEF:
+ m_engine->ResetKey();
+ UpdateKey();
+ break;
+
+ case EVENT_INTERFACE_JOYSTICK:
+ m_engine->SetJoystick(!m_engine->RetJoystick());
+ UpdateSetupButtons();
+ break;
+ }
+ return false;
+ }
+
+ if ( m_phase == PHASE_SETUPs || // setup/sound ?
+ m_phase == PHASE_SETUPss )
+ {
+ switch( event.event )
+ {
+ case EVENT_INTERFACE_VOLSOUND:
+ case EVENT_INTERFACE_VOLMUSIC:
+ ChangeSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_SOUND3D:
+ m_sound->SetSound3D(!m_sound->RetSound3D());
+ ChangeSetupButtons();
+ UpdateSetupButtons();
+ break;
+
+ case EVENT_INTERFACE_SILENT:
+ m_sound->SetAudioVolume(0);
+ m_sound->SetMidiVolume(0);
+ UpdateSetupButtons();
+ break;
+ case EVENT_INTERFACE_NOISY:
+ m_sound->SetAudioVolume(MAXVOLUME);
+ m_sound->SetMidiVolume(MAXVOLUME*3/4);
+ UpdateSetupButtons();
+ break;
+ }
+ return false;
+ }
+
+ if ( m_phase == PHASE_READ )
+ {
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return false;
+
+ if ( event.event == pw->RetEventMsgClose() ||
+ event.event == EVENT_INTERFACE_BACK ||
+ (event.event == EVENT_KEYDOWN && event.param == VK_ESCAPE) )
+ {
+ ChangePhase(m_phaseTerm);
+ }
+
+ if ( event.event == EVENT_INTERFACE_IOLIST )
+ {
+ IOUpdateList();
+ }
+ if ( event.event == EVENT_INTERFACE_IODELETE )
+ {
+ IODeleteScene();
+ IOUpdateList();
+ }
+ if ( event.event == EVENT_INTERFACE_IOREAD )
+ {
+ if ( IOReadScene() )
+ {
+ m_main->ChangePhase(PHASE_LOADING);
+ }
+ }
+
+ return false;
+ }
+
+ if ( m_phase == PHASE_WRITEs ||
+ m_phase == PHASE_READs )
+ {
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return false;
+
+ if ( event.event == pw->RetEventMsgClose() ||
+ event.event == EVENT_INTERFACE_BACK ||
+ (event.event == EVENT_KEYDOWN && event.param == VK_ESCAPE) )
+ {
+ m_interface->DeleteControl(EVENT_WINDOW5);
+ ChangePhase(PHASE_SIMUL);
+ StopSuspend();
+ }
+
+ if ( event.event == EVENT_INTERFACE_IOLIST )
+ {
+ IOUpdateList();
+ }
+ if ( event.event == EVENT_INTERFACE_IODELETE )
+ {
+ IODeleteScene();
+ IOUpdateList();
+ }
+ if ( event.event == EVENT_INTERFACE_IOWRITE )
+ {
+ IOWriteScene();
+ m_interface->DeleteControl(EVENT_WINDOW5);
+ ChangePhase(PHASE_SIMUL);
+ StopSuspend();
+ }
+ if ( event.event == EVENT_INTERFACE_IOREAD )
+ {
+ if ( IOReadScene() )
+ {
+ m_interface->DeleteControl(EVENT_WINDOW5);
+ ChangePhase(PHASE_SIMUL);
+ StopSuspend();
+ m_main->ChangePhase(PHASE_LOADING);
+ }
+ }
+
+ return false;
+ }
+
+ if ( m_phase == PHASE_WELCOME1 )
+ {
+ if ( event.event == EVENT_KEYDOWN ||
+ event.event == EVENT_LBUTTONDOWN ||
+ event.event == EVENT_RBUTTONDOWN )
+ {
+ ChangePhase(PHASE_WELCOME2);
+ return true;
+ }
+ }
+ if ( m_phase == PHASE_WELCOME2 )
+ {
+ if ( event.event == EVENT_KEYDOWN ||
+ event.event == EVENT_LBUTTONDOWN ||
+ event.event == EVENT_RBUTTONDOWN )
+ {
+ ChangePhase(PHASE_WELCOME3);
+ return true;
+ }
+ }
+ if ( m_phase == PHASE_WELCOME3 )
+ {
+ if ( event.event == EVENT_KEYDOWN ||
+ event.event == EVENT_LBUTTONDOWN ||
+ event.event == EVENT_RBUTTONDOWN )
+ {
+ ChangePhase(PHASE_NAME);
+ return true;
+ }
+ }
+
+ if ( m_phase == PHASE_GENERIC )
+ {
+ if ( event.event == EVENT_INTERFACE_ABORT )
+ {
+ ChangePhase(PHASE_INIT);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+ if ( event.param == VK_ESCAPE )
+ {
+ ChangePhase(PHASE_INIT);
+ }
+ else
+ {
+ m_event->MakeEvent(newEvent, EVENT_QUIT);
+ m_event->AddEvent(newEvent);
+ }
+ }
+
+ if ( event.event == EVENT_LBUTTONDOWN ||
+ event.event == EVENT_RBUTTONDOWN )
+ {
+ m_event->MakeEvent(newEvent, EVENT_QUIT);
+ m_event->AddEvent(newEvent);
+ }
+ }
+
+ return true;
+}
+
+
+// Moves the reflections.
+
+void CMainDialog::GlintMove()
+{
+ CWindow* pw;
+ CGroup* pg;
+ Math::Point pos, dim, zoom;
+
+ if ( m_phase == PHASE_SIMUL ) return;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+
+ if ( m_phase == PHASE_INIT )
+ {
+ pg = (CGroup*)pw->SearchControl(EVENT_INTERFACE_GLINTl);
+ if ( pg != 0 )
+ {
+ zoom.x = sinf(m_glintTime*0.23f);
+ zoom.y = sinf(m_glintTime*0.37f);
+ pos.x = 0.35f;
+ pos.y = 0.90f;
+ dim.x = 0.30f-0.10f*(zoom.x+1.0f)/2.0f;
+ dim.y = 0.50f-0.30f*(zoom.y+1.0f)/2.0f;
+ pos.y -= dim.y;
+ pg->SetPos(pos);
+ pg->SetDim(dim);
+ }
+
+ pg = (CGroup*)pw->SearchControl(EVENT_INTERFACE_GLINTr);
+ if ( pg != 0 )
+ {
+ zoom.x = sinf(m_glintTime*0.21f);
+ zoom.y = sinf(m_glintTime*0.26f);
+ pos.x = 0.65f;
+ pos.y = 0.10f;
+ dim.x = 0.30f-0.10f*(zoom.x+1.0f)/2.0f;
+ dim.y = 0.50f-0.30f*(zoom.y+1.0f)/2.0f;
+ pos.x -= dim.x;
+ pg->SetPos(pos);
+ pg->SetDim(dim);
+ }
+ }
+
+ if ( m_phase == PHASE_NAME ||
+ m_phase == PHASE_TRAINER ||
+ m_phase == PHASE_MISSION ||
+ m_phase == PHASE_FREE ||
+ m_phase == PHASE_TEEN ||
+ m_phase == PHASE_USER ||
+ m_phase == PHASE_PROTO )
+ {
+ pg = (CGroup*)pw->SearchControl(EVENT_INTERFACE_GLINTl);
+ if ( pg != 0 )
+ {
+ zoom.x = sinf(m_glintTime*0.22f);
+ zoom.y = sinf(m_glintTime*0.37f);
+ pos.x = 0.10f;
+ pos.y = 0.90f;
+ dim.x = 0.60f+0.30f*zoom.x;
+ dim.y = 0.60f+0.30f*zoom.y;
+ pos.y -= dim.y;
+ pg->SetPos(pos);
+ pg->SetDim(dim);
+ }
+
+ pg = (CGroup*)pw->SearchControl(EVENT_INTERFACE_GLINTr);
+ if ( pg != 0 )
+ {
+ zoom.x = sinf(m_glintTime*0.19f);
+ zoom.y = sinf(m_glintTime*0.28f);
+ pos.x = 0.90f;
+ pos.y = 0.10f;
+ dim.x = 0.60f+0.30f*zoom.x;
+ dim.y = 0.60f+0.30f*zoom.y;
+ pos.x -= dim.x;
+ pg->SetPos(pos);
+ pg->SetDim(dim);
+ }
+ }
+
+ if ( m_phase == PHASE_SETUPd ||
+ m_phase == PHASE_SETUPg ||
+ m_phase == PHASE_SETUPp ||
+ m_phase == PHASE_SETUPc ||
+ m_phase == PHASE_SETUPs ||
+ m_phase == PHASE_SETUPds ||
+ m_phase == PHASE_SETUPgs ||
+ m_phase == PHASE_SETUPps ||
+ m_phase == PHASE_SETUPcs ||
+ m_phase == PHASE_SETUPss )
+ {
+ pg = (CGroup*)pw->SearchControl(EVENT_INTERFACE_GLINTu);
+ if ( pg != 0 )
+ {
+ zoom.y = sinf(m_glintTime*0.27f);
+ pos.x = 0.10f;
+ pos.y = 0.76f;
+ dim.x = 0.80f;
+ dim.y = 0.32f+0.20f*zoom.y;
+ pos.y -= dim.y;
+ pg->SetPos(pos);
+ pg->SetDim(dim);
+ }
+
+ pg = (CGroup*)pw->SearchControl(EVENT_INTERFACE_GLINTr);
+ if ( pg != 0 )
+ {
+ zoom.x = sinf(m_glintTime*0.29f);
+ zoom.y = sinf(m_glintTime*0.14f);
+ pos.x = 0.90f;
+ pos.y = 0.10f;
+ dim.x = 0.40f+0.20f*zoom.x;
+ dim.y = 0.40f+0.20f*zoom.y;
+ pos.x -= dim.x;
+ pg->SetPos(pos);
+ pg->SetDim(dim);
+ }
+ }
+
+ if ( m_phase == PHASE_WRITE ||
+ m_phase == PHASE_READ ||
+ m_phase == PHASE_WRITEs ||
+ m_phase == PHASE_READs )
+ {
+ pg = (CGroup*)pw->SearchControl(EVENT_INTERFACE_GLINTl);
+ if ( pg != 0 )
+ {
+ zoom.x = sinf(m_glintTime*0.22f);
+ zoom.y = sinf(m_glintTime*0.37f);
+ pos.x = 0.10f;
+ pos.y = 0.90f;
+ dim.x = 0.60f+0.30f*zoom.x;
+ dim.y = 0.60f+0.30f*zoom.y;
+ pos.y -= dim.y;
+ pg->SetPos(pos);
+ pg->SetDim(dim);
+ }
+
+ pg = (CGroup*)pw->SearchControl(EVENT_INTERFACE_GLINTr);
+ if ( pg != 0 )
+ {
+ zoom.x = sinf(m_glintTime*0.19f);
+ zoom.y = sinf(m_glintTime*0.28f);
+ pos.x = 0.90f;
+ pos.y = 0.10f;
+ dim.x = 0.60f+0.30f*zoom.x;
+ dim.y = 0.60f+0.30f*zoom.y;
+ pos.x -= dim.x;
+ pg->SetPos(pos);
+ pg->SetDim(dim);
+ }
+ }
+}
+
+
+// Returns the position for a sound.
+
+Math::Vector SoundPos(Math::Point pos)
+{
+ Math::Vector s;
+
+ s.x = (pos.x-0.5f)*2.0f;
+ s.y = (pos.y-0.5f)*2.0f;
+ s.z = 0.0f;
+
+ return s;
+}
+
+// Returns a random position for a sound.
+
+Math::Vector SoundRand()
+{
+ Math::Vector s;
+
+ s.x = (Math::Rand()-0.5f)*2.0f;
+ s.y = (Math::Rand()-0.5f)*2.0f;
+ s.z = 0.0f;
+
+ return s;
+}
+
+// Makes pretty qq particles evolve.
+
+void CMainDialog::FrameParticule(float rTime)
+{
+#if _NEWLOOK
+#else
+ Math::Vector pos, speed;
+ Math::Point dim;
+ float *pParti, *pGlint;
+ int nParti, nGlint;
+ int i, r, ii;
+
+ static float partiPosInit[1+5*12] =
+ { // x x t2 t2 type
+ 12.0f,
+ 607.0f, 164.0f, 0.2f, 0.8f, 1.0f, // upper cable
+ 604.0f, 205.0f, 0.1f, 0.3f, 1.0f, // middle cable
+ 603.0f, 247.0f, 0.1f, 0.3f, 1.0f, // lower cable
+ 119.0f, 155.0f, 0.2f, 0.4f, 2.0f, // left pipe
+ 366.0f, 23.0f, 0.5f, 1.5f, 4.0f, // upper pipe
+ 560.0f, 414.0f, 0.1f, 0.1f, 1.0f, // button lower/right
+ 20.0f, 413.0f, 0.1f, 0.1f, 2.0f, // button lower/left
+ 39.0f, 78.0f, 0.1f, 0.2f, 1.0f, // left pot
+ 39.0f, 78.0f, 0.5f, 0.9f, 1.0f, // left pot
+ 170.0f, 229.0f, 0.5f, 0.5f, 3.0f, // left smoke
+ 170.0f, 229.0f, 0.5f, 0.5f, 3.0f, // left smoke
+ 474.0f, 229.0f, 0.5f, 0.5f, 3.0f, // right smoke
+ };
+
+ static float glintPosInit[1+2*14] =
+ {
+ 14.0f,
+ 15.0f, 407.0f,
+ 68.0f, 417.0f,
+ 548.0f, 36.0f,
+ 611.0f, 37.0f,
+ 611.0f, 100.0f,
+ 611.0f, 395.0f,
+ 36.0f, 35.0f,
+ 166.0f, 55.0f,
+ 166.0f, 94.0f,
+ 477.0f, 56.0f,
+ 31.0f, 190.0f,
+ 32.0f, 220.0f,
+ 65.0f, 221.0f,
+ 65.0f, 250.0f,
+ };
+
+ static float partiPosBig[1+5*12] =
+ { // x x t2 t2 type
+ 12.0f,
+ 607.0f, 164.0f, 0.2f, 0.8f, 1.0f, // upper cable
+ 604.0f, 205.0f, 0.1f, 0.3f, 1.0f, // middle cable
+ 603.0f, 247.0f, 0.1f, 0.3f, 1.0f, // lower cable
+ 64.0f, 444.0f, 0.2f, 0.8f, 1.0f, // down the left cable
+ 113.0f, 449.0f, 0.1f, 0.3f, 1.0f, // down the left cable
+ 340.0f, 463.0f, 0.2f, 0.8f, 1.0f, // down the middle cable
+ 36.0f, 155.0f, 0.2f, 0.4f, 2.0f, // left pipe
+ 366.0f, 23.0f, 0.5f, 1.5f, 4.0f, // upper pipe
+ 612.0f, 414.0f, 0.1f, 0.1f, 1.0f, // button lower/right
+ 20.0f, 413.0f, 0.1f, 0.1f, 2.0f, // button lower/left
+ 39.0f, 78.0f, 0.1f, 0.2f, 1.0f, // left pot
+ 39.0f, 78.0f, 0.5f, 0.9f, 1.0f, // left pot
+ };
+
+ static float glintPosBig[1+2*12] =
+ {
+ 12.0f,
+ 15.0f, 407.0f,
+ 48.0f, 399.0f,
+ 611.0f, 37.0f,
+ 611.0f, 100.0f,
+ 611.0f, 395.0f,
+ 36.0f, 35.0f,
+ 31.0f, 190.0f,
+ 32.0f, 220.0f,
+ 31.0f, 221.0f,
+ 31.0f, 189.0f,
+ 255.0f, 18.0f,
+ 279.0f, 18.0f,
+ };
+
+ if ( m_bDialog || !m_bRain ) return;
+
+ if ( m_phase == PHASE_INIT )
+ {
+ pParti = partiPosInit;
+ pGlint = glintPosInit;
+ }
+ else if ( m_phase == PHASE_NAME ||
+ m_phase == PHASE_TRAINER ||
+ m_phase == PHASE_DEFI ||
+ m_phase == PHASE_MISSION ||
+ m_phase == PHASE_FREE ||
+ m_phase == PHASE_TEEN ||
+ m_phase == PHASE_USER ||
+ m_phase == PHASE_PROTO ||
+ m_phase == PHASE_SETUPd ||
+ m_phase == PHASE_SETUPg ||
+ m_phase == PHASE_SETUPp ||
+ m_phase == PHASE_SETUPc ||
+ m_phase == PHASE_SETUPs ||
+ m_phase == PHASE_WRITE ||
+ m_phase == PHASE_READ )
+ {
+ pParti = partiPosBig;
+ pGlint = glintPosBig;
+ }
+ else
+ {
+ return;
+ }
+
+ nParti = (int)(*pParti++);
+ nGlint = (int)(*pGlint++);
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ if ( m_partiPhase[i] == 0 ) // waiting?
+ {
+ m_partiTime[i] -= rTime;
+ if ( m_partiTime[i] <= 0.0f )
+ {
+ r = rand()%3;
+
+ if ( r == 0 )
+ {
+ ii = rand()%nParti;
+ m_partiPos[i].x = pParti[ii*5+0]/640.0f;
+ m_partiPos[i].y = (480.0f-pParti[ii*5+1])/480.0f;
+ m_partiTime[i] = pParti[ii*5+2]+Math::Rand()*pParti[ii*5+3];
+ m_partiPhase[i] = (int)pParti[ii*5+4];
+ if ( m_partiPhase[i] == 3 )
+ {
+ m_sound->Play(SOUND_PSHHH, SoundPos(m_partiPos[i]), 0.3f+Math::Rand()*0.3f);
+ }
+ else
+ {
+ m_sound->Play(SOUND_GGG, SoundPos(m_partiPos[i]), 0.1f+Math::Rand()*0.4f);
+ }
+ }
+
+ if ( r == 1 )
+ {
+ ii = rand()%nGlint;
+ pos.x = pGlint[ii*2+0]/640.0f;
+ pos.y = (480.0f-pGlint[ii*2+1])/480.0f;
+ pos.z = 0.0f;
+ speed.x = 0.0f;
+ speed.y = 0.0f;
+ speed.z = 0.0f;
+ dim.x = 0.04f+Math::Rand()*0.04f;
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim,
+ rand()%2?PARTIGLINT:PARTICONTROL,
+ Math::Rand()*0.4f+0.4f, 0.0f, 0.0f,
+ SH_INTERFACE);
+ m_partiTime[i] = 0.5f+Math::Rand()*0.5f;
+ }
+
+ if ( r == 2 )
+ {
+ ii = rand()%7;
+ if ( ii == 0 )
+ {
+ m_sound->Play(SOUND_ENERGY, SoundRand(), 0.2f+Math::Rand()*0.2f);
+ m_partiTime[i] = 1.0f+Math::Rand()*1.0f;
+ }
+ if ( ii == 1 )
+ {
+ m_sound->Play(SOUND_STATION, SoundRand(), 0.2f+Math::Rand()*0.2f);
+ m_partiTime[i] = 1.0f+Math::Rand()*2.0f;
+ }
+ if ( ii == 2 )
+ {
+ m_sound->Play(SOUND_ALARM, SoundRand(), 0.1f+Math::Rand()*0.1f);
+ m_partiTime[i] = 2.0f+Math::Rand()*4.0f;
+ }
+ if ( ii == 3 )
+ {
+ m_sound->Play(SOUND_INFO, SoundRand(), 0.1f+Math::Rand()*0.1f);
+ m_partiTime[i] = 2.0f+Math::Rand()*4.0f;
+ }
+ if ( ii == 4 )
+ {
+ m_sound->Play(SOUND_RADAR, SoundRand(), 0.2f+Math::Rand()*0.2f);
+ m_partiTime[i] = 0.5f+Math::Rand()*1.0f;
+ }
+ if ( ii == 5 )
+ {
+ m_sound->Play(SOUND_GFLAT, SoundRand(), 0.3f+Math::Rand()*0.3f);
+ m_partiTime[i] = 2.0f+Math::Rand()*4.0f;
+ }
+ if ( ii == 6 )
+ {
+ m_sound->Play(SOUND_ALARMt, SoundRand(), 0.1f+Math::Rand()*0.1f);
+ m_partiTime[i] = 2.0f+Math::Rand()*4.0f;
+ }
+ }
+ }
+ }
+
+ if ( m_partiPhase[i] != 0 ) // generates?
+ {
+ m_partiTime[i] -= rTime;
+ if ( m_partiTime[i] > 0.0f )
+ {
+ if ( m_partiPhase[i] == 1 ) // sparks?
+ {
+ pos.x = m_partiPos[i].x;
+ pos.y = m_partiPos[i].y;
+ pos.z = 0.0f;
+ pos.x += (Math::Rand()-0.5f)*0.01f;
+ pos.y += (Math::Rand()-0.5f)*0.01f;
+ speed.x = (Math::Rand()-0.5f)*0.2f;
+ speed.y = (Math::Rand()-0.5f)*0.2f;
+ speed.z = 0.0f;
+ dim.x = 0.005f+Math::Rand()*0.005f;
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ,
+ Math::Rand()*0.2f+0.2f, 0.0f, 0.0f,
+ SH_INTERFACE);
+ pos.x = m_partiPos[i].x;
+ pos.y = m_partiPos[i].y;
+ pos.z = 0.0f;
+ speed.x = (Math::Rand()-0.5f)*0.5f;
+ speed.y = (0.3f+Math::Rand()*0.3f);
+ speed.z = 0.0f;
+ dim.x = 0.01f+Math::Rand()*0.01f;
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim,
+ (ParticuleType)(PARTILENS1+rand()%3),
+ Math::Rand()*0.5f+0.5f, 2.0f, 0.0f,
+ SH_INTERFACE);
+ }
+ if ( m_partiPhase[i] == 2 ) // sparks?
+ {
+ pos.x = m_partiPos[i].x;
+ pos.y = m_partiPos[i].y;
+ pos.z = 0.0f;
+ pos.x += (Math::Rand()-0.5f)*0.01f;
+ pos.y += (Math::Rand()-0.5f)*0.01f;
+ speed.x = (Math::Rand()-0.5f)*0.2f;
+ speed.y = (Math::Rand()-0.5f)*0.2f;
+ speed.z = 0.0f;
+ dim.x = 0.005f+Math::Rand()*0.005f;
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ,
+ Math::Rand()*0.2f+0.2f, 0.0f, 0.0f,
+ SH_INTERFACE);
+ pos.x = m_partiPos[i].x;
+ pos.y = m_partiPos[i].y;
+ pos.z = 0.0f;
+ speed.x = (Math::Rand()-0.5f)*0.5f;
+ speed.y = (0.3f+Math::Rand()*0.3f);
+ speed.z = 0.0f;
+ dim.x = 0.005f+Math::Rand()*0.005f;
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim, PARTISCRAPS,
+ Math::Rand()*0.5f+0.5f, 2.0f, 0.0f,
+ SH_INTERFACE);
+ }
+ if ( m_partiPhase[i] == 3 ) // smoke?
+ {
+ pos.x = m_partiPos[i].x;
+ pos.y = m_partiPos[i].y;
+ pos.z = 0.0f;
+ pos.x += (Math::Rand()-0.5f)*0.03f;
+ pos.y += (Math::Rand()-0.5f)*0.03f;
+ speed.x = (Math::Rand()-0.5f)*0.2f;
+ speed.y = Math::Rand()*0.5f;
+ speed.z = 0.0f;
+ dim.x = 0.03f+Math::Rand()*0.07f;
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH,
+ Math::Rand()*0.4f+0.4f, 0.0f, 0.0f,
+ SH_INTERFACE);
+ }
+ }
+ else
+ {
+ m_partiPhase[i] = 0;
+ m_partiTime[i] = 2.0f+Math::Rand()*4.0f;
+ }
+ }
+ }
+#endif
+}
+
+// Some nice particles following the mouse.
+
+void CMainDialog::NiceParticule(Math::Point mouse, bool bPress)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+
+ if ( !m_bRain ) return;
+ if ( (m_phase == PHASE_SIMUL ||
+ m_phase == PHASE_WIN ||
+ m_phase == PHASE_LOST ||
+ m_phase == PHASE_MODEL ) &&
+ !m_bDialog ) return;
+
+ if ( bPress )
+ {
+ pos.x = mouse.x;
+ pos.y = mouse.y;
+ pos.z = 0.0f;
+ speed.x = (Math::Rand()-0.5f)*0.5f;
+ speed.y = (0.3f+Math::Rand()*0.3f);
+ speed.z = 0.0f;
+ dim.x = 0.005f+Math::Rand()*0.005f;
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim, PARTISCRAPS,
+ Math::Rand()*0.5f+0.5f, 2.0f, 0.0f,
+ SH_INTERFACE);
+ }
+ else
+ {
+ pos.x = mouse.x;
+ pos.y = mouse.y;
+ pos.z = 0.0f;
+ speed.x = (Math::Rand()-0.5f)*0.5f;
+ speed.y = (0.3f+Math::Rand()*0.3f);
+ speed.z = 0.0f;
+ dim.x = 0.01f+Math::Rand()*0.01f;
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim,
+ (ParticuleType)(PARTILENS1+rand()%3),
+ Math::Rand()*0.5f+0.5f, 2.0f, 0.0f,
+ SH_INTERFACE);
+ }
+}
+
+
+
+// Specifies the special user folder if needed.
+
+void CMainDialog::SetUserDir(char *base, int rank)
+{
+ char dir[100];
+
+ if ( strcmp(base, "user") == 0 && rank >= 100 )
+ {
+ sprintf(dir, "%s\\%s", m_userDir, m_userList[rank/100-1]);
+ UserDir(true, dir);
+ }
+ else
+ {
+ UserDir(false, "");
+ }
+}
+
+// Builds the file name of a mission.
+
+void CMainDialog::BuildSceneName(char *filename, char *base, int rank)
+{
+ if ( strcmp(base, "user") == 0 )
+ {
+ sprintf(filename, "%s\\%s\\scene%.2d.txt", m_userDir, m_userList[rank/100-1], rank%100);
+ }
+ else
+ {
+ sprintf(filename, "%s\\%s%.3d.txt", m_sceneDir, base, rank);
+ }
+}
+
+// Built the default descriptive name of a mission.
+
+void CMainDialog::BuildResumeName(char *filename, char *base, int rank)
+{
+ sprintf(filename, "Scene %s %d", base, rank);
+}
+
+// Returns the name of the file or save the files.
+
+char* CMainDialog::RetFilesDir()
+{
+ return m_filesDir;
+}
+
+
+// Updates the list of players after checking the files on disk.
+
+void CMainDialog::ReadNameList()
+{
+ CWindow* pw;
+ CList* pl;
+ long hFile;
+ struct _finddata_t fBuffer;
+ bool bDo;
+ char dir[_MAX_FNAME];
+ char temp[_MAX_FNAME];
+ char filenames[_MAX_FNAME][100];
+ int nbFilenames, i;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pl = (CList*)pw->SearchControl(EVENT_INTERFACE_NLIST);
+ if ( pl == 0 ) return;
+ pl->Flush();
+
+ nbFilenames = 0;
+ sprintf(dir, "%s\\*", m_savegameDir);
+ hFile = _findfirst(dir, &fBuffer);
+ if ( hFile != -1 )
+ {
+ do
+ {
+ if ( (fBuffer.attrib & _A_SUBDIR) && fBuffer.name[0] != '.' )
+ {
+ strcpy(filenames[nbFilenames++], fBuffer.name);
+ }
+ }
+ while ( _findnext(hFile, &fBuffer) == 0 && nbFilenames < 100 );
+ }
+ do // sorts all names:
+ {
+ bDo = false;
+ for ( i=0 ; i<nbFilenames-1 ; i++ )
+ {
+ if ( strcmp(filenames[i], filenames[i+1]) > 0 )
+ {
+ strcpy(temp, filenames[i]);
+ strcpy(filenames[i], filenames[i+1]);
+ strcpy(filenames[i+1], temp);
+ bDo = true;
+ }
+ }
+ }
+ while ( bDo );
+
+ for ( i=0 ; i<nbFilenames ; i++ )
+ {
+ pl->SetName(i, filenames[i]);
+ }
+}
+
+// Updates the controls of the players.
+
+void CMainDialog::UpdateNameControl()
+{
+ CWindow* pw;
+ CList* pl;
+ CButton* pb;
+ CEdit* pe;
+ char name[100];
+ char* gamer;
+ int total, sel;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pl = (CList*)pw->SearchControl(EVENT_INTERFACE_NLIST);
+ if ( pl == 0 ) return;
+ pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_NEDIT);
+ if ( pe == 0 ) return;
+
+ gamer = m_main->RetGamerName();
+ total = pl->RetTotal();
+ sel = pl->RetSelect();
+ pe->GetText(name, 100);
+
+ pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_NCANCEL);
+ if ( pb != 0 )
+ {
+ pb->SetState(STATE_ENABLE, gamer[0]!=0);
+ }
+
+ pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_NDELETE);
+ if ( pb != 0 )
+ {
+ pb->SetState(STATE_ENABLE, total>0 && sel!=-1);
+ }
+
+ pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_NOK);
+ if ( pb != 0 )
+ {
+ pb->SetState(STATE_ENABLE, name[0]!=0 || sel!=-1);
+ }
+
+ pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_PERSO);
+ if ( pb != 0 )
+ {
+ pb->SetState(STATE_ENABLE, name[0]!=0 || sel!=-1);
+ }
+}
+
+// Updates the list of players by name frape.
+
+void CMainDialog::UpdateNameList()
+{
+ CWindow* pw;
+ CList* pl;
+ CEdit* pe;
+ char name[100];
+ int total, sel, i;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pl = (CList*)pw->SearchControl(EVENT_INTERFACE_NLIST);
+ if ( pl == 0 ) return;
+ pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_NEDIT);
+ if ( pe == 0 ) return;
+
+ pe->GetText(name, 100);
+ total = pl->RetTotal();
+ sel = pl->RetSelect();
+
+ for ( i=0 ; i<total ; i++ )
+ {
+ if ( stricmp(name, pl->RetName(i)) == 0 )
+ {
+ pl->SetSelect(i);
+ pl->ShowSelect(false);
+ return;
+ }
+ }
+
+ pl->SetSelect(-1);
+}
+
+// Updates the player's name and function of the selected list.
+
+void CMainDialog::UpdateNameEdit()
+{
+ CWindow* pw;
+ CList* pl;
+ CEdit* pe;
+ char* name;
+ int sel;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pl = (CList*)pw->SearchControl(EVENT_INTERFACE_NLIST);
+ if ( pl == 0 ) return;
+ pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_NEDIT);
+ if ( pe == 0 ) return;
+
+ sel = pl->RetSelect();
+ if ( sel == -1 )
+ {
+ pe->SetText("");
+ pe->SetCursor(0, 0);
+ }
+ else
+ {
+ name = pl->RetName(sel);
+ pe->SetText(name);
+ pe->SetCursor(strlen(name), 0);
+ }
+
+ UpdateNameControl();
+}
+
+// Updates the representation of the player depending on the selected list.
+
+void CMainDialog::UpdateNameFace()
+{
+ CWindow* pw;
+ CList* pl;
+ char* name;
+ int sel;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pl = (CList*)pw->SearchControl(EVENT_INTERFACE_NLIST);
+ if ( pl == 0 ) return;
+
+ sel = pl->RetSelect();
+ if ( sel == -1 ) return;
+ name = pl->RetName(sel);
+
+ ReadGamerPerso(name);
+}
+
+// Selects a player.
+
+void CMainDialog::NameSelect()
+{
+ CWindow* pw;
+ CList* pl;
+ CEdit* pe;
+ char name[100];
+ int sel;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pl = (CList*)pw->SearchControl(EVENT_INTERFACE_NLIST);
+ if ( pl == 0 ) return;
+ pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_NEDIT);
+ if ( pe == 0 ) return;
+
+ pe->GetText(name, 100);
+ sel = pl->RetSelect();
+
+ if ( sel == -1 )
+ {
+ NameCreate();
+ }
+ else
+ {
+ m_main->SetGamerName(pl->RetName(sel));
+ m_main->ChangePhase(PHASE_INIT);
+ }
+
+ RetGamerFace(m_main->RetGamerName());
+
+ SetProfileString("Gamer", "LastName", m_main->RetGamerName());
+}
+
+// Creates a new player.
+
+void CMainDialog::NameCreate()
+{
+ CWindow* pw;
+ CEdit* pe;
+ char name[100];
+ char dir[100];
+ char c;
+ int len, i, j;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_NEDIT);
+ if ( pe == 0 ) return;
+
+ pe->GetText(name, 100);
+ if ( name[0] == 0 )
+ {
+ m_sound->Play(SOUND_TZOING);
+ return;
+ }
+
+ len = strlen(name);
+ j = 0;
+ for ( i=0 ; i<len ; i++ )
+ {
+ c = RetNoAccent(RetToLower(name[i]));
+ if ( (c >= '0' && c <= '9') ||
+ (c >= 'a' && c <= 'z') ||
+ c == ' ' ||
+ c == '-' ||
+ c == '_' ||
+ c == '.' ||
+ c == ',' ||
+ c == '\'' )
+ {
+ name[j++] = name[i];
+ }
+ }
+ name[j] = 0;
+ if ( j == 0 )
+ {
+ m_sound->Play(SOUND_TZOING);
+ return;
+ }
+
+ _mkdir(m_savegameDir); // if does not exist yet!
+
+ sprintf(dir, "%s\\%s", m_savegameDir, name);
+ if ( _mkdir(dir) != 0 )
+ {
+ m_sound->Play(SOUND_TZOING);
+ pe->SetText(name);
+ pe->SetCursor(strlen(name), 0);
+ pe->SetFocus(true);
+ return;
+ }
+
+ SetGamerFace(name, 0);
+
+ m_main->SetGamerName(name);
+ m_main->ChangePhase(PHASE_INIT);
+}
+
+// Deletes a folder and all its offspring.
+
+bool RemoveDir(char *dirname)
+{
+ long hFile;
+ struct _finddata_t fBuffer;
+ char filename[100];
+
+ sprintf(filename, "%s\\*", dirname);
+ hFile = _findfirst(filename, &fBuffer);
+ if ( hFile != -1 )
+ {
+ do
+ {
+ if ( fBuffer.name[0] != '.' )
+ {
+ if ( fBuffer.attrib & _A_SUBDIR )
+ {
+ sprintf(filename, "%s\\%s", dirname, fBuffer.name);
+ RemoveDir(filename);
+ }
+ else
+ {
+ sprintf(filename, "%s\\%s", dirname, fBuffer.name);
+ remove(filename);
+ }
+ }
+ }
+ while ( _findnext(hFile, &fBuffer) == 0 );
+ }
+
+ if ( _rmdir(dirname) != 0 )
+ {
+ return false;
+ }
+ return true;
+}
+
+// Removes a player.
+
+void CMainDialog::NameDelete()
+{
+ CWindow* pw;
+ CList* pl;
+ int sel;
+ char* gamer;
+ char dir[100];
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pl = (CList*)pw->SearchControl(EVENT_INTERFACE_NLIST);
+ if ( pl == 0 ) return;
+
+ sel = pl->RetSelect();
+ if ( sel == -1 )
+ {
+ m_sound->Play(SOUND_TZOING);
+ return;
+ }
+ gamer = pl->RetName(sel);
+
+ // Deletes all the contents of the file.
+ sprintf(dir, "%s\\%s", m_savegameDir, gamer);
+ if ( !RemoveDir(dir) )
+ {
+ m_sound->Play(SOUND_TZOING);
+ return;
+ }
+
+ m_main->SetGamerName("");
+ pl->SetSelect(-1);
+
+ ReadNameList();
+ UpdateNameList();
+ UpdateNameControl();
+}
+
+
+
+// ests whether two colors are equal or nearly are.
+
+bool EqColor(const D3DCOLORVALUE &c1, const D3DCOLORVALUE &c2)
+{
+ return (fabs(c1.r-c2.r) < 0.01f &&
+ fabs(c1.g-c2.g) < 0.01f &&
+ fabs(c1.b-c2.b) < 0.01f );
+}
+
+// Updates all the buttons for the character.
+
+void CMainDialog::UpdatePerso()
+{
+ CWindow* pw;
+ CLabel* pl;
+ CButton* pb;
+ CColor* pc;
+ CSlider* ps;
+ D3DCOLORVALUE color;
+ char name[100];
+ int i;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+
+ pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_PHEAD);
+ if ( pb != 0 )
+ {
+ pb->SetState(STATE_CHECK, m_persoTab==0);
+ }
+ pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_PBODY);
+ if ( pb != 0 )
+ {
+ pb->SetState(STATE_CHECK, m_persoTab==1);
+ }
+
+ pl = (CLabel*)pw->SearchControl(EVENT_LABEL11);
+ if ( pl != 0 )
+ {
+ if ( m_persoTab == 0 )
+ {
+ pl->SetState(STATE_VISIBLE);
+ GetResource(RES_TEXT, RT_PERSO_FACE, name);
+ pl->SetName(name);
+ }
+ else
+ {
+ pl->ClearState(STATE_VISIBLE);
+ }
+ }
+
+ pl = (CLabel*)pw->SearchControl(EVENT_LABEL12);
+ if ( pl != 0 )
+ {
+ if ( m_persoTab == 0 )
+ {
+ pl->SetState(STATE_VISIBLE);
+ GetResource(RES_TEXT, RT_PERSO_GLASSES, name);
+ pl->SetName(name);
+ }
+ else
+ {
+ pl->ClearState(STATE_VISIBLE);
+ }
+ }
+
+ pl = (CLabel*)pw->SearchControl(EVENT_LABEL13);
+ if ( pl != 0 )
+ {
+ if ( m_persoTab == 0 ) GetResource(RES_TEXT, RT_PERSO_HAIR, name);
+ else GetResource(RES_TEXT, RT_PERSO_BAND, name);
+ pl->SetName(name);
+ }
+
+ pl = (CLabel*)pw->SearchControl(EVENT_LABEL14);
+ if ( pl != 0 )
+ {
+ if ( m_persoTab == 0 )
+ {
+ pl->ClearState(STATE_VISIBLE);
+ }
+ else
+ {
+ pl->SetState(STATE_VISIBLE);
+ GetResource(RES_TEXT, RT_PERSO_COMBI, name);
+ pl->SetName(name);
+ }
+ }
+
+ for ( i=0 ; i<4 ; i++ )
+ {
+ pb = (CButton*)pw->SearchControl((EventMsg)(EVENT_INTERFACE_PFACE1+i));
+ if ( pb == 0 ) break;
+ pb->SetState(STATE_VISIBLE, m_persoTab==0);
+ pb->SetState(STATE_CHECK, i==m_perso.face);
+ }
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ pb = (CButton*)pw->SearchControl((EventMsg)(EVENT_INTERFACE_PGLASS0+i));
+ if ( pb == 0 ) break;
+ pb->SetState(STATE_VISIBLE, m_persoTab==0);
+ pb->SetState(STATE_CHECK, i==m_perso.glasses);
+ }
+
+ for ( i=0 ; i<3*3 ; i++ )
+ {
+ pc = (CColor*)pw->SearchControl((EventMsg)(EVENT_INTERFACE_PC0a+i));
+ if ( pc == 0 ) break;
+ if ( m_persoTab == 0 )
+ {
+ pc->ClearState(STATE_VISIBLE);
+ }
+ else
+ {
+ pc->SetState(STATE_VISIBLE);
+ color.r = perso_color[3*10*1+3*i+0]/255.0f;
+ color.g = perso_color[3*10*1+3*i+1]/255.0f;
+ color.b = perso_color[3*10*1+3*i+2]/255.0f;
+ color.a = 0.0f;
+ pc->SetColor(color);
+ pc->SetState(STATE_CHECK, EqColor(color, m_perso.colorCombi));
+ }
+
+ pc = (CColor*)pw->SearchControl((EventMsg)(EVENT_INTERFACE_PC0b+i));
+ if ( pc == 0 ) break;
+ color.r = perso_color[3*10*2*m_persoTab+3*i+0]/255.0f;
+ color.g = perso_color[3*10*2*m_persoTab+3*i+1]/255.0f;
+ color.b = perso_color[3*10*2*m_persoTab+3*i+2]/255.0f;
+ color.a = 0.0f;
+ pc->SetColor(color);
+ pc->SetState(STATE_CHECK, EqColor(color, m_persoTab?m_perso.colorBand:m_perso.colorHair));
+ }
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ ps = (CSlider*)pw->SearchControl((EventMsg)(EVENT_INTERFACE_PCRa+i));
+ if ( ps == 0 ) break;
+ ps->SetState(STATE_VISIBLE, m_persoTab==1);
+ }
+
+ if ( m_persoTab == 1 )
+ {
+ color = m_perso.colorCombi;
+ ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCRa);
+ if ( ps != 0 ) ps->SetVisibleValue(color.r*255.0f);
+ ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCGa);
+ if ( ps != 0 ) ps->SetVisibleValue(color.g*255.0f);
+ ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCBa);
+ if ( ps != 0 ) ps->SetVisibleValue(color.b*255.0f);
+ }
+
+ if ( m_persoTab == 0 ) color = m_perso.colorHair;
+ else color = m_perso.colorBand;
+ ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCRb);
+ if ( ps != 0 ) ps->SetVisibleValue(color.r*255.0f);
+ ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCGb);
+ if ( ps != 0 ) ps->SetVisibleValue(color.g*255.0f);
+ ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCBb);
+ if ( ps != 0 ) ps->SetVisibleValue(color.b*255.0f);
+}
+
+// Updates the camera for the character.
+
+void CMainDialog::CameraPerso()
+{
+ if ( m_persoTab == 0 )
+ {
+//? m_camera->Init(Math::Vector(4.0f, 0.0f, 0.0f),
+//? Math::Vector(0.0f, 0.0f, 1.0f), 0.0f);
+ m_camera->Init(Math::Vector(6.0f, 0.0f, 0.0f),
+ Math::Vector(0.0f, 0.2f, 1.5f), 0.0f);
+ }
+ else
+ {
+ m_camera->Init(Math::Vector(18.0f, 0.0f, 4.5f),
+ Math::Vector(0.0f, 1.6f, 4.5f), 0.0f);
+ }
+
+ m_camera->SetType(CAMERA_SCRIPT);
+ m_camera->FixCamera();
+}
+
+// Sets a fixed color.
+
+void CMainDialog::FixPerso(int rank, int index)
+{
+ if ( m_persoTab == 0 )
+ {
+ if ( index == 1 )
+ {
+ m_perso.colorHair.r = perso_color[3*10*0+rank*3+0]/255.0f;
+ m_perso.colorHair.g = perso_color[3*10*0+rank*3+1]/255.0f;
+ m_perso.colorHair.b = perso_color[3*10*0+rank*3+2]/255.0f;
+ }
+ }
+ if ( m_persoTab == 1 )
+ {
+ if ( index == 0 )
+ {
+ m_perso.colorCombi.r = perso_color[3*10*1+rank*3+0]/255.0f;
+ m_perso.colorCombi.g = perso_color[3*10*1+rank*3+1]/255.0f;
+ m_perso.colorCombi.b = perso_color[3*10*1+rank*3+2]/255.0f;
+ }
+ if ( index == 1 )
+ {
+ m_perso.colorBand.r = perso_color[3*10*2+rank*3+0]/255.0f;
+ m_perso.colorBand.g = perso_color[3*10*2+rank*3+1]/255.0f;
+ m_perso.colorBand.b = perso_color[3*10*2+rank*3+2]/255.0f;
+ }
+ }
+}
+
+// Updates the color of the character.
+
+void CMainDialog::ColorPerso()
+{
+ CWindow* pw;
+ CSlider* ps;
+ D3DCOLORVALUE color;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+
+ color.a = 0.0f;
+
+ ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCRa);
+ if ( ps != 0 ) color.r = ps->RetVisibleValue()/255.0f;
+ ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCGa);
+ if ( ps != 0 ) color.g = ps->RetVisibleValue()/255.0f;
+ ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCBa);
+ if ( ps != 0 ) color.b = ps->RetVisibleValue()/255.0f;
+ if ( m_persoTab == 1 ) m_perso.colorCombi = color;
+
+ ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCRb);
+ if ( ps != 0 ) color.r = ps->RetVisibleValue()/255.0f;
+ ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCGb);
+ if ( ps != 0 ) color.g = ps->RetVisibleValue()/255.0f;
+ ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_PCBb);
+ if ( ps != 0 ) color.b = ps->RetVisibleValue()/255.0f;
+ if ( m_persoTab == 0 ) m_perso.colorHair = color;
+ else m_perso.colorBand = color;
+}
+
+// Updates the default settings of the character.
+
+void CMainDialog::DefPerso()
+{
+ m_perso.colorCombi.r = 206.0f/256.0f;
+ m_perso.colorCombi.g = 206.0f/256.0f;
+ m_perso.colorCombi.b = 204.0f/256.0f; // ~white
+ m_perso.colorBand.r = 255.0f/256.0f;
+ m_perso.colorBand.g = 132.0f/256.0f;
+ m_perso.colorBand.b = 1.0f/256.0f; // orange
+
+ if ( m_perso.face == 0 ) // normal ?
+ {
+ m_perso.glasses = 0;
+ m_perso.colorHair.r = 90.0f/256.0f;
+ m_perso.colorHair.g = 95.0f/256.0f;
+ m_perso.colorHair.b = 85.0f/256.0f; // black
+ }
+ if ( m_perso.face == 1 ) // bald ?
+ {
+ m_perso.glasses = 0;
+ m_perso.colorHair.r = 83.0f/256.0f;
+ m_perso.colorHair.g = 64.0f/256.0f;
+ m_perso.colorHair.b = 51.0f/256.0f; // brown
+ }
+ if ( m_perso.face == 2 ) // carlos ?
+ {
+ m_perso.glasses = 1;
+ m_perso.colorHair.r = 85.0f/256.0f;
+ m_perso.colorHair.g = 48.0f/256.0f;
+ m_perso.colorHair.b = 9.0f/256.0f; // brown
+ }
+ if ( m_perso.face == 3 ) // blond ?
+ {
+ m_perso.glasses = 4;
+ m_perso.colorHair.r = 255.0f/256.0f;
+ m_perso.colorHair.g = 255.0f/256.0f;
+ m_perso.colorHair.b = 181.0f/256.0f; // yellow
+ }
+
+ m_perso.colorHair.a = 0.0f;
+ m_perso.colorCombi.a = 0.0f;
+ m_perso.colorBand.a = 0.0f;
+}
+
+
+// Indicates if there is at least one backup.
+
+bool CMainDialog::IsIOReadScene()
+{
+ FILE* file;
+ char filename[100];
+
+ sprintf(filename, "%s\\%s\\save%c%.3d\\data.sav", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], 0);
+ file = fopen(filename, "r");
+ if ( file == NULL ) return false;
+ fclose(file);
+ return true;
+}
+
+// Builds the file name by default.
+
+void CMainDialog::IOReadName()
+{
+ FILE* file;
+ CWindow* pw;
+ CEdit* pe;
+ char filename[_MAX_FNAME];
+ char op[100];
+ char line[500];
+ char resume[100];
+ char name[100];
+ time_t now;
+ int i;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_IONAME);
+ if ( pe == 0 ) return;
+
+ sprintf(resume, "%s %d", m_sceneName, m_chap[m_index]+1);
+ BuildSceneName(filename, m_sceneName, (m_chap[m_index]+1)*100);
+ file = fopen(filename, "r");
+ if ( file != NULL )
+ {
+ while ( fgets(line, 500, file) != NULL )
+ {
+ for ( i=0 ; i<500 ; i++ )
+ {
+ if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space
+ if ( line[i] == '/' && line[i+1] == '/' )
+ {
+ line[i] = 0;
+ break;
+ }
+ }
+
+ sprintf(op, "Title.%c", RetLanguageLetter());
+ if ( Cmd(line, op) )
+ {
+ OpString(line, "resume", resume);
+ break;
+ }
+ }
+ fclose(file);
+ }
+
+ time(&now);
+ TimeToAscii(now, line);
+ sprintf(name, "%s %d - %s", resume, m_sel[m_index]+1, line);
+ pe->SetText(name);
+ pe->SetCursor(strlen(name), 0);
+ pe->SetFocus(true);
+}
+
+// Updates the list of games recorded on disk.
+
+void CMainDialog::IOReadList()
+{
+ FILE* file = NULL;
+ CWindow* pw;
+ CList* pl;
+ char filename[100];
+ char line[500];
+ char name[100];
+ int i, j;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pl = (CList*)pw->SearchControl(EVENT_INTERFACE_IOLIST);
+ if ( pl == 0 ) return;
+
+ pl->Flush();
+
+ for ( j=0 ; j<999 ; j++ )
+ {
+ sprintf(filename, "%s\\%s\\save%c%.3d\\data.sav", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], j);
+ file = fopen(filename, "r");
+ if ( file == NULL ) break;
+
+ strcmp(name, filename); // default name
+ while ( fgets(line, 500, file) != NULL )
+ {
+ for ( i=0 ; i<500 ; i++ )
+ {
+ if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space
+ if ( line[i] == '/' && line[i+1] == '/' )
+ {
+ line[i] = 0;
+ break;
+ }
+ }
+
+ if ( Cmd(line, "Title") )
+ {
+ OpString(line, "text", name);
+ break;
+ }
+ }
+ fclose(file);
+
+ pl->SetName(j, name);
+ }
+
+ if ( m_phase == PHASE_WRITE ||
+ m_phase == PHASE_WRITEs )
+ {
+ GetResource(RES_TEXT, RT_IO_NEW, name);
+ pl->SetName(j, name);
+ j ++;
+ }
+
+ pl->SetSelect(j-1);
+ pl->ShowSelect(false); // shows the selected columns
+}
+
+// Updates the buttons according to the selected part in the list.
+
+void CMainDialog::IOUpdateList()
+{
+ FILE* file = NULL;
+ CWindow* pw;
+ CList* pl;
+ CButton* pb;
+ CImage* pi;
+ char filename[100];
+ int sel, max;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pl = (CList*)pw->SearchControl(EVENT_INTERFACE_IOLIST);
+ if ( pl == 0 ) return;
+ pi = (CImage*)pw->SearchControl(EVENT_INTERFACE_IOIMAGE);
+ if ( pi == 0 ) return;
+
+ sel = pl->RetSelect();
+ max = pl->RetTotal();
+
+ sprintf(filename, "%s\\%s\\save%c%.3d\\screen.bmp", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
+
+ if ( m_phase == PHASE_WRITE ||
+ m_phase == PHASE_WRITEs )
+ {
+ if ( sel < max-1 )
+ {
+ pi->SetFilenameImage(filename);
+ }
+ else
+ {
+ pi->SetFilenameImage("");
+ }
+
+ pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_IODELETE);
+ if ( pb != 0 )
+ {
+ pb->SetState(STATE_ENABLE, sel < max-1);
+ }
+ }
+ else
+ {
+ pi->SetFilenameImage(filename);
+ }
+}
+
+// Deletes the selected scene.
+
+void CMainDialog::IODeleteScene()
+{
+ CWindow* pw;
+ CList* pl;
+ char dir[100];
+ char old[100];
+ long hFile;
+ struct _finddata_t fBuffer;
+ int sel, max, i;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pl = (CList*)pw->SearchControl(EVENT_INTERFACE_IOLIST);
+ if ( pl == 0 ) return;
+
+ sel = pl->RetSelect();
+ if ( sel == -1 )
+ {
+ m_sound->Play(SOUND_TZOING);
+ return;
+ }
+
+ // Deletes all the contents of the file.
+ sprintf(dir, "%s\\%s\\save%c%.3d\\*", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
+ hFile = _findfirst(dir, &fBuffer);
+ if ( hFile != -1 )
+ {
+ do
+ {
+ if ( fBuffer.name[0] != '.' )
+ {
+ sprintf(dir, "%s\\%s\\save%c%.3d\\%s", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel, fBuffer.name);
+ remove(dir);
+ }
+ }
+ while ( _findnext(hFile, &fBuffer) == 0 );
+ }
+
+ sprintf(dir, "%s\\%s\\save%c%.3d", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
+ if ( _rmdir(dir) != 0 )
+ {
+ m_sound->Play(SOUND_TZOING);
+ return;
+ }
+
+ max = pl->RetTotal();
+ for ( i=sel+1 ; i<max ; i++ )
+ {
+ sprintf(old, "%s\\%s\\save%c%.3d", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], i);
+ sprintf(dir, "%s\\%s\\save%c%.3d", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], i-1);
+ rename(old, dir);
+ }
+ IOReadList();
+}
+
+// Writes the scene.
+
+bool CMainDialog::IOWriteScene()
+{
+ CWindow* pw;
+ CList* pl;
+ CEdit* pe;
+ char filename[100];
+ char filecbot[100];
+ char info[100];
+ int sel;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return false;
+ pl = (CList*)pw->SearchControl(EVENT_INTERFACE_IOLIST);
+ if ( pl == 0 ) return false;
+ pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_IONAME);
+ if ( pe == 0 ) return false;
+
+ sel = pl->RetSelect();
+ if ( sel == -1 ) return false;
+
+ _mkdir("Savegame"); // if doesn't exist yet!
+ sprintf(filename, "%s\\%s", m_savegameDir, m_main->RetGamerName());
+ _mkdir(filename);
+ sprintf(filename, "%s\\%s\\save%c%.3d", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
+ _mkdir(filename);
+
+ sprintf(filename, "%s\\%s\\save%c%.3d\\data.sav", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
+ sprintf(filecbot, "%s\\%s\\save%c%.3d\\cbot.run", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
+ pe->GetText(info, 100);
+ m_main->IOWriteScene(filename, filecbot, info);
+
+ m_shotDelay = 3;
+ sprintf(m_shotName, "%s\\%s\\save%c%.3d\\screen.bmp", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
+
+ return true;
+}
+
+// Reads the scene.
+
+bool CMainDialog::IOReadScene()
+{
+ FILE* file;
+ CWindow* pw;
+ CList* pl;
+ char filename[100];
+ char filecbot[100];
+ char line[500];
+ char dir[100];
+ int sel, i;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return false;
+ pl = (CList*)pw->SearchControl(EVENT_INTERFACE_IOLIST);
+ if ( pl == 0 ) return false;
+
+ sel = pl->RetSelect();
+ if ( sel == -1 ) return false;
+
+ sprintf(filename, "%s\\%s\\save%c%.3d\\data.sav", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
+ sprintf(filecbot, "%s\\%s\\save%c%.3d\\cbot.run", m_savegameDir, m_main->RetGamerName(), m_sceneName[0], sel);
+
+ file = fopen(filename, "r");
+ if ( file == NULL ) return false;
+
+ while ( fgets(line, 500, file) != NULL )
+ {
+ for ( i=0 ; i<500 ; i++ )
+ {
+ if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space
+ if ( line[i] == '/' && line[i+1] == '/' )
+ {
+ line[i] = 0;
+ break;
+ }
+ }
+
+ if ( Cmd(line, "Mission") )
+ {
+ OpString(line, "base", m_sceneName);
+ m_sceneRank = OpInt(line, "rank", 0);
+
+ if ( strcmp(m_sceneName, "user") == 0 )
+ {
+ m_sceneRank = m_sceneRank%100;
+ OpString(line, "dir", dir);
+ for ( i=0 ; i<m_userTotal ; i++ )
+ {
+ if ( strcmp(m_userList[i], dir) == 0 )
+ {
+ m_sceneRank += (i+1)*100;
+ break;
+ }
+ }
+ if ( m_sceneRank/100 == 0 )
+ {
+ fclose(file);
+ return false;
+ }
+ }
+ }
+ }
+ fclose(file);
+
+ m_chap[m_index] = (m_sceneRank/100)-1;
+ m_sel[m_index] = (m_sceneRank%100)-1;
+
+ strcpy(m_sceneRead, filename);
+ strcpy(m_stackRead, filecbot);
+ return true;
+}
+
+
+// Returns the number of accessible chapters.
+
+int CMainDialog::RetChapPassed()
+{
+ int j;
+
+ if ( m_main->RetShowAll() ) return 9;
+
+ for ( j=0 ; j<9 ; j++ )
+ {
+ if ( !RetGamerInfoPassed((j+1)*100) )
+ {
+ return j;
+ }
+ }
+ return 9;
+}
+
+// Updates the lists according to the cheat code.
+
+void CMainDialog::AllMissionUpdate()
+{
+ if ( m_phase == PHASE_TRAINER ||
+ m_phase == PHASE_DEFI ||
+ m_phase == PHASE_MISSION ||
+ m_phase == PHASE_FREE ||
+ m_phase == PHASE_TEEN ||
+ m_phase == PHASE_USER ||
+ m_phase == PHASE_PROTO )
+ {
+ UpdateSceneChap(m_chap[m_index]);
+ UpdateSceneList(m_chap[m_index], m_sel[m_index]);
+ }
+}
+
+// Updates the chapters of exercises or missions.
+
+void CMainDialog::UpdateSceneChap(int &chap)
+{
+ FILE* file = NULL;
+ CWindow* pw;
+ CList* pl;
+ long hFile;
+ struct _finddata_t fileBuffer;
+ char filename[_MAX_FNAME];
+ char op[100];
+ char line[500];
+ char name[100];
+ int i, j;
+ bool bPassed, bDo;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pl = (CList*)pw->SearchControl(EVENT_INTERFACE_CHAP);
+ if ( pl == 0 ) return;
+
+ pl->Flush();
+
+ if ( m_phase == PHASE_USER )
+ {
+ j = 0;
+ hFile = _findfirst("user\\*", &fileBuffer);
+ if ( hFile != -1 )
+ {
+ do
+ {
+ if ( (fileBuffer.attrib & _A_SUBDIR) != 0 &&
+ fileBuffer.name[0] != '.' )
+ {
+ strcpy(m_userList[j++], fileBuffer.name);
+ }
+ }
+ while ( _findnext(hFile, &fileBuffer) == 0 && j < 100 );
+ }
+ m_userTotal = j;
+
+ do // sorts all names:
+ {
+ bDo = false;
+ for ( i=0 ; i<m_userTotal-1 ; i++ )
+ {
+ if ( strcmp(m_userList[i], m_userList[i+1]) > 0 )
+ {
+ strcpy(name, m_userList[i]);
+ strcpy(m_userList[i], m_userList[i+1]);
+ strcpy(m_userList[i+1], name);
+ bDo = true;
+ }
+ }
+ }
+ while ( bDo );
+
+ for ( j=0 ; j<m_userTotal ; j++ )
+ {
+ BuildSceneName(filename, m_sceneName, (j+1)*100);
+ file = fopen(filename, "r");
+ if ( file == NULL )
+ {
+ strcpy(name, m_userList[j]);
+ }
+ else
+ {
+ BuildResumeName(name, m_sceneName, j+1); // default name
+ while ( fgets(line, 500, file) != NULL )
+ {
+ for ( i=0 ; i<500 ; i++ )
+ {
+ if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space
+ if ( line[i] == '/' && line[i+1] == '/' )
+ {
+ line[i] = 0;
+ break;
+ }
+ }
+
+ sprintf(op, "Title.%c", RetLanguageLetter());
+ if ( Cmd(line, op) )
+ {
+ OpString(line, "text", name);
+ break;
+ }
+ }
+ fclose(file);
+ }
+
+ pl->SetName(j, name);
+ pl->SetEnable(j, true);
+ }
+ }
+ else
+ {
+ for ( j=0 ; j<9 ; j++ )
+ {
+#if _SCHOOL
+ if ( m_phase == PHASE_MISSION ) break;
+ if ( m_phase == PHASE_FREE ) break;
+#if _CEEBOTDEMO
+ if ( m_phase == PHASE_TRAINER && j >= 2 ) break;
+#endif
+#endif
+#if _DEMO
+ if ( m_phase == PHASE_MISSION && j >= 4 ) break;
+ if ( m_phase == PHASE_TRAINER && j >= 1 ) break;
+#endif
+ BuildSceneName(filename, m_sceneName, (j+1)*100);
+ file = fopen(filename, "r");
+ if ( file == NULL ) break;
+
+ BuildResumeName(name, m_sceneName, j+1); // default name
+ while ( fgets(line, 500, file) != NULL )
+ {
+ for ( i=0 ; i<500 ; i++ )
+ {
+ if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space
+ if ( line[i] == '/' && line[i+1] == '/' )
+ {
+ line[i] = 0;
+ break;
+ }
+ }
+
+ sprintf(op, "Title.%c", RetLanguageLetter());
+ if ( Cmd(line, op) )
+ {
+ OpString(line, "text", name);
+ break;
+ }
+ }
+ fclose(file);
+
+ bPassed = RetGamerInfoPassed((j+1)*100);
+ sprintf(line, "%d: %s", j+1, name);
+ pl->SetName(j, line);
+ pl->SetCheck(j, bPassed);
+ pl->SetEnable(j, true);
+
+ if ( m_phase == PHASE_MISSION && !m_main->RetShowAll() && !bPassed )
+ {
+ j ++;
+ break;
+ }
+
+#if _TEEN
+ if ( m_phase == PHASE_TRAINER && !m_main->RetShowAll() && !bPassed )
+ {
+ j ++;
+ break;
+ }
+#endif
+
+ if ( m_phase == PHASE_FREE && j == m_accessChap )
+ {
+ j ++;
+ break;
+ }
+ }
+ }
+
+ if ( chap > j-1 ) chap = j-1;
+
+ pl->SetSelect(chap);
+ pl->ShowSelect(false); // shows the selected columns
+}
+
+// Updates the list of exercises or missions.
+
+void CMainDialog::UpdateSceneList(int chap, int &sel)
+{
+ FILE* file = NULL;
+ CWindow* pw;
+ CList* pl;
+ char filename[_MAX_FNAME];
+ char op[100];
+ char line[500];
+ char name[100];
+ int i, j;
+ bool bPassed;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pl = (CList*)pw->SearchControl(EVENT_INTERFACE_LIST);
+ if ( pl == 0 ) return;
+
+ pl->Flush();
+
+ for ( j=0 ; j<99 ; j++ )
+ {
+#if _SCHOOL
+ if ( m_phase == PHASE_MISSION ) break;
+ if ( m_phase == PHASE_FREE ) break;
+#if _CEEBOTDEMO
+#if _TEEN
+ if ( m_phase == PHASE_TRAINER && j >= 5 ) break;
+#else
+ if ( m_phase == PHASE_TRAINER && j >= 3 ) break;
+#endif
+#endif
+#endif
+#if _DEMO
+ if ( m_phase == PHASE_MISSION && j >= 3 ) break;
+ if ( m_phase == PHASE_TRAINER && j >= 5 ) break;
+#endif
+ BuildSceneName(filename, m_sceneName, (chap+1)*100+(j+1));
+ file = fopen(filename, "r");
+ if ( file == NULL ) break;
+
+ BuildResumeName(name, m_sceneName, j+1); // default name
+ while ( fgets(line, 500, file) != NULL )
+ {
+ for ( i=0 ; i<500 ; i++ )
+ {
+ if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space
+ if ( line[i] == '/' && line[i+1] == '/' )
+ {
+ line[i] = 0;
+ break;
+ }
+ }
+
+ sprintf(op, "Title.%c", RetLanguageLetter());
+ if ( Cmd(line, op) )
+ {
+ OpString(line, "text", name);
+ break;
+ }
+ }
+ fclose(file);
+
+ bPassed = RetGamerInfoPassed((chap+1)*100+(j+1));
+ sprintf(line, "%d: %s", j+1, name);
+ pl->SetName(j, line);
+ pl->SetCheck(j, bPassed);
+ pl->SetEnable(j, true);
+
+ if ( m_phase == PHASE_MISSION && !m_main->RetShowAll() && !bPassed )
+ {
+ j ++;
+ break;
+ }
+
+#if _TEEN
+ if ( m_phase == PHASE_TRAINER && !m_main->RetShowAll() && !bPassed )
+ {
+ j ++;
+ break;
+ }
+#endif
+ }
+
+ BuildSceneName(filename, m_sceneName, (chap+1)*100+(j+1));
+ file = fopen(filename, "r");
+ if ( file == NULL )
+ {
+ m_maxList = j;
+ }
+ else
+ {
+ m_maxList = j+1; // this is not the last!
+ fclose(file);
+ }
+
+ if ( sel > j-1 ) sel = j-1;
+
+ pl->SetSelect(sel);
+ pl->ShowSelect(false); // shows the selected columns
+}
+
+// Updates the button "solution" according to cheat code.
+
+void CMainDialog::ShowSoluceUpdate()
+{
+ CWindow* pw;
+ CEdit* pe;
+ CCheck* pc;
+
+ if ( m_phase == PHASE_TRAINER ||
+ m_phase == PHASE_DEFI ||
+ m_phase == PHASE_MISSION ||
+ m_phase == PHASE_FREE ||
+ m_phase == PHASE_TEEN ||
+ m_phase == PHASE_USER ||
+ m_phase == PHASE_PROTO )
+ {
+ m_bSceneSoluce = false;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_RESUME);
+ if ( pe == 0 ) return;
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_SOLUCE);
+ if ( pc == 0 ) return;
+
+ if ( m_main->RetShowSoluce() )
+ {
+ pc->SetState(STATE_VISIBLE);
+ pc->SetState(STATE_CHECK);
+ m_bSceneSoluce = true;
+ }
+ else
+ {
+ pc->ClearState(STATE_VISIBLE);
+ pc->ClearState(STATE_CHECK);
+ m_bSceneSoluce = false;
+ }
+ }
+}
+
+// Updates a summary of exercise or mission.
+
+void CMainDialog::UpdateSceneResume(int rank)
+{
+ FILE* file = NULL;
+ CWindow* pw;
+ CEdit* pe;
+ CCheck* pc;
+ char filename[_MAX_FNAME];
+ char op[100];
+ char line[500];
+ char name[500];
+ int i, numTry;
+ bool bPassed, bVisible;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pe = (CEdit*)pw->SearchControl(EVENT_INTERFACE_RESUME);
+ if ( pe == 0 ) return;
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_SOLUCE);
+
+ if ( pc == 0 )
+ {
+ m_bSceneSoluce = false;
+ }
+ else
+ {
+ numTry = RetGamerInfoTry(rank);
+ bPassed = RetGamerInfoPassed(rank);
+ bVisible = ( numTry > 2 || bPassed || m_main->RetShowSoluce() );
+ if ( !RetSoluce4() ) bVisible = false;
+ pc->SetState(STATE_VISIBLE, bVisible);
+ if ( !bVisible )
+ {
+ pc->ClearState(STATE_CHECK);
+ m_bSceneSoluce = false;
+ }
+ }
+
+ BuildSceneName(filename, m_sceneName, rank);
+ file = fopen(filename, "r");
+ if ( file == NULL ) return;
+
+ name[0] = 0;
+ while ( fgets(line, 500, file) != NULL )
+ {
+ for ( i=0 ; i<500 ; i++ )
+ {
+ if ( line[i] == '\t' ) line[i] = ' '; // replaces tab by space
+ if ( line[i] == '/' && line[i+1] == '/' )
+ {
+ line[i] = 0;
+ break;
+ }
+ }
+
+ sprintf(op, "Resume.%c", RetLanguageLetter());
+ if ( Cmd(line, op) )
+ {
+ OpString(line, "text", name);
+ break;
+ }
+ }
+ fclose(file);
+
+ pe->SetText(name);
+}
+
+// Updates the list of devices.
+
+void CMainDialog::UpdateDisplayDevice()
+{
+ CWindow* pw;
+ CList* pl;
+ char bufDevices[1000];
+ char bufModes[5000];
+ int i, j, totalDevices, selectDevices, totalModes, selectModes;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pl = (CList*)pw->SearchControl(EVENT_LIST1);
+ if ( pl == 0 ) return;
+ pl->Flush();
+
+ m_engine->EnumDevices(bufDevices, 1000,
+ bufModes, 5000,
+ totalDevices, selectDevices,
+ totalModes, selectModes);
+
+ i = 0;
+ j = 0;
+ while ( bufDevices[i] != 0 )
+ {
+ pl->SetName(j++, bufDevices+i);
+ while ( bufDevices[i++] != 0 );
+ }
+
+ pl->SetSelect(selectDevices);
+ pl->ShowSelect(false);
+
+ m_setupSelDevice = selectDevices;
+}
+
+// Updates the list of modes.
+
+void CMainDialog::UpdateDisplayMode()
+{
+ CWindow* pw;
+ CList* pl;
+ char bufDevices[1000];
+ char bufModes[5000];
+ int i, j, totalDevices, selectDevices, totalModes, selectModes;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+ pl = (CList*)pw->SearchControl(EVENT_LIST2);
+ if ( pl == 0 ) return;
+ pl->Flush();
+
+ m_engine->EnumDevices(bufDevices, 1000,
+ bufModes, 5000,
+ totalDevices, selectDevices,
+ totalModes, selectModes);
+
+ i = 0;
+ j = 0;
+ while ( bufModes[i] != 0 )
+ {
+ pl->SetName(j++, bufModes+i);
+ while ( bufModes[i++] != 0 );
+ }
+
+ pl->SetSelect(selectModes);
+ pl->ShowSelect(false);
+
+ m_setupSelMode = selectModes;
+}
+
+// Change the graphics mode.
+
+void CMainDialog::ChangeDisplay()
+{
+ CWindow* pw;
+ CList* pl;
+ CCheck* pc;
+ char* device;
+ char* mode;
+ bool bFull;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+
+ pl = (CList*)pw->SearchControl(EVENT_LIST1);
+ if ( pl == 0 ) return;
+ m_setupSelDevice = pl->RetSelect();
+ device = pl->RetName(m_setupSelDevice);
+
+ pl = (CList*)pw->SearchControl(EVENT_LIST2);
+ if ( pl == 0 ) return;
+ m_setupSelMode = pl->RetSelect();
+ mode = pl->RetName(m_setupSelMode);
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_FULL);
+ if ( pc == 0 ) return;
+ bFull = pc->TestState(STATE_CHECK);
+ m_setupFull = bFull;
+
+ m_engine->ChangeDevice(device, mode, bFull);
+
+ if ( m_bSimulSetup )
+ {
+ m_main->ChangeColor();
+ m_main->UpdateMap();
+ }
+}
+
+
+
+// Updates the "apply" button.
+
+void CMainDialog::UpdateApply()
+{
+ CWindow* pw;
+ CButton* pb;
+ CList* pl;
+ CCheck* pc;
+ int sel1, sel2;
+ bool bFull;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+
+ pb = (CButton*)pw->SearchControl(EVENT_INTERFACE_APPLY);
+ if ( pb == 0 ) return;
+
+ pl = (CList*)pw->SearchControl(EVENT_LIST1);
+ if ( pl == 0 ) return;
+ sel1 = pl->RetSelect();
+
+ pl = (CList*)pw->SearchControl(EVENT_LIST2);
+ if ( pl == 0 ) return;
+ sel2 = pl->RetSelect();
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_FULL);
+ bFull = pc->TestState(STATE_CHECK);
+
+ if ( sel1 == m_setupSelDevice &&
+ sel2 == m_setupSelMode &&
+ bFull == m_setupFull )
+ {
+ pb->ClearState(STATE_ENABLE);
+ }
+ else
+ {
+ pb->SetState(STATE_ENABLE);
+ }
+}
+
+// Updates the buttons during the setup phase.
+
+void CMainDialog::UpdateSetupButtons()
+{
+ CWindow* pw;
+ CCheck* pc;
+ CEditValue* pv;
+ CSlider* ps;
+ float value;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_TOTO);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_engine->RetTotoMode());
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_TOOLTIP);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_bTooltip);
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_GLINT);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_bGlint);
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_RAIN);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_bRain);
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_MOUSE);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_engine->RetNiceMouse());
+ pc->SetState(STATE_ENABLE, m_engine->RetNiceMouseCap());
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_EDITMODE);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_engine->RetEditIndentMode());
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_EDITVALUE);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_engine->RetEditIndentValue()>2);
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_SOLUCE4);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_bSoluce4);
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_MOVIES);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_bMovies);
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_NICERST);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_bNiceReset);
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_HIMSELF);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_bHimselfDamage);
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_SCROLL);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_bCameraScroll);
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_INVERTX);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_bCameraInvertX);
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_INVERTY);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_bCameraInvertY);
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_EFFECT);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_bEffect);
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_SHADOW);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_engine->RetShadow());
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_GROUND);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_engine->RetGroundSpot());
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_DIRTY);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_engine->RetDirty());
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_FOG);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_engine->RetFog());
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_LENS);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_engine->RetLensMode());
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_SKY);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_engine->RetSkyMode());
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_PLANET);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_engine->RetPlanetMode());
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_LIGHT);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_engine->RetLightMode());
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_JOYSTICK);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_engine->RetJoystick());
+ }
+
+ pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_PARTI);
+ if ( pv != 0 )
+ {
+ value = m_engine->RetParticuleDensity();
+ pv->SetValue(value);
+ }
+
+ pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_CLIP);
+ if ( pv != 0 )
+ {
+ value = m_engine->RetClippingDistance();
+ pv->SetValue(value);
+ }
+
+ pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_DETAIL);
+ if ( pv != 0 )
+ {
+ value = m_engine->RetObjectDetail();
+ pv->SetValue(value);
+ }
+
+ pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_GADGET);
+ if ( pv != 0 )
+ {
+ value = m_engine->RetGadgetQuantity();
+ pv->SetValue(value);
+ }
+
+ pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_TEXTURE);
+ if ( pv != 0 )
+ {
+ value = (float)m_engine->RetTextureQuality();
+ pv->SetValue(value);
+ }
+
+ ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_VOLSOUND);
+ if ( ps != 0 )
+ {
+ value = (float)m_sound->RetAudioVolume();
+ ps->SetVisibleValue(value);
+ }
+
+ ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_VOLMUSIC);
+ if ( ps != 0 )
+ {
+ value = (float)m_sound->RetMidiVolume();
+ ps->SetVisibleValue(value);
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_INTERFACE_SOUND3D);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_sound->RetSound3D());
+ pc->SetState(STATE_ENABLE, m_sound->RetSound3DCap());
+ }
+}
+
+// Updates the engine function of the buttons after the setup phase.
+
+void CMainDialog::ChangeSetupButtons()
+{
+ CWindow* pw;
+ CEditValue* pv;
+ CSlider* ps;
+ float value;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+
+ pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_PARTI);
+ if ( pv != 0 )
+ {
+ value = pv->RetValue();
+ m_engine->SetParticuleDensity(value);
+ }
+
+ pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_CLIP);
+ if ( pv != 0 )
+ {
+ value = pv->RetValue();
+ m_engine->SetClippingDistance(value);
+ }
+
+ pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_DETAIL);
+ if ( pv != 0 )
+ {
+ value = pv->RetValue();
+ m_engine->SetObjectDetail(value);
+ }
+
+ pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_GADGET);
+ if ( pv != 0 )
+ {
+ value = pv->RetValue();
+ m_engine->SetGadgetQuantity(value);
+ }
+
+ pv = (CEditValue*)pw->SearchControl(EVENT_INTERFACE_TEXTURE);
+ if ( pv != 0 )
+ {
+ value = pv->RetValue();
+ m_engine->SetTextureQuality((int)value);
+ }
+
+ ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_VOLSOUND);
+ if ( ps != 0 )
+ {
+ value = ps->RetVisibleValue();
+ m_sound->SetAudioVolume((int)value);
+ }
+
+ ps = (CSlider*)pw->SearchControl(EVENT_INTERFACE_VOLMUSIC);
+ if ( ps != 0 )
+ {
+ value = ps->RetVisibleValue();
+ m_sound->SetMidiVolume((int)value);
+ }
+}
+
+
+// Memorizes all the settings.
+
+void CMainDialog::SetupMemorize()
+{
+ float fValue;
+ int iValue, i, j;
+ char key[500];
+ char num[10];
+
+ SetProfileString("Directory", "scene", m_sceneDir);
+ SetProfileString("Directory", "savegame", m_savegameDir);
+ SetProfileString("Directory", "public", m_publicDir);
+ SetProfileString("Directory", "user", m_userDir);
+ SetProfileString("Directory", "files", m_filesDir);
+
+ iValue = m_engine->RetTotoMode();
+ SetProfileInt("Setup", "TotoMode", iValue);
+
+ iValue = m_bTooltip;
+ SetProfileInt("Setup", "Tooltips", iValue);
+
+ iValue = m_bGlint;
+ SetProfileInt("Setup", "InterfaceGlint", iValue);
+
+ iValue = m_bRain;
+ SetProfileInt("Setup", "InterfaceGlint", iValue);
+
+ iValue = m_engine->RetNiceMouse();
+ SetProfileInt("Setup", "NiceMouse", iValue);
+
+ iValue = m_bSoluce4;
+ SetProfileInt("Setup", "Soluce4", iValue);
+
+ iValue = m_bMovies;
+ SetProfileInt("Setup", "Movies", iValue);
+
+ iValue = m_bNiceReset;
+ SetProfileInt("Setup", "NiceReset", iValue);
+
+ iValue = m_bHimselfDamage;
+ SetProfileInt("Setup", "HimselfDamage", iValue);
+
+ iValue = m_bCameraScroll;
+ SetProfileInt("Setup", "CameraScroll", iValue);
+
+ iValue = m_bCameraInvertX;
+ SetProfileInt("Setup", "CameraInvertX", iValue);
+
+ iValue = m_bEffect;
+ SetProfileInt("Setup", "InterfaceEffect", iValue);
+
+ iValue = m_engine->RetShadow();
+ SetProfileInt("Setup", "GroundShadow", iValue);
+
+ iValue = m_engine->RetGroundSpot();
+ SetProfileInt("Setup", "GroundSpot", iValue);
+
+ iValue = m_engine->RetDirty();
+ SetProfileInt("Setup", "ObjectDirty", iValue);
+
+ iValue = m_engine->RetFog();
+ SetProfileInt("Setup", "FogMode", iValue);
+
+ iValue = m_engine->RetLensMode();
+ SetProfileInt("Setup", "LensMode", iValue);
+
+ iValue = m_engine->RetSkyMode();
+ SetProfileInt("Setup", "SkyMode", iValue);
+
+ iValue = m_engine->RetPlanetMode();
+ SetProfileInt("Setup", "PlanetMode", iValue);
+
+ iValue = m_engine->RetLightMode();
+ SetProfileInt("Setup", "LightMode", iValue);
+
+ iValue = m_engine->RetJoystick();
+ SetProfileInt("Setup", "UseJoystick", iValue);
+
+ fValue = m_engine->RetParticuleDensity();
+ SetProfileFloat("Setup", "ParticuleDensity", fValue);
+
+ fValue = m_engine->RetClippingDistance();
+ SetProfileFloat("Setup", "ClippingDistance", fValue);
+
+ fValue = m_engine->RetObjectDetail();
+ SetProfileFloat("Setup", "ObjectDetail", fValue);
+
+ fValue = m_engine->RetGadgetQuantity();
+ SetProfileFloat("Setup", "GadgetQuantity", fValue);
+
+ iValue = m_engine->RetTextureQuality();
+ SetProfileInt("Setup", "TextureQuality", iValue);
+
+ iValue = m_sound->RetAudioVolume();
+ SetProfileInt("Setup", "AudioVolume", iValue);
+
+ iValue = m_sound->RetMidiVolume();
+ SetProfileInt("Setup", "MidiVolume", iValue);
+
+ iValue = m_sound->RetSound3D();
+ SetProfileInt("Setup", "Sound3D", iValue);
+
+ iValue = m_engine->RetEditIndentMode();
+ SetProfileInt("Setup", "EditIndentMode", iValue);
+
+ iValue = m_engine->RetEditIndentValue();
+ SetProfileInt("Setup", "EditIndentValue", iValue);
+
+ key[0] = 0;
+ for ( i=0 ; i<100 ; i++ )
+ {
+ if ( m_engine->RetKey(i, 0) == 0 ) break;
+
+ for ( j=0 ; j<2 ; j++ )
+ {
+ iValue = m_engine->RetKey(i, j);
+ sprintf(num, "%d%c", iValue, j==0?'+':' ');
+ strcat(key, num);
+ }
+ }
+ SetProfileString("Setup", "KeyMap", key);
+
+#if _NET
+ if ( m_accessEnable )
+ {
+ iValue = m_accessMission;
+ SetProfileInt("Setup", "AccessMission", iValue);
+
+ iValue = m_accessUser;
+ SetProfileInt("Setup", "AccessUser", iValue);
+ }
+#endif
+
+ iValue = m_bDeleteGamer;
+ SetProfileInt("Setup", "DeleteGamer", iValue);
+
+ m_engine->WriteProfile();
+}
+
+// Remember all the settings.
+
+void CMainDialog::SetupRecall()
+{
+ float fValue;
+ int iValue, i, j;
+ char key[500];
+ char* p;
+
+ if ( GetProfileString("Directory", "scene", key, _MAX_FNAME) )
+ {
+ strcpy(m_sceneDir, key);
+ }
+
+ if ( GetProfileString("Directory", "savegame", key, _MAX_FNAME) )
+ {
+ strcpy(m_savegameDir, key);
+ }
+
+ if ( GetProfileString("Directory", "public", key, _MAX_FNAME) )
+ {
+ strcpy(m_publicDir, key);
+ }
+
+ if ( GetProfileString("Directory", "user", key, _MAX_FNAME) )
+ {
+ strcpy(m_userDir, key);
+ }
+
+ if ( GetProfileString("Directory", "files", key, _MAX_FNAME) )
+ {
+ strcpy(m_filesDir, key);
+ }
+
+
+ if ( GetProfileInt("Setup", "TotoMode", iValue) )
+ {
+ m_engine->SetTotoMode(iValue);
+ }
+
+ if ( GetProfileInt("Setup", "Tooltips", iValue) )
+ {
+ m_bTooltip = iValue;
+ }
+
+ if ( GetProfileInt("Setup", "InterfaceGlint", iValue) )
+ {
+ m_bGlint = iValue;
+ }
+
+ if ( GetProfileInt("Setup", "InterfaceGlint", iValue) )
+ {
+ m_bRain = iValue;
+ }
+
+ if ( GetProfileInt("Setup", "NiceMouse", iValue) )
+ {
+ m_engine->SetNiceMouse(iValue);
+ }
+
+ if ( GetProfileInt("Setup", "Soluce4", iValue) )
+ {
+ m_bSoluce4 = iValue;
+ }
+
+ if ( GetProfileInt("Setup", "Movies", iValue) )
+ {
+ m_bMovies = iValue;
+ }
+
+ if ( GetProfileInt("Setup", "NiceReset", iValue) )
+ {
+ m_bNiceReset = iValue;
+ }
+
+ if ( GetProfileInt("Setup", "HimselfDamage", iValue) )
+ {
+ m_bHimselfDamage = iValue;
+ }
+
+ if ( GetProfileInt("Setup", "CameraScroll", iValue) )
+ {
+ m_bCameraScroll = iValue;
+ m_camera->SetCameraScroll(m_bCameraScroll);
+ }
+
+ if ( GetProfileInt("Setup", "CameraInvertX", iValue) )
+ {
+ m_bCameraInvertX = iValue;
+ m_camera->SetCameraInvertX(m_bCameraInvertX);
+ }
+
+ if ( GetProfileInt("Setup", "CameraInvertY", iValue) )
+ {
+ m_bCameraInvertY = iValue;
+ m_camera->SetCameraInvertY(m_bCameraInvertY);
+ }
+
+ if ( GetProfileInt("Setup", "InterfaceEffect", iValue) )
+ {
+ m_bEffect = iValue;
+ }
+
+ if ( GetProfileInt("Setup", "GroundShadow", iValue) )
+ {
+ m_engine->SetShadow(iValue);
+ }
+
+ if ( GetProfileInt("Setup", "GroundSpot", iValue) )
+ {
+ m_engine->SetGroundSpot(iValue);
+ }
+
+ if ( GetProfileInt("Setup", "ObjectDirty", iValue) )
+ {
+ m_engine->SetDirty(iValue);
+ }
+
+ if ( GetProfileInt("Setup", "FogMode", iValue) )
+ {
+ m_engine->SetFog(iValue);
+ m_camera->SetOverBaseColor(RetColor(RetColor(0.0f)));
+ }
+
+ if ( GetProfileInt("Setup", "LensMode", iValue) )
+ {
+ m_engine->SetLensMode(iValue);
+ }
+
+ if ( GetProfileInt("Setup", "SkyMode", iValue) )
+ {
+ m_engine->SetSkyMode(iValue);
+ }
+
+ if ( GetProfileInt("Setup", "PlanetMode", iValue) )
+ {
+ m_engine->SetPlanetMode(iValue);
+ }
+
+ if ( GetProfileInt("Setup", "LightMode", iValue) )
+ {
+ m_engine->SetLightMode(iValue);
+ }
+
+ if ( GetProfileInt("Setup", "UseJoystick", iValue) )
+ {
+ m_engine->SetJoystick(iValue);
+ }
+
+ if ( GetProfileFloat("Setup", "ParticuleDensity", fValue) )
+ {
+ m_engine->SetParticuleDensity(fValue);
+ }
+
+ if ( GetProfileFloat("Setup", "ClippingDistance", fValue) )
+ {
+ m_engine->SetClippingDistance(fValue);
+ }
+
+ if ( GetProfileFloat("Setup", "ObjectDetail", fValue) )
+ {
+ m_engine->SetObjectDetail(fValue);
+ }
+
+ if ( GetProfileFloat("Setup", "GadgetQuantity", fValue) )
+ {
+ m_engine->SetGadgetQuantity(fValue);
+ }
+
+ if ( GetProfileInt("Setup", "TextureQuality", iValue) )
+ {
+ m_engine->SetTextureQuality(iValue);
+ }
+
+ if ( GetProfileInt("Setup", "AudioVolume", iValue) )
+ {
+ m_sound->SetAudioVolume(iValue);
+ }
+
+ if ( GetProfileInt("Setup", "MidiVolume", iValue) )
+ {
+ m_sound->SetMidiVolume(iValue);
+ }
+
+ if ( GetProfileInt("Setup", "EditIndentMode", iValue) )
+ {
+ m_engine->SetEditIndentMode(iValue);
+ }
+
+ if ( GetProfileInt("Setup", "EditIndentValue", iValue) )
+ {
+ m_engine->SetEditIndentValue(iValue);
+ }
+
+ if ( GetProfileString("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 _NET
+ if ( m_accessEnable )
+ {
+ if ( GetProfileInt("Setup", "AccessMission", iValue) )
+ {
+ m_accessMission = iValue;
+ }
+
+ if ( GetProfileInt("Setup", "AccessUser", iValue) )
+ {
+ m_accessUser = iValue;
+ }
+ }
+#endif
+
+ if ( GetProfileInt("Setup", "DeleteGamer", iValue) )
+ {
+ m_bDeleteGamer = iValue;
+ }
+}
+
+
+// Changes the general level of quality.
+
+void CMainDialog::ChangeSetupQuality(int quality)
+{
+ bool bEnable;
+ float value;
+ int iValue;
+
+ bEnable = (quality >= 0);
+ m_engine->SetShadow(bEnable);
+ m_engine->SetGroundSpot(bEnable);
+ m_engine->SetDirty(bEnable);
+ m_engine->SetFog(bEnable);
+ m_engine->SetLensMode(bEnable);
+ m_engine->SetSkyMode(bEnable);
+ m_engine->SetPlanetMode(bEnable);
+ m_engine->SetLightMode(bEnable);
+ m_camera->SetOverBaseColor(RetColor(RetColor(0.0f)));
+
+ if ( quality < 0 ) value = 0.0f;
+ if ( quality == 0 ) value = 1.0f;
+ if ( quality > 0 ) value = 2.0f;
+ m_engine->SetParticuleDensity(value);
+
+ if ( quality < 0 ) value = 0.5f;
+ if ( quality == 0 ) value = 1.0f;
+ if ( quality > 0 ) value = 2.0f;
+ m_engine->SetClippingDistance(value);
+
+ if ( quality < 0 ) value = 0.0f;
+ if ( quality == 0 ) value = 1.0f;
+ if ( quality > 0 ) value = 2.0f;
+ m_engine->SetObjectDetail(value);
+
+ if ( quality < 0 ) value = 0.5f;
+ if ( quality == 0 ) value = 1.0f;
+ if ( quality > 0 ) value = 1.0f;
+ m_engine->SetGadgetQuantity(value);
+
+ if ( quality < 0 ) iValue = 0;
+ if ( quality == 0 ) iValue = 1;
+ if ( quality > 0 ) iValue = 2;
+ m_engine->SetTextureQuality(iValue);
+
+ m_engine->FirstExecuteAdapt(false);
+}
+
+
+// Redefinable keys:
+
+static int key_table[KEY_TOTAL] =
+{
+#if _SCHOOL & _TEEN
+ KEYRANK_LEFT,
+ KEYRANK_RIGHT,
+ KEYRANK_UP,
+ KEYRANK_DOWN,
+ KEYRANK_CAMERA,
+ KEYRANK_NEAR,
+ KEYRANK_AWAY,
+ KEYRANK_HELP,
+ KEYRANK_PROG,
+ KEYRANK_SPEED10,
+ KEYRANK_SPEED15,
+ KEYRANK_SPEED20,
+ KEYRANK_QUIT,
+#else
+ KEYRANK_LEFT,
+ KEYRANK_RIGHT,
+ KEYRANK_UP,
+ KEYRANK_DOWN,
+ KEYRANK_GUP,
+ KEYRANK_GDOWN,
+ KEYRANK_ACTION,
+ KEYRANK_CAMERA,
+ KEYRANK_VISIT,
+ KEYRANK_NEXT,
+ KEYRANK_HUMAN,
+ KEYRANK_DESEL,
+ KEYRANK_NEAR,
+ KEYRANK_AWAY,
+ KEYRANK_HELP,
+ KEYRANK_PROG,
+ KEYRANK_CBOT,
+ KEYRANK_SPEED10,
+ KEYRANK_SPEED15,
+ KEYRANK_SPEED20,
+ KEYRANK_QUIT,
+#endif
+};
+
+static EventMsg key_event[KEY_TOTAL] =
+{
+#if _SCHOOL & _TEEN
+ EVENT_INTERFACE_KLEFT,
+ EVENT_INTERFACE_KRIGHT,
+ EVENT_INTERFACE_KUP,
+ EVENT_INTERFACE_KDOWN,
+ EVENT_INTERFACE_KCAMERA,
+ EVENT_INTERFACE_KNEAR,
+ EVENT_INTERFACE_KAWAY,
+ EVENT_INTERFACE_KHELP,
+ EVENT_INTERFACE_KPROG,
+ EVENT_INTERFACE_KSPEED10,
+ EVENT_INTERFACE_KSPEED15,
+ EVENT_INTERFACE_KSPEED20,
+ EVENT_INTERFACE_KQUIT,
+#else
+ EVENT_INTERFACE_KLEFT,
+ EVENT_INTERFACE_KRIGHT,
+ EVENT_INTERFACE_KUP,
+ EVENT_INTERFACE_KDOWN,
+ EVENT_INTERFACE_KGUP,
+ EVENT_INTERFACE_KGDOWN,
+ EVENT_INTERFACE_KACTION,
+ EVENT_INTERFACE_KCAMERA,
+ EVENT_INTERFACE_KVISIT,
+ EVENT_INTERFACE_KNEXT,
+ EVENT_INTERFACE_KHUMAN,
+ EVENT_INTERFACE_KDESEL,
+ EVENT_INTERFACE_KNEAR,
+ EVENT_INTERFACE_KAWAY,
+ EVENT_INTERFACE_KHELP,
+ EVENT_INTERFACE_KPROG,
+ EVENT_INTERFACE_KCBOT,
+ EVENT_INTERFACE_KSPEED10,
+ EVENT_INTERFACE_KSPEED15,
+ EVENT_INTERFACE_KSPEED20,
+ EVENT_INTERFACE_KQUIT,
+#endif
+};
+
+// Updates the list of keys.
+
+void CMainDialog::UpdateKey()
+{
+ CWindow* pw;
+ CScroll* ps;
+ CKey* pk;
+ Math::Point pos, dim;
+ int first, i;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+
+ ps = (CScroll*)pw->SearchControl(EVENT_INTERFACE_KSCROLL);
+ if ( ps == 0 ) return;
+
+ first = (int)(ps->RetVisibleValue()*(KEY_TOTAL-KEY_VISIBLE));
+
+ for ( i=0 ; i<KEY_TOTAL ; i++ )
+ {
+ pw->DeleteControl(key_event[i]);
+ }
+
+ dim.x = 400.0f/640.0f;
+ dim.y = 20.0f/480.0f;
+ pos.x = 110.0f/640.0f;
+ pos.y = 168.0f/480.0f + dim.y*(KEY_VISIBLE-1);
+ for ( i=0 ; i<KEY_VISIBLE ; i++ )
+ {
+ pw->CreateKey(pos, dim, -1, key_event[first+i]);
+ pk = (CKey*)pw->SearchControl(key_event[first+i]);
+ if ( pk == 0 ) break;
+ pk->SetKey(0, m_engine->RetKey(key_table[first+i], 0));
+ pk->SetKey(1, m_engine->RetKey(key_table[first+i], 1));
+ pos.y -= dim.y;
+ }
+}
+
+// Change a key.
+
+void CMainDialog::ChangeKey(EventMsg event)
+{
+ CWindow* pw;
+ CScroll* ps;
+ CKey* pk;
+ int i;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw == 0 ) return;
+
+ ps = (CScroll*)pw->SearchControl(EVENT_INTERFACE_KSCROLL);
+ if ( ps == 0 ) return;
+
+ for ( i=0 ; i<KEY_TOTAL ; i++ )
+ {
+ if ( key_event[i] == event )
+ {
+ pk = (CKey*)pw->SearchControl(key_event[i]);
+ if ( pk == 0 ) break;
+ m_engine->SetKey(key_table[i], 0, pk->RetKey(0));
+ m_engine->SetKey(key_table[i], 1, pk->RetKey(1));
+ }
+ }
+}
+
+
+
+// Do you want to quit the current mission?
+
+void CMainDialog::StartAbort()
+{
+ CWindow* pw;
+ CButton* pb;
+ Math::Point pos, dim;
+ char name[100];
+
+ StartDialog(Math::Point(0.3f, 0.8f), true, false, false);
+ m_bDialogDelete = false;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
+ if ( pw == 0 ) return;
+
+ pos.x = 0.35f;
+ pos.y = 0.60f;
+ dim.x = 0.30f;
+ dim.y = 0.30f;
+ pw->CreateGroup(pos, dim, 5, EVENT_INTERFACE_GLINTl); // orange corner
+ pos.x = 0.35f;
+ pos.y = 0.10f;
+ dim.x = 0.30f;
+ dim.y = 0.30f;
+ pw->CreateGroup(pos, dim, 4, EVENT_INTERFACE_GLINTr); // blue corner
+
+ pos.x = 0.40f;
+ dim.x = 0.20f;
+#if _POLISH
+ pos.x -= 7.0f/640.0f;
+ dim.x += 14.0f/640.0f;
+#endif
+ dim.y = 32.0f/480.0f;
+
+ pos.y = 0.74f;
+ pb = pw->CreateButton(pos, dim, -1, EVENT_DIALOG_CANCEL);
+ pb->SetState(STATE_SHADOW);
+ GetResource(RES_TEXT, RT_DIALOG_NO, name);
+ pb->SetName(name);
+
+ if ( m_index == 2 || // missions ?
+ m_index == 3 || // free games?
+ m_index == 4 ) // user ?
+ {
+ pos.y = 0.62f;
+ pb = pw->CreateButton(pos, dim, -1, EVENT_INTERFACE_WRITE);
+ pb->SetState(STATE_SHADOW);
+ if ( m_main->IsBusy() ) // current task?
+ {
+ pb->ClearState(STATE_ENABLE);
+ }
+
+ pos.y = 0.53f;
+ pb = pw->CreateButton(pos, dim, -1, EVENT_INTERFACE_READ);
+ pb->SetState(STATE_SHADOW);
+ if ( !IsIOReadScene() ) // no file to read?
+ {
+ pb->ClearState(STATE_ENABLE);
+ }
+ pb->SetState(STATE_WARNING);
+ }
+
+ if ( m_engine->RetSetupMode() )
+ {
+ pos.y = 0.39f;
+ pb = pw->CreateButton(pos, dim, -1, EVENT_INTERFACE_SETUP);
+ pb->SetState(STATE_SHADOW);
+ }
+
+ pos.y = 0.25f;
+ pb = pw->CreateButton(pos, dim, -1, EVENT_INTERFACE_AGAIN);
+ pb->SetState(STATE_SHADOW);
+ pb->SetState(STATE_WARNING);
+
+ pos.y = 0.16f;
+ pb = pw->CreateButton(pos, dim, -1, EVENT_DIALOG_OK);
+ pb->SetState(STATE_SHADOW);
+ pb->SetState(STATE_WARNING);
+ GetResource(RES_TEXT, RT_DIALOG_YES, name);
+ pb->SetName(name);
+}
+
+// Do you want to destroy the building?
+
+void CMainDialog::StartDeleteObject()
+{
+ CWindow* pw;
+ CButton* pb;
+ Math::Point pos, dim;
+ char name[100];
+
+ StartDialog(Math::Point(0.7f, 0.3f), false, true, true);
+ m_bDialogDelete = true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
+ if ( pw == 0 ) return;
+
+ pos.x = 0.00f;
+ pos.y = 0.50f;
+ dim.x = 1.00f;
+ dim.y = 0.05f;
+ GetResource(RES_TEXT, RT_DIALOG_DELOBJ, name);
+ pw->CreateLabel(pos, dim, -1, EVENT_DIALOG_LABEL, name);
+
+ pb = (CButton*)pw->SearchControl(EVENT_DIALOG_OK);
+ if ( pb == 0 ) return;
+ GetResource(RES_TEXT, RT_DIALOG_YESDEL, name);
+ pb->SetName(name);
+ pb->SetState(STATE_WARNING);
+
+ pb = (CButton*)pw->SearchControl(EVENT_DIALOG_CANCEL);
+ if ( pb == 0 ) return;
+ GetResource(RES_TEXT, RT_DIALOG_NODEL, name);
+ pb->SetName(name);
+}
+
+// Do you want to delete the player?
+
+void CMainDialog::StartDeleteGame(char *gamer)
+{
+ CWindow* pw;
+ CButton* pb;
+ Math::Point pos, dim;
+ char name[100];
+ char text[100];
+
+ StartDialog(Math::Point(0.7f, 0.3f), false, true, true);
+ m_bDialogDelete = true;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
+ if ( pw == 0 ) return;
+
+ pos.x = 0.00f;
+ pos.y = 0.50f;
+ dim.x = 1.00f;
+ dim.y = 0.05f;
+ GetResource(RES_TEXT, RT_DIALOG_DELGAME, name);
+ sprintf(text, name, gamer);
+ pw->CreateLabel(pos, dim, -1, EVENT_DIALOG_LABEL, text);
+
+ pb = (CButton*)pw->SearchControl(EVENT_DIALOG_OK);
+ if ( pb == 0 ) return;
+ GetResource(RES_TEXT, RT_DIALOG_YESDEL, name);
+ pb->SetName(name);
+ pb->SetState(STATE_WARNING);
+
+ pb = (CButton*)pw->SearchControl(EVENT_DIALOG_CANCEL);
+ if ( pb == 0 ) return;
+ GetResource(RES_TEXT, RT_DIALOG_NODEL, name);
+ pb->SetName(name);
+}
+
+// Would you quit the game?
+
+void CMainDialog::StartQuit()
+{
+ CWindow* pw;
+ CButton* pb;
+ Math::Point pos, dim;
+ char name[100];
+
+ StartDialog(Math::Point(0.6f, 0.3f), false, true, true);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
+ if ( pw == 0 ) return;
+
+ pos.x = 0.00f;
+ pos.y = 0.50f;
+ dim.x = 1.00f;
+ dim.y = 0.05f;
+ GetResource(RES_TEXT, RT_DIALOG_QUIT, name);
+ pw->CreateLabel(pos, dim, -1, EVENT_DIALOG_LABEL, name);
+
+ pb = (CButton*)pw->SearchControl(EVENT_DIALOG_OK);
+ if ( pb == 0 ) return;
+ GetResource(RES_TEXT, RT_DIALOG_YESQUIT, name);
+ pb->SetName(name);
+ pb->SetState(STATE_WARNING);
+
+ pb = (CButton*)pw->SearchControl(EVENT_DIALOG_CANCEL);
+ if ( pb == 0 ) return;
+ GetResource(RES_TEXT, RT_DIALOG_NOQUIT, name);
+ pb->SetName(name);
+}
+
+// Beginning of displaying a dialog.
+
+void CMainDialog::StartDialog(Math::Point dim, bool bFire, bool bOK, bool bCancel)
+{
+ CWindow* pw;
+ CButton* pb;
+ Math::Point pos, ddim;
+ char name[100];
+
+ StartSuspend();
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW6);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW7);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW8);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
+ if ( pb != 0 )
+ {
+ pb->ClearState(STATE_VISIBLE);
+ }
+
+ m_bDialogFire = bFire;
+
+ pos.x = (1.0f-dim.x)/2.0f;
+ pos.y = (1.0f-dim.y)/2.0f;
+ pw = m_interface->CreateWindows(pos, dim, bFire?12:8, EVENT_WINDOW9);
+ pw->SetState(STATE_SHADOW);
+ GetResource(RES_TEXT, RT_TITLE_BASE, name);
+ pw->SetName(name);
+
+ m_dialogPos = pos;
+ m_dialogDim = dim;
+ m_dialogTime = 0.0f;
+ m_dialogParti = 999.0f;
+
+ if ( bOK )
+ {
+ pos.x = 0.50f-0.15f-0.02f;
+ pos.y = 0.50f-dim.y/2.0f+0.03f;
+ ddim.x = 0.15f;
+ ddim.y = 0.06f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_DIALOG_OK);
+ pb->SetState(STATE_SHADOW);
+ GetResource(RES_EVENT, EVENT_DIALOG_OK, name);
+ pb->SetName(name);
+ }
+
+ if ( bCancel )
+ {
+ pos.x = 0.50f+0.02f;
+ pos.y = 0.50f-dim.y/2.0f+0.03f;
+ ddim.x = 0.15f;
+ ddim.y = 0.06f;
+ pb = pw->CreateButton(pos, ddim, -1, EVENT_DIALOG_CANCEL);
+ pb->SetState(STATE_SHADOW);
+ GetResource(RES_EVENT, EVENT_DIALOG_CANCEL, name);
+ pb->SetName(name);
+ }
+
+ m_sound->Play(SOUND_TZOING);
+ m_bDialog = true;
+}
+
+// Animation of a dialog.
+
+void CMainDialog::FrameDialog(float rTime)
+{
+ CWindow* pw;
+ Math::Vector pos, speed;
+ Math::Point dim, dpos, ddim;
+ float zoom;
+ int i;
+
+ dpos = m_dialogPos;
+ ddim = m_dialogDim;
+
+ m_dialogTime += rTime;
+ if ( m_dialogTime < 1.0f )
+ {
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
+ if ( pw != 0 )
+ {
+ if ( m_dialogTime < 0.50f )
+ {
+ zoom = Math::Bounce(m_dialogTime/0.50f);
+ }
+ else
+ {
+ zoom = 1.0f;
+ }
+
+ dpos.x += ddim.x/2.0f;
+ dpos.y += ddim.y/2.0f;
+
+ ddim.x *= zoom;
+//? ddim.y *= zoom;
+
+ dpos.x -= ddim.x/2.0f;
+ dpos.y -= ddim.y/2.0f;
+
+ pw->SetPos(dpos);
+ pw->SetDim(ddim);
+ }
+ }
+
+ if ( !m_bGlint ) return;
+
+ m_dialogParti += rTime;
+ if ( m_dialogParti < m_engine->ParticuleAdapt(0.05f) ) return;
+ m_dialogParti = 0.0f;
+
+ if ( !m_bDialogFire ) return;
+
+ dpos = m_dialogPos;
+ ddim = m_dialogDim;
+
+ pos.z = 0.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+
+ for ( i=0 ; i<2 ; i++ )
+ {
+ // Bottom.
+ pos.x = dpos.x + ddim.x*Math::Rand();
+ pos.y = dpos.y;
+ pos.x += (Math::Rand()-0.5f)*(6.0f/640.0f);
+ pos.y += Math::Rand()*(16.0f/480.0f)-(10.0f/480.0f);
+ dim.x = 0.01f+Math::Rand()*0.01f;
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim,
+ (ParticuleType)(PARTILENS1+rand()%3),
+ 1.0f, 0.0f, 0.0f, SH_INTERFACE);
+
+ // Top.
+ pos.x = dpos.x + ddim.x*Math::Rand();
+ pos.y = dpos.y + ddim.y;
+ pos.x += (Math::Rand()-0.5f)*(6.0f/640.0f);
+ pos.y -= Math::Rand()*(16.0f/480.0f)-(10.0f/480.0f);
+ dim.x = 0.01f+Math::Rand()*0.01f;
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim,
+ (ParticuleType)(PARTILENS1+rand()%3),
+ 1.0f, 0.0f, 0.0f, SH_INTERFACE);
+
+ // Left.
+ pos.y = dpos.y + ddim.y*Math::Rand();
+ pos.x = dpos.x;
+ pos.x += Math::Rand()*(16.0f/640.0f)-(10.0f/640.0f);
+ pos.y += (Math::Rand()-0.5f)*(6.0f/480.0f);
+ dim.x = 0.01f+Math::Rand()*0.01f;
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim,
+ (ParticuleType)(PARTILENS1+rand()%3),
+ 1.0f, 0.0f, 0.0f, SH_INTERFACE);
+
+ // Right.
+ pos.y = dpos.y + ddim.y*Math::Rand();
+ pos.x = dpos.x + ddim.x;
+ pos.x -= Math::Rand()*(16.0f/640.0f)-(10.0f/640.0f);
+ pos.y += (Math::Rand()-0.5f)*(6.0f/480.0f);
+ dim.x = 0.01f+Math::Rand()*0.01f;
+ dim.y = dim.x/0.75f;
+ m_particule->CreateParticule(pos, speed, dim,
+ (ParticuleType)(PARTILENS1+rand()%3),
+ 1.0f, 0.0f, 0.0f, SH_INTERFACE);
+ }
+}
+
+// End of the display of a dialogue.
+
+void CMainDialog::StopDialog()
+{
+ CWindow* pw;
+ CButton* pb;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW2);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW6);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW7);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW8);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ pb = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
+ if ( pb != 0 )
+ {
+ pb->SetState(STATE_VISIBLE);
+ }
+
+ StopSuspend();
+ m_interface->DeleteControl(EVENT_WINDOW9);
+ m_bDialog = false;
+}
+
+// Suspends the simulation for a dialog phase.
+
+void CMainDialog::StartSuspend()
+{
+ m_sound->MuteAll(true);
+ m_main->ClearInterface();
+ m_bInitPause = m_engine->RetPause();
+ m_engine->SetPause(true);
+ m_engine->SetOverFront(false); // over flat behind
+ m_main->CreateShortcuts();
+ m_main->StartSuspend();
+ m_initCamera = m_camera->RetType();
+ m_camera->SetType(CAMERA_DIALOG);
+}
+
+// Resume the simulation after a period of dialog.
+
+void CMainDialog::StopSuspend()
+{
+ m_sound->MuteAll(false);
+ m_main->ClearInterface();
+ if ( !m_bInitPause ) m_engine->SetPause(false);
+ m_engine->SetOverFront(true); // over flat front
+ m_main->CreateShortcuts();
+ m_main->StopSuspend();
+ m_camera->SetType(m_initCamera);
+}
+
+
+// Whether to use tooltips.
+
+bool CMainDialog::RetTooltip()
+{
+ return m_bTooltip;
+}
+
+// Specifies whether a dialog is displayed.
+
+bool CMainDialog::IsDialog()
+{
+ return m_bDialog;
+}
+
+
+
+
+// Specifies the name of the scene to read.
+
+void CMainDialog::SetSceneRead(char* name)
+{
+ strcpy(m_sceneRead, name);
+}
+
+// Returns the name of the scene to read.
+
+char* CMainDialog::RetSceneRead()
+{
+ return m_sceneRead;
+}
+
+// Specifies the name of the scene to read.
+
+void CMainDialog::SetStackRead(char* name)
+{
+ strcpy(m_stackRead, name);
+}
+
+// Returns the name of the scene to read.
+
+char* CMainDialog::RetStackRead()
+{
+ return m_stackRead;
+}
+
+// Specifies the name of the chosen to play scene.
+
+void CMainDialog::SetSceneName(char* name)
+{
+ strcpy(m_sceneName, name);
+}
+
+// Returns the name of the chosen to play scene.
+
+char* CMainDialog::RetSceneName()
+{
+ return m_sceneName;
+}
+
+// Specifies the rank of the chosen to play scene.
+
+void CMainDialog::SetSceneRank(int rank)
+{
+ m_sceneRank = rank;
+}
+
+// Returns the rank of the chosen to play scene.
+
+int CMainDialog::RetSceneRank()
+{
+ return m_sceneRank;
+}
+
+// Returns folder name of the scene that user selected to play.
+
+char* CMainDialog::RetSceneDir()
+{
+ int i;
+
+ i = (m_sceneRank/100)-1;
+
+ if ( i < 0 || i >= m_userTotal ) return 0;
+ return m_userList[i];
+}
+
+// Whether to show the solution.
+
+bool CMainDialog::RetSceneSoluce()
+{
+ return m_bSceneSoluce;
+}
+
+// Returns the name of the folder to save.
+
+char* CMainDialog::RetSavegameDir()
+{
+ return m_savegameDir;
+}
+
+// Returns the name of public folder.
+
+char* CMainDialog::RetPublicDir()
+{
+ return m_publicDir;
+}
+
+
+// Indicates if there are reflections on the buttons.
+
+bool CMainDialog::RetGlint()
+{
+ return m_bGlint;
+}
+
+// Whether to show 4:solutions.
+
+bool CMainDialog::RetSoluce4()
+{
+ return m_bSoluce4;
+}
+
+// Whether to show the cinematics.
+
+bool CMainDialog::RetMovies()
+{
+ return m_bMovies;
+}
+
+// IWhether to make an animation in CTaskReset.
+
+bool CMainDialog::RetNiceReset()
+{
+ return m_bNiceReset;
+}
+
+// Indicates whether the fire causes damage to its own units.
+
+bool CMainDialog::RetHimselfDamage()
+{
+ return m_bHimselfDamage;
+}
+
+
+
+// Saves the personalized player.
+
+void CMainDialog::WriteGamerPerso(char *gamer)
+{
+ FILE* file;
+ char filename[100];
+ char line[100];
+
+ sprintf(filename, "%s\\%s\\face.gam", m_savegameDir, gamer);
+ file = fopen(filename, "w");
+ if ( file == NULL ) return;
+
+ sprintf(line, "Head face=%d glasses=%d hair=%.2f;%.2f;%.2f;%.2f\n",
+ m_perso.face, m_perso.glasses,
+ m_perso.colorHair.r, m_perso.colorHair.g, m_perso.colorHair.b, m_perso.colorHair.a);
+ fputs(line, file);
+
+ sprintf(line, "Body combi=%.2f;%.2f;%.2f;%.2f band=%.2f;%.2f;%.2f;%.2f\n",
+ m_perso.colorCombi.r, m_perso.colorCombi.g, m_perso.colorCombi.b, m_perso.colorCombi.a,
+ m_perso.colorBand.r, m_perso.colorBand.g, m_perso.colorBand.b, m_perso.colorBand.a);
+ fputs(line, file);
+
+ fclose(file);
+}
+
+// Reads the personalized player.
+
+void CMainDialog::ReadGamerPerso(char *gamer)
+{
+ FILE* file;
+ char filename[100];
+ char line[100];
+ D3DCOLORVALUE color;
+
+ m_perso.face = 0;
+ DefPerso();
+
+ sprintf(filename, "%s\\%s\\face.gam", m_savegameDir, gamer);
+ file = fopen(filename, "r");
+ if ( file == NULL ) return;
+
+ while ( fgets(line, 100, file) != NULL )
+ {
+ if ( Cmd(line, "Head") )
+ {
+ m_perso.face = OpInt(line, "face", 0);
+ m_perso.glasses = OpInt(line, "glasses", 0);
+
+ color.r = 0.0f;
+ color.g = 0.0f;
+ color.b = 0.0f;
+ color.a = 0.0f;
+ m_perso.colorHair = OpColorValue(line, "hair", color);
+ }
+
+ if ( Cmd(line, "Body") )
+ {
+ color.r = 0.0f;
+ color.g = 0.0f;
+ color.b = 0.0f;
+ color.a = 0.0f;
+ m_perso.colorCombi = OpColorValue(line, "combi", color);
+
+ color.r = 0.0f;
+ color.g = 0.0f;
+ color.b = 0.0f;
+ color.a = 0.0f;
+ m_perso.colorBand = OpColorValue(line, "band", color);
+ }
+ }
+
+ fclose(file);
+}
+
+// Specifies the face of the player.
+
+void CMainDialog::SetGamerFace(char *gamer, int face)
+{
+ m_perso.face = face;
+ WriteGamerPerso(gamer);
+}
+
+// Gives the face of the player.
+
+int CMainDialog::RetGamerFace(char *gamer)
+{
+ ReadGamerPerso(gamer);
+ return m_perso.face;
+}
+
+// Gives the face of the player.
+
+int CMainDialog::RetGamerFace()
+{
+ return m_perso.face;
+}
+
+int CMainDialog::RetGamerGlasses()
+{
+ return m_perso.glasses;
+}
+
+bool CMainDialog::RetGamerOnlyHead()
+{
+ return (m_phase == PHASE_PERSO && m_persoTab == 0);
+}
+
+float CMainDialog::RetPersoAngle()
+{
+ return m_persoAngle;
+}
+
+D3DCOLORVALUE CMainDialog::RetGamerColorHair()
+{
+ return m_perso.colorHair;
+}
+
+D3DCOLORVALUE CMainDialog::RetGamerColorCombi()
+{
+ return m_perso.colorCombi;
+}
+
+D3DCOLORVALUE CMainDialog::RetGamerColorBand()
+{
+ return m_perso.colorBand;
+}
+
+
+// Reads the file of the player.
+
+bool CMainDialog::ReadGamerInfo()
+{
+ FILE* file;
+ char line[100];
+ int chap, i, numTry, passed;
+
+ for ( i=0 ; i<MAXSCENE ; i++ )
+ {
+ m_sceneInfo[i].numTry = 0;
+ m_sceneInfo[i].bPassed = false;
+ }
+
+ sprintf(line, "%s\\%s\\%s.gam", m_savegameDir, m_main->RetGamerName(), m_sceneName);
+ file = fopen(line, "r");
+ if ( file == NULL ) return false;
+
+ if ( fgets(line, 100, file) != NULL )
+ {
+ sscanf(line, "CurrentChapter=%d CurrentSel=%d\n", &chap, &i);
+ m_chap[m_index] = chap-1;
+ m_sel[m_index] = i-1;
+ }
+
+ while ( fgets(line, 100, file) != NULL )
+ {
+ sscanf(line, "Chapter %d: Scene %d: numTry=%d passed=%d\n",
+ &chap, &i, &numTry, &passed);
+
+ i += chap*100;
+ if ( i >= 0 && i < MAXSCENE )
+ {
+ m_sceneInfo[i].numTry = numTry;
+ m_sceneInfo[i].bPassed = passed;
+ }
+ }
+
+ fclose(file);
+ return true;
+}
+
+// Writes the file of the player.
+
+bool CMainDialog::WriteGamerInfo()
+{
+ FILE* file;
+ char line[100];
+ int i;
+
+ sprintf(line, "%s\\%s\\%s.gam", m_savegameDir, m_main->RetGamerName(), m_sceneName);
+ file = fopen(line, "w");
+ if ( file == NULL ) return false;
+
+ sprintf(line, "CurrentChapter=%d CurrentSel=%d\n",
+ m_chap[m_index]+1, m_sel[m_index]+1);
+ fputs(line, file);
+
+ for ( i=0 ; i<MAXSCENE ; i++ )
+ {
+ if ( m_sceneInfo[i].numTry == 0 ) continue;
+
+ sprintf(line, "Chapter %d: Scene %d: numTry=%d passed=%d\n",
+ i/100, i%100, m_sceneInfo[i].numTry, m_sceneInfo[i].bPassed);
+ fputs(line, file);
+ }
+
+ fclose(file);
+ return true;
+}
+
+void CMainDialog::SetGamerInfoTry(int rank, int numTry)
+{
+ if ( rank < 0 || rank >= MAXSCENE ) return;
+ if ( numTry > 100 ) numTry = 100;
+ m_sceneInfo[rank].numTry = numTry;
+}
+
+int CMainDialog::RetGamerInfoTry(int rank)
+{
+ if ( rank < 0 || rank >= MAXSCENE ) return 0;
+ return m_sceneInfo[rank].numTry;
+}
+
+void CMainDialog::SetGamerInfoPassed(int rank, bool bPassed)
+{
+ int chap, i;
+ bool bAll;
+
+ if ( rank < 0 || rank >= MAXSCENE ) return;
+ m_sceneInfo[rank].bPassed = bPassed;
+
+ if ( bPassed )
+ {
+ bAll = true;
+ chap = rank/100;
+ for ( i=0 ; i<m_maxList ; i++ )
+ {
+ bAll &= m_sceneInfo[chap*100+i+1].bPassed;
+ }
+ m_sceneInfo[chap*100].numTry ++;
+ m_sceneInfo[chap*100].bPassed = bAll;
+ }
+}
+
+bool CMainDialog::RetGamerInfoPassed(int rank)
+{
+ if ( rank < 0 || rank >= MAXSCENE ) return false;
+ return m_sceneInfo[rank].bPassed;
+}
+
+
+// Passes to the next mission, and possibly in the next chapter.
+
+bool CMainDialog::NextMission()
+{
+ m_sel[m_index] ++; // next mission
+
+ if ( m_sel[m_index] >= m_maxList ) // last mission of the chapter?
+ {
+ m_chap[m_index] ++; // next chapter
+ m_sel[m_index] = 0; // first mission
+ }
+
+ return true;
+}
+
+
diff --git a/src/ui/maindialog.h b/src/ui/maindialog.h
index cd017f5..bcda4aa 100644
--- a/src/ui/maindialog.h
+++ b/src/ui/maindialog.h
@@ -1,253 +1,253 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// maindialog.h
-
-#pragma once
-
-
-#include "common/struct.h"
-#include "old/camera.h"
-#include "object/robotmain.h"
-
-
-class CInstanceManager;
-class CEvent;
-class CD3DEngine;
-class CInterface;
-class CWindow;
-class CControl;
-class CParticule;
-class CSound;
-
-
-const int USERLISTMAX = 100;
-const int MAXSCENE = 1000;
-
-struct SceneInfo
-{
- char numTry;
- char bPassed;
-};
-
-struct GamerPerso
-{
- int face; // face
- int glasses; // glasses
- D3DCOLORVALUE colorHair; // hair color
- D3DCOLORVALUE colorCombi; // spacesuit volor
- D3DCOLORVALUE colorBand; // strips color
-};
-
-
-
-class CMainDialog
-{
-public:
- CMainDialog(CInstanceManager* iMan);
- ~CMainDialog();
-
- bool EventProcess(const Event &event);
- void ChangePhase(Phase phase);
-
- void SetSceneRead(char* name);
- void SetStackRead(char* name);
- void SetSceneName(char* name);
- void SetSceneRank(int rank);
- char* RetSceneRead();
- char* RetStackRead();
- char* RetSceneName();
- int RetSceneRank();
- char* RetSceneDir();
- bool RetSceneSoluce();
- char* RetSavegameDir();
- char* RetPublicDir();
-
- bool RetTooltip();
- bool RetGlint();
- bool RetSoluce4();
- bool RetMovies();
- bool RetNiceReset();
- bool RetHimselfDamage();
-
- void SetUserDir(char *base, int rank);
- void BuildSceneName(char *filename, char *base, int rank);
- void BuildResumeName(char *filename, char *base, int rank);
- char* RetFilesDir();
-
- void StartAbort();
- void StartDeleteObject();
- void StartDeleteGame(char *gamer);
- void StartQuit();
- void StartDialog(Math::Point dim, bool bFire, bool bOK, bool bCancel);
- void FrameDialog(float rTime);
- void StopDialog();
- bool IsDialog();
-
- void StartSuspend();
- void StopSuspend();
-
- void SetupMemorize();
- void SetupRecall();
-
- bool ReadGamerInfo();
- bool WriteGamerInfo();
- void SetGamerInfoTry(int rank, int numTry);
- int RetGamerInfoTry(int rank);
- void SetGamerInfoPassed(int rank, bool bPassed);
- bool RetGamerInfoPassed(int rank);
- bool NextMission();
-
- void WriteGamerPerso(char *gamer);
- void ReadGamerPerso(char *gamer);
- void SetGamerFace(char *gamer, int face);
- int RetGamerFace(char *gamer);
- int RetGamerFace();
- int RetGamerGlasses();
- bool RetGamerOnlyHead();
- float RetPersoAngle();
- D3DCOLORVALUE RetGamerColorHair();
- D3DCOLORVALUE RetGamerColorCombi();
- D3DCOLORVALUE RetGamerColorBand();
-
- void AllMissionUpdate();
- void ShowSoluceUpdate();
-
-protected:
- void GlintMove();
- void FrameParticule(float rTime);
- void NiceParticule(Math::Point mouse, bool bPress);
- void ReadNameList();
- void UpdateNameList();
- void UpdateNameEdit();
- void UpdateNameControl();
- void UpdateNameFace();
- void NameSelect();
- void NameCreate();
- void NameDelete();
- void UpdatePerso();
- void CameraPerso();
- void FixPerso(int rank, int index);
- void ColorPerso();
- void DefPerso();
- bool IsIOReadScene();
- void IOReadName();
- void IOReadList();
- void IOUpdateList();
- void IODeleteScene();
- bool IOWriteScene();
- bool IOReadScene();
- int RetChapPassed();
- void UpdateSceneChap(int &chap);
- void UpdateSceneList(int chap, int &sel);
- void UpdateSceneResume(int rank);
- void UpdateDisplayDevice();
- void UpdateDisplayMode();
- void ChangeDisplay();
- void UpdateApply();
- void UpdateSetupButtons();
- void ChangeSetupButtons();
- void ChangeSetupQuality(int quality);
- void UpdateKey();
- void ChangeKey(EventMsg event);
-
-protected:
- CInstanceManager* m_iMan;
- CRobotMain* m_main;
- CEvent* m_event;
- CD3DEngine* m_engine;
- CInterface* m_interface;
- CParticule* m_particule;
- CCamera* m_camera;
- CSound* m_sound;
-
- Phase m_phase; // copy of CRobotMain
- Phase m_phaseSetup; // tab selected
- Phase m_phaseTerm; // phase trainer/scene/proto
- float m_phaseTime;
-
- GamerPerso m_perso; // perso: description
- GamerPerso m_persoCopy; // perso: copy for cancellation
- int m_persoTab; // perso: tab selected
- float m_persoAngle; // perso: angle of presentation
-
- char m_sceneDir[_MAX_FNAME]; // scene folder
- char m_savegameDir[_MAX_FNAME]; // savegame folder
- char m_publicDir[_MAX_FNAME]; // program folder
- char m_userDir[_MAX_FNAME]; // user folder
- char m_filesDir[_MAX_FNAME]; // case files
-
- int m_index; // 0..4
- int m_chap[10]; // selected chapter (0..8)
- int m_sel[10]; // chosen mission (0..98)
- int m_maxList;
- int m_accessChap;
- char m_sceneRead[100]; // name of the scene to read
- char m_stackRead[100]; // name of the scene to read
- char m_sceneName[20]; // name of the scene to play
- int m_sceneRank; // rank of the scene to play
- bool m_bSceneSoluce; // shows the solution
- bool m_bSimulSetup; // adjustment during the game
- bool m_accessEnable;
- bool m_accessMission;
- bool m_accessUser;
- bool m_bDeleteGamer;
-
- int m_userTotal;
- char m_userList[USERLISTMAX][100];
-
- int m_shotDelay; // number of frames before copy
- char m_shotName[100]; // generate a file name
-
- int m_setupSelDevice;
- int m_setupSelMode;
- bool m_setupFull;
-
- bool m_bTooltip; // tooltips to be displayed?
- bool m_bGlint; // reflections on buttons?
- bool m_bRain; // rain in the interface?
- bool m_bSoluce4; // solutions in program 4?
- bool m_bMovies; // cinematics?
- bool m_bNiceReset; // for CTaskReset
- bool m_bHimselfDamage; // for shots
- bool m_bCameraScroll; // for CCamera
- bool m_bCameraInvertX; // for CCamera
- bool m_bCameraInvertY; // for CCamera
- bool m_bEffect; // for CCamera
-
- Math::Point m_glintMouse;
- float m_glintTime;
-
- int m_loadingCounter;
-
- bool m_bDialog; // this dialogue?
- bool m_bDialogFire; // setting on fire?
- bool m_bDialogDelete;
- Math::Point m_dialogPos;
- Math::Point m_dialogDim;
- float m_dialogParti;
- float m_dialogTime;
- bool m_bInitPause;
- CameraType m_initCamera;
-
- int m_partiPhase[10];
- float m_partiTime[10];
- Math::Point m_partiPos[10];
-
- SceneInfo m_sceneInfo[MAXSCENE];
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// maindialog.h
+
+#pragma once
+
+
+#include "common/struct.h"
+#include "old/camera.h"
+#include "object/robotmain.h"
+
+
+class CInstanceManager;
+class CEvent;
+class CD3DEngine;
+class CInterface;
+class CWindow;
+class CControl;
+class CParticule;
+class CSound;
+
+
+const int USERLISTMAX = 100;
+const int MAXSCENE = 1000;
+
+struct SceneInfo
+{
+ char numTry;
+ char bPassed;
+};
+
+struct GamerPerso
+{
+ int face; // face
+ int glasses; // glasses
+ D3DCOLORVALUE colorHair; // hair color
+ D3DCOLORVALUE colorCombi; // spacesuit volor
+ D3DCOLORVALUE colorBand; // strips color
+};
+
+
+
+class CMainDialog
+{
+public:
+ CMainDialog(CInstanceManager* iMan);
+ ~CMainDialog();
+
+ bool EventProcess(const Event &event);
+ void ChangePhase(Phase phase);
+
+ void SetSceneRead(char* name);
+ void SetStackRead(char* name);
+ void SetSceneName(char* name);
+ void SetSceneRank(int rank);
+ char* RetSceneRead();
+ char* RetStackRead();
+ char* RetSceneName();
+ int RetSceneRank();
+ char* RetSceneDir();
+ bool RetSceneSoluce();
+ char* RetSavegameDir();
+ char* RetPublicDir();
+
+ bool RetTooltip();
+ bool RetGlint();
+ bool RetSoluce4();
+ bool RetMovies();
+ bool RetNiceReset();
+ bool RetHimselfDamage();
+
+ void SetUserDir(char *base, int rank);
+ void BuildSceneName(char *filename, char *base, int rank);
+ void BuildResumeName(char *filename, char *base, int rank);
+ char* RetFilesDir();
+
+ void StartAbort();
+ void StartDeleteObject();
+ void StartDeleteGame(char *gamer);
+ void StartQuit();
+ void StartDialog(Math::Point dim, bool bFire, bool bOK, bool bCancel);
+ void FrameDialog(float rTime);
+ void StopDialog();
+ bool IsDialog();
+
+ void StartSuspend();
+ void StopSuspend();
+
+ void SetupMemorize();
+ void SetupRecall();
+
+ bool ReadGamerInfo();
+ bool WriteGamerInfo();
+ void SetGamerInfoTry(int rank, int numTry);
+ int RetGamerInfoTry(int rank);
+ void SetGamerInfoPassed(int rank, bool bPassed);
+ bool RetGamerInfoPassed(int rank);
+ bool NextMission();
+
+ void WriteGamerPerso(char *gamer);
+ void ReadGamerPerso(char *gamer);
+ void SetGamerFace(char *gamer, int face);
+ int RetGamerFace(char *gamer);
+ int RetGamerFace();
+ int RetGamerGlasses();
+ bool RetGamerOnlyHead();
+ float RetPersoAngle();
+ D3DCOLORVALUE RetGamerColorHair();
+ D3DCOLORVALUE RetGamerColorCombi();
+ D3DCOLORVALUE RetGamerColorBand();
+
+ void AllMissionUpdate();
+ void ShowSoluceUpdate();
+
+protected:
+ void GlintMove();
+ void FrameParticule(float rTime);
+ void NiceParticule(Math::Point mouse, bool bPress);
+ void ReadNameList();
+ void UpdateNameList();
+ void UpdateNameEdit();
+ void UpdateNameControl();
+ void UpdateNameFace();
+ void NameSelect();
+ void NameCreate();
+ void NameDelete();
+ void UpdatePerso();
+ void CameraPerso();
+ void FixPerso(int rank, int index);
+ void ColorPerso();
+ void DefPerso();
+ bool IsIOReadScene();
+ void IOReadName();
+ void IOReadList();
+ void IOUpdateList();
+ void IODeleteScene();
+ bool IOWriteScene();
+ bool IOReadScene();
+ int RetChapPassed();
+ void UpdateSceneChap(int &chap);
+ void UpdateSceneList(int chap, int &sel);
+ void UpdateSceneResume(int rank);
+ void UpdateDisplayDevice();
+ void UpdateDisplayMode();
+ void ChangeDisplay();
+ void UpdateApply();
+ void UpdateSetupButtons();
+ void ChangeSetupButtons();
+ void ChangeSetupQuality(int quality);
+ void UpdateKey();
+ void ChangeKey(EventMsg event);
+
+protected:
+ CInstanceManager* m_iMan;
+ CRobotMain* m_main;
+ CEvent* m_event;
+ CD3DEngine* m_engine;
+ CInterface* m_interface;
+ CParticule* m_particule;
+ CCamera* m_camera;
+ CSound* m_sound;
+
+ Phase m_phase; // copy of CRobotMain
+ Phase m_phaseSetup; // tab selected
+ Phase m_phaseTerm; // phase trainer/scene/proto
+ float m_phaseTime;
+
+ GamerPerso m_perso; // perso: description
+ GamerPerso m_persoCopy; // perso: copy for cancellation
+ int m_persoTab; // perso: tab selected
+ float m_persoAngle; // perso: angle of presentation
+
+ char m_sceneDir[_MAX_FNAME]; // scene folder
+ char m_savegameDir[_MAX_FNAME]; // savegame folder
+ char m_publicDir[_MAX_FNAME]; // program folder
+ char m_userDir[_MAX_FNAME]; // user folder
+ char m_filesDir[_MAX_FNAME]; // case files
+
+ int m_index; // 0..4
+ int m_chap[10]; // selected chapter (0..8)
+ int m_sel[10]; // chosen mission (0..98)
+ int m_maxList;
+ int m_accessChap;
+ char m_sceneRead[100]; // name of the scene to read
+ char m_stackRead[100]; // name of the scene to read
+ char m_sceneName[20]; // name of the scene to play
+ int m_sceneRank; // rank of the scene to play
+ bool m_bSceneSoluce; // shows the solution
+ bool m_bSimulSetup; // adjustment during the game
+ bool m_accessEnable;
+ bool m_accessMission;
+ bool m_accessUser;
+ bool m_bDeleteGamer;
+
+ int m_userTotal;
+ char m_userList[USERLISTMAX][100];
+
+ int m_shotDelay; // number of frames before copy
+ char m_shotName[100]; // generate a file name
+
+ int m_setupSelDevice;
+ int m_setupSelMode;
+ bool m_setupFull;
+
+ bool m_bTooltip; // tooltips to be displayed?
+ bool m_bGlint; // reflections on buttons?
+ bool m_bRain; // rain in the interface?
+ bool m_bSoluce4; // solutions in program 4?
+ bool m_bMovies; // cinematics?
+ bool m_bNiceReset; // for CTaskReset
+ bool m_bHimselfDamage; // for shots
+ bool m_bCameraScroll; // for CCamera
+ bool m_bCameraInvertX; // for CCamera
+ bool m_bCameraInvertY; // for CCamera
+ bool m_bEffect; // for CCamera
+
+ Math::Point m_glintMouse;
+ float m_glintTime;
+
+ int m_loadingCounter;
+
+ bool m_bDialog; // this dialogue?
+ bool m_bDialogFire; // setting on fire?
+ bool m_bDialogDelete;
+ Math::Point m_dialogPos;
+ Math::Point m_dialogDim;
+ float m_dialogParti;
+ float m_dialogTime;
+ bool m_bInitPause;
+ CameraType m_initCamera;
+
+ int m_partiPhase[10];
+ float m_partiTime[10];
+ Math::Point m_partiPos[10];
+
+ SceneInfo m_sceneInfo[MAXSCENE];
+};
+
+
diff --git a/src/ui/mainmap.cpp b/src/ui/mainmap.cpp
index ad0ed58..76e3627 100644
--- a/src/ui/mainmap.cpp
+++ b/src/ui/mainmap.cpp
@@ -1,402 +1,402 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// mainmap.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/global.h"
-#include "common/event.h"
-#include "common/iman.h"
-#include "ui/interface.h"
-#include "ui/map.h"
-#include "ui/image.h"
-#include "ui/group.h"
-#include "ui/slider.h"
-#include "ui/scroll.h"
-#include "ui/window.h"
-#include "ui/mainmap.h"
-
-
-
-const float ZOOM_MIN = 1.0f;
-const float ZOOM_MAX = 16.0f;
-
-
-
-// Constructor of the application card.
-
-CMainMap::CMainMap(CInstanceManager* iMan)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_MAP, this);
-
- m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
- m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
-
- m_mapMode = 1;
- m_bFixImage = false;
-}
-
-// Destructor of the application card.
-
-CMainMap::~CMainMap()
-{
-}
-
-
-// Created the mini-map and the corresponding buttons.
-
-void CMainMap::CreateMap()
-{
- CWindow* pw;
- Math::Point pos, dim;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw == 0 )
- {
- pos.x = 0.0f;
- pos.y = 0.0f;
- dim.x = 0.0f;
- dim.y = 0.0f;
- pw = m_interface->CreateWindows(pos, dim, 10, EVENT_WINDOW1);
- }
-
- dim.x = 10.0f/640.0f;
- dim.y = 10.0f/480.0f;
- pos.x = 10.0f/640.0f;
- pos.y = 10.0f/480.0f;
- pw->CreateMap (pos, dim, 2, EVENT_OBJECT_MAP);
- pw->CreateSlider(pos, dim, 0, EVENT_OBJECT_MAPZOOM);
-
- DimMap();
-}
-
-// Indicates whether the mini-map should display a still image.
-
-void CMainMap::SetFixImage(char *filename)
-{
- CWindow* pw;
- CMap* pm;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw == 0 ) return;
-
- pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
- if ( pm == 0 ) return;
-
- pw->DeleteControl(EVENT_OBJECT_MAPZOOM);
- m_bFixImage = true;
-
- pm->SetFixImage(filename);
-}
-
-// Choosing colors of soil and water for the mini-map.
-
-void CMainMap::FloorColorMap(D3DCOLORVALUE floor, D3DCOLORVALUE water)
-{
- CWindow* pw;
- CMap* pm;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw == 0 ) return;
-
- pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
- if ( pm != 0 )
- {
- pm->SetFloorColor(floor);
- pm->SetWaterColor(water);
- }
-}
-
-// Shows or hides the minimap.
-
-void CMainMap::ShowMap(bool bShow)
-{
- CWindow* pw;
- CMap* pm;
- CSlider* ps;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw == 0 ) return;
-
- if ( bShow )
- {
- DimMap();
- }
- else
- {
- pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
- if ( pm != 0 )
- {
- pm->ClearState(STATE_VISIBLE);
- }
-
- ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_MAPZOOM);
- if ( ps != 0 )
- {
- ps->ClearState(STATE_VISIBLE);
- }
- }
-}
-
-// Dimensions of the mini-map.
-
-void CMainMap::DimMap()
-{
- CWindow* pw;
- CMap* pm;
- CSlider* ps;
- Math::Point pos, dim;
- float value;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw == 0 ) return;
- pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
- if ( pm == 0 ) return;
-
- pm->SetState(STATE_VISIBLE, (m_mapMode != 0));
-
- dim.x = 100.0f/640.0f;
- dim.y = 100.0f/480.0f;
- pos.x = 540.0f/640.0f;
- pos.y = 0.0f/480.0f;
- pm->SetPos(pos);
- pm->SetDim(dim);
-
- ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_MAPZOOM);
- if ( ps != 0 )
- {
- ps->SetState(STATE_VISIBLE, (m_mapMode != 0));
-
- dim.x = SCROLL_WIDTH;
- dim.y = 66.0f/480.0f;
- pos.x = 523.0f/640.0f;
- pos.y = 3.0f/480.0f;
- ps->SetPos(pos);
- ps->SetDim(dim);
-
- value = pm->RetZoom();
- value = (value-ZOOM_MIN)/(ZOOM_MAX-ZOOM_MIN);
- value = powf(value, 0.5f);
- ps->SetVisibleValue(value);
- ps->SetArrowStep(0.2f);
- }
-}
-
-// Returns the current zoom of the minimap.
-
-float CMainMap::RetZoomMap()
-{
- CWindow* pw;
- CMap* pm;
- CSlider* ps;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw == 0 ) return ZOOM_MIN;
-
- pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
- if ( pm == 0 ) return ZOOM_MIN;
-
- ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_MAPZOOM);
- if ( ps == 0 ) return ZOOM_MIN;
-
- return pm->RetZoom();
-}
-
-// Zoom the mini-map of any factor.
-
-void CMainMap::ZoomMap(float zoom)
-{
- CWindow* pw;
- CMap* pm;
- CSlider* ps;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw == 0 ) return;
- pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
- if ( pm == 0 ) return;
-
- ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_MAPZOOM);
- if ( ps == 0 ) return;
-
- if ( zoom < ZOOM_MIN ) zoom = ZOOM_MIN;
- if ( zoom > ZOOM_MAX ) zoom = ZOOM_MAX;
- pm->SetZoom(zoom);
-
- DimMap();
-}
-
-// The mini-map zoom depending on the slider.
-
-void CMainMap::ZoomMap()
-{
- CWindow* pw;
- CMap* pm;
- CSlider* ps;
- float zoom;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw == 0 ) return;
- pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
- if ( pm == 0 ) return;
-
- ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_MAPZOOM);
- if ( ps == 0 ) return;
-
- zoom = ps->RetVisibleValue();
- zoom = powf(zoom, 2.0f);
- zoom = ZOOM_MIN+zoom*(ZOOM_MAX-ZOOM_MIN);
- pm->SetZoom(zoom);
-
- DimMap();
-}
-
-// Enables or disables the card.
-
-void CMainMap::MapEnable(bool bEnable)
-{
- CWindow* pw;
- CMap* pm;
- CSlider* ps;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw == 0 ) return;
-
- pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
- if ( pm != 0 )
- {
- pm->SetEnable(bEnable);
- }
-
- ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_MAPZOOM);
- if ( ps != 0 )
- {
- ps->SetState(STATE_ENABLE, bEnable);
- }
-}
-
-// Specifies the type of icon for the selected object.
-
-void CMainMap::SetToy(bool bToy)
-{
- CWindow* pw;
- CMap* pm;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw == 0 ) return;
-
- pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
- if ( pm == 0 ) return;
-
- pm->SetToy(bToy);
-}
-
-// Specifies the parameters when using a still image.
-
-void CMainMap::SetFixParam(float zoom, float ox, float oy, float angle,
- int mode, bool bDebug)
-{
- CWindow* pw;
- CMap* pm;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw == 0 ) return;
-
- pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
- if ( pm == 0 ) return;
-
- pm->SetZoom(zoom);
- pm->SetOffset(ox, oy);
- pm->SetAngle(angle);
- pm->SetMode(mode);
- pm->SetDebug(bDebug);
-}
-
-// Updates the mini-map following to a change of terrain.
-
-void CMainMap::UpdateMap()
-{
- CWindow* pw;
- CMap* pm;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw == 0 ) return;
-
- pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
- if ( pm != 0 )
- {
- pm->UpdateTerrain();
- }
-}
-
-// Indicates if the mini-map is visible.
-
-bool CMainMap::RetShowMap()
-{
- return ( m_mapMode != 0 );
-}
-
-// Indicates whether the mini-map displays a still image.
-
-bool CMainMap::RetFixImage()
-{
- return m_bFixImage;
-}
-
-
-// The object is detected in the mini-map.
-
-CObject* CMainMap::DetectMap(Math::Point pos, bool &bInMap)
-{
- CWindow* pw;
- CMap* pm;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw == 0 ) return 0;
-
- bInMap = false;
- pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
- if ( pm == 0 ) return 0;
- return pm->DetectObject(pos, bInMap);
-}
-
-
-// Indicates the object with the mouse hovers over.
-
-void CMainMap::SetHilite(CObject* pObj)
-{
- CWindow* pw;
- CMap* pm;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw == 0 ) return;
-
- pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
- if ( pm != 0 )
- {
- pm->SetHilite(pObj);
- }
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// mainmap.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/global.h"
+#include "common/event.h"
+#include "common/iman.h"
+#include "ui/interface.h"
+#include "ui/map.h"
+#include "ui/image.h"
+#include "ui/group.h"
+#include "ui/slider.h"
+#include "ui/scroll.h"
+#include "ui/window.h"
+#include "ui/mainmap.h"
+
+
+
+const float ZOOM_MIN = 1.0f;
+const float ZOOM_MAX = 16.0f;
+
+
+
+// Constructor of the application card.
+
+CMainMap::CMainMap(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_MAP, this);
+
+ m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+ m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+
+ m_mapMode = 1;
+ m_bFixImage = false;
+}
+
+// Destructor of the application card.
+
+CMainMap::~CMainMap()
+{
+}
+
+
+// Created the mini-map and the corresponding buttons.
+
+void CMainMap::CreateMap()
+{
+ CWindow* pw;
+ Math::Point pos, dim;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw == 0 )
+ {
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ dim.x = 0.0f;
+ dim.y = 0.0f;
+ pw = m_interface->CreateWindows(pos, dim, 10, EVENT_WINDOW1);
+ }
+
+ dim.x = 10.0f/640.0f;
+ dim.y = 10.0f/480.0f;
+ pos.x = 10.0f/640.0f;
+ pos.y = 10.0f/480.0f;
+ pw->CreateMap (pos, dim, 2, EVENT_OBJECT_MAP);
+ pw->CreateSlider(pos, dim, 0, EVENT_OBJECT_MAPZOOM);
+
+ DimMap();
+}
+
+// Indicates whether the mini-map should display a still image.
+
+void CMainMap::SetFixImage(char *filename)
+{
+ CWindow* pw;
+ CMap* pm;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw == 0 ) return;
+
+ pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
+ if ( pm == 0 ) return;
+
+ pw->DeleteControl(EVENT_OBJECT_MAPZOOM);
+ m_bFixImage = true;
+
+ pm->SetFixImage(filename);
+}
+
+// Choosing colors of soil and water for the mini-map.
+
+void CMainMap::FloorColorMap(D3DCOLORVALUE floor, D3DCOLORVALUE water)
+{
+ CWindow* pw;
+ CMap* pm;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw == 0 ) return;
+
+ pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
+ if ( pm != 0 )
+ {
+ pm->SetFloorColor(floor);
+ pm->SetWaterColor(water);
+ }
+}
+
+// Shows or hides the minimap.
+
+void CMainMap::ShowMap(bool bShow)
+{
+ CWindow* pw;
+ CMap* pm;
+ CSlider* ps;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw == 0 ) return;
+
+ if ( bShow )
+ {
+ DimMap();
+ }
+ else
+ {
+ pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
+ if ( pm != 0 )
+ {
+ pm->ClearState(STATE_VISIBLE);
+ }
+
+ ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_MAPZOOM);
+ if ( ps != 0 )
+ {
+ ps->ClearState(STATE_VISIBLE);
+ }
+ }
+}
+
+// Dimensions of the mini-map.
+
+void CMainMap::DimMap()
+{
+ CWindow* pw;
+ CMap* pm;
+ CSlider* ps;
+ Math::Point pos, dim;
+ float value;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw == 0 ) return;
+ pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
+ if ( pm == 0 ) return;
+
+ pm->SetState(STATE_VISIBLE, (m_mapMode != 0));
+
+ dim.x = 100.0f/640.0f;
+ dim.y = 100.0f/480.0f;
+ pos.x = 540.0f/640.0f;
+ pos.y = 0.0f/480.0f;
+ pm->SetPos(pos);
+ pm->SetDim(dim);
+
+ ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_MAPZOOM);
+ if ( ps != 0 )
+ {
+ ps->SetState(STATE_VISIBLE, (m_mapMode != 0));
+
+ dim.x = SCROLL_WIDTH;
+ dim.y = 66.0f/480.0f;
+ pos.x = 523.0f/640.0f;
+ pos.y = 3.0f/480.0f;
+ ps->SetPos(pos);
+ ps->SetDim(dim);
+
+ value = pm->RetZoom();
+ value = (value-ZOOM_MIN)/(ZOOM_MAX-ZOOM_MIN);
+ value = powf(value, 0.5f);
+ ps->SetVisibleValue(value);
+ ps->SetArrowStep(0.2f);
+ }
+}
+
+// Returns the current zoom of the minimap.
+
+float CMainMap::RetZoomMap()
+{
+ CWindow* pw;
+ CMap* pm;
+ CSlider* ps;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw == 0 ) return ZOOM_MIN;
+
+ pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
+ if ( pm == 0 ) return ZOOM_MIN;
+
+ ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_MAPZOOM);
+ if ( ps == 0 ) return ZOOM_MIN;
+
+ return pm->RetZoom();
+}
+
+// Zoom the mini-map of any factor.
+
+void CMainMap::ZoomMap(float zoom)
+{
+ CWindow* pw;
+ CMap* pm;
+ CSlider* ps;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw == 0 ) return;
+ pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
+ if ( pm == 0 ) return;
+
+ ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_MAPZOOM);
+ if ( ps == 0 ) return;
+
+ if ( zoom < ZOOM_MIN ) zoom = ZOOM_MIN;
+ if ( zoom > ZOOM_MAX ) zoom = ZOOM_MAX;
+ pm->SetZoom(zoom);
+
+ DimMap();
+}
+
+// The mini-map zoom depending on the slider.
+
+void CMainMap::ZoomMap()
+{
+ CWindow* pw;
+ CMap* pm;
+ CSlider* ps;
+ float zoom;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw == 0 ) return;
+ pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
+ if ( pm == 0 ) return;
+
+ ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_MAPZOOM);
+ if ( ps == 0 ) return;
+
+ zoom = ps->RetVisibleValue();
+ zoom = powf(zoom, 2.0f);
+ zoom = ZOOM_MIN+zoom*(ZOOM_MAX-ZOOM_MIN);
+ pm->SetZoom(zoom);
+
+ DimMap();
+}
+
+// Enables or disables the card.
+
+void CMainMap::MapEnable(bool bEnable)
+{
+ CWindow* pw;
+ CMap* pm;
+ CSlider* ps;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw == 0 ) return;
+
+ pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
+ if ( pm != 0 )
+ {
+ pm->SetEnable(bEnable);
+ }
+
+ ps = (CSlider*)pw->SearchControl(EVENT_OBJECT_MAPZOOM);
+ if ( ps != 0 )
+ {
+ ps->SetState(STATE_ENABLE, bEnable);
+ }
+}
+
+// Specifies the type of icon for the selected object.
+
+void CMainMap::SetToy(bool bToy)
+{
+ CWindow* pw;
+ CMap* pm;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw == 0 ) return;
+
+ pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
+ if ( pm == 0 ) return;
+
+ pm->SetToy(bToy);
+}
+
+// Specifies the parameters when using a still image.
+
+void CMainMap::SetFixParam(float zoom, float ox, float oy, float angle,
+ int mode, bool bDebug)
+{
+ CWindow* pw;
+ CMap* pm;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw == 0 ) return;
+
+ pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
+ if ( pm == 0 ) return;
+
+ pm->SetZoom(zoom);
+ pm->SetOffset(ox, oy);
+ pm->SetAngle(angle);
+ pm->SetMode(mode);
+ pm->SetDebug(bDebug);
+}
+
+// Updates the mini-map following to a change of terrain.
+
+void CMainMap::UpdateMap()
+{
+ CWindow* pw;
+ CMap* pm;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw == 0 ) return;
+
+ pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
+ if ( pm != 0 )
+ {
+ pm->UpdateTerrain();
+ }
+}
+
+// Indicates if the mini-map is visible.
+
+bool CMainMap::RetShowMap()
+{
+ return ( m_mapMode != 0 );
+}
+
+// Indicates whether the mini-map displays a still image.
+
+bool CMainMap::RetFixImage()
+{
+ return m_bFixImage;
+}
+
+
+// The object is detected in the mini-map.
+
+CObject* CMainMap::DetectMap(Math::Point pos, bool &bInMap)
+{
+ CWindow* pw;
+ CMap* pm;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw == 0 ) return 0;
+
+ bInMap = false;
+ pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
+ if ( pm == 0 ) return 0;
+ return pm->DetectObject(pos, bInMap);
+}
+
+
+// Indicates the object with the mouse hovers over.
+
+void CMainMap::SetHilite(CObject* pObj)
+{
+ CWindow* pw;
+ CMap* pm;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw == 0 ) return;
+
+ pm = (CMap*)pw->SearchControl(EVENT_OBJECT_MAP);
+ if ( pm != 0 )
+ {
+ pm->SetHilite(pObj);
+ }
+}
+
+
diff --git a/src/ui/mainmap.h b/src/ui/mainmap.h
index 6b10d94..dba87fc 100644
--- a/src/ui/mainmap.h
+++ b/src/ui/mainmap.h
@@ -1,70 +1,70 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// mainmap.h
-
-#pragma once
-
-
-#include "common/struct.h"
-#include "math/point.h"
-
-
-class CInstanceManager;
-class CEvent;
-class CD3DEngine;
-class CInterface;
-class CObject;
-
-
-
-class CMainMap
-{
-public:
- CMainMap(CInstanceManager* iMan);
- ~CMainMap();
-
- void UpdateMap();
- void CreateMap();
- void SetFixImage(char *filename);
- void FloorColorMap(D3DCOLORVALUE floor, D3DCOLORVALUE water);
- void ShowMap(bool bShow);
- void DimMap();
- float RetZoomMap();
- void ZoomMap(float zoom);
- void ZoomMap();
- void MapEnable(bool bEnable);
- bool RetShowMap();
- bool RetFixImage();
- CObject* DetectMap(Math::Point pos, bool &bInMap);
- void SetHilite(CObject* pObj);
- void SetToy(bool bToy);
- void SetFixParam(float zoom, float ox, float oy, float angle, int mode, bool bDebug);
-
-protected:
- void CenterMap();
-
-protected:
- CInstanceManager* m_iMan;
- CEvent* m_event;
- CD3DEngine* m_engine;
- CInterface* m_interface;
-
- int m_mapMode;
- bool m_bFixImage;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// mainmap.h
+
+#pragma once
+
+
+#include "common/struct.h"
+#include "math/point.h"
+
+
+class CInstanceManager;
+class CEvent;
+class CD3DEngine;
+class CInterface;
+class CObject;
+
+
+
+class CMainMap
+{
+public:
+ CMainMap(CInstanceManager* iMan);
+ ~CMainMap();
+
+ void UpdateMap();
+ void CreateMap();
+ void SetFixImage(char *filename);
+ void FloorColorMap(D3DCOLORVALUE floor, D3DCOLORVALUE water);
+ void ShowMap(bool bShow);
+ void DimMap();
+ float RetZoomMap();
+ void ZoomMap(float zoom);
+ void ZoomMap();
+ void MapEnable(bool bEnable);
+ bool RetShowMap();
+ bool RetFixImage();
+ CObject* DetectMap(Math::Point pos, bool &bInMap);
+ void SetHilite(CObject* pObj);
+ void SetToy(bool bToy);
+ void SetFixParam(float zoom, float ox, float oy, float angle, int mode, bool bDebug);
+
+protected:
+ void CenterMap();
+
+protected:
+ CInstanceManager* m_iMan;
+ CEvent* m_event;
+ CD3DEngine* m_engine;
+ CInterface* m_interface;
+
+ int m_mapMode;
+ bool m_bFixImage;
+};
+
+
diff --git a/src/ui/mainshort.cpp b/src/ui/mainshort.cpp
index 332fa2b..f23354b 100644
--- a/src/ui/mainshort.cpp
+++ b/src/ui/mainshort.cpp
@@ -1,374 +1,374 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// mainshort.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "common/global.h"
-#include "common/event.h"
-#include "common/iman.h"
-#include "object/object.h"
-#include "ui/interface.h"
-#include "ui/map.h"
-#include "ui/button.h"
-#include "object/robotmain.h"
-#include "ui/mainshort.h"
-
-
-
-
-// Constructor of the application card.
-
-CMainShort::CMainShort(CInstanceManager* iMan)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_SHORT, this);
-
- m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
- m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
-
- FlushShortcuts();
-}
-
-// Destructor of the application card.
-
-CMainShort::~CMainShort()
-{
-}
-
-
-
-void CMainShort::SetMode(bool bBuilding)
-{
- m_bBuilding = bBuilding;
-}
-
-
-
-// Reset all shortcuts.
-
-void CMainShort::FlushShortcuts()
-{
- int i;
-
- for ( i=0 ; i<20 ; i++ )
- {
- m_shortcuts[i] = 0;
- }
-}
-
-static EventMsg table_sc_em[20] =
-{
- EVENT_OBJECT_SHORTCUT00,
- EVENT_OBJECT_SHORTCUT01,
- EVENT_OBJECT_SHORTCUT02,
- EVENT_OBJECT_SHORTCUT03,
- EVENT_OBJECT_SHORTCUT04,
- EVENT_OBJECT_SHORTCUT05,
- EVENT_OBJECT_SHORTCUT06,
- EVENT_OBJECT_SHORTCUT07,
- EVENT_OBJECT_SHORTCUT08,
- EVENT_OBJECT_SHORTCUT09,
- EVENT_OBJECT_SHORTCUT10,
- EVENT_OBJECT_SHORTCUT11,
- EVENT_OBJECT_SHORTCUT12,
- EVENT_OBJECT_SHORTCUT13,
- EVENT_OBJECT_SHORTCUT14,
- EVENT_OBJECT_SHORTCUT15,
- EVENT_OBJECT_SHORTCUT16,
- EVENT_OBJECT_SHORTCUT17,
- EVENT_OBJECT_SHORTCUT18,
- EVENT_OBJECT_SHORTCUT19,
-};
-
-// Interface creates shortcuts to the units.
-
-bool CMainShort::CreateShortcuts()
-{
- CObject* pObj;
- CControl* pc;
- ObjectType type;
- Math::Point pos, dim;
- int i, rank, icon;
- char name[100];
-
- if ( m_main->RetFixScene() ) return false;
-
- m_interface->DeleteControl(EVENT_OBJECT_MOVIELOCK);
- m_interface->DeleteControl(EVENT_OBJECT_EDITLOCK);
- for ( i=0 ; i<20 ; i++ )
- {
- if ( i != 0 && m_shortcuts[i] == 0 ) continue;
-
- m_interface->DeleteControl(table_sc_em[i]);
- m_shortcuts[i] = 0;
- }
-
- dim.x = 28.0f/640.0f;
- dim.y = 28.0f/480.0f;
- pos.x = 4.0f/640.0f;
- pos.y = (480.0f-32.0f)/480.0f;
-
- if ( m_main->RetMovieLock() &&
- !m_main->RetEditLock() ) // hangs during film?
- {
- m_interface->CreateShortcut(pos, dim, 7, EVENT_OBJECT_MOVIELOCK);
- return true;
- }
- if ( !m_main->RetFreePhoto() &&
- (m_main->RetEditLock() ||
- m_engine->RetPause()) ) // hangs during edition?
- {
- m_interface->CreateShortcut(pos, dim, 6, EVENT_OBJECT_EDITLOCK);
- return true;
- }
-
- rank = 0;
-
- m_interface->CreateShortcut(pos, dim, 2, table_sc_em[rank]);
- pos.x += dim.x*1.2f;
- m_shortcuts[rank] = 0;
- rank ++;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue;
- if ( !pObj->RetSelectable() ) continue;
- if ( pObj->RetProxyActivate() ) continue;
-
- type = pObj->RetType();
- icon = -1;
- if ( m_bBuilding )
- {
- if ( type == OBJECT_FACTORY ) icon = 32;
- if ( type == OBJECT_DERRICK ) icon = 33;
- if ( type == OBJECT_CONVERT ) icon = 34;
- if ( type == OBJECT_RESEARCH ) icon = 35;
- if ( type == OBJECT_STATION ) icon = 36;
- if ( type == OBJECT_TOWER ) icon = 37;
- if ( type == OBJECT_LABO ) icon = 38;
- if ( type == OBJECT_ENERGY ) icon = 39;
- if ( type == OBJECT_RADAR ) icon = 40;
- if ( type == OBJECT_INFO ) icon = 44;
- if ( type == OBJECT_REPAIR ) icon = 41;
- if ( type == OBJECT_DESTROYER) icon = 41;
- if ( type == OBJECT_NUCLEAR ) icon = 42;
- if ( type == OBJECT_PARA ) icon = 46;
- if ( type == OBJECT_SAFE ) icon = 47;
- if ( type == OBJECT_HUSTON ) icon = 48;
- if ( type == OBJECT_BASE ) icon = 43;
- }
- else
- {
- if ( type == OBJECT_HUMAN ) icon = 8;
- if ( type == OBJECT_MOBILEfa ) icon = 11;
- if ( type == OBJECT_MOBILEta ) icon = 10;
- if ( type == OBJECT_MOBILEwa ) icon = 9;
- if ( type == OBJECT_MOBILEia ) icon = 22;
- if ( type == OBJECT_MOBILEfc ) icon = 17;
- if ( type == OBJECT_MOBILEtc ) icon = 16;
- if ( type == OBJECT_MOBILEwc ) icon = 15;
- if ( type == OBJECT_MOBILEic ) icon = 23;
- if ( type == OBJECT_MOBILEfi ) icon = 27;
- if ( type == OBJECT_MOBILEti ) icon = 26;
- if ( type == OBJECT_MOBILEwi ) icon = 25;
- if ( type == OBJECT_MOBILEii ) icon = 28;
- if ( type == OBJECT_MOBILEfs ) icon = 14;
- if ( type == OBJECT_MOBILEts ) icon = 13;
- if ( type == OBJECT_MOBILEws ) icon = 12;
- if ( type == OBJECT_MOBILEis ) icon = 24;
- if ( type == OBJECT_MOBILErt ) icon = 18;
- if ( type == OBJECT_MOBILErc ) icon = 19;
- if ( type == OBJECT_MOBILErr ) icon = 20;
- if ( type == OBJECT_MOBILErs ) icon = 29;
- if ( type == OBJECT_MOBILEsa ) icon = 21;
- if ( type == OBJECT_MOBILEft ) icon = 30;
- if ( type == OBJECT_MOBILEtt ) icon = 30;
- if ( type == OBJECT_MOBILEwt ) icon = 30;
- if ( type == OBJECT_MOBILEit ) icon = 30;
- if ( type == OBJECT_MOBILEdr ) icon = 48;
- if ( type == OBJECT_APOLLO2 ) icon = 49;
- }
- if ( icon == -1 ) continue;
-
- m_interface->CreateShortcut(pos, dim, icon, table_sc_em[rank]);
- pos.x += dim.x;
- m_shortcuts[rank] = pObj;
-
- pc = m_interface->SearchControl(table_sc_em[rank]);
- if ( pc != 0 )
- {
- pObj->GetTooltipName(name);
- pc->SetTooltip(name);
- }
- rank ++;
-
- if ( rank >= 20 ) break;
- }
-
- UpdateShortcuts();
- return true;
-}
-
-// Updates the interface shortcuts to the units.
-
-bool CMainShort::UpdateShortcuts()
-{
- CControl* pc;
- int i;
-
- for ( i=0 ; i<20 ; i++ )
- {
- if ( m_shortcuts[i] == 0 ) continue;
-
- pc = m_interface->SearchControl(table_sc_em[i]);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_shortcuts[i]->RetSelect());
- pc->SetState(STATE_RUN, m_shortcuts[i]->IsProgram());
- }
- }
- return true;
-}
-
-// Selects an object through a shortcut.
-
-void CMainShort::SelectShortcut(EventMsg event)
-{
- int i;
-
- for ( i=0 ; i<20 ; i++ )
- {
- if ( event == table_sc_em[i] )
- {
- if ( i != 0 && m_shortcuts[i] == 0 ) continue;
-
- if ( i == 0 ) // buildings <-> vehicles?
- {
- m_bBuilding = !m_bBuilding;
- CreateShortcuts();
- }
- else
- {
- m_main->SelectObject(m_shortcuts[i]);
- }
- return;
- }
- }
-}
-
-
-// Selects the next object.
-
-void CMainShort::SelectNext()
-{
- CObject* pPrev;
- int i;
-
- if ( m_main->RetMovieLock() ||
- m_main->RetEditLock() ||
- m_engine->RetPause() ) return;
-
- pPrev = m_main->DeselectAll();
-
- for ( i=1 ; i<20 ; i++ )
- {
- if ( m_shortcuts[i] == pPrev )
- {
- if ( m_shortcuts[++i] == 0 ) i = 1;
- break;
- }
- }
-
- if ( i == 20 || m_shortcuts[i] == 0 )
- {
- m_main->SelectHuman();
- }
- else
- {
- m_main->SelectObject(m_shortcuts[i]);
- }
-}
-
-
-// The object detected by the mouse hovers over.
-
-CObject* CMainShort::DetectShort(Math::Point pos)
-{
- CControl* pc;
- Math::Point cpos, cdim;
- int i;
-
- for ( i=0 ; i<20 ; i++ )
- {
- if ( m_shortcuts[i] == 0 ) continue;
-
- pc = m_interface->SearchControl(table_sc_em[i]);
- if ( pc != 0 )
- {
- cpos = pc->RetPos();
- cdim = pc->RetDim();
-
- if ( pos.x >= cpos.x &&
- pos.x <= cpos.x+cdim.x &&
- pos.y >= cpos.y &&
- pos.y <= cpos.y+cdim.y )
- {
- return m_shortcuts[i];
- }
- }
- }
- return 0;
-}
-
-// Reports the object with the mouse hovers over.
-
-void CMainShort::SetHilite(CObject* pObj)
-{
- CControl* pc;
- int i;
-
- for ( i=0 ; i<20 ; i++ )
- {
- if ( m_shortcuts[i] == 0 ) continue;
-
- pc = m_interface->SearchControl(table_sc_em[i]);
- if ( pc == 0 ) continue;
-
- if ( m_shortcuts[i] == pObj )
- {
- pc->SetState(STATE_HILIGHT);
- pc->SetState(STATE_FRAME);
- }
- else
- {
- pc->ClearState(STATE_HILIGHT);
- pc->ClearState(STATE_FRAME);
- }
- }
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// mainshort.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "common/global.h"
+#include "common/event.h"
+#include "common/iman.h"
+#include "object/object.h"
+#include "ui/interface.h"
+#include "ui/map.h"
+#include "ui/button.h"
+#include "object/robotmain.h"
+#include "ui/mainshort.h"
+
+
+
+
+// Constructor of the application card.
+
+CMainShort::CMainShort(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_SHORT, this);
+
+ m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+ m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+
+ FlushShortcuts();
+}
+
+// Destructor of the application card.
+
+CMainShort::~CMainShort()
+{
+}
+
+
+
+void CMainShort::SetMode(bool bBuilding)
+{
+ m_bBuilding = bBuilding;
+}
+
+
+
+// Reset all shortcuts.
+
+void CMainShort::FlushShortcuts()
+{
+ int i;
+
+ for ( i=0 ; i<20 ; i++ )
+ {
+ m_shortcuts[i] = 0;
+ }
+}
+
+static EventMsg table_sc_em[20] =
+{
+ EVENT_OBJECT_SHORTCUT00,
+ EVENT_OBJECT_SHORTCUT01,
+ EVENT_OBJECT_SHORTCUT02,
+ EVENT_OBJECT_SHORTCUT03,
+ EVENT_OBJECT_SHORTCUT04,
+ EVENT_OBJECT_SHORTCUT05,
+ EVENT_OBJECT_SHORTCUT06,
+ EVENT_OBJECT_SHORTCUT07,
+ EVENT_OBJECT_SHORTCUT08,
+ EVENT_OBJECT_SHORTCUT09,
+ EVENT_OBJECT_SHORTCUT10,
+ EVENT_OBJECT_SHORTCUT11,
+ EVENT_OBJECT_SHORTCUT12,
+ EVENT_OBJECT_SHORTCUT13,
+ EVENT_OBJECT_SHORTCUT14,
+ EVENT_OBJECT_SHORTCUT15,
+ EVENT_OBJECT_SHORTCUT16,
+ EVENT_OBJECT_SHORTCUT17,
+ EVENT_OBJECT_SHORTCUT18,
+ EVENT_OBJECT_SHORTCUT19,
+};
+
+// Interface creates shortcuts to the units.
+
+bool CMainShort::CreateShortcuts()
+{
+ CObject* pObj;
+ CControl* pc;
+ ObjectType type;
+ Math::Point pos, dim;
+ int i, rank, icon;
+ char name[100];
+
+ if ( m_main->RetFixScene() ) return false;
+
+ m_interface->DeleteControl(EVENT_OBJECT_MOVIELOCK);
+ m_interface->DeleteControl(EVENT_OBJECT_EDITLOCK);
+ for ( i=0 ; i<20 ; i++ )
+ {
+ if ( i != 0 && m_shortcuts[i] == 0 ) continue;
+
+ m_interface->DeleteControl(table_sc_em[i]);
+ m_shortcuts[i] = 0;
+ }
+
+ dim.x = 28.0f/640.0f;
+ dim.y = 28.0f/480.0f;
+ pos.x = 4.0f/640.0f;
+ pos.y = (480.0f-32.0f)/480.0f;
+
+ if ( m_main->RetMovieLock() &&
+ !m_main->RetEditLock() ) // hangs during film?
+ {
+ m_interface->CreateShortcut(pos, dim, 7, EVENT_OBJECT_MOVIELOCK);
+ return true;
+ }
+ if ( !m_main->RetFreePhoto() &&
+ (m_main->RetEditLock() ||
+ m_engine->RetPause()) ) // hangs during edition?
+ {
+ m_interface->CreateShortcut(pos, dim, 6, EVENT_OBJECT_EDITLOCK);
+ return true;
+ }
+
+ rank = 0;
+
+ m_interface->CreateShortcut(pos, dim, 2, table_sc_em[rank]);
+ pos.x += dim.x*1.2f;
+ m_shortcuts[rank] = 0;
+ rank ++;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue;
+ if ( !pObj->RetSelectable() ) continue;
+ if ( pObj->RetProxyActivate() ) continue;
+
+ type = pObj->RetType();
+ icon = -1;
+ if ( m_bBuilding )
+ {
+ if ( type == OBJECT_FACTORY ) icon = 32;
+ if ( type == OBJECT_DERRICK ) icon = 33;
+ if ( type == OBJECT_CONVERT ) icon = 34;
+ if ( type == OBJECT_RESEARCH ) icon = 35;
+ if ( type == OBJECT_STATION ) icon = 36;
+ if ( type == OBJECT_TOWER ) icon = 37;
+ if ( type == OBJECT_LABO ) icon = 38;
+ if ( type == OBJECT_ENERGY ) icon = 39;
+ if ( type == OBJECT_RADAR ) icon = 40;
+ if ( type == OBJECT_INFO ) icon = 44;
+ if ( type == OBJECT_REPAIR ) icon = 41;
+ if ( type == OBJECT_DESTROYER) icon = 41;
+ if ( type == OBJECT_NUCLEAR ) icon = 42;
+ if ( type == OBJECT_PARA ) icon = 46;
+ if ( type == OBJECT_SAFE ) icon = 47;
+ if ( type == OBJECT_HUSTON ) icon = 48;
+ if ( type == OBJECT_BASE ) icon = 43;
+ }
+ else
+ {
+ if ( type == OBJECT_HUMAN ) icon = 8;
+ if ( type == OBJECT_MOBILEfa ) icon = 11;
+ if ( type == OBJECT_MOBILEta ) icon = 10;
+ if ( type == OBJECT_MOBILEwa ) icon = 9;
+ if ( type == OBJECT_MOBILEia ) icon = 22;
+ if ( type == OBJECT_MOBILEfc ) icon = 17;
+ if ( type == OBJECT_MOBILEtc ) icon = 16;
+ if ( type == OBJECT_MOBILEwc ) icon = 15;
+ if ( type == OBJECT_MOBILEic ) icon = 23;
+ if ( type == OBJECT_MOBILEfi ) icon = 27;
+ if ( type == OBJECT_MOBILEti ) icon = 26;
+ if ( type == OBJECT_MOBILEwi ) icon = 25;
+ if ( type == OBJECT_MOBILEii ) icon = 28;
+ if ( type == OBJECT_MOBILEfs ) icon = 14;
+ if ( type == OBJECT_MOBILEts ) icon = 13;
+ if ( type == OBJECT_MOBILEws ) icon = 12;
+ if ( type == OBJECT_MOBILEis ) icon = 24;
+ if ( type == OBJECT_MOBILErt ) icon = 18;
+ if ( type == OBJECT_MOBILErc ) icon = 19;
+ if ( type == OBJECT_MOBILErr ) icon = 20;
+ if ( type == OBJECT_MOBILErs ) icon = 29;
+ if ( type == OBJECT_MOBILEsa ) icon = 21;
+ if ( type == OBJECT_MOBILEft ) icon = 30;
+ if ( type == OBJECT_MOBILEtt ) icon = 30;
+ if ( type == OBJECT_MOBILEwt ) icon = 30;
+ if ( type == OBJECT_MOBILEit ) icon = 30;
+ if ( type == OBJECT_MOBILEdr ) icon = 48;
+ if ( type == OBJECT_APOLLO2 ) icon = 49;
+ }
+ if ( icon == -1 ) continue;
+
+ m_interface->CreateShortcut(pos, dim, icon, table_sc_em[rank]);
+ pos.x += dim.x;
+ m_shortcuts[rank] = pObj;
+
+ pc = m_interface->SearchControl(table_sc_em[rank]);
+ if ( pc != 0 )
+ {
+ pObj->GetTooltipName(name);
+ pc->SetTooltip(name);
+ }
+ rank ++;
+
+ if ( rank >= 20 ) break;
+ }
+
+ UpdateShortcuts();
+ return true;
+}
+
+// Updates the interface shortcuts to the units.
+
+bool CMainShort::UpdateShortcuts()
+{
+ CControl* pc;
+ int i;
+
+ for ( i=0 ; i<20 ; i++ )
+ {
+ if ( m_shortcuts[i] == 0 ) continue;
+
+ pc = m_interface->SearchControl(table_sc_em[i]);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_shortcuts[i]->RetSelect());
+ pc->SetState(STATE_RUN, m_shortcuts[i]->IsProgram());
+ }
+ }
+ return true;
+}
+
+// Selects an object through a shortcut.
+
+void CMainShort::SelectShortcut(EventMsg event)
+{
+ int i;
+
+ for ( i=0 ; i<20 ; i++ )
+ {
+ if ( event == table_sc_em[i] )
+ {
+ if ( i != 0 && m_shortcuts[i] == 0 ) continue;
+
+ if ( i == 0 ) // buildings <-> vehicles?
+ {
+ m_bBuilding = !m_bBuilding;
+ CreateShortcuts();
+ }
+ else
+ {
+ m_main->SelectObject(m_shortcuts[i]);
+ }
+ return;
+ }
+ }
+}
+
+
+// Selects the next object.
+
+void CMainShort::SelectNext()
+{
+ CObject* pPrev;
+ int i;
+
+ if ( m_main->RetMovieLock() ||
+ m_main->RetEditLock() ||
+ m_engine->RetPause() ) return;
+
+ pPrev = m_main->DeselectAll();
+
+ for ( i=1 ; i<20 ; i++ )
+ {
+ if ( m_shortcuts[i] == pPrev )
+ {
+ if ( m_shortcuts[++i] == 0 ) i = 1;
+ break;
+ }
+ }
+
+ if ( i == 20 || m_shortcuts[i] == 0 )
+ {
+ m_main->SelectHuman();
+ }
+ else
+ {
+ m_main->SelectObject(m_shortcuts[i]);
+ }
+}
+
+
+// The object detected by the mouse hovers over.
+
+CObject* CMainShort::DetectShort(Math::Point pos)
+{
+ CControl* pc;
+ Math::Point cpos, cdim;
+ int i;
+
+ for ( i=0 ; i<20 ; i++ )
+ {
+ if ( m_shortcuts[i] == 0 ) continue;
+
+ pc = m_interface->SearchControl(table_sc_em[i]);
+ if ( pc != 0 )
+ {
+ cpos = pc->RetPos();
+ cdim = pc->RetDim();
+
+ if ( pos.x >= cpos.x &&
+ pos.x <= cpos.x+cdim.x &&
+ pos.y >= cpos.y &&
+ pos.y <= cpos.y+cdim.y )
+ {
+ return m_shortcuts[i];
+ }
+ }
+ }
+ return 0;
+}
+
+// Reports the object with the mouse hovers over.
+
+void CMainShort::SetHilite(CObject* pObj)
+{
+ CControl* pc;
+ int i;
+
+ for ( i=0 ; i<20 ; i++ )
+ {
+ if ( m_shortcuts[i] == 0 ) continue;
+
+ pc = m_interface->SearchControl(table_sc_em[i]);
+ if ( pc == 0 ) continue;
+
+ if ( m_shortcuts[i] == pObj )
+ {
+ pc->SetState(STATE_HILIGHT);
+ pc->SetState(STATE_FRAME);
+ }
+ else
+ {
+ pc->ClearState(STATE_HILIGHT);
+ pc->ClearState(STATE_FRAME);
+ }
+ }
+}
+
diff --git a/src/ui/mainshort.h b/src/ui/mainshort.h
index 82b0253..f260f0e 100644
--- a/src/ui/mainshort.h
+++ b/src/ui/mainshort.h
@@ -1,62 +1,62 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// mainshort.h
-
-#pragma once
-
-
-#include "common/event.h"
-#include "math/point.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CInterface;
-class CRobotMain;
-class CObject;
-
-
-
-class CMainShort
-{
-public:
- CMainShort(CInstanceManager* iMan);
- ~CMainShort();
-
- void SetMode(bool bBuilding);
- void FlushShortcuts();
- bool CreateShortcuts();
- bool UpdateShortcuts();
- void SelectShortcut(EventMsg event);
- void SelectNext();
- CObject* DetectShort(Math::Point pos);
- void SetHilite(CObject* pObj);
-
-protected:
-
-protected:
- CInstanceManager* m_iMan;
- CEvent* m_event;
- CD3DEngine* m_engine;
- CInterface* m_interface;
- CRobotMain* m_main;
-
- CObject* m_shortcuts[20];
- bool m_bBuilding;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// mainshort.h
+
+#pragma once
+
+
+#include "common/event.h"
+#include "math/point.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CInterface;
+class CRobotMain;
+class CObject;
+
+
+
+class CMainShort
+{
+public:
+ CMainShort(CInstanceManager* iMan);
+ ~CMainShort();
+
+ void SetMode(bool bBuilding);
+ void FlushShortcuts();
+ bool CreateShortcuts();
+ bool UpdateShortcuts();
+ void SelectShortcut(EventMsg event);
+ void SelectNext();
+ CObject* DetectShort(Math::Point pos);
+ void SetHilite(CObject* pObj);
+
+protected:
+
+protected:
+ CInstanceManager* m_iMan;
+ CEvent* m_event;
+ CD3DEngine* m_engine;
+ CInterface* m_interface;
+ CRobotMain* m_main;
+
+ CObject* m_shortcuts[20];
+ bool m_bBuilding;
+};
+
+
diff --git a/src/ui/map.cpp b/src/ui/map.cpp
index 35e63d1..a74e557 100644
--- a/src/ui/map.cpp
+++ b/src/ui/map.cpp
@@ -1,1339 +1,1339 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// map.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/geometry.h"
-#include "old/d3dengine.h"
-#include "common/event.h"
-#include "old/math3d.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "object/object.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "object/robotmain.h"
-#include "common/iman.h"
-#include "ui/map.h"
-
-
-
-
-// Object's constructor.
-
-CMap::CMap(CInstanceManager* iMan) : CControl(iMan)
-{
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
-
- m_bEnable = true;
- m_time = 0.0f;
- m_zoom = 2.0f;
- m_offset.x = 0.0f;
- m_offset.y = 0.0f;
- m_angle = 0.0f;
-
- m_floorColor.r = 1.00f;
- m_floorColor.g = 0.50f;
- m_floorColor.b = 0.00f; // orange
-
- m_waterColor.r = 0.00f;
- m_waterColor.g = 0.80f;
- m_waterColor.b = 1.00f; // blue
-
- m_half = m_terrain->RetMosaic()*m_terrain->RetBrick()*m_terrain->RetSize()/2.0f;
-
- m_hiliteRank = -1;
- FlushObject();
-
- m_fixImage[0] = 0;
- m_mode = 0;
- m_bToy = false;
- m_bDebug = false;
-}
-
-// Object's destructor.
-
-CMap::~CMap()
-{
-}
-
-
-// Creates a new button.
-
-bool CMap::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- CControl::Create(pos, dim, icon, eventMsg);
- return true;
-}
-
-
-// Choice of the offset, when image is displayed.
-
-void CMap::SetOffset(float ox, float oy)
-{
- m_offset.x = ox;
- m_offset.y = oy;
- m_half = m_terrain->RetMosaic()*m_terrain->RetBrick()*m_terrain->RetSize()/2.0f;
-}
-
-// Choice of the global angle of rotation.
-
-void CMap::SetAngle(float angle)
-{
- m_angle = angle;
-}
-
-// Specifies the alternate mode.
-
-void CMap::SetMode(int mode)
-{
- m_mode = mode;
-}
-
-// Specifies the type of icon for the selected object.
-
-void CMap::SetToy(bool bToy)
-{
- m_bToy = bToy;
-}
-
-void CMap::SetDebug(bool bDebug)
-{
- m_bDebug = bDebug;
-}
-
-
-//Choice of magnification of the map.
-
-void CMap::SetZoom(float value)
-{
- m_zoom = value;
- m_half = m_terrain->RetMosaic()*m_terrain->RetBrick()*m_terrain->RetSize()/2.0f;
-}
-
-float CMap::RetZoom()
-{
- return m_zoom;
-}
-
-// Choosing a fixed offset.
-
-// Enables or disables the card.
-
-void CMap::SetEnable(bool bEnable)
-{
- m_bEnable = bEnable;
- SetState(STATE_DEAD, !bEnable);
-}
-
-bool CMap::RetEnable()
-{
- return m_bEnable;
-}
-
-
-// Choosing the color of the soil.
-
-void CMap::SetFloorColor(D3DCOLORVALUE color)
-{
- m_floorColor = color;
-}
-
-// Choosing the color of the water.
-
-void CMap::SetWaterColor(D3DCOLORVALUE color)
-{
- m_waterColor = color;
-}
-
-
-// Specifies a fixed image in place of the drawing of the relief.
-
-void CMap::SetFixImage(char *filename)
-{
- strcpy(m_fixImage, filename);
-}
-
-// Whether to use a still image.
-
-bool CMap::RetFixImage()
-{
- return (m_fixImage[0] != 0);
-}
-
-
-// Management of an event.
-
-bool CMap::EventProcess(const Event &event)
-{
- bool bInMap;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return true;
-
- CControl::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- m_time += event.rTime;
- }
-
- if ( event.event == EVENT_MOUSEMOVE && Detect(event.pos) )
- {
- m_engine->SetMouseType(D3DMOUSENORM);
- if ( DetectObject(event.pos, bInMap) != 0 )
- {
- m_engine->SetMouseType(D3DMOUSEHAND);
- }
- }
-
- if ( event.event == EVENT_LBUTTONDOWN )
- {
- if ( CControl::Detect(event.pos) )
- {
- SelectObject(event.pos);
- return false;
- }
- }
-
- return true;
-}
-
-// Adjusts the offset to not exceed the card.
-
-Math::Point CMap::AdjustOffset(Math::Point offset)
-{
- float limit;
-
- limit = m_half - m_half/m_zoom;
- if ( offset.x < -limit ) offset.x = -limit;
- if ( offset.x > limit ) offset.x = limit;
- if ( offset.y < -limit ) offset.y = -limit;
- if ( offset.y > limit ) offset.y = limit;
-
- return offset;
-}
-
-// Indicates the object with the mouse hovers over.
-
-void CMap::SetHilite(CObject* pObj)
-{
- int i;
-
- m_hiliteRank = -1;
- if ( m_bToy || m_fixImage[0] != 0 ) return; // card with still image?
- if ( pObj == 0 ) return;
-
- for ( i=0 ; i<MAPMAXOBJECT ; i++ )
- {
- if ( !m_map[i].bUsed ) continue;
-
- if ( m_map[i].object == pObj )
- {
- m_hiliteRank = i;
- break;
- }
- }
-}
-
-// Detects an object in the map.
-
-CObject* CMap::DetectObject(Math::Point pos, bool &bInMap)
-{
- float dist, min;
- int i, best;
-
- bInMap = false;
- if ( pos.x < m_pos.x ||
- pos.y < m_pos.y ||
- pos.x > m_pos.x+m_dim.x ||
- pos.y > m_pos.y+m_dim.y ) return 0;
-
- bInMap = true;
-
- pos.x = (pos.x-m_pos.x)/m_dim.x*256.0f;
- pos.y = (pos.y-m_pos.y)/m_dim.y*256.0f; // 0..256
- pos.x = (pos.x-128.0f)*m_half/(m_zoom*128.0f)+m_offset.x;
- pos.y = (pos.y-128.0f)*m_half/(m_zoom*128.0f)+m_offset.y;
-
- min = 10000.0f;
- best = -1;
- for ( i=MAPMAXOBJECT-1 ; i>=0 ; i-- )
- {
- if ( !m_map[i].bUsed ) continue;
- if ( m_map[i].color == MAPCOLOR_BBOX && !m_bRadar ) continue;
- if ( m_map[i].color == MAPCOLOR_ALIEN && !m_bRadar ) continue;
-
- dist = Math::Point(m_map[i].pos.x-pos.x, m_map[i].pos.y-pos.y).Length();
- if ( dist > m_half/m_zoom*8.0f/100.0f ) continue; // too far?
- if ( dist < min )
- {
- min = dist;
- best = i;
- }
- }
- if ( best == -1 ) return 0;
- return m_map[best].object;
-}
-
-// Selects an object.
-
-void CMap::SelectObject(Math::Point pos)
-{
- CObject *pObj;
- bool bInMap;
-
- pObj = DetectObject(pos, bInMap);
- if ( pObj != 0 )
- {
- m_main->SelectObject(pObj);
- }
-}
-
-
-// Draw the map.
-
-void CMap::Draw()
-{
- Math::Point uv1, uv2;
- int i;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return;
-
- CControl::Draw(); // draws the bottom (button)
-
- if ( !m_bEnable ) return;
-
- if ( m_fixImage[0] == 0 && m_map[MAPMAXOBJECT-1].bUsed )
- {
- m_offset = AdjustOffset(m_map[MAPMAXOBJECT-1].pos);
- }
-
- if ( m_fixImage[0] == 0 ) // drawing of the relief?
- {
- m_engine->SetTexture("map.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 0.5f+(m_offset.x-(m_half/m_zoom))/(m_half*2.0f);
- uv1.y = 0.5f-(m_offset.y+(m_half/m_zoom))/(m_half*2.0f);
- uv2.x = 0.5f+(m_offset.x+(m_half/m_zoom))/(m_half*2.0f);
- uv2.y = 0.5f-(m_offset.y-(m_half/m_zoom))/(m_half*2.0f);
- DrawVertex(uv1, uv2, 0.97f); // drawing the map
- }
- else // still image?
- {
- m_engine->LoadTexture(m_fixImage);
- m_engine->SetTexture(m_fixImage);
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 0.0f;
- uv1.y = 0.0f;
- uv2.x = 1.0f;
- uv2.y = 1.0f;
- DrawVertex(uv1, uv2, 0.97f); // drawing the map
- }
-
- i = MAPMAXOBJECT-1;
- if ( m_map[i].bUsed ) // selection:
- {
- DrawFocus(m_map[i].pos, m_map[i].dir, m_map[i].type, m_map[i].color);
- }
-
- for ( i=0 ; i<m_totalFix ; i++ ) // fixed objects:
- {
- if ( i == m_hiliteRank ) continue;
- DrawObject(m_map[i].pos, m_map[i].dir, m_map[i].type, m_map[i].color, false, false);
- }
-
- for ( i=MAPMAXOBJECT-2 ; i>m_totalMove ; i-- ) // moving objects:
- {
- if ( i == m_hiliteRank ) continue;
- DrawObject(m_map[i].pos, m_map[i].dir, m_map[i].type, m_map[i].color, false, false);
- }
-
- i = MAPMAXOBJECT-1;
- if ( m_map[i].bUsed && i != m_hiliteRank ) // selection:
- {
- DrawObject(m_map[i].pos, m_map[i].dir, m_map[i].type, m_map[i].color, true, false);
- }
-
- if ( m_hiliteRank != -1 && m_map[m_hiliteRank].bUsed )
- {
- i = m_hiliteRank;
- DrawObject(m_map[i].pos, m_map[i].dir, m_map[i].type, m_map[i].color, false, true);
- DrawHilite(m_map[i].pos);
- }
-}
-
-// Computing a point for drawFocus.
-
-Math::Point CMap::MapInter(Math::Point pos, float dir)
-{
- Math::Point p1;
- float limit;
-
- p1.x = pos.x+1.0f;
- p1.y = pos.y;
- p1 = Math::RotatePoint(pos, dir, p1);
-
- p1.x -= pos.x;
- p1.y -= pos.y;
-
- limit = m_mapPos.x+m_mapDim.x-pos.x;
- if ( p1.x > limit ) // exceeds the right?
- {
- p1.y = limit*p1.y/p1.x;
- p1.x = limit;
- }
- limit = m_mapPos.y*0.75f+m_mapDim.y*0.75f-pos.y;
- if ( p1.y > limit ) // exceeds the top?
- {
- p1.x = limit*p1.x/p1.y;
- p1.y = limit;
- }
- limit = m_mapPos.x-pos.x;
- if ( p1.x < limit ) // exceeds the left?
- {
- p1.y = limit*p1.y/p1.x;
- p1.x = limit;
- }
- limit = m_mapPos.y*0.75f-pos.y;
- if ( p1.y < limit ) // exceeds the bottom?
- {
- p1.x = limit*p1.x/p1.y;
- p1.y = limit;
- }
-
- p1.x += pos.x;
- p1.y += pos.y;
- return p1;
-}
-
-// Draw the field of vision of the selected object.
-
-void CMap::DrawFocus(Math::Point pos, float dir, ObjectType type, MapColor color)
-{
- Math::Point p0, p1, p2, uv1, uv2, rel;
- float aMin, aMax, aOct, focus, a;
- float limit[5];
- bool bEnding;
- int quart;
-
- if ( m_bToy || m_fixImage[0] != 0 ) return; // map with still image?
- if ( color != MAPCOLOR_MOVE ) return;
-
- pos.x = (pos.x-m_offset.x)*(m_zoom*0.5f)/m_half+0.5f;
- pos.y = (pos.y-m_offset.y)*(m_zoom*0.5f)/m_half+0.5f;
-
- if ( pos.x < 0.0f || pos.x > 1.0f ||
- pos.y < 0.0f || pos.y > 1.0f ) return;
-
- rel.x = pos.x*2.0f-1.0f;
- rel.y = pos.y*2.0f-1.0f; // rel [-1..1]
-
- pos.x = m_mapPos.x+m_mapDim.x*pos.x;
- pos.y = m_mapPos.y*0.75f+m_mapDim.y*pos.y*0.75f;
-
- focus = m_engine->RetFocus();
- dir += Math::PI/2.0f;
- aMin = Math::NormAngle(dir-Math::PI/4.0f*focus);
- aMax = Math::NormAngle(dir+Math::PI/4.0f*focus);
-
- if ( aMin > aMax )
- {
- aMax += Math::PI*2.0f; // aMax always after aMin
- }
-
- limit[0] = Math::RotateAngle( 1.0f-rel.x, 1.0f-rel.y); // upper/right
- limit[1] = Math::RotateAngle(-1.0f-rel.x, 1.0f-rel.y); // upper/left
- limit[2] = Math::RotateAngle(-1.0f-rel.x, -1.0f-rel.y); // lower/left
- limit[3] = Math::RotateAngle( 1.0f-rel.x, -1.0f-rel.y); // lower/right
- limit[4] = limit[0]+Math::PI*2.0f;
-
- a = Math::NormAngle(aMin);
- for ( quart=0 ; quart<4 ; quart++ )
- {
- if ( a >= limit[quart+0] &&
- a <= limit[quart+1] ) break;
- }
- if ( quart == 4 ) quart = -1;
-
- uv1.x = 113.0f/256.0f; // degrade green
- uv1.y = 240.5f/256.0f;
- uv2.x = 126.0f/256.0f;
- uv2.y = 255.0f/256.0f;
-
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTw);
-
- bEnding = false;
- do
- {
- quart ++;
- aOct = limit[quart%4];
- if ( quart >= 4 ) aOct += Math::PI*2.0f;
- if ( aOct >= aMax-Math::VERY_SMALL )
- {
- aOct = aMax;
- bEnding = true;
- }
-
- p0 = pos;
- p1 = MapInter(pos, aMin);
- p2 = MapInter(pos, aOct);
- p0.y /= 0.75f;
- p1.y /= 0.75f;
- p2.y /= 0.75f;
- DrawTriangle(p0, p2, p1, uv1, uv2);
-
- aMin = aOct;
- }
- while ( !bEnding );
-}
-
-// Draw an object.
-
-void CMap::DrawObject(Math::Point pos, float dir, ObjectType type, MapColor color,
- bool bSelect, bool bHilite)
-{
- Math::Point p1, p2, p3, p4, p5, dim, uv1, uv2;
- bool bOut, bUp, bDown, bLeft, bRight;
-
- pos.x = (pos.x-m_offset.x)*(m_zoom*0.5f)/m_half+0.5f;
- pos.y = (pos.y-m_offset.y)*(m_zoom*0.5f)/m_half+0.5f;
-
- bOut = bUp = bDown = bLeft = bRight = false;
- if ( pos.x < 0.06f ) { pos.x = 0.02f; bOut = bLeft = true; }
- if ( pos.y < 0.06f ) { pos.y = 0.02f; bOut = bDown = true; }
- if ( pos.x > 0.94f ) { pos.x = 0.98f; bOut = bRight = true; }
- if ( pos.y > 0.94f ) { pos.y = 0.98f; bOut = bUp = true; }
-
- pos.x = m_mapPos.x+m_mapDim.x*pos.x;
- pos.y = m_mapPos.y+m_mapDim.y*pos.y;
- dim.x = 2.0f/128.0f*0.75f;
- dim.y = 2.0f/128.0f;
-
- if ( bOut ) // outside the map?
- {
- if ( color == MAPCOLOR_BBOX && !m_bRadar ) return;
- if ( color == MAPCOLOR_ALIEN && !m_bRadar ) return;
-
- if ( Math::Mod(m_time+(pos.x+pos.y)*4.0f, 0.6f) > 0.2f )
- {
- return; // flashes
- }
-
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTb);
- if ( bUp )
- {
- uv1.x = 160.5f/256.0f; // yellow triangle ^
- uv1.y = 240.5f/256.0f;
- uv2.x = 175.0f/256.0f;
- uv2.y = 255.0f/256.0f;
- }
- if ( bDown )
- {
- uv1.x = 160.5f/256.0f; // yellow triangle v
- uv1.y = 255.0f/256.0f;
- uv2.x = 175.0f/256.0f;
- uv2.y = 240.5f/256.0f;
- }
- if ( bRight )
- {
- uv1.x = 176.5f/256.0f; // yellow triangle >
- uv1.y = 240.5f/256.0f;
- uv2.x = 191.0f/256.0f;
- uv2.y = 255.0f/256.0f;
- }
- if ( bLeft )
- {
- uv1.x = 191.0f/256.0f; // yellow triangle <
- uv1.y = 240.5f/256.0f;
- uv2.x = 176.5f/256.0f;
- uv2.y = 255.0f/256.0f;
- }
- pos.x -= dim.x/2.0f;
- pos.y -= dim.y/2.0f;
- DrawIcon(pos, dim, uv1, uv2);
- return;
- }
-
- if ( bSelect )
- {
- if ( m_bToy )
- {
- dim.x *= 1.2f+sinf(m_time*8.0f)*0.1f;
- dim.y *= 1.2f+sinf(m_time*8.0f)*0.1f;
- }
- else
- {
- dim.x *= 1.2f+sinf(m_time*8.0f)*0.3f;
- dim.y *= 1.2f+sinf(m_time*8.0f)*0.3f;
- }
- }
- if ( color == MAPCOLOR_BASE ||
- color == MAPCOLOR_FIX ||
- color == MAPCOLOR_MOVE )
- {
- if ( bHilite )
- {
- dim.x *= 2.2f;
- dim.y *= 2.2f;
- }
- else
- {
- dim.x *= 0.6f;
- dim.y *= 0.6f;
- }
- }
- if ( color == MAPCOLOR_ALIEN )
- {
- dim.x *= 1.4f;
- dim.y *= 1.4f;
- }
- if ( type == OBJECT_TEEN28 ) // bottle?
- {
- dim.x *= 3.0f;
- dim.y *= 3.0f;
- bHilite = true;
- }
- if ( type == OBJECT_TEEN34 ) // stone?
- {
- dim.x *= 2.0f;
- dim.y *= 2.0f;
- bHilite = true;
- }
-
- if ( color == MAPCOLOR_MOVE && bSelect )
- {
- if ( m_bToy )
- {
- p1.x = pos.x;
- p1.y = pos.y+dim.y*1.4f;
- p1 = Math::RotatePoint(pos, dir, p1);
- p1.x = pos.x+(p1.x-pos.x)*0.75f;
-
- p2.x = pos.x+dim.x*1.2f;
- p2.y = pos.y+dim.y*0.8f;
- p2 = Math::RotatePoint(pos, dir, p2);
- p2.x = pos.x+(p2.x-pos.x)*0.75f;
-
- p3.x = pos.x+dim.x*1.2f;
- p3.y = pos.y-dim.y*1.0f;
- p3 = Math::RotatePoint(pos, dir, p3);
- p3.x = pos.x+(p3.x-pos.x)*0.75f;
-
- p4.x = pos.x-dim.x*1.2f;
- p4.y = pos.y-dim.y*1.0f;
- p4 = Math::RotatePoint(pos, dir, p4);
- p4.x = pos.x+(p4.x-pos.x)*0.75f;
-
- p5.x = pos.x-dim.x*1.2f;
- p5.y = pos.y+dim.y*0.8f;
- p5 = Math::RotatePoint(pos, dir, p5);
- p5.x = pos.x+(p5.x-pos.x)*0.75f;
- }
- else
- {
- p1.x = pos.x;
- p1.y = pos.y+dim.y*2.4f;
- p1 = Math::RotatePoint(pos, dir, p1);
- p1.x = pos.x+(p1.x-pos.x)*0.75f;
-
- p2.x = pos.x+dim.x*1.0f;
- p2.y = pos.y-dim.y*1.6f;
- p2 = Math::RotatePoint(pos, dir, p2);
- p2.x = pos.x+(p2.x-pos.x)*0.75f;
-
- p3.x = pos.x-dim.x*1.0f;
- p3.y = pos.y-dim.y*1.6f;
- p3 = Math::RotatePoint(pos, dir, p3);
- p3.x = pos.x+(p3.x-pos.x)*0.75f;
- }
- }
-
- pos.x -= dim.x/2.0f;
- pos.y -= dim.y/2.0f;
-
- if ( color == MAPCOLOR_BASE ||
- color == MAPCOLOR_FIX )
- {
- DrawObjectIcon(pos, dim, color, type, bHilite);
- }
-
- if ( color == MAPCOLOR_MOVE )
- {
- if ( bSelect )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
- if ( m_bToy )
- {
- uv1.x = 164.5f/256.0f; // black pentagon
- uv1.y = 228.5f/256.0f;
- uv2.x = 172.0f/256.0f;
- uv2.y = 236.0f/256.0f;
- DrawPenta(p1, p2, p3, p4, p5, uv1, uv2);
- }
- else
- {
- uv1.x = 144.5f/256.0f; // red triangle
- uv1.y = 240.5f/256.0f;
- uv2.x = 159.0f/256.0f;
- uv2.y = 255.0f/256.0f;
- DrawTriangle(p1, p2, p3, uv1, uv2);
- }
- }
- DrawObjectIcon(pos, dim, color, type, bHilite);
- }
-
- if ( color == MAPCOLOR_BBOX )
- {
- if ( m_bRadar )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTw);
- uv1.x = 64.5f/256.0f; // blue triangle
- uv1.y = 240.5f/256.0f;
- uv2.x = 79.0f/256.0f;
- uv2.y = 255.0f/256.0f;
- DrawIcon(pos, dim, uv1, uv2);
- }
- }
-
- if ( color == MAPCOLOR_ALIEN )
- {
- if ( m_bRadar )
- {
- DrawObjectIcon(pos, dim, color, type, true);
- }
- }
-
- if ( color == MAPCOLOR_WAYPOINTb )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTb);
- uv1.x = 192.5f/256.0f; // blue cross
- uv1.y = 240.5f/256.0f;
- uv2.x = 207.0f/256.0f;
- uv2.y = 255.0f/256.0f;
- DrawIcon(pos, dim, uv1, uv2);
- }
- if ( color == MAPCOLOR_WAYPOINTr )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTb);
- uv1.x = 208.5f/256.0f; // red cross
- uv1.y = 240.5f/256.0f;
- uv2.x = 223.0f/256.0f;
- uv2.y = 255.0f/256.0f;
- DrawIcon(pos, dim, uv1, uv2);
- }
- if ( color == MAPCOLOR_WAYPOINTg )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTb);
- uv1.x = 224.5f/256.0f; // green cross
- uv1.y = 240.5f/256.0f;
- uv2.x = 239.0f/256.0f;
- uv2.y = 255.0f/256.0f;
- DrawIcon(pos, dim, uv1, uv2);
- }
- if ( color == MAPCOLOR_WAYPOINTy )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTb);
- uv1.x = 240.5f/256.0f; // yellow cross
- uv1.y = 240.5f/256.0f;
- uv2.x = 255.0f/256.0f;
- uv2.y = 255.0f/256.0f;
- DrawIcon(pos, dim, uv1, uv2);
- }
- if ( color == MAPCOLOR_WAYPOINTv )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTb);
- uv1.x = 192.5f/256.0f; // violet cross
- uv1.y = 224.5f/256.0f;
- uv2.x = 207.0f/256.0f;
- uv2.y = 239.0f/256.0f;
- DrawIcon(pos, dim, uv1, uv2);
- }
-}
-
-// Draws the icon of an object.
-
-void CMap::DrawObjectIcon(Math::Point pos, Math::Point dim, MapColor color,
- ObjectType type, bool bHilite)
-{
- Math::Point ppos, ddim, uv1, uv2;
- float dp;
- int icon;
-
- dp = 0.5f/256.0f;
-
- m_engine->SetTexture("button3.tga");
- m_engine->SetState(D3DSTATENORMAL);
- if ( color == MAPCOLOR_MOVE )
- {
- uv1.x = 160.0f/256.0f; // blue
- uv1.y = 224.0f/256.0f;
- }
- else if ( color == MAPCOLOR_ALIEN )
- {
- uv1.x = 224.0f/256.0f; // green
- uv1.y = 224.0f/256.0f;
- }
- else
- {
- uv1.x = 192.0f/256.0f; // yellow
- uv1.y = 224.0f/256.0f;
- }
- uv2.x = uv1.x+32.0f/256.0f;
- uv2.y = uv1.y+32.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2); // background colors
-
- if ( bHilite )
- {
- icon = -1;
- if ( type == OBJECT_FACTORY ) icon = 32;
- if ( type == OBJECT_DERRICK ) icon = 33;
- if ( type == OBJECT_CONVERT ) icon = 34;
- if ( type == OBJECT_RESEARCH ) icon = 35;
- if ( type == OBJECT_STATION ) icon = 36;
- if ( type == OBJECT_TOWER ) icon = 37;
- if ( type == OBJECT_LABO ) icon = 38;
- if ( type == OBJECT_ENERGY ) icon = 39;
- if ( type == OBJECT_RADAR ) icon = 40;
- if ( type == OBJECT_INFO ) icon = 44;
- if ( type == OBJECT_REPAIR ) icon = 41;
- if ( type == OBJECT_DESTROYER) icon = 41;
- if ( type == OBJECT_NUCLEAR ) icon = 42;
- if ( type == OBJECT_PARA ) icon = 46;
- if ( type == OBJECT_SAFE ) icon = 47;
- if ( type == OBJECT_HUSTON ) icon = 48;
- if ( type == OBJECT_TARGET1 ) icon = 45;
- if ( type == OBJECT_BASE ) icon = 43;
- if ( type == OBJECT_HUMAN ) icon = 8;
- if ( type == OBJECT_MOBILEfa ) icon = 11;
- if ( type == OBJECT_MOBILEta ) icon = 10;
- if ( type == OBJECT_MOBILEwa ) icon = 9;
- if ( type == OBJECT_MOBILEia ) icon = 22;
- if ( type == OBJECT_MOBILEfc ) icon = 17;
- if ( type == OBJECT_MOBILEtc ) icon = 16;
- if ( type == OBJECT_MOBILEwc ) icon = 15;
- if ( type == OBJECT_MOBILEic ) icon = 23;
- if ( type == OBJECT_MOBILEfi ) icon = 27;
- if ( type == OBJECT_MOBILEti ) icon = 26;
- if ( type == OBJECT_MOBILEwi ) icon = 25;
- if ( type == OBJECT_MOBILEii ) icon = 28;
- if ( type == OBJECT_MOBILEfs ) icon = 14;
- if ( type == OBJECT_MOBILEts ) icon = 13;
- if ( type == OBJECT_MOBILEws ) icon = 12;
- if ( type == OBJECT_MOBILEis ) icon = 24;
- if ( type == OBJECT_MOBILErt ) icon = 18;
- if ( type == OBJECT_MOBILErc ) icon = 19;
- if ( type == OBJECT_MOBILErr ) icon = 20;
- if ( type == OBJECT_MOBILErs ) icon = 29;
- if ( type == OBJECT_MOBILEsa ) icon = 21;
- if ( type == OBJECT_MOBILEft ) icon = 30;
- if ( type == OBJECT_MOBILEtt ) icon = 30;
- if ( type == OBJECT_MOBILEwt ) icon = 30;
- if ( type == OBJECT_MOBILEit ) icon = 30;
- if ( type == OBJECT_MOBILEtg ) icon = 45;
- if ( type == OBJECT_MOBILEdr ) icon = 48;
- if ( type == OBJECT_APOLLO2 ) icon = 49;
- if ( type == OBJECT_MOTHER ) icon = 31;
- if ( type == OBJECT_ANT ) icon = 31;
- if ( type == OBJECT_SPIDER ) icon = 31;
- if ( type == OBJECT_BEE ) icon = 31;
- if ( type == OBJECT_WORM ) icon = 31;
- if ( type == OBJECT_TEEN28 ) icon = 48; // bottle
- if ( type == OBJECT_TEEN34 ) icon = 48; // stone
- if ( icon == -1 ) return;
-
- m_engine->SetState(D3DSTATETTw);
- uv1.x = (32.0f/256.0f)*(icon%8);
- uv1.y = (32.0f/256.0f)*(icon/8);
- uv2.x = uv1.x+32.0f/256.0f;
- uv2.y = uv1.y+32.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2); // icon
- }
-}
-
-// Draw the object with the mouse hovers over.
-
-void CMap::DrawHilite(Math::Point pos)
-{
- Math::Point dim, uv1, uv2;
- bool bOut, bUp, bDown, bLeft, bRight;
-
- if ( m_bToy || m_fixImage[0] != 0 ) return; // map with still image?
-
- pos.x = (pos.x-m_offset.x)*(m_zoom*0.5f)/m_half+0.5f;
- pos.y = (pos.y-m_offset.y)*(m_zoom*0.5f)/m_half+0.5f;
-
- bOut = bUp = bDown = bLeft = bRight = false;
- if ( pos.x < 0.06f ) { pos.x = 0.02f; bOut = bLeft = true; }
- if ( pos.y < 0.06f ) { pos.y = 0.02f; bOut = bDown = true; }
- if ( pos.x > 0.94f ) { pos.x = 0.98f; bOut = bRight = true; }
- if ( pos.y > 0.94f ) { pos.y = 0.98f; bOut = bUp = true; }
-
- pos.x = m_mapPos.x+m_mapDim.x*pos.x;
- pos.y = m_mapPos.y+m_mapDim.y*pos.y;
- dim.x = 2.0f/128.0f*0.75f;
- dim.y = 2.0f/128.0f;
- dim.x *= 2.0f+cosf(m_time*8.0f)*0.5f;
- dim.y *= 2.0f+cosf(m_time*8.0f)*0.5f;
-
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTb);
- uv1.x = 160.5f/256.0f; // hilite
- uv1.y = 224.5f/256.0f;
- uv2.x = 175.0f/256.0f;
- uv2.y = 239.0f/256.0f;
- pos.x -= dim.x/2.0f;
- pos.y -= dim.y/2.0f;
- DrawIcon(pos, dim, uv1, uv2);
-}
-
-// Draws a triangular icon.
-
-void CMap::DrawTriangle(Math::Point p1, Math::Point p2, Math::Point p3, Math::Point uv1, Math::Point uv2)
-{
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2 vertex[3]; // 1 triangle
- Math::Vector n;
-
- device = m_engine->RetD3DDevice();
-
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x,uv1.y);
- vertex[1] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv1.x,uv2.y);
- vertex[2] = D3DVERTEX2(Math::Vector(p3.x, p3.y, 0.0f), n, uv2.x,uv2.y);
-
- device->DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_VERTEX2, vertex, 3, NULL);
- m_engine->AddStatisticTriangle(1);
-}
-
-// Draw a pentagon icon (a 5 rating, what!).
-
-void CMap::DrawPenta(Math::Point p1, Math::Point p2, Math::Point p3, Math::Point p4, Math::Point p5, Math::Point uv1, Math::Point uv2)
-{
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2 vertex[5]; // 1 pentagon
- Math::Vector n;
-
- device = m_engine->RetD3DDevice();
-
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
-
-#if 1
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x,uv1.y);
- vertex[1] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv1.x,uv2.y);
- vertex[2] = D3DVERTEX2(Math::Vector(p5.x, p5.y, 0.0f), n, uv2.x,uv2.y);
- vertex[3] = D3DVERTEX2(Math::Vector(p3.x, p3.y, 0.0f), n, uv2.x,uv2.y);
- vertex[4] = D3DVERTEX2(Math::Vector(p4.x, p4.y, 0.0f), n, uv2.x,uv2.y);
-
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 5, NULL);
-#else
- vertex[0] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv1.x,uv1.y);
- vertex[1] = D3DVERTEX2(Math::Vector(p3.x, p3.y, 0.0f), n, uv1.x,uv2.y);
- vertex[2] = D3DVERTEX2(Math::Vector(p4.x, p4.y, 0.0f), n, uv2.x,uv2.y);
-
- device->DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_VERTEX2, vertex, 3, NULL);
-#endif
- m_engine->AddStatisticTriangle(3);
-}
-
-// Draw the vertex array.
-
-void CMap::DrawVertex(Math::Point uv1, Math::Point uv2, float zoom)
-{
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Point p1, p2, c;
- Math::Vector n;
-
- device = m_engine->RetD3DDevice();
-
- p1.x = m_pos.x;
- p1.y = m_pos.y;
- p2.x = m_pos.x + m_dim.x;
- p2.y = m_pos.y + m_dim.y;
-
- c.x = (p1.x+p2.x)/2.0f;
- c.y = (p1.y+p2.y)/2.0f; // center
-
- p1.x = (p1.x-c.x)*zoom + c.x;
- p1.y = (p1.y-c.y)*zoom + c.y;
-
- p2.x = (p2.x-c.x)*zoom + c.x;
- p2.y = (p2.y-c.y)*zoom + c.y;
-
- m_mapPos = p1;
- m_mapDim.x = p2.x-p1.x;
- m_mapDim.y = p2.y-p1.y;
-
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x,uv2.y);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, uv1.x,uv1.y);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, uv2.x,uv2.y);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv2.x,uv1.y);
-
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-}
-
-
-// Updates the field in the map.
-
-void CMap::UpdateTerrain()
-{
- D3DCOLORVALUE color;
- Math::Vector pos;
- float scale, water, level, intensity;
- int x, y;
-
- if ( m_fixImage[0] != 0 ) return; // still image?
- if ( !m_engine->OpenImage("map.tga") ) return;
-
- scale = m_terrain->RetScaleRelief();
- water = m_water->RetLevel();
- color.a = 0.0f;
-
- for ( y=0 ; y<256 ; y++ )
- {
- for ( x=0 ; x<256 ; x++ )
- {
- pos.x = ((float)x-128.0f)*m_half/128.0f;
- pos.z = -((float)y-128.0f)*m_half/128.0f;
- pos.y = 0.0f;
-
- if ( pos.x >= -m_half && pos.x <= m_half &&
- pos.z >= -m_half && pos.z <= m_half )
- {
- level = m_terrain->RetFloorLevel(pos, true)/scale;
- }
- else
- {
- level = 1000.0f;
- }
-
- intensity = level/256.0f;
- if ( intensity < 0.0f ) intensity = 0.0f;
- if ( intensity > 1.0f ) intensity = 1.0f;
-
- if ( level >= water ) // on water?
- {
- color.r = m_floorColor.r + (intensity-0.5f);
- color.g = m_floorColor.g + (intensity-0.5f);
- color.b = m_floorColor.b + (intensity-0.5f);
- }
- else // underwater?
- {
- color.r = m_waterColor.r + (intensity-0.5f);
- color.g = m_waterColor.g + (intensity-0.5f);
- color.b = m_waterColor.b + (intensity-0.5f);
- }
-
- m_engine->SetDot(x, y, color);
- }
- }
-
- m_engine->CopyImage(); // copy the ground drawing
- m_engine->CloseImage();
-}
-
-// Updates the field in the map.
-
-void CMap::UpdateTerrain(int bx, int by, int ex, int ey)
-{
- D3DCOLORVALUE color;
- Math::Vector pos;
- float scale, water, level, intensity;
- int x, y;
-
- if ( m_fixImage[0] != 0 ) return; // still image?
- if ( !m_engine->OpenImage("map.tga") ) return;
- m_engine->LoadImage();
-
- scale = m_terrain->RetScaleRelief();
- water = m_water->RetLevel();
- color.a = 0.0f;
-
- for ( y=by ; y<ey ; y++ )
- {
- for ( x=bx ; x<ex ; x++ )
- {
- pos.x = ((float)x-128.0f)*m_half/128.0f;
- pos.z = -((float)y-128.0f)*m_half/128.0f;
- pos.y = 0.0f;
-
- if ( pos.x >= -m_half && pos.x <= m_half &&
- pos.z >= -m_half && pos.z <= m_half )
- {
- level = m_terrain->RetFloorLevel(pos, true)/scale;
- }
- else
- {
- level = 1000.0f;
- }
-
- intensity = level/256.0f;
- if ( intensity < 0.0f ) intensity = 0.0f;
- if ( intensity > 1.0f ) intensity = 1.0f;
-
- if ( level > water ) // on water?
- {
- color.r = m_floorColor.r + (intensity-0.5f);
- color.g = m_floorColor.g + (intensity-0.5f);
- color.b = m_floorColor.b + (intensity-0.5f);
- }
- else // underwater?
- {
- color.r = m_waterColor.r + (intensity-0.5f);
- color.g = m_waterColor.g + (intensity-0.5f);
- color.b = m_waterColor.b + (intensity-0.5f);
- }
-
- m_engine->SetDot(x, y, color);
- }
- }
-
- m_engine->CopyImage(); // copy the ground drawing
- m_engine->CloseImage();
-}
-
-
-// Empty all objects.
-
-void CMap::FlushObject()
-{
- int i;
-
- m_totalFix = 0; // object index fixed
- m_totalMove = MAPMAXOBJECT-2; // moving vehicles index
- m_bRadar = m_main->RetCheatRadar(); // no radar
-
- for ( i=0 ; i<MAPMAXOBJECT ; i++ )
- {
- m_map[i].bUsed = false;
- }
-}
-
-// Updates an object in the map.
-
-void CMap::UpdateObject(CObject* pObj)
-{
- ObjectType type;
- MapColor color;
- Math::Vector pos;
- Math::Point ppos;
- float dir;
-
- if ( !m_bEnable ) return;
- if ( m_totalFix >= m_totalMove ) return; // full table?
-
- if ( !pObj->RetActif() ) return;
- if ( !pObj->RetSelectable() ) return;
- if ( pObj->RetProxyActivate() ) return;
- if ( pObj->RetTruck() != 0 ) return;
-
- type = pObj->RetType();
- pos = pObj->RetPosition(0);
- dir = -(pObj->RetAngleY(0)+Math::PI/2.0f);
-
- if ( m_angle != 0.0f )
- {
- ppos = RotatePoint(m_angle, Math::Point(pos.x, pos.z));
- pos.x = ppos.x;
- pos.z = ppos.y;
- dir += m_angle;
- }
-
- if ( type == OBJECT_RADAR )
- {
- m_bRadar = true; // radar exists
- }
-
- color = MAPCOLOR_NULL;
- if ( type == OBJECT_BASE )
- {
- color = MAPCOLOR_BASE;
- }
- if ( type == OBJECT_DERRICK ||
- type == OBJECT_FACTORY ||
- type == OBJECT_STATION ||
- type == OBJECT_CONVERT ||
- type == OBJECT_REPAIR ||
- type == OBJECT_DESTROYER||
- 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 ||
- type == OBJECT_TARGET1 ||
- type == OBJECT_START ||
- type == OBJECT_END || // stationary object?
- type == OBJECT_TEEN28 || // bottle?
- type == OBJECT_TEEN34 ) // stone?
- {
- color = MAPCOLOR_FIX;
- }
- if ( type == OBJECT_BBOX ||
- type == OBJECT_KEYa ||
- type == OBJECT_KEYb ||
- type == OBJECT_KEYc ||
- type == OBJECT_KEYd )
- {
- color = MAPCOLOR_BBOX;
- }
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr ||
- type == OBJECT_APOLLO2 ) // moving vehicle?
- {
- color = MAPCOLOR_MOVE;
- }
- if ( type == OBJECT_ANT ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ||
- type == OBJECT_SPIDER ) // mobile enemy?
- {
- color = MAPCOLOR_ALIEN;
- }
- if ( type == OBJECT_WAYPOINT ||
- type == OBJECT_FLAGb )
- {
- color = MAPCOLOR_WAYPOINTb;
- }
- if ( type == OBJECT_FLAGr )
- {
- color = MAPCOLOR_WAYPOINTr;
- }
- if ( type == OBJECT_FLAGg )
- {
- color = MAPCOLOR_WAYPOINTg;
- }
- if ( type == OBJECT_FLAGy )
- {
- color = MAPCOLOR_WAYPOINTy;
- }
- if ( type == OBJECT_FLAGv )
- {
- color = MAPCOLOR_WAYPOINTv;
- }
-
- if ( color == MAPCOLOR_NULL ) return;
-
- if ( m_fixImage[0] != 0 && !m_bDebug ) // map with still image?
- {
- if ( (type == OBJECT_TEEN28 ||
- type == OBJECT_TEEN34 ) &&
- m_mode == 0 ) return;
-
- if ( type != OBJECT_TEEN28 &&
- type != OBJECT_TEEN34 &&
- color != MAPCOLOR_MOVE ) return;
- }
-
- if ( pObj->RetSelect() )
- {
- m_map[MAPMAXOBJECT-1].type = type;
- m_map[MAPMAXOBJECT-1].object = pObj;
- m_map[MAPMAXOBJECT-1].color = color;
- m_map[MAPMAXOBJECT-1].pos.x = pos.x;
- m_map[MAPMAXOBJECT-1].pos.y = pos.z;
- m_map[MAPMAXOBJECT-1].dir = dir;
- m_map[MAPMAXOBJECT-1].bUsed = true;
- }
- else
- {
- if ( color == MAPCOLOR_BASE ||
- color == MAPCOLOR_FIX )
- {
- m_map[m_totalFix].type = type;
- m_map[m_totalFix].object = pObj;
- m_map[m_totalFix].color = color;
- m_map[m_totalFix].pos.x = pos.x;
- m_map[m_totalFix].pos.y = pos.z;
- m_map[m_totalFix].dir = dir;
- m_map[m_totalFix].bUsed = true;
- m_totalFix ++;
- }
- else
- {
- m_map[m_totalMove].type = type;
- m_map[m_totalMove].object = pObj;
- m_map[m_totalMove].color = color;
- m_map[m_totalMove].pos.x = pos.x;
- m_map[m_totalMove].pos.y = pos.z;
- m_map[m_totalMove].dir = dir;
- m_map[m_totalMove].bUsed = true;
- m_totalMove --;
- }
- }
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// map.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/geometry.h"
+#include "old/d3dengine.h"
+#include "common/event.h"
+#include "old/math3d.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "object/object.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "object/robotmain.h"
+#include "common/iman.h"
+#include "ui/map.h"
+
+
+
+
+// Object's constructor.
+
+CMap::CMap(CInstanceManager* iMan) : CControl(iMan)
+{
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+
+ m_bEnable = true;
+ m_time = 0.0f;
+ m_zoom = 2.0f;
+ m_offset.x = 0.0f;
+ m_offset.y = 0.0f;
+ m_angle = 0.0f;
+
+ m_floorColor.r = 1.00f;
+ m_floorColor.g = 0.50f;
+ m_floorColor.b = 0.00f; // orange
+
+ m_waterColor.r = 0.00f;
+ m_waterColor.g = 0.80f;
+ m_waterColor.b = 1.00f; // blue
+
+ m_half = m_terrain->RetMosaic()*m_terrain->RetBrick()*m_terrain->RetSize()/2.0f;
+
+ m_hiliteRank = -1;
+ FlushObject();
+
+ m_fixImage[0] = 0;
+ m_mode = 0;
+ m_bToy = false;
+ m_bDebug = false;
+}
+
+// Object's destructor.
+
+CMap::~CMap()
+{
+}
+
+
+// Creates a new button.
+
+bool CMap::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ CControl::Create(pos, dim, icon, eventMsg);
+ return true;
+}
+
+
+// Choice of the offset, when image is displayed.
+
+void CMap::SetOffset(float ox, float oy)
+{
+ m_offset.x = ox;
+ m_offset.y = oy;
+ m_half = m_terrain->RetMosaic()*m_terrain->RetBrick()*m_terrain->RetSize()/2.0f;
+}
+
+// Choice of the global angle of rotation.
+
+void CMap::SetAngle(float angle)
+{
+ m_angle = angle;
+}
+
+// Specifies the alternate mode.
+
+void CMap::SetMode(int mode)
+{
+ m_mode = mode;
+}
+
+// Specifies the type of icon for the selected object.
+
+void CMap::SetToy(bool bToy)
+{
+ m_bToy = bToy;
+}
+
+void CMap::SetDebug(bool bDebug)
+{
+ m_bDebug = bDebug;
+}
+
+
+//Choice of magnification of the map.
+
+void CMap::SetZoom(float value)
+{
+ m_zoom = value;
+ m_half = m_terrain->RetMosaic()*m_terrain->RetBrick()*m_terrain->RetSize()/2.0f;
+}
+
+float CMap::RetZoom()
+{
+ return m_zoom;
+}
+
+// Choosing a fixed offset.
+
+// Enables or disables the card.
+
+void CMap::SetEnable(bool bEnable)
+{
+ m_bEnable = bEnable;
+ SetState(STATE_DEAD, !bEnable);
+}
+
+bool CMap::RetEnable()
+{
+ return m_bEnable;
+}
+
+
+// Choosing the color of the soil.
+
+void CMap::SetFloorColor(D3DCOLORVALUE color)
+{
+ m_floorColor = color;
+}
+
+// Choosing the color of the water.
+
+void CMap::SetWaterColor(D3DCOLORVALUE color)
+{
+ m_waterColor = color;
+}
+
+
+// Specifies a fixed image in place of the drawing of the relief.
+
+void CMap::SetFixImage(char *filename)
+{
+ strcpy(m_fixImage, filename);
+}
+
+// Whether to use a still image.
+
+bool CMap::RetFixImage()
+{
+ return (m_fixImage[0] != 0);
+}
+
+
+// Management of an event.
+
+bool CMap::EventProcess(const Event &event)
+{
+ bool bInMap;
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return true;
+
+ CControl::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ m_time += event.rTime;
+ }
+
+ if ( event.event == EVENT_MOUSEMOVE && Detect(event.pos) )
+ {
+ m_engine->SetMouseType(D3DMOUSENORM);
+ if ( DetectObject(event.pos, bInMap) != 0 )
+ {
+ m_engine->SetMouseType(D3DMOUSEHAND);
+ }
+ }
+
+ if ( event.event == EVENT_LBUTTONDOWN )
+ {
+ if ( CControl::Detect(event.pos) )
+ {
+ SelectObject(event.pos);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Adjusts the offset to not exceed the card.
+
+Math::Point CMap::AdjustOffset(Math::Point offset)
+{
+ float limit;
+
+ limit = m_half - m_half/m_zoom;
+ if ( offset.x < -limit ) offset.x = -limit;
+ if ( offset.x > limit ) offset.x = limit;
+ if ( offset.y < -limit ) offset.y = -limit;
+ if ( offset.y > limit ) offset.y = limit;
+
+ return offset;
+}
+
+// Indicates the object with the mouse hovers over.
+
+void CMap::SetHilite(CObject* pObj)
+{
+ int i;
+
+ m_hiliteRank = -1;
+ if ( m_bToy || m_fixImage[0] != 0 ) return; // card with still image?
+ if ( pObj == 0 ) return;
+
+ for ( i=0 ; i<MAPMAXOBJECT ; i++ )
+ {
+ if ( !m_map[i].bUsed ) continue;
+
+ if ( m_map[i].object == pObj )
+ {
+ m_hiliteRank = i;
+ break;
+ }
+ }
+}
+
+// Detects an object in the map.
+
+CObject* CMap::DetectObject(Math::Point pos, bool &bInMap)
+{
+ float dist, min;
+ int i, best;
+
+ bInMap = false;
+ if ( pos.x < m_pos.x ||
+ pos.y < m_pos.y ||
+ pos.x > m_pos.x+m_dim.x ||
+ pos.y > m_pos.y+m_dim.y ) return 0;
+
+ bInMap = true;
+
+ pos.x = (pos.x-m_pos.x)/m_dim.x*256.0f;
+ pos.y = (pos.y-m_pos.y)/m_dim.y*256.0f; // 0..256
+ pos.x = (pos.x-128.0f)*m_half/(m_zoom*128.0f)+m_offset.x;
+ pos.y = (pos.y-128.0f)*m_half/(m_zoom*128.0f)+m_offset.y;
+
+ min = 10000.0f;
+ best = -1;
+ for ( i=MAPMAXOBJECT-1 ; i>=0 ; i-- )
+ {
+ if ( !m_map[i].bUsed ) continue;
+ if ( m_map[i].color == MAPCOLOR_BBOX && !m_bRadar ) continue;
+ if ( m_map[i].color == MAPCOLOR_ALIEN && !m_bRadar ) continue;
+
+ dist = Math::Point(m_map[i].pos.x-pos.x, m_map[i].pos.y-pos.y).Length();
+ if ( dist > m_half/m_zoom*8.0f/100.0f ) continue; // too far?
+ if ( dist < min )
+ {
+ min = dist;
+ best = i;
+ }
+ }
+ if ( best == -1 ) return 0;
+ return m_map[best].object;
+}
+
+// Selects an object.
+
+void CMap::SelectObject(Math::Point pos)
+{
+ CObject *pObj;
+ bool bInMap;
+
+ pObj = DetectObject(pos, bInMap);
+ if ( pObj != 0 )
+ {
+ m_main->SelectObject(pObj);
+ }
+}
+
+
+// Draw the map.
+
+void CMap::Draw()
+{
+ Math::Point uv1, uv2;
+ int i;
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return;
+
+ CControl::Draw(); // draws the bottom (button)
+
+ if ( !m_bEnable ) return;
+
+ if ( m_fixImage[0] == 0 && m_map[MAPMAXOBJECT-1].bUsed )
+ {
+ m_offset = AdjustOffset(m_map[MAPMAXOBJECT-1].pos);
+ }
+
+ if ( m_fixImage[0] == 0 ) // drawing of the relief?
+ {
+ m_engine->SetTexture("map.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 0.5f+(m_offset.x-(m_half/m_zoom))/(m_half*2.0f);
+ uv1.y = 0.5f-(m_offset.y+(m_half/m_zoom))/(m_half*2.0f);
+ uv2.x = 0.5f+(m_offset.x+(m_half/m_zoom))/(m_half*2.0f);
+ uv2.y = 0.5f-(m_offset.y-(m_half/m_zoom))/(m_half*2.0f);
+ DrawVertex(uv1, uv2, 0.97f); // drawing the map
+ }
+ else // still image?
+ {
+ m_engine->LoadTexture(m_fixImage);
+ m_engine->SetTexture(m_fixImage);
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 0.0f;
+ uv1.y = 0.0f;
+ uv2.x = 1.0f;
+ uv2.y = 1.0f;
+ DrawVertex(uv1, uv2, 0.97f); // drawing the map
+ }
+
+ i = MAPMAXOBJECT-1;
+ if ( m_map[i].bUsed ) // selection:
+ {
+ DrawFocus(m_map[i].pos, m_map[i].dir, m_map[i].type, m_map[i].color);
+ }
+
+ for ( i=0 ; i<m_totalFix ; i++ ) // fixed objects:
+ {
+ if ( i == m_hiliteRank ) continue;
+ DrawObject(m_map[i].pos, m_map[i].dir, m_map[i].type, m_map[i].color, false, false);
+ }
+
+ for ( i=MAPMAXOBJECT-2 ; i>m_totalMove ; i-- ) // moving objects:
+ {
+ if ( i == m_hiliteRank ) continue;
+ DrawObject(m_map[i].pos, m_map[i].dir, m_map[i].type, m_map[i].color, false, false);
+ }
+
+ i = MAPMAXOBJECT-1;
+ if ( m_map[i].bUsed && i != m_hiliteRank ) // selection:
+ {
+ DrawObject(m_map[i].pos, m_map[i].dir, m_map[i].type, m_map[i].color, true, false);
+ }
+
+ if ( m_hiliteRank != -1 && m_map[m_hiliteRank].bUsed )
+ {
+ i = m_hiliteRank;
+ DrawObject(m_map[i].pos, m_map[i].dir, m_map[i].type, m_map[i].color, false, true);
+ DrawHilite(m_map[i].pos);
+ }
+}
+
+// Computing a point for drawFocus.
+
+Math::Point CMap::MapInter(Math::Point pos, float dir)
+{
+ Math::Point p1;
+ float limit;
+
+ p1.x = pos.x+1.0f;
+ p1.y = pos.y;
+ p1 = Math::RotatePoint(pos, dir, p1);
+
+ p1.x -= pos.x;
+ p1.y -= pos.y;
+
+ limit = m_mapPos.x+m_mapDim.x-pos.x;
+ if ( p1.x > limit ) // exceeds the right?
+ {
+ p1.y = limit*p1.y/p1.x;
+ p1.x = limit;
+ }
+ limit = m_mapPos.y*0.75f+m_mapDim.y*0.75f-pos.y;
+ if ( p1.y > limit ) // exceeds the top?
+ {
+ p1.x = limit*p1.x/p1.y;
+ p1.y = limit;
+ }
+ limit = m_mapPos.x-pos.x;
+ if ( p1.x < limit ) // exceeds the left?
+ {
+ p1.y = limit*p1.y/p1.x;
+ p1.x = limit;
+ }
+ limit = m_mapPos.y*0.75f-pos.y;
+ if ( p1.y < limit ) // exceeds the bottom?
+ {
+ p1.x = limit*p1.x/p1.y;
+ p1.y = limit;
+ }
+
+ p1.x += pos.x;
+ p1.y += pos.y;
+ return p1;
+}
+
+// Draw the field of vision of the selected object.
+
+void CMap::DrawFocus(Math::Point pos, float dir, ObjectType type, MapColor color)
+{
+ Math::Point p0, p1, p2, uv1, uv2, rel;
+ float aMin, aMax, aOct, focus, a;
+ float limit[5];
+ bool bEnding;
+ int quart;
+
+ if ( m_bToy || m_fixImage[0] != 0 ) return; // map with still image?
+ if ( color != MAPCOLOR_MOVE ) return;
+
+ pos.x = (pos.x-m_offset.x)*(m_zoom*0.5f)/m_half+0.5f;
+ pos.y = (pos.y-m_offset.y)*(m_zoom*0.5f)/m_half+0.5f;
+
+ if ( pos.x < 0.0f || pos.x > 1.0f ||
+ pos.y < 0.0f || pos.y > 1.0f ) return;
+
+ rel.x = pos.x*2.0f-1.0f;
+ rel.y = pos.y*2.0f-1.0f; // rel [-1..1]
+
+ pos.x = m_mapPos.x+m_mapDim.x*pos.x;
+ pos.y = m_mapPos.y*0.75f+m_mapDim.y*pos.y*0.75f;
+
+ focus = m_engine->RetFocus();
+ dir += Math::PI/2.0f;
+ aMin = Math::NormAngle(dir-Math::PI/4.0f*focus);
+ aMax = Math::NormAngle(dir+Math::PI/4.0f*focus);
+
+ if ( aMin > aMax )
+ {
+ aMax += Math::PI*2.0f; // aMax always after aMin
+ }
+
+ limit[0] = Math::RotateAngle( 1.0f-rel.x, 1.0f-rel.y); // upper/right
+ limit[1] = Math::RotateAngle(-1.0f-rel.x, 1.0f-rel.y); // upper/left
+ limit[2] = Math::RotateAngle(-1.0f-rel.x, -1.0f-rel.y); // lower/left
+ limit[3] = Math::RotateAngle( 1.0f-rel.x, -1.0f-rel.y); // lower/right
+ limit[4] = limit[0]+Math::PI*2.0f;
+
+ a = Math::NormAngle(aMin);
+ for ( quart=0 ; quart<4 ; quart++ )
+ {
+ if ( a >= limit[quart+0] &&
+ a <= limit[quart+1] ) break;
+ }
+ if ( quart == 4 ) quart = -1;
+
+ uv1.x = 113.0f/256.0f; // degrade green
+ uv1.y = 240.5f/256.0f;
+ uv2.x = 126.0f/256.0f;
+ uv2.y = 255.0f/256.0f;
+
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTw);
+
+ bEnding = false;
+ do
+ {
+ quart ++;
+ aOct = limit[quart%4];
+ if ( quart >= 4 ) aOct += Math::PI*2.0f;
+ if ( aOct >= aMax-Math::VERY_SMALL )
+ {
+ aOct = aMax;
+ bEnding = true;
+ }
+
+ p0 = pos;
+ p1 = MapInter(pos, aMin);
+ p2 = MapInter(pos, aOct);
+ p0.y /= 0.75f;
+ p1.y /= 0.75f;
+ p2.y /= 0.75f;
+ DrawTriangle(p0, p2, p1, uv1, uv2);
+
+ aMin = aOct;
+ }
+ while ( !bEnding );
+}
+
+// Draw an object.
+
+void CMap::DrawObject(Math::Point pos, float dir, ObjectType type, MapColor color,
+ bool bSelect, bool bHilite)
+{
+ Math::Point p1, p2, p3, p4, p5, dim, uv1, uv2;
+ bool bOut, bUp, bDown, bLeft, bRight;
+
+ pos.x = (pos.x-m_offset.x)*(m_zoom*0.5f)/m_half+0.5f;
+ pos.y = (pos.y-m_offset.y)*(m_zoom*0.5f)/m_half+0.5f;
+
+ bOut = bUp = bDown = bLeft = bRight = false;
+ if ( pos.x < 0.06f ) { pos.x = 0.02f; bOut = bLeft = true; }
+ if ( pos.y < 0.06f ) { pos.y = 0.02f; bOut = bDown = true; }
+ if ( pos.x > 0.94f ) { pos.x = 0.98f; bOut = bRight = true; }
+ if ( pos.y > 0.94f ) { pos.y = 0.98f; bOut = bUp = true; }
+
+ pos.x = m_mapPos.x+m_mapDim.x*pos.x;
+ pos.y = m_mapPos.y+m_mapDim.y*pos.y;
+ dim.x = 2.0f/128.0f*0.75f;
+ dim.y = 2.0f/128.0f;
+
+ if ( bOut ) // outside the map?
+ {
+ if ( color == MAPCOLOR_BBOX && !m_bRadar ) return;
+ if ( color == MAPCOLOR_ALIEN && !m_bRadar ) return;
+
+ if ( Math::Mod(m_time+(pos.x+pos.y)*4.0f, 0.6f) > 0.2f )
+ {
+ return; // flashes
+ }
+
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTb);
+ if ( bUp )
+ {
+ uv1.x = 160.5f/256.0f; // yellow triangle ^
+ uv1.y = 240.5f/256.0f;
+ uv2.x = 175.0f/256.0f;
+ uv2.y = 255.0f/256.0f;
+ }
+ if ( bDown )
+ {
+ uv1.x = 160.5f/256.0f; // yellow triangle v
+ uv1.y = 255.0f/256.0f;
+ uv2.x = 175.0f/256.0f;
+ uv2.y = 240.5f/256.0f;
+ }
+ if ( bRight )
+ {
+ uv1.x = 176.5f/256.0f; // yellow triangle >
+ uv1.y = 240.5f/256.0f;
+ uv2.x = 191.0f/256.0f;
+ uv2.y = 255.0f/256.0f;
+ }
+ if ( bLeft )
+ {
+ uv1.x = 191.0f/256.0f; // yellow triangle <
+ uv1.y = 240.5f/256.0f;
+ uv2.x = 176.5f/256.0f;
+ uv2.y = 255.0f/256.0f;
+ }
+ pos.x -= dim.x/2.0f;
+ pos.y -= dim.y/2.0f;
+ DrawIcon(pos, dim, uv1, uv2);
+ return;
+ }
+
+ if ( bSelect )
+ {
+ if ( m_bToy )
+ {
+ dim.x *= 1.2f+sinf(m_time*8.0f)*0.1f;
+ dim.y *= 1.2f+sinf(m_time*8.0f)*0.1f;
+ }
+ else
+ {
+ dim.x *= 1.2f+sinf(m_time*8.0f)*0.3f;
+ dim.y *= 1.2f+sinf(m_time*8.0f)*0.3f;
+ }
+ }
+ if ( color == MAPCOLOR_BASE ||
+ color == MAPCOLOR_FIX ||
+ color == MAPCOLOR_MOVE )
+ {
+ if ( bHilite )
+ {
+ dim.x *= 2.2f;
+ dim.y *= 2.2f;
+ }
+ else
+ {
+ dim.x *= 0.6f;
+ dim.y *= 0.6f;
+ }
+ }
+ if ( color == MAPCOLOR_ALIEN )
+ {
+ dim.x *= 1.4f;
+ dim.y *= 1.4f;
+ }
+ if ( type == OBJECT_TEEN28 ) // bottle?
+ {
+ dim.x *= 3.0f;
+ dim.y *= 3.0f;
+ bHilite = true;
+ }
+ if ( type == OBJECT_TEEN34 ) // stone?
+ {
+ dim.x *= 2.0f;
+ dim.y *= 2.0f;
+ bHilite = true;
+ }
+
+ if ( color == MAPCOLOR_MOVE && bSelect )
+ {
+ if ( m_bToy )
+ {
+ p1.x = pos.x;
+ p1.y = pos.y+dim.y*1.4f;
+ p1 = Math::RotatePoint(pos, dir, p1);
+ p1.x = pos.x+(p1.x-pos.x)*0.75f;
+
+ p2.x = pos.x+dim.x*1.2f;
+ p2.y = pos.y+dim.y*0.8f;
+ p2 = Math::RotatePoint(pos, dir, p2);
+ p2.x = pos.x+(p2.x-pos.x)*0.75f;
+
+ p3.x = pos.x+dim.x*1.2f;
+ p3.y = pos.y-dim.y*1.0f;
+ p3 = Math::RotatePoint(pos, dir, p3);
+ p3.x = pos.x+(p3.x-pos.x)*0.75f;
+
+ p4.x = pos.x-dim.x*1.2f;
+ p4.y = pos.y-dim.y*1.0f;
+ p4 = Math::RotatePoint(pos, dir, p4);
+ p4.x = pos.x+(p4.x-pos.x)*0.75f;
+
+ p5.x = pos.x-dim.x*1.2f;
+ p5.y = pos.y+dim.y*0.8f;
+ p5 = Math::RotatePoint(pos, dir, p5);
+ p5.x = pos.x+(p5.x-pos.x)*0.75f;
+ }
+ else
+ {
+ p1.x = pos.x;
+ p1.y = pos.y+dim.y*2.4f;
+ p1 = Math::RotatePoint(pos, dir, p1);
+ p1.x = pos.x+(p1.x-pos.x)*0.75f;
+
+ p2.x = pos.x+dim.x*1.0f;
+ p2.y = pos.y-dim.y*1.6f;
+ p2 = Math::RotatePoint(pos, dir, p2);
+ p2.x = pos.x+(p2.x-pos.x)*0.75f;
+
+ p3.x = pos.x-dim.x*1.0f;
+ p3.y = pos.y-dim.y*1.6f;
+ p3 = Math::RotatePoint(pos, dir, p3);
+ p3.x = pos.x+(p3.x-pos.x)*0.75f;
+ }
+ }
+
+ pos.x -= dim.x/2.0f;
+ pos.y -= dim.y/2.0f;
+
+ if ( color == MAPCOLOR_BASE ||
+ color == MAPCOLOR_FIX )
+ {
+ DrawObjectIcon(pos, dim, color, type, bHilite);
+ }
+
+ if ( color == MAPCOLOR_MOVE )
+ {
+ if ( bSelect )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ if ( m_bToy )
+ {
+ uv1.x = 164.5f/256.0f; // black pentagon
+ uv1.y = 228.5f/256.0f;
+ uv2.x = 172.0f/256.0f;
+ uv2.y = 236.0f/256.0f;
+ DrawPenta(p1, p2, p3, p4, p5, uv1, uv2);
+ }
+ else
+ {
+ uv1.x = 144.5f/256.0f; // red triangle
+ uv1.y = 240.5f/256.0f;
+ uv2.x = 159.0f/256.0f;
+ uv2.y = 255.0f/256.0f;
+ DrawTriangle(p1, p2, p3, uv1, uv2);
+ }
+ }
+ DrawObjectIcon(pos, dim, color, type, bHilite);
+ }
+
+ if ( color == MAPCOLOR_BBOX )
+ {
+ if ( m_bRadar )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTw);
+ uv1.x = 64.5f/256.0f; // blue triangle
+ uv1.y = 240.5f/256.0f;
+ uv2.x = 79.0f/256.0f;
+ uv2.y = 255.0f/256.0f;
+ DrawIcon(pos, dim, uv1, uv2);
+ }
+ }
+
+ if ( color == MAPCOLOR_ALIEN )
+ {
+ if ( m_bRadar )
+ {
+ DrawObjectIcon(pos, dim, color, type, true);
+ }
+ }
+
+ if ( color == MAPCOLOR_WAYPOINTb )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTb);
+ uv1.x = 192.5f/256.0f; // blue cross
+ uv1.y = 240.5f/256.0f;
+ uv2.x = 207.0f/256.0f;
+ uv2.y = 255.0f/256.0f;
+ DrawIcon(pos, dim, uv1, uv2);
+ }
+ if ( color == MAPCOLOR_WAYPOINTr )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTb);
+ uv1.x = 208.5f/256.0f; // red cross
+ uv1.y = 240.5f/256.0f;
+ uv2.x = 223.0f/256.0f;
+ uv2.y = 255.0f/256.0f;
+ DrawIcon(pos, dim, uv1, uv2);
+ }
+ if ( color == MAPCOLOR_WAYPOINTg )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTb);
+ uv1.x = 224.5f/256.0f; // green cross
+ uv1.y = 240.5f/256.0f;
+ uv2.x = 239.0f/256.0f;
+ uv2.y = 255.0f/256.0f;
+ DrawIcon(pos, dim, uv1, uv2);
+ }
+ if ( color == MAPCOLOR_WAYPOINTy )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTb);
+ uv1.x = 240.5f/256.0f; // yellow cross
+ uv1.y = 240.5f/256.0f;
+ uv2.x = 255.0f/256.0f;
+ uv2.y = 255.0f/256.0f;
+ DrawIcon(pos, dim, uv1, uv2);
+ }
+ if ( color == MAPCOLOR_WAYPOINTv )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTb);
+ uv1.x = 192.5f/256.0f; // violet cross
+ uv1.y = 224.5f/256.0f;
+ uv2.x = 207.0f/256.0f;
+ uv2.y = 239.0f/256.0f;
+ DrawIcon(pos, dim, uv1, uv2);
+ }
+}
+
+// Draws the icon of an object.
+
+void CMap::DrawObjectIcon(Math::Point pos, Math::Point dim, MapColor color,
+ ObjectType type, bool bHilite)
+{
+ Math::Point ppos, ddim, uv1, uv2;
+ float dp;
+ int icon;
+
+ dp = 0.5f/256.0f;
+
+ m_engine->SetTexture("button3.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ if ( color == MAPCOLOR_MOVE )
+ {
+ uv1.x = 160.0f/256.0f; // blue
+ uv1.y = 224.0f/256.0f;
+ }
+ else if ( color == MAPCOLOR_ALIEN )
+ {
+ uv1.x = 224.0f/256.0f; // green
+ uv1.y = 224.0f/256.0f;
+ }
+ else
+ {
+ uv1.x = 192.0f/256.0f; // yellow
+ uv1.y = 224.0f/256.0f;
+ }
+ uv2.x = uv1.x+32.0f/256.0f;
+ uv2.y = uv1.y+32.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2); // background colors
+
+ if ( bHilite )
+ {
+ icon = -1;
+ if ( type == OBJECT_FACTORY ) icon = 32;
+ if ( type == OBJECT_DERRICK ) icon = 33;
+ if ( type == OBJECT_CONVERT ) icon = 34;
+ if ( type == OBJECT_RESEARCH ) icon = 35;
+ if ( type == OBJECT_STATION ) icon = 36;
+ if ( type == OBJECT_TOWER ) icon = 37;
+ if ( type == OBJECT_LABO ) icon = 38;
+ if ( type == OBJECT_ENERGY ) icon = 39;
+ if ( type == OBJECT_RADAR ) icon = 40;
+ if ( type == OBJECT_INFO ) icon = 44;
+ if ( type == OBJECT_REPAIR ) icon = 41;
+ if ( type == OBJECT_DESTROYER) icon = 41;
+ if ( type == OBJECT_NUCLEAR ) icon = 42;
+ if ( type == OBJECT_PARA ) icon = 46;
+ if ( type == OBJECT_SAFE ) icon = 47;
+ if ( type == OBJECT_HUSTON ) icon = 48;
+ if ( type == OBJECT_TARGET1 ) icon = 45;
+ if ( type == OBJECT_BASE ) icon = 43;
+ if ( type == OBJECT_HUMAN ) icon = 8;
+ if ( type == OBJECT_MOBILEfa ) icon = 11;
+ if ( type == OBJECT_MOBILEta ) icon = 10;
+ if ( type == OBJECT_MOBILEwa ) icon = 9;
+ if ( type == OBJECT_MOBILEia ) icon = 22;
+ if ( type == OBJECT_MOBILEfc ) icon = 17;
+ if ( type == OBJECT_MOBILEtc ) icon = 16;
+ if ( type == OBJECT_MOBILEwc ) icon = 15;
+ if ( type == OBJECT_MOBILEic ) icon = 23;
+ if ( type == OBJECT_MOBILEfi ) icon = 27;
+ if ( type == OBJECT_MOBILEti ) icon = 26;
+ if ( type == OBJECT_MOBILEwi ) icon = 25;
+ if ( type == OBJECT_MOBILEii ) icon = 28;
+ if ( type == OBJECT_MOBILEfs ) icon = 14;
+ if ( type == OBJECT_MOBILEts ) icon = 13;
+ if ( type == OBJECT_MOBILEws ) icon = 12;
+ if ( type == OBJECT_MOBILEis ) icon = 24;
+ if ( type == OBJECT_MOBILErt ) icon = 18;
+ if ( type == OBJECT_MOBILErc ) icon = 19;
+ if ( type == OBJECT_MOBILErr ) icon = 20;
+ if ( type == OBJECT_MOBILErs ) icon = 29;
+ if ( type == OBJECT_MOBILEsa ) icon = 21;
+ if ( type == OBJECT_MOBILEft ) icon = 30;
+ if ( type == OBJECT_MOBILEtt ) icon = 30;
+ if ( type == OBJECT_MOBILEwt ) icon = 30;
+ if ( type == OBJECT_MOBILEit ) icon = 30;
+ if ( type == OBJECT_MOBILEtg ) icon = 45;
+ if ( type == OBJECT_MOBILEdr ) icon = 48;
+ if ( type == OBJECT_APOLLO2 ) icon = 49;
+ if ( type == OBJECT_MOTHER ) icon = 31;
+ if ( type == OBJECT_ANT ) icon = 31;
+ if ( type == OBJECT_SPIDER ) icon = 31;
+ if ( type == OBJECT_BEE ) icon = 31;
+ if ( type == OBJECT_WORM ) icon = 31;
+ if ( type == OBJECT_TEEN28 ) icon = 48; // bottle
+ if ( type == OBJECT_TEEN34 ) icon = 48; // stone
+ if ( icon == -1 ) return;
+
+ m_engine->SetState(D3DSTATETTw);
+ uv1.x = (32.0f/256.0f)*(icon%8);
+ uv1.y = (32.0f/256.0f)*(icon/8);
+ uv2.x = uv1.x+32.0f/256.0f;
+ uv2.y = uv1.y+32.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2); // icon
+ }
+}
+
+// Draw the object with the mouse hovers over.
+
+void CMap::DrawHilite(Math::Point pos)
+{
+ Math::Point dim, uv1, uv2;
+ bool bOut, bUp, bDown, bLeft, bRight;
+
+ if ( m_bToy || m_fixImage[0] != 0 ) return; // map with still image?
+
+ pos.x = (pos.x-m_offset.x)*(m_zoom*0.5f)/m_half+0.5f;
+ pos.y = (pos.y-m_offset.y)*(m_zoom*0.5f)/m_half+0.5f;
+
+ bOut = bUp = bDown = bLeft = bRight = false;
+ if ( pos.x < 0.06f ) { pos.x = 0.02f; bOut = bLeft = true; }
+ if ( pos.y < 0.06f ) { pos.y = 0.02f; bOut = bDown = true; }
+ if ( pos.x > 0.94f ) { pos.x = 0.98f; bOut = bRight = true; }
+ if ( pos.y > 0.94f ) { pos.y = 0.98f; bOut = bUp = true; }
+
+ pos.x = m_mapPos.x+m_mapDim.x*pos.x;
+ pos.y = m_mapPos.y+m_mapDim.y*pos.y;
+ dim.x = 2.0f/128.0f*0.75f;
+ dim.y = 2.0f/128.0f;
+ dim.x *= 2.0f+cosf(m_time*8.0f)*0.5f;
+ dim.y *= 2.0f+cosf(m_time*8.0f)*0.5f;
+
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTb);
+ uv1.x = 160.5f/256.0f; // hilite
+ uv1.y = 224.5f/256.0f;
+ uv2.x = 175.0f/256.0f;
+ uv2.y = 239.0f/256.0f;
+ pos.x -= dim.x/2.0f;
+ pos.y -= dim.y/2.0f;
+ DrawIcon(pos, dim, uv1, uv2);
+}
+
+// Draws a triangular icon.
+
+void CMap::DrawTriangle(Math::Point p1, Math::Point p2, Math::Point p3, Math::Point uv1, Math::Point uv2)
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DVERTEX2 vertex[3]; // 1 triangle
+ Math::Vector n;
+
+ device = m_engine->RetD3DDevice();
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x,uv1.y);
+ vertex[1] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv1.x,uv2.y);
+ vertex[2] = D3DVERTEX2(Math::Vector(p3.x, p3.y, 0.0f), n, uv2.x,uv2.y);
+
+ device->DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_VERTEX2, vertex, 3, NULL);
+ m_engine->AddStatisticTriangle(1);
+}
+
+// Draw a pentagon icon (a 5 rating, what!).
+
+void CMap::DrawPenta(Math::Point p1, Math::Point p2, Math::Point p3, Math::Point p4, Math::Point p5, Math::Point uv1, Math::Point uv2)
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DVERTEX2 vertex[5]; // 1 pentagon
+ Math::Vector n;
+
+ device = m_engine->RetD3DDevice();
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+
+#if 1
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x,uv1.y);
+ vertex[1] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv1.x,uv2.y);
+ vertex[2] = D3DVERTEX2(Math::Vector(p5.x, p5.y, 0.0f), n, uv2.x,uv2.y);
+ vertex[3] = D3DVERTEX2(Math::Vector(p3.x, p3.y, 0.0f), n, uv2.x,uv2.y);
+ vertex[4] = D3DVERTEX2(Math::Vector(p4.x, p4.y, 0.0f), n, uv2.x,uv2.y);
+
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 5, NULL);
+#else
+ vertex[0] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv1.x,uv1.y);
+ vertex[1] = D3DVERTEX2(Math::Vector(p3.x, p3.y, 0.0f), n, uv1.x,uv2.y);
+ vertex[2] = D3DVERTEX2(Math::Vector(p4.x, p4.y, 0.0f), n, uv2.x,uv2.y);
+
+ device->DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_VERTEX2, vertex, 3, NULL);
+#endif
+ m_engine->AddStatisticTriangle(3);
+}
+
+// Draw the vertex array.
+
+void CMap::DrawVertex(Math::Point uv1, Math::Point uv2, float zoom)
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Point p1, p2, c;
+ Math::Vector n;
+
+ device = m_engine->RetD3DDevice();
+
+ p1.x = m_pos.x;
+ p1.y = m_pos.y;
+ p2.x = m_pos.x + m_dim.x;
+ p2.y = m_pos.y + m_dim.y;
+
+ c.x = (p1.x+p2.x)/2.0f;
+ c.y = (p1.y+p2.y)/2.0f; // center
+
+ p1.x = (p1.x-c.x)*zoom + c.x;
+ p1.y = (p1.y-c.y)*zoom + c.y;
+
+ p2.x = (p2.x-c.x)*zoom + c.x;
+ p2.y = (p2.y-c.y)*zoom + c.y;
+
+ m_mapPos = p1;
+ m_mapDim.x = p2.x-p1.x;
+ m_mapDim.y = p2.y-p1.y;
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, uv1.x,uv2.y);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, uv1.x,uv1.y);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, uv2.x,uv2.y);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, uv2.x,uv1.y);
+
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+}
+
+
+// Updates the field in the map.
+
+void CMap::UpdateTerrain()
+{
+ D3DCOLORVALUE color;
+ Math::Vector pos;
+ float scale, water, level, intensity;
+ int x, y;
+
+ if ( m_fixImage[0] != 0 ) return; // still image?
+ if ( !m_engine->OpenImage("map.tga") ) return;
+
+ scale = m_terrain->RetScaleRelief();
+ water = m_water->RetLevel();
+ color.a = 0.0f;
+
+ for ( y=0 ; y<256 ; y++ )
+ {
+ for ( x=0 ; x<256 ; x++ )
+ {
+ pos.x = ((float)x-128.0f)*m_half/128.0f;
+ pos.z = -((float)y-128.0f)*m_half/128.0f;
+ pos.y = 0.0f;
+
+ if ( pos.x >= -m_half && pos.x <= m_half &&
+ pos.z >= -m_half && pos.z <= m_half )
+ {
+ level = m_terrain->RetFloorLevel(pos, true)/scale;
+ }
+ else
+ {
+ level = 1000.0f;
+ }
+
+ intensity = level/256.0f;
+ if ( intensity < 0.0f ) intensity = 0.0f;
+ if ( intensity > 1.0f ) intensity = 1.0f;
+
+ if ( level >= water ) // on water?
+ {
+ color.r = m_floorColor.r + (intensity-0.5f);
+ color.g = m_floorColor.g + (intensity-0.5f);
+ color.b = m_floorColor.b + (intensity-0.5f);
+ }
+ else // underwater?
+ {
+ color.r = m_waterColor.r + (intensity-0.5f);
+ color.g = m_waterColor.g + (intensity-0.5f);
+ color.b = m_waterColor.b + (intensity-0.5f);
+ }
+
+ m_engine->SetDot(x, y, color);
+ }
+ }
+
+ m_engine->CopyImage(); // copy the ground drawing
+ m_engine->CloseImage();
+}
+
+// Updates the field in the map.
+
+void CMap::UpdateTerrain(int bx, int by, int ex, int ey)
+{
+ D3DCOLORVALUE color;
+ Math::Vector pos;
+ float scale, water, level, intensity;
+ int x, y;
+
+ if ( m_fixImage[0] != 0 ) return; // still image?
+ if ( !m_engine->OpenImage("map.tga") ) return;
+ m_engine->LoadImage();
+
+ scale = m_terrain->RetScaleRelief();
+ water = m_water->RetLevel();
+ color.a = 0.0f;
+
+ for ( y=by ; y<ey ; y++ )
+ {
+ for ( x=bx ; x<ex ; x++ )
+ {
+ pos.x = ((float)x-128.0f)*m_half/128.0f;
+ pos.z = -((float)y-128.0f)*m_half/128.0f;
+ pos.y = 0.0f;
+
+ if ( pos.x >= -m_half && pos.x <= m_half &&
+ pos.z >= -m_half && pos.z <= m_half )
+ {
+ level = m_terrain->RetFloorLevel(pos, true)/scale;
+ }
+ else
+ {
+ level = 1000.0f;
+ }
+
+ intensity = level/256.0f;
+ if ( intensity < 0.0f ) intensity = 0.0f;
+ if ( intensity > 1.0f ) intensity = 1.0f;
+
+ if ( level > water ) // on water?
+ {
+ color.r = m_floorColor.r + (intensity-0.5f);
+ color.g = m_floorColor.g + (intensity-0.5f);
+ color.b = m_floorColor.b + (intensity-0.5f);
+ }
+ else // underwater?
+ {
+ color.r = m_waterColor.r + (intensity-0.5f);
+ color.g = m_waterColor.g + (intensity-0.5f);
+ color.b = m_waterColor.b + (intensity-0.5f);
+ }
+
+ m_engine->SetDot(x, y, color);
+ }
+ }
+
+ m_engine->CopyImage(); // copy the ground drawing
+ m_engine->CloseImage();
+}
+
+
+// Empty all objects.
+
+void CMap::FlushObject()
+{
+ int i;
+
+ m_totalFix = 0; // object index fixed
+ m_totalMove = MAPMAXOBJECT-2; // moving vehicles index
+ m_bRadar = m_main->RetCheatRadar(); // no radar
+
+ for ( i=0 ; i<MAPMAXOBJECT ; i++ )
+ {
+ m_map[i].bUsed = false;
+ }
+}
+
+// Updates an object in the map.
+
+void CMap::UpdateObject(CObject* pObj)
+{
+ ObjectType type;
+ MapColor color;
+ Math::Vector pos;
+ Math::Point ppos;
+ float dir;
+
+ if ( !m_bEnable ) return;
+ if ( m_totalFix >= m_totalMove ) return; // full table?
+
+ if ( !pObj->RetActif() ) return;
+ if ( !pObj->RetSelectable() ) return;
+ if ( pObj->RetProxyActivate() ) return;
+ if ( pObj->RetTruck() != 0 ) return;
+
+ type = pObj->RetType();
+ pos = pObj->RetPosition(0);
+ dir = -(pObj->RetAngleY(0)+Math::PI/2.0f);
+
+ if ( m_angle != 0.0f )
+ {
+ ppos = RotatePoint(m_angle, Math::Point(pos.x, pos.z));
+ pos.x = ppos.x;
+ pos.z = ppos.y;
+ dir += m_angle;
+ }
+
+ if ( type == OBJECT_RADAR )
+ {
+ m_bRadar = true; // radar exists
+ }
+
+ color = MAPCOLOR_NULL;
+ if ( type == OBJECT_BASE )
+ {
+ color = MAPCOLOR_BASE;
+ }
+ if ( type == OBJECT_DERRICK ||
+ type == OBJECT_FACTORY ||
+ type == OBJECT_STATION ||
+ type == OBJECT_CONVERT ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_DESTROYER||
+ 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 ||
+ type == OBJECT_TARGET1 ||
+ type == OBJECT_START ||
+ type == OBJECT_END || // stationary object?
+ type == OBJECT_TEEN28 || // bottle?
+ type == OBJECT_TEEN34 ) // stone?
+ {
+ color = MAPCOLOR_FIX;
+ }
+ if ( type == OBJECT_BBOX ||
+ type == OBJECT_KEYa ||
+ type == OBJECT_KEYb ||
+ type == OBJECT_KEYc ||
+ type == OBJECT_KEYd )
+ {
+ color = MAPCOLOR_BBOX;
+ }
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr ||
+ type == OBJECT_APOLLO2 ) // moving vehicle?
+ {
+ color = MAPCOLOR_MOVE;
+ }
+ if ( type == OBJECT_ANT ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ||
+ type == OBJECT_SPIDER ) // mobile enemy?
+ {
+ color = MAPCOLOR_ALIEN;
+ }
+ if ( type == OBJECT_WAYPOINT ||
+ type == OBJECT_FLAGb )
+ {
+ color = MAPCOLOR_WAYPOINTb;
+ }
+ if ( type == OBJECT_FLAGr )
+ {
+ color = MAPCOLOR_WAYPOINTr;
+ }
+ if ( type == OBJECT_FLAGg )
+ {
+ color = MAPCOLOR_WAYPOINTg;
+ }
+ if ( type == OBJECT_FLAGy )
+ {
+ color = MAPCOLOR_WAYPOINTy;
+ }
+ if ( type == OBJECT_FLAGv )
+ {
+ color = MAPCOLOR_WAYPOINTv;
+ }
+
+ if ( color == MAPCOLOR_NULL ) return;
+
+ if ( m_fixImage[0] != 0 && !m_bDebug ) // map with still image?
+ {
+ if ( (type == OBJECT_TEEN28 ||
+ type == OBJECT_TEEN34 ) &&
+ m_mode == 0 ) return;
+
+ if ( type != OBJECT_TEEN28 &&
+ type != OBJECT_TEEN34 &&
+ color != MAPCOLOR_MOVE ) return;
+ }
+
+ if ( pObj->RetSelect() )
+ {
+ m_map[MAPMAXOBJECT-1].type = type;
+ m_map[MAPMAXOBJECT-1].object = pObj;
+ m_map[MAPMAXOBJECT-1].color = color;
+ m_map[MAPMAXOBJECT-1].pos.x = pos.x;
+ m_map[MAPMAXOBJECT-1].pos.y = pos.z;
+ m_map[MAPMAXOBJECT-1].dir = dir;
+ m_map[MAPMAXOBJECT-1].bUsed = true;
+ }
+ else
+ {
+ if ( color == MAPCOLOR_BASE ||
+ color == MAPCOLOR_FIX )
+ {
+ m_map[m_totalFix].type = type;
+ m_map[m_totalFix].object = pObj;
+ m_map[m_totalFix].color = color;
+ m_map[m_totalFix].pos.x = pos.x;
+ m_map[m_totalFix].pos.y = pos.z;
+ m_map[m_totalFix].dir = dir;
+ m_map[m_totalFix].bUsed = true;
+ m_totalFix ++;
+ }
+ else
+ {
+ m_map[m_totalMove].type = type;
+ m_map[m_totalMove].object = pObj;
+ m_map[m_totalMove].color = color;
+ m_map[m_totalMove].pos.x = pos.x;
+ m_map[m_totalMove].pos.y = pos.z;
+ m_map[m_totalMove].dir = dir;
+ m_map[m_totalMove].bUsed = true;
+ m_totalMove --;
+ }
+ }
+}
+
diff --git a/src/ui/map.h b/src/ui/map.h
index 9551d12..efdf54b 100644
--- a/src/ui/map.h
+++ b/src/ui/map.h
@@ -1,137 +1,137 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// map.h
-
-#pragma once
-
-
-#include "ui/control.h"
-#include "object/object.h"
-
-
-class CD3DEngine;
-class CTerrain;
-class CWater;
-class CRobotMain;
-
-
-
-const int MAPMAXOBJECT = 100;
-
-enum MapColor
-{
- MAPCOLOR_NULL,
- MAPCOLOR_BASE,
- MAPCOLOR_FIX,
- MAPCOLOR_MOVE,
- MAPCOLOR_ALIEN,
- MAPCOLOR_WAYPOINTb,
- MAPCOLOR_WAYPOINTr,
- MAPCOLOR_WAYPOINTg,
- MAPCOLOR_WAYPOINTy,
- MAPCOLOR_WAYPOINTv,
- MAPCOLOR_BBOX,
-};
-
-struct MapObject
-{
- char bUsed;
- CObject* object;
- MapColor color;
- ObjectType type;
- Math::Point pos;
- float dir;
-};
-
-
-
-class CMap : public CControl
-{
-public:
- CMap(CInstanceManager* iMan);
- ~CMap();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- bool EventProcess(const Event &event);
- void Draw();
-
- void UpdateTerrain();
- void UpdateTerrain(int bx, int by, int ex, int ey);
-
- void SetFixImage(char *filename);
- bool RetFixImage();
-
- void SetOffset(float ox, float oy);
- void SetAngle(float angle);
- void SetMode(int mode);
- void SetToy(bool bToy);
- void SetDebug(bool bDebug);
-
- void SetZoom(float value);
- float RetZoom();
-
- void SetEnable(bool bEnable);
- bool RetEnable();
-
- void SetFloorColor(D3DCOLORVALUE color);
- void SetWaterColor(D3DCOLORVALUE color);
-
- void FlushObject();
- void UpdateObject(CObject* pObj);
-
- CObject* DetectObject(Math::Point pos, bool &bInMap);
- void SetHilite(CObject* pObj);
-
-protected:
- Math::Point AdjustOffset(Math::Point offset);
- void SelectObject(Math::Point pos);
- Math::Point MapInter(Math::Point pos, float dir);
- void DrawFocus(Math::Point pos, float dir, ObjectType type, MapColor color);
- void DrawObject(Math::Point pos, float dir, ObjectType type, MapColor color, bool bSelect, bool bHilite);
- void DrawObjectIcon(Math::Point pos, Math::Point dim, MapColor color, ObjectType type, bool bHilite);
- void DrawHilite(Math::Point pos);
- void DrawTriangle(Math::Point p1, Math::Point p2, Math::Point p3, Math::Point uv1, Math::Point uv2);
- void DrawPenta(Math::Point p1, Math::Point p2, Math::Point p3, Math::Point p4, Math::Point p5, Math::Point uv1, Math::Point uv2);
- void DrawVertex(Math::Point uv1, Math::Point uv2, float zoom);
-
-protected:
- CTerrain* m_terrain;
- CWater* m_water;
- CRobotMain* m_main;
-
- bool m_bEnable;
- float m_time;
- float m_half;
- float m_zoom;
- Math::Point m_offset;
- float m_angle;
- D3DCOLORVALUE m_floorColor;
- D3DCOLORVALUE m_waterColor;
- MapObject m_map[MAPMAXOBJECT];
- int m_totalFix;
- int m_totalMove;
- int m_hiliteRank;
- Math::Point m_mapPos;
- Math::Point m_mapDim;
- bool m_bRadar;
- char m_fixImage[100];
- int m_mode;
- bool m_bToy;
- bool m_bDebug;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// map.h
+
+#pragma once
+
+
+#include "ui/control.h"
+#include "object/object.h"
+
+
+class CD3DEngine;
+class CTerrain;
+class CWater;
+class CRobotMain;
+
+
+
+const int MAPMAXOBJECT = 100;
+
+enum MapColor
+{
+ MAPCOLOR_NULL,
+ MAPCOLOR_BASE,
+ MAPCOLOR_FIX,
+ MAPCOLOR_MOVE,
+ MAPCOLOR_ALIEN,
+ MAPCOLOR_WAYPOINTb,
+ MAPCOLOR_WAYPOINTr,
+ MAPCOLOR_WAYPOINTg,
+ MAPCOLOR_WAYPOINTy,
+ MAPCOLOR_WAYPOINTv,
+ MAPCOLOR_BBOX,
+};
+
+struct MapObject
+{
+ char bUsed;
+ CObject* object;
+ MapColor color;
+ ObjectType type;
+ Math::Point pos;
+ float dir;
+};
+
+
+
+class CMap : public CControl
+{
+public:
+ CMap(CInstanceManager* iMan);
+ ~CMap();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ bool EventProcess(const Event &event);
+ void Draw();
+
+ void UpdateTerrain();
+ void UpdateTerrain(int bx, int by, int ex, int ey);
+
+ void SetFixImage(char *filename);
+ bool RetFixImage();
+
+ void SetOffset(float ox, float oy);
+ void SetAngle(float angle);
+ void SetMode(int mode);
+ void SetToy(bool bToy);
+ void SetDebug(bool bDebug);
+
+ void SetZoom(float value);
+ float RetZoom();
+
+ void SetEnable(bool bEnable);
+ bool RetEnable();
+
+ void SetFloorColor(D3DCOLORVALUE color);
+ void SetWaterColor(D3DCOLORVALUE color);
+
+ void FlushObject();
+ void UpdateObject(CObject* pObj);
+
+ CObject* DetectObject(Math::Point pos, bool &bInMap);
+ void SetHilite(CObject* pObj);
+
+protected:
+ Math::Point AdjustOffset(Math::Point offset);
+ void SelectObject(Math::Point pos);
+ Math::Point MapInter(Math::Point pos, float dir);
+ void DrawFocus(Math::Point pos, float dir, ObjectType type, MapColor color);
+ void DrawObject(Math::Point pos, float dir, ObjectType type, MapColor color, bool bSelect, bool bHilite);
+ void DrawObjectIcon(Math::Point pos, Math::Point dim, MapColor color, ObjectType type, bool bHilite);
+ void DrawHilite(Math::Point pos);
+ void DrawTriangle(Math::Point p1, Math::Point p2, Math::Point p3, Math::Point uv1, Math::Point uv2);
+ void DrawPenta(Math::Point p1, Math::Point p2, Math::Point p3, Math::Point p4, Math::Point p5, Math::Point uv1, Math::Point uv2);
+ void DrawVertex(Math::Point uv1, Math::Point uv2, float zoom);
+
+protected:
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CRobotMain* m_main;
+
+ bool m_bEnable;
+ float m_time;
+ float m_half;
+ float m_zoom;
+ Math::Point m_offset;
+ float m_angle;
+ D3DCOLORVALUE m_floorColor;
+ D3DCOLORVALUE m_waterColor;
+ MapObject m_map[MAPMAXOBJECT];
+ int m_totalFix;
+ int m_totalMove;
+ int m_hiliteRank;
+ Math::Point m_mapPos;
+ Math::Point m_mapDim;
+ bool m_bRadar;
+ char m_fixImage[100];
+ int m_mode;
+ bool m_bToy;
+ bool m_bDebug;
+};
+
+
diff --git a/src/ui/scroll.cpp b/src/ui/scroll.cpp
index 59b3fbd..051de8d 100644
--- a/src/ui/scroll.cpp
+++ b/src/ui/scroll.cpp
@@ -1,469 +1,469 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// scroll.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "ui/button.h"
-#include "ui/scroll.h"
-
-
-
-
-// Object's constructor.
-
-CScroll::CScroll(CInstanceManager* iMan) : CControl(iMan)
-{
- m_buttonUp = 0;
- m_buttonDown = 0;
-
- m_visibleValue = 0.0f;
- m_visibleRatio = 1.0f;
- m_step = 0.0f;
-
- m_eventUp = EVENT_NULL;
- m_eventDown = EVENT_NULL;
-
- m_bCapture = false;
-}
-
-// Object's destructor.
-
-CScroll::~CScroll()
-{
- delete m_buttonUp;
- delete m_buttonDown;
-}
-
-
-// Creates a new button.
-
-bool CScroll::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
- CControl::Create(pos, dim, icon, eventMsg);
-
- MoveAdjust();
- return true;
-}
-
-
-void CScroll::SetPos(Math::Point pos)
-{
- CControl::SetPos(pos);
- MoveAdjust();
-}
-
-void CScroll::SetDim(Math::Point dim)
-{
- CControl::SetDim(dim);
- MoveAdjust();
-}
-
-// Adjust both buttons.
-
-void CScroll::MoveAdjust()
-{
- CButton* pc;
- Math::Point pos, dim;
-
- if ( m_dim.y < m_dim.x*2.0f ) // very short lift?
- {
- delete m_buttonUp;
- m_buttonUp = 0;
-
- delete m_buttonDown;
- m_buttonDown = 0;
- }
- else
- {
- if ( m_buttonUp == 0 )
- {
- m_buttonUp = new CButton(m_iMan);
- pc = (CButton*)m_buttonUp;
- pc->Create(Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f), 49, EVENT_NULL);
- pc->SetRepeat(true);
- m_eventUp = pc->RetEventMsg();
- }
-
- if ( m_buttonDown == 0 )
- {
- m_buttonDown = new CButton(m_iMan);
- pc = (CButton*)m_buttonDown;
- pc->Create(Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f), 50, EVENT_NULL);
- pc->SetRepeat(true);
- m_eventDown = pc->RetEventMsg();
- }
- }
-
- if ( m_buttonUp != 0 )
- {
- pos.x = m_pos.x;
- pos.y = m_pos.y+m_dim.y-m_dim.x/0.75f;
- dim.x = m_dim.x;
- dim.y = m_dim.x/0.75f;
- m_buttonUp->SetPos(pos);
- m_buttonUp->SetDim(dim);
- }
-
- if ( m_buttonDown != 0 )
- {
- pos.x = m_pos.x;
- pos.y = m_pos.y;
- dim.x = m_dim.x;
- dim.y = m_dim.x/0.75f;
- m_buttonDown->SetPos(pos);
- m_buttonDown->SetDim(dim);
- }
-
- AdjustGlint();
-}
-
-// Adjusts the position of reflection.
-
-void CScroll::AdjustGlint()
-{
- Math::Point ref;
- float hButton, h;
-
- hButton = m_buttonUp?m_dim.x/0.75f:0.0f;
- h = m_dim.y-hButton*2.0f;
-
- ref.x = m_pos.x;
- ref.y = m_pos.y+hButton+h*m_visibleRatio+0.003f;
- ref.y += h*(1.0f-m_visibleRatio)*(1.0f-m_visibleValue);
-
- GlintCreate(ref);
-}
-
-
-
-bool CScroll::SetState(int state, bool bState)
-{
- if ( state & STATE_ENABLE )
- {
- if ( m_buttonUp != 0 ) m_buttonUp->SetState(state, bState);
- if ( m_buttonDown != 0 ) m_buttonDown->SetState(state, bState);
- }
-
- return CControl::SetState(state, bState);
-}
-
-bool CScroll::SetState(int state)
-{
- if ( state & STATE_ENABLE )
- {
- if ( m_buttonUp != 0 ) m_buttonUp->SetState(state);
- if ( m_buttonDown != 0 ) m_buttonDown->SetState(state);
- }
-
- return CControl::SetState(state);
-}
-
-bool CScroll::ClearState(int state)
-{
- if ( state & STATE_ENABLE )
- {
- if ( m_buttonUp != 0 ) m_buttonUp->ClearState(state);
- if ( m_buttonDown != 0 ) m_buttonDown->ClearState(state);
- }
-
- return CControl::ClearState(state);
-}
-
-
-// Management of an event.
-
-bool CScroll::EventProcess(const Event &event)
-{
- Math::Point pos, dim;
- float hButton, h, value;
-
- CControl::EventProcess(event);
-
- if ( m_buttonUp != 0 && !m_bCapture )
- {
- if ( !m_buttonUp->EventProcess(event) ) return false;
- }
- if ( m_buttonDown != 0 && !m_bCapture )
- {
- if ( !m_buttonDown->EventProcess(event) ) return false;
- }
-
- if ( event.event == m_eventUp && m_step > 0.0f )
- {
- m_visibleValue -= m_step;
- if ( m_visibleValue < 0.0f ) m_visibleValue = 0.0f;
- AdjustGlint();
-
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- }
-
- if ( event.event == m_eventDown && m_step > 0.0f )
- {
- m_visibleValue += m_step;
- if ( m_visibleValue > 1.0f ) m_visibleValue = 1.0f;
- AdjustGlint();
-
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- }
-
- hButton = m_buttonUp?m_dim.x/0.75f:0.0f;
-
- if ( event.event == EVENT_LBUTTONDOWN &&
- (m_state & STATE_VISIBLE) &&
- (m_state & STATE_ENABLE) )
- {
- if ( CControl::Detect(event.pos) )
- {
- pos.y = m_pos.y+hButton;
- dim.y = m_dim.y-hButton*2.0f;
- pos.y += dim.y*(1.0f-m_visibleRatio)*(1.0f-m_visibleValue);
- dim.y *= m_visibleRatio;
- if ( event.pos.y < pos.y ||
- event.pos.y > pos.y+dim.y ) // click outside cabin?
- {
- h = (m_dim.y-hButton*2.0f)*(1.0f-m_visibleRatio);
- value = 1.0f-(event.pos.y-(m_pos.y+hButton+dim.y*0.5f))/h;
- if ( value < 0.0f ) value = 0.0f;
- if ( value > 1.0f ) value = 1.0f;
- m_visibleValue = value;
- AdjustGlint();
-
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- }
- m_bCapture = true;
- m_pressPos = event.pos;
- m_pressValue = m_visibleValue;
- }
- }
-
- if ( event.event == EVENT_MOUSEMOVE && m_bCapture )
- {
- h = (m_dim.y-hButton*2.0f)*(1.0f-m_visibleRatio);
- if ( h != 0 )
- {
- value = m_pressValue - (event.pos.y-m_pressPos.y)/h;
- if ( value < 0.0f ) value = 0.0f;
- if ( value > 1.0f ) value = 1.0f;
-
- if ( value != m_visibleValue )
- {
- m_visibleValue = value;
- AdjustGlint();
-
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- }
- }
- }
-
- if ( event.event == EVENT_LBUTTONUP && m_bCapture )
- {
- m_bCapture = false;
- }
-
- if ( event.event == EVENT_KEYDOWN &&
- event.param == VK_WHEELUP &&
- Detect(event.pos) &&
- m_buttonUp != 0 )
- {
- Event newEvent = event;
- newEvent.event = m_buttonUp->RetEventMsg();
- m_event->AddEvent(newEvent);
- }
- if ( event.event == EVENT_KEYDOWN &&
- event.param == VK_WHEELDOWN &&
- Detect(event.pos) &&
- m_buttonDown != 0 )
- {
- Event newEvent = event;
- newEvent.event = m_buttonDown->RetEventMsg();
- m_event->AddEvent(newEvent);
- }
-
- return true;
-}
-
-
-// Draws the button.
-
-void CScroll::Draw()
-{
- Math::Point pos, dim, ppos, ddim;
- float hButton;
- int icon, n, i;
-
- hButton = m_buttonUp?m_dim.x/0.75f:0.0f;
-
- // Draws the bottom.
- pos.x = m_pos.x;
- pos.y = m_pos.y+hButton;
- dim.x = m_dim.x;
- dim.y = m_dim.y-hButton*2.0f;
- if ( m_state & STATE_ENABLE ) icon = 0;
- else icon = 1;
- DrawVertex(pos, dim, icon);
-
- // Draws the cabin.
- if ( m_visibleRatio < 1.0f && (m_state & STATE_ENABLE) )
- {
- pos.x += 0.003f; // ch'tite(?) margin
- pos.y += 0.003f;
- dim.x -= 0.006f;
- dim.y -= 0.006f;
- pos.y += dim.y*(1.0f-m_visibleRatio)*(1.0f-m_visibleValue);
- dim.y *= m_visibleRatio;
- DrawVertex(pos, dim, 2);
-
- n = (int)(dim.y*0.8f/0.012f);
- if ( n < 1 ) n = 1;
- if ( n > 5 ) n = 5;
-
- ppos.x = pos.x+0.003f;
- ppos.y = pos.y+(dim.y-(n-1)*0.012f-0.008f)/2.0f;
- ddim.x = dim.x-0.006f;
- ddim.y = 0.008f;
- for ( i=0 ; i<n ; i++ )
- {
- DrawVertex(ppos, ddim, 3); // horizontal bar
- ppos.y += 0.012f;
- }
- }
-
- if ( m_buttonUp != 0 )
- {
- m_buttonUp->Draw();
- }
- if ( m_buttonDown != 0 )
- {
- m_buttonDown->Draw();
- }
-}
-
-// Draws a rectangle.
-
-void CScroll::DrawVertex(Math::Point pos, Math::Point dim, int icon)
-{
- Math::Point uv1, uv2;
- float ex, dp;
-
- if ( icon == 0 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 0.0f/256.0f; // yellow rectangle
- uv1.y = 32.0f/256.0f;
- uv2.x = 32.0f/256.0f;
- uv2.y = 64.0f/256.0f;
- ex = 8.0f/256.0f;
- }
- else if ( icon == 1 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 128.0f/256.0f; // gray rectangle
- uv1.y = 32.0f/256.0f;
- uv2.x = 160.0f/256.0f;
- uv2.y = 64.0f/256.0f;
- ex = 8.0f/256.0f;
- }
- else if ( icon == 2 )
- {
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 64.0f/256.0f; // blue rectangle
- uv1.y = 0.0f/256.0f;
- uv2.x = 96.0f/256.0f;
- uv2.y = 32.0f/256.0f;
- ex = 8.0f/256.0f;
- }
- else
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 104.0f/256.0f; // blue line -
- uv1.y = 32.0f/256.0f;
- uv2.x = 128.0f/256.0f;
- uv2.y = 40.0f/256.0f;
- ex = 0.0f;
- }
-
- dp = 0.5f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- DrawIcon(pos, dim, uv1, uv2, ex);
-}
-
-
-void CScroll::SetVisibleValue(float value)
-{
- if ( value < 0.0 ) value = 0.0f;
- if ( value > 1.0 ) value = 1.0f;
- m_visibleValue = value;
- AdjustGlint();
-}
-
-float CScroll::RetVisibleValue()
-{
- return m_visibleValue;
-}
-
-
-void CScroll::SetVisibleRatio(float value)
-{
- if ( value < 0.1 ) value = 0.1f;
- if ( value > 1.0 ) value = 1.0f;
- m_visibleRatio = value;
- AdjustGlint();
-}
-
-float CScroll::RetVisibleRatio()
-{
- return m_visibleRatio;
-}
-
-
-void CScroll::SetArrowStep(float step)
-{
- m_step = step;
-}
-
-float CScroll::RetArrowStep()
-{
- return m_step;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// scroll.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "ui/button.h"
+#include "ui/scroll.h"
+
+
+
+
+// Object's constructor.
+
+CScroll::CScroll(CInstanceManager* iMan) : CControl(iMan)
+{
+ m_buttonUp = 0;
+ m_buttonDown = 0;
+
+ m_visibleValue = 0.0f;
+ m_visibleRatio = 1.0f;
+ m_step = 0.0f;
+
+ m_eventUp = EVENT_NULL;
+ m_eventDown = EVENT_NULL;
+
+ m_bCapture = false;
+}
+
+// Object's destructor.
+
+CScroll::~CScroll()
+{
+ delete m_buttonUp;
+ delete m_buttonDown;
+}
+
+
+// Creates a new button.
+
+bool CScroll::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+ CControl::Create(pos, dim, icon, eventMsg);
+
+ MoveAdjust();
+ return true;
+}
+
+
+void CScroll::SetPos(Math::Point pos)
+{
+ CControl::SetPos(pos);
+ MoveAdjust();
+}
+
+void CScroll::SetDim(Math::Point dim)
+{
+ CControl::SetDim(dim);
+ MoveAdjust();
+}
+
+// Adjust both buttons.
+
+void CScroll::MoveAdjust()
+{
+ CButton* pc;
+ Math::Point pos, dim;
+
+ if ( m_dim.y < m_dim.x*2.0f ) // very short lift?
+ {
+ delete m_buttonUp;
+ m_buttonUp = 0;
+
+ delete m_buttonDown;
+ m_buttonDown = 0;
+ }
+ else
+ {
+ if ( m_buttonUp == 0 )
+ {
+ m_buttonUp = new CButton(m_iMan);
+ pc = (CButton*)m_buttonUp;
+ pc->Create(Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f), 49, EVENT_NULL);
+ pc->SetRepeat(true);
+ m_eventUp = pc->RetEventMsg();
+ }
+
+ if ( m_buttonDown == 0 )
+ {
+ m_buttonDown = new CButton(m_iMan);
+ pc = (CButton*)m_buttonDown;
+ pc->Create(Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f), 50, EVENT_NULL);
+ pc->SetRepeat(true);
+ m_eventDown = pc->RetEventMsg();
+ }
+ }
+
+ if ( m_buttonUp != 0 )
+ {
+ pos.x = m_pos.x;
+ pos.y = m_pos.y+m_dim.y-m_dim.x/0.75f;
+ dim.x = m_dim.x;
+ dim.y = m_dim.x/0.75f;
+ m_buttonUp->SetPos(pos);
+ m_buttonUp->SetDim(dim);
+ }
+
+ if ( m_buttonDown != 0 )
+ {
+ pos.x = m_pos.x;
+ pos.y = m_pos.y;
+ dim.x = m_dim.x;
+ dim.y = m_dim.x/0.75f;
+ m_buttonDown->SetPos(pos);
+ m_buttonDown->SetDim(dim);
+ }
+
+ AdjustGlint();
+}
+
+// Adjusts the position of reflection.
+
+void CScroll::AdjustGlint()
+{
+ Math::Point ref;
+ float hButton, h;
+
+ hButton = m_buttonUp?m_dim.x/0.75f:0.0f;
+ h = m_dim.y-hButton*2.0f;
+
+ ref.x = m_pos.x;
+ ref.y = m_pos.y+hButton+h*m_visibleRatio+0.003f;
+ ref.y += h*(1.0f-m_visibleRatio)*(1.0f-m_visibleValue);
+
+ GlintCreate(ref);
+}
+
+
+
+bool CScroll::SetState(int state, bool bState)
+{
+ if ( state & STATE_ENABLE )
+ {
+ if ( m_buttonUp != 0 ) m_buttonUp->SetState(state, bState);
+ if ( m_buttonDown != 0 ) m_buttonDown->SetState(state, bState);
+ }
+
+ return CControl::SetState(state, bState);
+}
+
+bool CScroll::SetState(int state)
+{
+ if ( state & STATE_ENABLE )
+ {
+ if ( m_buttonUp != 0 ) m_buttonUp->SetState(state);
+ if ( m_buttonDown != 0 ) m_buttonDown->SetState(state);
+ }
+
+ return CControl::SetState(state);
+}
+
+bool CScroll::ClearState(int state)
+{
+ if ( state & STATE_ENABLE )
+ {
+ if ( m_buttonUp != 0 ) m_buttonUp->ClearState(state);
+ if ( m_buttonDown != 0 ) m_buttonDown->ClearState(state);
+ }
+
+ return CControl::ClearState(state);
+}
+
+
+// Management of an event.
+
+bool CScroll::EventProcess(const Event &event)
+{
+ Math::Point pos, dim;
+ float hButton, h, value;
+
+ CControl::EventProcess(event);
+
+ if ( m_buttonUp != 0 && !m_bCapture )
+ {
+ if ( !m_buttonUp->EventProcess(event) ) return false;
+ }
+ if ( m_buttonDown != 0 && !m_bCapture )
+ {
+ if ( !m_buttonDown->EventProcess(event) ) return false;
+ }
+
+ if ( event.event == m_eventUp && m_step > 0.0f )
+ {
+ m_visibleValue -= m_step;
+ if ( m_visibleValue < 0.0f ) m_visibleValue = 0.0f;
+ AdjustGlint();
+
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ }
+
+ if ( event.event == m_eventDown && m_step > 0.0f )
+ {
+ m_visibleValue += m_step;
+ if ( m_visibleValue > 1.0f ) m_visibleValue = 1.0f;
+ AdjustGlint();
+
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ }
+
+ hButton = m_buttonUp?m_dim.x/0.75f:0.0f;
+
+ if ( event.event == EVENT_LBUTTONDOWN &&
+ (m_state & STATE_VISIBLE) &&
+ (m_state & STATE_ENABLE) )
+ {
+ if ( CControl::Detect(event.pos) )
+ {
+ pos.y = m_pos.y+hButton;
+ dim.y = m_dim.y-hButton*2.0f;
+ pos.y += dim.y*(1.0f-m_visibleRatio)*(1.0f-m_visibleValue);
+ dim.y *= m_visibleRatio;
+ if ( event.pos.y < pos.y ||
+ event.pos.y > pos.y+dim.y ) // click outside cabin?
+ {
+ h = (m_dim.y-hButton*2.0f)*(1.0f-m_visibleRatio);
+ value = 1.0f-(event.pos.y-(m_pos.y+hButton+dim.y*0.5f))/h;
+ if ( value < 0.0f ) value = 0.0f;
+ if ( value > 1.0f ) value = 1.0f;
+ m_visibleValue = value;
+ AdjustGlint();
+
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ }
+ m_bCapture = true;
+ m_pressPos = event.pos;
+ m_pressValue = m_visibleValue;
+ }
+ }
+
+ if ( event.event == EVENT_MOUSEMOVE && m_bCapture )
+ {
+ h = (m_dim.y-hButton*2.0f)*(1.0f-m_visibleRatio);
+ if ( h != 0 )
+ {
+ value = m_pressValue - (event.pos.y-m_pressPos.y)/h;
+ if ( value < 0.0f ) value = 0.0f;
+ if ( value > 1.0f ) value = 1.0f;
+
+ if ( value != m_visibleValue )
+ {
+ m_visibleValue = value;
+ AdjustGlint();
+
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ }
+ }
+ }
+
+ if ( event.event == EVENT_LBUTTONUP && m_bCapture )
+ {
+ m_bCapture = false;
+ }
+
+ if ( event.event == EVENT_KEYDOWN &&
+ event.param == VK_WHEELUP &&
+ Detect(event.pos) &&
+ m_buttonUp != 0 )
+ {
+ Event newEvent = event;
+ newEvent.event = m_buttonUp->RetEventMsg();
+ m_event->AddEvent(newEvent);
+ }
+ if ( event.event == EVENT_KEYDOWN &&
+ event.param == VK_WHEELDOWN &&
+ Detect(event.pos) &&
+ m_buttonDown != 0 )
+ {
+ Event newEvent = event;
+ newEvent.event = m_buttonDown->RetEventMsg();
+ m_event->AddEvent(newEvent);
+ }
+
+ return true;
+}
+
+
+// Draws the button.
+
+void CScroll::Draw()
+{
+ Math::Point pos, dim, ppos, ddim;
+ float hButton;
+ int icon, n, i;
+
+ hButton = m_buttonUp?m_dim.x/0.75f:0.0f;
+
+ // Draws the bottom.
+ pos.x = m_pos.x;
+ pos.y = m_pos.y+hButton;
+ dim.x = m_dim.x;
+ dim.y = m_dim.y-hButton*2.0f;
+ if ( m_state & STATE_ENABLE ) icon = 0;
+ else icon = 1;
+ DrawVertex(pos, dim, icon);
+
+ // Draws the cabin.
+ if ( m_visibleRatio < 1.0f && (m_state & STATE_ENABLE) )
+ {
+ pos.x += 0.003f; // ch'tite(?) margin
+ pos.y += 0.003f;
+ dim.x -= 0.006f;
+ dim.y -= 0.006f;
+ pos.y += dim.y*(1.0f-m_visibleRatio)*(1.0f-m_visibleValue);
+ dim.y *= m_visibleRatio;
+ DrawVertex(pos, dim, 2);
+
+ n = (int)(dim.y*0.8f/0.012f);
+ if ( n < 1 ) n = 1;
+ if ( n > 5 ) n = 5;
+
+ ppos.x = pos.x+0.003f;
+ ppos.y = pos.y+(dim.y-(n-1)*0.012f-0.008f)/2.0f;
+ ddim.x = dim.x-0.006f;
+ ddim.y = 0.008f;
+ for ( i=0 ; i<n ; i++ )
+ {
+ DrawVertex(ppos, ddim, 3); // horizontal bar
+ ppos.y += 0.012f;
+ }
+ }
+
+ if ( m_buttonUp != 0 )
+ {
+ m_buttonUp->Draw();
+ }
+ if ( m_buttonDown != 0 )
+ {
+ m_buttonDown->Draw();
+ }
+}
+
+// Draws a rectangle.
+
+void CScroll::DrawVertex(Math::Point pos, Math::Point dim, int icon)
+{
+ Math::Point uv1, uv2;
+ float ex, dp;
+
+ if ( icon == 0 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 0.0f/256.0f; // yellow rectangle
+ uv1.y = 32.0f/256.0f;
+ uv2.x = 32.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+ ex = 8.0f/256.0f;
+ }
+ else if ( icon == 1 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 128.0f/256.0f; // gray rectangle
+ uv1.y = 32.0f/256.0f;
+ uv2.x = 160.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+ ex = 8.0f/256.0f;
+ }
+ else if ( icon == 2 )
+ {
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 64.0f/256.0f; // blue rectangle
+ uv1.y = 0.0f/256.0f;
+ uv2.x = 96.0f/256.0f;
+ uv2.y = 32.0f/256.0f;
+ ex = 8.0f/256.0f;
+ }
+ else
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 104.0f/256.0f; // blue line -
+ uv1.y = 32.0f/256.0f;
+ uv2.x = 128.0f/256.0f;
+ uv2.y = 40.0f/256.0f;
+ ex = 0.0f;
+ }
+
+ dp = 0.5f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+
+ DrawIcon(pos, dim, uv1, uv2, ex);
+}
+
+
+void CScroll::SetVisibleValue(float value)
+{
+ if ( value < 0.0 ) value = 0.0f;
+ if ( value > 1.0 ) value = 1.0f;
+ m_visibleValue = value;
+ AdjustGlint();
+}
+
+float CScroll::RetVisibleValue()
+{
+ return m_visibleValue;
+}
+
+
+void CScroll::SetVisibleRatio(float value)
+{
+ if ( value < 0.1 ) value = 0.1f;
+ if ( value > 1.0 ) value = 1.0f;
+ m_visibleRatio = value;
+ AdjustGlint();
+}
+
+float CScroll::RetVisibleRatio()
+{
+ return m_visibleRatio;
+}
+
+
+void CScroll::SetArrowStep(float step)
+{
+ m_step = step;
+}
+
+float CScroll::RetArrowStep()
+{
+ return m_step;
+}
+
diff --git a/src/ui/scroll.h b/src/ui/scroll.h
index 26b8d9b..6854e61 100644
--- a/src/ui/scroll.h
+++ b/src/ui/scroll.h
@@ -1,81 +1,81 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// scroll.h
-
-#pragma once
-
-
-#include "ui/control.h"
-
-
-class CD3DEngine;
-class CButton;
-
-
-const float SCROLL_WIDTH = (15.0f/640.0f);
-
-
-
-class CScroll : public CControl
-{
-public:
- CScroll(CInstanceManager* iMan);
- ~CScroll();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
-
- void SetPos(Math::Point pos);
- void SetDim(Math::Point dim);
-
- bool SetState(int state, bool bState);
- bool SetState(int state);
- bool ClearState(int state);
-
- bool EventProcess(const Event &event);
- void Draw();
-
- void SetVisibleValue(float value);
- float RetVisibleValue();
-
- void SetVisibleRatio(float value);
- float RetVisibleRatio();
-
- void SetArrowStep(float step);
- float RetArrowStep();
-
-protected:
- void MoveAdjust();
- void AdjustGlint();
- void DrawVertex(Math::Point pos, Math::Point dim, int icon);
-
-protected:
- CButton* m_buttonUp;
- CButton* m_buttonDown;
-
- float m_visibleValue;
- float m_visibleRatio;
- float m_step;
-
- bool m_bCapture;
- Math::Point m_pressPos;
- float m_pressValue;
-
- EventMsg m_eventUp;
- EventMsg m_eventDown;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// scroll.h
+
+#pragma once
+
+
+#include "ui/control.h"
+
+
+class CD3DEngine;
+class CButton;
+
+
+const float SCROLL_WIDTH = (15.0f/640.0f);
+
+
+
+class CScroll : public CControl
+{
+public:
+ CScroll(CInstanceManager* iMan);
+ ~CScroll();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+
+ void SetPos(Math::Point pos);
+ void SetDim(Math::Point dim);
+
+ bool SetState(int state, bool bState);
+ bool SetState(int state);
+ bool ClearState(int state);
+
+ bool EventProcess(const Event &event);
+ void Draw();
+
+ void SetVisibleValue(float value);
+ float RetVisibleValue();
+
+ void SetVisibleRatio(float value);
+ float RetVisibleRatio();
+
+ void SetArrowStep(float step);
+ float RetArrowStep();
+
+protected:
+ void MoveAdjust();
+ void AdjustGlint();
+ void DrawVertex(Math::Point pos, Math::Point dim, int icon);
+
+protected:
+ CButton* m_buttonUp;
+ CButton* m_buttonDown;
+
+ float m_visibleValue;
+ float m_visibleRatio;
+ float m_step;
+
+ bool m_bCapture;
+ Math::Point m_pressPos;
+ float m_pressValue;
+
+ EventMsg m_eventUp;
+ EventMsg m_eventDown;
+};
+
+
diff --git a/src/ui/shortcut.cpp b/src/ui/shortcut.cpp
index 1a5fc41..fe9ca9b 100644
--- a/src/ui/shortcut.cpp
+++ b/src/ui/shortcut.cpp
@@ -1,241 +1,241 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// shortcut.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "ui/shortcut.h"
-
-
-
-
-// Object's constructor.
-
-CShortcut::CShortcut(CInstanceManager* iMan) : CControl(iMan)
-{
- m_time = 0.0f;
-}
-
-// Object's destructor.
-
-CShortcut::~CShortcut()
-{
-}
-
-
-// Creates a new button.
-
-bool CShortcut::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- CControl::Create(pos, dim, icon, eventMsg);
- return true;
-}
-
-
-// Management of an event.
-
-bool CShortcut::EventProcess(const Event &event)
-{
- CControl::EventProcess(event);
-
- if ( event.event == EVENT_FRAME )
- {
- m_time += event.rTime;
- }
-
- if ( event.event == EVENT_LBUTTONDOWN )
- {
- if ( CControl::Detect(event.pos) )
- {
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- return false;
- }
- }
-
- return true;
-}
-
-
-// Draws the button.
-
-void CShortcut::Draw()
-{
- float zoom;
- int icon, mode;
-
- icon = 0;
- zoom = 0.8f;
- mode = D3DSTATETTw;
- if ( m_state & STATE_HILIGHT )
- {
- icon = 4;
- zoom = 0.9f;
- mode = D3DSTATENORMAL;
- }
- if ( m_state & STATE_CHECK )
- {
- icon = 1;
- zoom = 0.8f;
- mode = D3DSTATENORMAL;
- }
- if ( m_state & STATE_PRESS )
- {
- icon = 1;
- zoom = 1.0f;
- mode = D3DSTATENORMAL;
- }
- if ( m_icon == 6 || m_icon == 7 ) // pause or film?
- {
- icon = -1; // no bottom
- zoom = 1.0f;
- }
-
- m_engine->SetTexture("button3.tga");
-
- if ( icon != -1 )
- {
- m_engine->SetState(mode);
- DrawVertex(icon, 0.95f);
- }
-
- m_engine->SetState(D3DSTATETTb);
- DrawVertex(m_icon, zoom);
-
- if ( m_state & STATE_FRAME )
- {
- Math::Point p1, p2, c, uv1, uv2;
- float zoom, dp;
-
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTw);
-
- zoom = 0.9f+sinf(m_time*8.0f)*0.1f;
-
- p1.x = m_pos.x;
- p1.y = m_pos.y;
- p2.x = m_pos.x + m_dim.x;
- p2.y = m_pos.y + m_dim.y;
-
- c.x = (p1.x+p2.x)/2.0f;
- c.y = (p1.y+p2.y)/2.0f; // center
-
- p1.x = (p1.x-c.x)*zoom + c.x;
- p1.y = (p1.y-c.y)*zoom + c.y;
- p2.x = (p2.x-c.x)*zoom + c.x;
- p2.y = (p2.y-c.y)*zoom + c.y;
-
- p2.x -= p1.x;
- p2.y -= p1.y;
-
- uv1.x = 176.0f/256.0f;
- uv1.y = 224.0f/256.0f;
- uv2.x = 192.0f/256.0f;
- uv2.y = 240.0f/256.0f;
-
- dp = 0.5f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- DrawIcon(p1, p2, uv1, uv2);
- }
-
- if ( (m_state & STATE_RUN) && Math::Mod(m_time, 0.7f) >= 0.3f )
- {
- Math::Point uv1, uv2;
- float dp;
-
- m_engine->SetTexture("button3.tga");
- m_engine->SetState(D3DSTATETTw);
-
- uv1.x = 160.0f/256.0f;
- uv1.y = 0.0f/256.0f;
- uv2.x = 192.0f/256.0f;
- uv2.y = 32.0f/256.0f;
-
- dp = 0.5f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- DrawIcon(m_pos, m_dim, uv1, uv2);
- }
-}
-
-// Draw the vertex array.
-
-void CShortcut::DrawVertex(int icon, float zoom)
-{
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Point p1, p2, c;
- Math::Vector n;
- float u1, u2, v1, v2, dp;
-
- device = m_engine->RetD3DDevice();
-
- p1.x = m_pos.x;
- p1.y = m_pos.y;
- p2.x = m_pos.x + m_dim.x;
- p2.y = m_pos.y + m_dim.y;
-
- c.x = (p1.x+p2.x)/2.0f;
- c.y = (p1.y+p2.y)/2.0f; // center
-
- p1.x = (p1.x-c.x)*zoom + c.x;
- p1.y = (p1.y-c.y)*zoom + c.y;
-
- p2.x = (p2.x-c.x)*zoom + c.x;
- p2.y = (p2.y-c.y)*zoom + c.y;
-
- u1 = (32.0f/256.0f)*(icon%8);
- v1 = (32.0f/256.0f)*(icon/8); // u-v texture
- u2 = (32.0f/256.0f)+u1;
- v2 = (32.0f/256.0f)+v1;
-
- dp = 0.5f/256.0f;
- u1 += dp;
- v1 += dp;
- u2 -= dp;
- v2 -= dp;
-
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
-
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// shortcut.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "ui/shortcut.h"
+
+
+
+
+// Object's constructor.
+
+CShortcut::CShortcut(CInstanceManager* iMan) : CControl(iMan)
+{
+ m_time = 0.0f;
+}
+
+// Object's destructor.
+
+CShortcut::~CShortcut()
+{
+}
+
+
+// Creates a new button.
+
+bool CShortcut::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ CControl::Create(pos, dim, icon, eventMsg);
+ return true;
+}
+
+
+// Management of an event.
+
+bool CShortcut::EventProcess(const Event &event)
+{
+ CControl::EventProcess(event);
+
+ if ( event.event == EVENT_FRAME )
+ {
+ m_time += event.rTime;
+ }
+
+ if ( event.event == EVENT_LBUTTONDOWN )
+ {
+ if ( CControl::Detect(event.pos) )
+ {
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+// Draws the button.
+
+void CShortcut::Draw()
+{
+ float zoom;
+ int icon, mode;
+
+ icon = 0;
+ zoom = 0.8f;
+ mode = D3DSTATETTw;
+ if ( m_state & STATE_HILIGHT )
+ {
+ icon = 4;
+ zoom = 0.9f;
+ mode = D3DSTATENORMAL;
+ }
+ if ( m_state & STATE_CHECK )
+ {
+ icon = 1;
+ zoom = 0.8f;
+ mode = D3DSTATENORMAL;
+ }
+ if ( m_state & STATE_PRESS )
+ {
+ icon = 1;
+ zoom = 1.0f;
+ mode = D3DSTATENORMAL;
+ }
+ if ( m_icon == 6 || m_icon == 7 ) // pause or film?
+ {
+ icon = -1; // no bottom
+ zoom = 1.0f;
+ }
+
+ m_engine->SetTexture("button3.tga");
+
+ if ( icon != -1 )
+ {
+ m_engine->SetState(mode);
+ DrawVertex(icon, 0.95f);
+ }
+
+ m_engine->SetState(D3DSTATETTb);
+ DrawVertex(m_icon, zoom);
+
+ if ( m_state & STATE_FRAME )
+ {
+ Math::Point p1, p2, c, uv1, uv2;
+ float zoom, dp;
+
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTw);
+
+ zoom = 0.9f+sinf(m_time*8.0f)*0.1f;
+
+ p1.x = m_pos.x;
+ p1.y = m_pos.y;
+ p2.x = m_pos.x + m_dim.x;
+ p2.y = m_pos.y + m_dim.y;
+
+ c.x = (p1.x+p2.x)/2.0f;
+ c.y = (p1.y+p2.y)/2.0f; // center
+
+ p1.x = (p1.x-c.x)*zoom + c.x;
+ p1.y = (p1.y-c.y)*zoom + c.y;
+ p2.x = (p2.x-c.x)*zoom + c.x;
+ p2.y = (p2.y-c.y)*zoom + c.y;
+
+ p2.x -= p1.x;
+ p2.y -= p1.y;
+
+ uv1.x = 176.0f/256.0f;
+ uv1.y = 224.0f/256.0f;
+ uv2.x = 192.0f/256.0f;
+ uv2.y = 240.0f/256.0f;
+
+ dp = 0.5f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+
+ DrawIcon(p1, p2, uv1, uv2);
+ }
+
+ if ( (m_state & STATE_RUN) && Math::Mod(m_time, 0.7f) >= 0.3f )
+ {
+ Math::Point uv1, uv2;
+ float dp;
+
+ m_engine->SetTexture("button3.tga");
+ m_engine->SetState(D3DSTATETTw);
+
+ uv1.x = 160.0f/256.0f;
+ uv1.y = 0.0f/256.0f;
+ uv2.x = 192.0f/256.0f;
+ uv2.y = 32.0f/256.0f;
+
+ dp = 0.5f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+
+ DrawIcon(m_pos, m_dim, uv1, uv2);
+ }
+}
+
+// Draw the vertex array.
+
+void CShortcut::DrawVertex(int icon, float zoom)
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Point p1, p2, c;
+ Math::Vector n;
+ float u1, u2, v1, v2, dp;
+
+ device = m_engine->RetD3DDevice();
+
+ p1.x = m_pos.x;
+ p1.y = m_pos.y;
+ p2.x = m_pos.x + m_dim.x;
+ p2.y = m_pos.y + m_dim.y;
+
+ c.x = (p1.x+p2.x)/2.0f;
+ c.y = (p1.y+p2.y)/2.0f; // center
+
+ p1.x = (p1.x-c.x)*zoom + c.x;
+ p1.y = (p1.y-c.y)*zoom + c.y;
+
+ p2.x = (p2.x-c.x)*zoom + c.x;
+ p2.y = (p2.y-c.y)*zoom + c.y;
+
+ u1 = (32.0f/256.0f)*(icon%8);
+ v1 = (32.0f/256.0f)*(icon/8); // u-v texture
+ u2 = (32.0f/256.0f)+u1;
+ v2 = (32.0f/256.0f)+v1;
+
+ dp = 0.5f/256.0f;
+ u1 += dp;
+ v1 += dp;
+ u2 -= dp;
+ v2 -= dp;
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
+
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+}
+
diff --git a/src/ui/shortcut.h b/src/ui/shortcut.h
index 528afd2..b918ccc 100644
--- a/src/ui/shortcut.h
+++ b/src/ui/shortcut.h
@@ -1,48 +1,48 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// shortcut.h
-
-#pragma once
-
-
-#include "ui/control.h"
-
-
-class CD3DEngine;
-
-
-
-class CShortcut : public CControl
-{
-public:
- CShortcut(CInstanceManager* iMan);
- ~CShortcut();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
-
- bool EventProcess(const Event &event);
-
- void Draw();
-
-protected:
- void DrawVertex(int icon, float zoom);
-
-protected:
- float m_time;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// shortcut.h
+
+#pragma once
+
+
+#include "ui/control.h"
+
+
+class CD3DEngine;
+
+
+
+class CShortcut : public CControl
+{
+public:
+ CShortcut(CInstanceManager* iMan);
+ ~CShortcut();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+
+ bool EventProcess(const Event &event);
+
+ void Draw();
+
+protected:
+ void DrawVertex(int icon, float zoom);
+
+protected:
+ float m_time;
+};
+
+
diff --git a/src/ui/slider.cpp b/src/ui/slider.cpp
index d332ff4..be8af18 100644
--- a/src/ui/slider.cpp
+++ b/src/ui/slider.cpp
@@ -1,580 +1,580 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// slider.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/text.h"
-#include "ui/button.h"
-#include "ui/slider.h"
-
-
-
-const float CURSOR_WIDTH = (10.0f/640.0f);
-const float HOLE_WIDTH = (5.0f/480.0f);
-
-
-
-
-// Object's constructor.
-
-CSlider::CSlider(CInstanceManager* iMan) : CControl(iMan)
-{
- m_buttonLeft = 0;
- m_buttonRight = 0;
-
- m_min = 0.0f;
- m_max = 1.0f;
- m_visibleValue = 0.0f;
- m_step = 0.0f;
-
- m_marginButton = 0.0f;
- m_bHoriz = false;
-
- m_eventUp = EVENT_NULL;
- m_eventDown = EVENT_NULL;
-
- m_bCapture = false;
-}
-
-// Object's destructor.
-
-CSlider::~CSlider()
-{
- delete m_buttonLeft;
- delete m_buttonRight;
-}
-
-
-// Creates a new button.
-
-bool CSlider::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
- CControl::Create(pos, dim, icon, eventMsg);
-
- MoveAdjust();
- return true;
-}
-
-
-void CSlider::SetPos(Math::Point pos)
-{
- CControl::SetPos(pos);
- MoveAdjust();
-}
-
-void CSlider::SetDim(Math::Point dim)
-{
- CControl::SetDim(dim);
- MoveAdjust();
-}
-
-void CSlider::MoveAdjust()
-{
- Math::Point pos, dim;
-
- m_bHoriz = ( m_dim.x > m_dim.y );
-
- if ( ( m_bHoriz && m_dim.x < m_dim.y*4.0f) ||
- (!m_bHoriz && m_dim.y < m_dim.x*4.0f) ) // very short slider?
- {
- delete m_buttonLeft;
- m_buttonLeft = 0;
-
- delete m_buttonRight;
- m_buttonRight = 0;
-
- m_marginButton = 0.0f;
- }
- else
- {
-#if 1
- if ( m_buttonLeft == 0 )
- {
- m_buttonLeft = new CButton(m_iMan);
- m_buttonLeft->Create(Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f), m_bHoriz?55:49, EVENT_NULL); // </^
- m_buttonLeft->SetRepeat(true);
- if ( m_state & STATE_SHADOW ) m_buttonLeft->SetState(STATE_SHADOW);
- m_eventUp = m_buttonLeft->RetEventMsg();
- }
-
- if ( m_buttonRight == 0 )
- {
- m_buttonRight = new CButton(m_iMan);
- m_buttonRight->Create(Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f), m_bHoriz?48:50, EVENT_NULL); // >/v
- m_buttonRight->SetRepeat(true);
- if ( m_state & STATE_SHADOW ) m_buttonRight->SetState(STATE_SHADOW);
- m_eventDown = m_buttonRight->RetEventMsg();
- }
-
- m_marginButton = m_bHoriz?(m_dim.y*0.75f):(m_dim.x/0.75f);
-#endif
- }
-
- if ( m_buttonLeft != 0 )
- {
- if ( m_bHoriz )
- {
- pos.x = m_pos.x;
- pos.y = m_pos.y;
- dim.x = m_dim.y*0.75f;
- dim.y = m_dim.y;
- }
- else
- {
- pos.x = m_pos.x;
- pos.y = m_pos.y+m_dim.y-m_dim.x/0.75f;
- dim.x = m_dim.x;
- dim.y = m_dim.x/0.75f;
- }
- m_buttonLeft->SetPos(pos);
- m_buttonLeft->SetDim(dim);
- }
-
- if ( m_buttonRight != 0 )
- {
- if ( m_bHoriz )
- {
- pos.x = m_pos.x+m_dim.x-m_dim.y*0.75f;
- pos.y = m_pos.y;
- dim.x = m_dim.y*0.75f;
- dim.y = m_dim.y;
- }
- else
- {
- pos.x = m_pos.x;
- pos.y = m_pos.y;
- dim.x = m_dim.x;
- dim.y = m_dim.x/0.75f;
- }
- m_buttonRight->SetPos(pos);
- m_buttonRight->SetDim(dim);
- }
-
- AdjustGlint();
-}
-
-// Adjusts the position of reflection.
-
-void CSlider::AdjustGlint()
-{
- Math::Point ref;
- float w;
-
- if ( m_bHoriz )
- {
- w = m_dim.x-m_marginButton*0.75f;
- ref.x = m_pos.x+m_marginButton;
- ref.x += (w-CURSOR_WIDTH)*m_visibleValue;
- ref.y = m_pos.y+m_dim.y;
- }
- else
- {
- w = m_dim.y-m_marginButton*2.0f;
- ref.y = m_pos.y+m_marginButton+CURSOR_WIDTH;
- ref.y += (w-CURSOR_WIDTH)*m_visibleValue;
- ref.x = m_pos.x;
- }
-
- GlintCreate(ref);
-}
-
-
-bool CSlider::SetState(int state, bool bState)
-{
- if ( (state & STATE_ENABLE) ||
- (state & STATE_SHADOW) )
- {
- if ( m_buttonLeft != 0 ) m_buttonLeft->SetState(state, bState);
- if ( m_buttonRight != 0 ) m_buttonRight->SetState(state, bState);
- }
-
- return CControl::SetState(state, bState);
-}
-
-bool CSlider::SetState(int state)
-{
- if ( (state & STATE_ENABLE) ||
- (state & STATE_SHADOW) )
- {
- if ( m_buttonLeft != 0 ) m_buttonLeft->SetState(state);
- if ( m_buttonRight != 0 ) m_buttonRight->SetState(state);
- }
-
- return CControl::SetState(state);
-}
-
-bool CSlider::ClearState(int state)
-{
- if ( (state & STATE_ENABLE) ||
- (state & STATE_SHADOW) )
- {
- if ( m_buttonLeft != 0 ) m_buttonLeft->ClearState(state);
- if ( m_buttonRight != 0 ) m_buttonRight->ClearState(state);
- }
-
- return CControl::ClearState(state);
-}
-
-
-// Management of an event.
-
-bool CSlider::EventProcess(const Event &event)
-{
- Math::Point pos, dim;
- float value;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return true;
-
- CControl::EventProcess(event);
-
- if ( m_buttonLeft != 0 && !m_bCapture )
- {
- if ( !m_buttonLeft->EventProcess(event) ) return false;
- }
- if ( m_buttonRight != 0 && !m_bCapture )
- {
- if ( !m_buttonRight->EventProcess(event) ) return false;
- }
-
- if ( event.event == m_eventUp && m_step > 0.0f )
- {
- m_visibleValue -= m_bHoriz?m_step:-m_step;
- if ( m_visibleValue < 0.0f ) m_visibleValue = 0.0f;
- if ( m_visibleValue > 1.0f ) m_visibleValue = 1.0f;
- AdjustGlint();
-
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- }
-
- if ( event.event == m_eventDown && m_step > 0.0f )
- {
- m_visibleValue += m_bHoriz?m_step:-m_step;
- if ( m_visibleValue < 0.0f ) m_visibleValue = 0.0f;
- if ( m_visibleValue > 1.0f ) m_visibleValue = 1.0f;
- AdjustGlint();
-
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- }
-
- if ( event.event == EVENT_LBUTTONDOWN &&
- (m_state & STATE_VISIBLE) &&
- (m_state & STATE_ENABLE) )
- {
- if ( CControl::Detect(event.pos) )
- {
- if ( m_bHoriz )
- {
- pos.x = m_pos.x+m_marginButton;
- dim.x = m_dim.x-m_marginButton*2.0f;
- value = (event.pos.x-pos.x-CURSOR_WIDTH/2.0f);
- value /= (dim.x-CURSOR_WIDTH);
- }
- else
- {
- pos.y = m_pos.y+m_marginButton;
- dim.y = m_dim.y-m_marginButton*2.0f;
- value = (event.pos.y-pos.y-CURSOR_WIDTH/2.0f);
- value /= (dim.y-CURSOR_WIDTH);
- }
- if ( value < 0.0f ) value = 0.0f;
- if ( value > 1.0f ) value = 1.0f;
- m_visibleValue = value;
- AdjustGlint();
-
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
-
- m_bCapture = true;
- m_pressPos = event.pos;
- m_pressValue = m_visibleValue;
- }
- }
-
- if ( event.event == EVENT_MOUSEMOVE && m_bCapture )
- {
- if ( m_bHoriz )
- {
- pos.x = m_pos.x+m_marginButton;
- dim.x = m_dim.x-m_marginButton*2.0f;
- value = (event.pos.x-pos.x-CURSOR_WIDTH/2.0f);
- value /= (dim.x-CURSOR_WIDTH);
- }
- else
- {
- pos.y = m_pos.y+m_marginButton;
- dim.y = m_dim.y-m_marginButton*2.0f;
- value = (event.pos.y-pos.y-CURSOR_WIDTH/2.0f);
- value /= (dim.y-CURSOR_WIDTH);
- }
- if ( value < 0.0f ) value = 0.0f;
- if ( value > 1.0f ) value = 1.0f;
-
- if ( value != m_visibleValue )
- {
- m_visibleValue = value;
- AdjustGlint();
-
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- }
- }
-
- if ( event.event == EVENT_LBUTTONUP && m_bCapture )
- {
- m_bCapture = false;
- }
-
- if ( event.event == EVENT_KEYDOWN &&
- event.param == VK_WHEELUP &&
- Detect(event.pos) &&
- m_buttonLeft != 0 )
- {
- Event newEvent = event;
- newEvent.event = m_buttonLeft->RetEventMsg();
- m_event->AddEvent(newEvent);
- }
- if ( event.event == EVENT_KEYDOWN &&
- event.param == VK_WHEELDOWN &&
- Detect(event.pos) &&
- m_buttonRight != 0 )
- {
- Event newEvent = event;
- newEvent.event = m_buttonRight->RetEventMsg();
- m_event->AddEvent(newEvent);
- }
-
- return true;
-}
-
-
-// Draws button.
-
-void CSlider::Draw()
-{
- Math::Point pos, dim, ppos, ddim, spos;
- int icon;
- float h;
- char text[100];
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return;
-
- if ( m_buttonLeft != 0 )
- {
- m_buttonLeft->Draw();
- }
-
- if ( m_bHoriz )
- {
- pos.x = m_pos.x+m_marginButton;
- pos.y = m_pos.y;
- dim.x = m_dim.x-m_marginButton*2.0f;
- dim.y = m_dim.y;
- }
- else
- {
- pos.x = m_pos.x;
- pos.y = m_pos.y+m_marginButton;
- dim.x = m_dim.x;
- dim.y = m_dim.y-m_marginButton*2.0f;
- }
-
- // Draws the bottom.
- if ( m_bHoriz )
- {
- ppos.x = pos.x + CURSOR_WIDTH/2.0f;
- ppos.y = pos.y + (dim.y-HOLE_WIDTH)/2.0f;
- ddim.x = dim.x - CURSOR_WIDTH;
- ddim.y = HOLE_WIDTH;
- }
- else
- {
- ppos.x = pos.x + (dim.x-HOLE_WIDTH*0.75f)/2.0f;
- ppos.y = pos.y + CURSOR_WIDTH/2.0f;
- ddim.x = HOLE_WIDTH*0.75f;
- ddim.y = dim.y - CURSOR_WIDTH;
- }
-
- if ( m_state & STATE_SHADOW )
- {
- spos = ppos;
- spos.x -= 0.005f*0.75f;
- spos.y += 0.005f;
- DrawShadow(spos, ddim);
- }
-
- if ( m_state & STATE_ENABLE ) icon = 0;
- else icon = 1;
- DrawVertex(ppos, ddim, icon);
-
- // Draws the cabin.
- if ( m_state & STATE_ENABLE )
- {
- if ( m_bHoriz )
- {
- ppos.x = pos.x + (dim.x-CURSOR_WIDTH)*m_visibleValue;
- ppos.y = pos.y;
- ddim.x = CURSOR_WIDTH;
- ddim.y = dim.y;
- }
- else
- {
- ppos.x = pos.x;
- ppos.y = pos.y + (dim.y-CURSOR_WIDTH)*m_visibleValue;
- ddim.x = dim.x;
- ddim.y = CURSOR_WIDTH;
- }
- DrawShadow(ppos, ddim, 0.7f);
- DrawVertex(ppos, ddim, 2);
- }
-
- if ( m_buttonRight != 0 )
- {
- m_buttonRight->Draw();
- }
-
- if ( m_bHoriz )
- {
- sprintf(text, "%d", (int)(m_min+m_visibleValue*(m_max-m_min)));
- h = m_engine->RetText()->RetHeight(m_fontSize, m_fontType);
- pos.x = m_pos.x+m_dim.x+(10.0f/640.0f);
- pos.y = m_pos.y+(m_dim.y-h)/2.0f;
- m_engine->RetText()->DrawText(text, pos, m_dim.x, 1, m_fontSize, m_fontStretch, m_fontType, 0);
- }
- else
- {
- if ( m_state & STATE_VALUE )
- {
- pos.x = m_pos.x+m_dim.x+4.0f/640.0f;
- h = m_dim.y-m_marginButton*2.0f;
- pos.y = m_pos.y+m_marginButton-4.0f/480.0f;
- pos.y += (h-CURSOR_WIDTH)*m_visibleValue;
- dim.x = 50.0f/640.0f;
- dim.y = 16.0f/480.0f;
- sprintf(text, "%d", (int)(m_min+(m_visibleValue*(m_max-m_min))));
- m_engine->RetText()->DrawText(text, pos, dim.x, 1, m_fontSize, m_fontStretch, m_fontType, 0);
- }
- }
-}
-
-// Draws a rectangle.
-
-void CSlider::DrawVertex(Math::Point pos, Math::Point dim, int icon)
-{
- Math::Point uv1, uv2, corner;
- float ex, dp;
-
- if ( icon == 0 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 0.0f/256.0f; // yellow rectangle
- uv1.y = 32.0f/256.0f;
- uv2.x = 32.0f/256.0f;
- uv2.y = 64.0f/256.0f;
- corner.x = 2.0f/640.0f;
- corner.y = 2.0f/480.0f;
- ex = 4.0f/256.0f;
- }
- else if ( icon == 1 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 128.0f/256.0f; // gray rectangle
- uv1.y = 32.0f/256.0f;
- uv2.x = 160.0f/256.0f;
- uv2.y = 64.0f/256.0f;
- corner.x = 2.0f/640.0f;
- corner.y = 2.0f/480.0f;
- ex = 4.0f/256.0f;
- }
- else
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 224.0f/256.0f; // cursor
- uv1.y = 32.0f/256.0f;
- uv2.x = 256.0f/256.0f;
- uv2.y = 64.0f/256.0f;
- if ( !m_bHoriz )
- {
- uv1.y += 64.0f/256.0f;
- uv2.y += 64.0f/256.0f;
- }
- corner.x = 2.0f/640.0f;
- corner.y = 2.0f/480.0f;
- ex = 4.0f/256.0f;
- }
-
- dp = 0.5f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- DrawIcon(pos, dim, uv1, uv2, corner, ex);
-}
-
-
-void CSlider::SetLimit(float min, float max)
-{
- m_min = min;
- m_max = max;
-}
-
-void CSlider::SetVisibleValue(float value)
-{
- value = (value-m_min)/(m_max-m_min);
- if ( value < 0.0 ) value = 0.0f;
- if ( value > 1.0 ) value = 1.0f;
- m_visibleValue = value;
- AdjustGlint();
-}
-
-float CSlider::RetVisibleValue()
-{
- return m_min+m_visibleValue*(m_max-m_min);
-}
-
-
-void CSlider::SetArrowStep(float step)
-{
- m_step = step/(m_max-m_min);
-}
-
-float CSlider::RetArrowStep()
-{
- return m_step*(m_max-m_min);
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// slider.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/text.h"
+#include "ui/button.h"
+#include "ui/slider.h"
+
+
+
+const float CURSOR_WIDTH = (10.0f/640.0f);
+const float HOLE_WIDTH = (5.0f/480.0f);
+
+
+
+
+// Object's constructor.
+
+CSlider::CSlider(CInstanceManager* iMan) : CControl(iMan)
+{
+ m_buttonLeft = 0;
+ m_buttonRight = 0;
+
+ m_min = 0.0f;
+ m_max = 1.0f;
+ m_visibleValue = 0.0f;
+ m_step = 0.0f;
+
+ m_marginButton = 0.0f;
+ m_bHoriz = false;
+
+ m_eventUp = EVENT_NULL;
+ m_eventDown = EVENT_NULL;
+
+ m_bCapture = false;
+}
+
+// Object's destructor.
+
+CSlider::~CSlider()
+{
+ delete m_buttonLeft;
+ delete m_buttonRight;
+}
+
+
+// Creates a new button.
+
+bool CSlider::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+ CControl::Create(pos, dim, icon, eventMsg);
+
+ MoveAdjust();
+ return true;
+}
+
+
+void CSlider::SetPos(Math::Point pos)
+{
+ CControl::SetPos(pos);
+ MoveAdjust();
+}
+
+void CSlider::SetDim(Math::Point dim)
+{
+ CControl::SetDim(dim);
+ MoveAdjust();
+}
+
+void CSlider::MoveAdjust()
+{
+ Math::Point pos, dim;
+
+ m_bHoriz = ( m_dim.x > m_dim.y );
+
+ if ( ( m_bHoriz && m_dim.x < m_dim.y*4.0f) ||
+ (!m_bHoriz && m_dim.y < m_dim.x*4.0f) ) // very short slider?
+ {
+ delete m_buttonLeft;
+ m_buttonLeft = 0;
+
+ delete m_buttonRight;
+ m_buttonRight = 0;
+
+ m_marginButton = 0.0f;
+ }
+ else
+ {
+#if 1
+ if ( m_buttonLeft == 0 )
+ {
+ m_buttonLeft = new CButton(m_iMan);
+ m_buttonLeft->Create(Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f), m_bHoriz?55:49, EVENT_NULL); // </^
+ m_buttonLeft->SetRepeat(true);
+ if ( m_state & STATE_SHADOW ) m_buttonLeft->SetState(STATE_SHADOW);
+ m_eventUp = m_buttonLeft->RetEventMsg();
+ }
+
+ if ( m_buttonRight == 0 )
+ {
+ m_buttonRight = new CButton(m_iMan);
+ m_buttonRight->Create(Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f), m_bHoriz?48:50, EVENT_NULL); // >/v
+ m_buttonRight->SetRepeat(true);
+ if ( m_state & STATE_SHADOW ) m_buttonRight->SetState(STATE_SHADOW);
+ m_eventDown = m_buttonRight->RetEventMsg();
+ }
+
+ m_marginButton = m_bHoriz?(m_dim.y*0.75f):(m_dim.x/0.75f);
+#endif
+ }
+
+ if ( m_buttonLeft != 0 )
+ {
+ if ( m_bHoriz )
+ {
+ pos.x = m_pos.x;
+ pos.y = m_pos.y;
+ dim.x = m_dim.y*0.75f;
+ dim.y = m_dim.y;
+ }
+ else
+ {
+ pos.x = m_pos.x;
+ pos.y = m_pos.y+m_dim.y-m_dim.x/0.75f;
+ dim.x = m_dim.x;
+ dim.y = m_dim.x/0.75f;
+ }
+ m_buttonLeft->SetPos(pos);
+ m_buttonLeft->SetDim(dim);
+ }
+
+ if ( m_buttonRight != 0 )
+ {
+ if ( m_bHoriz )
+ {
+ pos.x = m_pos.x+m_dim.x-m_dim.y*0.75f;
+ pos.y = m_pos.y;
+ dim.x = m_dim.y*0.75f;
+ dim.y = m_dim.y;
+ }
+ else
+ {
+ pos.x = m_pos.x;
+ pos.y = m_pos.y;
+ dim.x = m_dim.x;
+ dim.y = m_dim.x/0.75f;
+ }
+ m_buttonRight->SetPos(pos);
+ m_buttonRight->SetDim(dim);
+ }
+
+ AdjustGlint();
+}
+
+// Adjusts the position of reflection.
+
+void CSlider::AdjustGlint()
+{
+ Math::Point ref;
+ float w;
+
+ if ( m_bHoriz )
+ {
+ w = m_dim.x-m_marginButton*0.75f;
+ ref.x = m_pos.x+m_marginButton;
+ ref.x += (w-CURSOR_WIDTH)*m_visibleValue;
+ ref.y = m_pos.y+m_dim.y;
+ }
+ else
+ {
+ w = m_dim.y-m_marginButton*2.0f;
+ ref.y = m_pos.y+m_marginButton+CURSOR_WIDTH;
+ ref.y += (w-CURSOR_WIDTH)*m_visibleValue;
+ ref.x = m_pos.x;
+ }
+
+ GlintCreate(ref);
+}
+
+
+bool CSlider::SetState(int state, bool bState)
+{
+ if ( (state & STATE_ENABLE) ||
+ (state & STATE_SHADOW) )
+ {
+ if ( m_buttonLeft != 0 ) m_buttonLeft->SetState(state, bState);
+ if ( m_buttonRight != 0 ) m_buttonRight->SetState(state, bState);
+ }
+
+ return CControl::SetState(state, bState);
+}
+
+bool CSlider::SetState(int state)
+{
+ if ( (state & STATE_ENABLE) ||
+ (state & STATE_SHADOW) )
+ {
+ if ( m_buttonLeft != 0 ) m_buttonLeft->SetState(state);
+ if ( m_buttonRight != 0 ) m_buttonRight->SetState(state);
+ }
+
+ return CControl::SetState(state);
+}
+
+bool CSlider::ClearState(int state)
+{
+ if ( (state & STATE_ENABLE) ||
+ (state & STATE_SHADOW) )
+ {
+ if ( m_buttonLeft != 0 ) m_buttonLeft->ClearState(state);
+ if ( m_buttonRight != 0 ) m_buttonRight->ClearState(state);
+ }
+
+ return CControl::ClearState(state);
+}
+
+
+// Management of an event.
+
+bool CSlider::EventProcess(const Event &event)
+{
+ Math::Point pos, dim;
+ float value;
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return true;
+
+ CControl::EventProcess(event);
+
+ if ( m_buttonLeft != 0 && !m_bCapture )
+ {
+ if ( !m_buttonLeft->EventProcess(event) ) return false;
+ }
+ if ( m_buttonRight != 0 && !m_bCapture )
+ {
+ if ( !m_buttonRight->EventProcess(event) ) return false;
+ }
+
+ if ( event.event == m_eventUp && m_step > 0.0f )
+ {
+ m_visibleValue -= m_bHoriz?m_step:-m_step;
+ if ( m_visibleValue < 0.0f ) m_visibleValue = 0.0f;
+ if ( m_visibleValue > 1.0f ) m_visibleValue = 1.0f;
+ AdjustGlint();
+
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ }
+
+ if ( event.event == m_eventDown && m_step > 0.0f )
+ {
+ m_visibleValue += m_bHoriz?m_step:-m_step;
+ if ( m_visibleValue < 0.0f ) m_visibleValue = 0.0f;
+ if ( m_visibleValue > 1.0f ) m_visibleValue = 1.0f;
+ AdjustGlint();
+
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ }
+
+ if ( event.event == EVENT_LBUTTONDOWN &&
+ (m_state & STATE_VISIBLE) &&
+ (m_state & STATE_ENABLE) )
+ {
+ if ( CControl::Detect(event.pos) )
+ {
+ if ( m_bHoriz )
+ {
+ pos.x = m_pos.x+m_marginButton;
+ dim.x = m_dim.x-m_marginButton*2.0f;
+ value = (event.pos.x-pos.x-CURSOR_WIDTH/2.0f);
+ value /= (dim.x-CURSOR_WIDTH);
+ }
+ else
+ {
+ pos.y = m_pos.y+m_marginButton;
+ dim.y = m_dim.y-m_marginButton*2.0f;
+ value = (event.pos.y-pos.y-CURSOR_WIDTH/2.0f);
+ value /= (dim.y-CURSOR_WIDTH);
+ }
+ if ( value < 0.0f ) value = 0.0f;
+ if ( value > 1.0f ) value = 1.0f;
+ m_visibleValue = value;
+ AdjustGlint();
+
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+
+ m_bCapture = true;
+ m_pressPos = event.pos;
+ m_pressValue = m_visibleValue;
+ }
+ }
+
+ if ( event.event == EVENT_MOUSEMOVE && m_bCapture )
+ {
+ if ( m_bHoriz )
+ {
+ pos.x = m_pos.x+m_marginButton;
+ dim.x = m_dim.x-m_marginButton*2.0f;
+ value = (event.pos.x-pos.x-CURSOR_WIDTH/2.0f);
+ value /= (dim.x-CURSOR_WIDTH);
+ }
+ else
+ {
+ pos.y = m_pos.y+m_marginButton;
+ dim.y = m_dim.y-m_marginButton*2.0f;
+ value = (event.pos.y-pos.y-CURSOR_WIDTH/2.0f);
+ value /= (dim.y-CURSOR_WIDTH);
+ }
+ if ( value < 0.0f ) value = 0.0f;
+ if ( value > 1.0f ) value = 1.0f;
+
+ if ( value != m_visibleValue )
+ {
+ m_visibleValue = value;
+ AdjustGlint();
+
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ }
+ }
+
+ if ( event.event == EVENT_LBUTTONUP && m_bCapture )
+ {
+ m_bCapture = false;
+ }
+
+ if ( event.event == EVENT_KEYDOWN &&
+ event.param == VK_WHEELUP &&
+ Detect(event.pos) &&
+ m_buttonLeft != 0 )
+ {
+ Event newEvent = event;
+ newEvent.event = m_buttonLeft->RetEventMsg();
+ m_event->AddEvent(newEvent);
+ }
+ if ( event.event == EVENT_KEYDOWN &&
+ event.param == VK_WHEELDOWN &&
+ Detect(event.pos) &&
+ m_buttonRight != 0 )
+ {
+ Event newEvent = event;
+ newEvent.event = m_buttonRight->RetEventMsg();
+ m_event->AddEvent(newEvent);
+ }
+
+ return true;
+}
+
+
+// Draws button.
+
+void CSlider::Draw()
+{
+ Math::Point pos, dim, ppos, ddim, spos;
+ int icon;
+ float h;
+ char text[100];
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return;
+
+ if ( m_buttonLeft != 0 )
+ {
+ m_buttonLeft->Draw();
+ }
+
+ if ( m_bHoriz )
+ {
+ pos.x = m_pos.x+m_marginButton;
+ pos.y = m_pos.y;
+ dim.x = m_dim.x-m_marginButton*2.0f;
+ dim.y = m_dim.y;
+ }
+ else
+ {
+ pos.x = m_pos.x;
+ pos.y = m_pos.y+m_marginButton;
+ dim.x = m_dim.x;
+ dim.y = m_dim.y-m_marginButton*2.0f;
+ }
+
+ // Draws the bottom.
+ if ( m_bHoriz )
+ {
+ ppos.x = pos.x + CURSOR_WIDTH/2.0f;
+ ppos.y = pos.y + (dim.y-HOLE_WIDTH)/2.0f;
+ ddim.x = dim.x - CURSOR_WIDTH;
+ ddim.y = HOLE_WIDTH;
+ }
+ else
+ {
+ ppos.x = pos.x + (dim.x-HOLE_WIDTH*0.75f)/2.0f;
+ ppos.y = pos.y + CURSOR_WIDTH/2.0f;
+ ddim.x = HOLE_WIDTH*0.75f;
+ ddim.y = dim.y - CURSOR_WIDTH;
+ }
+
+ if ( m_state & STATE_SHADOW )
+ {
+ spos = ppos;
+ spos.x -= 0.005f*0.75f;
+ spos.y += 0.005f;
+ DrawShadow(spos, ddim);
+ }
+
+ if ( m_state & STATE_ENABLE ) icon = 0;
+ else icon = 1;
+ DrawVertex(ppos, ddim, icon);
+
+ // Draws the cabin.
+ if ( m_state & STATE_ENABLE )
+ {
+ if ( m_bHoriz )
+ {
+ ppos.x = pos.x + (dim.x-CURSOR_WIDTH)*m_visibleValue;
+ ppos.y = pos.y;
+ ddim.x = CURSOR_WIDTH;
+ ddim.y = dim.y;
+ }
+ else
+ {
+ ppos.x = pos.x;
+ ppos.y = pos.y + (dim.y-CURSOR_WIDTH)*m_visibleValue;
+ ddim.x = dim.x;
+ ddim.y = CURSOR_WIDTH;
+ }
+ DrawShadow(ppos, ddim, 0.7f);
+ DrawVertex(ppos, ddim, 2);
+ }
+
+ if ( m_buttonRight != 0 )
+ {
+ m_buttonRight->Draw();
+ }
+
+ if ( m_bHoriz )
+ {
+ sprintf(text, "%d", (int)(m_min+m_visibleValue*(m_max-m_min)));
+ h = m_engine->RetText()->RetHeight(m_fontSize, m_fontType);
+ pos.x = m_pos.x+m_dim.x+(10.0f/640.0f);
+ pos.y = m_pos.y+(m_dim.y-h)/2.0f;
+ m_engine->RetText()->DrawText(text, pos, m_dim.x, 1, m_fontSize, m_fontStretch, m_fontType, 0);
+ }
+ else
+ {
+ if ( m_state & STATE_VALUE )
+ {
+ pos.x = m_pos.x+m_dim.x+4.0f/640.0f;
+ h = m_dim.y-m_marginButton*2.0f;
+ pos.y = m_pos.y+m_marginButton-4.0f/480.0f;
+ pos.y += (h-CURSOR_WIDTH)*m_visibleValue;
+ dim.x = 50.0f/640.0f;
+ dim.y = 16.0f/480.0f;
+ sprintf(text, "%d", (int)(m_min+(m_visibleValue*(m_max-m_min))));
+ m_engine->RetText()->DrawText(text, pos, dim.x, 1, m_fontSize, m_fontStretch, m_fontType, 0);
+ }
+ }
+}
+
+// Draws a rectangle.
+
+void CSlider::DrawVertex(Math::Point pos, Math::Point dim, int icon)
+{
+ Math::Point uv1, uv2, corner;
+ float ex, dp;
+
+ if ( icon == 0 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 0.0f/256.0f; // yellow rectangle
+ uv1.y = 32.0f/256.0f;
+ uv2.x = 32.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+ corner.x = 2.0f/640.0f;
+ corner.y = 2.0f/480.0f;
+ ex = 4.0f/256.0f;
+ }
+ else if ( icon == 1 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 128.0f/256.0f; // gray rectangle
+ uv1.y = 32.0f/256.0f;
+ uv2.x = 160.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+ corner.x = 2.0f/640.0f;
+ corner.y = 2.0f/480.0f;
+ ex = 4.0f/256.0f;
+ }
+ else
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 224.0f/256.0f; // cursor
+ uv1.y = 32.0f/256.0f;
+ uv2.x = 256.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+ if ( !m_bHoriz )
+ {
+ uv1.y += 64.0f/256.0f;
+ uv2.y += 64.0f/256.0f;
+ }
+ corner.x = 2.0f/640.0f;
+ corner.y = 2.0f/480.0f;
+ ex = 4.0f/256.0f;
+ }
+
+ dp = 0.5f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+
+ DrawIcon(pos, dim, uv1, uv2, corner, ex);
+}
+
+
+void CSlider::SetLimit(float min, float max)
+{
+ m_min = min;
+ m_max = max;
+}
+
+void CSlider::SetVisibleValue(float value)
+{
+ value = (value-m_min)/(m_max-m_min);
+ if ( value < 0.0 ) value = 0.0f;
+ if ( value > 1.0 ) value = 1.0f;
+ m_visibleValue = value;
+ AdjustGlint();
+}
+
+float CSlider::RetVisibleValue()
+{
+ return m_min+m_visibleValue*(m_max-m_min);
+}
+
+
+void CSlider::SetArrowStep(float step)
+{
+ m_step = step/(m_max-m_min);
+}
+
+float CSlider::RetArrowStep()
+{
+ return m_step*(m_max-m_min);
+}
+
+
diff --git a/src/ui/slider.h b/src/ui/slider.h
index a1eb127..1ec9ea5 100644
--- a/src/ui/slider.h
+++ b/src/ui/slider.h
@@ -1,81 +1,81 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// slider.h
-
-#pragma once
-
-
-#include "ui/control.h"
-
-
-class CD3DEngine;
-class CButton;
-
-
-
-class CSlider : public CControl
-{
-public:
- CSlider(CInstanceManager* iMan);
- ~CSlider();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
-
- void SetPos(Math::Point pos);
- void SetDim(Math::Point dim);
-
- bool SetState(int state, bool bState);
- bool SetState(int state);
- bool ClearState(int state);
-
- bool EventProcess(const Event &event);
- void Draw();
-
- void SetLimit(float min, float max);
-
- void SetVisibleValue(float value);
- float RetVisibleValue();
-
- void SetArrowStep(float step);
- float RetArrowStep();
-
-protected:
- void MoveAdjust();
- void AdjustGlint();
- void DrawVertex(Math::Point pos, Math::Point dim, int icon);
-
-protected:
- CButton* m_buttonLeft;
- CButton* m_buttonRight;
-
- float m_min;
- float m_max;
- float m_visibleValue;
- float m_step;
-
- bool m_bHoriz;
- float m_marginButton;
-
- bool m_bCapture;
- Math::Point m_pressPos;
- float m_pressValue;
-
- EventMsg m_eventUp;
- EventMsg m_eventDown;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// slider.h
+
+#pragma once
+
+
+#include "ui/control.h"
+
+
+class CD3DEngine;
+class CButton;
+
+
+
+class CSlider : public CControl
+{
+public:
+ CSlider(CInstanceManager* iMan);
+ ~CSlider();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+
+ void SetPos(Math::Point pos);
+ void SetDim(Math::Point dim);
+
+ bool SetState(int state, bool bState);
+ bool SetState(int state);
+ bool ClearState(int state);
+
+ bool EventProcess(const Event &event);
+ void Draw();
+
+ void SetLimit(float min, float max);
+
+ void SetVisibleValue(float value);
+ float RetVisibleValue();
+
+ void SetArrowStep(float step);
+ float RetArrowStep();
+
+protected:
+ void MoveAdjust();
+ void AdjustGlint();
+ void DrawVertex(Math::Point pos, Math::Point dim, int icon);
+
+protected:
+ CButton* m_buttonLeft;
+ CButton* m_buttonRight;
+
+ float m_min;
+ float m_max;
+ float m_visibleValue;
+ float m_step;
+
+ bool m_bHoriz;
+ float m_marginButton;
+
+ bool m_bCapture;
+ Math::Point m_pressPos;
+ float m_pressValue;
+
+ EventMsg m_eventUp;
+ EventMsg m_eventDown;
+};
+
+
diff --git a/src/ui/studio.cpp b/src/ui/studio.cpp
index d37c6fd..215dc51 100644
--- a/src/ui/studio.cpp
+++ b/src/ui/studio.cpp
@@ -1,1665 +1,1665 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// studio.cpp
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <windows.h>
-#include <direct.h>
-#include <io.h>
-#include <time.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/language.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "old/math3d.h"
-#include "object/robotmain.h"
-#include "object/object.h"
-#include "old/camera.h"
-#include "old/sound.h"
-#include "script/script.h"
-#include "ui/interface.h"
-#include "ui/button.h"
-#include "ui/check.h"
-#include "ui/slider.h"
-#include "ui/edit.h"
-#include "ui/list.h"
-#include "ui/label.h"
-#include "ui/group.h"
-#include "ui/window.h"
-#include "old/text.h"
-#include "script/cbottoken.h"
-#include "ui/studio.h"
-
-
-
-
-// Object's constructor.
-
-CStudio::CStudio(CInstanceManager* iMan)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_STUDIO, this);
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
- m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
-
- m_bEditMaximized = false;
- m_bEditMinimized = false;
-
- m_time = 0.0f;
- m_bRealTime = true;
- m_bRunning = false;
- m_fixInfoTextTime = 0.0f;
- m_helpFilename[0] = 0;
- m_dialog = SD_NULL;
-}
-
-// Object's destructor.
-
-CStudio::~CStudio()
-{
- m_iMan->DeleteInstance(CLASS_STUDIO, this);
-}
-
-
-// Management of an event.
-
-bool CStudio::EventProcess(const Event &event)
-{
- CWindow* pw;
- CEdit* edit;
- CSlider* slider;
- char res[100];
-
- if ( m_dialog != SD_NULL ) // dialogue exists?
- {
- return EventDialog(event);
- }
-
- if ( event.event == EVENT_FRAME )
- {
- EventFrame(event);
- }
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw == 0 ) return false;
-
- edit = (CEdit*)pw->SearchControl(EVENT_STUDIO_EDIT);
- if ( edit == 0 ) return false;
-
- if ( event.event == pw->RetEventMsgClose() )
- {
- Event newEvent = event;
- newEvent.event = EVENT_STUDIO_OK;
- m_event->AddEvent(newEvent);
- }
-
- if ( event.event == EVENT_STUDIO_EDIT ) // text modifief?
- {
- ColorizeScript(edit);
- }
-
- if ( event.event == EVENT_STUDIO_LIST ) // list clicked?
- {
- m_main->StartDisplayInfo(m_helpFilename, -1);
- }
-
- if ( event.event == EVENT_STUDIO_NEW ) // new?
- {
- m_script->New(edit, "");
- }
-
- if ( event.event == EVENT_STUDIO_OPEN ) // open?
- {
- StartDialog(SD_OPEN);
- }
- if ( event.event == EVENT_STUDIO_SAVE ) // save?
- {
- StartDialog(SD_SAVE);
- }
-
- if ( event.event == EVENT_STUDIO_UNDO ) // undo?
- {
- edit->Undo();
- }
- if ( event.event == EVENT_STUDIO_CUT ) // cut?
- {
- edit->Cut();
- }
- if ( event.event == EVENT_STUDIO_COPY ) // copy?
- {
- edit->Copy();
- }
- if ( event.event == EVENT_STUDIO_PASTE ) // paste?
- {
- edit->Paste();
- }
-
- if ( event.event == EVENT_STUDIO_SIZE ) // size?
- {
- slider = (CSlider*)pw->SearchControl(EVENT_STUDIO_SIZE);
- if ( slider == 0 ) return false;
- m_main->SetFontSize(9.0f+slider->RetVisibleValue()*6.0f);
- ViewEditScript();
- }
-
- if ( event.event == EVENT_STUDIO_TOOL && // instructions?
- m_dialog == SD_NULL )
- {
- m_main->StartDisplayInfo(SATCOM_HUSTON, false);
- }
- if ( event.event == EVENT_STUDIO_HELP && // help?
- m_dialog == SD_NULL )
- {
- m_main->StartDisplayInfo(SATCOM_PROG, false);
- }
-
- if ( event.event == EVENT_STUDIO_COMPILE ) // compile?
- {
- char buffer[100];
-
- if ( m_script->GetScript(edit) ) // compile
- {
- GetResource(RES_TEXT, RT_STUDIO_COMPOK, res);
- SetInfoText(res, false);
- }
- else
- {
- m_script->GetError(buffer);
- SetInfoText(buffer, false);
- }
- }
-
- if ( event.event == EVENT_STUDIO_RUN ) // run/stop?
- {
- if ( m_script->IsRunning() )
- {
- Event newEvent = event;
- newEvent.event = EVENT_OBJECT_PROGSTOP;
- m_event->AddEvent(newEvent); // stop
- }
- else
- {
- if ( m_script->GetScript(edit) ) // compile
- {
- SetInfoText("", false);
-
- Event newEvent = event;
- newEvent.event = EVENT_OBJECT_PROGSTART;
- m_event->AddEvent(newEvent); // start
- }
- else
- {
- char buffer[100];
- m_script->GetError(buffer);
- SetInfoText(buffer, false);
- }
- }
- }
-
- if ( event.event == EVENT_STUDIO_REALTIME ) // real time?
- {
- m_bRealTime = !m_bRealTime;
- m_script->SetStepMode(!m_bRealTime);
- UpdateFlux();
- UpdateButtons();
- }
-
- if ( event.event == EVENT_STUDIO_STEP ) // step?
- {
- m_script->Step(event);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
- if ( event.param == m_engine->RetKey(KEYRANK_CBOT, 0) ||
- event.param == m_engine->RetKey(KEYRANK_CBOT, 1) )
- {
- if ( m_helpFilename[0] != 0 )
- {
- m_main->StartDisplayInfo(m_helpFilename, -1);
- }
- }
- }
-
- if ( event.event == EVENT_WINDOW3 ) // window is moved?
- {
- m_editActualPos = m_editFinalPos = pw->RetPos();
- m_editActualDim = m_editFinalDim = pw->RetDim();
- m_main->SetWindowPos(m_editActualPos);
- m_main->SetWindowDim(m_editActualDim);
- AdjustEditScript();
- }
- if ( event.event == pw->RetEventMsgReduce() )
- {
- if ( m_bEditMinimized )
- {
- m_editFinalPos = m_main->RetWindowPos();
- m_editFinalDim = m_main->RetWindowDim();
- m_bEditMinimized = false;
- m_bEditMaximized = false;
- }
- else
- {
- m_editFinalPos.x = 0.00f;
- m_editFinalPos.y = -0.44f;
- m_editFinalDim.x = 1.00f;
- m_editFinalDim.y = 0.50f;
- m_bEditMinimized = true;
- m_bEditMaximized = false;
- }
- m_main->SetEditFull(m_bEditMaximized);
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw != 0 )
- {
- pw->SetMaximized(m_bEditMaximized);
- pw->SetMinimized(m_bEditMinimized);
- }
- }
- if ( event.event == pw->RetEventMsgFull() )
- {
- if ( m_bEditMaximized )
- {
- m_editFinalPos = m_main->RetWindowPos();
- m_editFinalDim = m_main->RetWindowDim();
- m_bEditMinimized = false;
- m_bEditMaximized = false;
- }
- else
- {
- m_editFinalPos.x = 0.00f;
- m_editFinalPos.y = 0.00f;
- m_editFinalDim.x = 1.00f;
- m_editFinalDim.y = 1.00f;
- m_bEditMinimized = false;
- m_bEditMaximized = true;
- }
- m_main->SetEditFull(m_bEditMaximized);
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw != 0 )
- {
- pw->SetMaximized(m_bEditMaximized);
- pw->SetMinimized(m_bEditMinimized);
- }
- }
-
- return true;
-}
-
-
-// Evolves value with time elapsed.
-
-float Evolution(float final, float actual, float time)
-{
- float value;
-
- value = actual + (final-actual)*time;
-
- if ( final > actual )
- {
- if ( value > final ) value = final; // does not exceed
- }
- else
- {
- if ( value < final ) value = final; // does not exceed
- }
-
- return value;
-}
-
-// Makes the studio evolve as time elapsed.
-
-bool CStudio::EventFrame(const Event &event)
-{
- CWindow* pw;
- CEdit* edit;
- CList* list;
- float time;
- int cursor1, cursor2, iCursor1, iCursor2;
- char res[100];
-
- m_time += event.rTime;
- m_fixInfoTextTime -= event.rTime;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw == 0 ) return false;
-
- edit = (CEdit*)pw->SearchControl(EVENT_STUDIO_EDIT);
- if ( edit == 0 ) return false;
-
- list = (CList*)pw->SearchControl(EVENT_STUDIO_LIST);
- if ( list == 0 ) return false;
-
- if ( !m_script->IsRunning() && m_bRunning ) // stop?
- {
- m_bRunning = false;
- UpdateFlux(); // stop
- AdjustEditScript();
- GetResource(RES_TEXT, RT_STUDIO_PROGSTOP, res);
- SetInfoText(res, false);
-
- Event newEvent = event;
- newEvent.event = EVENT_OBJECT_PROGSTOP;
- m_event->AddEvent(newEvent); // stop
- }
-
- if ( m_script->IsRunning() && !m_bRunning ) // starting?
- {
- m_bRunning = true;
- UpdateFlux(); // run
- AdjustEditScript();
- }
- UpdateButtons();
-
- if ( m_bRunning )
- {
- m_script->GetCursor(cursor1, cursor2);
- edit->GetCursor(iCursor1, iCursor2);
- if ( cursor1 != iCursor1 ||
- cursor2 != iCursor2 ) // cursors change?
- {
- edit->SetCursor(cursor1, cursor2); // shows it on the execution
- edit->ShowSelect();
- }
-
- m_script->UpdateList(list); // updates the list of variables
- }
- else
- {
- SearchToken(edit);
- }
-
- if ( m_editFinalPos.x != m_editActualPos.x ||
- m_editFinalPos.y != m_editActualPos.y ||
- m_editFinalDim.x != m_editActualDim.x ||
- m_editFinalDim.y != m_editActualDim.y )
- {
- time = event.rTime*20.0f;
- m_editActualPos.x = Evolution(m_editFinalPos.x, m_editActualPos.x, time);
- m_editActualPos.y = Evolution(m_editFinalPos.y, m_editActualPos.y, time);
- m_editActualDim.x = Evolution(m_editFinalDim.x, m_editActualDim.x, time);
- m_editActualDim.y = Evolution(m_editFinalDim.y, m_editActualDim.y, time);
- AdjustEditScript();
- }
-
- return true;
-}
-
-
-// Indicates whether a character is part of a word.
-
-bool IsToken(int character)
-{
- char c;
-
- c = tolower(RetNoAccent(character));
-
- return ( (c >= 'a' && c <= 'z') ||
- (c >= '0' && c <= '9') ||
- c == '_' );
-}
-
-// Seeks if the cursor is on a keyword.
-
-void CStudio::SearchToken(CEdit* edit)
-{
- ObjectType type;
- int len, cursor1, cursor2, i, character, level;
- char* text;
- char token[100];
-
- text = edit->RetText();
- len = edit->RetTextLength();
- edit->GetCursor(cursor1, cursor2);
-
- i = cursor1;
- if ( i > 0 )
- {
- character = (unsigned char)text[i-1];
- if ( !IsToken(character) )
- {
- level = 1;
- while ( i > 0 )
- {
- character = (unsigned char)text[i-1];
- if ( character == ')' )
- {
- level ++;
- }
- else if ( character == '(' )
- {
- level --;
- if ( level == 0 ) break;
- }
- i --;
- }
- if ( level > 0 )
- {
- m_helpFilename[0] = 0;
- SetInfoText("", true);
- return;
- }
- while ( i > 0 )
- {
- character = (unsigned char)text[i-1];
- if ( IsToken(character) ) break;
- i --;
- }
- }
- }
-
- while ( i > 0 )
- {
- character = (unsigned char)text[i-1];
- if ( !IsToken(character) ) break;
- i --;
- }
- cursor2 = i;
-
- while ( i < len )
- {
- character = (unsigned char)text[i];
- if ( !IsToken(character) ) break;
- i ++;
- }
- cursor1 = i;
- len = cursor1-cursor2;
-
- if ( len > 100-1 ) len = 100-1;
- for ( i=0 ; i<len ; i++ )
- {
- token[i] = text[cursor2+i];
- }
- token[i] = 0;
-
- strcpy(m_helpFilename, RetHelpFilename(token));
- if ( m_helpFilename[0] == 0 )
- {
- for ( i=0 ; i<OBJECT_MAX ; i++ )
- {
- type = (ObjectType)i;
- text = RetObjectName(type);
- if ( text[0] != 0 )
- {
- if ( strcmp(token, text) == 0 )
- {
- strcpy(m_helpFilename, RetHelpFilename(type));
- SetInfoText(token, true);
- return;
- }
- }
- text = RetObjectAlias(type);
- if ( text[0] != 0 )
- {
- if ( strcmp(token, text) == 0 )
- {
- strcpy(m_helpFilename, RetHelpFilename(type));
- SetInfoText(token, true);
- return;
- }
- }
- }
- }
-
- text = RetHelpText(token);
- if ( text[0] == 0 && m_helpFilename[0] != 0 )
- {
- SetInfoText(token, true);
- }
- else
- {
- SetInfoText(text, true);
- }
-}
-
-// Colors the text according to syntax.
-
-void CStudio::ColorizeScript(CEdit* edit)
-{
- m_script->ColorizeScript(edit);
-}
-
-
-// Starts editing a program.
-
-void CStudio::StartEditScript(CScript *script, char* name, int rank)
-{
- Math::Point pos, dim;
- CWindow* pw;
- CEdit* edit;
- CButton* button;
- CSlider* slider;
- CList* list;
- char res[100];
-
- m_script = script;
- m_rank = rank;
-
- m_main->SetEditLock(true, true);
- m_main->SetEditFull(false);
- m_bInitPause = m_engine->RetPause();
- m_main->SetSpeed(1.0f);
- m_editCamera = m_camera->RetType();
- m_camera->SetType(CAMERA_EDIT);
-
- m_bRunning = m_script->IsRunning();
- m_bRealTime = m_bRunning;
- m_script->SetStepMode(!m_bRealTime);
-
- button = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
- if ( button != 0 )
- {
- button->ClearState(STATE_VISIBLE);
- }
-
- pos = m_editFinalPos = m_editActualPos = m_main->RetWindowPos();
- dim = m_editFinalDim = m_editActualDim = m_main->RetWindowDim();
- pw = m_interface->CreateWindows(pos, dim, 8, EVENT_WINDOW3);
- if ( pw == 0 ) return;
- pw->SetState(STATE_SHADOW);
- pw->SetRedim(true); // before SetName!
- pw->SetMovable(true);
- pw->SetClosable(true);
- GetResource(RES_TEXT, RT_STUDIO_TITLE, res);
- pw->SetName(res);
- pw->SetMinDim(Math::Point(0.49f, 0.50f));
- pw->SetMaximized(m_bEditMaximized);
- pw->SetMinimized(m_bEditMinimized);
- m_main->SetEditFull(m_bEditMaximized);
-
- edit = pw->CreateEdit(pos, dim, 0, EVENT_STUDIO_EDIT);
- if ( edit == 0 ) return;
- edit->SetState(STATE_SHADOW);
- edit->SetInsideScroll(false);
-//? if ( m_bRunning ) edit->SetEdit(false);
- edit->SetMaxChar(EDITSTUDIOMAX);
- edit->SetFontType(FONT_COURIER);
- edit->SetFontStretch(0.7f);
- edit->SetDisplaySpec(true);
- edit->SetAutoIndent(m_engine->RetEditIndentMode());
- m_script->PutScript(edit, name);
- ColorizeScript(edit);
-
- ViewEditScript();
-
- list = pw->CreateList(pos, dim, 1, EVENT_STUDIO_LIST, 1.2f);
- list->SetState(STATE_SHADOW);
- list->SetFontType(FONT_COURIER);
- list->SetSelectCap(false);
- list->SetFontSize(SMALLFONT*0.85f);
-//? list->SetFontStretch(1.0f);
-
- button = pw->CreateButton(pos, dim, 56, EVENT_STUDIO_NEW);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 57, EVENT_STUDIO_OPEN);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 58, EVENT_STUDIO_SAVE);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 59, EVENT_STUDIO_UNDO);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 60, EVENT_STUDIO_CUT);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 61, EVENT_STUDIO_COPY);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 62, EVENT_STUDIO_PASTE);
- button->SetState(STATE_SHADOW);
- slider = pw->CreateSlider(pos, dim, 0, EVENT_STUDIO_SIZE);
- slider->SetState(STATE_SHADOW);
- slider->SetVisibleValue((m_main->RetFontSize()-9.0f)/6.0f);
- pw->CreateGroup(pos, dim, 19, EVENT_LABEL1); // SatCom logo
- button = pw->CreateButton(pos, dim, 128+57, EVENT_STUDIO_TOOL);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 128+60, EVENT_STUDIO_HELP);
- button->SetState(STATE_SHADOW);
-
- button = pw->CreateButton(pos, dim, -1, EVENT_STUDIO_OK);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, -1, EVENT_STUDIO_CANCEL);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 64+23, EVENT_STUDIO_COMPILE);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 21, EVENT_STUDIO_RUN);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 64+22, EVENT_STUDIO_REALTIME);
- button->SetState(STATE_SHADOW);
- button = pw->CreateButton(pos, dim, 64+29, EVENT_STUDIO_STEP);
- button->SetState(STATE_SHADOW);
-
- UpdateFlux();
- UpdateButtons();
- AdjustEditScript();
-}
-
-// Repositions all the editing controls.
-
-void CStudio::AdjustEditScript()
-{
- CWindow* pw;
- CEdit* edit;
- CButton* button;
- CGroup* group;
- CSlider* slider;
- CList* list;
- Math::Point wpos, wdim, pos, dim, ppos, ddim;
- float hList;
-
- wpos = m_editActualPos;
- wdim = m_editActualDim;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw != 0 )
- {
- pw->SetPos(wpos);
- pw->SetDim(wdim);
- wdim = pw->RetDim();
- }
-
- if ( m_bRunning ) hList = 80.0f/480.0f;
- else hList = 20.0f/480.0f;
-
- pos.x = wpos.x+0.01f;
- pos.y = wpos.y+0.09f+hList;
- dim.x = wdim.x-0.02f;
- dim.y = wdim.y-0.22f-hList;
- edit = (CEdit*)pw->SearchControl(EVENT_STUDIO_EDIT);
- if ( edit != 0 )
- {
- edit->SetPos(pos);
- edit->SetDim(dim);
- }
-
- pos.x = wpos.x+0.01f;
- pos.y = wpos.y+0.09f;
- dim.x = wdim.x-0.02f;
- dim.y = hList;
- list = (CList*)pw->SearchControl(EVENT_STUDIO_LIST);
- if ( list != 0 )
- {
- list->SetPos(pos);
- list->SetDim(dim);
- }
-
- dim.x = 0.04f;
- dim.y = 0.04f*1.5f;
- dim.y = 25.0f/480.0f;
-
- pos.y = wpos.y+wdim.y-dim.y-0.06f;
- pos.x = wpos.x+0.01f;
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_NEW);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x = wpos.x+0.05f;
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_OPEN);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x = wpos.x+0.09f;
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_SAVE);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x = wpos.x+0.14f;
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_UNDO);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x = wpos.x+0.19f;
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_CUT);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x = wpos.x+0.23f;
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_COPY);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x = wpos.x+0.27f;
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_PASTE);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x = wpos.x+0.32f;
- slider = (CSlider*)pw->SearchControl(EVENT_STUDIO_SIZE);
- if ( slider != 0 )
- {
- ppos = pos;
- ddim.x = dim.x*0.7f;
- ddim.y = dim.y;
- ppos.y -= 3.0f/480.0f;
- ddim.y += 6.0f/480.0f;
- slider->SetPos(ppos);
- slider->SetDim(ddim);
- }
- pos.x = wpos.x+0.36f;
- group = (CGroup*)pw->SearchControl(EVENT_LABEL1);
- if ( group != 0 )
- {
- group->SetPos(pos);
- group->SetDim(dim);
- }
- pos.x = wpos.x+0.40f;
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_TOOL);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x = wpos.x+0.44f;
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_HELP);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
-
- pos.y = wpos.y+0.02f;
- pos.x = wpos.x+0.01f;
- dim.x = 80.0f/640.0f;
- dim.y = 25.0f/480.0f;
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_OK);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x = wpos.x+0.14f;
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_CANCEL);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x = wpos.x+0.28f;
- dim.x = dim.y*0.75f;
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_COMPILE);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x = wpos.x+0.28f+dim.x*1;
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_RUN);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x = wpos.x+0.28f+dim.x*2;
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_REALTIME);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
- pos.x = wpos.x+0.28f+dim.x*3;
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_STEP);
- if ( button != 0 )
- {
- button->SetPos(pos);
- button->SetDim(dim);
- }
-}
-
-// Ends edition of a program.
-
-bool CStudio::StopEditScript(bool bCancel)
-{
- CWindow* pw;
- CEdit* edit;
- CButton* button;
- char buffer[100];
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw == 0 ) return false;
-
- if ( !bCancel && !m_script->IsRunning() )
- {
- edit = (CEdit*)pw->SearchControl(EVENT_STUDIO_EDIT);
- if ( edit != 0 )
- {
- if ( !m_script->GetScript(edit) ) // compile
- {
- m_script->GetError(buffer);
- SetInfoText(buffer, false);
- return false;
- }
- }
- }
- m_script->SetStepMode(false);
-
- m_interface->DeleteControl(EVENT_WINDOW3);
-
- button = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
- if ( button != 0 )
- {
- button->SetState(STATE_VISIBLE);
- }
-
- if ( !m_bInitPause ) m_engine->SetPause(false);
- m_sound->MuteAll(false);
- m_main->SetEditLock(false, true);
- m_camera->SetType(m_editCamera);
- return true;
-}
-
-// Specifies the message to display.
-// The messages are not clickable 8 seconds,
-// even if a message was clickable poster before.
-
-void CStudio::SetInfoText(char *text, bool bClickable)
-{
- CWindow* pw;
- CList* list;
- char res[100];
-
- if ( bClickable && m_fixInfoTextTime > 0.0f ) return;
- if ( !bClickable ) m_fixInfoTextTime = 8.0f;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw == 0 ) return;
-
- list = (CList*)pw->SearchControl(EVENT_STUDIO_LIST);
- if ( list == 0 ) return;
-
- list->Flush(); // just text
- list->SetName(0, text);
-
- if ( text[0] == 0 ) bClickable = false;
- list->SetSelectCap(bClickable);
-
- if ( bClickable )
- {
- GetResource(RES_TEXT, RT_STUDIO_LISTTT, res);
- list->SetTooltip(res);
- list->SetState(STATE_ENABLE);
- }
- else
- {
- list->SetTooltip("");
-//? list->ClearState(STATE_ENABLE);
- list->SetState(STATE_ENABLE, text[0] != 0);
- }
-}
-
-
-// Changing the size of a editing program.
-
-void CStudio::ViewEditScript()
-{
- CWindow* pw;
- CEdit* edit;
- POINT dim;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw == 0 ) return;
-
- edit = (CEdit*)pw->SearchControl(EVENT_STUDIO_EDIT);
- if ( edit == 0 ) return;
-
- dim = m_engine->RetDim();
- edit->SetFontSize(m_main->RetFontSize()/(dim.x/640.0f));
-}
-
-
-// Updates the operating mode.
-
-void CStudio::UpdateFlux()
-{
- if ( m_bRunning )
- {
-#if 1
- if ( m_bRealTime ) // run?
- {
- m_engine->SetPause(false);
- m_sound->MuteAll(false);
- }
- else // step by step?
- {
- m_engine->SetPause(true);
- m_sound->MuteAll(true);
- }
-#else
- m_engine->SetPause(false);
- m_sound->MuteAll(false);
-#endif
- }
- else // stop?
- {
- m_engine->SetPause(true);
- m_sound->MuteAll(true);
- }
-}
-
-// Updates the buttons.
-
-void CStudio::UpdateButtons()
-{
- CWindow* pw;
- CEdit* edit;
- CButton* button;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw == 0 ) return;
-
- edit = (CEdit*)pw->SearchControl(EVENT_STUDIO_EDIT);
- if ( edit == 0 ) return;
-
- if ( m_bRunning )
- {
- edit->SetIcon(1); // red background
- edit->SetEditCap(false); // just to see
- edit->SetHiliteCap(true);
- }
- else
- {
- edit->SetIcon(0); // standard background
- edit->SetEditCap(true);
- edit->SetHiliteCap(true);
- }
-
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_COMPILE);
- if ( button == 0 ) return;
- button->SetState(STATE_ENABLE, !m_bRunning);
-
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_RUN);
- if ( button == 0 ) return;
- button->SetIcon(m_bRunning?8:21); // stop/run
-
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_REALTIME);
- if ( button == 0 ) return;
- button->SetIcon(m_bRealTime?64+22:64+21);
- button->SetState(STATE_ENABLE, (!m_bRunning || !m_script->IsContinue()));
-
- button = (CButton*)pw->SearchControl(EVENT_STUDIO_STEP);
- if ( button == 0 ) return;
- button->SetState(STATE_ENABLE, (m_bRunning && !m_bRealTime && !m_script->IsContinue()));
-}
-
-
-// Beginning of the display of a dialogue.
-
-void CStudio::StartDialog(StudioDialog type)
-{
- CWindow* pw;
- CButton* pb;
- CCheck* pc;
- CLabel* pla;
- CList* pli;
- CEdit* pe;
- Math::Point pos, dim;
- char name[100];
-
- m_dialog = type;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW6);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW7);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW8);
- if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
-
- if ( m_dialog == SD_OPEN ||
- m_dialog == SD_SAVE )
- {
- pos = m_main->RetIOPos();
- dim = m_main->RetIODim();
- }
-//? pw = m_interface->CreateWindows(pos, dim, 8, EVENT_WINDOW9);
- pw = m_interface->CreateWindows(pos, dim, m_dialog==SD_OPEN?14:13, EVENT_WINDOW9);
- pw->SetState(STATE_SHADOW);
- pw->SetMovable(true);
- pw->SetClosable(true);
- pw->SetMinDim(Math::Point(320.0f/640.0f, (121.0f+18.0f*4)/480.0f));
- if ( m_dialog == SD_OPEN ) GetResource(RES_TEXT, RT_IO_OPEN, name);
- if ( m_dialog == SD_SAVE ) GetResource(RES_TEXT, RT_IO_SAVE, name);
- pw->SetName(name);
-
- pos = Math::Point(0.0f, 0.0f);
- dim = Math::Point(0.0f, 0.0f);
-
- if ( m_dialog == SD_OPEN ||
- m_dialog == SD_SAVE )
- {
- GetResource(RES_TEXT, RT_IO_LIST, name);
- pla = pw->CreateLabel(pos, dim, 0, EVENT_DIALOG_LABEL1, name);
- pla->SetJustif(1);
-
- pli = pw->CreateList(pos, dim, 0, EVENT_DIALOG_LIST);
- pli->SetState(STATE_SHADOW);
-
- GetResource(RES_TEXT, RT_IO_NAME, name);
- pla = pw->CreateLabel(pos, dim, 0, EVENT_DIALOG_LABEL2, name);
- pla->SetJustif(1);
-
- pe = pw->CreateEdit(pos, dim, 0, EVENT_DIALOG_EDIT);
- pe->SetState(STATE_SHADOW);
- if ( m_dialog == SD_SAVE )
- {
- pe->SetText(m_script->RetFilename());
- }
-
- GetResource(RES_TEXT, RT_IO_DIR, name);
- pla = pw->CreateLabel(pos, dim, 0, EVENT_DIALOG_LABEL3, name);
- pla->SetJustif(1);
-
- pc = pw->CreateCheck(pos, dim, 0, EVENT_DIALOG_CHECK1);
- GetResource(RES_TEXT, RT_IO_PRIVATE, name);
- pc->SetName(name);
- pc->SetState(STATE_SHADOW);
-#if _POLISH
- pc->SetFontSize(8.0f);
-#endif
-
- pc = pw->CreateCheck(pos, dim, 0, EVENT_DIALOG_CHECK2);
- GetResource(RES_TEXT, RT_IO_PUBLIC, name);
- pc->SetName(name);
- pc->SetState(STATE_SHADOW);
-#if _POLISH
- pc->SetFontSize(8.0f);
-#endif
-
- pb = pw->CreateButton(pos, dim, -1, EVENT_DIALOG_OK);
- pb->SetState(STATE_SHADOW);
- if ( m_dialog == SD_OPEN ) GetResource(RES_TEXT, RT_IO_OPEN, name);
- if ( m_dialog == SD_SAVE ) GetResource(RES_TEXT, RT_IO_SAVE, name);
- pb->SetName(name);
-
- pb = pw->CreateButton(pos, dim, -1, EVENT_DIALOG_CANCEL);
- pb->SetState(STATE_SHADOW);
- GetResource(RES_EVENT, EVENT_DIALOG_CANCEL, name);
- pb->SetName(name);
-
- AdjustDialog();
- UpdateDialogList();
- UpdateDialogPublic();
- UpdateDialogAction();
-
- pe->SetCursor(999, 0); // selects all
- pe->SetFocus(true);
- }
-
- m_main->SetSatComLock(true); // impossible to use the SatCom
-}
-
-// End of the display of a dialogue.
-
-void CStudio::StopDialog()
-{
- CWindow* pw;
-
- if ( m_dialog == SD_NULL ) return;
- m_dialog = SD_NULL;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW6);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW7);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW8);
- if ( pw != 0 ) pw->SetState(STATE_ENABLE);
-
- m_interface->DeleteControl(EVENT_WINDOW9);
- m_main->SetSatComLock(false); // possible to use the SatCom
-}
-
-// Adjust all controls of dialogue after a change in geometry.
-
-void CStudio::AdjustDialog()
-{
- CWindow* pw;
- CButton* pb;
- CCheck* pc;
- CLabel* pla;
- CList* pli;
- CEdit* pe;
- Math::Point wpos, wdim, ppos, ddim;
- int nli, nch;
- char name[100];
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
- if ( pw == 0 ) return;
-
- wpos = pw->RetPos();
- wdim = pw->RetDim();
- pw->SetPos(wpos); // to move the buttons on the titlebar
-
- if ( m_dialog == SD_OPEN ||
- m_dialog == SD_SAVE )
- {
- ppos.x = wpos.x+10.0f/640.0f;
- ppos.y = wpos.y+wdim.y-55.0f/480.0f;
- ddim.x = wdim.x-20.0f/640.0f;
- ddim.y = 20.0f/480.0f;
- pla = (CLabel*)pw->SearchControl(EVENT_DIALOG_LABEL1);
- if ( pla != 0 )
- {
- pla->SetPos(ppos);
- pla->SetDim(ddim);
- }
-
- nli = (int)((wdim.y-120.0f/480.0f)/(18.0f/480.0f));
- ddim.y = nli*18.0f/480.0f+9.0f/480.0f;
- ppos.y = wpos.y+wdim.y-48.0f/480.0f-ddim.y;
- pli = (CList*)pw->SearchControl(EVENT_DIALOG_LIST);
- if ( pli != 0 )
- {
- pli->SetPos(ppos);
- pli->SetDim(ddim);
- pli->SetTabs(0, ddim.x-(50.0f+130.0f+16.0f)/640.0f);
- pli->SetTabs(1, 50.0f/640.0f, -1);
- pli->SetTabs(2, 130.0f/640.0f);
-//? pli->ShowSelect();
- }
-
- ppos.y = wpos.y+30.0f/480.0f;
- ddim.x = 50.0f/640.0f;
- ddim.y = 20.0f/480.0f;
- pla = (CLabel*)pw->SearchControl(EVENT_DIALOG_LABEL2);
- if ( pla != 0 )
- {
- pla->SetPos(ppos);
- pla->SetDim(ddim);
- }
-
- ppos.x += 50.0f/640.0f;
- ppos.y = wpos.y+36.0f/480.0f;
- ddim.x = wdim.x-170.0f/640.0f;
- pe = (CEdit*)pw->SearchControl(EVENT_DIALOG_EDIT);
- if ( pe != 0 )
- {
- pe->SetPos(ppos);
- pe->SetDim(ddim);
-
- nch = (int)((ddim.x*640.0f-22.0f)/8.0f);
- pe->GetText(name, 100);
- pe->SetMaxChar(nch);
- name[nch] = 0; // truncates the text according to max
- pe->SetText(name);
- }
-
- ppos.x = wpos.x+10.0f/640.0f;
- ppos.y = wpos.y+5.0f/480.0f;
- ddim.x = 50.0f/640.0f;
- ddim.y = 16.0f/480.0f;
- pla = (CLabel*)pw->SearchControl(EVENT_DIALOG_LABEL3);
- if ( pla != 0 )
- {
- pla->SetPos(ppos);
- pla->SetDim(ddim);
- }
-
- ppos.x += 50.0f/640.0f;
- ppos.y = wpos.y+12.0f/480.0f;
- ddim.x = 70.0f/640.0f;
- pc = (CCheck*)pw->SearchControl(EVENT_DIALOG_CHECK1);
- if ( pc != 0 )
- {
- pc->SetPos(ppos);
- pc->SetDim(ddim);
- }
-
- ppos.x += 80.0f/640.0f;
- pc = (CCheck*)pw->SearchControl(EVENT_DIALOG_CHECK2);
- if ( pc != 0 )
- {
- pc->SetPos(ppos);
- pc->SetDim(ddim);
- }
-
- ppos.x = wpos.x+wdim.x-100.0f/640.0f;
- ppos.y = wpos.y+34.0f/480.0f;
- ddim.x = 90.0f/640.0f;
- ddim.y = 23.0f/480.0f;
- pb = (CButton*)pw->SearchControl(EVENT_DIALOG_OK);
- if ( pb != 0 )
- {
- pb->SetPos(ppos);
- pb->SetDim(ddim);
- }
-
- ppos.y -= 26.0f/480.0f;
- pb = (CButton*)pw->SearchControl(EVENT_DIALOG_CANCEL);
- if ( pb != 0 )
- {
- pb->SetPos(ppos);
- pb->SetDim(ddim);
- }
- }
-}
-
-// Management of the event of a dialogue.
-
-bool CStudio::EventDialog(const Event &event)
-{
- CWindow* pw;
- Math::Point wpos, wdim;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
- if ( pw == 0 ) return false;
-
- if ( event.event == EVENT_WINDOW9 ) // window is moved?
- {
- wpos = pw->RetPos();
- wdim = pw->RetDim();
- m_main->SetIOPos(wpos);
- m_main->SetIODim(wdim);
- AdjustDialog();
- }
-
- if ( m_dialog == SD_OPEN ||
- m_dialog == SD_SAVE )
- {
- if ( event.event == EVENT_DIALOG_LIST )
- {
- UpdateChangeList();
- }
- if ( event.event == EVENT_DIALOG_EDIT )
- {
- UpdateChangeEdit();
- }
-
- if ( event.event == EVENT_DIALOG_CHECK1 ) // private?
- {
- m_main->SetIOPublic(false);
- UpdateDialogPublic();
- UpdateDialogList();
- }
- if ( event.event == EVENT_DIALOG_CHECK2 ) // public?
- {
- m_main->SetIOPublic(true);
- UpdateDialogPublic();
- UpdateDialogList();
- }
- }
-
- if ( event.event == EVENT_DIALOG_OK ||
- (event.event == EVENT_KEYDOWN && event.param == VK_RETURN) )
- {
- if ( m_dialog == SD_OPEN )
- {
- if ( !ReadProgram() ) return true;
- }
- if ( m_dialog == SD_SAVE )
- {
- if ( !WriteProgram() ) return true;
- }
-
- StopDialog();
- return true;
- }
-
- if ( event.event == EVENT_DIALOG_CANCEL ||
- (event.event == EVENT_KEYDOWN && event.param == VK_ESCAPE) ||
- event.event == pw->RetEventMsgClose() )
- {
- StopDialog();
- return true;
- }
-
- return true;
-}
-
-// Updates the name after a click in the list.
-
-void CStudio::UpdateChangeList()
-{
- CWindow* pw;
- CList* pl;
- CEdit* pe;
- char name[100];
- char* p;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
- if ( pw == 0 ) return;
- pl = (CList*)pw->SearchControl(EVENT_DIALOG_LIST);
- if ( pl == 0 ) return;
- pe = (CEdit*)pw->SearchControl(EVENT_DIALOG_EDIT);
- if ( pe == 0 ) return;
-
- strcpy(name, pl->RetName(pl->RetSelect()));
- name[pe->RetMaxChar()] = 0; // truncates according lg max editable
- p = strchr(name, '\t'); // seeks first tab
- if ( p != 0 ) *p = 0;
- pe->SetText(name);
- pe->SetCursor(999, 0); // selects all
- pe->SetFocus(true);
-
- UpdateDialogAction();
-}
-
-// Updates the list after a change in name.
-
-void CStudio::UpdateChangeEdit()
-{
- CWindow* pw;
- CList* pl;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
- if ( pw == 0 ) return;
- pl = (CList*)pw->SearchControl(EVENT_DIALOG_LIST);
- if ( pl == 0 ) return;
-
- pl->SetSelect(-1);
-
- UpdateDialogAction();
-}
-
-// Updates the action button.
-
-void CStudio::UpdateDialogAction()
-{
- CWindow* pw;
- CEdit* pe;
- CButton* pb;
- char name[100];
- int len, i;
- bool bError;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
- if ( pw == 0 ) return;
- pe = (CEdit*)pw->SearchControl(EVENT_DIALOG_EDIT);
- if ( pe == 0 ) return;
- pb = (CButton*)pw->SearchControl(EVENT_DIALOG_OK);
- if ( pb == 0 ) return;
-
- pe->GetText(name, 100);
- len = strlen(name);
- if ( len == 0 )
- {
- bError = true;
- }
- else
- {
- bError = false;
- for ( i=0 ; i<len ; i++ )
- {
- if ( name[i] == '*' ||
- name[i] == '?' ||
- name[i] == ':' ||
- name[i] == '<' ||
- name[i] == '>' ||
- name[i] == '"' ||
- name[i] == '|' ||
- name[i] == '/' ||
- name[i] == '\\' ) bError = true;
- }
- }
-
- pb->SetState(STATE_ENABLE, !bError);
-}
-
-// Updates the buttons private/public.
-
-void CStudio::UpdateDialogPublic()
-{
- CWindow* pw;
- CCheck* pc;
- CLabel* pl;
- char name[100];
- char dir[_MAX_FNAME];
- char text[_MAX_FNAME+100];
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
- if ( pw == 0 ) return;
-
- pc = (CCheck*)pw->SearchControl(EVENT_DIALOG_CHECK1);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, !m_main->RetIOPublic());
- }
-
- pc = (CCheck*)pw->SearchControl(EVENT_DIALOG_CHECK2);
- if ( pc != 0 )
- {
- pc->SetState(STATE_CHECK, m_main->RetIOPublic());
- }
-
- pl = (CLabel*)pw->SearchControl(EVENT_DIALOG_LABEL1);
- if ( pl != 0 )
- {
- GetResource(RES_TEXT, RT_IO_LIST, name);
- SearchDirectory(dir, false);
- sprintf(text, name, dir);
- pl->SetName(text, false);
- }
-}
-
-// Fills the list with all programs saved.
-
-void CStudio::UpdateDialogList()
-{
- CWindow* pw;
- CList* pl;
- long hFile;
- struct _finddata_t fileBuffer;
- struct _finddata_t* listBuffer;
- bool bDo;
- char dir[_MAX_FNAME];
- char temp[_MAX_FNAME];
- int nbFilenames, i;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
- if ( pw == 0 ) return;
- pl = (CList*)pw->SearchControl(EVENT_DIALOG_LIST);
- if ( pl == 0 ) return;
- pl->Flush();
-
- nbFilenames = 0;
- listBuffer = (_finddata_t*)malloc(sizeof(_finddata_t)*1000);
-
- SearchDirectory(dir, false);
- strcat(dir, "*"); // list all
- hFile = _findfirst(dir, &fileBuffer);
- if ( hFile != -1 )
- {
- do
- {
- if ( (fileBuffer.attrib & _A_SUBDIR) == 0 )
- {
- listBuffer[nbFilenames++] = fileBuffer;
- }
- }
- while ( _findnext(hFile, &fileBuffer) == 0 && nbFilenames < 1000 );
- }
- do // sorts all names:
- {
- bDo = false;
- for ( i=0 ; i<nbFilenames-1 ; i++ )
- {
- if ( strcmp(listBuffer[i].name, listBuffer[i+1].name) > 0 )
- {
- fileBuffer = listBuffer[i]; // exchange i and i +1
- listBuffer[i] = listBuffer[i+1];
- listBuffer[i+1] = fileBuffer;
- bDo = true;
- }
- }
- }
- while ( bDo );
-
- for ( i=0 ; i<nbFilenames ; i++ )
- {
- TimeToAscii(listBuffer[i].time_write, dir);
- sprintf(temp, "%s\t%d \t%s", listBuffer[i].name, listBuffer[i].size, dir);
- pl->SetName(i, temp);
- }
-
- free(listBuffer);
-}
-
-// Constructs the name of the folder or open/save.
-// If the folder does not exist, it will be created.
-
-void CStudio::SearchDirectory(char *dir, bool bCreate)
-{
- if ( m_main->RetIOPublic() )
- {
- sprintf(dir, "%s\\", m_main->RetPublicDir());
- }
- else
- {
- sprintf(dir, "%s\\%s\\Program\\", m_main->RetSavegameDir(), m_main->RetGamerName());
- }
-
- if ( bCreate )
- {
- _mkdir(dir); // if does not exist yet!
- }
-}
-
-// Reads a new program.
-
-bool CStudio::ReadProgram()
-{
- CWindow* pw;
- CEdit* pe;
- char filename[100];
- char dir[100];
- char* p;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
- if ( pw == 0 ) return false;
-
- pe = (CEdit*)pw->SearchControl(EVENT_DIALOG_EDIT);
- if ( pe == 0 ) return false;
- pe->GetText(filename, 100);
- if ( filename[0] == 0 ) return false;
-
- p = strstr(filename, ".txt");
- if ( p == 0 || p != filename+strlen(filename)-4 )
- {
- strcat(filename, ".txt");
- }
- SearchDirectory(dir, true);
- strcat(dir, filename);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw == 0 ) return false;
- pe = (CEdit*)pw->SearchControl(EVENT_STUDIO_EDIT);
- if ( pe == 0 ) return false;
-
- if ( !pe->ReadText(dir) ) return false;
-
- m_script->SetFilename(filename);
- ColorizeScript(pe);
- return true;
-}
-
-// Writes the current program.
-
-bool CStudio::WriteProgram()
-{
- CWindow* pw;
- CEdit* pe;
- char filename[100];
- char dir[100];
- char* p;
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
- if ( pw == 0 ) return false;
-
- pe = (CEdit*)pw->SearchControl(EVENT_DIALOG_EDIT);
- if ( pe == 0 ) return false;
- pe->GetText(filename, 100);
- if ( filename[0] == 0 ) return false;
-
- p = strstr(filename, ".txt");
- if ( p == 0 || p != filename+strlen(filename)-4 )
- {
- strcat(filename, ".txt");
- }
- SearchDirectory(dir, true);
- strcat(dir, filename);
-
- pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
- if ( pw == 0 ) return false;
- pe = (CEdit*)pw->SearchControl(EVENT_STUDIO_EDIT);
- if ( pe == 0 ) return false;
-
- if ( !pe->WriteText(dir) ) return false;
-
- m_script->SetFilename(filename);
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// studio.cpp
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <windows.h>
+#include <direct.h>
+#include <io.h>
+#include <time.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/language.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "old/math3d.h"
+#include "object/robotmain.h"
+#include "object/object.h"
+#include "old/camera.h"
+#include "old/sound.h"
+#include "script/script.h"
+#include "ui/interface.h"
+#include "ui/button.h"
+#include "ui/check.h"
+#include "ui/slider.h"
+#include "ui/edit.h"
+#include "ui/list.h"
+#include "ui/label.h"
+#include "ui/group.h"
+#include "ui/window.h"
+#include "old/text.h"
+#include "script/cbottoken.h"
+#include "ui/studio.h"
+
+
+
+
+// Object's constructor.
+
+CStudio::CStudio(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_STUDIO, this);
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_event = (CEvent*)m_iMan->SearchInstance(CLASS_EVENT);
+ m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+
+ m_bEditMaximized = false;
+ m_bEditMinimized = false;
+
+ m_time = 0.0f;
+ m_bRealTime = true;
+ m_bRunning = false;
+ m_fixInfoTextTime = 0.0f;
+ m_helpFilename[0] = 0;
+ m_dialog = SD_NULL;
+}
+
+// Object's destructor.
+
+CStudio::~CStudio()
+{
+ m_iMan->DeleteInstance(CLASS_STUDIO, this);
+}
+
+
+// Management of an event.
+
+bool CStudio::EventProcess(const Event &event)
+{
+ CWindow* pw;
+ CEdit* edit;
+ CSlider* slider;
+ char res[100];
+
+ if ( m_dialog != SD_NULL ) // dialogue exists?
+ {
+ return EventDialog(event);
+ }
+
+ if ( event.event == EVENT_FRAME )
+ {
+ EventFrame(event);
+ }
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw == 0 ) return false;
+
+ edit = (CEdit*)pw->SearchControl(EVENT_STUDIO_EDIT);
+ if ( edit == 0 ) return false;
+
+ if ( event.event == pw->RetEventMsgClose() )
+ {
+ Event newEvent = event;
+ newEvent.event = EVENT_STUDIO_OK;
+ m_event->AddEvent(newEvent);
+ }
+
+ if ( event.event == EVENT_STUDIO_EDIT ) // text modifief?
+ {
+ ColorizeScript(edit);
+ }
+
+ if ( event.event == EVENT_STUDIO_LIST ) // list clicked?
+ {
+ m_main->StartDisplayInfo(m_helpFilename, -1);
+ }
+
+ if ( event.event == EVENT_STUDIO_NEW ) // new?
+ {
+ m_script->New(edit, "");
+ }
+
+ if ( event.event == EVENT_STUDIO_OPEN ) // open?
+ {
+ StartDialog(SD_OPEN);
+ }
+ if ( event.event == EVENT_STUDIO_SAVE ) // save?
+ {
+ StartDialog(SD_SAVE);
+ }
+
+ if ( event.event == EVENT_STUDIO_UNDO ) // undo?
+ {
+ edit->Undo();
+ }
+ if ( event.event == EVENT_STUDIO_CUT ) // cut?
+ {
+ edit->Cut();
+ }
+ if ( event.event == EVENT_STUDIO_COPY ) // copy?
+ {
+ edit->Copy();
+ }
+ if ( event.event == EVENT_STUDIO_PASTE ) // paste?
+ {
+ edit->Paste();
+ }
+
+ if ( event.event == EVENT_STUDIO_SIZE ) // size?
+ {
+ slider = (CSlider*)pw->SearchControl(EVENT_STUDIO_SIZE);
+ if ( slider == 0 ) return false;
+ m_main->SetFontSize(9.0f+slider->RetVisibleValue()*6.0f);
+ ViewEditScript();
+ }
+
+ if ( event.event == EVENT_STUDIO_TOOL && // instructions?
+ m_dialog == SD_NULL )
+ {
+ m_main->StartDisplayInfo(SATCOM_HUSTON, false);
+ }
+ if ( event.event == EVENT_STUDIO_HELP && // help?
+ m_dialog == SD_NULL )
+ {
+ m_main->StartDisplayInfo(SATCOM_PROG, false);
+ }
+
+ if ( event.event == EVENT_STUDIO_COMPILE ) // compile?
+ {
+ char buffer[100];
+
+ if ( m_script->GetScript(edit) ) // compile
+ {
+ GetResource(RES_TEXT, RT_STUDIO_COMPOK, res);
+ SetInfoText(res, false);
+ }
+ else
+ {
+ m_script->GetError(buffer);
+ SetInfoText(buffer, false);
+ }
+ }
+
+ if ( event.event == EVENT_STUDIO_RUN ) // run/stop?
+ {
+ if ( m_script->IsRunning() )
+ {
+ Event newEvent = event;
+ newEvent.event = EVENT_OBJECT_PROGSTOP;
+ m_event->AddEvent(newEvent); // stop
+ }
+ else
+ {
+ if ( m_script->GetScript(edit) ) // compile
+ {
+ SetInfoText("", false);
+
+ Event newEvent = event;
+ newEvent.event = EVENT_OBJECT_PROGSTART;
+ m_event->AddEvent(newEvent); // start
+ }
+ else
+ {
+ char buffer[100];
+ m_script->GetError(buffer);
+ SetInfoText(buffer, false);
+ }
+ }
+ }
+
+ if ( event.event == EVENT_STUDIO_REALTIME ) // real time?
+ {
+ m_bRealTime = !m_bRealTime;
+ m_script->SetStepMode(!m_bRealTime);
+ UpdateFlux();
+ UpdateButtons();
+ }
+
+ if ( event.event == EVENT_STUDIO_STEP ) // step?
+ {
+ m_script->Step(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+ if ( event.param == m_engine->RetKey(KEYRANK_CBOT, 0) ||
+ event.param == m_engine->RetKey(KEYRANK_CBOT, 1) )
+ {
+ if ( m_helpFilename[0] != 0 )
+ {
+ m_main->StartDisplayInfo(m_helpFilename, -1);
+ }
+ }
+ }
+
+ if ( event.event == EVENT_WINDOW3 ) // window is moved?
+ {
+ m_editActualPos = m_editFinalPos = pw->RetPos();
+ m_editActualDim = m_editFinalDim = pw->RetDim();
+ m_main->SetWindowPos(m_editActualPos);
+ m_main->SetWindowDim(m_editActualDim);
+ AdjustEditScript();
+ }
+ if ( event.event == pw->RetEventMsgReduce() )
+ {
+ if ( m_bEditMinimized )
+ {
+ m_editFinalPos = m_main->RetWindowPos();
+ m_editFinalDim = m_main->RetWindowDim();
+ m_bEditMinimized = false;
+ m_bEditMaximized = false;
+ }
+ else
+ {
+ m_editFinalPos.x = 0.00f;
+ m_editFinalPos.y = -0.44f;
+ m_editFinalDim.x = 1.00f;
+ m_editFinalDim.y = 0.50f;
+ m_bEditMinimized = true;
+ m_bEditMaximized = false;
+ }
+ m_main->SetEditFull(m_bEditMaximized);
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw != 0 )
+ {
+ pw->SetMaximized(m_bEditMaximized);
+ pw->SetMinimized(m_bEditMinimized);
+ }
+ }
+ if ( event.event == pw->RetEventMsgFull() )
+ {
+ if ( m_bEditMaximized )
+ {
+ m_editFinalPos = m_main->RetWindowPos();
+ m_editFinalDim = m_main->RetWindowDim();
+ m_bEditMinimized = false;
+ m_bEditMaximized = false;
+ }
+ else
+ {
+ m_editFinalPos.x = 0.00f;
+ m_editFinalPos.y = 0.00f;
+ m_editFinalDim.x = 1.00f;
+ m_editFinalDim.y = 1.00f;
+ m_bEditMinimized = false;
+ m_bEditMaximized = true;
+ }
+ m_main->SetEditFull(m_bEditMaximized);
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw != 0 )
+ {
+ pw->SetMaximized(m_bEditMaximized);
+ pw->SetMinimized(m_bEditMinimized);
+ }
+ }
+
+ return true;
+}
+
+
+// Evolves value with time elapsed.
+
+float Evolution(float final, float actual, float time)
+{
+ float value;
+
+ value = actual + (final-actual)*time;
+
+ if ( final > actual )
+ {
+ if ( value > final ) value = final; // does not exceed
+ }
+ else
+ {
+ if ( value < final ) value = final; // does not exceed
+ }
+
+ return value;
+}
+
+// Makes the studio evolve as time elapsed.
+
+bool CStudio::EventFrame(const Event &event)
+{
+ CWindow* pw;
+ CEdit* edit;
+ CList* list;
+ float time;
+ int cursor1, cursor2, iCursor1, iCursor2;
+ char res[100];
+
+ m_time += event.rTime;
+ m_fixInfoTextTime -= event.rTime;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw == 0 ) return false;
+
+ edit = (CEdit*)pw->SearchControl(EVENT_STUDIO_EDIT);
+ if ( edit == 0 ) return false;
+
+ list = (CList*)pw->SearchControl(EVENT_STUDIO_LIST);
+ if ( list == 0 ) return false;
+
+ if ( !m_script->IsRunning() && m_bRunning ) // stop?
+ {
+ m_bRunning = false;
+ UpdateFlux(); // stop
+ AdjustEditScript();
+ GetResource(RES_TEXT, RT_STUDIO_PROGSTOP, res);
+ SetInfoText(res, false);
+
+ Event newEvent = event;
+ newEvent.event = EVENT_OBJECT_PROGSTOP;
+ m_event->AddEvent(newEvent); // stop
+ }
+
+ if ( m_script->IsRunning() && !m_bRunning ) // starting?
+ {
+ m_bRunning = true;
+ UpdateFlux(); // run
+ AdjustEditScript();
+ }
+ UpdateButtons();
+
+ if ( m_bRunning )
+ {
+ m_script->GetCursor(cursor1, cursor2);
+ edit->GetCursor(iCursor1, iCursor2);
+ if ( cursor1 != iCursor1 ||
+ cursor2 != iCursor2 ) // cursors change?
+ {
+ edit->SetCursor(cursor1, cursor2); // shows it on the execution
+ edit->ShowSelect();
+ }
+
+ m_script->UpdateList(list); // updates the list of variables
+ }
+ else
+ {
+ SearchToken(edit);
+ }
+
+ if ( m_editFinalPos.x != m_editActualPos.x ||
+ m_editFinalPos.y != m_editActualPos.y ||
+ m_editFinalDim.x != m_editActualDim.x ||
+ m_editFinalDim.y != m_editActualDim.y )
+ {
+ time = event.rTime*20.0f;
+ m_editActualPos.x = Evolution(m_editFinalPos.x, m_editActualPos.x, time);
+ m_editActualPos.y = Evolution(m_editFinalPos.y, m_editActualPos.y, time);
+ m_editActualDim.x = Evolution(m_editFinalDim.x, m_editActualDim.x, time);
+ m_editActualDim.y = Evolution(m_editFinalDim.y, m_editActualDim.y, time);
+ AdjustEditScript();
+ }
+
+ return true;
+}
+
+
+// Indicates whether a character is part of a word.
+
+bool IsToken(int character)
+{
+ char c;
+
+ c = tolower(RetNoAccent(character));
+
+ return ( (c >= 'a' && c <= 'z') ||
+ (c >= '0' && c <= '9') ||
+ c == '_' );
+}
+
+// Seeks if the cursor is on a keyword.
+
+void CStudio::SearchToken(CEdit* edit)
+{
+ ObjectType type;
+ int len, cursor1, cursor2, i, character, level;
+ char* text;
+ char token[100];
+
+ text = edit->RetText();
+ len = edit->RetTextLength();
+ edit->GetCursor(cursor1, cursor2);
+
+ i = cursor1;
+ if ( i > 0 )
+ {
+ character = (unsigned char)text[i-1];
+ if ( !IsToken(character) )
+ {
+ level = 1;
+ while ( i > 0 )
+ {
+ character = (unsigned char)text[i-1];
+ if ( character == ')' )
+ {
+ level ++;
+ }
+ else if ( character == '(' )
+ {
+ level --;
+ if ( level == 0 ) break;
+ }
+ i --;
+ }
+ if ( level > 0 )
+ {
+ m_helpFilename[0] = 0;
+ SetInfoText("", true);
+ return;
+ }
+ while ( i > 0 )
+ {
+ character = (unsigned char)text[i-1];
+ if ( IsToken(character) ) break;
+ i --;
+ }
+ }
+ }
+
+ while ( i > 0 )
+ {
+ character = (unsigned char)text[i-1];
+ if ( !IsToken(character) ) break;
+ i --;
+ }
+ cursor2 = i;
+
+ while ( i < len )
+ {
+ character = (unsigned char)text[i];
+ if ( !IsToken(character) ) break;
+ i ++;
+ }
+ cursor1 = i;
+ len = cursor1-cursor2;
+
+ if ( len > 100-1 ) len = 100-1;
+ for ( i=0 ; i<len ; i++ )
+ {
+ token[i] = text[cursor2+i];
+ }
+ token[i] = 0;
+
+ strcpy(m_helpFilename, RetHelpFilename(token));
+ if ( m_helpFilename[0] == 0 )
+ {
+ for ( i=0 ; i<OBJECT_MAX ; i++ )
+ {
+ type = (ObjectType)i;
+ text = RetObjectName(type);
+ if ( text[0] != 0 )
+ {
+ if ( strcmp(token, text) == 0 )
+ {
+ strcpy(m_helpFilename, RetHelpFilename(type));
+ SetInfoText(token, true);
+ return;
+ }
+ }
+ text = RetObjectAlias(type);
+ if ( text[0] != 0 )
+ {
+ if ( strcmp(token, text) == 0 )
+ {
+ strcpy(m_helpFilename, RetHelpFilename(type));
+ SetInfoText(token, true);
+ return;
+ }
+ }
+ }
+ }
+
+ text = RetHelpText(token);
+ if ( text[0] == 0 && m_helpFilename[0] != 0 )
+ {
+ SetInfoText(token, true);
+ }
+ else
+ {
+ SetInfoText(text, true);
+ }
+}
+
+// Colors the text according to syntax.
+
+void CStudio::ColorizeScript(CEdit* edit)
+{
+ m_script->ColorizeScript(edit);
+}
+
+
+// Starts editing a program.
+
+void CStudio::StartEditScript(CScript *script, char* name, int rank)
+{
+ Math::Point pos, dim;
+ CWindow* pw;
+ CEdit* edit;
+ CButton* button;
+ CSlider* slider;
+ CList* list;
+ char res[100];
+
+ m_script = script;
+ m_rank = rank;
+
+ m_main->SetEditLock(true, true);
+ m_main->SetEditFull(false);
+ m_bInitPause = m_engine->RetPause();
+ m_main->SetSpeed(1.0f);
+ m_editCamera = m_camera->RetType();
+ m_camera->SetType(CAMERA_EDIT);
+
+ m_bRunning = m_script->IsRunning();
+ m_bRealTime = m_bRunning;
+ m_script->SetStepMode(!m_bRealTime);
+
+ button = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
+ if ( button != 0 )
+ {
+ button->ClearState(STATE_VISIBLE);
+ }
+
+ pos = m_editFinalPos = m_editActualPos = m_main->RetWindowPos();
+ dim = m_editFinalDim = m_editActualDim = m_main->RetWindowDim();
+ pw = m_interface->CreateWindows(pos, dim, 8, EVENT_WINDOW3);
+ if ( pw == 0 ) return;
+ pw->SetState(STATE_SHADOW);
+ pw->SetRedim(true); // before SetName!
+ pw->SetMovable(true);
+ pw->SetClosable(true);
+ GetResource(RES_TEXT, RT_STUDIO_TITLE, res);
+ pw->SetName(res);
+ pw->SetMinDim(Math::Point(0.49f, 0.50f));
+ pw->SetMaximized(m_bEditMaximized);
+ pw->SetMinimized(m_bEditMinimized);
+ m_main->SetEditFull(m_bEditMaximized);
+
+ edit = pw->CreateEdit(pos, dim, 0, EVENT_STUDIO_EDIT);
+ if ( edit == 0 ) return;
+ edit->SetState(STATE_SHADOW);
+ edit->SetInsideScroll(false);
+//? if ( m_bRunning ) edit->SetEdit(false);
+ edit->SetMaxChar(EDITSTUDIOMAX);
+ edit->SetFontType(FONT_COURIER);
+ edit->SetFontStretch(0.7f);
+ edit->SetDisplaySpec(true);
+ edit->SetAutoIndent(m_engine->RetEditIndentMode());
+ m_script->PutScript(edit, name);
+ ColorizeScript(edit);
+
+ ViewEditScript();
+
+ list = pw->CreateList(pos, dim, 1, EVENT_STUDIO_LIST, 1.2f);
+ list->SetState(STATE_SHADOW);
+ list->SetFontType(FONT_COURIER);
+ list->SetSelectCap(false);
+ list->SetFontSize(SMALLFONT*0.85f);
+//? list->SetFontStretch(1.0f);
+
+ button = pw->CreateButton(pos, dim, 56, EVENT_STUDIO_NEW);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 57, EVENT_STUDIO_OPEN);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 58, EVENT_STUDIO_SAVE);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 59, EVENT_STUDIO_UNDO);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 60, EVENT_STUDIO_CUT);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 61, EVENT_STUDIO_COPY);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 62, EVENT_STUDIO_PASTE);
+ button->SetState(STATE_SHADOW);
+ slider = pw->CreateSlider(pos, dim, 0, EVENT_STUDIO_SIZE);
+ slider->SetState(STATE_SHADOW);
+ slider->SetVisibleValue((m_main->RetFontSize()-9.0f)/6.0f);
+ pw->CreateGroup(pos, dim, 19, EVENT_LABEL1); // SatCom logo
+ button = pw->CreateButton(pos, dim, 128+57, EVENT_STUDIO_TOOL);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 128+60, EVENT_STUDIO_HELP);
+ button->SetState(STATE_SHADOW);
+
+ button = pw->CreateButton(pos, dim, -1, EVENT_STUDIO_OK);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, -1, EVENT_STUDIO_CANCEL);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 64+23, EVENT_STUDIO_COMPILE);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 21, EVENT_STUDIO_RUN);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 64+22, EVENT_STUDIO_REALTIME);
+ button->SetState(STATE_SHADOW);
+ button = pw->CreateButton(pos, dim, 64+29, EVENT_STUDIO_STEP);
+ button->SetState(STATE_SHADOW);
+
+ UpdateFlux();
+ UpdateButtons();
+ AdjustEditScript();
+}
+
+// Repositions all the editing controls.
+
+void CStudio::AdjustEditScript()
+{
+ CWindow* pw;
+ CEdit* edit;
+ CButton* button;
+ CGroup* group;
+ CSlider* slider;
+ CList* list;
+ Math::Point wpos, wdim, pos, dim, ppos, ddim;
+ float hList;
+
+ wpos = m_editActualPos;
+ wdim = m_editActualDim;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw != 0 )
+ {
+ pw->SetPos(wpos);
+ pw->SetDim(wdim);
+ wdim = pw->RetDim();
+ }
+
+ if ( m_bRunning ) hList = 80.0f/480.0f;
+ else hList = 20.0f/480.0f;
+
+ pos.x = wpos.x+0.01f;
+ pos.y = wpos.y+0.09f+hList;
+ dim.x = wdim.x-0.02f;
+ dim.y = wdim.y-0.22f-hList;
+ edit = (CEdit*)pw->SearchControl(EVENT_STUDIO_EDIT);
+ if ( edit != 0 )
+ {
+ edit->SetPos(pos);
+ edit->SetDim(dim);
+ }
+
+ pos.x = wpos.x+0.01f;
+ pos.y = wpos.y+0.09f;
+ dim.x = wdim.x-0.02f;
+ dim.y = hList;
+ list = (CList*)pw->SearchControl(EVENT_STUDIO_LIST);
+ if ( list != 0 )
+ {
+ list->SetPos(pos);
+ list->SetDim(dim);
+ }
+
+ dim.x = 0.04f;
+ dim.y = 0.04f*1.5f;
+ dim.y = 25.0f/480.0f;
+
+ pos.y = wpos.y+wdim.y-dim.y-0.06f;
+ pos.x = wpos.x+0.01f;
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_NEW);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x = wpos.x+0.05f;
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_OPEN);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x = wpos.x+0.09f;
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_SAVE);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x = wpos.x+0.14f;
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_UNDO);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x = wpos.x+0.19f;
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_CUT);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x = wpos.x+0.23f;
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_COPY);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x = wpos.x+0.27f;
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_PASTE);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x = wpos.x+0.32f;
+ slider = (CSlider*)pw->SearchControl(EVENT_STUDIO_SIZE);
+ if ( slider != 0 )
+ {
+ ppos = pos;
+ ddim.x = dim.x*0.7f;
+ ddim.y = dim.y;
+ ppos.y -= 3.0f/480.0f;
+ ddim.y += 6.0f/480.0f;
+ slider->SetPos(ppos);
+ slider->SetDim(ddim);
+ }
+ pos.x = wpos.x+0.36f;
+ group = (CGroup*)pw->SearchControl(EVENT_LABEL1);
+ if ( group != 0 )
+ {
+ group->SetPos(pos);
+ group->SetDim(dim);
+ }
+ pos.x = wpos.x+0.40f;
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_TOOL);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x = wpos.x+0.44f;
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_HELP);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+
+ pos.y = wpos.y+0.02f;
+ pos.x = wpos.x+0.01f;
+ dim.x = 80.0f/640.0f;
+ dim.y = 25.0f/480.0f;
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_OK);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x = wpos.x+0.14f;
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_CANCEL);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x = wpos.x+0.28f;
+ dim.x = dim.y*0.75f;
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_COMPILE);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x = wpos.x+0.28f+dim.x*1;
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_RUN);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x = wpos.x+0.28f+dim.x*2;
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_REALTIME);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+ pos.x = wpos.x+0.28f+dim.x*3;
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_STEP);
+ if ( button != 0 )
+ {
+ button->SetPos(pos);
+ button->SetDim(dim);
+ }
+}
+
+// Ends edition of a program.
+
+bool CStudio::StopEditScript(bool bCancel)
+{
+ CWindow* pw;
+ CEdit* edit;
+ CButton* button;
+ char buffer[100];
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw == 0 ) return false;
+
+ if ( !bCancel && !m_script->IsRunning() )
+ {
+ edit = (CEdit*)pw->SearchControl(EVENT_STUDIO_EDIT);
+ if ( edit != 0 )
+ {
+ if ( !m_script->GetScript(edit) ) // compile
+ {
+ m_script->GetError(buffer);
+ SetInfoText(buffer, false);
+ return false;
+ }
+ }
+ }
+ m_script->SetStepMode(false);
+
+ m_interface->DeleteControl(EVENT_WINDOW3);
+
+ button = (CButton*)m_interface->SearchControl(EVENT_BUTTON_QUIT);
+ if ( button != 0 )
+ {
+ button->SetState(STATE_VISIBLE);
+ }
+
+ if ( !m_bInitPause ) m_engine->SetPause(false);
+ m_sound->MuteAll(false);
+ m_main->SetEditLock(false, true);
+ m_camera->SetType(m_editCamera);
+ return true;
+}
+
+// Specifies the message to display.
+// The messages are not clickable 8 seconds,
+// even if a message was clickable poster before.
+
+void CStudio::SetInfoText(char *text, bool bClickable)
+{
+ CWindow* pw;
+ CList* list;
+ char res[100];
+
+ if ( bClickable && m_fixInfoTextTime > 0.0f ) return;
+ if ( !bClickable ) m_fixInfoTextTime = 8.0f;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw == 0 ) return;
+
+ list = (CList*)pw->SearchControl(EVENT_STUDIO_LIST);
+ if ( list == 0 ) return;
+
+ list->Flush(); // just text
+ list->SetName(0, text);
+
+ if ( text[0] == 0 ) bClickable = false;
+ list->SetSelectCap(bClickable);
+
+ if ( bClickable )
+ {
+ GetResource(RES_TEXT, RT_STUDIO_LISTTT, res);
+ list->SetTooltip(res);
+ list->SetState(STATE_ENABLE);
+ }
+ else
+ {
+ list->SetTooltip("");
+//? list->ClearState(STATE_ENABLE);
+ list->SetState(STATE_ENABLE, text[0] != 0);
+ }
+}
+
+
+// Changing the size of a editing program.
+
+void CStudio::ViewEditScript()
+{
+ CWindow* pw;
+ CEdit* edit;
+ POINT dim;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw == 0 ) return;
+
+ edit = (CEdit*)pw->SearchControl(EVENT_STUDIO_EDIT);
+ if ( edit == 0 ) return;
+
+ dim = m_engine->RetDim();
+ edit->SetFontSize(m_main->RetFontSize()/(dim.x/640.0f));
+}
+
+
+// Updates the operating mode.
+
+void CStudio::UpdateFlux()
+{
+ if ( m_bRunning )
+ {
+#if 1
+ if ( m_bRealTime ) // run?
+ {
+ m_engine->SetPause(false);
+ m_sound->MuteAll(false);
+ }
+ else // step by step?
+ {
+ m_engine->SetPause(true);
+ m_sound->MuteAll(true);
+ }
+#else
+ m_engine->SetPause(false);
+ m_sound->MuteAll(false);
+#endif
+ }
+ else // stop?
+ {
+ m_engine->SetPause(true);
+ m_sound->MuteAll(true);
+ }
+}
+
+// Updates the buttons.
+
+void CStudio::UpdateButtons()
+{
+ CWindow* pw;
+ CEdit* edit;
+ CButton* button;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw == 0 ) return;
+
+ edit = (CEdit*)pw->SearchControl(EVENT_STUDIO_EDIT);
+ if ( edit == 0 ) return;
+
+ if ( m_bRunning )
+ {
+ edit->SetIcon(1); // red background
+ edit->SetEditCap(false); // just to see
+ edit->SetHiliteCap(true);
+ }
+ else
+ {
+ edit->SetIcon(0); // standard background
+ edit->SetEditCap(true);
+ edit->SetHiliteCap(true);
+ }
+
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_COMPILE);
+ if ( button == 0 ) return;
+ button->SetState(STATE_ENABLE, !m_bRunning);
+
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_RUN);
+ if ( button == 0 ) return;
+ button->SetIcon(m_bRunning?8:21); // stop/run
+
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_REALTIME);
+ if ( button == 0 ) return;
+ button->SetIcon(m_bRealTime?64+22:64+21);
+ button->SetState(STATE_ENABLE, (!m_bRunning || !m_script->IsContinue()));
+
+ button = (CButton*)pw->SearchControl(EVENT_STUDIO_STEP);
+ if ( button == 0 ) return;
+ button->SetState(STATE_ENABLE, (m_bRunning && !m_bRealTime && !m_script->IsContinue()));
+}
+
+
+// Beginning of the display of a dialogue.
+
+void CStudio::StartDialog(StudioDialog type)
+{
+ CWindow* pw;
+ CButton* pb;
+ CCheck* pc;
+ CLabel* pla;
+ CList* pli;
+ CEdit* pe;
+ Math::Point pos, dim;
+ char name[100];
+
+ m_dialog = type;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW6);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW7);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW8);
+ if ( pw != 0 ) pw->ClearState(STATE_ENABLE);
+
+ if ( m_dialog == SD_OPEN ||
+ m_dialog == SD_SAVE )
+ {
+ pos = m_main->RetIOPos();
+ dim = m_main->RetIODim();
+ }
+//? pw = m_interface->CreateWindows(pos, dim, 8, EVENT_WINDOW9);
+ pw = m_interface->CreateWindows(pos, dim, m_dialog==SD_OPEN?14:13, EVENT_WINDOW9);
+ pw->SetState(STATE_SHADOW);
+ pw->SetMovable(true);
+ pw->SetClosable(true);
+ pw->SetMinDim(Math::Point(320.0f/640.0f, (121.0f+18.0f*4)/480.0f));
+ if ( m_dialog == SD_OPEN ) GetResource(RES_TEXT, RT_IO_OPEN, name);
+ if ( m_dialog == SD_SAVE ) GetResource(RES_TEXT, RT_IO_SAVE, name);
+ pw->SetName(name);
+
+ pos = Math::Point(0.0f, 0.0f);
+ dim = Math::Point(0.0f, 0.0f);
+
+ if ( m_dialog == SD_OPEN ||
+ m_dialog == SD_SAVE )
+ {
+ GetResource(RES_TEXT, RT_IO_LIST, name);
+ pla = pw->CreateLabel(pos, dim, 0, EVENT_DIALOG_LABEL1, name);
+ pla->SetJustif(1);
+
+ pli = pw->CreateList(pos, dim, 0, EVENT_DIALOG_LIST);
+ pli->SetState(STATE_SHADOW);
+
+ GetResource(RES_TEXT, RT_IO_NAME, name);
+ pla = pw->CreateLabel(pos, dim, 0, EVENT_DIALOG_LABEL2, name);
+ pla->SetJustif(1);
+
+ pe = pw->CreateEdit(pos, dim, 0, EVENT_DIALOG_EDIT);
+ pe->SetState(STATE_SHADOW);
+ if ( m_dialog == SD_SAVE )
+ {
+ pe->SetText(m_script->RetFilename());
+ }
+
+ GetResource(RES_TEXT, RT_IO_DIR, name);
+ pla = pw->CreateLabel(pos, dim, 0, EVENT_DIALOG_LABEL3, name);
+ pla->SetJustif(1);
+
+ pc = pw->CreateCheck(pos, dim, 0, EVENT_DIALOG_CHECK1);
+ GetResource(RES_TEXT, RT_IO_PRIVATE, name);
+ pc->SetName(name);
+ pc->SetState(STATE_SHADOW);
+#if _POLISH
+ pc->SetFontSize(8.0f);
+#endif
+
+ pc = pw->CreateCheck(pos, dim, 0, EVENT_DIALOG_CHECK2);
+ GetResource(RES_TEXT, RT_IO_PUBLIC, name);
+ pc->SetName(name);
+ pc->SetState(STATE_SHADOW);
+#if _POLISH
+ pc->SetFontSize(8.0f);
+#endif
+
+ pb = pw->CreateButton(pos, dim, -1, EVENT_DIALOG_OK);
+ pb->SetState(STATE_SHADOW);
+ if ( m_dialog == SD_OPEN ) GetResource(RES_TEXT, RT_IO_OPEN, name);
+ if ( m_dialog == SD_SAVE ) GetResource(RES_TEXT, RT_IO_SAVE, name);
+ pb->SetName(name);
+
+ pb = pw->CreateButton(pos, dim, -1, EVENT_DIALOG_CANCEL);
+ pb->SetState(STATE_SHADOW);
+ GetResource(RES_EVENT, EVENT_DIALOG_CANCEL, name);
+ pb->SetName(name);
+
+ AdjustDialog();
+ UpdateDialogList();
+ UpdateDialogPublic();
+ UpdateDialogAction();
+
+ pe->SetCursor(999, 0); // selects all
+ pe->SetFocus(true);
+ }
+
+ m_main->SetSatComLock(true); // impossible to use the SatCom
+}
+
+// End of the display of a dialogue.
+
+void CStudio::StopDialog()
+{
+ CWindow* pw;
+
+ if ( m_dialog == SD_NULL ) return;
+ m_dialog = SD_NULL;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW0);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW1);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW4);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW5);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW6);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW7);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW8);
+ if ( pw != 0 ) pw->SetState(STATE_ENABLE);
+
+ m_interface->DeleteControl(EVENT_WINDOW9);
+ m_main->SetSatComLock(false); // possible to use the SatCom
+}
+
+// Adjust all controls of dialogue after a change in geometry.
+
+void CStudio::AdjustDialog()
+{
+ CWindow* pw;
+ CButton* pb;
+ CCheck* pc;
+ CLabel* pla;
+ CList* pli;
+ CEdit* pe;
+ Math::Point wpos, wdim, ppos, ddim;
+ int nli, nch;
+ char name[100];
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
+ if ( pw == 0 ) return;
+
+ wpos = pw->RetPos();
+ wdim = pw->RetDim();
+ pw->SetPos(wpos); // to move the buttons on the titlebar
+
+ if ( m_dialog == SD_OPEN ||
+ m_dialog == SD_SAVE )
+ {
+ ppos.x = wpos.x+10.0f/640.0f;
+ ppos.y = wpos.y+wdim.y-55.0f/480.0f;
+ ddim.x = wdim.x-20.0f/640.0f;
+ ddim.y = 20.0f/480.0f;
+ pla = (CLabel*)pw->SearchControl(EVENT_DIALOG_LABEL1);
+ if ( pla != 0 )
+ {
+ pla->SetPos(ppos);
+ pla->SetDim(ddim);
+ }
+
+ nli = (int)((wdim.y-120.0f/480.0f)/(18.0f/480.0f));
+ ddim.y = nli*18.0f/480.0f+9.0f/480.0f;
+ ppos.y = wpos.y+wdim.y-48.0f/480.0f-ddim.y;
+ pli = (CList*)pw->SearchControl(EVENT_DIALOG_LIST);
+ if ( pli != 0 )
+ {
+ pli->SetPos(ppos);
+ pli->SetDim(ddim);
+ pli->SetTabs(0, ddim.x-(50.0f+130.0f+16.0f)/640.0f);
+ pli->SetTabs(1, 50.0f/640.0f, -1);
+ pli->SetTabs(2, 130.0f/640.0f);
+//? pli->ShowSelect();
+ }
+
+ ppos.y = wpos.y+30.0f/480.0f;
+ ddim.x = 50.0f/640.0f;
+ ddim.y = 20.0f/480.0f;
+ pla = (CLabel*)pw->SearchControl(EVENT_DIALOG_LABEL2);
+ if ( pla != 0 )
+ {
+ pla->SetPos(ppos);
+ pla->SetDim(ddim);
+ }
+
+ ppos.x += 50.0f/640.0f;
+ ppos.y = wpos.y+36.0f/480.0f;
+ ddim.x = wdim.x-170.0f/640.0f;
+ pe = (CEdit*)pw->SearchControl(EVENT_DIALOG_EDIT);
+ if ( pe != 0 )
+ {
+ pe->SetPos(ppos);
+ pe->SetDim(ddim);
+
+ nch = (int)((ddim.x*640.0f-22.0f)/8.0f);
+ pe->GetText(name, 100);
+ pe->SetMaxChar(nch);
+ name[nch] = 0; // truncates the text according to max
+ pe->SetText(name);
+ }
+
+ ppos.x = wpos.x+10.0f/640.0f;
+ ppos.y = wpos.y+5.0f/480.0f;
+ ddim.x = 50.0f/640.0f;
+ ddim.y = 16.0f/480.0f;
+ pla = (CLabel*)pw->SearchControl(EVENT_DIALOG_LABEL3);
+ if ( pla != 0 )
+ {
+ pla->SetPos(ppos);
+ pla->SetDim(ddim);
+ }
+
+ ppos.x += 50.0f/640.0f;
+ ppos.y = wpos.y+12.0f/480.0f;
+ ddim.x = 70.0f/640.0f;
+ pc = (CCheck*)pw->SearchControl(EVENT_DIALOG_CHECK1);
+ if ( pc != 0 )
+ {
+ pc->SetPos(ppos);
+ pc->SetDim(ddim);
+ }
+
+ ppos.x += 80.0f/640.0f;
+ pc = (CCheck*)pw->SearchControl(EVENT_DIALOG_CHECK2);
+ if ( pc != 0 )
+ {
+ pc->SetPos(ppos);
+ pc->SetDim(ddim);
+ }
+
+ ppos.x = wpos.x+wdim.x-100.0f/640.0f;
+ ppos.y = wpos.y+34.0f/480.0f;
+ ddim.x = 90.0f/640.0f;
+ ddim.y = 23.0f/480.0f;
+ pb = (CButton*)pw->SearchControl(EVENT_DIALOG_OK);
+ if ( pb != 0 )
+ {
+ pb->SetPos(ppos);
+ pb->SetDim(ddim);
+ }
+
+ ppos.y -= 26.0f/480.0f;
+ pb = (CButton*)pw->SearchControl(EVENT_DIALOG_CANCEL);
+ if ( pb != 0 )
+ {
+ pb->SetPos(ppos);
+ pb->SetDim(ddim);
+ }
+ }
+}
+
+// Management of the event of a dialogue.
+
+bool CStudio::EventDialog(const Event &event)
+{
+ CWindow* pw;
+ Math::Point wpos, wdim;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
+ if ( pw == 0 ) return false;
+
+ if ( event.event == EVENT_WINDOW9 ) // window is moved?
+ {
+ wpos = pw->RetPos();
+ wdim = pw->RetDim();
+ m_main->SetIOPos(wpos);
+ m_main->SetIODim(wdim);
+ AdjustDialog();
+ }
+
+ if ( m_dialog == SD_OPEN ||
+ m_dialog == SD_SAVE )
+ {
+ if ( event.event == EVENT_DIALOG_LIST )
+ {
+ UpdateChangeList();
+ }
+ if ( event.event == EVENT_DIALOG_EDIT )
+ {
+ UpdateChangeEdit();
+ }
+
+ if ( event.event == EVENT_DIALOG_CHECK1 ) // private?
+ {
+ m_main->SetIOPublic(false);
+ UpdateDialogPublic();
+ UpdateDialogList();
+ }
+ if ( event.event == EVENT_DIALOG_CHECK2 ) // public?
+ {
+ m_main->SetIOPublic(true);
+ UpdateDialogPublic();
+ UpdateDialogList();
+ }
+ }
+
+ if ( event.event == EVENT_DIALOG_OK ||
+ (event.event == EVENT_KEYDOWN && event.param == VK_RETURN) )
+ {
+ if ( m_dialog == SD_OPEN )
+ {
+ if ( !ReadProgram() ) return true;
+ }
+ if ( m_dialog == SD_SAVE )
+ {
+ if ( !WriteProgram() ) return true;
+ }
+
+ StopDialog();
+ return true;
+ }
+
+ if ( event.event == EVENT_DIALOG_CANCEL ||
+ (event.event == EVENT_KEYDOWN && event.param == VK_ESCAPE) ||
+ event.event == pw->RetEventMsgClose() )
+ {
+ StopDialog();
+ return true;
+ }
+
+ return true;
+}
+
+// Updates the name after a click in the list.
+
+void CStudio::UpdateChangeList()
+{
+ CWindow* pw;
+ CList* pl;
+ CEdit* pe;
+ char name[100];
+ char* p;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
+ if ( pw == 0 ) return;
+ pl = (CList*)pw->SearchControl(EVENT_DIALOG_LIST);
+ if ( pl == 0 ) return;
+ pe = (CEdit*)pw->SearchControl(EVENT_DIALOG_EDIT);
+ if ( pe == 0 ) return;
+
+ strcpy(name, pl->RetName(pl->RetSelect()));
+ name[pe->RetMaxChar()] = 0; // truncates according lg max editable
+ p = strchr(name, '\t'); // seeks first tab
+ if ( p != 0 ) *p = 0;
+ pe->SetText(name);
+ pe->SetCursor(999, 0); // selects all
+ pe->SetFocus(true);
+
+ UpdateDialogAction();
+}
+
+// Updates the list after a change in name.
+
+void CStudio::UpdateChangeEdit()
+{
+ CWindow* pw;
+ CList* pl;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
+ if ( pw == 0 ) return;
+ pl = (CList*)pw->SearchControl(EVENT_DIALOG_LIST);
+ if ( pl == 0 ) return;
+
+ pl->SetSelect(-1);
+
+ UpdateDialogAction();
+}
+
+// Updates the action button.
+
+void CStudio::UpdateDialogAction()
+{
+ CWindow* pw;
+ CEdit* pe;
+ CButton* pb;
+ char name[100];
+ int len, i;
+ bool bError;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
+ if ( pw == 0 ) return;
+ pe = (CEdit*)pw->SearchControl(EVENT_DIALOG_EDIT);
+ if ( pe == 0 ) return;
+ pb = (CButton*)pw->SearchControl(EVENT_DIALOG_OK);
+ if ( pb == 0 ) return;
+
+ pe->GetText(name, 100);
+ len = strlen(name);
+ if ( len == 0 )
+ {
+ bError = true;
+ }
+ else
+ {
+ bError = false;
+ for ( i=0 ; i<len ; i++ )
+ {
+ if ( name[i] == '*' ||
+ name[i] == '?' ||
+ name[i] == ':' ||
+ name[i] == '<' ||
+ name[i] == '>' ||
+ name[i] == '"' ||
+ name[i] == '|' ||
+ name[i] == '/' ||
+ name[i] == '\\' ) bError = true;
+ }
+ }
+
+ pb->SetState(STATE_ENABLE, !bError);
+}
+
+// Updates the buttons private/public.
+
+void CStudio::UpdateDialogPublic()
+{
+ CWindow* pw;
+ CCheck* pc;
+ CLabel* pl;
+ char name[100];
+ char dir[_MAX_FNAME];
+ char text[_MAX_FNAME+100];
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
+ if ( pw == 0 ) return;
+
+ pc = (CCheck*)pw->SearchControl(EVENT_DIALOG_CHECK1);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, !m_main->RetIOPublic());
+ }
+
+ pc = (CCheck*)pw->SearchControl(EVENT_DIALOG_CHECK2);
+ if ( pc != 0 )
+ {
+ pc->SetState(STATE_CHECK, m_main->RetIOPublic());
+ }
+
+ pl = (CLabel*)pw->SearchControl(EVENT_DIALOG_LABEL1);
+ if ( pl != 0 )
+ {
+ GetResource(RES_TEXT, RT_IO_LIST, name);
+ SearchDirectory(dir, false);
+ sprintf(text, name, dir);
+ pl->SetName(text, false);
+ }
+}
+
+// Fills the list with all programs saved.
+
+void CStudio::UpdateDialogList()
+{
+ CWindow* pw;
+ CList* pl;
+ long hFile;
+ struct _finddata_t fileBuffer;
+ struct _finddata_t* listBuffer;
+ bool bDo;
+ char dir[_MAX_FNAME];
+ char temp[_MAX_FNAME];
+ int nbFilenames, i;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
+ if ( pw == 0 ) return;
+ pl = (CList*)pw->SearchControl(EVENT_DIALOG_LIST);
+ if ( pl == 0 ) return;
+ pl->Flush();
+
+ nbFilenames = 0;
+ listBuffer = (_finddata_t*)malloc(sizeof(_finddata_t)*1000);
+
+ SearchDirectory(dir, false);
+ strcat(dir, "*"); // list all
+ hFile = _findfirst(dir, &fileBuffer);
+ if ( hFile != -1 )
+ {
+ do
+ {
+ if ( (fileBuffer.attrib & _A_SUBDIR) == 0 )
+ {
+ listBuffer[nbFilenames++] = fileBuffer;
+ }
+ }
+ while ( _findnext(hFile, &fileBuffer) == 0 && nbFilenames < 1000 );
+ }
+ do // sorts all names:
+ {
+ bDo = false;
+ for ( i=0 ; i<nbFilenames-1 ; i++ )
+ {
+ if ( strcmp(listBuffer[i].name, listBuffer[i+1].name) > 0 )
+ {
+ fileBuffer = listBuffer[i]; // exchange i and i +1
+ listBuffer[i] = listBuffer[i+1];
+ listBuffer[i+1] = fileBuffer;
+ bDo = true;
+ }
+ }
+ }
+ while ( bDo );
+
+ for ( i=0 ; i<nbFilenames ; i++ )
+ {
+ TimeToAscii(listBuffer[i].time_write, dir);
+ sprintf(temp, "%s\t%d \t%s", listBuffer[i].name, listBuffer[i].size, dir);
+ pl->SetName(i, temp);
+ }
+
+ free(listBuffer);
+}
+
+// Constructs the name of the folder or open/save.
+// If the folder does not exist, it will be created.
+
+void CStudio::SearchDirectory(char *dir, bool bCreate)
+{
+ if ( m_main->RetIOPublic() )
+ {
+ sprintf(dir, "%s\\", m_main->RetPublicDir());
+ }
+ else
+ {
+ sprintf(dir, "%s\\%s\\Program\\", m_main->RetSavegameDir(), m_main->RetGamerName());
+ }
+
+ if ( bCreate )
+ {
+ _mkdir(dir); // if does not exist yet!
+ }
+}
+
+// Reads a new program.
+
+bool CStudio::ReadProgram()
+{
+ CWindow* pw;
+ CEdit* pe;
+ char filename[100];
+ char dir[100];
+ char* p;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
+ if ( pw == 0 ) return false;
+
+ pe = (CEdit*)pw->SearchControl(EVENT_DIALOG_EDIT);
+ if ( pe == 0 ) return false;
+ pe->GetText(filename, 100);
+ if ( filename[0] == 0 ) return false;
+
+ p = strstr(filename, ".txt");
+ if ( p == 0 || p != filename+strlen(filename)-4 )
+ {
+ strcat(filename, ".txt");
+ }
+ SearchDirectory(dir, true);
+ strcat(dir, filename);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw == 0 ) return false;
+ pe = (CEdit*)pw->SearchControl(EVENT_STUDIO_EDIT);
+ if ( pe == 0 ) return false;
+
+ if ( !pe->ReadText(dir) ) return false;
+
+ m_script->SetFilename(filename);
+ ColorizeScript(pe);
+ return true;
+}
+
+// Writes the current program.
+
+bool CStudio::WriteProgram()
+{
+ CWindow* pw;
+ CEdit* pe;
+ char filename[100];
+ char dir[100];
+ char* p;
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW9);
+ if ( pw == 0 ) return false;
+
+ pe = (CEdit*)pw->SearchControl(EVENT_DIALOG_EDIT);
+ if ( pe == 0 ) return false;
+ pe->GetText(filename, 100);
+ if ( filename[0] == 0 ) return false;
+
+ p = strstr(filename, ".txt");
+ if ( p == 0 || p != filename+strlen(filename)-4 )
+ {
+ strcat(filename, ".txt");
+ }
+ SearchDirectory(dir, true);
+ strcat(dir, filename);
+
+ pw = (CWindow*)m_interface->SearchControl(EVENT_WINDOW3);
+ if ( pw == 0 ) return false;
+ pe = (CEdit*)pw->SearchControl(EVENT_STUDIO_EDIT);
+ if ( pe == 0 ) return false;
+
+ if ( !pe->WriteText(dir) ) return false;
+
+ m_script->SetFilename(filename);
+ return true;
+}
+
diff --git a/src/ui/studio.h b/src/ui/studio.h
index 0c9eac2..687ab22 100644
--- a/src/ui/studio.h
+++ b/src/ui/studio.h
@@ -1,115 +1,115 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// studio.h
-
-#pragma once
-
-
-#include "object/object.h"
-#include "script/script.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CEvent;
-class CRobotMain;
-class CCamera;
-class CSound;
-class CInterface;
-class CScript;
-class CList;
-class CEdit;
-
-
-
-enum StudioDialog
-{
- SD_NULL,
- SD_OPEN,
- SD_SAVE,
- SD_FIND,
- SD_REPLACE,
-};
-
-
-
-class CStudio
-{
-public:
- CStudio(CInstanceManager* iMan);
- ~CStudio();
-
- bool EventProcess(const Event &event);
-
- void StartEditScript(CScript *script, char* name, int rank);
- bool StopEditScript(bool bCancel);
-
-protected:
- bool EventFrame(const Event &event);
- void SearchToken(CEdit* edit);
- void ColorizeScript(CEdit* edit);
- void AdjustEditScript();
- void SetInfoText(char *text, bool bClickable);
- void ViewEditScript();
- void UpdateFlux();
- void UpdateButtons();
-
- void StartDialog(StudioDialog type);
- void StopDialog();
- void AdjustDialog();
- bool EventDialog(const Event &event);
- void UpdateChangeList();
- void UpdateChangeEdit();
- void UpdateDialogAction();
- void UpdateDialogPublic();
- void UpdateDialogList();
- void SearchDirectory(char *dir, bool bCreate);
- bool ReadProgram();
- bool WriteProgram();
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CEvent* m_event;
- CRobotMain* m_main;
- CCamera* m_camera;
- CSound* m_sound;
- CInterface* m_interface;
-
- int m_rank;
- CScript* m_script;
-
- bool m_bEditMaximized;
- bool m_bEditMinimized;
-
- CameraType m_editCamera;
- Math::Point m_editActualPos;
- Math::Point m_editActualDim;
- Math::Point m_editFinalPos;
- Math::Point m_editFinalDim;
-
- float m_time;
- float m_fixInfoTextTime;
- bool m_bRunning;
- bool m_bRealTime;
- bool m_bInitPause;
- char m_helpFilename[100];
-
- StudioDialog m_dialog;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// studio.h
+
+#pragma once
+
+
+#include "object/object.h"
+#include "script/script.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CEvent;
+class CRobotMain;
+class CCamera;
+class CSound;
+class CInterface;
+class CScript;
+class CList;
+class CEdit;
+
+
+
+enum StudioDialog
+{
+ SD_NULL,
+ SD_OPEN,
+ SD_SAVE,
+ SD_FIND,
+ SD_REPLACE,
+};
+
+
+
+class CStudio
+{
+public:
+ CStudio(CInstanceManager* iMan);
+ ~CStudio();
+
+ bool EventProcess(const Event &event);
+
+ void StartEditScript(CScript *script, char* name, int rank);
+ bool StopEditScript(bool bCancel);
+
+protected:
+ bool EventFrame(const Event &event);
+ void SearchToken(CEdit* edit);
+ void ColorizeScript(CEdit* edit);
+ void AdjustEditScript();
+ void SetInfoText(char *text, bool bClickable);
+ void ViewEditScript();
+ void UpdateFlux();
+ void UpdateButtons();
+
+ void StartDialog(StudioDialog type);
+ void StopDialog();
+ void AdjustDialog();
+ bool EventDialog(const Event &event);
+ void UpdateChangeList();
+ void UpdateChangeEdit();
+ void UpdateDialogAction();
+ void UpdateDialogPublic();
+ void UpdateDialogList();
+ void SearchDirectory(char *dir, bool bCreate);
+ bool ReadProgram();
+ bool WriteProgram();
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CEvent* m_event;
+ CRobotMain* m_main;
+ CCamera* m_camera;
+ CSound* m_sound;
+ CInterface* m_interface;
+
+ int m_rank;
+ CScript* m_script;
+
+ bool m_bEditMaximized;
+ bool m_bEditMinimized;
+
+ CameraType m_editCamera;
+ Math::Point m_editActualPos;
+ Math::Point m_editActualDim;
+ Math::Point m_editFinalPos;
+ Math::Point m_editFinalDim;
+
+ float m_time;
+ float m_fixInfoTextTime;
+ bool m_bRunning;
+ bool m_bRealTime;
+ bool m_bInitPause;
+ char m_helpFilename[100];
+
+ StudioDialog m_dialog;
+};
+
+
diff --git a/src/ui/target.cpp b/src/ui/target.cpp
index cf37a3d..f94ae02 100644
--- a/src/ui/target.cpp
+++ b/src/ui/target.cpp
@@ -1,283 +1,283 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// target.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "object/robotmain.h"
-#include "object/object.h"
-#include "common/restext.h"
-#include "ui/target.h"
-
-
-
-
-// Object's constructor.
-
-CTarget::CTarget(CInstanceManager* iMan) : CControl(iMan)
-{
-}
-
-// Object's destructor.
-
-CTarget::~CTarget()
-{
-}
-
-
-// Creates a new button.
-
-bool CTarget::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- CControl::Create(pos, dim, icon, eventMsg);
-
- return true;
-}
-
-
-// Management of an event.
-
-bool CTarget::EventProcess(const Event &event)
-{
-#if 0
- if ( (m_state & STATE_VISIBLE) == 0 ) return true;
- if ( m_state & STATE_DEAD ) return true;
-
- CControl::EventProcess(event);
-
- if ( event.event == EVENT_MOUSEMOVE )
- {
- if ( CControl::Detect(event.pos) )
- {
- m_engine->SetMouseType(D3DMOUSETARGET);
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- return false;
- }
- }
-
- if ( event.event == EVENT_LBUTTONDOWN &&
- (m_state & STATE_VISIBLE) &&
- (m_state & STATE_ENABLE) )
- {
- if ( CControl::Detect(event.pos) )
- {
- Event newEvent = event;
- newEvent.event = EVENT_OBJECT_FIRE;
- m_event->AddEvent(newEvent);
- return false;
- }
- }
-
- return true;
-#else
- CObject* pObj;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return true;
- if ( m_state & STATE_DEAD ) return true;
-
- CControl::EventProcess(event);
-
- if ( event.event == EVENT_MOUSEMOVE )
- {
- m_main->SetFriendAim(false);
-
- if ( CControl::Detect(event.pos) )
- {
- pObj = DetectFriendObject(event.pos);
- if ( pObj == 0 )
- {
- m_engine->SetMouseType(D3DMOUSETARGET);
-
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- return false;
- }
- else
- {
- m_main->SetFriendAim(true);
- m_engine->SetMouseType(D3DMOUSENORM);
- }
- }
- }
-
- if ( event.event == EVENT_LBUTTONDOWN &&
- (m_state & STATE_VISIBLE) &&
- (m_state & STATE_ENABLE) )
- {
- if ( CControl::Detect(event.pos) )
- {
- if ( !m_main->RetFriendAim() )
- {
- Event newEvent = event;
- newEvent.event = EVENT_OBJECT_FIRE;
- m_event->AddEvent(newEvent);
- return false;
- }
- }
- }
-
- return true;
-#endif
-}
-
-
-// Draws button.
-
-void CTarget::Draw()
-{
- // It is completely invisible!
-}
-
-
-// Returns the tooltip.
-
-bool CTarget::GetTooltip(Math::Point pos, char* name)
-{
-#if 0
- if ( (m_state&STATE_VISIBLE) && Detect(pos) ) // in the window?
- {
- strcpy(name, m_tooltip);
- return true; // does not detect objects below!
- }
-
- return false;
-#else
-//? CObject* pObj;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return false;
-
- if ( (m_state&STATE_VISIBLE) && Detect(pos) ) // in the window?
- {
-//? pObj = DetectFriendObject(pos);
-//? if ( pObj == 0 )
- if ( !m_main->RetFriendAim() )
- {
- strcpy(name, m_tooltip);
- return true; // does not detect objects below!
- }
- }
-
- return false;
-#endif
-}
-
-
-// Detects the object aimed by the mouse.
-
-CObject* CTarget::DetectFriendObject(Math::Point pos)
-{
- ObjectType type;
- CObject *pObj, *pTarget;
- int objRank, i, j, rank;
-
- objRank = m_engine->DetectObject(pos);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue;
- if ( pObj->RetProxyActivate() ) continue;
- if ( pObj->RetSelect() ) continue;
-
- pTarget = 0;
- type = pObj->RetType();
- if ( 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 ||
- type == OBJECT_HUMAN ||
- type == OBJECT_TECH ||
- type == OBJECT_TOTO ||
- 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 )
- {
- pTarget = pObj;
- }
- else if ( (type == OBJECT_POWER ||
- type == OBJECT_ATOMIC ) &&
- pObj->RetTruck() != 0 ) // battery used?
- {
- pTarget = pObj->RetTruck();
- if ( pTarget->RetType() == OBJECT_MOBILEtg )
- {
- pTarget = 0;
- }
- }
-
- for ( j=0 ; j<OBJECTMAXPART ; j++ )
- {
- rank = pObj->RetObjectRank(j);
- if ( rank == -1 ) continue;
- if ( rank != objRank ) continue;
- return pTarget;
- }
- }
- return 0;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// target.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "object/robotmain.h"
+#include "object/object.h"
+#include "common/restext.h"
+#include "ui/target.h"
+
+
+
+
+// Object's constructor.
+
+CTarget::CTarget(CInstanceManager* iMan) : CControl(iMan)
+{
+}
+
+// Object's destructor.
+
+CTarget::~CTarget()
+{
+}
+
+
+// Creates a new button.
+
+bool CTarget::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ CControl::Create(pos, dim, icon, eventMsg);
+
+ return true;
+}
+
+
+// Management of an event.
+
+bool CTarget::EventProcess(const Event &event)
+{
+#if 0
+ if ( (m_state & STATE_VISIBLE) == 0 ) return true;
+ if ( m_state & STATE_DEAD ) return true;
+
+ CControl::EventProcess(event);
+
+ if ( event.event == EVENT_MOUSEMOVE )
+ {
+ if ( CControl::Detect(event.pos) )
+ {
+ m_engine->SetMouseType(D3DMOUSETARGET);
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ return false;
+ }
+ }
+
+ if ( event.event == EVENT_LBUTTONDOWN &&
+ (m_state & STATE_VISIBLE) &&
+ (m_state & STATE_ENABLE) )
+ {
+ if ( CControl::Detect(event.pos) )
+ {
+ Event newEvent = event;
+ newEvent.event = EVENT_OBJECT_FIRE;
+ m_event->AddEvent(newEvent);
+ return false;
+ }
+ }
+
+ return true;
+#else
+ CObject* pObj;
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return true;
+ if ( m_state & STATE_DEAD ) return true;
+
+ CControl::EventProcess(event);
+
+ if ( event.event == EVENT_MOUSEMOVE )
+ {
+ m_main->SetFriendAim(false);
+
+ if ( CControl::Detect(event.pos) )
+ {
+ pObj = DetectFriendObject(event.pos);
+ if ( pObj == 0 )
+ {
+ m_engine->SetMouseType(D3DMOUSETARGET);
+
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ return false;
+ }
+ else
+ {
+ m_main->SetFriendAim(true);
+ m_engine->SetMouseType(D3DMOUSENORM);
+ }
+ }
+ }
+
+ if ( event.event == EVENT_LBUTTONDOWN &&
+ (m_state & STATE_VISIBLE) &&
+ (m_state & STATE_ENABLE) )
+ {
+ if ( CControl::Detect(event.pos) )
+ {
+ if ( !m_main->RetFriendAim() )
+ {
+ Event newEvent = event;
+ newEvent.event = EVENT_OBJECT_FIRE;
+ m_event->AddEvent(newEvent);
+ return false;
+ }
+ }
+ }
+
+ return true;
+#endif
+}
+
+
+// Draws button.
+
+void CTarget::Draw()
+{
+ // It is completely invisible!
+}
+
+
+// Returns the tooltip.
+
+bool CTarget::GetTooltip(Math::Point pos, char* name)
+{
+#if 0
+ if ( (m_state&STATE_VISIBLE) && Detect(pos) ) // in the window?
+ {
+ strcpy(name, m_tooltip);
+ return true; // does not detect objects below!
+ }
+
+ return false;
+#else
+//? CObject* pObj;
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return false;
+
+ if ( (m_state&STATE_VISIBLE) && Detect(pos) ) // in the window?
+ {
+//? pObj = DetectFriendObject(pos);
+//? if ( pObj == 0 )
+ if ( !m_main->RetFriendAim() )
+ {
+ strcpy(name, m_tooltip);
+ return true; // does not detect objects below!
+ }
+ }
+
+ return false;
+#endif
+}
+
+
+// Detects the object aimed by the mouse.
+
+CObject* CTarget::DetectFriendObject(Math::Point pos)
+{
+ ObjectType type;
+ CObject *pObj, *pTarget;
+ int objRank, i, j, rank;
+
+ objRank = m_engine->DetectObject(pos);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue;
+ if ( pObj->RetProxyActivate() ) continue;
+ if ( pObj->RetSelect() ) continue;
+
+ pTarget = 0;
+ type = pObj->RetType();
+ if ( 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 ||
+ type == OBJECT_HUMAN ||
+ type == OBJECT_TECH ||
+ type == OBJECT_TOTO ||
+ 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 )
+ {
+ pTarget = pObj;
+ }
+ else if ( (type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC ) &&
+ pObj->RetTruck() != 0 ) // battery used?
+ {
+ pTarget = pObj->RetTruck();
+ if ( pTarget->RetType() == OBJECT_MOBILEtg )
+ {
+ pTarget = 0;
+ }
+ }
+
+ for ( j=0 ; j<OBJECTMAXPART ; j++ )
+ {
+ rank = pObj->RetObjectRank(j);
+ if ( rank == -1 ) continue;
+ if ( rank != objRank ) continue;
+ return pTarget;
+ }
+ }
+ return 0;
+}
+
diff --git a/src/ui/target.h b/src/ui/target.h
index df1c962..ae0c7af 100644
--- a/src/ui/target.h
+++ b/src/ui/target.h
@@ -1,48 +1,48 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// target.h
-
-#pragma once
-
-
-#include "ui/control.h"
-
-
-class CD3DEngine;
-class CObject;
-
-
-
-class CTarget : public CControl
-{
-public:
- CTarget(CInstanceManager* iMan);
- ~CTarget();
-
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
-
- bool EventProcess(const Event &event);
- void Draw();
- bool GetTooltip(Math::Point pos, char* name);
-
-protected:
- CObject* DetectFriendObject(Math::Point pos);
-
-protected:
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// target.h
+
+#pragma once
+
+
+#include "ui/control.h"
+
+
+class CD3DEngine;
+class CObject;
+
+
+
+class CTarget : public CControl
+{
+public:
+ CTarget(CInstanceManager* iMan);
+ ~CTarget();
+
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+
+ bool EventProcess(const Event &event);
+ void Draw();
+ bool GetTooltip(Math::Point pos, char* name);
+
+protected:
+ CObject* DetectFriendObject(Math::Point pos);
+
+protected:
+};
+
+
diff --git a/src/ui/window.cpp b/src/ui/window.cpp
index d250ec9..8866643 100644
--- a/src/ui/window.cpp
+++ b/src/ui/window.cpp
@@ -1,1620 +1,1620 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// window.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "common/language.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/restext.h"
-#include "common/iman.h"
-#include "ui/button.h"
-#include "ui/color.h"
-#include "ui/check.h"
-#include "ui/key.h"
-#include "ui/group.h"
-#include "ui/image.h"
-#include "ui/label.h"
-#include "ui/edit.h"
-#include "ui/editvalue.h"
-#include "ui/scroll.h"
-#include "ui/slider.h"
-#include "ui/list.h"
-#include "ui/shortcut.h"
-#include "ui/map.h"
-#include "ui/gauge.h"
-#include "ui/compass.h"
-#include "ui/target.h"
-#include "old/text.h"
-#include "ui/window.h"
-
-
-
-
-// Object's constructor.
-
-CWindow::CWindow(CInstanceManager* iMan) : CControl(iMan)
-{
- int i;
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- m_table[i] = 0;
- }
-
- m_bTrashEvent = true;
- m_bMaximized = false;
- m_bMinimized = false;
- m_bFixed = false;
-
- m_minDim = Math::Point(0.0f, 0.0f);
- m_maxDim = Math::Point(1.0f, 1.0f);
-
- m_buttonReduce = 0;
- m_buttonFull = 0;
- m_buttonClose = 0;
-
- m_bMovable = false;
- m_bRedim = false;
- m_bClosable = false;
- m_bCapture = false;
-
- m_fontStretch = NORMSTRETCH*1.2f;
-}
-
-// Object's destructor.
-
-CWindow::~CWindow()
-{
- Flush();
-}
-
-
-// Purge all the controls.
-
-void CWindow::Flush()
-{
- int i;
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] != 0 )
- {
- delete m_table[i];
- m_table[i] = 0;
- }
- }
-
- if ( m_buttonReduce != 0 )
- {
- delete m_buttonReduce;
- m_buttonReduce = 0;
- }
-
- if ( m_buttonFull != 0 )
- {
- delete m_buttonFull;
- m_buttonFull = 0;
- }
-
- if ( m_buttonClose != 0 )
- {
- delete m_buttonClose;
- m_buttonClose = 0;
- }
-}
-
-
-// Creates a new window.
-
-bool CWindow::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- CControl::Create(pos, dim, icon, eventMsg);
- return true;
-}
-
-
-// Creates a new button.
-
-CButton* CWindow::CreateButton(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CButton* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CButton(m_iMan);
- pc = (CButton*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new button.
-
-CColor* CWindow::CreateColor(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CColor* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CColor(m_iMan);
- pc = (CColor*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new button.
-
-CCheck* CWindow::CreateCheck(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CCheck* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CCheck(m_iMan);
- pc = (CCheck*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new button.
-
-CKey* CWindow::CreateKey(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CKey* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CKey(m_iMan);
- pc = (CKey*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new button.
-
-CGroup* CWindow::CreateGroup(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CGroup* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CGroup(m_iMan);
- pc = (CGroup*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new button.
-
-CImage* CWindow::CreateImage(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CImage* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CImage(m_iMan);
- pc = (CImage*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new label.
-
-CLabel* CWindow::CreateLabel(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg,
- char *name)
-{
- CLabel* pc;
- char* p;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CLabel(m_iMan);
- pc = (CLabel*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
-
- p = strchr(name, '\\');
- if ( p == 0 )
- {
- pc->SetName(name);
- }
- else
- {
- char text[100];
- strncpy(text, name, 100);
- text[100-1] = 0;
- if ( p-name < 100 )
- {
- text[p-name] = 0; // deletes text after "\\" (tooltip)
- }
- pc->SetName(text);
- }
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new editable pave.
-
-CEdit* CWindow::CreateEdit(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CEdit* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CEdit(m_iMan);
- pc = (CEdit*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new editable pave.
-
-CEditValue* CWindow::CreateEditValue(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CEditValue* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CEditValue(m_iMan);
- pc = (CEditValue*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new elevator.
-
-CScroll* CWindow::CreateScroll(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CScroll* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CScroll(m_iMan);
- pc = (CScroll*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new cursor.
-
-CSlider* CWindow::CreateSlider(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CSlider* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CSlider(m_iMan);
- pc = (CSlider*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new list.
-
-CList* CWindow::CreateList(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg,
- float expand)
-{
- CList* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CList(m_iMan);
- pc = (CList*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg, expand);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new shortcut.
-
-CShortcut* CWindow::CreateShortcut(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CShortcut* ps;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CShortcut(m_iMan);
- ps = (CShortcut*)m_table[i];
- ps->Create(pos, dim, icon, eventMsg);
- return ps;
- }
- }
- return 0;
-}
-
-// Creates a new card.
-
-CMap* CWindow::CreateMap(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CMap* pm;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CMap(m_iMan);
- pm = (CMap*)m_table[i];
- pm->Create(pos, dim, icon, eventMsg);
- return pm;
- }
- }
- return 0;
-}
-
-// Creates a new gauge.
-
-CGauge* CWindow::CreateGauge(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CGauge* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CGauge(m_iMan);
- pc = (CGauge*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new compass.
-
-CCompass* CWindow::CreateCompass(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CCompass* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CCompass(m_iMan);
- pc = (CCompass*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Creates a new target.
-
-CTarget* CWindow::CreateTarget(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
-{
- CTarget* pc;
- int i;
-
- if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] == 0 )
- {
- m_table[i] = new CTarget(m_iMan);
- pc = (CTarget*)m_table[i];
- pc->Create(pos, dim, icon, eventMsg);
- return pc;
- }
- }
- return 0;
-}
-
-// Removes a control.
-
-bool CWindow::DeleteControl(EventMsg eventMsg)
-{
- int i;
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] != 0 )
- {
- if ( eventMsg == m_table[i]->RetEventMsg() )
- {
- delete m_table[i];
- m_table[i] = 0;
- return true;
- }
- }
- }
- return false;
-}
-
-// Gives a control.
-
-CControl* CWindow::SearchControl(EventMsg eventMsg)
-{
- int i;
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] != 0 )
- {
- if ( eventMsg == m_table[i]->RetEventMsg() )
- {
- return m_table[i];
- }
- }
- }
- return 0;
-}
-
-
-// Makes the tooltip binds to the window.
-
-bool CWindow::GetTooltip(Math::Point pos, char* name)
-{
- int i;
-
- for ( i=MAXWINDOW-1 ; i>=0 ; i-- )
- {
- if ( m_table[i] != 0 )
- {
- if ( m_table[i]->GetTooltip(pos, name) )
- {
- return true;
- }
- }
- }
-
- if ( m_buttonClose != 0 &&
- m_buttonClose->GetTooltip(pos, name) )
- {
- return true;
- }
- if ( m_buttonFull != 0 &&
- m_buttonFull->GetTooltip(pos, name) )
- {
- return true;
- }
- if ( m_buttonReduce != 0 &&
- m_buttonReduce->GetTooltip(pos, name) )
- {
- return true;
- }
-
- if ( Detect(pos) ) // in the window?
- {
- strcpy(name, m_tooltip);
- return true;
- }
-
- return false;
-}
-
-
-// Specifies the name for the title bar.
-
-void CWindow::SetName(char* name)
-{
- CButton* pc;
- bool bAdjust;
-
- CControl::SetName(name);
-
- if ( m_buttonReduce != 0 )
- {
- delete m_buttonReduce;
- m_buttonReduce = 0;
- }
-
- if ( m_buttonFull != 0 )
- {
- delete m_buttonFull;
- m_buttonFull = 0;
- }
-
- if ( m_buttonClose != 0 )
- {
- delete m_buttonClose;
- m_buttonClose = 0;
- }
-
- bAdjust = false;
-
- if ( m_name[0] != 0 && m_bRedim ) // title bar exists?
- {
- m_buttonReduce = new CButton(m_iMan);
- pc = (CButton*)m_buttonReduce;
- pc->Create(m_pos, m_dim, 0, EVENT_NULL);
-
- m_buttonFull = new CButton(m_iMan);
- pc = (CButton*)m_buttonFull;
- pc->Create(m_pos, m_dim, 0, EVENT_NULL);
-
- bAdjust = true;
- }
-
- if ( m_name[0] != 0 && m_bClosable ) // title bar exists?
- {
- m_buttonClose = new CButton(m_iMan);
- pc = (CButton*)m_buttonClose;
- pc->Create(m_pos, m_dim, 0, EVENT_NULL);
-
- bAdjust = true;
- }
-
- if ( bAdjust )
- {
- AdjustButtons();
- }
-
- MoveAdjust();
-}
-
-
-void CWindow::SetPos(Math::Point pos)
-{
- CControl::SetPos(pos);
- MoveAdjust();
-}
-
-void CWindow::SetDim(Math::Point dim)
-{
- if ( dim.x < m_minDim.x ) dim.x = m_minDim.x;
- if ( dim.x > m_maxDim.x ) dim.x = m_maxDim.x;
- if ( dim.y < m_minDim.y ) dim.y = m_minDim.y;
- if ( dim.y > m_maxDim.y ) dim.y = m_maxDim.y;
-
- CControl::SetDim(dim);
- MoveAdjust();
-}
-
-void CWindow::MoveAdjust()
-{
- Math::Point pos, dim;
- float h, offset;
-
- h = m_engine->RetText()->RetHeight(m_fontSize, m_fontType);
- dim.y = h*1.2f;
- dim.x = dim.y*0.75f;
-
- if ( m_buttonClose != 0 )
- {
- pos.x = m_pos.x+m_dim.x-0.01f-dim.x;
- pos.y = m_pos.y+m_dim.y-0.01f-h*1.2f;
- m_buttonClose->SetPos(pos);
- m_buttonClose->SetDim(dim);
- offset = dim.x*1.0f;
- }
- else
- {
- offset = 0.0f;
- }
-
- if ( m_buttonFull != 0 )
- {
- pos.x = m_pos.x+m_dim.x-0.01f-dim.x-offset;
- pos.y = m_pos.y+m_dim.y-0.01f-h*1.2f;
- m_buttonFull->SetPos(pos);
- m_buttonFull->SetDim(dim);
- }
-
- if ( m_buttonReduce != 0 )
- {
- pos.x = m_pos.x+m_dim.x-0.01f-dim.x*2.0f-offset;
- pos.y = m_pos.y+m_dim.y-0.01f-h*1.2f;
- m_buttonReduce->SetPos(pos);
- m_buttonReduce->SetDim(dim);
- }
-}
-
-
-void CWindow::SetMinDim(Math::Point dim)
-{
- m_minDim = dim;
-}
-
-void CWindow::SetMaxDim(Math::Point dim)
-{
- m_maxDim = dim;
-}
-
-Math::Point CWindow::RetMinDim()
-{
- return m_minDim;
-}
-
-Math::Point CWindow::RetMaxDim()
-{
- return m_maxDim;
-}
-
-
-// Indicates whether the window is moved.
-
-void CWindow::SetMovable(bool bMode)
-{
- m_bMovable = bMode;
-}
-
-bool CWindow::RetMovable()
-{
- return m_bMovable;
-}
-
-
-// Management of the presence of minimize/maximize buttons.
-
-void CWindow::SetRedim(bool bMode)
-{
- m_bRedim = bMode;
-}
-
-bool CWindow::RetRedim()
-{
- return m_bRedim;
-}
-
-
-// Management of the presence of the close button.
-
-void CWindow::SetClosable(bool bMode)
-{
- m_bClosable = bMode;
-}
-
-bool CWindow::RetClosable()
-{
- return m_bClosable;
-}
-
-
-void CWindow::SetMaximized(bool bMaxi)
-{
- m_bMaximized = bMaxi;
- AdjustButtons();
-}
-
-bool CWindow::RetMaximized()
-{
- return m_bMaximized;
-}
-
-void CWindow::SetMinimized(bool bMini)
-{
- m_bMinimized = bMini;
- AdjustButtons();
-}
-
-bool CWindow::RetMinimized()
-{
- return m_bMinimized;
-}
-
-void CWindow::SetFixed(bool bFix)
-{
- m_bFixed = bFix;
-}
-
-bool CWindow::RetFixed()
-{
- return m_bFixed;
-}
-
-
-// Adjusts the buttons in the title bar.
-
-void CWindow::AdjustButtons()
-{
- char res[100];
-
- if ( m_buttonFull != 0 )
- {
- if ( m_bMaximized )
- {
- m_buttonFull->SetIcon(54);
- GetResource(RES_TEXT, RT_WINDOW_STANDARD, res);
- m_buttonFull->SetTooltip(res);
- }
- else
- {
- m_buttonFull->SetIcon(52);
- GetResource(RES_TEXT, RT_WINDOW_MAXIMIZED, res);
- m_buttonFull->SetTooltip(res);
- }
- }
-
- if ( m_buttonReduce != 0 )
- {
- if ( m_bMinimized )
- {
- m_buttonReduce->SetIcon(54);
- GetResource(RES_TEXT, RT_WINDOW_STANDARD, res);
- m_buttonReduce->SetTooltip(res);
- }
- else
- {
- m_buttonReduce->SetIcon(51);
- GetResource(RES_TEXT, RT_WINDOW_MINIMIZED, res);
- m_buttonReduce->SetTooltip(res);
- }
- }
-
- if ( m_buttonClose != 0 )
- {
- m_buttonClose->SetIcon(11); // x
- GetResource(RES_TEXT, RT_WINDOW_CLOSE, res);
- m_buttonClose->SetTooltip(res);
- }
-}
-
-
-void CWindow::SetTrashEvent(bool bTrash)
-{
- m_bTrashEvent = bTrash;
-}
-
-bool CWindow::RetTrashEvent()
-{
- return m_bTrashEvent;
-}
-
-
-// Returns the message from the button "reduce".
-
-EventMsg CWindow::RetEventMsgReduce()
-{
- if ( m_buttonReduce == 0 ) return EVENT_NULL;
- return m_buttonReduce->RetEventMsg();
-}
-
-// Returns the message from the button "full".
-
-EventMsg CWindow::RetEventMsgFull()
-{
- if ( m_buttonFull == 0 ) return EVENT_NULL;
- return m_buttonFull->RetEventMsg();
-}
-
-// Returns the message from the button "close".
-
-EventMsg CWindow::RetEventMsgClose()
-{
- if ( m_buttonClose == 0 ) return EVENT_NULL;
- return m_buttonClose->RetEventMsg();
-}
-
-
-// Detects whether the mouse is in an edge of the window, to resize it.
-// Bit returns: 0 = left, 1 = down, 2 = right, 3 = up, 1 = all.
-
-int CWindow::BorderDetect(Math::Point pos)
-{
- Math::Point dim;
- float h;
- int flags;
-
- if ( m_bMaximized || m_bMinimized || m_bFixed ) return 0;
-
- flags = 0;
- if ( pos.x < m_pos.x+0.030f )
- {
- flags |= (1<<0);
- }
- if ( pos.y < m_pos.y+0.020f )
- {
- flags |= (1<<1);
- }
- if ( pos.x > m_pos.x+m_dim.x-0.030f )
- {
- flags |= (1<<2);
- }
- if ( pos.y > m_pos.y+m_dim.y-0.020f )
- {
- flags |= (1<<3);
- }
-
- if ( pos.x > m_pos.x+ 0.015f &&
- pos.x < m_pos.x+m_dim.x-0.015f &&
- pos.y > m_pos.y+ 0.010f &&
- pos.y < m_pos.y+m_dim.y-0.010f )
- {
- flags = 0;
- }
-
- if ( flags == 0 )
- {
- h = m_engine->RetText()->RetHeight(m_fontSize, m_fontType);
- dim.y = h*1.2f;
- dim.x = dim.y*0.75f;
- if ( pos.x < m_pos.x+m_dim.x-0.01f-dim.x*3.0f &&
- pos.y >= m_pos.y+m_dim.y-0.01f-h*1.2f )
- {
- flags = -1;
- }
- }
-
- return flags;
-}
-
-// Management of an event.
-
-bool CWindow::EventProcess(const Event &event)
-{
- Math::Point pos;
- int i, flags;
-
- if ( event.event == EVENT_MOUSEMOVE )
- {
- if ( m_bCapture )
- {
- m_engine->SetMouseType(m_pressMouse);
- }
- else
- {
- m_pressMouse = D3DMOUSENORM;
-
- if ( m_name[0] != 0 && m_bMovable && // title bar?
- Detect(event.pos) )
- {
- flags = BorderDetect(event.pos);
- if ( flags == -1 )
- {
- m_pressMouse = D3DMOUSEMOVE; // +
- }
- else if ( ((flags & (1<<0)) && (flags & (1<<3))) ||
- ((flags & (1<<1)) && (flags & (1<<2))) )
- {
- m_pressMouse = D3DMOUSEMOVEI; // \ //
- }
- else if ( ((flags & (1<<0)) && (flags & (1<<1))) ||
- ((flags & (1<<2)) && (flags & (1<<3))) )
- {
- m_pressMouse = D3DMOUSEMOVED; // /
- }
- else if ( (flags & (1<<0)) || (flags & (1<<2)) )
- {
- m_pressMouse = D3DMOUSEMOVEH; // -
- }
- else if ( (flags & (1<<1)) || (flags & (1<<3)) )
- {
- m_pressMouse = D3DMOUSEMOVEV; // |
- }
- }
-
- if ( m_pressMouse != D3DMOUSENORM )
- {
- m_engine->SetMouseType(m_pressMouse);
- }
- }
- }
-
- if ( !m_bCapture )
- {
- for ( i=MAXWINDOW-1 ; i>=0 ; i-- )
- {
- if ( m_table[i] != 0 )
- {
- if ( !m_table[i]->EventProcess(event) )
- {
- return false;
- }
- }
- }
-
- if ( m_buttonReduce != 0 )
- {
- m_buttonReduce->EventProcess(event);
- }
- if ( m_buttonFull != 0 )
- {
- m_buttonFull->EventProcess(event);
- }
- if ( m_buttonClose != 0 )
- {
- m_buttonClose->EventProcess(event);
- }
- }
-
- if ( m_bTrashEvent && event.event == EVENT_LBUTTONDOWN )
- {
- if ( Detect(event.pos) )
- {
- if ( m_name[0] != 0 && m_bMovable ) // title bar?
- {
- m_pressFlags = BorderDetect(event.pos);
- if ( m_pressFlags != 0 )
- {
- m_bCapture = true;
- m_pressPos = event.pos;
- }
- }
- return false;
- }
- }
-
- if ( event.event == EVENT_MOUSEMOVE && m_bCapture )
- {
- pos = event.pos;
- if ( m_pressFlags == -1 ) // all moves?
- {
- m_pos.x += pos.x-m_pressPos.x;
- m_pos.y += pos.y-m_pressPos.y;
- }
- else
- {
- if ( m_pressFlags & (1<<0) ) // left edge?
- {
- if ( pos.x > m_pressPos.x+m_dim.x-m_minDim.x )
- {
- pos.x = m_pressPos.x+m_dim.x-m_minDim.x;
- }
- m_pos.x += pos.x-m_pressPos.x;
- m_dim.x -= pos.x-m_pressPos.x;
- }
- if ( m_pressFlags & (1<<1) ) // bottom edge?
- {
- if ( pos.y > m_pressPos.y+m_dim.y-m_minDim.y )
- {
- pos.y = m_pressPos.y+m_dim.y-m_minDim.y;
- }
- m_pos.y += pos.y-m_pressPos.y;
- m_dim.y -= pos.y-m_pressPos.y;
- }
- if ( m_pressFlags & (1<<2) ) // right edge?
- {
- if ( pos.x < m_pressPos.x-m_dim.x+m_minDim.x )
- {
- pos.x = m_pressPos.x-m_dim.x+m_minDim.x;
- }
- m_dim.x += pos.x-m_pressPos.x;
- }
- if ( m_pressFlags & (1<<3) ) // top edge?
- {
- if ( pos.y < m_pressPos.y-m_dim.y+m_minDim.y )
- {
- pos.y = m_pressPos.y-m_dim.y+m_minDim.y;
- }
- m_dim.y += pos.y-m_pressPos.y;
- }
- }
- m_pressPos = pos;
- AdjustButtons();
-
- Event newEvent = event;
- newEvent.event = m_eventMsg;
- m_event->AddEvent(newEvent);
- }
-
- if ( event.event == EVENT_LBUTTONUP && m_bCapture )
- {
- m_bCapture = false;
- }
-
- return true;
-}
-
-
-// Draws the window.
-
-void CWindow::Draw()
-{
- Math::Point pos, dim;
- float width, h, sw;
- int i;
-
- if ( (m_state & STATE_VISIBLE) == 0 ) return;
-
- if ( m_state & STATE_SHADOW )
- {
- DrawShadow(m_pos, m_dim);
- }
-
- DrawVertex(m_pos, m_dim, m_icon); // draws the background
-
- if ( m_name[0] != 0 ) // title bar?
- {
- h = m_engine->RetText()->RetHeight(m_fontSize, m_fontType);
-
- // Draws the shadow under the title bar.
- {
- Math::Point sPos, sDim;
-
- pos.x = m_pos.x+0.01f;
- dim.x = m_dim.x-0.02f;
- pos.y = m_pos.y+m_dim.y-0.01f-h*1.2f;
- dim.y = h*1.2f;
- DrawShadow(pos, dim);
- }
-
- width = m_dim.x;
- if ( m_bRedim ) width -= h*1.2f*0.75f*2.0f;
- if ( m_bClosable ) width -= h*1.2f*0.75f;
-
- pos.x = m_pos.x+0.01f;
- dim.x = width-0.02f;
- pos.y = m_pos.y+m_dim.y-0.01f-h*1.2f;
- dim.y = h*1.2f;
- DrawVertex(pos, dim, (m_state&STATE_ENABLE)?2:9);
-
- sw = m_engine->RetText()->RetStringWidth(m_name, strlen(m_name), m_fontSize, m_fontStretch, m_fontType);
-
- if ( m_state&STATE_ENABLE )
- {
- pos.x = m_pos.x+0.015f;
- dim.x = (width-sw-0.06f)/2.0f;
- pos.y = m_pos.y+m_dim.y-0.01f-h*1.0f;
- dim.y = h*0.8f;
- DrawHach(pos, dim); // left hatch
- pos.x = m_pos.x+width-dim.x-0.015f;
- DrawHach(pos, dim); // right hatch
- }
-
- pos.x = m_pos.x+width/2.0f;
- pos.y = m_pos.y+m_dim.y-0.01f-h*1.10f;
- m_engine->RetText()->DrawText(m_name, pos, width, 0, m_fontSize, m_fontStretch, m_fontType, 0);
-
- if ( m_buttonReduce != 0 )
- {
- m_buttonReduce->Draw();
- }
-
- if ( m_buttonFull != 0 )
- {
- m_buttonFull->Draw();
- }
-
- if ( m_buttonClose != 0 )
- {
- m_buttonClose->Draw();
- }
- }
-
- for ( i=0 ; i<MAXWINDOW ; i++ )
- {
- if ( m_table[i] != 0 )
- {
- m_table[i]->Draw();
- }
- }
-}
-
-// Draws a rectangle.
-
-void CWindow::DrawVertex(Math::Point pos, Math::Point dim, int icon)
-{
- Math::Point p1, p2, uv1, uv2, corner;
- float dp;
- int i;
-
- dp = 0.5f/256.0f;
-
- if ( icon == 0 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTw);
- uv1.x = 64.0f/256.0f; // dark blue transparent
- uv1.y = 64.0f/256.0f;
- uv2.x = 128.0f/256.0f;
- uv2.y = 128.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 14.0f/640.0f;
- corner.y = 14.0f/480.0f;
- DrawIcon(pos, dim, uv1, uv2, corner, 8.0f/256.0f);
- }
- else if ( icon == 1 )
- {
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 128.0f/256.0f; // yellow tooltip
- uv1.y = 0.0f/256.0f;
- uv2.x = 224.0f/256.0f;
- uv2.y = 16.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f);
- }
- else if ( icon == 2 )
- {
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 128.0f/256.0f; // yellow
- uv1.y = 16.0f/256.0f;
- uv2.x = 224.0f/256.0f;
- uv2.y = 32.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f);
- }
- else if ( icon == 3 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTb);
- uv1.x = 0.0f/256.0f; // transparent blue bar with yellow upper
- uv1.y = 64.0f/256.0f;
- uv2.x = 64.0f/256.0f;
- uv2.y = 128.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f);
- }
- else if ( icon == 4 ) // SatCom ?
- {
- pos.x -= 50.0f/640.0f;
- pos.y -= 30.0f/480.0f;
- dim.x += 100.0f/640.0f;
- dim.y += 60.0f/480.0f;
-
- m_engine->SetTexture("human.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 140.0f/256.0f;
- uv1.y = 32.0f/256.0f;
- uv2.x = 182.0f/256.0f;
- uv2.y = 64.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2); // clothing
-
- pos.x += 20.0f/640.0f;
- pos.y -= 10.0f/480.0f;
- dim.x -= 20.0f/640.0f;
- dim.y += 0.0f/480.0f;
-
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTw);
- uv1.x = 192.0f/256.0f;
- uv1.y = 32.0f/256.0f;
- uv2.x = 224.0f/256.0f;
- uv2.y = 64.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 30.0f/640.0f;
- corner.y = 30.0f/480.0f;
- DrawIcon(pos, dim, uv1, uv2, corner, 5.0f/256.0f); // shadow
-
- pos.x += 0.0f/640.0f;
- pos.y += 20.0f/480.0f;
- dim.x -= 20.0f/640.0f;
- dim.y -= 20.0f/480.0f;
-
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 64.0f/256.0f;
- uv1.y = 0.0f/256.0f;
- uv2.x = 96.0f/256.0f;
- uv2.y = 32.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 14.0f/640.0f;
- corner.y = 14.0f/480.0f;
- DrawIcon(pos, dim, uv1, uv2, corner, 8.0f/256.0f); // outside blue
-
- pos.x += 20.0f/640.0f;
- pos.y += 10.0f/480.0f;
- dim.x -= 40.0f/640.0f;
- dim.y -= 20.0f/480.0f;
-
- uv1.x = 96.0f/256.0f;
- uv1.y = 0.0f/256.0f;
- uv2.x = 128.0f/256.0f;
- uv2.y = 32.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 14.0f/640.0f;
- corner.y = 14.0f/480.0f;
- DrawIcon(pos, dim, uv1, uv2, corner, 8.0f/256.0f); // inside blue
-
- pos.x += 10.0f/640.0f;
- pos.y += 10.0f/480.0f;
- dim.x -= 20.0f/640.0f;
- dim.y -= 20.0f/480.0f;
-
- m_engine->SetTexture("button3.tga");
- uv1.x = 0.0f/256.0f;
- uv1.y = 224.0f/256.0f;
- uv2.x = 32.0f/256.0f;
- uv2.y = 256.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2); // dark blue background
-
- m_engine->SetTexture("button2.tga");
- uv1.x = 224.0f/256.0f;
- uv1.y = 224.0f/256.0f;
- uv2.x = 249.0f/256.0f;
- uv2.y = 235.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- pos.x = 20.0f/640.0f;
- pos.y = 70.0f/480.0f;
- dim.x = 25.0f/640.0f;
- dim.y = 11.0f/480.0f;
- for ( i=0 ; i<5 ; i++ )
- {
- DrawIcon(pos, dim, uv1, uv2); // = bottom/left
- pos.y += 15.0f/480.0f;
- }
- pos.y = (480.0f-70.0f-11.0f)/480.0f;
- for ( i=0 ; i<5 ; i++ )
- {
- DrawIcon(pos, dim, uv1, uv2); // = top/left
- pos.y -= 15.0f/480.0f;
- }
- pos.x = (640.0f-25.0f-20.0f)/640.0f;
- pos.y = 70.0f/480.0f;
- for ( i=0 ; i<5 ; i++ )
- {
- DrawIcon(pos, dim, uv1, uv2); // = bottom/right
- pos.y += 15.0f/480.0f;
- }
- pos.y = (480.0f-70.0f-11.0f)/480.0f;
- for ( i=0 ; i<5 ; i++ )
- {
- DrawIcon(pos, dim, uv1, uv2); // = top/right
- pos.y -= 15.0f/480.0f;
- }
-
- uv1.x = 208.0f/256.0f;
- uv1.y = 224.0f/256.0f;
- uv2.x = 224.0f/256.0f;
- uv2.y = 240.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- dim.x = 10.0f/640.0f;
- dim.y = 10.0f/480.0f;
- pos.x = 534.0f/640.0f;
- pos.y = 430.0f/480.0f;
- for ( i=0 ; i<3 ; i++ )
- {
- DrawIcon(pos, dim, uv1, uv2); // micro
- pos.x += 12.0f/640.0f;
- }
- pos.x = 528.0f/640.0f;
- pos.y -= 12.0f/480.0f;
- for ( i=0 ; i<4 ; i++ )
- {
- DrawIcon(pos, dim, uv1, uv2); // micro
- pos.x += 12.0f/640.0f;
- }
- pos.x = 534.0f/640.0f;
- pos.y -= 12.0f/480.0f;
- for ( i=0 ; i<3 ; i++ )
- {
- DrawIcon(pos, dim, uv1, uv2); // micro
- pos.x += 12.0f/640.0f;
- }
- }
- else if ( icon == 5 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTb);
- uv1.x = 64.0f/256.0f; // transparent green
- uv1.y = 160.0f/256.0f;
- uv2.x = 160.0f/256.0f;
- uv2.y = 176.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f);
- }
- else if ( icon == 6 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTb);
- uv1.x = 64.0f/256.0f; // transparent red
- uv1.y = 176.0f/256.0f;
- uv2.x = 160.0f/256.0f;
- uv2.y = 192.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f);
- }
- else if ( icon == 7 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTb);
- uv1.x = 64.0f/256.0f; // transparent blue
- uv1.y = 192.0f/256.0f;
- uv2.x = 160.0f/256.0f;
- uv2.y = 208.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f);
- }
- else if ( icon == 8 )
- {
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 0.0f/256.0f; // opaque orange
- uv1.y = 0.0f/256.0f;
- uv2.x = 32.0f/256.0f;
- uv2.y = 32.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 14.0f/640.0f;
- corner.y = 14.0f/480.0f;
- DrawIcon(pos, dim, uv1, uv2, corner, 8.0f/256.0f);
- }
- else if ( icon == 9 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 32.0f/256.0f; // opaque gray
- uv1.y = 32.0f/256.0f;
- uv2.x = 64.0f/256.0f;
- uv2.y = 64.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 14.0f/640.0f;
- corner.y = 14.0f/480.0f;
- DrawIcon(pos, dim, uv1, uv2, corner, 8.0f/256.0f);
- }
- else if ( icon == 10 )
- {
- // nothing (in the background image)!
- }
- else if ( icon == 11 )
- {
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATETTb);
- uv1.x = 64.0f/256.0f; // transparent yellow
- uv1.y = 224.0f/256.0f;
- uv2.x = 160.0f/256.0f;
- uv2.y = 240.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f);
- }
- else if ( icon == 12 )
- {
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 128.0f/256.0f; // dirty opaque gray
- uv1.y = 128.0f/256.0f;
- uv2.x = 160.0f/256.0f;
- uv2.y = 160.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 6.0f/640.0f;
- corner.y = 6.0f/480.0f;
- DrawIcon(pos, dim, uv1, uv2, corner, 5.0f/256.0f);
- }
- else if ( icon == 13 )
- {
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 192.0f/256.0f; // dirty opaque blue
- uv1.y = 128.0f/256.0f;
- uv2.x = 224.0f/256.0f;
- uv2.y = 160.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 6.0f/640.0f;
- corner.y = 6.0f/480.0f;
- DrawIcon(pos, dim, uv1, uv2, corner, 5.0f/256.0f);
- }
- else if ( icon == 14 )
- {
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 160.0f/256.0f; // dirty opaque red
- uv1.y = 128.0f/256.0f;
- uv2.x = 192.0f/256.0f;
- uv2.y = 160.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
- corner.x = 6.0f/640.0f;
- corner.y = 6.0f/480.0f;
- DrawIcon(pos, dim, uv1, uv2, corner, 5.0f/256.0f);
- }
-}
-
-// Draws hatching.
-
-void CWindow::DrawHach(Math::Point pos, Math::Point dim)
-{
-#if _NEWLOOK
-#else
- Math::Point ppos, ddim, uv1, uv2;
- float dp, max, ndim;
- bool bStop;
-
- dp = 0.5f/256.0f;
-
- m_engine->SetTexture("button2.tga");
- m_engine->SetState(D3DSTATENORMAL);
- uv1.x = 64.0f/256.0f; // hatching
- uv1.y = 208.0f/256.0f;
- uv2.x = 145.0f/256.0f;
- uv2.y = 224.0f/256.0f;
- uv1.x += dp;
- uv1.y += dp;
- uv2.x -= dp;
- uv2.y -= dp;
-
- max = dim.y*(uv2.x-uv1.x)/(uv2.y-uv1.y);
-
- ppos = pos;
- ddim = dim;
- bStop = false;
- do
- {
- ddim.x = max;
- if ( ppos.x+ddim.x > pos.x+dim.x )
- {
- ndim = pos.x+dim.x-ppos.x;
- uv2.x = uv1.x+(uv2.x-uv1.x)*(ndim/ddim.x);
- ddim.x = ndim;
- bStop = true;
- }
- DrawIcon(ppos, ddim, uv1, uv2);
-
- ppos.x += ddim.x;
- }
- while ( !bStop );
-#endif
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// window.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "common/language.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/restext.h"
+#include "common/iman.h"
+#include "ui/button.h"
+#include "ui/color.h"
+#include "ui/check.h"
+#include "ui/key.h"
+#include "ui/group.h"
+#include "ui/image.h"
+#include "ui/label.h"
+#include "ui/edit.h"
+#include "ui/editvalue.h"
+#include "ui/scroll.h"
+#include "ui/slider.h"
+#include "ui/list.h"
+#include "ui/shortcut.h"
+#include "ui/map.h"
+#include "ui/gauge.h"
+#include "ui/compass.h"
+#include "ui/target.h"
+#include "old/text.h"
+#include "ui/window.h"
+
+
+
+
+// Object's constructor.
+
+CWindow::CWindow(CInstanceManager* iMan) : CControl(iMan)
+{
+ int i;
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ m_table[i] = 0;
+ }
+
+ m_bTrashEvent = true;
+ m_bMaximized = false;
+ m_bMinimized = false;
+ m_bFixed = false;
+
+ m_minDim = Math::Point(0.0f, 0.0f);
+ m_maxDim = Math::Point(1.0f, 1.0f);
+
+ m_buttonReduce = 0;
+ m_buttonFull = 0;
+ m_buttonClose = 0;
+
+ m_bMovable = false;
+ m_bRedim = false;
+ m_bClosable = false;
+ m_bCapture = false;
+
+ m_fontStretch = NORMSTRETCH*1.2f;
+}
+
+// Object's destructor.
+
+CWindow::~CWindow()
+{
+ Flush();
+}
+
+
+// Purge all the controls.
+
+void CWindow::Flush()
+{
+ int i;
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] != 0 )
+ {
+ delete m_table[i];
+ m_table[i] = 0;
+ }
+ }
+
+ if ( m_buttonReduce != 0 )
+ {
+ delete m_buttonReduce;
+ m_buttonReduce = 0;
+ }
+
+ if ( m_buttonFull != 0 )
+ {
+ delete m_buttonFull;
+ m_buttonFull = 0;
+ }
+
+ if ( m_buttonClose != 0 )
+ {
+ delete m_buttonClose;
+ m_buttonClose = 0;
+ }
+}
+
+
+// Creates a new window.
+
+bool CWindow::Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ CControl::Create(pos, dim, icon, eventMsg);
+ return true;
+}
+
+
+// Creates a new button.
+
+CButton* CWindow::CreateButton(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CButton* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CButton(m_iMan);
+ pc = (CButton*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new button.
+
+CColor* CWindow::CreateColor(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CColor* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CColor(m_iMan);
+ pc = (CColor*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new button.
+
+CCheck* CWindow::CreateCheck(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CCheck* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CCheck(m_iMan);
+ pc = (CCheck*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new button.
+
+CKey* CWindow::CreateKey(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CKey* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CKey(m_iMan);
+ pc = (CKey*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new button.
+
+CGroup* CWindow::CreateGroup(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CGroup* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CGroup(m_iMan);
+ pc = (CGroup*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new button.
+
+CImage* CWindow::CreateImage(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CImage* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CImage(m_iMan);
+ pc = (CImage*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new label.
+
+CLabel* CWindow::CreateLabel(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg,
+ char *name)
+{
+ CLabel* pc;
+ char* p;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CLabel(m_iMan);
+ pc = (CLabel*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+
+ p = strchr(name, '\\');
+ if ( p == 0 )
+ {
+ pc->SetName(name);
+ }
+ else
+ {
+ char text[100];
+ strncpy(text, name, 100);
+ text[100-1] = 0;
+ if ( p-name < 100 )
+ {
+ text[p-name] = 0; // deletes text after "\\" (tooltip)
+ }
+ pc->SetName(text);
+ }
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new editable pave.
+
+CEdit* CWindow::CreateEdit(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CEdit* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CEdit(m_iMan);
+ pc = (CEdit*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new editable pave.
+
+CEditValue* CWindow::CreateEditValue(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CEditValue* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CEditValue(m_iMan);
+ pc = (CEditValue*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new elevator.
+
+CScroll* CWindow::CreateScroll(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CScroll* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CScroll(m_iMan);
+ pc = (CScroll*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new cursor.
+
+CSlider* CWindow::CreateSlider(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CSlider* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CSlider(m_iMan);
+ pc = (CSlider*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new list.
+
+CList* CWindow::CreateList(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg,
+ float expand)
+{
+ CList* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CList(m_iMan);
+ pc = (CList*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg, expand);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new shortcut.
+
+CShortcut* CWindow::CreateShortcut(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CShortcut* ps;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CShortcut(m_iMan);
+ ps = (CShortcut*)m_table[i];
+ ps->Create(pos, dim, icon, eventMsg);
+ return ps;
+ }
+ }
+ return 0;
+}
+
+// Creates a new card.
+
+CMap* CWindow::CreateMap(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CMap* pm;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CMap(m_iMan);
+ pm = (CMap*)m_table[i];
+ pm->Create(pos, dim, icon, eventMsg);
+ return pm;
+ }
+ }
+ return 0;
+}
+
+// Creates a new gauge.
+
+CGauge* CWindow::CreateGauge(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CGauge* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CGauge(m_iMan);
+ pc = (CGauge*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new compass.
+
+CCompass* CWindow::CreateCompass(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CCompass* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CCompass(m_iMan);
+ pc = (CCompass*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Creates a new target.
+
+CTarget* CWindow::CreateTarget(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg)
+{
+ CTarget* pc;
+ int i;
+
+ if ( eventMsg == EVENT_NULL ) eventMsg = GetUniqueEventMsg();
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] == 0 )
+ {
+ m_table[i] = new CTarget(m_iMan);
+ pc = (CTarget*)m_table[i];
+ pc->Create(pos, dim, icon, eventMsg);
+ return pc;
+ }
+ }
+ return 0;
+}
+
+// Removes a control.
+
+bool CWindow::DeleteControl(EventMsg eventMsg)
+{
+ int i;
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] != 0 )
+ {
+ if ( eventMsg == m_table[i]->RetEventMsg() )
+ {
+ delete m_table[i];
+ m_table[i] = 0;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// Gives a control.
+
+CControl* CWindow::SearchControl(EventMsg eventMsg)
+{
+ int i;
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] != 0 )
+ {
+ if ( eventMsg == m_table[i]->RetEventMsg() )
+ {
+ return m_table[i];
+ }
+ }
+ }
+ return 0;
+}
+
+
+// Makes the tooltip binds to the window.
+
+bool CWindow::GetTooltip(Math::Point pos, char* name)
+{
+ int i;
+
+ for ( i=MAXWINDOW-1 ; i>=0 ; i-- )
+ {
+ if ( m_table[i] != 0 )
+ {
+ if ( m_table[i]->GetTooltip(pos, name) )
+ {
+ return true;
+ }
+ }
+ }
+
+ if ( m_buttonClose != 0 &&
+ m_buttonClose->GetTooltip(pos, name) )
+ {
+ return true;
+ }
+ if ( m_buttonFull != 0 &&
+ m_buttonFull->GetTooltip(pos, name) )
+ {
+ return true;
+ }
+ if ( m_buttonReduce != 0 &&
+ m_buttonReduce->GetTooltip(pos, name) )
+ {
+ return true;
+ }
+
+ if ( Detect(pos) ) // in the window?
+ {
+ strcpy(name, m_tooltip);
+ return true;
+ }
+
+ return false;
+}
+
+
+// Specifies the name for the title bar.
+
+void CWindow::SetName(char* name)
+{
+ CButton* pc;
+ bool bAdjust;
+
+ CControl::SetName(name);
+
+ if ( m_buttonReduce != 0 )
+ {
+ delete m_buttonReduce;
+ m_buttonReduce = 0;
+ }
+
+ if ( m_buttonFull != 0 )
+ {
+ delete m_buttonFull;
+ m_buttonFull = 0;
+ }
+
+ if ( m_buttonClose != 0 )
+ {
+ delete m_buttonClose;
+ m_buttonClose = 0;
+ }
+
+ bAdjust = false;
+
+ if ( m_name[0] != 0 && m_bRedim ) // title bar exists?
+ {
+ m_buttonReduce = new CButton(m_iMan);
+ pc = (CButton*)m_buttonReduce;
+ pc->Create(m_pos, m_dim, 0, EVENT_NULL);
+
+ m_buttonFull = new CButton(m_iMan);
+ pc = (CButton*)m_buttonFull;
+ pc->Create(m_pos, m_dim, 0, EVENT_NULL);
+
+ bAdjust = true;
+ }
+
+ if ( m_name[0] != 0 && m_bClosable ) // title bar exists?
+ {
+ m_buttonClose = new CButton(m_iMan);
+ pc = (CButton*)m_buttonClose;
+ pc->Create(m_pos, m_dim, 0, EVENT_NULL);
+
+ bAdjust = true;
+ }
+
+ if ( bAdjust )
+ {
+ AdjustButtons();
+ }
+
+ MoveAdjust();
+}
+
+
+void CWindow::SetPos(Math::Point pos)
+{
+ CControl::SetPos(pos);
+ MoveAdjust();
+}
+
+void CWindow::SetDim(Math::Point dim)
+{
+ if ( dim.x < m_minDim.x ) dim.x = m_minDim.x;
+ if ( dim.x > m_maxDim.x ) dim.x = m_maxDim.x;
+ if ( dim.y < m_minDim.y ) dim.y = m_minDim.y;
+ if ( dim.y > m_maxDim.y ) dim.y = m_maxDim.y;
+
+ CControl::SetDim(dim);
+ MoveAdjust();
+}
+
+void CWindow::MoveAdjust()
+{
+ Math::Point pos, dim;
+ float h, offset;
+
+ h = m_engine->RetText()->RetHeight(m_fontSize, m_fontType);
+ dim.y = h*1.2f;
+ dim.x = dim.y*0.75f;
+
+ if ( m_buttonClose != 0 )
+ {
+ pos.x = m_pos.x+m_dim.x-0.01f-dim.x;
+ pos.y = m_pos.y+m_dim.y-0.01f-h*1.2f;
+ m_buttonClose->SetPos(pos);
+ m_buttonClose->SetDim(dim);
+ offset = dim.x*1.0f;
+ }
+ else
+ {
+ offset = 0.0f;
+ }
+
+ if ( m_buttonFull != 0 )
+ {
+ pos.x = m_pos.x+m_dim.x-0.01f-dim.x-offset;
+ pos.y = m_pos.y+m_dim.y-0.01f-h*1.2f;
+ m_buttonFull->SetPos(pos);
+ m_buttonFull->SetDim(dim);
+ }
+
+ if ( m_buttonReduce != 0 )
+ {
+ pos.x = m_pos.x+m_dim.x-0.01f-dim.x*2.0f-offset;
+ pos.y = m_pos.y+m_dim.y-0.01f-h*1.2f;
+ m_buttonReduce->SetPos(pos);
+ m_buttonReduce->SetDim(dim);
+ }
+}
+
+
+void CWindow::SetMinDim(Math::Point dim)
+{
+ m_minDim = dim;
+}
+
+void CWindow::SetMaxDim(Math::Point dim)
+{
+ m_maxDim = dim;
+}
+
+Math::Point CWindow::RetMinDim()
+{
+ return m_minDim;
+}
+
+Math::Point CWindow::RetMaxDim()
+{
+ return m_maxDim;
+}
+
+
+// Indicates whether the window is moved.
+
+void CWindow::SetMovable(bool bMode)
+{
+ m_bMovable = bMode;
+}
+
+bool CWindow::RetMovable()
+{
+ return m_bMovable;
+}
+
+
+// Management of the presence of minimize/maximize buttons.
+
+void CWindow::SetRedim(bool bMode)
+{
+ m_bRedim = bMode;
+}
+
+bool CWindow::RetRedim()
+{
+ return m_bRedim;
+}
+
+
+// Management of the presence of the close button.
+
+void CWindow::SetClosable(bool bMode)
+{
+ m_bClosable = bMode;
+}
+
+bool CWindow::RetClosable()
+{
+ return m_bClosable;
+}
+
+
+void CWindow::SetMaximized(bool bMaxi)
+{
+ m_bMaximized = bMaxi;
+ AdjustButtons();
+}
+
+bool CWindow::RetMaximized()
+{
+ return m_bMaximized;
+}
+
+void CWindow::SetMinimized(bool bMini)
+{
+ m_bMinimized = bMini;
+ AdjustButtons();
+}
+
+bool CWindow::RetMinimized()
+{
+ return m_bMinimized;
+}
+
+void CWindow::SetFixed(bool bFix)
+{
+ m_bFixed = bFix;
+}
+
+bool CWindow::RetFixed()
+{
+ return m_bFixed;
+}
+
+
+// Adjusts the buttons in the title bar.
+
+void CWindow::AdjustButtons()
+{
+ char res[100];
+
+ if ( m_buttonFull != 0 )
+ {
+ if ( m_bMaximized )
+ {
+ m_buttonFull->SetIcon(54);
+ GetResource(RES_TEXT, RT_WINDOW_STANDARD, res);
+ m_buttonFull->SetTooltip(res);
+ }
+ else
+ {
+ m_buttonFull->SetIcon(52);
+ GetResource(RES_TEXT, RT_WINDOW_MAXIMIZED, res);
+ m_buttonFull->SetTooltip(res);
+ }
+ }
+
+ if ( m_buttonReduce != 0 )
+ {
+ if ( m_bMinimized )
+ {
+ m_buttonReduce->SetIcon(54);
+ GetResource(RES_TEXT, RT_WINDOW_STANDARD, res);
+ m_buttonReduce->SetTooltip(res);
+ }
+ else
+ {
+ m_buttonReduce->SetIcon(51);
+ GetResource(RES_TEXT, RT_WINDOW_MINIMIZED, res);
+ m_buttonReduce->SetTooltip(res);
+ }
+ }
+
+ if ( m_buttonClose != 0 )
+ {
+ m_buttonClose->SetIcon(11); // x
+ GetResource(RES_TEXT, RT_WINDOW_CLOSE, res);
+ m_buttonClose->SetTooltip(res);
+ }
+}
+
+
+void CWindow::SetTrashEvent(bool bTrash)
+{
+ m_bTrashEvent = bTrash;
+}
+
+bool CWindow::RetTrashEvent()
+{
+ return m_bTrashEvent;
+}
+
+
+// Returns the message from the button "reduce".
+
+EventMsg CWindow::RetEventMsgReduce()
+{
+ if ( m_buttonReduce == 0 ) return EVENT_NULL;
+ return m_buttonReduce->RetEventMsg();
+}
+
+// Returns the message from the button "full".
+
+EventMsg CWindow::RetEventMsgFull()
+{
+ if ( m_buttonFull == 0 ) return EVENT_NULL;
+ return m_buttonFull->RetEventMsg();
+}
+
+// Returns the message from the button "close".
+
+EventMsg CWindow::RetEventMsgClose()
+{
+ if ( m_buttonClose == 0 ) return EVENT_NULL;
+ return m_buttonClose->RetEventMsg();
+}
+
+
+// Detects whether the mouse is in an edge of the window, to resize it.
+// Bit returns: 0 = left, 1 = down, 2 = right, 3 = up, 1 = all.
+
+int CWindow::BorderDetect(Math::Point pos)
+{
+ Math::Point dim;
+ float h;
+ int flags;
+
+ if ( m_bMaximized || m_bMinimized || m_bFixed ) return 0;
+
+ flags = 0;
+ if ( pos.x < m_pos.x+0.030f )
+ {
+ flags |= (1<<0);
+ }
+ if ( pos.y < m_pos.y+0.020f )
+ {
+ flags |= (1<<1);
+ }
+ if ( pos.x > m_pos.x+m_dim.x-0.030f )
+ {
+ flags |= (1<<2);
+ }
+ if ( pos.y > m_pos.y+m_dim.y-0.020f )
+ {
+ flags |= (1<<3);
+ }
+
+ if ( pos.x > m_pos.x+ 0.015f &&
+ pos.x < m_pos.x+m_dim.x-0.015f &&
+ pos.y > m_pos.y+ 0.010f &&
+ pos.y < m_pos.y+m_dim.y-0.010f )
+ {
+ flags = 0;
+ }
+
+ if ( flags == 0 )
+ {
+ h = m_engine->RetText()->RetHeight(m_fontSize, m_fontType);
+ dim.y = h*1.2f;
+ dim.x = dim.y*0.75f;
+ if ( pos.x < m_pos.x+m_dim.x-0.01f-dim.x*3.0f &&
+ pos.y >= m_pos.y+m_dim.y-0.01f-h*1.2f )
+ {
+ flags = -1;
+ }
+ }
+
+ return flags;
+}
+
+// Management of an event.
+
+bool CWindow::EventProcess(const Event &event)
+{
+ Math::Point pos;
+ int i, flags;
+
+ if ( event.event == EVENT_MOUSEMOVE )
+ {
+ if ( m_bCapture )
+ {
+ m_engine->SetMouseType(m_pressMouse);
+ }
+ else
+ {
+ m_pressMouse = D3DMOUSENORM;
+
+ if ( m_name[0] != 0 && m_bMovable && // title bar?
+ Detect(event.pos) )
+ {
+ flags = BorderDetect(event.pos);
+ if ( flags == -1 )
+ {
+ m_pressMouse = D3DMOUSEMOVE; // +
+ }
+ else if ( ((flags & (1<<0)) && (flags & (1<<3))) ||
+ ((flags & (1<<1)) && (flags & (1<<2))) )
+ {
+ m_pressMouse = D3DMOUSEMOVEI; // \ //
+ }
+ else if ( ((flags & (1<<0)) && (flags & (1<<1))) ||
+ ((flags & (1<<2)) && (flags & (1<<3))) )
+ {
+ m_pressMouse = D3DMOUSEMOVED; // /
+ }
+ else if ( (flags & (1<<0)) || (flags & (1<<2)) )
+ {
+ m_pressMouse = D3DMOUSEMOVEH; // -
+ }
+ else if ( (flags & (1<<1)) || (flags & (1<<3)) )
+ {
+ m_pressMouse = D3DMOUSEMOVEV; // |
+ }
+ }
+
+ if ( m_pressMouse != D3DMOUSENORM )
+ {
+ m_engine->SetMouseType(m_pressMouse);
+ }
+ }
+ }
+
+ if ( !m_bCapture )
+ {
+ for ( i=MAXWINDOW-1 ; i>=0 ; i-- )
+ {
+ if ( m_table[i] != 0 )
+ {
+ if ( !m_table[i]->EventProcess(event) )
+ {
+ return false;
+ }
+ }
+ }
+
+ if ( m_buttonReduce != 0 )
+ {
+ m_buttonReduce->EventProcess(event);
+ }
+ if ( m_buttonFull != 0 )
+ {
+ m_buttonFull->EventProcess(event);
+ }
+ if ( m_buttonClose != 0 )
+ {
+ m_buttonClose->EventProcess(event);
+ }
+ }
+
+ if ( m_bTrashEvent && event.event == EVENT_LBUTTONDOWN )
+ {
+ if ( Detect(event.pos) )
+ {
+ if ( m_name[0] != 0 && m_bMovable ) // title bar?
+ {
+ m_pressFlags = BorderDetect(event.pos);
+ if ( m_pressFlags != 0 )
+ {
+ m_bCapture = true;
+ m_pressPos = event.pos;
+ }
+ }
+ return false;
+ }
+ }
+
+ if ( event.event == EVENT_MOUSEMOVE && m_bCapture )
+ {
+ pos = event.pos;
+ if ( m_pressFlags == -1 ) // all moves?
+ {
+ m_pos.x += pos.x-m_pressPos.x;
+ m_pos.y += pos.y-m_pressPos.y;
+ }
+ else
+ {
+ if ( m_pressFlags & (1<<0) ) // left edge?
+ {
+ if ( pos.x > m_pressPos.x+m_dim.x-m_minDim.x )
+ {
+ pos.x = m_pressPos.x+m_dim.x-m_minDim.x;
+ }
+ m_pos.x += pos.x-m_pressPos.x;
+ m_dim.x -= pos.x-m_pressPos.x;
+ }
+ if ( m_pressFlags & (1<<1) ) // bottom edge?
+ {
+ if ( pos.y > m_pressPos.y+m_dim.y-m_minDim.y )
+ {
+ pos.y = m_pressPos.y+m_dim.y-m_minDim.y;
+ }
+ m_pos.y += pos.y-m_pressPos.y;
+ m_dim.y -= pos.y-m_pressPos.y;
+ }
+ if ( m_pressFlags & (1<<2) ) // right edge?
+ {
+ if ( pos.x < m_pressPos.x-m_dim.x+m_minDim.x )
+ {
+ pos.x = m_pressPos.x-m_dim.x+m_minDim.x;
+ }
+ m_dim.x += pos.x-m_pressPos.x;
+ }
+ if ( m_pressFlags & (1<<3) ) // top edge?
+ {
+ if ( pos.y < m_pressPos.y-m_dim.y+m_minDim.y )
+ {
+ pos.y = m_pressPos.y-m_dim.y+m_minDim.y;
+ }
+ m_dim.y += pos.y-m_pressPos.y;
+ }
+ }
+ m_pressPos = pos;
+ AdjustButtons();
+
+ Event newEvent = event;
+ newEvent.event = m_eventMsg;
+ m_event->AddEvent(newEvent);
+ }
+
+ if ( event.event == EVENT_LBUTTONUP && m_bCapture )
+ {
+ m_bCapture = false;
+ }
+
+ return true;
+}
+
+
+// Draws the window.
+
+void CWindow::Draw()
+{
+ Math::Point pos, dim;
+ float width, h, sw;
+ int i;
+
+ if ( (m_state & STATE_VISIBLE) == 0 ) return;
+
+ if ( m_state & STATE_SHADOW )
+ {
+ DrawShadow(m_pos, m_dim);
+ }
+
+ DrawVertex(m_pos, m_dim, m_icon); // draws the background
+
+ if ( m_name[0] != 0 ) // title bar?
+ {
+ h = m_engine->RetText()->RetHeight(m_fontSize, m_fontType);
+
+ // Draws the shadow under the title bar.
+ {
+ Math::Point sPos, sDim;
+
+ pos.x = m_pos.x+0.01f;
+ dim.x = m_dim.x-0.02f;
+ pos.y = m_pos.y+m_dim.y-0.01f-h*1.2f;
+ dim.y = h*1.2f;
+ DrawShadow(pos, dim);
+ }
+
+ width = m_dim.x;
+ if ( m_bRedim ) width -= h*1.2f*0.75f*2.0f;
+ if ( m_bClosable ) width -= h*1.2f*0.75f;
+
+ pos.x = m_pos.x+0.01f;
+ dim.x = width-0.02f;
+ pos.y = m_pos.y+m_dim.y-0.01f-h*1.2f;
+ dim.y = h*1.2f;
+ DrawVertex(pos, dim, (m_state&STATE_ENABLE)?2:9);
+
+ sw = m_engine->RetText()->RetStringWidth(m_name, strlen(m_name), m_fontSize, m_fontStretch, m_fontType);
+
+ if ( m_state&STATE_ENABLE )
+ {
+ pos.x = m_pos.x+0.015f;
+ dim.x = (width-sw-0.06f)/2.0f;
+ pos.y = m_pos.y+m_dim.y-0.01f-h*1.0f;
+ dim.y = h*0.8f;
+ DrawHach(pos, dim); // left hatch
+ pos.x = m_pos.x+width-dim.x-0.015f;
+ DrawHach(pos, dim); // right hatch
+ }
+
+ pos.x = m_pos.x+width/2.0f;
+ pos.y = m_pos.y+m_dim.y-0.01f-h*1.10f;
+ m_engine->RetText()->DrawText(m_name, pos, width, 0, m_fontSize, m_fontStretch, m_fontType, 0);
+
+ if ( m_buttonReduce != 0 )
+ {
+ m_buttonReduce->Draw();
+ }
+
+ if ( m_buttonFull != 0 )
+ {
+ m_buttonFull->Draw();
+ }
+
+ if ( m_buttonClose != 0 )
+ {
+ m_buttonClose->Draw();
+ }
+ }
+
+ for ( i=0 ; i<MAXWINDOW ; i++ )
+ {
+ if ( m_table[i] != 0 )
+ {
+ m_table[i]->Draw();
+ }
+ }
+}
+
+// Draws a rectangle.
+
+void CWindow::DrawVertex(Math::Point pos, Math::Point dim, int icon)
+{
+ Math::Point p1, p2, uv1, uv2, corner;
+ float dp;
+ int i;
+
+ dp = 0.5f/256.0f;
+
+ if ( icon == 0 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTw);
+ uv1.x = 64.0f/256.0f; // dark blue transparent
+ uv1.y = 64.0f/256.0f;
+ uv2.x = 128.0f/256.0f;
+ uv2.y = 128.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 14.0f/640.0f;
+ corner.y = 14.0f/480.0f;
+ DrawIcon(pos, dim, uv1, uv2, corner, 8.0f/256.0f);
+ }
+ else if ( icon == 1 )
+ {
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 128.0f/256.0f; // yellow tooltip
+ uv1.y = 0.0f/256.0f;
+ uv2.x = 224.0f/256.0f;
+ uv2.y = 16.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f);
+ }
+ else if ( icon == 2 )
+ {
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 128.0f/256.0f; // yellow
+ uv1.y = 16.0f/256.0f;
+ uv2.x = 224.0f/256.0f;
+ uv2.y = 32.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f);
+ }
+ else if ( icon == 3 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTb);
+ uv1.x = 0.0f/256.0f; // transparent blue bar with yellow upper
+ uv1.y = 64.0f/256.0f;
+ uv2.x = 64.0f/256.0f;
+ uv2.y = 128.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f);
+ }
+ else if ( icon == 4 ) // SatCom ?
+ {
+ pos.x -= 50.0f/640.0f;
+ pos.y -= 30.0f/480.0f;
+ dim.x += 100.0f/640.0f;
+ dim.y += 60.0f/480.0f;
+
+ m_engine->SetTexture("human.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 140.0f/256.0f;
+ uv1.y = 32.0f/256.0f;
+ uv2.x = 182.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2); // clothing
+
+ pos.x += 20.0f/640.0f;
+ pos.y -= 10.0f/480.0f;
+ dim.x -= 20.0f/640.0f;
+ dim.y += 0.0f/480.0f;
+
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTw);
+ uv1.x = 192.0f/256.0f;
+ uv1.y = 32.0f/256.0f;
+ uv2.x = 224.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 30.0f/640.0f;
+ corner.y = 30.0f/480.0f;
+ DrawIcon(pos, dim, uv1, uv2, corner, 5.0f/256.0f); // shadow
+
+ pos.x += 0.0f/640.0f;
+ pos.y += 20.0f/480.0f;
+ dim.x -= 20.0f/640.0f;
+ dim.y -= 20.0f/480.0f;
+
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 64.0f/256.0f;
+ uv1.y = 0.0f/256.0f;
+ uv2.x = 96.0f/256.0f;
+ uv2.y = 32.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 14.0f/640.0f;
+ corner.y = 14.0f/480.0f;
+ DrawIcon(pos, dim, uv1, uv2, corner, 8.0f/256.0f); // outside blue
+
+ pos.x += 20.0f/640.0f;
+ pos.y += 10.0f/480.0f;
+ dim.x -= 40.0f/640.0f;
+ dim.y -= 20.0f/480.0f;
+
+ uv1.x = 96.0f/256.0f;
+ uv1.y = 0.0f/256.0f;
+ uv2.x = 128.0f/256.0f;
+ uv2.y = 32.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 14.0f/640.0f;
+ corner.y = 14.0f/480.0f;
+ DrawIcon(pos, dim, uv1, uv2, corner, 8.0f/256.0f); // inside blue
+
+ pos.x += 10.0f/640.0f;
+ pos.y += 10.0f/480.0f;
+ dim.x -= 20.0f/640.0f;
+ dim.y -= 20.0f/480.0f;
+
+ m_engine->SetTexture("button3.tga");
+ uv1.x = 0.0f/256.0f;
+ uv1.y = 224.0f/256.0f;
+ uv2.x = 32.0f/256.0f;
+ uv2.y = 256.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2); // dark blue background
+
+ m_engine->SetTexture("button2.tga");
+ uv1.x = 224.0f/256.0f;
+ uv1.y = 224.0f/256.0f;
+ uv2.x = 249.0f/256.0f;
+ uv2.y = 235.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ pos.x = 20.0f/640.0f;
+ pos.y = 70.0f/480.0f;
+ dim.x = 25.0f/640.0f;
+ dim.y = 11.0f/480.0f;
+ for ( i=0 ; i<5 ; i++ )
+ {
+ DrawIcon(pos, dim, uv1, uv2); // = bottom/left
+ pos.y += 15.0f/480.0f;
+ }
+ pos.y = (480.0f-70.0f-11.0f)/480.0f;
+ for ( i=0 ; i<5 ; i++ )
+ {
+ DrawIcon(pos, dim, uv1, uv2); // = top/left
+ pos.y -= 15.0f/480.0f;
+ }
+ pos.x = (640.0f-25.0f-20.0f)/640.0f;
+ pos.y = 70.0f/480.0f;
+ for ( i=0 ; i<5 ; i++ )
+ {
+ DrawIcon(pos, dim, uv1, uv2); // = bottom/right
+ pos.y += 15.0f/480.0f;
+ }
+ pos.y = (480.0f-70.0f-11.0f)/480.0f;
+ for ( i=0 ; i<5 ; i++ )
+ {
+ DrawIcon(pos, dim, uv1, uv2); // = top/right
+ pos.y -= 15.0f/480.0f;
+ }
+
+ uv1.x = 208.0f/256.0f;
+ uv1.y = 224.0f/256.0f;
+ uv2.x = 224.0f/256.0f;
+ uv2.y = 240.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ dim.x = 10.0f/640.0f;
+ dim.y = 10.0f/480.0f;
+ pos.x = 534.0f/640.0f;
+ pos.y = 430.0f/480.0f;
+ for ( i=0 ; i<3 ; i++ )
+ {
+ DrawIcon(pos, dim, uv1, uv2); // micro
+ pos.x += 12.0f/640.0f;
+ }
+ pos.x = 528.0f/640.0f;
+ pos.y -= 12.0f/480.0f;
+ for ( i=0 ; i<4 ; i++ )
+ {
+ DrawIcon(pos, dim, uv1, uv2); // micro
+ pos.x += 12.0f/640.0f;
+ }
+ pos.x = 534.0f/640.0f;
+ pos.y -= 12.0f/480.0f;
+ for ( i=0 ; i<3 ; i++ )
+ {
+ DrawIcon(pos, dim, uv1, uv2); // micro
+ pos.x += 12.0f/640.0f;
+ }
+ }
+ else if ( icon == 5 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTb);
+ uv1.x = 64.0f/256.0f; // transparent green
+ uv1.y = 160.0f/256.0f;
+ uv2.x = 160.0f/256.0f;
+ uv2.y = 176.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f);
+ }
+ else if ( icon == 6 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTb);
+ uv1.x = 64.0f/256.0f; // transparent red
+ uv1.y = 176.0f/256.0f;
+ uv2.x = 160.0f/256.0f;
+ uv2.y = 192.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f);
+ }
+ else if ( icon == 7 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTb);
+ uv1.x = 64.0f/256.0f; // transparent blue
+ uv1.y = 192.0f/256.0f;
+ uv2.x = 160.0f/256.0f;
+ uv2.y = 208.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f);
+ }
+ else if ( icon == 8 )
+ {
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 0.0f/256.0f; // opaque orange
+ uv1.y = 0.0f/256.0f;
+ uv2.x = 32.0f/256.0f;
+ uv2.y = 32.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 14.0f/640.0f;
+ corner.y = 14.0f/480.0f;
+ DrawIcon(pos, dim, uv1, uv2, corner, 8.0f/256.0f);
+ }
+ else if ( icon == 9 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 32.0f/256.0f; // opaque gray
+ uv1.y = 32.0f/256.0f;
+ uv2.x = 64.0f/256.0f;
+ uv2.y = 64.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 14.0f/640.0f;
+ corner.y = 14.0f/480.0f;
+ DrawIcon(pos, dim, uv1, uv2, corner, 8.0f/256.0f);
+ }
+ else if ( icon == 10 )
+ {
+ // nothing (in the background image)!
+ }
+ else if ( icon == 11 )
+ {
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATETTb);
+ uv1.x = 64.0f/256.0f; // transparent yellow
+ uv1.y = 224.0f/256.0f;
+ uv2.x = 160.0f/256.0f;
+ uv2.y = 240.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ DrawIcon(pos, dim, uv1, uv2, 8.0f/256.0f);
+ }
+ else if ( icon == 12 )
+ {
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 128.0f/256.0f; // dirty opaque gray
+ uv1.y = 128.0f/256.0f;
+ uv2.x = 160.0f/256.0f;
+ uv2.y = 160.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 6.0f/640.0f;
+ corner.y = 6.0f/480.0f;
+ DrawIcon(pos, dim, uv1, uv2, corner, 5.0f/256.0f);
+ }
+ else if ( icon == 13 )
+ {
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 192.0f/256.0f; // dirty opaque blue
+ uv1.y = 128.0f/256.0f;
+ uv2.x = 224.0f/256.0f;
+ uv2.y = 160.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 6.0f/640.0f;
+ corner.y = 6.0f/480.0f;
+ DrawIcon(pos, dim, uv1, uv2, corner, 5.0f/256.0f);
+ }
+ else if ( icon == 14 )
+ {
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 160.0f/256.0f; // dirty opaque red
+ uv1.y = 128.0f/256.0f;
+ uv2.x = 192.0f/256.0f;
+ uv2.y = 160.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+ corner.x = 6.0f/640.0f;
+ corner.y = 6.0f/480.0f;
+ DrawIcon(pos, dim, uv1, uv2, corner, 5.0f/256.0f);
+ }
+}
+
+// Draws hatching.
+
+void CWindow::DrawHach(Math::Point pos, Math::Point dim)
+{
+#if _NEWLOOK
+#else
+ Math::Point ppos, ddim, uv1, uv2;
+ float dp, max, ndim;
+ bool bStop;
+
+ dp = 0.5f/256.0f;
+
+ m_engine->SetTexture("button2.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+ uv1.x = 64.0f/256.0f; // hatching
+ uv1.y = 208.0f/256.0f;
+ uv2.x = 145.0f/256.0f;
+ uv2.y = 224.0f/256.0f;
+ uv1.x += dp;
+ uv1.y += dp;
+ uv2.x -= dp;
+ uv2.y -= dp;
+
+ max = dim.y*(uv2.x-uv1.x)/(uv2.y-uv1.y);
+
+ ppos = pos;
+ ddim = dim;
+ bStop = false;
+ do
+ {
+ ddim.x = max;
+ if ( ppos.x+ddim.x > pos.x+dim.x )
+ {
+ ndim = pos.x+dim.x-ppos.x;
+ uv2.x = uv1.x+(uv2.x-uv1.x)*(ndim/ddim.x);
+ ddim.x = ndim;
+ bStop = true;
+ }
+ DrawIcon(ppos, ddim, uv1, uv2);
+
+ ppos.x += ddim.x;
+ }
+ while ( !bStop );
+#endif
+}
+
diff --git a/src/ui/window.h b/src/ui/window.h
index 169c68e..3acf3b4 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -1,146 +1,146 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// window.h
-
-#pragma once
-
-
-#include "ui/control.h"
-
-
-class CD3DEngine;
-class CButton;
-class CColor;
-class CCheck;
-class CKey;
-class CGroup;
-class CImage;
-class CLabel;
-class CEdit;
-class CEditValue;
-class CScroll;
-class CSlider;
-class CList;
-class CShortcut;
-class CMap;
-class CGauge;
-class CCompass;
-class CTarget;
-
-
-const int MAXWINDOW = 100;
-
-
-class CWindow : public CControl
-{
-public:
- CWindow(CInstanceManager* iMan);
- ~CWindow();
-
- void Flush();
- bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CButton* CreateButton(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CColor* CreateColor(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CCheck* CreateCheck(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CKey* CreateKey(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CGroup* CreateGroup(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CImage* CreateImage(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CLabel* CreateLabel(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg, char *name);
- CEdit* CreateEdit(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CEditValue* CreateEditValue(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CScroll* CreateScroll(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CSlider* CreateSlider(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CList* CreateList(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg, float expand=1.2f);
- CShortcut* CreateShortcut(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CMap* CreateMap(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CGauge* CreateGauge(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CCompass* CreateCompass(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- CTarget* CreateTarget(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
- bool DeleteControl(EventMsg eventMsg);
- CControl* SearchControl(EventMsg eventMsg);
-
- EventMsg RetEventMsgReduce();
- EventMsg RetEventMsgFull();
- EventMsg RetEventMsgClose();
-
- void SetName(char* name);
-
- void SetTrashEvent(bool bTrash);
- bool RetTrashEvent();
-
- void SetPos(Math::Point pos);
- void SetDim(Math::Point dim);
-
- void SetMinDim(Math::Point dim);
- void SetMaxDim(Math::Point dim);
- Math::Point RetMinDim();
- Math::Point RetMaxDim();
-
- void SetMovable(bool bMode);
- bool RetMovable();
-
- void SetRedim(bool bMode);
- bool RetRedim();
-
- void SetClosable(bool bMode);
- bool RetClosable();
-
- void SetMaximized(bool bMaxi);
- bool RetMaximized();
- void SetMinimized(bool bMini);
- bool RetMinimized();
- void SetFixed(bool bFix);
- bool RetFixed();
-
- bool GetTooltip(Math::Point pos, char* name);
-
- bool EventProcess(const Event &event);
-
- void Draw();
-
-protected:
- int BorderDetect(Math::Point pos);
- void AdjustButtons();
- void MoveAdjust();
- void DrawVertex(Math::Point pos, Math::Point dim, int icon);
- void DrawHach(Math::Point pos, Math::Point dim);
-
-protected:
- CControl* m_table[MAXWINDOW];
-
- bool m_bTrashEvent;
- bool m_bMaximized;
- bool m_bMinimized;
- bool m_bFixed;
-
- Math::Point m_minDim;
- Math::Point m_maxDim;
-
- CButton* m_buttonReduce;
- CButton* m_buttonFull;
- CButton* m_buttonClose;
-
- bool m_bMovable;
- bool m_bRedim;
- bool m_bClosable;
- bool m_bCapture;
- Math::Point m_pressPos;
- int m_pressFlags;
- D3DMouse m_pressMouse;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// window.h
+
+#pragma once
+
+
+#include "ui/control.h"
+
+
+class CD3DEngine;
+class CButton;
+class CColor;
+class CCheck;
+class CKey;
+class CGroup;
+class CImage;
+class CLabel;
+class CEdit;
+class CEditValue;
+class CScroll;
+class CSlider;
+class CList;
+class CShortcut;
+class CMap;
+class CGauge;
+class CCompass;
+class CTarget;
+
+
+const int MAXWINDOW = 100;
+
+
+class CWindow : public CControl
+{
+public:
+ CWindow(CInstanceManager* iMan);
+ ~CWindow();
+
+ void Flush();
+ bool Create(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CButton* CreateButton(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CColor* CreateColor(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CCheck* CreateCheck(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CKey* CreateKey(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CGroup* CreateGroup(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CImage* CreateImage(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CLabel* CreateLabel(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg, char *name);
+ CEdit* CreateEdit(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CEditValue* CreateEditValue(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CScroll* CreateScroll(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CSlider* CreateSlider(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CList* CreateList(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg, float expand=1.2f);
+ CShortcut* CreateShortcut(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CMap* CreateMap(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CGauge* CreateGauge(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CCompass* CreateCompass(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ CTarget* CreateTarget(Math::Point pos, Math::Point dim, int icon, EventMsg eventMsg);
+ bool DeleteControl(EventMsg eventMsg);
+ CControl* SearchControl(EventMsg eventMsg);
+
+ EventMsg RetEventMsgReduce();
+ EventMsg RetEventMsgFull();
+ EventMsg RetEventMsgClose();
+
+ void SetName(char* name);
+
+ void SetTrashEvent(bool bTrash);
+ bool RetTrashEvent();
+
+ void SetPos(Math::Point pos);
+ void SetDim(Math::Point dim);
+
+ void SetMinDim(Math::Point dim);
+ void SetMaxDim(Math::Point dim);
+ Math::Point RetMinDim();
+ Math::Point RetMaxDim();
+
+ void SetMovable(bool bMode);
+ bool RetMovable();
+
+ void SetRedim(bool bMode);
+ bool RetRedim();
+
+ void SetClosable(bool bMode);
+ bool RetClosable();
+
+ void SetMaximized(bool bMaxi);
+ bool RetMaximized();
+ void SetMinimized(bool bMini);
+ bool RetMinimized();
+ void SetFixed(bool bFix);
+ bool RetFixed();
+
+ bool GetTooltip(Math::Point pos, char* name);
+
+ bool EventProcess(const Event &event);
+
+ void Draw();
+
+protected:
+ int BorderDetect(Math::Point pos);
+ void AdjustButtons();
+ void MoveAdjust();
+ void DrawVertex(Math::Point pos, Math::Point dim, int icon);
+ void DrawHach(Math::Point pos, Math::Point dim);
+
+protected:
+ CControl* m_table[MAXWINDOW];
+
+ bool m_bTrashEvent;
+ bool m_bMaximized;
+ bool m_bMinimized;
+ bool m_bFixed;
+
+ Math::Point m_minDim;
+ Math::Point m_maxDim;
+
+ CButton* m_buttonReduce;
+ CButton* m_buttonFull;
+ CButton* m_buttonClose;
+
+ bool m_bMovable;
+ bool m_bRedim;
+ bool m_bClosable;
+ bool m_bCapture;
+ Math::Point m_pressPos;
+ int m_pressFlags;
+ D3DMouse m_pressMouse;
+};
+
+
diff --git a/tools/README.txt b/tools/README.txt
new file mode 100644
index 0000000..89d5b9c
--- /dev/null
+++ b/tools/README.txt
@@ -0,0 +1,4 @@
+tools/
+
+This directory contains useful scripts for changing many files at once,
+for example replacing string occurences or converting whitespace.
diff --git a/tools/convert-whitespace.sh b/tools/convert-whitespace.sh
new file mode 100755
index 0000000..6f844ad
--- /dev/null
+++ b/tools/convert-whitespace.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+# A script for converting whitespace from old format to new
+# For each argument, replaces tabs with 4 spaces and DOS line endings to UNIX
+
+for file in "$@"; do
+ dos2unix "$file"
+ expand -t 4 "$file" > "$file.out"
+ mv -f "$file.out" "$file"
+done