From fc5389d18816799ba2698914384cd099ba8a7a6c Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Tue, 26 Jun 2012 19:56:04 +0200 Subject: Created dev-opengl branch --- README-DEV-OPENGL.txt | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++ README-DEV.txt | 86 --------------------------------------------------- 2 files changed, 86 insertions(+), 86 deletions(-) create mode 100644 README-DEV-OPENGL.txt delete mode 100644 README-DEV.txt diff --git a/README-DEV-OPENGL.txt b/README-DEV-OPENGL.txt new file mode 100644 index 0000000..a71c429 --- /dev/null +++ b/README-DEV-OPENGL.txt @@ -0,0 +1,86 @@ +README for developers + +This file outlines the most important things for developers. + +1. Goal. + + This branch is dedicated to rewriting the graphics engine as well as window & event handling, sound and all other parts of the project dependent on WinAPI or DirectX, to new platform-independent libraries: SDL, OpenGL and fmod (for sound). + The general rule is to rewrite the code so that it resembles the old one as closely as possible so that later on, it can be joined easily with the other modules, which will not be touched yet. Of course, it doesn't mean to sacrifice the usability or flexibility of new interfaces, so some cleaning-up is welcome. + + +2. Build system and organisation of directories. + + The directories in the repository are as following: + src/CBot separate CBot library + src/app class CApplication and everything concerned with SDL plus other system-dependent code such as displaying a message box, finding files, etc. + src/common shared structs, enums, defines, etc.; should not have any external dependencies + src/graphics/common interface of graphics engine (CEngine) and device (CDevice), without concrete implementation, shared structs such as Vertex, Material, etc., "effects" classes: CCamera, CLight, CParticle that will use the graphics engine interface + src/graphics/opengl concrete implementation of CEngine and CDevice classes in OpenGL: CGLEngine and CGLDevice + src/graphics/d3d in (far) future - perhaps a newer implementation in DirectX (9? 10?) + src/math mathematical structures and functions + src/object non-graphical game engine, that is robots, buildings, etc.; dependent only on interface of graphics engine, not on concrete implementation + src/ui 2D user interface (menu, buttons, check boxes, etc.); also without dependencies to concrete implementation of graphics engine + src/sound sound and music engine written using fmod library + src/physics physics engine + src/script link with the CBot library + src/old old modules that will be replaced by new code + + Other directories, not very important right now, include: + src/doc contains the Doxygen mainpage text; it will probably be removed to app/main.cpp or some other place soon + src/metafile a separate program for packing data files to .dat format + + The build system is as follows: + /CMakeLists.txt - definition of project, build type setup, general compiler options and reference to src subdirectory + /src/CMakeLists.txt - currently defines two targets: colobot_old - the original game comprised of old sources, compiles and runs only on Windows; colobot_new - new implementation in SDL, compiles and runs on Windows and Linux, for now only "hello world"-like; colobot_old target references also CBot library + /src/CBot/CMakeLists.txt - defines the CBot library target + + There is also a generated header common/config.h with #defines set by CMake. + + +3. Plan of work. + + What is done so far: + - changes in the build system + - rewriting of math module and reaching independence from old FPOINT, D3DVECTOR and D3DMATRIX structs + - first draft of class and struct templates in src/graphics/common + + What remains to be done: + - in CBot library - remove dependencies to WinAPI and translate the comments from French to English + - write CApplication class, including handling of SDL events, mouse, joystick, etc. + - (connected with the above) remove dependencies from src/common + - complete the CDevice and CEngine interfaces and write the concrete implementations of CGLDevice and CGLEngine + - write the implementation of other classes in graphics engine, matching the old implementation but using only the new interface + - write the implementation of new sound module + - rewrite the old UI classes to use new graphics interface + - rewrite the old src/object classes to use new graphics interface + + Certain tasks regarding the work should be assigned to each developer using Issues on github, so that the division is clear. + + +3. Rewriting modules. + + The rewriting rule is the following: every old module/header that needs to be replaced will be moved to src/old and all references to it in the rest of the code shall be changed to src/old as well. In place of the old module, a new one will be created with the new declarations, preferrably enclosing everything in a separate namespace. This way, the new code will be separated from the old one, for the time being, thus making it possible to work on new code and not break anything else. Once the functionality of new code matches the old one, it can be replaced in old code with ease. + + +4. Documentation. + + All new code should be documented in Doxygen. Also, don't hesitate to add comments in the old code, where you deciphered some use or detail that you want to share. + + +5. Tests. + + Whenever possible, please write unit tests for your code. Tests should go into test subdirectory in each of the code directories and for now, should be independent of main build system (later on, we will combine them, but for now it will be easier this way). + + +6. Commiting code. + + Code commited to the repository should not break compilation nor tests. Breaking the compilation of old code can be tolerated but the new one - no! If you are uncertain, or want to make partial commit or something like that, commit to your own fork, or if you must, commit but comment out the code that breaks the build. + + +7. Whitespace rules. + + Please indent with spaces, 1 indentation level = 4 spaces. Unix line endings. And don't leave whitespace at the end of lines. Thank you :) + + + +I will probably think of something more in the future, but that's it for now. Thanks for reading and good luck :) diff --git a/README-DEV.txt b/README-DEV.txt deleted file mode 100644 index a71c429..0000000 --- a/README-DEV.txt +++ /dev/null @@ -1,86 +0,0 @@ -README for developers - -This file outlines the most important things for developers. - -1. Goal. - - This branch is dedicated to rewriting the graphics engine as well as window & event handling, sound and all other parts of the project dependent on WinAPI or DirectX, to new platform-independent libraries: SDL, OpenGL and fmod (for sound). - The general rule is to rewrite the code so that it resembles the old one as closely as possible so that later on, it can be joined easily with the other modules, which will not be touched yet. Of course, it doesn't mean to sacrifice the usability or flexibility of new interfaces, so some cleaning-up is welcome. - - -2. Build system and organisation of directories. - - The directories in the repository are as following: - src/CBot separate CBot library - src/app class CApplication and everything concerned with SDL plus other system-dependent code such as displaying a message box, finding files, etc. - src/common shared structs, enums, defines, etc.; should not have any external dependencies - src/graphics/common interface of graphics engine (CEngine) and device (CDevice), without concrete implementation, shared structs such as Vertex, Material, etc., "effects" classes: CCamera, CLight, CParticle that will use the graphics engine interface - src/graphics/opengl concrete implementation of CEngine and CDevice classes in OpenGL: CGLEngine and CGLDevice - src/graphics/d3d in (far) future - perhaps a newer implementation in DirectX (9? 10?) - src/math mathematical structures and functions - src/object non-graphical game engine, that is robots, buildings, etc.; dependent only on interface of graphics engine, not on concrete implementation - src/ui 2D user interface (menu, buttons, check boxes, etc.); also without dependencies to concrete implementation of graphics engine - src/sound sound and music engine written using fmod library - src/physics physics engine - src/script link with the CBot library - src/old old modules that will be replaced by new code - - Other directories, not very important right now, include: - src/doc contains the Doxygen mainpage text; it will probably be removed to app/main.cpp or some other place soon - src/metafile a separate program for packing data files to .dat format - - The build system is as follows: - /CMakeLists.txt - definition of project, build type setup, general compiler options and reference to src subdirectory - /src/CMakeLists.txt - currently defines two targets: colobot_old - the original game comprised of old sources, compiles and runs only on Windows; colobot_new - new implementation in SDL, compiles and runs on Windows and Linux, for now only "hello world"-like; colobot_old target references also CBot library - /src/CBot/CMakeLists.txt - defines the CBot library target - - There is also a generated header common/config.h with #defines set by CMake. - - -3. Plan of work. - - What is done so far: - - changes in the build system - - rewriting of math module and reaching independence from old FPOINT, D3DVECTOR and D3DMATRIX structs - - first draft of class and struct templates in src/graphics/common - - What remains to be done: - - in CBot library - remove dependencies to WinAPI and translate the comments from French to English - - write CApplication class, including handling of SDL events, mouse, joystick, etc. - - (connected with the above) remove dependencies from src/common - - complete the CDevice and CEngine interfaces and write the concrete implementations of CGLDevice and CGLEngine - - write the implementation of other classes in graphics engine, matching the old implementation but using only the new interface - - write the implementation of new sound module - - rewrite the old UI classes to use new graphics interface - - rewrite the old src/object classes to use new graphics interface - - Certain tasks regarding the work should be assigned to each developer using Issues on github, so that the division is clear. - - -3. Rewriting modules. - - The rewriting rule is the following: every old module/header that needs to be replaced will be moved to src/old and all references to it in the rest of the code shall be changed to src/old as well. In place of the old module, a new one will be created with the new declarations, preferrably enclosing everything in a separate namespace. This way, the new code will be separated from the old one, for the time being, thus making it possible to work on new code and not break anything else. Once the functionality of new code matches the old one, it can be replaced in old code with ease. - - -4. Documentation. - - All new code should be documented in Doxygen. Also, don't hesitate to add comments in the old code, where you deciphered some use or detail that you want to share. - - -5. Tests. - - Whenever possible, please write unit tests for your code. Tests should go into test subdirectory in each of the code directories and for now, should be independent of main build system (later on, we will combine them, but for now it will be easier this way). - - -6. Commiting code. - - Code commited to the repository should not break compilation nor tests. Breaking the compilation of old code can be tolerated but the new one - no! If you are uncertain, or want to make partial commit or something like that, commit to your own fork, or if you must, commit but comment out the code that breaks the build. - - -7. Whitespace rules. - - Please indent with spaces, 1 indentation level = 4 spaces. Unix line endings. And don't leave whitespace at the end of lines. Thank you :) - - - -I will probably think of something more in the future, but that's it for now. Thanks for reading and good luck :) -- cgit v1.2.3-1-g7c22 From ebed57aa22b772211387a5561f995eee8f5faed1 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Tue, 26 Jun 2012 22:23:05 +0200 Subject: Whitespace and language change - changed tabs to spaces and DOS line endings to Unix (except in CBot and metafile) - changed language to English - fixed #include in d3dengine.h --- src/app/app.cpp | 602 +- src/app/app.h | 174 +- src/app/main.cpp | 18 +- src/app/system.cpp | 340 +- src/app/system.h | 28 +- src/common/event.cpp | 192 +- src/common/event.h | 1266 +-- src/common/global.h | 132 +- src/common/iman.cpp | 324 +- src/common/iman.h | 110 +- src/common/language.h | 108 +- src/common/metafile.cpp | 832 +- src/common/metafile.h | 148 +- src/common/misc.cpp | 882 +- src/common/misc.h | 476 +- src/common/modfile.cpp | 1390 ++-- src/common/modfile.h | 230 +- src/common/profile.cpp | 228 +- src/common/profile.h | 60 +- src/common/restext.cpp | 7319 ++++++++-------- src/common/restext.h | 316 +- src/common/struct.h | 106 +- src/graphics/common/camera.h | 378 +- src/graphics/common/cloud.h | 74 +- src/graphics/common/color.h | 12 +- src/graphics/common/device.cpp | 16 +- src/graphics/common/device.h | 36 +- src/graphics/common/engine.cpp | 52 +- src/graphics/common/engine.h | 1122 +-- src/graphics/common/light.h | 104 +- src/graphics/common/lightning.h | 60 +- src/graphics/common/material.h | 12 +- src/graphics/common/model.h | 198 +- src/graphics/common/modfile.h | 114 +- src/graphics/common/particle.h | 506 +- src/graphics/common/planet.h | 54 +- src/graphics/common/pyro.h | 202 +- src/graphics/common/terrain.h | 270 +- src/graphics/common/text.h | 82 +- src/graphics/common/vertex.h | 26 +- src/graphics/common/water.h | 130 +- src/math/const.h | 32 +- src/math/conv.h | 26 +- src/math/func.h | 156 +- src/math/geometry.h | 496 +- src/math/intpoint.h | 10 +- src/math/matrix.h | 630 +- src/math/point.h | 216 +- src/math/test/geometry_test.cpp | 472 +- src/math/test/matrix_test.cpp | 612 +- src/math/test/vector_test.cpp | 132 +- src/math/vector.h | 332 +- src/object/auto/auto.cpp | 874 +- src/object/auto/auto.h | 222 +- src/object/auto/autobase.cpp | 2882 +++---- src/object/auto/autobase.h | 224 +- src/object/auto/autoconvert.cpp | 1054 +-- src/object/auto/autoconvert.h | 140 +- src/object/auto/autoderrick.cpp | 1178 +-- src/object/auto/autoderrick.h | 142 +- src/object/auto/autodestroyer.cpp | 748 +- src/object/auto/autodestroyer.h | 130 +- src/object/auto/autoegg.cpp | 718 +- src/object/auto/autoegg.h | 138 +- src/object/auto/autoenergy.cpp | 1294 +-- src/object/auto/autoenergy.h | 142 +- src/object/auto/autofactory.cpp | 1882 ++--- src/object/auto/autofactory.h | 148 +- src/object/auto/autoflag.cpp | 324 +- src/object/auto/autoflag.h | 92 +- src/object/auto/autohuston.cpp | 592 +- src/object/auto/autohuston.h | 130 +- src/object/auto/autoinfo.cpp | 1034 +-- src/object/auto/autoinfo.h | 136 +- src/object/auto/autojostle.cpp | 284 +- src/object/auto/autojostle.h | 96 +- src/object/auto/autokid.cpp | 402 +- src/object/auto/autokid.h | 94 +- src/object/auto/autolabo.cpp | 1220 +-- src/object/auto/autolabo.h | 150 +- src/object/auto/automush.cpp | 688 +- src/object/auto/automush.h | 122 +- src/object/auto/autonest.cpp | 550 +- src/object/auto/autonest.h | 122 +- src/object/auto/autonuclear.cpp | 968 +-- src/object/auto/autonuclear.h | 136 +- src/object/auto/autopara.cpp | 654 +- src/object/auto/autopara.h | 130 +- src/object/auto/autoportico.cpp | 850 +- src/object/auto/autoportico.h | 138 +- src/object/auto/autoradar.cpp | 612 +- src/object/auto/autoradar.h | 128 +- src/object/auto/autorepair.cpp | 678 +- src/object/auto/autorepair.h | 130 +- src/object/auto/autoresearch.cpp | 1216 +-- src/object/auto/autoresearch.h | 140 +- src/object/auto/autoroot.cpp | 240 +- src/object/auto/autoroot.h | 88 +- src/object/auto/autosafe.cpp | 1224 +-- src/object/auto/autosafe.h | 148 +- src/object/auto/autostation.cpp | 740 +- src/object/auto/autostation.h | 112 +- src/object/auto/autotower.cpp | 1082 +-- src/object/auto/autotower.h | 148 +- src/object/brain.cpp | 5998 +++++++------- src/object/brain.h | 436 +- src/object/mainmovie.cpp | 476 +- src/object/mainmovie.h | 160 +- src/object/motion/motion.cpp | 478 +- src/object/motion/motion.h | 186 +- src/object/motion/motionant.cpp | 1742 ++-- src/object/motion/motionant.h | 146 +- src/object/motion/motionbee.cpp | 1288 +-- src/object/motion/motionbee.h | 132 +- src/object/motion/motionhuman.cpp | 3540 ++++---- src/object/motion/motionhuman.h | 188 +- src/object/motion/motionmother.cpp | 1048 +-- src/object/motion/motionmother.h | 108 +- src/object/motion/motionspider.cpp | 1518 ++-- src/object/motion/motionspider.h | 142 +- src/object/motion/motiontoto.cpp | 1738 ++-- src/object/motion/motiontoto.h | 140 +- src/object/motion/motionvehicle.cpp | 4146 ++++----- src/object/motion/motionvehicle.h | 138 +- src/object/motion/motionworm.cpp | 730 +- src/object/motion/motionworm.h | 124 +- src/object/object.cpp | 15212 +++++++++++++++++----------------- src/object/object.h | 1550 ++-- src/object/robotmain.cpp | 14064 +++++++++++++++---------------- src/object/robotmain.h | 918 +- src/object/task/task.cpp | 178 +- src/object/task/task.h | 172 +- src/object/task/taskadvance.cpp | 292 +- src/object/task/taskadvance.h | 100 +- src/object/task/taskbuild.cpp | 1612 ++-- src/object/task/taskbuild.h | 170 +- src/object/task/taskfire.cpp | 768 +- src/object/task/taskfire.h | 104 +- src/object/task/taskfireant.cpp | 424 +- src/object/task/taskfireant.h | 126 +- src/object/task/taskflag.cpp | 610 +- src/object/task/taskflag.h | 116 +- src/object/task/taskgoto.cpp | 4682 +++++------ src/object/task/taskgoto.h | 314 +- src/object/task/taskgungoal.cpp | 298 +- src/object/task/taskgungoal.h | 96 +- src/object/task/taskinfo.cpp | 438 +- src/object/task/taskinfo.h | 94 +- src/object/task/taskmanager.cpp | 556 +- src/object/task/taskmanager.h | 142 +- src/object/task/taskmanip.cpp | 2766 +++---- src/object/task/taskmanip.h | 198 +- src/object/task/taskpen.cpp | 574 +- src/object/task/taskpen.h | 136 +- src/object/task/taskrecover.cpp | 834 +- src/object/task/taskrecover.h | 132 +- src/object/task/taskreset.cpp | 660 +- src/object/task/taskreset.h | 126 +- src/object/task/tasksearch.cpp | 642 +- src/object/task/tasksearch.h | 140 +- src/object/task/taskshield.cpp | 1120 +-- src/object/task/taskshield.h | 168 +- src/object/task/taskspiderexplo.cpp | 220 +- src/object/task/taskspiderexplo.h | 88 +- src/object/task/tasktake.cpp | 1192 +-- src/object/task/tasktake.h | 150 +- src/object/task/taskterraform.cpp | 832 +- src/object/task/taskterraform.h | 124 +- src/object/task/taskturn.cpp | 268 +- src/object/task/taskturn.h | 92 +- src/object/task/taskwait.cpp | 148 +- src/object/task/taskwait.h | 88 +- src/old/blitz.cpp | 950 +-- src/old/blitz.h | 166 +- src/old/camera.cpp | 4218 +++++----- src/old/camera.h | 538 +- src/old/cloud.cpp | 676 +- src/old/cloud.h | 176 +- src/old/d3dapp.cpp | 4902 +++++------ src/old/d3dapp.h | 332 +- src/old/d3dengine.cpp | 11650 +++++++++++++------------- src/old/d3dengine.h | 1354 +-- src/old/d3denum.cpp | 1240 +-- src/old/d3denum.h | 266 +- src/old/d3dframe.cpp | 1244 +-- src/old/d3dframe.h | 282 +- src/old/d3dmath.cpp | 686 +- src/old/d3dmath.h | 214 +- src/old/d3dres.h | 110 +- src/old/d3dtextr.cpp | 2162 ++--- src/old/d3dtextr.h | 158 +- src/old/d3dutil.cpp | 650 +- src/old/d3dutil.h | 226 +- src/old/joystick.cpp | 488 +- src/old/joystick.h | 54 +- src/old/light.cpp | 1008 +-- src/old/light.h | 218 +- src/old/math3d.cpp | 2394 +++--- src/old/math3d.h | 96 +- src/old/model.cpp | 6456 +++++++-------- src/old/model.h | 272 +- src/old/modfile.cpp | 1058 +-- src/old/modfile.h | 114 +- src/old/particule.cpp | 8802 ++++++++++---------- src/old/particule.h | 674 +- src/old/planet.cpp | 494 +- src/old/planet.h | 152 +- src/old/pyro.cpp | 4972 +++++------ src/old/pyro.h | 340 +- src/old/resource.h | 110 +- src/old/sound.cpp | 3318 ++++---- src/old/sound.h | 484 +- src/old/terrain.cpp | 4540 +++++----- src/old/terrain.h | 418 +- src/old/text.cpp | 3758 ++++----- src/old/text.h | 222 +- src/old/water.cpp | 1688 ++-- src/old/water.h | 260 +- src/physics/physics.cpp | 7770 ++++++++--------- src/physics/physics.h | 492 +- src/script/ClassFILE.cpp | 850 +- src/script/cbottoken.cpp | 1038 +-- src/script/cbottoken.h | 72 +- src/script/cmdtoken.cpp | 1952 ++--- src/script/cmdtoken.h | 128 +- src/script/dd.cpp | 350 +- src/script/script.cpp | 7552 ++++++++--------- src/script/script.h | 236 +- src/sound/sound.h | 222 +- src/ui/button.cpp | 492 +- src/ui/button.h | 112 +- src/ui/check.cpp | 332 +- src/ui/check.h | 92 +- src/ui/color.cpp | 448 +- src/ui/color.h | 112 +- src/ui/compass.cpp | 350 +- src/ui/compass.h | 100 +- src/ui/control.cpp | 1748 ++-- src/ui/control.h | 276 +- src/ui/displayinfo.cpp | 2438 +++--- src/ui/displayinfo.h | 180 +- src/ui/displaytext.cpp | 1226 +-- src/ui/displaytext.h | 192 +- src/ui/edit.cpp | 6632 +++++++-------- src/ui/edit.h | 496 +- src/ui/editvalue.cpp | 756 +- src/ui/editvalue.h | 166 +- src/ui/gauge.cpp | 314 +- src/ui/gauge.h | 100 +- src/ui/group.cpp | 1288 +-- src/ui/group.h | 92 +- src/ui/image.cpp | 310 +- src/ui/image.h | 100 +- src/ui/interface.cpp | 1210 +-- src/ui/interface.h | 190 +- src/ui/key.cpp | 576 +- src/ui/key.h | 104 +- src/ui/label.cpp | 186 +- src/ui/label.h | 92 +- src/ui/list.cpp | 1736 ++-- src/ui/list.h | 230 +- src/ui/maindialog.cpp | 13870 +++++++++++++++---------------- src/ui/maindialog.h | 506 +- src/ui/mainmap.cpp | 804 +- src/ui/mainmap.h | 140 +- src/ui/mainshort.cpp | 748 +- src/ui/mainshort.h | 124 +- src/ui/map.cpp | 2678 +++--- src/ui/map.h | 274 +- src/ui/scroll.cpp | 938 +-- src/ui/scroll.h | 162 +- src/ui/shortcut.cpp | 482 +- src/ui/shortcut.h | 96 +- src/ui/slider.cpp | 1160 +-- src/ui/slider.h | 162 +- src/ui/studio.cpp | 3330 ++++---- src/ui/studio.h | 230 +- src/ui/target.cpp | 566 +- src/ui/target.h | 96 +- src/ui/window.cpp | 3240 ++++---- src/ui/window.h | 292 +- tools/README.txt | 4 + tools/convert-whitespace.sh | 10 + 283 files changed, 137774 insertions(+), 137759 deletions(-) create mode 100644 tools/README.txt create mode 100755 tools/convert-whitespace.sh 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(¤tEvent, 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(¤tEvent, 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 - - -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 + + +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 - -#include "common/struct.h" -#include "common/iman.h" - - - - -// Object's constructor. - -CInstanceManager::CInstanceManager() -{ - int i; - - for ( i=0 ; i= 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= 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 + +#include "common/struct.h" +#include "common/iman.h" + + + + +// Object's constructor. + +CInstanceManager::CInstanceManager() +{ + int i; + + for ( i=0 ; i= 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= 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 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 -#include - -#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 +#include + +#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 - - -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 + + +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 -#include -#include -#include -#include -#include -#include - -#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 +#include +#include +#include +#include +#include +#include + +#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 - - -#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 + + +#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 -#include -#include - -#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 ; iRetLimitLOD(0); // frontier AB as config - limit[1] = m_engine->RetLimitLOD(1); // frontier BC as config - - // Standard frontiers -> config. - for ( i=first ; iRetSecondTexture(); - } - 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 ; iRetSecondTexture(); - } - 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 +#include +#include + +#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 ; iRetLimitLOD(0); // frontier AB as config + limit[1] = m_engine->RetLimitLOD(1); // frontier BC as config + + // Standard frontiers -> config. + for ( i=first ; iRetSecondTexture(); + } + 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 ; iRetSecondTexture(); + } + 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 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 -#include -#include - -#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 +#include +#include + +#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 -#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 +#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 - - -#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 + + +#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) && (np.y||p.y>m) && (np.y||p.y>m) && (np.y||p.y>m) && (n= 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 ¢er, 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 ¢er, 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 - -#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 + +#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 - -#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 ; iCreateParticule(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 ; iCreateParticule(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 ; iCreateParticule(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 ; iCreateParticule(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 + +#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 ; iCreateParticule(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 ; iCreateParticule(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 ; iCreateParticule(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 ; iCreateParticule(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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 ; iRetPosition(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 ; iDeleteParticule(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 + +#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 ; iRetPosition(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 ; iDeleteParticule(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 - -#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 ; iRetInfo(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 ; jSetName(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 + +#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 ; iRetInfo(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 ; jSetName(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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 ; iCreateParticule(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 ; iCreateParticule(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 + +#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 ; iCreateParticule(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 ; iCreateParticule(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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 ; iDeleteInstance(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 ; iGetTitle(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 ; iCompare(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 ; iSendScript(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 + +#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 ; iDeleteInstance(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 ; iGetTitle(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 ; iCompare(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 ; iSendScript(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 - -#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 + +#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 - - -#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 + + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 ; iCreateObject(); - 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 ; iRetBurn() ) // 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 ; iSetObjectShadowRadius(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 ; iRetPosition(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 + +#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 ; iCreateObject(); + 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 ; iRetBurn() ) // 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 ; iSetObjectShadowRadius(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 ; iRetPosition(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 -#include -#include - -#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 ; iAddUpdateFunc(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 ; iDeleteObject(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 ; iDeleteParticule(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 ; iSetIdent(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 ; iWrite(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 ; iReadModel("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 ; level1RetLimitLOD(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 ; iGetPosition(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 ; iSetObjectTransparency(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 ; iSetHiliteRank(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 ; iRetTraceDown(); -} - -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 +#include +#include + +#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 ; iAddUpdateFunc(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 ; iDeleteObject(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 ; iDeleteParticule(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 ; iSetIdent(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 ; iWrite(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 ; iReadModel("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 ; level1RetLimitLOD(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 ; iGetPosition(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 ; iSetObjectTransparency(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 ; iSetHiliteRank(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 ; iRetTraceDown(); +} + +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 -#include -#include - -#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 ; iAddItem("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 ; iRetType() == 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 ; jSearchControl(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 ; iSearchInstance(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 ; jRetObjectRank(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 ; iInitTextures(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 ; iSearchInstance(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 ; iRetCompile(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 ; iRetCompile(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 ; iWriteProgram(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 ; iWriteProgram(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 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 ; iRetObjectRank(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 ; iRetObjectRank(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 ; tSearchInstance(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 ; tDisplayError(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 ; iRetGlint(); -} - -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 +#include +#include + +#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 ; iAddItem("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 ; iRetType() == 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 ; jSearchControl(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 ; iSearchInstance(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 ; jRetObjectRank(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 ; iInitTextures(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 ; iSearchInstance(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 ; iRetCompile(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 ; iRetCompile(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 ; iWriteProgram(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 ; iWriteProgram(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 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 ; iRetObjectRank(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 ; iRetObjectRank(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 ; tSearchInstance(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 ; tDisplayError(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 ; iRetGlint(); +} + +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 - -#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 ¢er, 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 + +#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 ¢er, 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 - -#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 + +#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 - -#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 + +#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 - -#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 ; iFlushEnvelope(m_soundChannel); - m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); - m_soundChannel = -1; - } - - for ( i=0 ; iDeleteLight(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 ; iCreateLight(); - 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 ; iSetLightColor(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 + +#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 ; iFlushEnvelope(m_soundChannel); + m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 1.0f, SOPER_STOP); + m_soundChannel = -1; + } + + for ( i=0 ; iDeleteLight(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 ; iCreateLight(); + 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 ; iSetLightColor(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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 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 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<= m_bmSize || - y < 0 || y >= m_bmSize ) return; - - m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] &= ~(1<= 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< + +#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 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 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<= m_bmSize || + y < 0 || y >= m_bmSize ) return; + + m_bmArray[rank*m_bmLine*m_bmSize + m_bmLine*y + x/8] &= ~(1<= 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< - -#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 + +#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 - -#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 ; iRetInfo(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 ; iRetInfo(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 + +#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 ; iRetInfo(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 ; iRetInfo(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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 + +#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 - -#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 ; iMoveOnFloor(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 + +#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 ; iMoveOnFloor(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 - -#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 + +#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 - -#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 + +#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 -#include -#include - -#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 ; iRetPause() ) 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 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 ; iDrawPrimitive(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 +#include +#include + +#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 ; iRetPause() ) 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 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 ; iDrawPrimitive(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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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 ; iDrawPrimitive(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 +#include +#include + +#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 ; iDrawPrimitive(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 -#include -#include -#include -#include -#include -#include -#include - -#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 ; devicestrDesc)+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 ; modedwNumModes ; 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 ; devicestrDesc, deviceName) == 0 ) // device found ? - { - for( mode=0 ; modedwNumModes ; 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 +#include +#include +#include +#include +#include +#include +#include + +#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 ; devicestrDesc)+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 ; modedwNumModes ; 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 ; devicestrDesc, deviceName) == 0 ) // device found ? + { + for( mode=0 ; modedwNumModes ; 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 - -#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 + +#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 -#include - -#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 ; l1totalUsed ; l1++ ) - { - p2 = p1->table[l1]; - if ( p2 == 0 ) continue; - for ( l2=0 ; l2totalUsed ; l2++ ) - { - p3 = p2->table[l2]; - if ( p3 == 0 ) continue; - for ( l3=0 ; l3totalUsed ; l3++ ) - { - p4 = p3->table[l3]; - if ( p4 == 0 ) continue; - for ( l4=0 ; l4totalUsed ; l4++ ) - { - p5 = p4->table[l4]; - if ( p5 == 0 ) continue; - for ( l5=0 ; l5totalUsed ; 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= 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 ; l1totalUsed ; l1++ ) - { - p2 = p1->table[l1]; - if ( p2 == 0 ) continue; - for ( l2=0 ; l2totalUsed ; l2++ ) - { - p3 = p2->table[l2]; - if ( p3 == 0 ) continue; - for ( l3=0 ; l3totalUsed ; l3++ ) - { - p4 = p3->table[l3]; - if ( p4 == 0 ) continue; - for ( l4=0 ; l4totalUsed ; l4++ ) - { - p5 = p4->table[l4]; - if ( p5 == 0 ) continue; - for ( l5=0 ; l5totalUsed ; 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 ; itotalUsed ; l1++ ) - { - p2 = p1->table[l1]; - if ( p2 == 0 ) continue; - for ( l2=0 ; l2totalUsed ; l2++ ) - { - p3 = p2->table[l2]; - if ( p3 == 0 ) continue; - if ( p3->objRank != objRank ) continue; - for ( l3=0 ; l3totalUsed ; l3++ ) - { - p4 = p3->table[l3]; - if ( p4 == 0 ) continue; - for ( l4=0 ; l4totalUsed ; l4++ ) - { - p5 = p4->table[l4]; - if ( p5 == 0 ) continue; - for ( l5=0 ; l5totalUsed ; 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 ) 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 ; l1totalUsed ; 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 ; l2totalUsed ; 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 ; l3totalUsed ; 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 ; l4totalUsed ; 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 ; l5totalUsed ; 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 ; ivertex[p6->totalUsed], vertex, sizeof(D3DVERTEX2)*nb); - p6->totalUsed += nb; - - if ( bGlobalUpdate ) - { - m_bUpdateGeometry = true; - } - else - { - for ( i=0 ; itotalUsed++; - p5->table[l5] = buffer; - - if ( bGlobalUpdate ) - { - m_bUpdateGeometry = true; - } - else - { - for ( i=0 ; itotalUsed ; 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 ; l1totalUsed ; l1++ ) - { - p2 = p1->table[l1]; - if ( p2 == 0 ) continue; - for ( l2=0 ; l2totalUsed ; l2++ ) - { - p3 = p2->table[l2]; - if ( p3 == 0 ) continue; - for ( l3=0 ; l3totalUsed ; 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 ; l1totalUsed ; 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 ; l2totalUsed ; l2++ ) - { - p3 = p2->table[l2]; - if ( p3 == 0 ) continue; - if ( p3->objRank != objRank ) continue; - for ( l3=0 ; l3totalUsed ; l3++ ) - { - p4 = p3->table[l3]; - if ( p4 == 0 ) continue; - if ( p4->min != min || - p4->max != max ) continue; - for ( l4=0 ; l4totalUsed ; l4++ ) - { - p5 = p4->table[l4]; - if ( p5 == 0 ) continue; - for ( l5=0 ; l5totalUsed ; 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 ; l1totalUsed ; l1++ ) - { - p2 = p1->table[l1]; - if ( p2 == 0 ) continue; - if ( strcmp(p2->texName2, texName2) == 0 ) continue; // already new - for ( l2=0 ; l2totalUsed ; 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 ; l1totalUsed ; l1++ ) - { - p2 = p1->table[l1]; - if ( p2 == 0 ) continue; -//? if ( p2->texName[0] == 0 ) continue; - for ( l2=0 ; l2totalUsed ; l2++ ) - { - p3 = p2->table[l2]; - if ( p3 == 0 ) continue; - if ( p3->objRank != objRank ) continue; - for ( l3=0 ; l3totalUsed ; l3++ ) - { - p4 = p3->table[l3]; - if ( p4 == 0 ) continue; - if ( p4->min != min || - p4->max != max ) continue; - for ( l4=0 ; l4totalUsed ; l4++ ) - { - p5 = p4->table[l4]; - if ( p5 == 0 ) continue; - for ( l5=0 ; l5totalUsed ; l5++ ) - { - p6 = p5->table[l5]; - if ( p6 == 0 ) continue; - if ( p6->type == D3DTYPE6T ) - { - pv = &p6->vertex[0]; - for ( l6=0 ; l6totalUsed/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 ; l6totalUsed-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 ; l6tu = pv->z*au+bu; - pv->tv = pv->y*av+bv; - pv ++; - } - } - - if ( mode == D3DMAPPINGY ) - { - for ( l6=0 ; l6tu = pv->x*au+bu; - pv->tv = pv->z*av+bv; - pv ++; - } - } - - if ( mode == D3DMAPPINGZ ) - { - for ( l6=0 ; l6tu = pv->x*au+bu; - pv->tv = pv->y*av+bv; - pv ++; - } - } - - if ( mode == D3DMAPPING1X ) - { - for ( l6=0 ; l6tu = pv->x*au+bu; - pv ++; - } - } - - if ( mode == D3DMAPPING1Y ) - { - for ( l6=0 ; l6tv = pv->y*au+bu; - pv ++; - } - } - - if ( mode == D3DMAPPING1Z ) - { - for ( l6=0 ; l6tu = 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)-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 ; itotalUsed ; l1++ ) - { - p2 = p1->table[l1]; - if ( p2 == 0 ) continue; - for ( l2=0 ; l2totalUsed ; l2++ ) - { - p3 = p2->table[l2]; - if ( p3 == 0 ) continue; - objRank = p3->objRank; - for ( l3=0 ; l3totalUsed ; l3++ ) - { - p4 = p3->table[l3]; - if ( p4 == 0 ) continue; - for ( l4=0 ; l4totalUsed ; l4++ ) - { - p5 = p4->table[l4]; - if ( p5 == 0 ) continue; - for ( l5=0 ; l5totalUsed ; l5++ ) - { - p6 = p5->table[l5]; - if ( p6 == 0 ) continue; - - for ( i=0 ; itotalUsed ; 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(¢erD3D, &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 ; l1totalUsed ; l1++ ) - { - p2 = p1->table[l1]; - if ( p2 == 0 ) continue; - for ( l2=0 ; l2totalUsed ; 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 ; l3totalUsed ; l3++ ) - { - p4 = p3->table[l3]; - if ( p4 == 0 ) continue; - if ( p4->min != 0.0f ) continue; // LOD B or C? - for ( l4=0 ; l4totalUsed ; l4++ ) - { - p5 = p4->table[l4]; - if ( p5 == 0 ) continue; - for ( l5=0 ; l5totalUsed ; l5++ ) - { - p6 = p5->table[l5]; - if ( p6 == 0 ) continue; - - if ( p6->type == D3DTYPE6T ) - { - pv = &p6->vertex[0]; - for ( i=0 ; itotalUsed/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 ; itotalUsed-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 ; iIsVideo8MB() ) - { - 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= 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 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 ; l1totalUsed ; 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 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 ; iSetRenderState(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 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 ; l1totalUsed ; l1++ ) - { - p2 = p1->table[l1]; - if ( p2 == 0 ) continue; - SetTexture(p2->texName1, 0); - SetTexture(p2->texName2, 1); - for ( l2=0 ; l2totalUsed ; 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 ; l3totalUsed ; 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 ; l4totalUsed ; l4++ ) - { - p5 = p4->table[l4]; - if ( p5 == 0 ) continue; - for ( l5=0 ; l5totalUsed ; 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 ; l1totalUsed ; l1++ ) - { - p2 = p1->table[l1]; - if ( p2 == 0 ) continue; - SetTexture(p2->texName1, 0); - SetTexture(p2->texName2, 1); - for ( l2=0 ; l2totalUsed ; 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 ; l3totalUsed ; 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 ; l4totalUsed ; l4++ ) - { - p5 = p4->table[l4]; - if ( p5 == 0 ) continue; - for ( l5=0 ; l5totalUsed ; 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 ; l1totalUsed ; l1++ ) - { - p2 = p1->table[l1]; - if ( p2 == 0 ) continue; - SetTexture(p2->texName1, 0); - SetTexture(p2->texName2, 1); - for ( l2=0 ; l2totalUsed ; 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 ; l3totalUsed ; 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 ; l4totalUsed ; l4++ ) - { - p5 = p4->table[l4]; - if ( p5 == 0 ) continue; - for ( l5=0 ; l5totalUsed ; 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 ; l1totalUsed ; l1++ ) - { - p2 = p1->table[l1]; - if ( p2 == 0 ) continue; - SetTexture(p2->texName1, 0); - SetTexture(p2->texName2, 1); - for ( l2=0 ; l2totalUsed ; 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 ; l3totalUsed ; 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 ; l4totalUsed ; l4++ ) - { - p5 = p4->table[l4]; - if ( p5 == 0 ) continue; - for ( l5=0 ; l5totalUsed ; 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 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 0 ) - { - for ( y=0 ; y=-dx ; x-- ) - { - m_imageCopy[x+y*m_imageDX] = m_imageCopy[x+dx+y*m_imageDX]; - } - } - } - - if ( dy > 0 ) - { - for ( y=0 ; 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 +#include + +#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 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + for ( l2=0 ; l2totalUsed ; l2++ ) + { + p3 = p2->table[l2]; + if ( p3 == 0 ) continue; + for ( l3=0 ; l3totalUsed ; l3++ ) + { + p4 = p3->table[l3]; + if ( p4 == 0 ) continue; + for ( l4=0 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; 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= 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 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + for ( l2=0 ; l2totalUsed ; l2++ ) + { + p3 = p2->table[l2]; + if ( p3 == 0 ) continue; + for ( l3=0 ; l3totalUsed ; l3++ ) + { + p4 = p3->table[l3]; + if ( p4 == 0 ) continue; + for ( l4=0 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; 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 ; itotalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + for ( l2=0 ; l2totalUsed ; l2++ ) + { + p3 = p2->table[l2]; + if ( p3 == 0 ) continue; + if ( p3->objRank != objRank ) continue; + for ( l3=0 ; l3totalUsed ; l3++ ) + { + p4 = p3->table[l3]; + if ( p4 == 0 ) continue; + for ( l4=0 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; 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 ) 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 ; l1totalUsed ; 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 ; l2totalUsed ; 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 ; l3totalUsed ; 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 ; l4totalUsed ; 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 ; l5totalUsed ; 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 ; ivertex[p6->totalUsed], vertex, sizeof(D3DVERTEX2)*nb); + p6->totalUsed += nb; + + if ( bGlobalUpdate ) + { + m_bUpdateGeometry = true; + } + else + { + for ( i=0 ; itotalUsed++; + p5->table[l5] = buffer; + + if ( bGlobalUpdate ) + { + m_bUpdateGeometry = true; + } + else + { + for ( i=0 ; itotalUsed ; 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 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + for ( l2=0 ; l2totalUsed ; l2++ ) + { + p3 = p2->table[l2]; + if ( p3 == 0 ) continue; + for ( l3=0 ; l3totalUsed ; 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 ; l1totalUsed ; 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 ; l2totalUsed ; l2++ ) + { + p3 = p2->table[l2]; + if ( p3 == 0 ) continue; + if ( p3->objRank != objRank ) continue; + for ( l3=0 ; l3totalUsed ; l3++ ) + { + p4 = p3->table[l3]; + if ( p4 == 0 ) continue; + if ( p4->min != min || + p4->max != max ) continue; + for ( l4=0 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; 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 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + if ( strcmp(p2->texName2, texName2) == 0 ) continue; // already new + for ( l2=0 ; l2totalUsed ; 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 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; +//? if ( p2->texName[0] == 0 ) continue; + for ( l2=0 ; l2totalUsed ; l2++ ) + { + p3 = p2->table[l2]; + if ( p3 == 0 ) continue; + if ( p3->objRank != objRank ) continue; + for ( l3=0 ; l3totalUsed ; l3++ ) + { + p4 = p3->table[l3]; + if ( p4 == 0 ) continue; + if ( p4->min != min || + p4->max != max ) continue; + for ( l4=0 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; l5++ ) + { + p6 = p5->table[l5]; + if ( p6 == 0 ) continue; + if ( p6->type == D3DTYPE6T ) + { + pv = &p6->vertex[0]; + for ( l6=0 ; l6totalUsed/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 ; l6totalUsed-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 ; l6tu = pv->z*au+bu; + pv->tv = pv->y*av+bv; + pv ++; + } + } + + if ( mode == D3DMAPPINGY ) + { + for ( l6=0 ; l6tu = pv->x*au+bu; + pv->tv = pv->z*av+bv; + pv ++; + } + } + + if ( mode == D3DMAPPINGZ ) + { + for ( l6=0 ; l6tu = pv->x*au+bu; + pv->tv = pv->y*av+bv; + pv ++; + } + } + + if ( mode == D3DMAPPING1X ) + { + for ( l6=0 ; l6tu = pv->x*au+bu; + pv ++; + } + } + + if ( mode == D3DMAPPING1Y ) + { + for ( l6=0 ; l6tv = pv->y*au+bu; + pv ++; + } + } + + if ( mode == D3DMAPPING1Z ) + { + for ( l6=0 ; l6tu = 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)-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 ; itotalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + for ( l2=0 ; l2totalUsed ; l2++ ) + { + p3 = p2->table[l2]; + if ( p3 == 0 ) continue; + objRank = p3->objRank; + for ( l3=0 ; l3totalUsed ; l3++ ) + { + p4 = p3->table[l3]; + if ( p4 == 0 ) continue; + for ( l4=0 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; l5++ ) + { + p6 = p5->table[l5]; + if ( p6 == 0 ) continue; + + for ( i=0 ; itotalUsed ; 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(¢erD3D, &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 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + for ( l2=0 ; l2totalUsed ; 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 ; l3totalUsed ; l3++ ) + { + p4 = p3->table[l3]; + if ( p4 == 0 ) continue; + if ( p4->min != 0.0f ) continue; // LOD B or C? + for ( l4=0 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; l5++ ) + { + p6 = p5->table[l5]; + if ( p6 == 0 ) continue; + + if ( p6->type == D3DTYPE6T ) + { + pv = &p6->vertex[0]; + for ( i=0 ; itotalUsed/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 ; itotalUsed-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 ; iIsVideo8MB() ) + { + 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= 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 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 ; l1totalUsed ; 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 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 ; iSetRenderState(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 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 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + SetTexture(p2->texName1, 0); + SetTexture(p2->texName2, 1); + for ( l2=0 ; l2totalUsed ; 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 ; l3totalUsed ; 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 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; 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 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + SetTexture(p2->texName1, 0); + SetTexture(p2->texName2, 1); + for ( l2=0 ; l2totalUsed ; 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 ; l3totalUsed ; 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 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; 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 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + SetTexture(p2->texName1, 0); + SetTexture(p2->texName2, 1); + for ( l2=0 ; l2totalUsed ; 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 ; l3totalUsed ; 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 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; 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 ; l1totalUsed ; l1++ ) + { + p2 = p1->table[l1]; + if ( p2 == 0 ) continue; + SetTexture(p2->texName1, 0); + SetTexture(p2->texName2, 1); + for ( l2=0 ; l2totalUsed ; 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 ; l3totalUsed ; 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 ; l4totalUsed ; l4++ ) + { + p5 = p4->table[l4]; + if ( p5 == 0 ) continue; + for ( l5=0 ; l5totalUsed ; 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 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 0 ) + { + for ( y=0 ; y=-dx ; x-- ) + { + m_imageCopy[x+y*m_imageDX] = m_imageCopy[x+dx+y*m_imageDX]; + } + } + } + + if ( dy > 0 ) + { + for ( y=0 ; 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 + +#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 -#include -#include -#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; idwNumModes; 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; idwNumModes; 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; ibDesktopCompatible ) - 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; ibWindowed = 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 +#include +#include +#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; idwNumModes; 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; idwNumModes; 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; ibDesktopCompatible ) + 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; ibWindowed = 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 - - -//----------------------------------------------------------------------------- -// 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 + + +//----------------------------------------------------------------------------- +// 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 -#include -#include -#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 +#include +#include +#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 -#include - - - - -//----------------------------------------------------------------------------- -// 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 +#include + + + + +//----------------------------------------------------------------------------- +// 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 -#include -#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 +#include +#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 -#include - - -//----------------------------------------------------------------------------- -// 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 +#include + + +//----------------------------------------------------------------------------- +// 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 -#include -#include -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; yGetCaps( &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; iCreatePalette( 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; yUnlock( 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>24)&0x000000ff); - BYTE g = (BYTE)((dwPixel>>16)&0x000000ff); - BYTE b = (BYTE)((dwPixel>> 8)&0x000000ff); - BYTE a = (BYTE)((dwPixel>> 0)&0x000000ff); - - DWORD dr = ((r>>(dwRShiftL))<>(dwGShiftL))<>(dwBShiftL))<>(dwAShiftL))<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 +#include +#include +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; yGetCaps( &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; iCreatePalette( 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; yUnlock( 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>24)&0x000000ff); + BYTE g = (BYTE)((dwPixel>>16)&0x000000ff); + BYTE b = (BYTE)((dwPixel>> 8)&0x000000ff); + BYTE a = (BYTE)((dwPixel>> 0)&0x000000ff); + + DWORD dr = ((r>>(dwRShiftL))<>(dwGShiftL))<>(dwBShiftL))<>(dwAShiftL))<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 -#include - - - - -//----------------------------------------------------------------------------- -// 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 +#include + + + + +//----------------------------------------------------------------------------- +// 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 -#include -#include -#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 +#include +#include +#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 -#include - - - - -//----------------------------------------------------------------------------- -// 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 +#include + + + + +//----------------------------------------------------------------------------- +// 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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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 ; iLightEnable(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 ) return false; - - m_lightTable[lightRank].bUsed = false; - m_pD3DDevice->LightEnable(lightRank, false); - - m_lightUsed = 0; - for ( i=0 ; i= 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 ; iRetPause() ) return; - - m_time += rTime; - - for ( i=0 ; iRetEyePt()-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 ; iSetLight(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 ; iLightEnable(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 +#include +#include + +#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 ; iLightEnable(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 ) return false; + + m_lightTable[lightRank].bUsed = false; + m_pD3DDevice->LightEnable(lightRank, false); + + m_lightUsed = 0; + for ( i=0 ; i= 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 ; iRetPause() ) return; + + m_time += rTime; + + for ( i=0 ; iRetEyePt()-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 ; iSetLight(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 ; iLightEnable(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 -#include -#include - -#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) && (np.y||p.y>m) && (n= 100 ) break; - } - } - - sum.x = 0; - sum.y = 0; - sum.z = 0; - for ( j=0 ; j 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 +#include +#include + +#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) && (np.y||p.y>m) && (n= 100 ) break; + } + } + + sum.x = 0; + sum.y = 0; + sum.z = 0; + for ( j=0 ; j 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 - -#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 + +#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 -#include -#include - -#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= 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= 100 ) break; - } - } - - sum.x = 0; - sum.y = 0; - sum.z = 0; - for ( j=0 ; jRetTriangleUsed(); - - for ( i=0 ; iRetTriangleUsed(); - for ( i=0 ; iRetTriangleUsed(); - for ( i=0 ; iRetTriangleUsed(); - for ( i=0 ; iReadModel(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 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 ; iRetTriangleUsed(); - for ( i=0 ; iRetTriangleUsed(); - for ( i=0 ; iRetTriangleUsed(); - for ( i=0 ; iRetTriangleUsed(); - for ( i=0 ; iRetTriangleUsed(); - for ( i=0 ; i 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 2 ) - { - MappingSelectPlane2(subdiv-3, bMirrorX, bMirrorY); - return; - } - - BBoxCompute(min, max); - center = (min+max)/2.0f; - - for ( i=0 ; iRetTriangleUsed(); - for ( i=0 ; iRetTriangleUsed(); - for ( i=0 ; iRetTriangleUsed(); - for ( i=0 ; i= 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 ) 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 ; iRetTriangleUsed(); - for ( i=0 ; 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 ; iRetTriangleUsed(); - for ( i=0 ; 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 ; iRetTriangleUsed(); - for ( i=0 ; iSetTriangleUsed(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= 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 +#include +#include + +#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= 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= 100 ) break; + } + } + + sum.x = 0; + sum.y = 0; + sum.z = 0; + for ( j=0 ; jRetTriangleUsed(); + + for ( i=0 ; iRetTriangleUsed(); + for ( i=0 ; iRetTriangleUsed(); + for ( i=0 ; iRetTriangleUsed(); + for ( i=0 ; iReadModel(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 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 ; iRetTriangleUsed(); + for ( i=0 ; iRetTriangleUsed(); + for ( i=0 ; iRetTriangleUsed(); + for ( i=0 ; iRetTriangleUsed(); + for ( i=0 ; iRetTriangleUsed(); + for ( i=0 ; i 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 2 ) + { + MappingSelectPlane2(subdiv-3, bMirrorX, bMirrorY); + return; + } + + BBoxCompute(min, max); + center = (min+max)/2.0f; + + for ( i=0 ; iRetTriangleUsed(); + for ( i=0 ; iRetTriangleUsed(); + for ( i=0 ; iRetTriangleUsed(); + for ( i=0 ; i= 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 ) 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 ; iRetTriangleUsed(); + for ( i=0 ; 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 ; iRetTriangleUsed(); + for ( i=0 ; 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 ; iRetTriangleUsed(); + for ( i=0 ; iSetTriangleUsed(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= 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 ; iRetLimitLOD(0); // frontier AB as config - limit[1] = m_engine->RetLimitLOD(1); // frontier BC as config - - // Standard frontiers -> config. - for ( i=first ; iRetLimitLOD(0); // frontier AB as config + limit[1] = m_engine->RetLimitLOD(1); // frontier BC as config + + // Standard frontiers -> config. + for ( i=first ; iRetSecondTexture(); - } - 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 ; iRetSecondTexture(); + } + 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 ; iRetSecondTexture(); - } - 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 ; iRetSecondTexture(); + } + 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 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 -#include -#include - -#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 ; iSearchInstance(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= 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= MAXPARTITYPE ) return -1; - if ( t == -1 ) return -1; - - for ( j=0 ; jRetWheelTraceQuantity()*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 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 ; iRetFloorLevel(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 ; jExploObject(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= 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 ; iRetParticuleDensity()); - for ( i=0 ; i= 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 ; counterSetTransform(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 ; counterDrawPrimitive(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= 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 ; ringDrawPrimitive(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 ; ringDrawPrimitive(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 ; iSetTexture(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=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 ; jSetTexture(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_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 ; iCreateBitmapInfoStruct(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 +#include +#include + +#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 ; iSearchInstance(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= 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= MAXPARTITYPE ) return -1; + if ( t == -1 ) return -1; + + for ( j=0 ; jRetWheelTraceQuantity()*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 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 ; iRetFloorLevel(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 ; jExploObject(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= 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 ; iRetParticuleDensity()); + for ( i=0 ; i= 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 ; counterSetTransform(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 ; counterDrawPrimitive(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= 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 ; ringDrawPrimitive(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 ; ringDrawPrimitive(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 ; iSetTexture(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=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 ; jSetTexture(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_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 ; iCreateBitmapInfoStruct(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 -#include -#include - -#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 ; iRetPause() ) return true; - - m_time += event.rTime; - - for ( i=0 ; iLoadTexture(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 ; iSetTexture(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 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 +#include +#include + +#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 ; iRetPause() ) return true; + + m_time += event.rTime; + + for ( i=0 ; iLoadTexture(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 ; iSetTexture(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 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 -#include -#include - -#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 ; partRetParticuleDensity()); - if ( oType == OBJECT_TNT || - oType == OBJECT_BOMB ) total *= 3; - for ( i=0 ; iCreateTrack(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 ; iCreateParticule(pos, speed, dim, PARTIORGANIC1, - duration, mass); - } - total = (int)(5.0f*m_engine->RetParticuleDensity()); - for ( i=0 ; iCreateTrack(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 ; iCreateTrack(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 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 ; iCreateParticule(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 ; iSetLightIntensity(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 ; iRetObjectRank(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 ; iRetObjectRank(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 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 ; iRetObjectRank(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 +#include +#include + +#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 ; partRetParticuleDensity()); + if ( oType == OBJECT_TNT || + oType == OBJECT_BOMB ) total *= 3; + for ( i=0 ; iCreateTrack(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 ; iCreateParticule(pos, speed, dim, PARTIORGANIC1, + duration, mass); + } + total = (int)(5.0f*m_engine->RetParticuleDensity()); + for ( i=0 ; iCreateTrack(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 ; iCreateTrack(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 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 ; iCreateParticule(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 ; iSetLightIntensity(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 ; iRetObjectRank(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 ; iRetObjectRank(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 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 ; iRetObjectRank(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 -#include -#include -#include -#include - -#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 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 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 ; iStop(); - 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 ; iGetStatus(&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 ; iGetStatus(&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= 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 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 ; iSetPosition(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 ; iGetStatus(&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 ; iSetVolume(-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 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 +#include +#include +#include +#include + +#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 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 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 ; iStop(); + 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 ; iGetStatus(&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 ; iGetStatus(&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= 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 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 ; iSetPosition(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 ; iGetStatus(&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 ; iSetVolume(-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 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 - - -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 + + +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 -#include -#include - -#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<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= 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 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= 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 ; mytotalPossible = 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 ; itexName); - 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 ; imat[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 ; upmat[1]; - mat[2] = tm->mat[2]; - mat[3] = tm->mat[3]; - - if ( LevelIfDot(x, y, id, mat) ) return true; - } - - for ( right=0 ; rightmat[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 ; downmat[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 ; leftmat[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 ; upmat[1]; - mat[2] = down; - mat[3] = tm->mat[3]; - - if ( LevelIfDot(x, y, id, mat) ) return true; - } - } - - for ( right=0 ; rightmat[0]; - mat[1] = right; - mat[2] = tm->mat[2]; - mat[3] = left; - - if ( LevelIfDot(x, y, id, mat) ) return true; - } - } - - for ( up=0 ; upmat[2]; - mat[3] = tm->mat[3]; - - if ( LevelIfDot(x, y, id, mat) ) return true; - } - } - - for ( right=0 ; rightmat[0]; - mat[1] = right; - mat[2] = down; - mat[3] = tm->mat[3]; - - if ( LevelIfDot(x, y, id, mat) ) return true; - } - } - - for ( down=0 ; downmat[0]; - mat[1] = tm->mat[1]; - mat[2] = down; - mat[3] = left; - - if ( LevelIfDot(x, y, id, mat) ) return true; - } - } - - for ( up=0 ; upmat[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 ; upmat[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 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 ; iCreateObject(); - 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 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= 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_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_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 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_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 +#include +#include + +#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<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= 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 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= 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 ; mytotalPossible = 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 ; itexName); + 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 ; imat[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 ; upmat[1]; + mat[2] = tm->mat[2]; + mat[3] = tm->mat[3]; + + if ( LevelIfDot(x, y, id, mat) ) return true; + } + + for ( right=0 ; rightmat[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 ; downmat[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 ; leftmat[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 ; upmat[1]; + mat[2] = down; + mat[3] = tm->mat[3]; + + if ( LevelIfDot(x, y, id, mat) ) return true; + } + } + + for ( right=0 ; rightmat[0]; + mat[1] = right; + mat[2] = tm->mat[2]; + mat[3] = left; + + if ( LevelIfDot(x, y, id, mat) ) return true; + } + } + + for ( up=0 ; upmat[2]; + mat[3] = tm->mat[3]; + + if ( LevelIfDot(x, y, id, mat) ) return true; + } + } + + for ( right=0 ; rightmat[0]; + mat[1] = right; + mat[2] = down; + mat[3] = tm->mat[3]; + + if ( LevelIfDot(x, y, id, mat) ) return true; + } + } + + for ( down=0 ; downmat[0]; + mat[1] = tm->mat[1]; + mat[2] = down; + mat[3] = left; + + if ( LevelIfDot(x, y, id, mat) ) return true; + } + } + + for ( up=0 ; upmat[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 ; upmat[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 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 ; iCreateObject(); + 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 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= 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_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_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 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_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 -#include -#include - -#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 ; iRetEditIndentValue(); - 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 ; iRetEditIndentValue(); - 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 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 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 ; iSetTexture("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 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 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 +#include +#include + +#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 ; iRetEditIndentValue(); + 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 ; iRetEditIndentValue(); + 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 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 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 ; iSetTexture("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 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 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 -#include -#include - -#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= 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 ; iPlay(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 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 ; jDrawPrimitive(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= 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 +#include +#include + +#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= 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 ; iPlay(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 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 ; jDrawPrimitive(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= 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 -#include -#include - -#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 ; iRetWorldMatrix(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 ; iCreateParticule(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 ; iRetPosition(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 ; iRetPosition(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 ; iCreateParticule(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 +#include +#include + +#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 ; iRetWorldMatrix(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 ; iCreateParticule(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 ; iRetPosition(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 ; iRetPosition(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 ; iCreateParticule(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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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= '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 +#include +#include + +#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= '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 -#include -#include - -#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 ; iRetInfo(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 ; iRetInfo(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 ; iRetCheckToken() ) return true; - - m_error = 0; - m_title[0] = 0; - m_token[0] = 0; - m_bCompile = false; - - for ( i=0 ; iRetObligatoryToken() ; 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, ""); - CBotToken::Delete(bt); - return false; - } - - bt = bt->GivNext(); - } - - // At least once every obligatory instruction? - for ( i=0 ; iRetObligatoryToken() ; i++ ) - { - if ( used[i] == 0 ) // token not used? - { - strcpy(m_token, m_main->RetObligatoryToken(i)); - m_error = ERR_OBLIGATORYTOKEN; - strcpy(m_title, ""); - 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, ""); - } - 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, ""); - 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= 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 +#include +#include + +#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 ; iRetInfo(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 ; iRetInfo(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 ; iRetCheckToken() ) return true; + + m_error = 0; + m_title[0] = 0; + m_token[0] = 0; + m_bCompile = false; + + for ( i=0 ; iRetObligatoryToken() ; 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, ""); + CBotToken::Delete(bt); + return false; + } + + bt = bt->GivNext(); + } + + // At least once every obligatory instruction? + for ( i=0 ; iRetObligatoryToken() ; i++ ) + { + if ( used[i] == 0 ) // token not used? + { + strcpy(m_token, m_main->RetObligatoryToken(i)); + m_error = ERR_OBLIGATORYTOKEN; + strcpy(m_title, ""); + 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, ""); + } + 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, ""); + 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= 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 - -#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 + +#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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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 ; iDeleteInstance(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 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 ; iSearchControl(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 ; iDeleteControl(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 ; iSearchControl(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 ; iSearchControl(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 ; iSearchControl(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 +#include +#include + +#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 ; iDeleteInstance(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 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 ; iSearchControl(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 ; iDeleteControl(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 ; iSearchControl(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 ; iSearchControl(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 ; iSearchControl(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 -#include -#include -#include -#include - -#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 ; iCreate(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_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_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_lineFirst+m_lineVisible ) break; - - pos.x = m_pos.x+(10.0f/640.0f); - if ( m_bAutoIndent ) - { - for ( j=0 ; jRetText()->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 ; iRetText()->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 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 ; iFreeTexture(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 ; iCountRetKey(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= 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 ; iRetText()->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 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 ; iRetEditIndentValue() ; 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 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 ; inumber ; 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 ; iRetText()->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= 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_lineOffset[i] ) - { - line = i; - } - } - return line; -} - - -// Flush the buffer undo. - -void CEdit::UndoFlush() -{ - int i; - - for ( i=0 ; 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 +#include +#include +#include +#include + +#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 ; iCreate(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_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_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_lineFirst+m_lineVisible ) break; + + pos.x = m_pos.x+(10.0f/640.0f); + if ( m_bAutoIndent ) + { + for ( j=0 ; jRetText()->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 ; iRetText()->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 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 ; iFreeTexture(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 ; iCountRetKey(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= 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 ; iRetText()->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 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 ; iRetEditIndentValue() ; 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 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 ; inumber ; 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 ; iRetText()->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= 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_lineOffset[i] ) + { + line = i; + } + } + return line; +} + + +// Flush the buffer undo. + +void CEdit::UndoFlush() +{ + int i; + + for ( i=0 ; 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 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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(pos, dim, icon, eventMsg); - return pm; - } - } - return 0; -} - -// Removes a control. - -bool CInterface::DeleteControl(EventMsg eventMsg) -{ - int i; - - for ( i=0 ; iRetEventMsg() ) - { - 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 ; iRetEventMsg() ) - { - 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=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 +#include +#include + +#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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(pos, dim, icon, eventMsg); + return pm; + } + } + return 0; +} + +// Removes a control. + +bool CInterface::DeleteControl(EventMsg eventMsg) +{ + int i; + + for ( i=0 ; iRetEventMsg() ) + { + 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 ; iRetEventMsg() ) + { + 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=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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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 ; iCreate(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 ; iRetText()->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 ; iCreate(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 ; iSetState(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 ; iSetState(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 ; iClearState(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_totalLine ) break; - if ( m_button[i] != 0 ) - { - m_button[i]->EventProcess(event); - } - } - } - - if ( m_bSelectCap ) - { - for ( i=0 ; i= 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_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 ; iSetState(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 +#include +#include + +#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 ; iCreate(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 ; iRetText()->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 ; iCreate(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 ; iSetState(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 ; iSetState(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 ; iClearState(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_totalLine ) break; + if ( m_button[i] != 0 ) + { + m_button[i]->EventProcess(event); + } + } + } + + if ( m_bSelectCap ) + { + for ( i=0 ; i= 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_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 ; iSetState(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 -#include -#include -#include -#include -#include - -#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 0 ) - { - strcpy(temp, filenames[i]); - strcpy(filenames[i], filenames[i+1]); - strcpy(filenames[i+1], temp); - bDo = true; - } - } - } - while ( bDo ); - - for ( i=0 ; iSetName(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 ; iRetName(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= '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 ; iRetGamerName(), 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 ; iRetShowAll() ) 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 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 ; jSetName(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 ; iDeleteControl(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 ; iCreateKey(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 ; iSearchControl(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 ; iRetGamerName(), 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 ) 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= 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 +#include +#include +#include +#include +#include + +#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 0 ) + { + strcpy(temp, filenames[i]); + strcpy(filenames[i], filenames[i+1]); + strcpy(filenames[i+1], temp); + bDo = true; + } + } + } + while ( bDo ); + + for ( i=0 ; iSetName(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 ; iRetName(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= '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 ; iRetGamerName(), 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 ; iRetShowAll() ) 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 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 ; jSetName(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 ; iDeleteControl(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 ; iCreateKey(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 ; iSearchControl(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 ; iRetGamerName(), 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 ) 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= 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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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 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 ; im_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= -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= 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 +#include +#include + +#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 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 ; im_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= -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= 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 -#include -#include - -#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 ; iDraw(); - } - 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 +#include +#include + +#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 ; iDraw(); + } + 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 -#include -#include - -#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 +#include +#include + +#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 -#include -#include - -#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); // 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 +#include +#include + +#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); // 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 -#include -#include -#include -#include -#include -#include -#include - -#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 ; iColorizeScript(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' || - 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 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 ; iSetName(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 +#include +#include +#include +#include +#include +#include +#include + +#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 ; iColorizeScript(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' || + 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 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 ; iSetName(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 -#include -#include - -#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 ; jRetObjectRank(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 +#include +#include + +#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 ; jRetObjectRank(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 -#include -#include - -#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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(pos, dim, icon, eventMsg); - return pc; - } - } - return 0; -} - -// Removes a control. - -bool CWindow::DeleteControl(EventMsg eventMsg) -{ - int i; - - for ( i=0 ; iRetEventMsg() ) - { - 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 ; iRetEventMsg() ) - { - 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 ; iDraw(); - } - } -} - -// 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 +#include +#include + +#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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(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 ; iCreate(pos, dim, icon, eventMsg); + return pc; + } + } + return 0; +} + +// Removes a control. + +bool CWindow::DeleteControl(EventMsg eventMsg) +{ + int i; + + for ( i=0 ; iRetEventMsg() ) + { + 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 ; iRetEventMsg() ) + { + 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 ; iDraw(); + } + } +} + +// 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 -- cgit v1.2.3-1-g7c22 From bf06998ece3ba9d47b595e3761beba54b3793036 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Tue, 26 Jun 2012 22:36:52 +0200 Subject: Forgotten language change --- src/common/language.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/language.h b/src/common/language.h index 51b80f4..82a7235 100644 --- a/src/common/language.h +++ b/src/common/language.h @@ -28,8 +28,8 @@ #define _NET false #define _DEMO false // DEMO only CoLoBoT (with _Full = false)! -#define _FRENCH true -#define _ENGLISH false +#define _FRENCH false +#define _ENGLISH true #define _GERMAN false #define _WG false #define _POLISH false -- cgit v1.2.3-1-g7c22